Skip to content

Commit

Permalink
Struct array fixes: fix FeatureIndexArray, better align fill-extrusio…
Browse files Browse the repository at this point in the history
…n vertex layout
  • Loading branch information
Lauren Budorick authored Dec 20, 2017
1 parent 45de446 commit b2ea22c
Show file tree
Hide file tree
Showing 19 changed files with 118 additions and 63 deletions.
8 changes: 4 additions & 4 deletions build/generate-struct-arrays.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ function createStructArrayType(name: string, layout: StructArrayLayout, includeS
}
}

function createStructArrayLayoutType({members, size}) {
function createStructArrayLayoutType({members, size, alignment}) {
const usedTypes = new Set(['Uint8']);
members = normalizeMembers(members, usedTypes);

// combine consecutive 'members' with same underlying type, summing their
// component counts
members = members.reduce((memo, member) => {
if (!alignment || alignment === 1) members = members.reduce((memo, member) => {
if (memo.length > 0 && memo[memo.length - 1].type === member.type) {
const last = memo[memo.length - 1];
return memo.slice(0, -1).concat(util.extend({}, last, {
Expand Down Expand Up @@ -154,7 +154,7 @@ createStructArrayType('feature_index', createLayout([
{ type: 'Uint16', name: 'sourceLayerIndex' },
// the bucket the feature appears in
{ type: 'Uint16', name: 'bucketIndex' }
], 4), true);
]), true);

// triangle index array
createStructArrayType('triangle_index', createLayout([
Expand Down Expand Up @@ -192,7 +192,7 @@ createStructArrayLayoutType(createLayout([{
const layouts = Object.keys(layoutCache).map(k => layoutCache[k]);

fs.writeFileSync('src/data/array_types.js',
`// This file is generated. Edit build/generate-struct-arrays.js, then run \`node build/generate-struct-arrays.js\`.
`// This file is generated. Edit build/generate-struct-arrays.js, then run \`yarn run codegen\`.
// @flow
const assert = require('assert');
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@
"test-flow": "node build/generate-flow-typed-style-spec && flow .",
"test-flow-cov": "flow-coverage-report -i 'src/**/*.js' -t html",
"test-cov": "nyc --require=flow-remove-types/register --reporter=text-summary --reporter=lcov --cache run-s test-unit test-expressions test-query test-render",
"prepublish": "in-publish && run-s build-dev build-min || not-in-publish"
"prepublish": "in-publish && run-s build-dev build-min || not-in-publish",
"codegen": "node build/generate-style-code.js && flow-node build/generate-struct-arrays.js"
},
"files": [
"build/",
Expand Down
53 changes: 28 additions & 25 deletions src/data/array_types.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is generated. Edit build/generate-struct-arrays.js, then run `node build/generate-struct-arrays.js`.
// This file is generated. Edit build/generate-struct-arrays.js, then run `yarn run codegen`.
// @flow

const assert = require('assert');
Expand Down Expand Up @@ -72,11 +72,12 @@ register('StructArrayLayout4i8', StructArrayLayout4i8);

/**
* Implementation of the StructArray layout:
* [0]: Int16[6]
* [0]: Int16[2]
* [4]: Int16[4]
*
* @private
*/
class StructArrayLayout6i16 extends StructArray {
class StructArrayLayout2i4i12 extends StructArray {
uint8: Uint8Array;
int16: Int16Array;

Expand All @@ -88,7 +89,7 @@ class StructArrayLayout6i16 extends StructArray {
emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number) {
const i = this.length;
this.resize(i + 1);
const o2 = i * 8;
const o2 = i * 6;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
Expand All @@ -100,8 +101,8 @@ class StructArrayLayout6i16 extends StructArray {

}

StructArrayLayout6i16.prototype.bytesPerElement = 16;
register('StructArrayLayout6i16', StructArrayLayout6i16);
StructArrayLayout2i4i12.prototype.bytesPerElement = 12;
register('StructArrayLayout2i4i12', StructArrayLayout2i4i12);


/**
Expand Down Expand Up @@ -290,11 +291,13 @@ register('StructArrayLayout6i1ul2ui2i24', StructArrayLayout6i1ul2ui2i24);

/**
* Implementation of the StructArray layout:
* [0]: Int16[6]
* [0]: Int16[2]
* [4]: Int16[2]
* [8]: Int16[2]
*
* @private
*/
class StructArrayLayout6i12 extends StructArray {
class StructArrayLayout2i2i2i12 extends StructArray {
uint8: Uint8Array;
int16: Int16Array;

Expand All @@ -318,8 +321,8 @@ class StructArrayLayout6i12 extends StructArray {

}

StructArrayLayout6i12.prototype.bytesPerElement = 12;
register('StructArrayLayout6i12', StructArrayLayout6i12);
StructArrayLayout2i2i2i12.prototype.bytesPerElement = 12;
register('StructArrayLayout2i2i2i12', StructArrayLayout2i2i2i12);


/**
Expand Down Expand Up @@ -472,7 +475,7 @@ register('StructArrayLayout3i6', StructArrayLayout3i6);
*
* @private
*/
class StructArrayLayout1ul2ui12 extends StructArray {
class StructArrayLayout1ul2ui8 extends StructArray {
uint8: Uint8Array;
uint32: Uint32Array;
uint16: Uint16Array;
Expand All @@ -486,8 +489,8 @@ class StructArrayLayout1ul2ui12 extends StructArray {
emplaceBack(v0: number, v1: number, v2: number) {
const i = this.length;
this.resize(i + 1);
const o4 = i * 3;
const o2 = i * 6;
const o4 = i * 2;
const o2 = i * 4;
this.uint32[o4 + 0] = v0;
this.uint16[o2 + 2] = v1;
this.uint16[o2 + 3] = v2;
Expand All @@ -496,8 +499,8 @@ class StructArrayLayout1ul2ui12 extends StructArray {

}

StructArrayLayout1ul2ui12.prototype.bytesPerElement = 12;
register('StructArrayLayout1ul2ui12', StructArrayLayout1ul2ui12);
StructArrayLayout1ul2ui8.prototype.bytesPerElement = 8;
register('StructArrayLayout1ul2ui8', StructArrayLayout1ul2ui8);


/**
Expand Down Expand Up @@ -825,19 +828,19 @@ class FeatureIndexStruct extends Struct {
set featureIndex(x) { this._structArray.uint32[this._pos4 + 0] = x; }
get sourceLayerIndex() { return this._structArray.uint16[this._pos2 + 2]; }
set sourceLayerIndex(x) { this._structArray.uint16[this._pos2 + 2] = x; }
get bucketIndex() { return this._structArray.uint16[this._pos2 + 4]; }
set bucketIndex(x) { this._structArray.uint16[this._pos2 + 4] = x; }
get bucketIndex() { return this._structArray.uint16[this._pos2 + 3]; }
set bucketIndex(x) { this._structArray.uint16[this._pos2 + 3] = x; }
}

FeatureIndexStruct.prototype.size = 12;
FeatureIndexStruct.prototype.size = 8;

export type FeatureIndex = FeatureIndexStruct;


/**
* @private
*/
class FeatureIndexArray extends StructArrayLayout1ul2ui12 {
class FeatureIndexArray extends StructArrayLayout1ul2ui8 {
/**
* Return the FeatureIndexStruct at the given location in the array.
* @param {number} index The index of the element.
Expand All @@ -854,18 +857,18 @@ register('FeatureIndexArray', FeatureIndexArray);
module.exports = {
StructArrayLayout2i4,
StructArrayLayout4i8,
StructArrayLayout6i16,
StructArrayLayout2i4i12,
StructArrayLayout4i4ub12,
StructArrayLayout4i4ui16,
StructArrayLayout3f12,
StructArrayLayout1ul4,
StructArrayLayout6i1ul2ui2i24,
StructArrayLayout6i12,
StructArrayLayout2i2i2i12,
StructArrayLayout2ub4,
StructArrayLayout2i2ui3ul3ui2f2ub40,
StructArrayLayout1f4,
StructArrayLayout3i6,
StructArrayLayout1ul2ui12,
StructArrayLayout1ul2ui8,
StructArrayLayout3ui6,
StructArrayLayout2ui4,
StructArrayLayout2f8,
Expand All @@ -874,14 +877,14 @@ module.exports = {
RasterBoundsArray: StructArrayLayout4i8,
CircleLayoutArray: StructArrayLayout2i4,
FillLayoutArray: StructArrayLayout2i4,
FillExtrusionLayoutArray: StructArrayLayout6i16,
FillExtrusionLayoutArray: StructArrayLayout2i4i12,
HeatmapLayoutArray: StructArrayLayout2i4,
LineLayoutArray: StructArrayLayout4i4ub12,
SymbolLayoutArray: StructArrayLayout4i4ui16,
SymbolDynamicLayoutArray: StructArrayLayout3f12,
SymbolOpacityArray: StructArrayLayout1ul4,
CollisionBoxLayoutArray: StructArrayLayout6i12,
CollisionCircleLayoutArray: StructArrayLayout6i12,
CollisionBoxLayoutArray: StructArrayLayout2i2i2i12,
CollisionCircleLayoutArray: StructArrayLayout2i2i2i12,
CollisionVertexArray: StructArrayLayout2ub4,
TriangleIndexArray: StructArrayLayout3ui6,
LineIndexArray: StructArrayLayout2ui4,
Expand Down
3 changes: 1 addition & 2 deletions src/data/bucket/fill_extrusion_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@
const {createLayout} = require('../../util/struct_array');
module.exports = createLayout([
{name: 'a_pos', components: 2, type: 'Int16'},
{name: 'a_normal', components: 3, type: 'Int16'},
{name: 'a_edgedistance', components: 1, type: 'Int16'}
{name: 'a_normal_ed', components: 4, type: 'Int16'},
], 4);
21 changes: 16 additions & 5 deletions src/data/bucket/fill_extrusion_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@ function addVertex(vertexArray, x, y, nx, ny, nz, t, e) {
// a_pos
x,
y,
// a_normal
// a_normal_ed: 3-component normal and 1-component edgedistance
Math.floor(nx * FACTOR) * 2 + t,
ny * FACTOR * 2,
nz * FACTOR * 2,

// a_edgedistance
// edgedistance (used for wrapping patterns around extrusion sides)
Math.round(e)
);
}
Expand Down Expand Up @@ -107,14 +106,17 @@ class FillExtrusionBucket implements Bucket {
for (const ring of polygon) {
numVertices += ring.length;
}

let segment = this.segments.prepareSegment(4, this.layoutVertexArray, this.indexArray);

for (const ring of polygon) {
if (ring.length === 0) {
continue;
}

if (isEntirelyOutside(ring)) {
continue;
}

let edgeDistance = 0;

for (let p = 0; p < ring.length; p++) {
Expand All @@ -129,11 +131,13 @@ class FillExtrusionBucket implements Bucket {
}

const perp = p1.sub(p2)._perp()._unit();
const dist = p2.dist(p1);
if (edgeDistance + dist > 32768) edgeDistance = 0;

addVertex(this.layoutVertexArray, p1.x, p1.y, perp.x, perp.y, 0, 0, edgeDistance);
addVertex(this.layoutVertexArray, p1.x, p1.y, perp.x, perp.y, 0, 1, edgeDistance);

edgeDistance += p2.dist(p1);
edgeDistance += dist;

addVertex(this.layoutVertexArray, p2.x, p2.y, perp.x, perp.y, 0, 0, edgeDistance);
addVertex(this.layoutVertexArray, p2.x, p2.y, perp.x, perp.y, 0, 1, edgeDistance);
Expand Down Expand Up @@ -203,3 +207,10 @@ function isBoundaryEdge(p1, p2) {
return (p1.x === p2.x && (p1.x < 0 || p1.x > EXTENT)) ||
(p1.y === p2.y && (p1.y < 0 || p1.y > EXTENT));
}

function isEntirelyOutside(ring) {
return ring.every(p => p.x < 0) ||
ring.every(p => p.x > EXTENT) ||
ring.every(p => p.y < 0) ||
ring.every(p => p.y > EXTENT);
}
12 changes: 6 additions & 6 deletions src/shaders/fill_extrusion.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ uniform lowp vec3 u_lightpos;
uniform lowp float u_lightintensity;

attribute vec2 a_pos;
attribute vec3 a_normal;
attribute float a_edgedistance;
attribute vec4 a_normal_ed;

varying vec4 v_color;

Expand All @@ -19,11 +18,12 @@ void main() {
#pragma mapbox: initialize lowp float height
#pragma mapbox: initialize highp vec4 color

vec3 normal = a_normal_ed.xyz;

base = max(0.0, base);
height = max(0.0, height);

float ed = a_edgedistance; // use each attrib in order to not trip a VAO assert
float t = mod(a_normal.x, 2.0);
float t = mod(normal.x, 2.0);

gl_Position = u_matrix * vec4(a_pos, t > 0.0 ? height : base, 1);

Expand All @@ -37,7 +37,7 @@ void main() {
color += ambientlight;

// Calculate cos(theta), where theta is the angle between surface normal and diffuse light ray
float directional = clamp(dot(a_normal / 16384.0, u_lightpos), 0.0, 1.0);
float directional = clamp(dot(normal / 16384.0, u_lightpos), 0.0, 1.0);

// Adjust directional so that
// the range of values for highlight/shading is narrower
Expand All @@ -46,7 +46,7 @@ void main() {
directional = mix((1.0 - u_lightintensity), max((1.0 - colorvalue + u_lightintensity), 1.0), directional);

// Add gradient along z axis of side surfaces
if (a_normal.y != 0.0) {
if (normal.y != 0.0) {
directional *= clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0);
}

Expand Down
16 changes: 9 additions & 7 deletions src/shaders/fill_extrusion_pattern.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ uniform lowp vec3 u_lightpos;
uniform lowp float u_lightintensity;

attribute vec2 a_pos;
attribute vec3 a_normal;
attribute float a_edgedistance;
attribute vec4 a_normal_ed;

varying vec2 v_pos_a;
varying vec2 v_pos_b;
Expand All @@ -28,26 +27,29 @@ void main() {
#pragma mapbox: initialize lowp float base
#pragma mapbox: initialize lowp float height

vec3 normal = a_normal_ed.xyz;
float edgedistance = a_normal_ed.w;

base = max(0.0, base);
height = max(0.0, height);

float t = mod(a_normal.x, 2.0);
float t = mod(normal.x, 2.0);
float z = t > 0.0 ? height : base;

gl_Position = u_matrix * vec4(a_pos, z, 1);

vec2 pos = a_normal.x == 1.0 && a_normal.y == 0.0 && a_normal.z == 16384.0
vec2 pos = normal.x == 1.0 && normal.y == 0.0 && normal.z == 16384.0
? a_pos // extrusion top
: vec2(a_edgedistance, z * u_height_factor); // extrusion side
: vec2(edgedistance, z * u_height_factor); // extrusion side

v_pos_a = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_a * u_pattern_size_a, u_tile_units_to_pixels, pos);
v_pos_b = get_pattern_pos(u_pixel_coord_upper, u_pixel_coord_lower, u_scale_b * u_pattern_size_b, u_tile_units_to_pixels, pos);

v_lighting = vec4(0.0, 0.0, 0.0, 1.0);
float directional = clamp(dot(a_normal / 16383.0, u_lightpos), 0.0, 1.0);
float directional = clamp(dot(normal / 16383.0, u_lightpos), 0.0, 1.0);
directional = mix((1.0 - u_lightintensity), max((0.5 + u_lightintensity), 1.0), directional);

if (a_normal.y != 0.0) {
if (normal.y != 0.0) {
directional *= clamp((t + base) * pow(height / 150.0, 0.5), mix(0.7, 0.98, 1.0 - u_lightintensity), 1.0);
}

Expand Down
2 changes: 1 addition & 1 deletion src/style/style_layer/background_style_layer_properties.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is generated. Edit build/generate-style-code.js, then run `node build/generate-style-code.js`.
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
// @flow
/* eslint-disable */

Expand Down
2 changes: 1 addition & 1 deletion src/style/style_layer/circle_style_layer_properties.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is generated. Edit build/generate-style-code.js, then run `node build/generate-style-code.js`.
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
// @flow
/* eslint-disable */

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is generated. Edit build/generate-style-code.js, then run `node build/generate-style-code.js`.
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
// @flow
/* eslint-disable */

Expand Down
2 changes: 1 addition & 1 deletion src/style/style_layer/fill_style_layer_properties.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is generated. Edit build/generate-style-code.js, then run `node build/generate-style-code.js`.
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
// @flow
/* eslint-disable */

Expand Down
2 changes: 1 addition & 1 deletion src/style/style_layer/heatmap_style_layer_properties.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is generated. Edit build/generate-style-code.js, then run `node build/generate-style-code.js`.
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
// @flow
/* eslint-disable */

Expand Down
2 changes: 1 addition & 1 deletion src/style/style_layer/hillshade_style_layer_properties.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file is generated. Edit build/generate-style-code.js, then run `node build/generate-style-code.js`.
// This file is generated. Edit build/generate-style-code.js, then run `yarn run codegen`.
// @flow
/* eslint-disable */

Expand Down
Loading

0 comments on commit b2ea22c

Please sign in to comment.