// 欧拉角
function Euler( x,y,z,order ) {
// 自定义 x,y,z,order,并且设定默认值
this._x= x ||0;
this._y= y ||0;
this._z= z ||0;
this._order= order || Euler.DefaultOrder; // 默认值可以修改
}
Euler.RotationOrders= ['XYZ','YZX','ZXY','XZY','YXZ','ZYX'];
Euler.DefaultOrder='XYZ';
Object.defineProperties(Euler.prototype,{
// 通过 ‘’属性描述对象 “的存储器,其中存值函数,称为setter,使用属性描述对象的set属性,取值函数用getter,使用属性描述对象get属性,一旦对目标属性定义了存取器,那么存取的时候,都将执行对应的函数。利用这个功能,可以实现许多高级特性,参考 http://javascript.ruanyifeng.com/stdlib/attributes.html#toc3 // 这里就是利用该特性,使得我们设置属性值时,同时执行自定义的 this.onChangeCallback 事件
x: {
get:function() {
return this._x;
},
set:function( value ) {
this._x= value;
this.onChangeCallback();
}
},
y: {
get:function() {
return this._y;
},
set:function( value ) {
this._y= value;
this.onChangeCallback();
}
},
z: {
get:function() {
return this._z;
},
set:function( value ) {
this._z= value;
this.onChangeCallback();
}
},
order: {
get:function() {
return this._order;
},
set:function( value ) {
this._order= value;
this.onChangeCallback();
}
}
} );
Object.assign(Euler.prototype,{
isEuler:true,
// 重新设置
set:function( x,y,z,order ) {
this._x= x;
this._y= y;
this._z= z;
this._order= order || this._order;
this.onChangeCallback();
return this;
},
// 重新实例化对象 , 这里巧妙的利用了 this.constructor
clone:function() {
return new this.constructor(this._x,this._y,this._z,this._order);
},
// 复制另外一个 EULER 对象的值
copy:function( euler ) {
this._x= euler._x;
this._y= euler._y;
this._z= euler._z;
this._order= euler._order;
this.onChangeCallback();
return this;
},
// m : 是一个4 * 4 的矩阵,,前面的 3*3矩阵必须是一个旋转矩阵,通过旋转矩阵来控制旋转。具体算法可以参考 http://blog.csdn.net/csxiaoshui/article/details/65446125
setFromRotationMatrix:function( m,order,update ) {
// 后续讲解,,将值限制在某个范围
varclamp = _Math.clamp;
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
var te = m.elements;
var m11 = te[0],m12 = te[4],m13 = te[8];
var m21 = te[1],m22 = te[5],m23 = te[9];
var m31 = te[2],m32 = te[6],m33 = te[10];
order = order ||this._order;
// 具体判断原理不是很清楚,大家会用就可以,,本人能力有限
if( order ==='XYZ') {
// Math.asin() 求出通过asin 弧度值
this._y= Math.asin( clamp( m13,-1,1) );
if( Math.abs( m13 ) <0.99999 ) {
// 通过Math.atan2 来计算出当前的方向弧度,用法 Math.atan2(y,x); 当y>0 ,为正值,当 y<0 ;为负值,下面是我的测试结果 :Math.atan2(4,-4); 2.356194490192345 Math.atan2(4,4); 0.7853981633974483
Math.atan2(-4,-4); -2.356194490192345 Math.atan2(-4,4); -0.7853981633974483
Math.atan2(0,8); 0 Math.atan2(0,-8); 3.141592653589793
this._x= Math.atan2( - m23,m33 );
this._z= Math.atan2( - m12,m11 );
}else{
this._x= Math.atan2( m32,m22 );
this._z=0;
}
} else if( order ==='YXZ') {
this._x= Math.asin( - clamp( m23,-1,1) );
if( Math.abs( m23 ) <0.99999 ) {
this._y= Math.atan2( m13,m33 );
this._z= Math.atan2( m21,m22 );
}else{
this._y= Math.atan2( - m31,m11 );
this._z=0;
}
} else if( order ==='ZXY') {
this._x= Math.asin( clamp( m32,-1,1) );
if( Math.abs( m32 ) <0.99999 ) {
this._y= Math.atan2( - m31,m33 );
this._z= Math.atan2( - m12,m22 );
}else{
this._y=0;
this._z= Math.atan2( m21,m11 );
}
} else if( order ==='ZYX') {
this._y= Math.asin( - clamp( m31,-1,1) );
if( Math.abs( m31 ) <0.99999 ) {
this._x= Math.atan2( m32,m33 );
this._z= Math.atan2( m21,m11 );
}else{
this._x=0;
this._z= Math.atan2( - m12,m22 );
}
} else if( order ==='YZX') {
this._z= Math.asin( clamp( m21,-1,1) );
if( Math.abs( m21 ) <0.99999 ) {
this._x= Math.atan2( - m23,m22 );
this._y= Math.atan2( - m31,m11 );
}else{
this._x=0;
this._y= Math.atan2( m13,m33 );
}
} else if( order ==='XZY') {
this._z= Math.asin( - clamp( m12,-1,1) );
if( Math.abs( m12 ) <0.99999 ) {
this._x= Math.atan2( m32,m22 );
this._y= Math.atan2( m13,m11 );
}else{
this._x= Math.atan2( - m23,m33 );
this._y=0;
}
} else{
console.warn('THREE.Euler: .setFromRotationMatrix() given unsupported order: '+ order );
}
this._order= order;
if( update !==false)this.onChangeCallback();
return this;
},
setFromQuaternion:function() {
// 创建一个四维矩阵
var matrix =new Matrix4();
return functionsetFromQuaternion( q,order,update ) {
// 四维矩阵通过调用setFromRotationMatrix将四元数转化为对应的矩阵,然后调用上面的方法 //setFromRotationMatrix
matrix.makeRotationFromQuaternion( q );
return this.setFromRotationMatrix( matrix, order,update );
};
}(),
setFromVector3:function( v,order ) {
// 通过将Vector3的值赋值给Elur
return this.set( v.x, v.y,v.z,order || this._order);
},
reorder:function() {
// WARNING: this discards revolution information -bhouston
// 声明一个四元数,
var q =newQuaternion();
return functionreorder( newOrder ) {
// 将欧拉角设置为四元数 ,这里的this,是现在的欧拉角
q.setFromEuler(this);
// 执行上面的方法
return this.setFromQuaternion( q, newOrder );
};
}(),
// 判断两个欧拉角是否完全相同
equals:function( euler ) {
return( euler._x ===this._x ) && ( euler._y ===this._y ) && ( euler._z ===this._z ) && ( euler._order===this._order);
},
// 设置欧拉角通过数组赋值,,数组可以省略order
fromArray:function( array ) {
this._x= array[0];
this._y= array[1];
this._z= array[2];
if( array[3] !==undefined)this._order= array[3];
this.onChangeCallback();
return this;
},
// 转化为数组,,可以传入数组,并且返回该数组,也可以不传,,offset,,指从哪个位置开始赋值
toArray:function( array,offset ) {
if( array ===undefined) array = [];
if( offset ===undefined) offset =0;
array[ offset ] =this._x;
array[ offset +1] =this._y;
array[ offset +2] =this._z;
array[ offset +3] =this._order;
returnarray;
},
// 可以传入一个vector3,并且返回该verctor3,否则返回一个新的vector3,传入的是地址
toVector3:function( optionalResult ) {
if( optionalResult ) {
return optionalResult.set(this._x,this._y,this._z );
}else{
return newVector3(this._x,this._y,this._z );
}
},
// 通过onChange 指定onChangeCallback的函数结果
onChange:function( callback ) {
this.onChangeCallback= callback;
return this;
},
onChangeCallback:function() {}
} );