diff --git a/Apps/Sandcastle/gallery/development/Geometry Offset Attribute.html b/Apps/Sandcastle/gallery/development/Geometry Offset Attribute.html new file mode 100644 index 000000000000..19c38c511ef9 --- /dev/null +++ b/Apps/Sandcastle/gallery/development/Geometry Offset Attribute.html @@ -0,0 +1,195 @@ + + +
+ + + + + +true
and componentDatatype
is an integer format,
+ * indicate that the components should be mapped to the range [0, 1] (unsigned)
+ * or [-1, 1] (signed) when they are accessed as floating-point for rendering.
+ *
+ * @memberof OffsetGeometryInstanceAttribute.prototype
+ *
+ * @type {Boolean}
+ * @readonly
+ *
+ * @default false
+ */
+ normalize : {
+ get : function() {
+ return false;
+ }
+ }
+ });
+
+ /**
+ * Creates a new {@link OffsetGeometryInstanceAttribute} instance given the provided an enabled flag and {@link DistanceDisplayCondition}.
+ *
+ * @param {Cartesian3} offset The cartesian offset
+ * @returns {OffsetGeometryInstanceAttribute} The new {@link OffsetGeometryInstanceAttribute} instance.
+ */
+ OffsetGeometryInstanceAttribute.fromCartesian3 = function(offset) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.defined('offset', offset);
+ //>>includeEnd('debug');
+
+ return new OffsetGeometryInstanceAttribute(offset.x, offset.y, offset.z);
+ };
+
+ /**
+ * Converts a distance display condition to a typed array that can be used to assign a distance display condition attribute.
+ *
+ * @param {Cartesian3} offset The cartesian offset
+ * @param {Float32Array} [result] The array to store the result in, if undefined a new instance will be created.
+ * @returns {Float32Array} The modified result parameter or a new instance if result was undefined.
+ *
+ * @example
+ * var attributes = primitive.getGeometryInstanceAttributes('an id');
+ * attributes.modelMatrix = Cesium.OffsetGeometryInstanceAttribute.toValue(modelMatrix, attributes.modelMatrix);
+ */
+ OffsetGeometryInstanceAttribute.toValue = function(offset, result) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.defined('offset', offset);
+ //>>includeEnd('debug');
+
+ if (!defined(result)) {
+ result = new Float32Array([offset.x, offset.y, offset.z]);
+ }
+
+ result[0] = offset.x;
+ result[1] = offset.y;
+ result[2] = offset.z;
+ return result;
+ };
+
+ return OffsetGeometryInstanceAttribute;
+});
diff --git a/Source/Core/PolygonGeometry.js b/Source/Core/PolygonGeometry.js
index ddd97f6c05a1..5c214d2573f5 100644
--- a/Source/Core/PolygonGeometry.js
+++ b/Source/Core/PolygonGeometry.js
@@ -1,4 +1,5 @@
define([
+ './arrayFill',
'./BoundingRectangle',
'./BoundingSphere',
'./Cartesian2',
@@ -15,6 +16,7 @@ define([
'./Geometry',
'./GeometryAttribute',
'./GeometryInstance',
+ './GeometryOffsetAttribute',
'./GeometryPipeline',
'./IndexDatatype',
'./Math',
@@ -27,6 +29,7 @@ define([
'./VertexFormat',
'./WindingOrder'
], function(
+ arrayFill,
BoundingRectangle,
BoundingSphere,
Cartesian2,
@@ -43,6 +46,7 @@ define([
Geometry,
GeometryAttribute,
GeometryInstance,
+ GeometryOffsetAttribute,
GeometryPipeline,
IndexDatatype,
CesiumMath,
@@ -127,6 +131,11 @@ define([
var vertexFormat = options.vertexFormat;
var geometry = options.geometry;
var shadowVolume = options.shadowVolume;
+ var flatPositions = geometry.attributes.position.values;
+ var length = flatPositions.length;
+ var wall = options.wall;
+ var top = options.top || wall;
+ var bottom = options.bottom || wall;
if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent || shadowVolume) {
// PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision.
// PERFORMANCE_IDEA: Compute with createGeometryFromPositions() for fast path when there's no holes.
@@ -134,18 +143,12 @@ define([
var tangentPlane = options.tangentPlane;
var ellipsoid = options.ellipsoid;
var stRotation = options.stRotation;
- var wall = options.wall;
- var top = options.top || wall;
- var bottom = options.bottom || wall;
var perPositionHeight = options.perPositionHeight;
var origin = appendTextureCoordinatesOrigin;
origin.x = boundingRectangle.x;
origin.y = boundingRectangle.y;
- var flatPositions = geometry.attributes.position.values;
- var length = flatPositions.length;
-
var textureCoordinates = vertexFormat.st ? new Float32Array(2 * (length / 3)) : undefined;
var normals;
if (vertexFormat.normal) {
@@ -366,6 +369,29 @@ define([
});
}
}
+
+ if (options.extrude && defined(options.offsetAttribute)) {
+ var size = flatPositions.length / 3;
+ var offsetAttribute = new Uint8Array(size);
+
+ if (options.offsetAttribute === GeometryOffsetAttribute.TOP) {
+ if ((top && bottom) || wall) {
+ offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);
+ } else if (top) {
+ offsetAttribute = arrayFill(offsetAttribute, 1);
+ }
+ } else {
+ var offsetValue = options.offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;
+ offsetAttribute = arrayFill(offsetAttribute, offsetValue);
+ }
+
+ geometry.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values : offsetAttribute
+ });
+ }
+
return geometry;
}
@@ -429,7 +455,6 @@ define([
geos.topAndBottom = new GeometryInstance({
geometry : topGeo
});
-
}
var outerRing = hierarchy.outerRing;
@@ -595,6 +620,7 @@ define([
this._perPositionHeightExtrude = perPositionHeightExtrude;
this._shadowVolume = defaultValue(options.shadowVolume, false);
this._workerName = 'createPolygonGeometry';
+ this._offsetAttribute = options.offsetAttribute;
this._rectangle = undefined;
this._textureCoordinateRotationPoints = undefined;
@@ -603,7 +629,7 @@ define([
* The number of elements used to pack the object into an array.
* @type {Number}
*/
- this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + VertexFormat.packedLength + 10;
+ this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + VertexFormat.packedLength + 11;
}
/**
@@ -657,7 +683,8 @@ define([
granularity : options.granularity,
perPositionHeight : options.perPositionHeight,
closeTop : options.closeTop,
- closeBottom: options.closeBottom
+ closeBottom : options.closeBottom,
+ offsetAttribute : options.offsetAttribute
};
return new PolygonGeometry(newOptions);
};
@@ -696,6 +723,7 @@ define([
array[startingIndex++] = value._closeTop ? 1.0 : 0.0;
array[startingIndex++] = value._closeBottom ? 1.0 : 0.0;
array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0;
+ array[startingIndex++] = defaultValue(value._offsetAttribute, -1);
array[startingIndex] = value.packedLength;
return array;
@@ -704,7 +732,7 @@ define([
var scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);
var scratchVertexFormat = new VertexFormat();
- //Only used to avoid inaability to default construct.
+ //Only used to avoid inability to default construct.
var dummyOptions = {
polygonHierarchy : {}
};
@@ -742,6 +770,7 @@ define([
var closeTop = array[startingIndex++] === 1.0;
var closeBottom = array[startingIndex++] === 1.0;
var shadowVolume = array[startingIndex++] === 1.0;
+ var offsetAttribute = array[startingIndex++];
var packedLength = array[startingIndex];
if (!defined(result)) {
@@ -760,6 +789,7 @@ define([
result._closeTop = closeTop;
result._closeBottom = closeBottom;
result._shadowVolume = shadowVolume;
+ result._offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
result.packedLength = packedLength;
return result;
};
@@ -798,7 +828,6 @@ define([
outerPositions = hierarchy[0].outerRing;
var boundingRectangle = computeBoundingRectangle(tangentPlane, outerPositions, stRotation, scratchBoundingRectangle);
- var geometry;
var geometries = [];
var height = polygonGeometry._height;
@@ -815,29 +844,31 @@ define([
stRotation: stRotation,
bottom: false,
top: true,
- wall: false
+ wall: false,
+ extrude: false
};
var i;
if (extrude) {
+ options.extrude = true;
options.top = closeTop;
options.bottom = closeBottom;
options.shadowVolume = polygonGeometry._shadowVolume;
-
+ options.offsetAttribute = polygonGeometry._offsetAttribute;
for (i = 0; i < polygons.length; i++) {
- geometry = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], granularity, hierarchy[i], perPositionHeight, closeTop, closeBottom, vertexFormat);
+ var splitGeometry = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], granularity, hierarchy[i], perPositionHeight, closeTop, closeBottom, vertexFormat);
var topAndBottom;
if (closeTop && closeBottom) {
- topAndBottom = geometry.topAndBottom;
+ topAndBottom = splitGeometry.topAndBottom;
options.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(topAndBottom.geometry, height, extrudedHeight, ellipsoid, perPositionHeight);
} else if (closeTop) {
- topAndBottom = geometry.topAndBottom;
+ topAndBottom = splitGeometry.topAndBottom;
topAndBottom.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(topAndBottom.geometry.attributes.position.values, height, ellipsoid, !perPositionHeight);
options.geometry = topAndBottom.geometry;
} else if (closeBottom) {
- topAndBottom = geometry.topAndBottom;
+ topAndBottom = splitGeometry.topAndBottom;
topAndBottom.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(topAndBottom.geometry.attributes.position.values, extrudedHeight, ellipsoid, true);
options.geometry = topAndBottom.geometry;
}
@@ -847,7 +878,7 @@ define([
geometries.push(topAndBottom);
}
- var walls = geometry.walls;
+ var walls = splitGeometry.walls;
options.wall = true;
for ( var k = 0; k < walls.length; k++) {
var wall = walls[k];
@@ -858,17 +889,30 @@ define([
}
} else {
for (i = 0; i < polygons.length; i++) {
- geometry = new GeometryInstance({
+ var geometryInstance = new GeometryInstance({
geometry : PolygonGeometryLibrary.createGeometryFromPositions(ellipsoid, polygons[i], granularity, perPositionHeight, vertexFormat)
});
- geometry.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geometry.geometry.attributes.position.values, height, ellipsoid, !perPositionHeight);
- options.geometry = geometry.geometry;
- geometry.geometry = computeAttributes(options);
- geometries.push(geometry);
+ geometryInstance.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geometryInstance.geometry.attributes.position.values, height, ellipsoid, !perPositionHeight);
+ options.geometry = geometryInstance.geometry;
+ geometryInstance.geometry = computeAttributes(options);
+
+ if (defined(polygonGeometry._offsetAttribute)) {
+ var length = geometryInstance.geometry.attributes.position.values.length;
+ var applyOffset = new Uint8Array(length / 3);
+ var offsetValue = polygonGeometry._offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;
+ arrayFill(applyOffset, offsetValue);
+ geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values: applyOffset
+ });
+ }
+
+ geometries.push(geometryInstance);
}
}
- geometry = GeometryPipeline.combineInstances(geometries)[0];
+ var geometry = GeometryPipeline.combineInstances(geometries)[0];
geometry.attributes.position.values = new Float64Array(geometry.attributes.position.values);
geometry.indices = IndexDatatype.createTypedArray(geometry.attributes.position.values.length / 3, geometry.indices);
diff --git a/Source/Core/PolygonOutlineGeometry.js b/Source/Core/PolygonOutlineGeometry.js
index be5fe8c82881..ed02b8938d89 100644
--- a/Source/Core/PolygonOutlineGeometry.js
+++ b/Source/Core/PolygonOutlineGeometry.js
@@ -1,4 +1,5 @@
define([
+ './arrayFill',
'./arrayRemoveDuplicates',
'./BoundingSphere',
'./Cartesian3',
@@ -13,6 +14,7 @@ define([
'./GeometryAttribute',
'./GeometryAttributes',
'./GeometryInstance',
+ './GeometryOffsetAttribute',
'./GeometryPipeline',
'./IndexDatatype',
'./Math',
@@ -22,6 +24,7 @@ define([
'./Queue',
'./WindingOrder'
], function(
+ arrayFill,
arrayRemoveDuplicates,
BoundingSphere,
Cartesian3,
@@ -36,6 +39,7 @@ define([
GeometryAttribute,
GeometryAttributes,
GeometryInstance,
+ GeometryOffsetAttribute,
GeometryPipeline,
IndexDatatype,
CesiumMath,
@@ -317,13 +321,14 @@ define([
this._polygonHierarchy = polygonHierarchy;
this._perPositionHeight = perPositionHeight;
this._perPositionHeightExtrude = perPositionHeightExtrude;
+ this._offsetAttribute = options.offsetAttribute;
this._workerName = 'createPolygonOutlineGeometry';
/**
* The number of elements used to pack the object into an array.
* @type {Number}
*/
- this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + 6;
+ this.packedLength = PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + Ellipsoid.packedLength + 7;
}
/**
@@ -353,6 +358,7 @@ define([
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._perPositionHeightExtrude ? 1.0 : 0.0;
array[startingIndex++] = value._perPositionHeight ? 1.0 : 0.0;
+ array[startingIndex++] = defaultValue(value._offsetAttribute, -1);
array[startingIndex] = value.packedLength;
return array;
@@ -390,6 +396,7 @@ define([
var granularity = array[startingIndex++];
var perPositionHeightExtrude = array[startingIndex++] === 1.0;
var perPositionHeight = array[startingIndex++] === 1.0;
+ var offsetAttribute = array[startingIndex++];
var packedLength = array[startingIndex];
if (!defined(result)) {
@@ -403,6 +410,7 @@ define([
result._granularity = granularity;
result._perPositionHeight = perPositionHeight;
result._perPositionHeightExtrude = perPositionHeightExtrude;
+ result._offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
result.packedLength = packedLength;
return result;
@@ -451,7 +459,8 @@ define([
extrudedHeight : options.extrudedHeight,
ellipsoid : options.ellipsoid,
granularity : options.granularity,
- perPositionHeight : options.perPositionHeight
+ perPositionHeight : options.perPositionHeight,
+ offsetAttribute : options.offsetAttribute
};
return new PolygonOutlineGeometry(newOptions);
};
@@ -509,29 +518,58 @@ define([
return undefined;
}
- var geometry;
+ var geometryInstance;
var geometries = [];
var minDistance = CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);
var height = polygonGeometry._height;
var extrudedHeight = polygonGeometry._extrudedHeight;
var extrude = polygonGeometry._perPositionHeightExtrude || !CesiumMath.equalsEpsilon(height, extrudedHeight, 0, CesiumMath.EPSILON2);
-
+ var offsetValue;
if (extrude) {
for (i = 0; i < polygons.length; i++) {
- geometry = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], minDistance, perPositionHeight);
- geometry.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(geometry.geometry, height, extrudedHeight, ellipsoid, perPositionHeight);
- geometries.push(geometry);
+ geometryInstance = createGeometryFromPositionsExtruded(ellipsoid, polygons[i], minDistance, perPositionHeight);
+ geometryInstance.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(geometryInstance.geometry, height, extrudedHeight, ellipsoid, perPositionHeight);
+ if (defined(polygonGeometry._offsetAttribute)) {
+ var size = geometryInstance.geometry.attributes.position.values.length / 3;
+ var offsetAttribute = new Uint8Array(size);
+ if (polygonGeometry._offsetAttribute === GeometryOffsetAttribute.TOP) {
+ offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);
+ } else {
+ offsetValue = polygonGeometry._offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;
+ offsetAttribute = arrayFill(offsetAttribute, offsetValue);
+ }
+
+ geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values : offsetAttribute
+ });
+ }
+ geometries.push(geometryInstance);
}
} else {
for (i = 0; i < polygons.length; i++) {
- geometry = createGeometryFromPositions(ellipsoid, polygons[i], minDistance, perPositionHeight);
- geometry.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geometry.geometry.attributes.position.values, height, ellipsoid, !perPositionHeight);
- geometries.push(geometry);
+ geometryInstance = createGeometryFromPositions(ellipsoid, polygons[i], minDistance, perPositionHeight);
+ geometryInstance.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geometryInstance.geometry.attributes.position.values, height, ellipsoid, !perPositionHeight);
+
+ if (defined(polygonGeometry._offsetAttribute)) {
+ var length = geometryInstance.geometry.attributes.position.values.length;
+ var applyOffset = new Uint8Array(length / 3);
+ offsetValue = polygonGeometry._offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;
+ arrayFill(applyOffset, offsetValue);
+ geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values: applyOffset
+ });
+ }
+
+ geometries.push(geometryInstance);
}
}
- geometry = GeometryPipeline.combineInstances(geometries)[0];
+ var geometry = GeometryPipeline.combineInstances(geometries)[0];
var boundingSphere = BoundingSphere.fromVertices(geometry.attributes.position.values);
return new Geometry({
diff --git a/Source/Core/RectangleGeometry.js b/Source/Core/RectangleGeometry.js
index 0f5016d3a0c6..4dfec55be646 100644
--- a/Source/Core/RectangleGeometry.js
+++ b/Source/Core/RectangleGeometry.js
@@ -1,4 +1,5 @@
define([
+ './arrayFill',
'./BoundingSphere',
'./Cartesian2',
'./Cartesian3',
@@ -14,6 +15,7 @@ define([
'./GeometryAttribute',
'./GeometryAttributes',
'./GeometryInstance',
+ './GeometryOffsetAttribute',
'./GeometryPipeline',
'./IndexDatatype',
'./Math',
@@ -26,6 +28,7 @@ define([
'./RectangleGeometryLibrary',
'./VertexFormat'
], function(
+ arrayFill,
BoundingSphere,
Cartesian2,
Cartesian3,
@@ -41,6 +44,7 @@ define([
GeometryAttribute,
GeometryAttributes,
GeometryInstance,
+ GeometryOffsetAttribute,
GeometryPipeline,
IndexDatatype,
CesiumMath,
@@ -335,6 +339,7 @@ define([
function constructExtrudedRectangle(options) {
var shadowVolume = options.shadowVolume;
+ var offsetAttributeValue = options.offsetAttribute;
var vertexFormat = options.vertexFormat;
var minHeight = options.extrudedHeight;
var maxHeight = options.surfaceHeight;
@@ -392,6 +397,25 @@ define([
});
}
+ var offsetValue;
+ var hasOffsets = defined(offsetAttributeValue);
+ if (hasOffsets) {
+ var size = length / 3 * 2;
+ var offsetAttribute = new Uint8Array(size);
+ if (offsetAttributeValue === GeometryOffsetAttribute.TOP) {
+ offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);
+ } else {
+ offsetValue = offsetAttributeValue === GeometryOffsetAttribute.NONE ? 0 : 1;
+ offsetAttribute = arrayFill(offsetAttribute, offsetValue);
+ }
+
+ topBottomGeo.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values : offsetAttribute
+ });
+ }
+
if (vertexFormat.tangent) {
var topTangents = topBottomGeo.attributes.tangent.values;
tangents.set(topTangents);
@@ -431,11 +455,19 @@ define([
var wallPositions = new Float64Array(wallCount * 3);
var wallExtrudeNormals = shadowVolume ? new Float32Array(wallCount * 3) : undefined;
+ var wallOffsetAttribute = hasOffsets ? new Uint8Array(wallCount) : undefined;
var wallTextures = (vertexFormat.st) ? new Float32Array(wallCount * 2) : undefined;
+ var computeTopOffsets = offsetAttributeValue === GeometryOffsetAttribute.TOP;
+ if (hasOffsets && !computeTopOffsets) {
+ offsetValue = offsetAttributeValue === GeometryOffsetAttribute.ALL ? 1 : 0;
+ wallOffsetAttribute = arrayFill(wallOffsetAttribute, offsetValue);
+ }
+
var posIndex = 0;
var stIndex = 0;
var extrudeNormalIndex = 0;
+ var wallOffsetIndex = 0;
var area = width * height;
var threeI;
for (i = 0; i < area; i += width) {
@@ -452,6 +484,10 @@ define([
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
+ if (computeTopOffsets) {
+ wallOffsetAttribute[wallOffsetIndex++] = 1;
+ wallOffsetIndex += 1;
+ }
}
for (i = area - width; i < area; i++) {
@@ -468,6 +504,11 @@ define([
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
+ if (computeTopOffsets) {
+ wallOffsetAttribute[wallOffsetIndex++] = 1;
+ wallOffsetIndex += 1;
+ }
+
}
for (i = area - 1; i > 0; i -= width) {
@@ -484,6 +525,11 @@ define([
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
+ if (computeTopOffsets) {
+ wallOffsetAttribute[wallOffsetIndex++] = 1;
+ wallOffsetIndex += 1;
+ }
+
}
for (i = width - 1; i >= 0; i--) {
@@ -500,6 +546,10 @@ define([
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
+ if (computeTopOffsets) {
+ wallOffsetAttribute[wallOffsetIndex++] = 1;
+ wallOffsetIndex += 1;
+ }
}
var geo = calculateAttributesWall(wallPositions, vertexFormat, ellipsoid);
@@ -518,6 +568,13 @@ define([
values : wallExtrudeNormals
});
}
+ if (hasOffsets) {
+ geo.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values : wallOffsetAttribute
+ });
+ }
var wallIndices = IndexDatatype.createTypedArray(wallCount, perimeterPositions * 6);
@@ -652,6 +709,7 @@ define([
this._extrudedHeight = Math.min(height, extrudedHeight);
this._shadowVolume = defaultValue(options.shadowVolume, false);
this._workerName = 'createRectangleGeometry';
+ this._offsetAttribute = options.offsetAttribute;
this._rotatedRectangle = undefined;
this._textureCoordinateRotationPoints = undefined;
@@ -661,7 +719,7 @@ define([
* The number of elements used to pack the object into an array.
* @type {Number}
*/
- RectangleGeometry.packedLength = Rectangle.packedLength + Ellipsoid.packedLength + VertexFormat.packedLength + 6;
+ RectangleGeometry.packedLength = Rectangle.packedLength + Ellipsoid.packedLength + VertexFormat.packedLength + 7;
/**
* Stores the provided instance into the provided array.
@@ -694,7 +752,8 @@ define([
array[startingIndex++] = value._rotation;
array[startingIndex++] = value._stRotation;
array[startingIndex++] = value._extrudedHeight;
- array[startingIndex] = value._shadowVolume ? 1.0 : 0.0;
+ array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0;
+ array[startingIndex] = defaultValue(value._offsetAttribute, -1);
return array;
};
@@ -710,7 +769,8 @@ define([
rotation : undefined,
stRotation : undefined,
extrudedHeight : undefined,
- shadowVolume : undefined
+ shadowVolume : undefined,
+ offsetAttribute: undefined
};
/**
@@ -742,7 +802,8 @@ define([
var rotation = array[startingIndex++];
var stRotation = array[startingIndex++];
var extrudedHeight = array[startingIndex++];
- var shadowVolume = array[startingIndex] === 1.0;
+ var shadowVolume = array[startingIndex++] === 1.0;
+ var offsetAttribute = array[startingIndex];
if (!defined(result)) {
scratchOptions.granularity = granularity;
@@ -751,6 +812,8 @@ define([
scratchOptions.stRotation = stRotation;
scratchOptions.extrudedHeight = extrudedHeight;
scratchOptions.shadowVolume = shadowVolume;
+ scratchOptions.offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
+
return new RectangleGeometry(scratchOptions);
}
@@ -763,6 +826,7 @@ define([
result._stRotation = stRotation;
result._extrudedHeight = extrudedHeight;
result._shadowVolume = shadowVolume;
+ result._offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
return result;
};
@@ -819,6 +883,7 @@ define([
rectangle = rectangleGeometry._rectangle;
if (extrude) {
options.shadowVolume = rectangleGeometry._shadowVolume;
+ options.offsetAttribute = rectangleGeometry._offsetAttribute;
geometry = constructExtrudedRectangle(options);
var topBS = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, surfaceHeight, topBoundingSphere);
var bottomBS = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, extrudedHeight, bottomBoundingSphere);
@@ -826,6 +891,19 @@ define([
} else {
geometry = constructRectangle(options);
geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geometry.attributes.position.values, surfaceHeight, ellipsoid, false);
+
+ if (defined(rectangleGeometry._offsetAttribute)) {
+ var length = geometry.attributes.position.values.length;
+ var applyOffset = new Uint8Array(length / 3);
+ var offsetValue = rectangleGeometry._offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;
+ arrayFill(applyOffset, offsetValue);
+ geometry.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values: applyOffset
+ });
+ }
+
boundingSphere = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, surfaceHeight);
}
diff --git a/Source/Core/RectangleOutlineGeometry.js b/Source/Core/RectangleOutlineGeometry.js
index 9defa9b21155..7666b3109a6f 100644
--- a/Source/Core/RectangleOutlineGeometry.js
+++ b/Source/Core/RectangleOutlineGeometry.js
@@ -1,4 +1,5 @@
define([
+ './arrayFill',
'./BoundingSphere',
'./Cartesian3',
'./Cartographic',
@@ -10,6 +11,7 @@ define([
'./Geometry',
'./GeometryAttribute',
'./GeometryAttributes',
+ './GeometryOffsetAttribute',
'./IndexDatatype',
'./Math',
'./PolygonPipeline',
@@ -17,6 +19,7 @@ define([
'./Rectangle',
'./RectangleGeometryLibrary'
], function(
+ arrayFill,
BoundingSphere,
Cartesian3,
Cartographic,
@@ -28,6 +31,7 @@ define([
Geometry,
GeometryAttribute,
GeometryAttributes,
+ GeometryOffsetAttribute,
IndexDatatype,
CesiumMath,
PolygonPipeline,
@@ -213,6 +217,7 @@ define([
this._surfaceHeight = Math.max(height, extrudedHeight);
this._rotation = rotation;
this._extrudedHeight = Math.min(height, extrudedHeight);
+ this._offsetAttribute = options.offsetAttribute;
this._workerName = 'createRectangleOutlineGeometry';
}
@@ -220,7 +225,7 @@ define([
* The number of elements used to pack the object into an array.
* @type {Number}
*/
- RectangleOutlineGeometry.packedLength = Rectangle.packedLength + Ellipsoid.packedLength + 4;
+ RectangleOutlineGeometry.packedLength = Rectangle.packedLength + Ellipsoid.packedLength + 5;
/**
* Stores the provided instance into the provided array.
@@ -253,7 +258,8 @@ define([
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._surfaceHeight;
array[startingIndex++] = value._rotation;
- array[startingIndex] = value._extrudedHeight;
+ array[startingIndex++] = value._extrudedHeight;
+ array[startingIndex] = defaultValue(value._offsetAttribute, -1);
return array;
};
@@ -266,7 +272,8 @@ define([
granularity : undefined,
height : undefined,
rotation : undefined,
- extrudedHeight : undefined
+ extrudedHeight : undefined,
+ offsetAttribute: undefined
};
/**
@@ -295,13 +302,16 @@ define([
var granularity = array[startingIndex++];
var height = array[startingIndex++];
var rotation = array[startingIndex++];
- var extrudedHeight = array[startingIndex];
+ var extrudedHeight = array[startingIndex++];
+ var offsetAttribute = array[startingIndex];
if (!defined(result)) {
scratchOptions.granularity = granularity;
scratchOptions.height = height;
scratchOptions.rotation = rotation;
scratchOptions.extrudedHeight = extrudedHeight;
+ scratchOptions.offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
+
return new RectangleOutlineGeometry(scratchOptions);
}
@@ -310,6 +320,7 @@ define([
result._surfaceHeight = height;
result._rotation = rotation;
result._extrudedHeight = extrudedHeight;
+ result._offsetAttribute = offsetAttribute === -1 ? undefined : offsetAttribute;
return result;
};
@@ -341,15 +352,44 @@ define([
var surfaceHeight = rectangleGeometry._surfaceHeight;
var extrudedHeight = rectangleGeometry._extrudedHeight;
var extrude = !CesiumMath.equalsEpsilon(surfaceHeight, extrudedHeight, 0, CesiumMath.EPSILON2);
-
+ var offsetValue;
if (extrude) {
geometry = constructExtrudedRectangle(options);
+ if (defined(rectangleGeometry._offsetAttribute)) {
+ var size = geometry.attributes.position.values.length / 3;
+ var offsetAttribute = new Uint8Array(size);
+ if (rectangleGeometry._offsetAttribute === GeometryOffsetAttribute.TOP) {
+ offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);
+ } else {
+ offsetValue = rectangleGeometry._offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;
+ offsetAttribute = arrayFill(offsetAttribute, offsetValue);
+ }
+
+ geometry.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values : offsetAttribute
+ });
+ }
var topBS = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, surfaceHeight, topBoundingSphere);
var bottomBS = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, extrudedHeight, bottomBoundingSphere);
boundingSphere = BoundingSphere.union(topBS, bottomBS);
} else {
geometry = constructRectangle(options);
geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geometry.attributes.position.values, surfaceHeight, ellipsoid, false);
+
+ if (defined(rectangleGeometry._offsetAttribute)) {
+ var length = geometry.attributes.position.values.length;
+ var applyOffset = new Uint8Array(length / 3);
+ offsetValue = rectangleGeometry._offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;
+ arrayFill(applyOffset, offsetValue);
+ geometry.attributes.applyOffset = new GeometryAttribute({
+ componentDatatype : ComponentDatatype.UNSIGNED_BYTE,
+ componentsPerAttribute : 1,
+ values: applyOffset
+ });
+ }
+
boundingSphere = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, surfaceHeight);
}
diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js
index aa026437b501..dc581b4c4904 100644
--- a/Source/Scene/Primitive.js
+++ b/Source/Scene/Primitive.js
@@ -18,8 +18,10 @@ define([
'../Core/Geometry',
'../Core/GeometryAttribute',
'../Core/GeometryAttributes',
+ '../Core/Intersect',
'../Core/isArray',
'../Core/Matrix4',
+ '../Core/Plane',
'../Core/RuntimeError',
'../Core/subdivideArray',
'../Core/TaskProcessor',
@@ -59,8 +61,10 @@ define([
Geometry,
GeometryAttribute,
GeometryAttributes,
+ Intersect,
isArray,
Matrix4,
+ Plane,
RuntimeError,
subdivideArray,
TaskProcessor,
@@ -379,8 +383,11 @@ define([
this._batchTable = undefined;
this._batchTableAttributeIndices = undefined;
+ this._offsetInstanceExtend = undefined;
this._instanceBoundingSpheres = undefined;
this._instanceBoundingSpheresCV = undefined;
+ this._tempBoundingSpheres = undefined;
+ this._recomputeBoundingSpheres = false;
this._batchTableBoundingSpheresUpdated = false;
this._batchTableBoundingSphereAttributeIndices = undefined;
}
@@ -603,19 +610,19 @@ define([
functionName : 'czm_batchTable_boundingSphereCenter3DHigh',
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3
- },{
+ }, {
functionName : 'czm_batchTable_boundingSphereCenter3DLow',
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3
- },{
+ }, {
functionName : 'czm_batchTable_boundingSphereCenter2DHigh',
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3
- },{
+ }, {
functionName : 'czm_batchTable_boundingSphereCenter2DLow',
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 3
- },{
+ }, {
functionName : 'czm_batchTable_boundingSphereRadius',
componentDatatype : ComponentDatatype.FLOAT,
componentsPerAttribute : 1
@@ -720,6 +727,7 @@ define([
function cloneInstance(instance, geometry) {
return {
geometry : geometry,
+ attributes: instance.attributes,
modelMatrix : Matrix4.clone(instance.modelMatrix),
pickPrimitive : instance.pickPrimitive,
id : instance.id
@@ -867,6 +875,21 @@ define([
return vsPick;
};
+ Primitive._appendOffsetToShader = function(primitive, vertexShaderSource) {
+ if (!defined(primitive._batchTableAttributeIndices.offset)) {
+ return vertexShaderSource;
+ }
+
+ var attr = 'attribute float batchId;\n';
+ attr += 'attribute float applyOffset;';
+ var modifiedShader = vertexShaderSource.replace(/attribute\s+float\s+batchId;/g, attr);
+
+ var str = 'vec4 $1 = czm_computePosition();\n';
+ str += ' $1 = $1 + vec4(czm_batchTable_offset(batchId) * applyOffset, 0.0);';
+ modifiedShader = modifiedShader.replace(/vec4\s+([A-Za-z0-9_]+)\s+=\s+czm_computePosition\(\);/g, str);
+ return modifiedShader;
+ };
+
Primitive._appendDistanceDisplayConditionToShader = function(primitive, vertexShaderSource, scene3DOnly) {
if (!defined(primitive._batchTableAttributeIndices.distanceDisplayCondition)) {
return vertexShaderSource;
@@ -1049,7 +1072,7 @@ define([
if (shaderAttributes.hasOwnProperty(name)) {
if (!defined(attributeLocations[name])) {
throw new DeveloperError('Appearance/Geometry mismatch. The appearance requires vertex shader attribute input \'' + name +
- '\', which was not computed as part of the Geometry. Use the appearance\'s vertexFormat property when constructing the geometry.');
+ '\', which was not computed as part of the Geometry. Use the appearance\'s vertexFormat property when constructing the geometry.');
}
}
}
@@ -1177,10 +1200,12 @@ define([
primitive._attributeLocations = result.attributeLocations;
primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix);
primitive._pickOffsets = result.pickOffsets;
+ primitive._offsetInstanceExtend = result.offsetInstanceExtend;
primitive._instanceBoundingSpheres = result.boundingSpheres;
primitive._instanceBoundingSpheresCV = result.boundingSpheresCV;
if (defined(primitive._geometries) && primitive._geometries.length > 0) {
+ primitive._recomputeBoundingSpheres = true;
primitive._state = PrimitiveState.COMBINED;
} else {
setReady(primitive, frameState, PrimitiveState.FAILED, undefined);
@@ -1237,16 +1262,93 @@ define([
primitive._attributeLocations = result.attributeLocations;
primitive.modelMatrix = Matrix4.clone(result.modelMatrix, primitive.modelMatrix);
primitive._pickOffsets = result.pickOffsets;
+ primitive._offsetInstanceExtend = result.offsetInstanceExtend;
primitive._instanceBoundingSpheres = result.boundingSpheres;
primitive._instanceBoundingSpheresCV = result.boundingSpheresCV;
if (defined(primitive._geometries) && primitive._geometries.length > 0) {
+ primitive._recomputeBoundingSpheres = true;
primitive._state = PrimitiveState.COMBINED;
} else {
setReady(primitive, frameState, PrimitiveState.FAILED, undefined);
}
}
+ function recomputeBoundingSpheres(primitive, frameState) {
+ var offsetIndex = primitive._batchTableAttributeIndices.offset;
+ if (!primitive._recomputeBoundingSpheres || !defined(offsetIndex)) {
+ primitive._recomputeBoundingSpheres = false;
+ return;
+ }
+
+ var i;
+ var offsetInstanceExtend = primitive._offsetInstanceExtend;
+ var boundingSpheres = primitive._instanceBoundingSpheres;
+ var length = boundingSpheres.length;
+ var newBoundingSpheres = primitive._tempBoundingSpheres;
+ if (!defined(newBoundingSpheres)) {
+ newBoundingSpheres = new Array(length);
+ for (i = 0; i < length; i++) {
+ newBoundingSpheres[i] = new BoundingSphere();
+ }
+ primitive._tempBoundingSpheres = newBoundingSpheres;
+ }
+ for (i = 0; i < length; ++i) {
+ var newBS = newBoundingSpheres[i];
+ var offset = primitive._batchTable.getBatchedAttribute(i, offsetIndex, new Cartesian3());
+ newBS = boundingSpheres[i].clone(newBS);
+ transformBoundingSphere(newBS, offset, offsetInstanceExtend[i]);
+ }
+ var combinedBS = [];
+ var combinedWestBS = [];
+ var combinedEastBS = [];
+
+ for (i = 0; i < length; ++i) {
+ var bs = newBoundingSpheres[i];
+
+ var minX = bs.center.x - bs.radius;
+ if (minX > 0 || BoundingSphere.intersectPlane(bs, Plane.ORIGIN_ZX_PLANE) !== Intersect.INTERSECTING) {
+ combinedBS.push(bs);
+ } else {
+ combinedWestBS.push(bs);
+ combinedEastBS.push(bs);
+ }
+ }
+
+ var resultBS1 = combinedBS[0];
+ var resultBS2 = combinedEastBS[0];
+ var resultBS3 = combinedWestBS[0];
+
+ for (i = 1; i < combinedBS.length; i++) {
+ resultBS1 = BoundingSphere.union(resultBS1, combinedBS[i]);
+ }
+ for (i = 1; i < combinedEastBS.length; i++) {
+ resultBS2 = BoundingSphere.union(resultBS2, combinedEastBS[i]);
+ }
+ for (i = 1; i < combinedWestBS.length; i++) {
+ resultBS3 = BoundingSphere.union(resultBS3, combinedWestBS[i]);
+ }
+ var result = [];
+ if (defined(resultBS1)) {
+ result.push(resultBS1);
+ }
+ if (defined(resultBS2)) {
+ result.push(resultBS2);
+ }
+ if (defined(resultBS3)) {
+ result.push(resultBS3);
+ }
+
+ for (i = 0; i < result.length; i++) {
+ var boundingSphere = result[i].clone(primitive._boundingSpheres[i]);
+ primitive._boundingSpheres[i] = boundingSphere;
+ primitive._boundingSphereCV[i] = BoundingSphere.projectTo2D(boundingSphere, frameState.mapProjection, primitive._boundingSphereCV[i]);
+ }
+
+ Primitive._updateBoundingVolumes(primitive, frameState, primitive.modelMatrix, true);
+ primitive._recomputeBoundingSpheres = false;
+ }
+
var scratchBoundingSphereCenterEncoded = new EncodedCartesian3();
var scratchBoundingSphereCartographic = new Cartographic();
var scratchBoundingSphereCenter2D = new Cartesian3();
@@ -1403,6 +1505,7 @@ define([
var attributeLocations = primitive._attributeLocations;
var vs = primitive._batchTable.getVertexShaderCallback()(appearance.vertexShaderSource);
+ vs = Primitive._appendOffsetToShader(primitive, vs);
vs = Primitive._appendShowToShader(primitive, vs);
vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs, frameState.scene3DOnly);
vs = appendPickToVertexShader(vs);
@@ -1572,26 +1675,12 @@ define([
}
}
- Primitive._updateBoundingVolumes = function(primitive, frameState, modelMatrix) {
+ Primitive._updateBoundingVolumes = function(primitive, frameState, modelMatrix, forceUpdate) {
var i;
var length;
var boundingSphere;
- // Update bounding volumes for primitives that are sized in pixels.
- // The pixel size in meters varies based on the distance from the camera.
- var pixelSize = primitive.appearance.pixelSize;
- if (defined(pixelSize)) {
- length = primitive._boundingSpheres.length;
- for (i = 0; i < length; ++i) {
- boundingSphere = primitive._boundingSpheres[i];
- var boundingSphereWC = primitive._boundingSphereWC[i];
- var pixelSizeInMeters = frameState.camera.getPixelSize(boundingSphere, frameState.context.drawingBufferWidth, frameState.context.drawingBufferHeight);
- var sizeInMeters = pixelSizeInMeters * pixelSize;
- boundingSphereWC.radius = boundingSphere.radius + sizeInMeters;
- }
- }
-
- if (!Matrix4.equals(modelMatrix, primitive._modelMatrix)) {
+ if (forceUpdate || !Matrix4.equals(modelMatrix, primitive._modelMatrix)) {
Matrix4.clone(modelMatrix, primitive._modelMatrix);
length = primitive._boundingSpheres.length;
for (i = 0; i < length; ++i) {
@@ -1606,6 +1695,20 @@ define([
}
}
}
+
+ // Update bounding volumes for primitives that are sized in pixels.
+ // The pixel size in meters varies based on the distance from the camera.
+ var pixelSize = primitive.appearance.pixelSize;
+ if (defined(pixelSize)) {
+ length = primitive._boundingSpheres.length;
+ for (i = 0; i < length; ++i) {
+ boundingSphere = primitive._boundingSpheres[i];
+ var boundingSphereWC = primitive._boundingSphereWC[i];
+ var pixelSizeInMeters = frameState.camera.getPixelSize(boundingSphere, frameState.context.drawingBufferWidth, frameState.context.drawingBufferHeight);
+ var sizeInMeters = pixelSizeInMeters * pixelSize;
+ boundingSphereWC.radius = boundingSphere.radius + sizeInMeters;
+ }
+ }
};
function updateAndQueueCommands(primitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume, twoPasses) {
@@ -1724,6 +1827,10 @@ define([
return;
}
+ if (this._recomputeBoundingSpheres) {
+ recomputeBoundingSpheres(this, frameState);
+ }
+
// Create or recreate render state and shader program if appearance/material changed
var appearance = this.appearance;
var material = appearance.material;
@@ -1735,7 +1842,7 @@ define([
this._material = material;
createRS = true;
createSP = true;
- } else if (this._material !== material ) {
+ } else if (this._material !== material) {
this._material = material;
createSP = true;
}
@@ -1784,6 +1891,21 @@ define([
updateAndQueueCommandsFunc(this, frameState, this._colorCommands, this._pickCommands, this.modelMatrix, this.cull, this.debugShowBoundingVolume, twoPasses);
};
+ var offsetBoundingSphereScratch1 = new BoundingSphere();
+ var offsetBoundingSphereScratch2 = new BoundingSphere();
+ function transformBoundingSphere(boundingSphere, offset, extend) {
+ if (extend) {
+ var origBS = BoundingSphere.clone(boundingSphere, offsetBoundingSphereScratch1);
+ var offsetBS = BoundingSphere.clone(boundingSphere, offsetBoundingSphereScratch2);
+ offsetBS.center = Cartesian3.add(offsetBS.center, offset, offsetBS.center);
+ boundingSphere = BoundingSphere.union(origBS, offsetBS, boundingSphere);
+ } else {
+ boundingSphere.center = Cartesian3.add(boundingSphere.center, offset, boundingSphere.center);
+ }
+
+ return boundingSphere;
+ }
+
function createGetFunction(batchTable, instanceIndex, attributeIndex) {
return function() {
var attributeValue = batchTable.getBatchedAttribute(instanceIndex, attributeIndex);
@@ -1799,7 +1921,7 @@ define([
};
}
- function createSetFunction(batchTable, instanceIndex, attributeIndex) {
+ function createSetFunction(batchTable, instanceIndex, attributeIndex, primitive, name) {
return function(value) {
//>>includeStart('debug', pragmas.debug);
if (!defined(value) || !defined(value.length) || value.length < 1 || value.length > 4) {
@@ -1808,17 +1930,29 @@ define([
//>>includeEnd('debug');
var attributeValue = getAttributeValue(value);
batchTable.setBatchedAttribute(instanceIndex, attributeIndex, attributeValue);
+ if (name === 'offset') {
+ primitive._recomputeBoundingSpheres = true;
+ }
};
}
+ var offsetScratch = new Cartesian3();
+
function createBoundingSphereProperties(primitive, properties, index) {
properties.boundingSphere = {
get : function() {
var boundingSphere = primitive._instanceBoundingSpheres[index];
- var modelMatrix = primitive.modelMatrix;
- if (defined(modelMatrix) && defined(boundingSphere)) {
- boundingSphere = BoundingSphere.transform(boundingSphere, modelMatrix);
+ if (defined(boundingSphere)) {
+ var modelMatrix = primitive.modelMatrix;
+ var offset = properties.offset;
+ if (defined(offset)) {
+ transformBoundingSphere(boundingSphere.center, Cartesian3.fromArray(offset, 0, offsetScratch), primitive._offsetInstanceExtend[index]);
+ }
+ if (defined(modelMatrix)) {
+ boundingSphere = BoundingSphere.transform(boundingSphere, modelMatrix);
+ }
}
+
return boundingSphere;
}
};
@@ -1850,6 +1984,7 @@ define([
* attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA);
* attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true);
* attributes.distanceDisplayCondition = Cesium.DistanceDisplayConditionGeometryInstanceAttribute.toValue(100.0, 10000.0);
+ * attributes.offset = Cesium.OffsetGeometryInstanceAttribute.toValue(Cartesian3.IDENTITY);
*/
Primitive.prototype.getGeometryInstanceAttributes = function(id) {
//>>includeStart('debug', pragmas.debug);
@@ -1907,7 +2042,7 @@ define([
}
if (createSetter) {
- properties[name].set = createSetFunction(batchTable, index, attributeIndex);
+ properties[name].set = createSetFunction(batchTable, index, attributeIndex, this, name);
}
}
}
diff --git a/Source/Scene/PrimitivePipeline.js b/Source/Scene/PrimitivePipeline.js
index 353a6a2e072a..b4549b046d92 100644
--- a/Source/Scene/PrimitivePipeline.js
+++ b/Source/Scene/PrimitivePipeline.js
@@ -12,6 +12,7 @@ define([
'../Core/GeometryPipeline',
'../Core/IndexDatatype',
'../Core/Matrix4',
+ '../Core/OffsetGeometryInstanceAttribute',
'../Core/WebMercatorProjection'
], function(
BoundingSphere,
@@ -27,6 +28,7 @@ define([
GeometryPipeline,
IndexDatatype,
Matrix4,
+ OffsetGeometryInstanceAttribute,
WebMercatorProjection) {
'use strict';
@@ -109,7 +111,7 @@ define([
var primitiveType;
var length = instances.length;
- for (i = 0 ; i < length; ++i) {
+ for (i = 0; i < length; ++i) {
if (defined(instances[i].geometry)) {
primitiveType = instances[i].geometry.primitiveType;
break;
@@ -274,6 +276,8 @@ define([
var length = instances.length;
var pickOffsets;
+ var offsetInstanceExtend;
+ var hasOffset = false;
if (length > 0) {
geometries = geometryPipeline(parameters);
if (geometries.length > 0) {
@@ -282,6 +286,10 @@ define([
pickOffsets = createInstancePickOffsets(instances, geometries);
}
}
+ if (defined(instances[0].attributes) && defined(instances[0].attributes.offset)) {
+ offsetInstanceExtend = new Array(length);
+ hasOffset = true;
+ }
}
var boundingSpheres = new Array(length);
@@ -292,6 +300,9 @@ define([
if (defined(geometry)) {
boundingSpheres[i] = geometry.boundingSphere;
boundingSpheresCV[i] = geometry.boundingSphereCV;
+ if (hasOffset) {
+ offsetInstanceExtend[i] = defined(instance.geometry.attributes) && defined(instance.geometry.attributes.applyOffset) && instance.geometry.attributes.applyOffset.values.indexOf(0) !== -1;
+ }
}
var eastHemisphereGeometry = instance.eastHemisphereGeometry;
@@ -311,6 +322,7 @@ define([
modelMatrix : parameters.modelMatrix,
attributeLocations : attributeLocations,
pickOffsets : pickOffsets,
+ offsetInstanceExtend : offsetInstanceExtend,
boundingSpheres : boundingSpheres,
boundingSpheresCV : boundingSpheresCV
};
@@ -318,7 +330,7 @@ define([
function transferGeometry(geometry, transferableObjects) {
var attributes = geometry.attributes;
- for ( var name in attributes) {
+ for (var name in attributes) {
if (attributes.hasOwnProperty(name)) {
var attribute = attributes[name];
@@ -356,7 +368,7 @@ define([
count += 6 + 2 * BoundingSphere.packedLength + (defined(geometry.indices) ? geometry.indices.length : 0);
- for ( var property in attributes) {
+ for (var property in attributes) {
if (attributes.hasOwnProperty(property) && defined(attributes[property])) {
var attribute = attributes[property];
count += 5 + attribute.values.length;
@@ -409,7 +421,7 @@ define([
var attributes = geometry.attributes;
var attributesToWrite = [];
- for ( var property in attributes) {
+ for (var property in attributes) {
if (attributes.hasOwnProperty(property) && defined(attributes[property])) {
attributesToWrite.push(property);
if (!defined(stringHash[property])) {
@@ -539,14 +551,20 @@ define([
function packInstancesForCombine(instances, transferableObjects) {
var length = instances.length;
- var packedData = new Float64Array(1 + (length * 16));
+ var packedData = new Float64Array(1 + (length * 19));
var count = 0;
packedData[count++] = length;
for (var i = 0; i < length; i++) {
var instance = instances[i];
-
Matrix4.pack(instance.modelMatrix, packedData, count);
count += Matrix4.packedLength;
+ if (defined(instance.attributes) && defined(instance.attributes.offset)) {
+ var values = instance.attributes.offset.value;
+ packedData[count] = values[0];
+ packedData[count + 1] = values[1];
+ packedData[count + 2] = values[2];
+ }
+ count += 3;
}
transferableObjects.push(packedData.buffer);
@@ -561,10 +579,18 @@ define([
var i = 1;
while (i < packedInstances.length) {
var modelMatrix = Matrix4.unpack(packedInstances, i);
+ var attributes;
i += Matrix4.packedLength;
+ if (defined(packedInstances[i])) {
+ attributes = {
+ offset : new OffsetGeometryInstanceAttribute(packedInstances[i], packedInstances[i + 1], packedInstances[i + 2])
+ };
+ }
+ i += 3;
result[count++] = {
- modelMatrix : modelMatrix
+ modelMatrix : modelMatrix,
+ attributes : attributes
};
}
@@ -687,6 +713,7 @@ define([
attributeLocations : results.attributeLocations,
modelMatrix : results.modelMatrix,
pickOffsets : results.pickOffsets,
+ offsetInstanceExtend: results.offsetInstanceExtend,
boundingSpheres : packedBoundingSpheres,
boundingSpheresCV : packedBoundingSpheresCV
};
@@ -701,6 +728,7 @@ define([
attributeLocations : packedResult.attributeLocations,
modelMatrix : packedResult.modelMatrix,
pickOffsets : packedResult.pickOffsets,
+ offsetInstanceExtend: packedResult.offsetInstanceExtend,
boundingSpheres : unpackBoundingSpheres(packedResult.boundingSpheres),
boundingSpheresCV : unpackBoundingSpheres(packedResult.boundingSpheresCV)
};
diff --git a/Specs/Core/CircleGeometrySpec.js b/Specs/Core/CircleGeometrySpec.js
index 1d247c4a7fd0..c31b377543e0 100644
--- a/Specs/Core/CircleGeometrySpec.js
+++ b/Specs/Core/CircleGeometrySpec.js
@@ -193,6 +193,6 @@ defineSuite([
radius : 1.0,
stRotation : CesiumMath.PI_OVER_TWO
});
- var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, CesiumMath.PI_OVER_TWO, 0.0, 0.1, 0.0, 0.0];
+ var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, CesiumMath.PI_OVER_TWO, 0.0, 0.1, 0.0, 0.0, -1];
createPackableSpecs(CircleGeometry, packableInstance, packedInstance);
});
diff --git a/Specs/Core/CircleOutlineGeometrySpec.js b/Specs/Core/CircleOutlineGeometrySpec.js
index c99c39102320..916e1c203e35 100644
--- a/Specs/Core/CircleOutlineGeometrySpec.js
+++ b/Specs/Core/CircleOutlineGeometrySpec.js
@@ -104,7 +104,7 @@ defineSuite([
height : 5,
extrudedHeight : 7
});
- var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 2, 2, 0, 7, 1, 5, 4];
+ var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 2, 2, 0, 7, 1, 5, 4, -1];
createPackableSpecs(CircleOutlineGeometry, packableInstance, packedInstance, 'extruded');
//Because extrudedHeight is optional and has to be taken into account when packing, we have a second test without it.
@@ -116,6 +116,6 @@ defineSuite([
numberOfVerticalLines : 4,
height : 5
});
- packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 2, 2, 0, 5, 1, 5, 4];
+ packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 2, 2, 0, 5, 1, 5, 4, -1];
createPackableSpecs(CircleOutlineGeometry, packableInstance, packedInstance, 'at height');
});
diff --git a/Specs/Core/CorridorGeometrySpec.js b/Specs/Core/CorridorGeometrySpec.js
index dca5468bf5b2..0fbfe8c00dea 100644
--- a/Specs/Core/CorridorGeometrySpec.js
+++ b/Specs/Core/CorridorGeometrySpec.js
@@ -1,17 +1,21 @@
defineSuite([
'Core/CorridorGeometry',
+ 'Core/arrayFill',
'Core/Cartesian3',
'Core/CornerType',
'Core/Ellipsoid',
+ 'Core/GeometryOffsetAttribute',
'Core/Math',
'Core/Rectangle',
'Core/VertexFormat',
'Specs/createPackableSpecs'
], function(
CorridorGeometry,
+ arrayFill,
Cartesian3,
CornerType,
Ellipsoid,
+ GeometryOffsetAttribute,
CesiumMath,
Rectangle,
VertexFormat,
@@ -128,6 +132,76 @@ defineSuite([
expect(m.indices.length).toEqual(numTriangles * 3);
});
+ it('computes offset attribute', function() {
+ var m = CorridorGeometry.createGeometry(new CorridorGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ 90.0, -30.0,
+ 90.0, -35.0
+ ]),
+ cornerType: CornerType.MITERED,
+ width : 30000,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 12;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for top vertices', function() {
+ var m = CorridorGeometry.createGeometry(new CorridorGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ 90.0, -30.0,
+ 90.0, -35.0
+ ]),
+ cornerType: CornerType.MITERED,
+ width : 30000,
+ extrudedHeight: 30000,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 72;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 12);
+ expected = arrayFill(expected, 1, 24, 48);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for all vertices', function() {
+ var m = CorridorGeometry.createGeometry(new CorridorGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ 90.0, -30.0,
+ 90.0, -35.0
+ ]),
+ cornerType: CornerType.MITERED,
+ width : 30000,
+ extrudedHeight: 30000,
+ offsetAttribute: GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 72;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
it('computes right turn', function() {
var m = CorridorGeometry.createGeometry(new CorridorGeometry({
vertexFormat : VertexFormat.POSITION_ONLY,
@@ -320,6 +394,6 @@ defineSuite([
var packedInstance = [2, positions[0].x, positions[0].y, positions[0].z, positions[1].x, positions[1].y, positions[1].z];
packedInstance.push(Ellipsoid.WGS84.radii.x, Ellipsoid.WGS84.radii.y, Ellipsoid.WGS84.radii.z);
packedInstance.push(1.0, 0.0, 0.0, 0.0, 0.0, 0.0);
- packedInstance.push(30000.0, 0.0, 0.0, 2.0, 0.1, 0.0);
+ packedInstance.push(30000.0, 0.0, 0.0, 2.0, 0.1, 0.0, -1);
createPackableSpecs(CorridorGeometry, corridor, packedInstance);
});
diff --git a/Specs/Core/CorridorOutlineGeometrySpec.js b/Specs/Core/CorridorOutlineGeometrySpec.js
index 4392d7b89468..c1b31b935174 100644
--- a/Specs/Core/CorridorOutlineGeometrySpec.js
+++ b/Specs/Core/CorridorOutlineGeometrySpec.js
@@ -1,14 +1,18 @@
defineSuite([
'Core/CorridorOutlineGeometry',
+ 'Core/arrayFill',
'Core/Cartesian3',
'Core/CornerType',
'Core/Ellipsoid',
+ 'Core/GeometryOffsetAttribute',
'Specs/createPackableSpecs'
], function(
CorridorOutlineGeometry,
+ arrayFill,
Cartesian3,
CornerType,
Ellipsoid,
+ GeometryOffsetAttribute,
createPackableSpecs) {
'use strict';
@@ -73,6 +77,72 @@ defineSuite([
expect(m.indices.length).toEqual(28 * 2); // 5 segments * 4 lines per segment + 4 lines * 2 ends
});
+ it('computes offset attribute for top vertices', function() {
+ var m = CorridorOutlineGeometry.createGeometry(new CorridorOutlineGeometry({
+ positions : Cartesian3.fromDegreesArray([
+ 90.0, -30.0,
+ 90.0, -35.0
+ ]),
+ cornerType: CornerType.MITERED,
+ width : 30000,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 12;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3); // 6 left + 6 right
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for top vertices', function() {
+ var m = CorridorOutlineGeometry.createGeometry(new CorridorOutlineGeometry({
+ positions : Cartesian3.fromDegreesArray([
+ 90.0, -30.0,
+ 90.0, -35.0
+ ]),
+ cornerType: CornerType.MITERED,
+ width : 30000,
+ extrudedHeight: 30000,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 24;
+ expect(m.attributes.position.values.length).toEqual(24 * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 12);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for all vertices', function() {
+ var m = CorridorOutlineGeometry.createGeometry(new CorridorOutlineGeometry({
+ positions : Cartesian3.fromDegreesArray([
+ 90.0, -30.0,
+ 90.0, -35.0
+ ]),
+ cornerType: CornerType.MITERED,
+ width : 30000,
+ extrudedHeight: 30000,
+ offsetAttribute: GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 24;
+ expect(m.attributes.position.values.length).toEqual(24 * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
it('computes right turn', function() {
var m = CorridorOutlineGeometry.createGeometry(new CorridorOutlineGeometry({
positions : Cartesian3.fromDegreesArray([
@@ -175,6 +245,6 @@ defineSuite([
});
var packedInstance = [2, positions[0].x, positions[0].y, positions[0].z, positions[1].x, positions[1].y, positions[1].z];
packedInstance.push(Ellipsoid.WGS84.radii.x, Ellipsoid.WGS84.radii.y, Ellipsoid.WGS84.radii.z);
- packedInstance.push(30000.0, 0.0, 0.0, 2.0, 0.1);
+ packedInstance.push(30000.0, 0.0, 0.0, 2.0, 0.1, -1);
createPackableSpecs(CorridorOutlineGeometry, corridor, packedInstance);
});
diff --git a/Specs/Core/EllipseGeometrySpec.js b/Specs/Core/EllipseGeometrySpec.js
index 9f331f0d4841..5003bdcc99fe 100644
--- a/Specs/Core/EllipseGeometrySpec.js
+++ b/Specs/Core/EllipseGeometrySpec.js
@@ -1,14 +1,18 @@
defineSuite([
'Core/EllipseGeometry',
+ 'Core/arrayFill',
'Core/Cartesian3',
'Core/Ellipsoid',
+ 'Core/GeometryOffsetAttribute',
'Core/Math',
'Core/VertexFormat',
'Specs/createPackableSpecs'
], function(
EllipseGeometry,
+ arrayFill,
Cartesian3,
Ellipsoid,
+ GeometryOffsetAttribute,
CesiumMath,
VertexFormat,
createPackableSpecs) {
@@ -139,6 +143,73 @@ defineSuite([
expect(m.indices.length).toEqual(numTriangles * 3);
});
+ it('computes offset attribute', function() {
+ var m = EllipseGeometry.createGeometry(new EllipseGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ ellipsoid : Ellipsoid.WGS84,
+ center : Cartesian3.fromDegrees(0,0),
+ granularity : 0.1,
+ semiMajorAxis : 1.0,
+ semiMinorAxis : 1.0,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 16;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for top vertices', function() {
+ var m = EllipseGeometry.createGeometry(new EllipseGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ ellipsoid : Ellipsoid.WGS84,
+ center : Cartesian3.fromDegrees(0,0),
+ granularity : 0.1,
+ semiMajorAxis : 1.0,
+ semiMinorAxis : 1.0,
+ extrudedHeight : 50000,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 48;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 16);
+ expected = arrayFill(expected, 1, 32, 40);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for all vertices', function() {
+ var m = EllipseGeometry.createGeometry(new EllipseGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ ellipsoid : Ellipsoid.WGS84,
+ center : Cartesian3.fromDegrees(0,0),
+ granularity : 0.1,
+ semiMajorAxis : 1.0,
+ semiMinorAxis : 1.0,
+ extrudedHeight : 50000,
+ offsetAttribute: GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 48;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
it('compute all vertex attributes extruded', function() {
var m = EllipseGeometry.createGeometry(new EllipseGeometry({
vertexFormat : VertexFormat.ALL,
@@ -311,7 +382,7 @@ defineSuite([
semiMinorAxis : 1.0,
stRotation : CesiumMath.PI_OVER_TWO
});
- var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, CesiumMath.PI_OVER_TWO, 0.0, 0.1, 0.0, 0.0];
+ var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, CesiumMath.PI_OVER_TWO, 0.0, 0.1, 0.0, 0.0, -1];
createPackableSpecs(EllipseGeometry, packableInstance, packedInstance);
});
diff --git a/Specs/Core/EllipseOutlineGeometrySpec.js b/Specs/Core/EllipseOutlineGeometrySpec.js
index 69d38898e1e2..763b9b8dd124 100644
--- a/Specs/Core/EllipseOutlineGeometrySpec.js
+++ b/Specs/Core/EllipseOutlineGeometrySpec.js
@@ -1,12 +1,16 @@
defineSuite([
'Core/EllipseOutlineGeometry',
+ 'Core/arrayFill',
'Core/Cartesian3',
'Core/Ellipsoid',
+ 'Core/GeometryOffsetAttribute',
'Specs/createPackableSpecs'
], function(
EllipseOutlineGeometry,
+ arrayFill,
Cartesian3,
Ellipsoid,
+ GeometryOffsetAttribute,
createPackableSpecs) {
'use strict';
@@ -86,6 +90,69 @@ defineSuite([
expect(m.indices.length).toEqual(24 * 2); // 8 top + 8 bottom + 8 sides
});
+ it('computes offset attribute', function() {
+ var m = EllipseOutlineGeometry.createGeometry(new EllipseOutlineGeometry({
+ ellipsoid : Ellipsoid.WGS84,
+ center : Cartesian3.fromDegrees(0,0),
+ granularity : 0.1,
+ semiMajorAxis : 1.0,
+ semiMinorAxis : 1.0,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 8;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for top vertices', function() {
+ var m = EllipseOutlineGeometry.createGeometry(new EllipseOutlineGeometry({
+ ellipsoid : Ellipsoid.WGS84,
+ center : Cartesian3.fromDegrees(0,0),
+ granularity : 0.1,
+ semiMajorAxis : 1.0,
+ semiMinorAxis : 1.0,
+ extrudedHeight : 5.0,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 16;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 8);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for all vertices', function() {
+ var m = EllipseOutlineGeometry.createGeometry(new EllipseOutlineGeometry({
+ ellipsoid : Ellipsoid.WGS84,
+ center : Cartesian3.fromDegrees(0,0),
+ granularity : 0.1,
+ semiMajorAxis : 1.0,
+ semiMinorAxis : 1.0,
+ extrudedHeight : 5.0,
+ offsetAttribute: GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 16;
+ expect(m.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
it('computes positions extruded, no lines drawn between top and bottom', function() {
var m = EllipseOutlineGeometry.createGeometry(new EllipseOutlineGeometry({
ellipsoid : Ellipsoid.WGS84,
@@ -147,7 +214,7 @@ defineSuite([
rotation : 6,
extrudedHeight : 7
});
- var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 3, 2, 6, 7, 1, 5, 4];
+ var packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 3, 2, 6, 7, 1, 5, 4, -1];
createPackableSpecs(EllipseOutlineGeometry, packableInstance, packedInstance, 'extruded');
//Because extrudedHeight is optional and has to be taken into account when packing, we have a second test without it.
@@ -161,6 +228,6 @@ defineSuite([
height : 5,
rotation : 6
});
- packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 3, 2, 6, 5, 1, 5, 4];
+ packedInstance = [center.x, center.y, center.z, ellipsoid.radii.x, ellipsoid.radii.y, ellipsoid.radii.z, 3, 2, 6, 5, 1, 5, 4, -1];
createPackableSpecs(EllipseOutlineGeometry, packableInstance, packedInstance, 'at height');
});
diff --git a/Specs/Core/PolygonGeometrySpec.js b/Specs/Core/PolygonGeometrySpec.js
index 90d519197bb6..20b8f0e8e0b7 100644
--- a/Specs/Core/PolygonGeometrySpec.js
+++ b/Specs/Core/PolygonGeometrySpec.js
@@ -1,8 +1,10 @@
defineSuite([
'Core/PolygonGeometry',
+ 'Core/arrayFill',
'Core/BoundingSphere',
'Core/Cartesian3',
'Core/Ellipsoid',
+ 'Core/GeometryOffsetAttribute',
'Core/GeometryPipeline',
'Core/Math',
'Core/Rectangle',
@@ -10,9 +12,11 @@ defineSuite([
'Specs/createPackableSpecs'
], function(
PolygonGeometry,
+ arrayFill,
BoundingSphere,
Cartesian3,
Ellipsoid,
+ GeometryOffsetAttribute,
GeometryPipeline,
CesiumMath,
Rectangle,
@@ -448,6 +452,226 @@ defineSuite([
expect(p.indices.length).toEqual(numTriangles * 3);
});
+ it('computes offset attribute', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ granularity: CesiumMath.RADIANS_PER_DEGREE,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 13;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for top vertices', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 50;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 13);
+ expected = arrayFill(expected, 1, 26, 38);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded and not closeTop for top vertices', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ closeTop: false,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 37; // 13 bottom + 8 top edge + 8 bottom edge + 4 top corner + 4 bottom corner
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 13, 25);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded and not closeBottom for top vertcies', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ closeBottom: false,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 37;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 25);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded and not closeBottom or closeTop for top vertices', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ closeTop: false,
+ closeBottom: false,
+ offsetAttribute: GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 24;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 12);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for all vertices', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ offsetAttribute: GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 50;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded and not closeTop for all vertices', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ closeTop: false,
+ offsetAttribute: GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 37; // 13 bottom + 8 top edge + 8 bottom edge + 4 top corner + 4 bottom corner
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded and not closeBottom for all vertcies', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ closeBottom: false,
+ offsetAttribute: GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 37;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded and not closeBottom or closeTop for all vertices', function() {
+ var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ closeTop: false,
+ closeBottom: false,
+ offsetAttribute: GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 24;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
it('removes duplicates extruded', function() {
var p = PolygonGeometry.createGeometry(PolygonGeometry.fromPositions({
vertexFormat : VertexFormat.POSITION_ONLY,
@@ -743,6 +967,6 @@ defineSuite([
addPositions(packedInstance, holePositions1);
packedInstance.push(Ellipsoid.WGS84.radii.x, Ellipsoid.WGS84.radii.y, Ellipsoid.WGS84.radii.z);
packedInstance.push(1.0, 0.0, 0.0, 0.0, 0.0, 0.0);
- packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 0.0, 1.0, 0, 1, 0, 52);
+ packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 0.0, 1.0, 0, 1, 0, -1, 53);
createPackableSpecs(PolygonGeometry, polygon, packedInstance);
});
diff --git a/Specs/Core/PolygonOutlineGeometrySpec.js b/Specs/Core/PolygonOutlineGeometrySpec.js
index 348d16438730..907a21fb31bb 100644
--- a/Specs/Core/PolygonOutlineGeometrySpec.js
+++ b/Specs/Core/PolygonOutlineGeometrySpec.js
@@ -1,15 +1,19 @@
defineSuite([
'Core/PolygonOutlineGeometry',
+ 'Core/arrayFill',
'Core/BoundingSphere',
'Core/Cartesian3',
'Core/Ellipsoid',
+ 'Core/GeometryOffsetAttribute',
'Core/Math',
'Specs/createPackableSpecs'
], function(
PolygonOutlineGeometry,
+ arrayFill,
BoundingSphere,
Cartesian3,
Ellipsoid,
+ GeometryOffsetAttribute,
CesiumMath,
createPackableSpecs) {
'use strict';
@@ -360,6 +364,71 @@ defineSuite([
expect(p.indices.length).toEqual(36 * 2); // 12 top + 12 bottom + 12 edges
});
+ it('computes offset attribute', function() {
+ var p = PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ offsetAttribute : GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 8;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for top vertices', function() {
+ var p = PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ offsetAttribute : GeometryOffsetAttribute.TOP
+ }));
+
+ var numVertices = 16;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 8);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for all vertices', function() {
+ var p = PolygonOutlineGeometry.createGeometry(PolygonOutlineGeometry.fromPositions({
+ positions : Cartesian3.fromDegreesArray([
+ -1.0, -1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ -1.0, 1.0
+ ]),
+ extrudedHeight: 30000,
+ offsetAttribute : GeometryOffsetAttribute.ALL
+ }));
+
+ var numVertices = 16;
+ expect(p.attributes.position.values.length).toEqual(numVertices * 3);
+
+ var offset = p.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
it('undefined is returned if there are less than 3 positions', function() {
var polygonOutline = PolygonOutlineGeometry.fromPositions({
positions : Cartesian3.fromDegreesArray([
@@ -415,7 +484,6 @@ defineSuite([
packedInstance.push(3.0, 0.0);
addPositions(packedInstance, holePositions1);
packedInstance.push(Ellipsoid.WGS84.radii.x, Ellipsoid.WGS84.radii.y, Ellipsoid.WGS84.radii.z);
- packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 1.0, 42);
+ packedInstance.push(0.0, 0.0, CesiumMath.PI_OVER_THREE, 0.0, 1.0, -1, 43);
createPackableSpecs(PolygonOutlineGeometry, polygon, packedInstance);
-
});
diff --git a/Specs/Core/RectangleGeometrySpec.js b/Specs/Core/RectangleGeometrySpec.js
index 4a6b2a65df44..7e2323c21e91 100644
--- a/Specs/Core/RectangleGeometrySpec.js
+++ b/Specs/Core/RectangleGeometrySpec.js
@@ -1,9 +1,11 @@
defineSuite([
'Core/RectangleGeometry',
+ 'Core/arrayFill',
'Core/Cartesian2',
'Core/Cartesian3',
'Core/Ellipsoid',
'Core/GeographicProjection',
+ 'Core/GeometryOffsetAttribute',
'Core/Math',
'Core/Matrix2',
'Core/Rectangle',
@@ -11,10 +13,12 @@ defineSuite([
'Specs/createPackableSpecs'
], function(
RectangleGeometry,
+ arrayFill,
Cartesian2,
Cartesian3,
Ellipsoid,
GeographicProjection,
+ GeometryOffsetAttribute,
CesiumMath,
Matrix2,
Rectangle,
@@ -262,6 +266,75 @@ defineSuite([
expect(m.indices.length).toEqual(numTriangles * 3);
});
+ it('computes offset attribute', function() {
+ var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
+ var m = RectangleGeometry.createGeometry(new RectangleGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ rectangle : rectangle,
+ granularity : 1.0,
+ offsetAttribute : GeometryOffsetAttribute.TOP
+ }));
+ var positions = m.attributes.position.values;
+
+ var numVertices = 9;
+ expect(positions.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for top vertices', function() {
+ var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
+ var m = RectangleGeometry.createGeometry(new RectangleGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ rectangle : rectangle,
+ granularity : 1.0,
+ extrudedHeight : 2,
+ offsetAttribute : GeometryOffsetAttribute.TOP
+ }));
+ var positions = m.attributes.position.values;
+
+ var numVertices = 42; // (9 fill + 8 edge + 4 corners) * 2 to duplicate for bottom
+ expect(positions.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 9);
+ for (var i = 18; i < offset.length; i+=2) {
+ expected[i] = 1;
+ }
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for all vertices', function() {
+ var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
+ var m = RectangleGeometry.createGeometry(new RectangleGeometry({
+ vertexFormat : VertexFormat.POSITION_ONLY,
+ rectangle : rectangle,
+ granularity : 1.0,
+ extrudedHeight : 2,
+ offsetAttribute : GeometryOffsetAttribute.ALL
+ }));
+ var positions = m.attributes.position.values;
+
+ var numVertices = 42; // (9 fill + 8 edge + 4 corners) * 2 to duplicate for bottom
+ expect(positions.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ for (var i = 18; i < offset.length; i+=2) {
+ expected[i] = 1;
+ }
+ expect(offset).toEqual(expected);
+ });
+
it('undefined is returned if any side are of length zero', function() {
var rectangle0 = new RectangleGeometry({
rectangle : Rectangle.fromDegrees(-80.0, 39.0, -80.0, 42.0)
@@ -384,6 +457,6 @@ defineSuite([
granularity : 1.0,
ellipsoid : Ellipsoid.UNIT_SPHERE
});
- var packedInstance = [-2.0, -1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0];
+ var packedInstance = [-2.0, -1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1];
createPackableSpecs(RectangleGeometry, rectangle, packedInstance);
});
diff --git a/Specs/Core/RectangleOutlineGeometrySpec.js b/Specs/Core/RectangleOutlineGeometrySpec.js
index aaf57809d56a..7ed6583e5520 100644
--- a/Specs/Core/RectangleOutlineGeometrySpec.js
+++ b/Specs/Core/RectangleOutlineGeometrySpec.js
@@ -1,8 +1,10 @@
defineSuite([
'Core/RectangleOutlineGeometry',
+ 'Core/arrayFill',
'Core/Cartesian2',
'Core/Cartesian3',
'Core/Ellipsoid',
+ 'Core/GeometryOffsetAttribute',
'Core/GeographicProjection',
'Core/Math',
'Core/Matrix2',
@@ -10,9 +12,11 @@ defineSuite([
'Specs/createPackableSpecs'
], function(
RectangleOutlineGeometry,
+ arrayFill,
Cartesian2,
Cartesian3,
Ellipsoid,
+ GeometryOffsetAttribute,
GeographicProjection,
CesiumMath,
Matrix2,
@@ -166,6 +170,66 @@ defineSuite([
expect(geometry2).toBeUndefined();
});
+ it('computes offset attribute', function() {
+ var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
+ var m = RectangleOutlineGeometry.createGeometry(new RectangleOutlineGeometry({
+ rectangle : rectangle,
+ granularity : 1.0,
+ offsetAttribute : GeometryOffsetAttribute.TOP
+ }));
+ var positions = m.attributes.position.values;
+
+ var numVertices = 8;
+ expect(positions.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for top vertices', function() {
+ var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
+ var m = RectangleOutlineGeometry.createGeometry(new RectangleOutlineGeometry({
+ rectangle : rectangle,
+ granularity : 1.0,
+ extrudedHeight : 2,
+ offsetAttribute : GeometryOffsetAttribute.TOP
+ }));
+ var positions = m.attributes.position.values;
+
+ var numVertices = 16;
+ expect(positions.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 0);
+ expected = arrayFill(expected, 1, 0, 8);
+ expect(offset).toEqual(expected);
+ });
+
+ it('computes offset attribute extruded for all vertices', function() {
+ var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
+ var m = RectangleOutlineGeometry.createGeometry(new RectangleOutlineGeometry({
+ rectangle : rectangle,
+ granularity : 1.0,
+ extrudedHeight : 2,
+ offsetAttribute : GeometryOffsetAttribute.ALL
+ }));
+ var positions = m.attributes.position.values;
+
+ var numVertices = 16;
+ expect(positions.length).toEqual(numVertices * 3);
+
+ var offset = m.attributes.applyOffset.values;
+ expect(offset.length).toEqual(numVertices);
+ var expected = new Array(offset.length);
+ expected = arrayFill(expected, 1);
+ expect(offset).toEqual(expected);
+ });
+
var rectangle = new RectangleOutlineGeometry({
rectangle : new Rectangle(0.1, 0.2, 0.3, 0.4),
ellipsoid : new Ellipsoid(5, 6, 7),
@@ -174,7 +238,7 @@ defineSuite([
rotation : 10,
extrudedHeight : 11
});
- var packedInstance = [0.1, 0.2, 0.3, 0.4, 5, 6, 7, 8, 11, 10, 9];
+ var packedInstance = [0.1, 0.2, 0.3, 0.4, 5, 6, 7, 8, 11, 10, 9, -1];
createPackableSpecs(RectangleOutlineGeometry, rectangle, packedInstance, 'extruded');
rectangle = new RectangleOutlineGeometry({
@@ -184,7 +248,7 @@ defineSuite([
height : 9,
rotation : 10
});
- packedInstance = [0.1, 0.2, 0.3, 0.4, 5, 6, 7, 8, 9, 10, 9];
+ packedInstance = [0.1, 0.2, 0.3, 0.4, 5, 6, 7, 8, 9, 10, 9, -1];
createPackableSpecs(RectangleOutlineGeometry, rectangle, packedInstance, 'at height');
});