5

特にiOSでGLKitを使用して、クォータニオンを使用した3Dモデルでのアークボール回転の簡単な実装を探しています。これまで、次の情報源を調べてきました。

私はまた、ここここからソースコードと数学を理解しようとしています。オブジェクトを回転させることはできますが、特定の角度でジャンプし続けるため、ジンバルロックが機能しているのではないかと心配しています。ジェスチャレコグナイザーを使用して回転を制御しています(パンジェスチャはロールとヨーに影響し、回転ジェスチャはピッチに影響します)。クォータニオン処理とモデルビュー行列変換のコードを添付しています。

変数:

  • GLKQuaternion rotationE;

クォータニオン処理:

- (void)rotateWithXY:(float)x and:(float)y
{
    const float rate = M_PI/360.0f;
    GLKVector3 up = GLKVector3Make(0.0f, 1.0f, 0.0f);
    GLKVector3 right = GLKVector3Make(1.0f, 0.0f, 0.0f);

    up = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), up);
    self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(x*rate, up));

    right = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), right);
    self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(y*rate, right));
}

- (void)rotateWithZ:(float)z
{
    GLKVector3 front = GLKVector3Make(0.0f, 0.0f, -1.0f);

    front = GLKQuaternionRotateVector3(GLKQuaternionInvert(self.rotationE), front);
    self.rotationE = GLKQuaternionMultiply(self.rotationE, GLKQuaternionMakeWithAngleAndVector3Axis(z, front));
}

Modelviewマトリックス変換(描画ループ内):

// Get Quaternion Rotation
GLKVector3 rAxis = GLKQuaternionAxis(self.transformations.rotationE);
float rAngle = GLKQuaternionAngle(self.transformations.rotationE);

// Set Modelview Matrix
GLKMatrix4 modelviewMatrix = GLKMatrix4Identity;
modelviewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -0.55f);
modelviewMatrix = GLKMatrix4Rotate(modelviewMatrix, rAngle, rAxis.x, rAxis.y, rAxis.z);
modelviewMatrix = GLKMatrix4Scale(modelviewMatrix, 0.5f, 0.5f, 0.5f);
glUniformMatrix4fv(self.sunShader.uModelviewMatrix, 1, 0, modelviewMatrix.m);

どんな助けでも大歓迎ですが、私はそれをできるだけシンプルに保ち、GLKitに固執したいと思います。

4

2 に答える 2

6

ここでいくつかの問題が発生しているようです。

  1. [x,y] をパンに使用していると言っていますが、ピッチとヨーに使用しているように見えます。少なくとも私にとって、パンは移動であり、回転ではありません。

  2. 何かが欠けていない限り、更新しようとするたびにローテーション全体を置き換えているようにも見えます。現在の回転の逆数でベクトルを回転させ、そのベクトルと角度からクォータニオンを作成します。これは、元のベクトルから四元数を作成し、現在の回転を逆に回転させることと同じだと思います。だからあなたは持っていq_e'*q_upます。次に、それを現在の回転で乗算すると、 が得られq_e*q_e'*q_up = q_upます。現在の回転はキャンセルされます。これはあなたが望むものではないようです。

    実際に必要なことは、axis-and-angle から新しい四元数を作成し、それを現在の四元数で乗算することだけです。新しいクォータニオンが左側にある場合、向きの変更には目ローカル フレームが使用されます。新しいクォータニオンが右側にある場合、方向の変更はグローバル フレームで行われます。私はあなたが欲しいと思います:

    self.rotationE =
      GLKQuaternionMultiply( 
        GLKQuaternionMakeWithAngleAndVector3Axis(x*rate, up),self.rotationE);
    

    3 つのケースすべてについて、逆に前回転せずにこれを行います。

  3. GLKit を使用したことはありませんが、Quaternion から Matrix に変換するときに軸角度を抽出することはまれです。角度がゼロの場合、軸は未定義です。ゼロに近づくと、数値が不安定になります。GLKMatrix4MakeWithQuaternion結果のマトリックスを使用してから、変換マトリックスとスケールマトリックスを乗算する必要があるようです。

    GLKMatrix4 modelviewMatrix = 
      GLKMatrix4Multiply( GLKMatrix4MakeTranslation(0.0f, 0.0f, -0.55f),
                          GLKMatrix4MakeWithQuaternion( self.rotationE ) );
    modelviewMatrix = GLKMatrix4Scale( modelviewMatrix, 0.5f, 0.5f, 0.5f );
    
于 2013-01-01T17:08:36.750 に答える
3

私は最近、この問題の結果としての実装についてもう少し尋ねられたので、ここにあります!

- (void)rotate:(GLKVector3)r
{
    // Convert degrees to radians for maths calculations
    r.x = GLKMathDegreesToRadians(r.x);
    r.y = GLKMathDegreesToRadians(r.y);
    r.z = GLKMathDegreesToRadians(r.z);

    // Axis Vectors w/ Direction (x=right, y=up, z=front)
    // In OpenGL, negative z values go "into" the screen. In GLKit, positive z values go "into" the screen.
    GLKVector3 right = GLKVector3Make(1.0f, 0.0f, 0.0f);
    GLKVector3 up = GLKVector3Make(0.0f, 1.0f, 0.0f);
    GLKVector3 front = GLKVector3Make(0.0f, 0.0f, 1.0f);

    // Quaternion w/ Angle and Vector
    // Positive angles are counter-clockwise, so convert to negative for a clockwise rotation
    GLKQuaternion q = GLKQuaternionIdentity;
    q = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(-r.x, right), q);
    q = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(-r.y, up), q);
    q = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(-r.z, front), q);

    // ModelView Matrix
    GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;
    modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeWithQuaternion(q));
}

うまく活用していただければ幸いです:)

于 2013-09-06T17:28:42.597 に答える