diff --git a/Source/Core/Cartesian2.js b/Source/Core/Cartesian2.js index f5dd314f2ddf..0b4927d01d54 100644 --- a/Source/Core/Cartesian2.js +++ b/Source/Core/Cartesian2.js @@ -414,6 +414,13 @@ define([ result.x = cartesian.x / magnitude; result.y = cartesian.y / magnitude; + + //>>includeStart('debug', pragmas.debug); + if (isNaN(result.x) || isNaN(result.y)) { + throw new DeveloperError('normalized result is not a number'); + } + //>>includeEnd('debug'); + return result; }; diff --git a/Source/Core/Cartesian3.js b/Source/Core/Cartesian3.js index f79730cf540a..a2e1f2f268f7 100644 --- a/Source/Core/Cartesian3.js +++ b/Source/Core/Cartesian3.js @@ -453,6 +453,13 @@ define([ result.x = cartesian.x / magnitude; result.y = cartesian.y / magnitude; result.z = cartesian.z / magnitude; + + //>>includeStart('debug', pragmas.debug); + if (isNaN(result.x) || isNaN(result.y) || isNaN(result.z)) { + throw new DeveloperError('normalized result is not a number'); + } + //>>includeEnd('debug'); + return result; }; diff --git a/Source/Core/Cartesian4.js b/Source/Core/Cartesian4.js index fda43f93cbef..f9ca0bddc60d 100644 --- a/Source/Core/Cartesian4.js +++ b/Source/Core/Cartesian4.js @@ -455,6 +455,13 @@ define([ result.y = cartesian.y / magnitude; result.z = cartesian.z / magnitude; result.w = cartesian.w / magnitude; + + //>>includeStart('debug', pragmas.debug); + if (isNaN(result.x) || isNaN(result.y) || isNaN(result.z) || isNaN(result.w)) { + throw new DeveloperError('normalized result is not a number'); + } + //>>includeEnd('debug'); + return result; }; diff --git a/Source/Core/CorridorGeometry.js b/Source/Core/CorridorGeometry.js index 08682a31f142..29aeb0c86b91 100644 --- a/Source/Core/CorridorGeometry.js +++ b/Source/Core/CorridorGeometry.js @@ -678,8 +678,9 @@ define([ var scratchCartographicMax = new Cartographic(); function computeRectangle(positions, ellipsoid, width, cornerType) { - var length = positions.length - 1; - if (length === 0) { + var cleanPositions = arrayRemoveDuplicates(positions, Cartesian3.equalsEpsilon); + var length = cleanPositions.length - 1; + if (length === 0 || width === 0) { return new Rectangle(); } var halfWidth = width * 0.5; @@ -692,8 +693,8 @@ define([ var lat, lon; if (cornerType === CornerType.ROUNDED) { // Compute start cap - var first = positions[0]; - Cartesian3.subtract(first, positions[1], scratchCartesianOffset); + var first = cleanPositions[0]; + Cartesian3.subtract(first, cleanPositions[1], scratchCartesianOffset); Cartesian3.normalize(scratchCartesianOffset, scratchCartesianOffset); Cartesian3.multiplyByScalar(scratchCartesianOffset, halfWidth, scratchCartesianOffset); Cartesian3.add(first, scratchCartesianOffset, scratchCartesianEnds); @@ -709,13 +710,13 @@ define([ // Compute the rest for (var i = 0; i < length; ++i) { - computeOffsetPoints(positions[i], positions[i+1], ellipsoid, halfWidth, + computeOffsetPoints(cleanPositions[i], cleanPositions[i+1], ellipsoid, halfWidth, scratchCartographicMin, scratchCartographicMax); } // Compute ending point - var last = positions[length]; - Cartesian3.subtract(last, positions[length-1], scratchCartesianOffset); + var last = cleanPositions[length]; + Cartesian3.subtract(last, cleanPositions[length-1], scratchCartesianOffset); Cartesian3.normalize(scratchCartesianOffset, scratchCartesianOffset); Cartesian3.multiplyByScalar(scratchCartesianOffset, halfWidth, scratchCartesianOffset); Cartesian3.add(last, scratchCartesianOffset, scratchCartesianEnds); diff --git a/Source/Core/EllipsoidalOccluder.js b/Source/Core/EllipsoidalOccluder.js index ae0d355c4fe1..31c776faa4ee 100644 --- a/Source/Core/EllipsoidalOccluder.js +++ b/Source/Core/EllipsoidalOccluder.js @@ -305,6 +305,10 @@ define([ var directionToPointScratch = new Cartesian3(); function computeScaledSpaceDirectionToPoint(ellipsoid, directionToPoint) { + if (Cartesian3.equals(directionToPoint, Cartesian3.ZERO)) { + return directionToPoint; + } + ellipsoid.transformPositionToScaledSpace(directionToPoint, directionToPointScratch); return Cartesian3.normalize(directionToPointScratch, directionToPointScratch); } diff --git a/Source/Core/IntersectionTests.js b/Source/Core/IntersectionTests.js index 9fde976ee8df..3657b9b48ee5 100644 --- a/Source/Core/IntersectionTests.js +++ b/Source/Core/IntersectionTests.js @@ -219,6 +219,15 @@ define([ if (!defined(v1)) { throw new DeveloperError('v1 is required.'); } + if (!defined(p0)) { + throw new DeveloperError('p0 is required.'); + } + if (!defined(p1)) { + throw new DeveloperError('p1 is required.'); + } + if (!defined(p2)) { + throw new DeveloperError('p2 is required.'); + } //>>includeEnd('debug'); var ray = scratchLineSegmentTriangleRay; @@ -605,9 +614,11 @@ define([ var position = ray.origin; var direction = ray.direction; - var normal = ellipsoid.geodeticSurfaceNormal(position, firstAxisScratch); - if (Cartesian3.dot(direction, normal) >= 0.0) { // The location provided is the closest point in altitude - return position; + if (!Cartesian3.equals(position, Cartesian3.ZERO)) { + var normal = ellipsoid.geodeticSurfaceNormal(position, firstAxisScratch); + if (Cartesian3.dot(direction, normal) >= 0.0) { // The location provided is the closest point in altitude + return position; + } } var intersects = defined(this.rayEllipsoid(ray, ellipsoid)); diff --git a/Source/Core/PolylineVolumeGeometry.js b/Source/Core/PolylineVolumeGeometry.js index 35bdc4099c1b..4cf9b5cf04f9 100644 --- a/Source/Core/PolylineVolumeGeometry.js +++ b/Source/Core/PolylineVolumeGeometry.js @@ -9,6 +9,7 @@ define([ './CornerType', './defaultValue', './defined', + './oneTimeWarning', './DeveloperError', './Ellipsoid', './Geometry', @@ -32,6 +33,7 @@ define([ CornerType, defaultValue, defined, + oneTimeWarning, DeveloperError, Ellipsoid, Geometry, @@ -163,7 +165,13 @@ define([ } if (vertexFormat.tangent || vertexFormat.binormal) { - geometry = GeometryPipeline.computeBinormalAndTangent(geometry); + try { + geometry = GeometryPipeline.computeBinormalAndTangent(geometry); + } catch (e) { + oneTimeWarning('polyline-volume-tangent-binormal', 'Unable to compute tangents and binormals for polyline volume geometry'); + //TODO https://github.com/AnalyticalGraphicsInc/cesium/issues/3609 + } + if (!vertexFormat.tangent) { geometry.attributes.tangent = undefined; } diff --git a/Source/Scene/Camera.js b/Source/Scene/Camera.js index 11f34b25e406..97e4dbff4634 100644 --- a/Source/Scene/Camera.js +++ b/Source/Scene/Camera.js @@ -2846,8 +2846,15 @@ define([ var qUnit = Cartesian3.normalize(q, scratchCartesian3_2); // Determine the east and north directions at q. - var eUnit = Cartesian3.normalize(Cartesian3.cross(Cartesian3.UNIT_Z, q, scratchCartesian3_3), scratchCartesian3_3); - var nUnit = Cartesian3.normalize(Cartesian3.cross(qUnit, eUnit, scratchCartesian3_4), scratchCartesian3_4); + var eUnit; + var nUnit; + if (Cartesian3.equalsEpsilon(qUnit, Cartesian3.UNIT_Z, CesiumMath.EPSILON10)) { + eUnit = new Cartesian3(0, 1, 0); + nUnit = new Cartesian3(0, 0, 1); + } else { + eUnit = Cartesian3.normalize(Cartesian3.cross(Cartesian3.UNIT_Z, qUnit, scratchCartesian3_3), scratchCartesian3_3); + nUnit = Cartesian3.normalize(Cartesian3.cross(qUnit, eUnit, scratchCartesian3_4), scratchCartesian3_4); + } // Determine the radius of the 'limb' of the ellipsoid. var wMagnitude = Math.sqrt(Cartesian3.magnitudeSquared(q) - 1.0); diff --git a/Specs/Core/Cartesian2Spec.js b/Specs/Core/Cartesian2Spec.js index ec37a85d19a0..4087a64e6959 100644 --- a/Specs/Core/Cartesian2Spec.js +++ b/Specs/Core/Cartesian2Spec.js @@ -303,6 +303,12 @@ defineSuite([ expect(cartesian).toEqual(expectedResult); }); + it('normalize throws with zero vector', function() { + expect(function() { + Cartesian2.normalize(Cartesian2.ZERO, new Cartesian2()); + }).toThrowDeveloperError(); + }); + it('multiplyComponents works with a result parameter', function() { var left = new Cartesian2(2.0, 3.0); var right = new Cartesian2(4.0, 5.0); diff --git a/Specs/Core/Cartesian3Spec.js b/Specs/Core/Cartesian3Spec.js index 66385ca41198..188e6ee724a2 100644 --- a/Specs/Core/Cartesian3Spec.js +++ b/Specs/Core/Cartesian3Spec.js @@ -375,6 +375,12 @@ defineSuite([ expect(cartesian).toEqual(expectedResult); }); + it('normalize throws with zero vector', function() { + expect(function() { + Cartesian3.normalize(Cartesian3.ZERO, new Cartesian3()); + }).toThrowDeveloperError(); + }); + it('multiplyComponents works with a result parameter', function() { var left = new Cartesian3(2.0, 3.0, 6.0); var right = new Cartesian3(4.0, 5.0, 7.0); diff --git a/Specs/Core/Cartesian4Spec.js b/Specs/Core/Cartesian4Spec.js index da056752bca9..4e9cbb91737b 100644 --- a/Specs/Core/Cartesian4Spec.js +++ b/Specs/Core/Cartesian4Spec.js @@ -439,6 +439,12 @@ defineSuite([ expect(cartesian).toEqual(expectedResult); }); + it('normalize throws with zero vector', function() { + expect(function() { + Cartesian4.normalize(Cartesian4.ZERO, new Cartesian4()); + }).toThrowDeveloperError(); + }); + it('multiplyComponents works with a result parameter', function() { var left = new Cartesian4(2.0, 3.0, 6.0, 8.0); var right = new Cartesian4(4.0, 5.0, 7.0, 9.0); diff --git a/Specs/Core/IntersectionTestsSpec.js b/Specs/Core/IntersectionTestsSpec.js index c090321d670b..787cf5aff3b2 100644 --- a/Specs/Core/IntersectionTestsSpec.js +++ b/Specs/Core/IntersectionTestsSpec.js @@ -174,6 +174,7 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('lineSegmentTriangle throws without v1', function() { expect(function() { IntersectionTests.lineSegmentTriangle(new Cartesian3()); diff --git a/Specs/Core/OrientedBoundingBoxSpec.js b/Specs/Core/OrientedBoundingBoxSpec.js index ae73533c6ab0..9845c0dc700e 100644 --- a/Specs/Core/OrientedBoundingBoxSpec.js +++ b/Specs/Core/OrientedBoundingBoxSpec.js @@ -338,6 +338,9 @@ defineSuite([ Matrix3.multiplyByVector(axes, tang, tang); Matrix3.multiplyByVector(axes, binorm, binorm); Cartesian3.cross(tang, binorm, n); + if (Cartesian3.magnitude(n) === 0) { + return undefined; + } Cartesian3.normalize(n, n); Cartesian3.add(p0, center, p0); diff --git a/Specs/Core/PolylineVolumeGeometrySpec.js b/Specs/Core/PolylineVolumeGeometrySpec.js index 54e124dba34b..6dd11a5b8645 100644 --- a/Specs/Core/PolylineVolumeGeometrySpec.js +++ b/Specs/Core/PolylineVolumeGeometrySpec.js @@ -84,7 +84,27 @@ defineSuite([ expect(m.indices.length).toEqual(44 * 3); }); - it('compute all vertex attributes', function() { + it('computes most vertex attributes', function() { + var m = PolylineVolumeGeometry.createGeometry(new PolylineVolumeGeometry({ + vertexFormat : VertexFormat.POSITION_NORMAL_AND_ST, + polylinePositions : Cartesian3.fromDegreesArray([ + 90.0, -30.0, + 90.0, -35.0 + ]), + cornerType: CornerType.MITERED, + shapePositions: shape + })); + + var numVertices = 56; + var numTriangles = 44; + expect(m.attributes.position.values.length).toEqual(numVertices * 3); + expect(m.attributes.st.values.length).toEqual(numVertices * 2); + expect(m.attributes.normal.values.length).toEqual(numVertices * 3); + expect(m.indices.length).toEqual(numTriangles * 3); + }); + + //https://github.com/AnalyticalGraphicsInc/cesium/issues/3609 + xit('compute all vertex attributes', function() { var m = PolylineVolumeGeometry.createGeometry(new PolylineVolumeGeometry({ vertexFormat : VertexFormat.ALL, polylinePositions : Cartesian3.fromDegreesArray([ diff --git a/Specs/DataSources/KmlDataSourceSpec.js b/Specs/DataSources/KmlDataSourceSpec.js index 3d14f8d07774..ba88a616ec05 100644 --- a/Specs/DataSources/KmlDataSourceSpec.js +++ b/Specs/DataSources/KmlDataSourceSpec.js @@ -4002,7 +4002,9 @@ defineSuite([ \ '; - var camera = createCamera(); + var camera = createCamera({ + offset: Cartesian3.fromDegrees(-110, 30, 1000) + }); Camera.clone(options.camera, camera); var kmlOptions = { diff --git a/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js b/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js index 9752be442f2e..27618dda0ddf 100644 --- a/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js @@ -69,7 +69,7 @@ defineSuite([ function createBasicPolylineVolume() { var polylineVolume = new PolylineVolumeGraphics(); - polylineVolume.positions = new ConstantProperty(Cartesian3.fromRadiansArray([ + polylineVolume.positions = new ConstantProperty(Cartesian3.fromDegreesArray([ 0, 0, 1, 0, 1, 1, diff --git a/Specs/Scene/SceneTransformsSpec.js b/Specs/Scene/SceneTransformsSpec.js index 31da8ab3b415..de674888cb81 100644 --- a/Specs/Scene/SceneTransformsSpec.js +++ b/Specs/Scene/SceneTransformsSpec.js @@ -1,6 +1,7 @@ /*global defineSuite*/ defineSuite([ 'Scene/SceneTransforms', + 'Scene/SceneMode', 'Core/Cartesian2', 'Core/Cartesian3', 'Core/Ellipsoid', @@ -10,6 +11,7 @@ defineSuite([ 'Specs/createScene' ], function( SceneTransforms, + SceneMode, Cartesian2, Cartesian3, Ellipsoid, @@ -32,6 +34,7 @@ defineSuite([ }); beforeEach(function() { + scene.mode = SceneMode.SCENE3D; scene.camera.position = defaultCamera.position.clone(); scene.camera.direction = defaultCamera.direction.clone(); scene.camera.up = defaultCamera.up.clone(); @@ -179,6 +182,10 @@ defineSuite([ }); it('returns correct drawing buffer position in 2D', function() { + scene.camera.setView({ + destination : Rectangle.fromDegrees(-0.000001, -0.000001, 0.000001, 0.000001) + }); + // Update scene state scene.morphTo2D(0); scene.renderForSpecs();