actionscript-3quaternionsaway3d

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


I'm trying to append the pitch,roll and yaw of an object to a matrix3d, then get que quaternions and slerp the rotation... but the result it's really shaky, its the first time i deal with quaternions and i'm new in 3d programing, to this point i'm guessing the correct use of quaternions (to avoid gimbal lock) is there a way to not "append" just "assign" the new rotation values?

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();

Solution

  • Check this class, I made it for IMU Brick, so if you have a similar device, it may work for you. I was obtaining the values from javascript, but that may be different in your case. You may also need to tweak the relX, relY... etc (observe how, for example, I had to change the quaternionArray[0] to be negative, etc.).

    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;
            }
        }
    }
    

    Then, in some other class (my main, in this case) I simply call:

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

    Also note that the js error catching makes no sense in my case cos I was sure that it will never fail. Of course if it may fall for you, you will have to handle it (my code would actually throw some error in that case).