Skip to content

Commit

Permalink
Merge pull request #7037 from mksquires/modelViewMatrixInversionBug
Browse files Browse the repository at this point in the history
Altered matrix inversion code to behave correctly with single precision zero scaling
  • Loading branch information
bagnell authored Sep 17, 2018
2 parents 32c7098 + 93cb38e commit 229fdf6
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Change Log
##### Fixes :wrench:
* Fixed an issue in the 3D Tiles traversal where external tilesets would not always traverse to their root tile. [#7035](https://github.com/AnalyticalGraphicsInc/cesium/pull/7035)
* 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 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
Expand Down
7 changes: 7 additions & 0 deletions Source/Core/Math.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
51 changes: 25 additions & 26 deletions Source/Core/Matrix4.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) < 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) &&
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.');
}

Expand Down
32 changes: 32 additions & 0 deletions Specs/Core/Matrix4Spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 229fdf6

Please sign in to comment.