diff --git a/CHANGES.md b/CHANGES.md
index c3891b1f8bcc..3703add5564f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -21,7 +21,7 @@ Beta Releases
* Removed `Polygon.bufferUsage`. It is no longer needed.
* Removed `height` and `textureRotationAngle` arguments from `Polygon` `setPositions` and `configureFromPolygonHierarchy` functions. Use `Polygon` `height` and `textureRotationAngle` properties.
* Renamed `PolygonPipeline.cleanUp` to `PolygonPipeline.removeDuplicates`.
- * Removed `PolygonPipeline.wrapLongitude`. It is no longer needed.
+ * Removed `PolygonPipeline.wrapLongitude`. Use `GeometryPipeline.wrapLongitude` instead.
* Added `height` parameter to `BoundingSphere.fromExtent3D`.
* Added `height` parameter to `Extent.subsample`.
* Added `ExtentPrimitive`.
@@ -42,11 +42,11 @@ Beta Releases
* Added `GeometryPipeline.combine` to combine meshes for better batching.
* Added `GeometryPipeline.computeNormal` to compute normals for a geometry.
* Added `GeometryPipeline.computeBinormalAndTangent` to compute binormals and tangent vectors for a geometry.
-* Added the following functions to `GeometryPipeline` to index non-indexed primitive types: `indexLines`, `indexLineLoop`, `indexLineStrip`, `indexTriangles`, `indexTriangleFan`, and `indexTriangleStrip`.
* Added `GeometryPipeline.wrapLongitude` to split geometry across the International Date Line.
* Added `PolylinePipeline.removeDuplicates`.
* Added `barycentricCoordinates` to compute the barycentric coordinates of a point with respect to three vertices of a triangle.
* Added `BoundingSphere.fromEllipsoid`.
+* Added `BoundingSphere.projectTo2D`.
* Added `Extent.fromDegrees`.
* Added `czm_tangentToEyeSpaceMatrix` built-in GLSL function.
* Improved the performance of drawing polygons created with `configureFromPolygonHierarchy`.
diff --git a/Source/Core/BoundingSphere.js b/Source/Core/BoundingSphere.js
index fd29f9655756..8215e08c2d41 100644
--- a/Source/Core/BoundingSphere.js
+++ b/Source/Core/BoundingSphere.js
@@ -761,6 +761,117 @@ define([
return result;
};
+ var projectTo2DNormal = new Cartesian3();
+ var projectTo2DEast = new Cartesian3();
+ var projectTo2DNorth = new Cartesian3();
+ var projectTo2DWest = new Cartesian3();
+ var projectTo2DSouth = new Cartesian3();
+ var projectTo2DCartographic = new Cartographic();
+ var projectTo2DPositions = new Array(8);
+ for (var n = 0; n < 8; ++n) {
+ projectTo2DPositions[n] = new Cartesian3();
+ }
+ /**
+ * Creates a bounding sphere in 2D from a bounding sphere in 3D world coordinates.
+ * @memberof BoundingSphere
+ *
+ * @param {BoundingSphere} sphere The bounding sphere to transform to 2D.
+ * @param {Object} [projection=GeographicProjection] The projection to 2D.
+ * @param {BoundingSphere} [result] The object onto which to store the result.
+ * @return {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
+ *
+ * @exception {DeveloperError} sphere is required.
+ */
+ BoundingSphere.projectTo2D = function(sphere, projection, result) {
+ if (typeof sphere === 'undefined') {
+ throw new DeveloperError('sphere is required.');
+ }
+
+ projection = (typeof projection !== 'undefined') ? projection : new GeographicProjection();
+
+ var ellipsoid = projection.getEllipsoid();
+ var center = sphere.center;
+ var radius = sphere.radius;
+
+ var normal = ellipsoid.geodeticSurfaceNormal(center, projectTo2DNormal);
+ var east = Cartesian3.cross(Cartesian3.UNIT_Z, normal, projectTo2DEast);
+ Cartesian3.normalize(east, east);
+ var north = Cartesian3.cross(normal, east, projectTo2DNorth);
+ Cartesian3.normalize(north, north);
+
+ Cartesian3.multiplyByScalar(normal, radius, normal);
+ Cartesian3.multiplyByScalar(north, radius, north);
+ Cartesian3.multiplyByScalar(east, radius, east);
+
+ var south = Cartesian3.negate(north, projectTo2DSouth);
+ var west = Cartesian3.negate(east, projectTo2DWest);
+
+ var positions = projectTo2DPositions;
+
+ // top NE corner
+ var corner = positions[0];
+ Cartesian3.add(normal, north, corner);
+ Cartesian3.add(corner, east, corner);
+
+ // top NW corner
+ corner = positions[1];
+ Cartesian3.add(normal, north, corner);
+ Cartesian3.add(corner, west, corner);
+
+ // top SW corner
+ corner = positions[2];
+ Cartesian3.add(normal, south, corner);
+ Cartesian3.add(corner, west, corner);
+
+ // top SE corner
+ corner = positions[3];
+ Cartesian3.add(normal, south, corner);
+ Cartesian3.add(corner, east, corner);
+
+ Cartesian3.negate(normal, normal);
+
+ // bottom NE corner
+ corner = positions[4];
+ Cartesian3.add(normal, north, corner);
+ Cartesian3.add(corner, east, corner);
+
+ // bottom NW corner
+ corner = positions[5];
+ Cartesian3.add(normal, north, corner);
+ Cartesian3.add(corner, west, corner);
+
+ // bottom SW corner
+ corner = positions[6];
+ Cartesian3.add(normal, south, corner);
+ Cartesian3.add(corner, west, corner);
+
+ // bottom SE corner
+ corner = positions[7];
+ Cartesian3.add(normal, south, corner);
+ Cartesian3.add(corner, east, corner);
+
+ var length = positions.length;
+ for (var i = 0; i < length; ++i) {
+ var position = positions[i];
+ Cartesian3.add(center, position, position);
+ var cartographic = ellipsoid.cartesianToCartographic(position, projectTo2DCartographic);
+ projection.project(cartographic, position);
+ }
+
+ result = BoundingSphere.fromPoints(positions, result);
+
+ // swizzle center components
+ center = result.center;
+ var x = center.x;
+ var y = center.y;
+ var z = center.z;
+ center.x = z;
+ center.y = x;
+ center.z = y;
+
+ return result;
+ };
+
/**
* Compares the provided BoundingSphere componentwise and returns
* true
if they are equal, false
otherwise.
@@ -868,6 +979,18 @@ define([
return BoundingSphere.getPlaneDistances(this, position, direction, result);
};
+ /**
+ * Creates a bounding sphere in 2D from this bounding sphere. This bounding sphere must be in 3D world coordinates.
+ * @memberof BoundingSphere
+ *
+ * @param {Object} [projection=GeographicProjection] The projection to 2D.
+ * @param {BoundingSphere} [result] The object onto which to store the result.
+ * @return {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
+ */
+ BoundingSphere.prototype.projectTo2D = function(projection, result) {
+ return BoundingSphere.projectTo2D(this, projection, result);
+ };
+
/**
* Compares this BoundingSphere against the provided BoundingSphere componentwise and returns
* true
if they are equal, false
otherwise.
diff --git a/Source/Core/GeometryPipeline.js b/Source/Core/GeometryPipeline.js
index 99b31c9f9885..96b86150976e 100644
--- a/Source/Core/GeometryPipeline.js
+++ b/Source/Core/GeometryPipeline.js
@@ -1187,10 +1187,7 @@ define([
return geometry;
};
- /**
- * DOC_TBA
- */
- GeometryPipeline.indexTriangles = function(geometry) {
+ function indexTriangles(geometry) {
if (typeof geometry === 'undefined') {
throw new DeveloperError('geometry is required.');
}
@@ -1199,10 +1196,6 @@ define([
return geometry;
}
- if (geometry.primitiveType !== PrimitiveType.TRIANGLES) {
- throw new DeveloperError('geometry.primitiveType must be PrimitiveType.TRIANGLES.');
- }
-
var numberOfVertices = Geometry.computeNumberOfVertices(geometry);
if (numberOfVertices < 3) {
throw new DeveloperError('The number of vertices must be at least three.');
@@ -1219,20 +1212,13 @@ define([
geometry.indices = indices;
return geometry;
- };
+ }
- /**
- * DOC_TBA
- */
- GeometryPipeline.indexTriangleFan = function(geometry) {
+ function indexTriangleFan(geometry) {
if (typeof geometry === 'undefined') {
throw new DeveloperError('geometry is required.');
}
- if (geometry.primitiveType !== PrimitiveType.TRIANGLE_FAN) {
- throw new DeveloperError('geometry.primitiveType must be PrimitiveType.TRIANGLE_FAN.');
- }
-
var numberOfVertices = Geometry.computeNumberOfVertices(geometry);
if (numberOfVertices < 3) {
throw new DeveloperError('The number of vertices must be at least three.');
@@ -1253,20 +1239,13 @@ define([
geometry.indices = indices;
geometry.primitiveType = PrimitiveType.TRIANGLES;
return geometry;
- };
+ }
- /**
- * DOC_TBA
- */
- GeometryPipeline.indexTriangleStrip = function(geometry) {
+ function indexTriangleStrip(geometry) {
if (typeof geometry === 'undefined') {
throw new DeveloperError('geometry is required.');
}
- if (geometry.primitiveType !== PrimitiveType.TRIANGLE_STRIP) {
- throw new DeveloperError('geometry.primitiveType must be PrimitiveType.TRIANGLE_STRIP.');
- }
-
var numberOfVertices = Geometry.computeNumberOfVertices(geometry);
if (numberOfVertices < 3) {
throw new DeveloperError('The number of vertices must be at least 3.');
@@ -1299,12 +1278,9 @@ define([
geometry.indices = indices;
geometry.primitiveType = PrimitiveType.TRIANGLES;
return geometry;
- };
+ }
- /**
- * DOC_TBA
- */
- GeometryPipeline.indexLines = function(geometry) {
+ function indexLines(geometry) {
if (typeof geometry === 'undefined') {
throw new DeveloperError('undefined');
}
@@ -1313,10 +1289,6 @@ define([
return geometry;
}
- if (geometry.primitiveType !== PrimitiveType.LINES) {
- throw new DeveloperError('geometry.primitiveType must be PrimitiveType.LINES.');
- }
-
var numberOfVertices = Geometry.computeNumberOfVertices(geometry);
if (numberOfVertices < 2) {
throw new DeveloperError('The number of vertices must be at least two.');
@@ -1333,20 +1305,13 @@ define([
geometry.indices = indices;
return geometry;
- };
+ }
- /**
- * DOC_TBA
- */
- GeometryPipeline.indexLineStrip = function(geometry) {
+ function indexLineStrip(geometry) {
if (typeof geometry === 'undefined') {
throw new DeveloperError('geometry is required.');
}
- if (geometry.primitiveType !== PrimitiveType.LINE_STRIP) {
- throw new DeveloperError('geometry.primitiveType must be PrimitiveType.LINE_STRIP.');
- }
-
var numberOfVertices = Geometry.computeNumberOfVertices(geometry);
if (numberOfVertices < 2) {
throw new DeveloperError('The number of vertices must be at least two.');
@@ -1365,20 +1330,13 @@ define([
geometry.indices = indices;
geometry.primitiveType = PrimitiveType.LINES;
return geometry;
- };
+ }
- /**
- * DOC_TBA
- */
- GeometryPipeline.indexLineLoop = function(geometry) {
+ function indexLineLoop(geometry) {
if (typeof geometry === 'undefined') {
throw new DeveloperError('geometry is required.');
}
- if (geometry.primitiveType !== PrimitiveType.LINE_LOOP) {
- throw new DeveloperError('geometry.primitiveType must be PrimitiveType.LINE_LOOP.');
- }
-
var numberOfVertices = Geometry.computeNumberOfVertices(geometry);
if (numberOfVertices < 2) {
throw new DeveloperError('The number of vertices must be at least two.');
@@ -1401,7 +1359,26 @@ define([
geometry.indices = indices;
geometry.primitiveType = PrimitiveType.LINES;
return geometry;
- };
+ }
+
+ function indexPrimitive(geometry) {
+ switch (geometry.primitiveType) {
+ case PrimitiveType.TRIANGLE_FAN:
+ return indexTriangleFan(geometry);
+ case PrimitiveType.TRIANGLE_STRIP:
+ return indexTriangleStrip(geometry);
+ case PrimitiveType.TRIANGLES:
+ return indexTriangles(geometry);
+ case PrimitiveType.LINE_STRIP:
+ return indexLineStrip(geometry);
+ case PrimitiveType.LINE_LOOP:
+ return indexLineLoop(geometry);
+ case PrimitiveType.LINES:
+ return indexLines(geometry);
+ }
+
+ return geometry;
+ }
function offsetPointFromXZPlane(p, isBehind) {
if (Math.abs(p.y) < CesiumMath.EPSILON11){
@@ -1797,28 +1774,10 @@ define([
}
}
- var primitiveType = geometry.primitiveType;
- if (primitiveType === PrimitiveType.TRIANGLE_FAN) {
- GeometryPipeline.indexTriangleFan(primitiveType);
+ indexPrimitive(geometry);
+ if (geometry.primitiveType === PrimitiveType.TRIANGLES) {
wrapLongitudeTriangles(geometry);
- } else if (primitiveType === PrimitiveType.TRIANGLE_STRIP) {
- GeometryPipeline.indexTriangleStrip(geometry);
- wrapLongitudeTriangles(geometry);
- } else if (primitiveType === PrimitiveType.TRIANGLES) {
- if (typeof geometry.indices === 'undefined') {
- GeometryPipeline.indexTriangles(geometry);
- }
- wrapLongitudeTriangles(geometry);
- } else if (primitiveType === PrimitiveType.LINE_STRIP) {
- GeometryPipeline.indexLineStrip(geometry);
- wrapLongitudeLines(geometry);
- } else if (primitiveType === PrimitiveType.LINE_LOOP) {
- GeometryPipeline.indexLineLoop(geometry);
- wrapLongitudeLines(geometry);
- } else if (primitiveType === PrimitiveType.LINES) {
- if (typeof geometry.indices === 'undefined') {
- GeometryPipeline.indexLines(geometry);
- }
+ } else if (geometry.primitiveType === PrimitiveType.LINES) {
wrapLongitudeLines(geometry);
}
diff --git a/Source/Scene/Primitive.js b/Source/Scene/Primitive.js
index 73e162a70053..b440e30fb433 100644
--- a/Source/Scene/Primitive.js
+++ b/Source/Scene/Primitive.js
@@ -306,17 +306,7 @@ define([
// PERFORMANCE_IDEA: Move pipeline to a web-worker.
function geometryPipeline(primitive, instances, context, projection) {
- // Copy instances first since most pipeline operations modify the geometry and instance in-place.
var length = instances.length;
- var insts = new Array(length);
- for (var i = 0; i < length; ++i) {
- insts[i] = instances[i].clone();
- }
-
- // Unify to world coordinates before combining. If there is only one geometry or all
- // geometries are in the same (non-world) coordinate system, only combine if the user requested it.
- transformToWorldCoordinates(primitive, insts);
-
var primitiveType = instances[0].geometry.primitiveType;
for (var j = 1; j < length; ++j) {
if (instances[j].geometry.primitiveType !== primitiveType) {
@@ -324,6 +314,15 @@ define([
}
}
+ // Copy instances first since most pipeline operations modify the geometry and instance in-place.
+ var insts = new Array(length);
+ for (var i = 0; i < length; ++i) {
+ insts[i] = instances[i].clone();
+ }
+
+ // Unify to world coordinates before combining.
+ transformToWorldCoordinates(primitive, insts);
+
// Clip to IDL
if (primitive._allowColumbusView) {
for (var k = 0; k < length; ++k) {
@@ -439,96 +438,6 @@ define([
}
- function updateBoundingSpheres(primitive, boundingSphere, projection) {
- primitive._boundingSphere = boundingSphere;
-
- if (!primitive._allowColumbusView || typeof boundingSphere === 'undefined') {
- return;
- }
-
- var ellipsoid = projection.getEllipsoid();
- var center = boundingSphere.center;
- var radius = boundingSphere.radius;
-
- var normal = ellipsoid.geodeticSurfaceNormal(center);
- var east = Cartesian3.cross(Cartesian3.UNIT_Z, normal);
- Cartesian3.normalize(east, east);
- var north = Cartesian3.cross(normal, east);
- Cartesian3.normalize(north, north);
-
- Cartesian3.multiplyByScalar(normal, radius, normal);
- Cartesian3.multiplyByScalar(north, radius, north);
- Cartesian3.multiplyByScalar(east, radius, east);
-
- var south = Cartesian3.negate(north);
- var west = Cartesian3.negate(east);
-
- var positions = new Array(8);
-
- // top NE corner
- var corner = positions[0] = new Cartesian3();
- Cartesian3.add(normal, north, corner);
- Cartesian3.add(corner, east, corner);
-
- // top NW corner
- corner = positions[1] = new Cartesian3();
- Cartesian3.add(normal, north, corner);
- Cartesian3.add(corner, west, corner);
-
- // top SW corner
- corner = positions[2] = new Cartesian3();
- Cartesian3.add(normal, south, corner);
- Cartesian3.add(corner, west, corner);
-
- // top SE corner
- corner = positions[3] = new Cartesian3();
- Cartesian3.add(normal, south, corner);
- Cartesian3.add(corner, east, corner);
-
- Cartesian3.negate(normal, normal);
-
- // bottom NE corner
- corner = positions[4] = new Cartesian3();
- Cartesian3.add(normal, north, corner);
- Cartesian3.add(corner, east, corner);
-
- // bottom NW corner
- corner = positions[5] = new Cartesian3();
- Cartesian3.add(normal, north, corner);
- Cartesian3.add(corner, west, corner);
-
- // bottom SW corner
- corner = positions[6] = new Cartesian3();
- Cartesian3.add(normal, south, corner);
- Cartesian3.add(corner, west, corner);
-
- // bottom SE corner
- corner = positions[7] = new Cartesian3();
- Cartesian3.add(normal, south, corner);
- Cartesian3.add(corner, east, corner);
-
- var length = positions.length;
- for (var i = 0; i < length; ++i) {
- var position = positions[i];
- Cartesian3.add(center, position, position);
- var cartographic = ellipsoid.cartesianToCartographic(position);
- projection.project(cartographic, position);
- }
-
- boundingSphere = BoundingSphere.fromPoints(positions);
-
- // swizzle center components
- center = boundingSphere.center;
- var x = center.x;
- var y = center.y;
- var z = center.z;
- center.x = z;
- center.y = x;
- center.z = y;
-
- primitive._boundingSphere2D = boundingSphere;
- }
-
/**
* @private
*/
@@ -567,7 +476,11 @@ define([
}
this._attributeIndices = GeometryPipeline.createAttributeIndices(geometries[0]);
- updateBoundingSpheres(this, geometries[0].boundingSphere, projection);
+
+ this._boundingSphere = geometries[0].boundingSphere;
+ if (this._allowColumbusView && typeof this._boundingSphere !== 'undefined') {
+ this._boundingSphere2D = BoundingSphere.projectTo2D(this._boundingSphere, projection);
+ }
var va = [];
for (i = 0; i < length; ++i) {