0
votes

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();
1
What do you mean by "really shaky"? How often are you updating pitch/yaw/roll?Fygo
the rotation seems like a gimbal lock its happening even with quaternions, i'm updating the pitch yaw roll every frame. thanks for the reply.zkr
It is not happening cos of the quaternions (you cannot get gimbal lock with quaternions) it is probably because you are converting yaw/pitch/roll to quat and obviously it can happen with yaw/pitch/roll so I assume the conversion will have no benefit. (take this with a grain of salt, I am not really good at 3D stuff). What exactly is returning you the yaw/pitch/roll? Some device? Doesn't it natively support x/y/z/w for quaternions? Also, if you are updating it on every frame, it makes no sense to slerp it imho. You should better try to smooth the values (remove spikes), otherwise it will shake.Fygo
yes, the roll/pitch/yaw are from a device, i think it does have x/y/z/w but i get the values from those because i don't know how to manage the "native quaternions", i mean, do i have to multiply, add or something the values before doing anything? (the values i'm refering are X(xyzw) Y(xyzw) Z(xyzw)) or should i create a quaternion for each? and if its the case how do i apply several quaternions at once? thanks.zkr

1 Answers

0
votes

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).