当前位置: 代码迷 >> 综合 >> three 源码解析之 Euler
  详细解决方案

three 源码解析之 Euler

热度:18   发布时间:2023-12-25 15:30:04.0

// 欧拉角
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() {}

} );