来自 matrix3d 的四元数 slerp 附加旋转俯仰、滚动、偏航 AS3

Quaternion slerp from matrix3d append rotation pitch,roll,yaw AS3

我正在尝试将对象的俯仰、滚动和偏航附加到 matrix3d,然后获取四元数并进行旋转……但结果真的不稳定,这是我第一次处理四元数我是 3d 编程的新手,到目前为止我猜测四元数的正确使用(以避免万向节锁定)有没有办法不 "append" 只是 "assign" 新的旋转值?

pitch=(obj.pitch);
yaw=(obj.yaw);
roll=(obj.roll);

mtrx:Matrix3D=new Matrix3D();
mtrx=setV[a].transform.clone();

mtrx.appendRotation(pitch,Vector3D.Y_AXIS);
mtrx.appendRotation(roll,Vector3D.X_AXIS);
mtrx.appendRotation(yaw,Vector3D.Z_AXIS);

quat1:Quaternion=new Quaternion;
quat1.fromMatrix(mtrx);
quat2:Quaternion=new Quaternion;
quat2.fromMatrix(setV[a].transform);

quat2.slerp(quat2,quat1,0.1);

mtrx2:Matrix3D=new Matrix3D();              
quat1.toMatrix3D(mtrx2);

setV[a].transform=mtrx.clone();

检查这个class,我是为 IMU Brick 制作的,所以如果你有类似的设备,它可能适合你。我从 javascript 获取值,但在您的情况下可能有所不同。您可能还需要调整 relX、relY...等(例如,观察我如何将 quaternionArray[0] 更改为负数等)。

package com.company.product.imu {

    import flash.external.ExternalInterface;
    import flash.geom.Matrix3D;

    public final class Brick {

        private static var _relX:Number;
        private static var _relY:Number;
        private static var _relZ:Number;
        private static var _relW:Number;

        public function Brick() {
            super();
            throw new Error("Brick is a static class.");
        }

        public static function saveOrientation():void {
            var quaternionString:String;
            if(ExternalInterface.available) {
                try {
                    quaternionString = ExternalInterface.call("getQuaternionString");
                }
                catch(e:SecurityError) {}
            }
            var quaternionArray:Array = quaternionString.split(",");
            _relX = -quaternionArray[0];
            _relY = -quaternionArray[1];
            _relZ = quaternionArray[2];
            _relW = quaternionArray[3];
        }

        public static function getTransformationMatrix():Matrix3D {
            var quaternionString:String;
            if(isNaN(_relX)) {
                saveOrientation();
            }
            if(ExternalInterface.available) {
                try {
                    quaternionString = ExternalInterface.call("getQuaternionString");
                }
                catch(e:SecurityError) {}
            }
            var quaternionArray:Array = quaternionString.split(",");
            var x:Number = -quaternionArray[0];
            var y:Number = -quaternionArray[1];
            var z:Number = quaternionArray[2];
            var w:Number = -quaternionArray[3];

            var wn:Number = w * _relW - x * _relX - y * _relY - z * _relZ;
            var xn:Number = w * _relX + x * _relW + y * _relZ - z * _relY;
            var yn:Number = w * _relY - x * _relZ + y * _relW + z * _relX;
            var zn:Number = w * _relZ + x * _relY - y * _relX + z * _relW;

            x = xn;
            y = yn;
            z = zn;
            w = wn;

            var xx:Number = x * x;
            var yy:Number = y * y;
            var zz:Number = z * z;
            var xy:Number = x * y;
            var xz:Number = x * z;
            var yz:Number = y * z;
            var wx:Number = w * x;
            var wy:Number = w * y;
            var wz:Number = w * z;

            var matrix:Matrix3D = new Matrix3D();
            var matrixData:Vector.<Number> = new <Number>[1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy), 0.0,
                                                          2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx), 0.0,
                                                          2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy), 0.0,
                                                          0.0, 0.0, 0.0, 1];
            matrix.rawData = matrixData;
            return matrix;
        }
    }
}

然后,在其他一些 class(我的主要,在这种情况下)我简单地调用:

private function onEnterFrame(e:Event):void {
    if(_drill.isLoaded) {
        _drill.transform = Brick.getTransformationMatrix();
        //other things to perform
    }
    _view.render();
}

另请注意,js 错误捕获在我的案例中毫无意义,因为我确信它永远不会失败。当然,如果它可能适合你,你将不得不处理它(在那种情况下我的代码实际上会抛出一些错误)。