2016-11-24 4 views
1

J'utilise le quaternion de CMAttitude pour faire pivoter la caméra SceneKit. J'ai aussi besoin d'utiliser l'angle de rotation Y extrait du quaternion. Je m'attendais à ce que ça roule, mais après l'extraction Y l'angle de rotation correspond au pas qui a -90: 90. Comment puis-je convertir cette plage à 0: 180 ou 0: 360?Jet et hauteur inattendus extraits de GLKQuaternion

- (SCNQuaternion)SCNQuaternionFromCMQuaternion:(CMQuaternion)q { 

    GLKQuaternion Q = GLKQuaternionMake(q.x, q.y, q.z, q.w); 
    GLKQuaternion xRotQ = GLKQuaternionMakeWithAngleAndAxis(-M_PI_2, 1, 0, 0); 
    Q = GLKQuaternionMultiply(xRotQ, Q); 

    double roll = atan2(2.0 * (Q.y * Q.z - Q.w * Q.x), 1.0 - 2.0 * (Q.x * Q.x + Q.y * Q.y)); // 0:180 but around X 

    double pitch = RADIANS_TO_DEGREES(asin(-2.0f * (Q.x * Q.z + Q.w * Q.y))); // 0:90 around Y 

    NSLog(@"%f", pitch); 
    // ... 

    CMQuaternion rq = {.x = Q.x, .y = Q.y, .z = Q.z, .w = Q.w}; 

    return SCNVector4Make(rq.x, rq.y, rq.z, rq.w); 
} 

Répondre

1

Je trouve cette façon:

- (SCNQuaternion)SCNQuaternionFromCMQuaternion:(CMQuaternion)q { 

    GLKQuaternion Q = GLKQuaternionMake(q.x, q.y, q.z, q.w); 
    GLKQuaternion xRotQ = GLKQuaternionMakeWithAngleAndAxis(-M_PI_2, 1, 0, 0); 
    Q = GLKQuaternionMultiply(xRotQ, Q); 

    double gx = 2.0 * (Q.y * Q.w - Q.x * Q.z); 
    //double gy = 2.0 * (Q.x * Q.y + Q.z * Q.w); 
    double gz = Q.x * Q.x - Q.y * Q.y - Q.z * Q.z + Q.w * Q.w; 

    double pitch = RADIANS_TO_DEGREES(-asin(-2.0 * (Q.y * Q.w - Q.x * Q.z))); 

    if (gx >= 0 && gz < 0) 
     pitch = 180 - pitch; 
    else if (gx < 0 && gz < 0) 
     pitch = 180 - pitch; 
    else if (gx < 0 && gz >= 0) 
     pitch = 360 + pitch; 

    NSLog(@"%f", pitch); // now it has 0-360 range 

    CMQuaternion rq = {.x = Q.x, .y = Q.y, .z = Q.z, .w = Q.w}; 

    return SCNVector4Make(rq.x, rq.y, rq.z, rq.w); 
}