From b85a3829ba1b891753bbb72c8f7eb69b74953d0f Mon Sep 17 00:00:00 2001 From: Michael Squires Date: Wed, 12 Sep 2018 15:05:30 -0400 Subject: [PATCH 1/2] fix for issue. added appropriate tests to the matrix4 spec --- CHANGES.md | 1 + Source/Core/Matrix4.js | 51 +++++++++++++++++++-------------------- Specs/Core/Matrix4Spec.js | 32 ++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bf2ba5572d65..8fdc0d6a6b9c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ Change Log ##### Fixes :wrench: * Fixed an issue in the 3D Tiles traversal where empty tiles would be selected instead of their nearest loaded ancestors. [#7011](https://github.com/AnalyticalGraphicsInc/cesium/pull/7011) +* Fixed an issue where scaling near zero could cause rendering to stop. [#6954](https://github.com/AnalyticalGraphicsInc/cesium/pull/6954) ### 1.49 - 2018-09-04 diff --git a/Source/Core/Matrix4.js b/Source/Core/Matrix4.js index 5d1fd4809f10..d67c763310bc 100644 --- a/Source/Core/Matrix4.js +++ b/Source/Core/Matrix4.js @@ -2211,31 +2211,6 @@ define([ Check.typeOf.object('matrix', matrix); Check.typeOf.object('result', result); //>>includeEnd('debug'); - - // Special case for a zero scale matrix that can occur, for example, - // when a model's node has a [0, 0, 0] scale. - if (Matrix3.equalsEpsilon(Matrix4.getRotation(matrix, scratchInverseRotation), scratchMatrix3Zero, CesiumMath.EPSILON7) && - Cartesian4.equals(Matrix4.getRow(matrix, 3, scratchBottomRow), scratchExpectedBottomRow)) { - - result[0] = 0.0; - result[1] = 0.0; - result[2] = 0.0; - result[3] = 0.0; - result[4] = 0.0; - result[5] = 0.0; - result[6] = 0.0; - result[7] = 0.0; - result[8] = 0.0; - result[9] = 0.0; - result[10] = 0.0; - result[11] = 0.0; - result[12] = -matrix[12]; - result[13] = -matrix[13]; - result[14] = -matrix[14]; - result[15] = 1.0; - return result; - } - // // Ported from: // ftp://download.intel.com/design/PentiumIII/sml/24504301.pdf @@ -2308,7 +2283,31 @@ define([ // calculate determinant var det = src0 * dst0 + src1 * dst1 + src2 * dst2 + src3 * dst3; - if (Math.abs(det) < CesiumMath.EPSILON20) { + if (Math.abs(det) < 1e-21) { + // Special case for a zero scale matrix that can occur, for example, + // when a model's node has a [0, 0, 0] scale. + if (Matrix3.equalsEpsilon(Matrix4.getRotation(matrix, scratchInverseRotation), scratchMatrix3Zero, CesiumMath.EPSILON7) && + Cartesian4.equals(Matrix4.getRow(matrix, 3, scratchBottomRow), scratchExpectedBottomRow)) { + + result[0] = 0.0; + result[1] = 0.0; + result[2] = 0.0; + result[3] = 0.0; + result[4] = 0.0; + result[5] = 0.0; + result[6] = 0.0; + result[7] = 0.0; + result[8] = 0.0; + result[9] = 0.0; + result[10] = 0.0; + result[11] = 0.0; + result[12] = -matrix[12]; + result[13] = -matrix[13]; + result[14] = -matrix[14]; + result[15] = 1.0; + return result; + } + throw new RuntimeError('matrix is not invertible because its determinate is zero.'); } diff --git a/Specs/Core/Matrix4Spec.js b/Specs/Core/Matrix4Spec.js index 2086c403e390..52f3a9d47273 100644 --- a/Specs/Core/Matrix4Spec.js +++ b/Specs/Core/Matrix4Spec.js @@ -993,6 +993,38 @@ defineSuite([ expect(expected).toEqualEpsilon(result, CesiumMath.EPSILON20); }); + it('inverse behaves acceptably with near single precision zero scale matrix', function() { + var trs = new TranslationRotationScale(new Cartesian3(0.0, 0.0, 0.0), + Quaternion.fromAxisAngle(Cartesian3.UNIT_X, 0.0), + new Cartesian3(1.0e-7, 1.0e-7, 1.1e-7)); + + var matrix = Matrix4.fromTranslationRotationScale(trs); + + var expected = new Matrix4(1e7, 0, 0, 0, + 0, 1e7, 0, 0, + 0, 0, (1.0/1.1)*1e7, 0, + 0, 0, 0, 1); + + var result = Matrix4.inverse(matrix, new Matrix4()); + expect(expected).toEqualEpsilon(result, CesiumMath.EPSILON15); + }); + + it('inverse behaves acceptably with single precision zero scale matrix', function() { + var trs = new TranslationRotationScale(new Cartesian3(0.0, 0.0, 0.0), + Quaternion.fromAxisAngle(Cartesian3.UNIT_X, 0.0), + new Cartesian3(1.8e-8, 1.2e-8, 1.2e-8)); + + var matrix = Matrix4.fromTranslationRotationScale(trs); + + var expected = new Matrix4(0, 0, 0, -matrix[12], + 0, 0, 0, -matrix[13], + 0, 0, 0, -matrix[14], + 0, 0, 0, 1); + + var result = Matrix4.inverse(matrix, new Matrix4()); + expect(expected).toEqualEpsilon(result, CesiumMath.EPSILON20); + }); + it('inverseTransformation works', function() { var matrix = new Matrix4(1, 0, 0, 10, 0, 0, 1, 20, From 93cb38e060ab69fad7f543a388eef1e910ee6ad6 Mon Sep 17 00:00:00 2001 From: Dan Bagnell Date: Mon, 17 Sep 2018 15:55:19 -0400 Subject: [PATCH 2/2] Minor tweaks. --- CHANGES.md | 2 +- Source/Core/Math.js | 7 +++++++ Source/Core/Matrix4.js | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3cb2b0ebe621..a1f913f2a0ed 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,7 +9,7 @@ Change Log ##### Fixes :wrench: * Fixed an issue in the 3D Tiles traversal where empty tiles would be selected instead of their nearest loaded ancestors. [#7011](https://github.com/AnalyticalGraphicsInc/cesium/pull/7011) -* Fixed an issue where scaling near zero could cause rendering to stop. [#6954](https://github.com/AnalyticalGraphicsInc/cesium/pull/6954) +* Fixed an issue where scaling near zero with an model animation could cause rendering to stop. [#6954](https://github.com/AnalyticalGraphicsInc/cesium/pull/6954) * Fixed bug where credits weren't displaying correctly if more than one viewer was initialized [#6965](expect(https://github.com/AnalyticalGraphicsInc/cesium/issues/6965) ### 1.49 - 2018-09-04 diff --git a/Source/Core/Math.js b/Source/Core/Math.js index 4cc87eb31536..04494d6484e9 100644 --- a/Source/Core/Math.js +++ b/Source/Core/Math.js @@ -160,6 +160,13 @@ define([ */ CesiumMath.EPSILON20 = 0.00000000000000000001; + /** + * 0.000000000000000000001 + * @type {Number} + * @constant + */ + CesiumMath.EPSILON21 = 0.000000000000000000001; + /** * The gravitational parameter of the Earth in meters cubed * per second squared as defined by the WGS84 model: 3.986004418e14 diff --git a/Source/Core/Matrix4.js b/Source/Core/Matrix4.js index d67c763310bc..19ed5ed1d520 100644 --- a/Source/Core/Matrix4.js +++ b/Source/Core/Matrix4.js @@ -2283,7 +2283,7 @@ define([ // calculate determinant var det = src0 * dst0 + src1 * dst1 + src2 * dst2 + src3 * dst3; - if (Math.abs(det) < 1e-21) { + if (Math.abs(det) < CesiumMath.EPSILON21) { // Special case for a zero scale matrix that can occur, for example, // when a model's node has a [0, 0, 0] scale. if (Matrix3.equalsEpsilon(Matrix4.getRotation(matrix, scratchInverseRotation), scratchMatrix3Zero, CesiumMath.EPSILON7) &&