How to derive “standard” rotations from three.js when using quaternions?

后端 未结 2 1922
刺人心
刺人心 2020-12-31 19:00

Newbie stackoverflow participant, newbie 3D programmer, and far from a math wiz... so I\'ll try to frame this question as clearly as I can, hoping it makes sense, and hoping

2条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-31 19:53

    Thanks for the quick response - it wasn't exactly what I was looking for, but I probably didn't know how to ask the question clearly. My specific use-case was that I wanted to draw a 2D map the represented the relative positions of all the objects in my 3D scene, but I wanted to rotate the objects in the map based on the yaw of the camera in the 3D scene - so I needed to know the "angle" that the quaternion-based camera was facing so that I could offset the rotations of the 2D objects on the map accordingly. Seems to work pretty well. I just wish there didn't have to be so many calculations, but at least Javascript is fast.

    // Pass the obj.quaternion that you want to convert here:
    //*********************************************************
    function quatToEuler (q1) {
        var pitchYawRoll = new THREE.Vector3();
         sqw = q1.w*q1.w;
         sqx = q1.x*q1.x;
         sqy = q1.y*q1.y;
         sqz = q1.z*q1.z;
         unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
         test = q1.x*q1.y + q1.z*q1.w;
        if (test > 0.499*unit) { // singularity at north pole
            heading = 2 * Math.atan2(q1.x,q1.w);
            attitude = Math.PI/2;
            bank = 0;
            return;
        }
        if (test < -0.499*unit) { // singularity at south pole
            heading = -2 * Math.atan2(q1.x,q1.w);
            attitude = -Math.PI/2;
            bank = 0;
            return;
        }
        else {
            heading = Math.atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw);
            attitude = Math.asin(2*test/unit);
            bank = Math.atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw)
        }
        pitchYawRoll.z = Math.floor(attitude * 1000) / 1000;
        pitchYawRoll.y = Math.floor(heading * 1000) / 1000;
        pitchYawRoll.x = Math.floor(bank * 1000) / 1000;
    
        return pitchYawRoll;
    }        
    
    // Then, if I want the specific yaw (rotation around y), I pass the results of
    // pitchYawRoll.y into the following to get back the angle in radians which is
    // what can be set to the object's rotation.
    
    //*********************************************************
    function eulerToAngle(rot) {
        var ca = 0;
        if (rot > 0)
            { ca = (Math.PI*2) - rot; } 
        else 
            { ca = -rot }
    
        return (ca / ((Math.PI*2)/360));  // camera angle radians converted to degrees
    }
    

提交回复
热议问题