提交 05e26f97 编写于 作者: B Ben Houston

fix Euler.setFromQuaternion bug - see #5659

上级 50688132
......@@ -101,7 +101,7 @@ THREE.Euler.prototype = {
},
setFromRotationMatrix: function ( m, order ) {
setFromRotationMatrix: function ( m, order, update ) {
var clamp = THREE.Math.clamp;
......@@ -218,76 +218,26 @@ THREE.Euler.prototype = {
this._order = order;
this.onChangeCallback();
if ( update !== false ) this.onChangeCallback();
return this;
},
setFromQuaternion: function ( q, order, update ) {
var clamp = THREE.Math.clamp;
// q is assumed to be normalized
// http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
var sqx = q.x * q.x;
var sqy = q.y * q.y;
var sqz = q.z * q.z;
var sqw = q.w * q.w;
order = order || this._order;
if ( order === 'XYZ' ) {
this._x = Math.atan2( 2 * ( q.x * q.w - q.y * q.z ), ( sqw - sqx - sqy + sqz ) );
this._y = Math.asin( clamp( 2 * ( q.x * q.z + q.y * q.w ), - 1, 1 ) );
this._z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw + sqx - sqy - sqz ) );
} else if ( order === 'YXZ' ) {
this._x = Math.asin( clamp( 2 * ( q.x * q.w - q.y * q.z ), - 1, 1 ) );
this._y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw - sqx - sqy + sqz ) );
this._z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw - sqx + sqy - sqz ) );
} else if ( order === 'ZXY' ) {
this._x = Math.asin( clamp( 2 * ( q.x * q.w + q.y * q.z ), - 1, 1 ) );
this._y = Math.atan2( 2 * ( q.y * q.w - q.z * q.x ), ( sqw - sqx - sqy + sqz ) );
this._z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw - sqx + sqy - sqz ) );
setFromQuaternion: function() {
} else if ( order === 'ZYX' ) {
var mIntermediate = null;
return function( q, order, update ) {
mIntermediate = mIntermediate || new THREE.Matrix4();
mIntermediate.makeRotationFromQuaternion( q );
this.setFromRotationMatrix( mIntermediate, order );
return this;
};
this._x = Math.atan2( 2 * ( q.x * q.w + q.z * q.y ), ( sqw - sqx - sqy + sqz ) );
this._y = Math.asin( clamp( 2 * ( q.y * q.w - q.x * q.z ), - 1, 1 ) );
this._z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw + sqx - sqy - sqz ) );
} else if ( order === 'YZX' ) {
this._x = Math.atan2( 2 * ( q.x * q.w - q.z * q.y ), ( sqw - sqx + sqy - sqz ) );
this._y = Math.atan2( 2 * ( q.y * q.w - q.x * q.z ), ( sqw + sqx - sqy - sqz ) );
this._z = Math.asin( clamp( 2 * ( q.x * q.y + q.z * q.w ), - 1, 1 ) );
} else if ( order === 'XZY' ) {
this._x = Math.atan2( 2 * ( q.x * q.w + q.y * q.z ), ( sqw - sqx + sqy - sqz ) );
this._y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw + sqx - sqy - sqz ) );
this._z = Math.asin( clamp( 2 * ( q.z * q.w - q.x * q.y ), - 1, 1 ) );
} else {
console.warn( 'THREE.Euler: .setFromQuaternion() given unsupported order: ' + order )
}
this._order = order;
if ( update !== false ) this.onChangeCallback();
return this;
},
}(),
reorder: function () {
......@@ -302,7 +252,6 @@ THREE.Euler.prototype = {
};
}(),
equals: function ( euler ) {
......
......@@ -22,6 +22,19 @@ var matrixEquals4 = function( a, b, tolerance ) {
return true;
};
var eulerEquals = function( a, b, tolerance ) {
tolerance = tolerance || 0.0001;
var diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z );
return ( diff < tolerance );
};
var quatEquals = function( a, b, tolerance ) {
tolerance = tolerance || 0.0001;
var diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z ) + Math.abs( a.w - b.w );
return ( diff < tolerance );
};
test( "constructor/equals", function() {
var a = new THREE.Euler();
ok( a.equals( eulerZero ), "Passed!" );
......@@ -59,7 +72,7 @@ test( "Quaternion.setFromEuler/Euler.fromQuaternion", function() {
var v2 = new THREE.Euler().setFromQuaternion( q, v.order );
var q2 = new THREE.Quaternion().setFromEuler( v2 );
ok( q.equals( q2 ), "Passed!" );
ok( eulerEquals( q, q2 ), "Passed!" );
}
});
......@@ -84,10 +97,30 @@ test( "reorder", function() {
v.reorder( 'YZX' );
var q2 = new THREE.Quaternion().setFromEuler( v );
ok( q.equals( q2 ), "Passed!" );
ok( quatEquals( q, q2 ), "Passed!" );
v.reorder( 'ZXY' );
var q3 = new THREE.Quaternion().setFromEuler( v );
ok( q.equals( q3 ), "Passed!" );
ok( quatEquals( q, q3 ), "Passed!" );
}
});
test( "gimbalLocalQuat", function() {
// known problematic quaternions
var q1 = new THREE.Quaternion( 0.5207769385244341, -0.4783214164122354, 0.520776938524434, 0.47832141641223547 );
var q2 = new THREE.Quaternion( 0.11284905712620674, 0.6980437630368944, -0.11284905712620674, 0.6980437630368944 );
var eulerOrder = "ZYX";
// create Euler directly from a Quaternion
var eViaQ1 = new THREE.Euler().setFromQuaternion( q1, eulerOrder ); // there is likely a bug here
// create Euler from Quaternion via an intermediate Matrix4
var mViaQ1 = new THREE.Matrix4().makeRotationFromQuaternion( q1 );
var eViaMViaQ1 = new THREE.Euler().setFromRotationMatrix( mViaQ1, eulerOrder );
// the results here are different
ok( eulerEquals( eViaQ1, eViaMViaQ1 ), "Passed!" ); // this result is correct
});
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册