0

私はクォータニオン チュートリアルに従っています: http://www.raywenderlich.com/12667/how-to-rotate-a-3d-object-using-touches-with-openglで、地球儀を XYZ 位置に回転させようとしています。初期クォータニオンがあり、地球の表面にランダムな XYZ 位置を生成します。その XYZ 位置を次の関数に渡します。GLKMatrix4MakeLookAt を使用して lookAt ベクターを生成し、lookAt マトリックスからスラープ ステップの終了クォータニオンを定義するというアイデアでした。

- (void)rotateToLocationX:(float)x andY:(float)y andZ:(float)z {

    // Turn on the interpolation for smooth rotation
    _slerping = YES; // Begin auto rotating to this location
    _slerpCur = 0;
    _slerpMax = 1.0;
    _slerpStart = _quat;

    // The eye location is defined by the look at location multiplied by this modifier
    float modifier = 1.0;

    // Create a look at vector for which we will create a GLK4Matrix from
    float xEye = x;
    float yEye = y;
    float zEye = z;
    //NSLog(@"%f %f %f %f %f %f",xEye, yEye, zEye, x, y, z);
    _currentSatelliteLocation = GLKMatrix4MakeLookAt(xEye, yEye, zEye, 0, 0, 0, 0, 1, 0);
    _currentSatelliteLocation = GLKMatrix4Multiply(_currentSatelliteLocation,self.effect.transform.modelviewMatrix);

    // Turn our 4x4 matrix into a quat and use it to mark the end point of our interpolation
    //_currentSatelliteLocation = GLKMatrix4Translate(_currentSatelliteLocation, 0.0f, 0.0f, GLOBAL_EARTH_Z_LOCATION);
    _slerpEnd = GLKQuaternionMakeWithMatrix4(_currentSatelliteLocation);

    // Print info on the quat
    GLKVector3 vec = GLKQuaternionAxis(_slerpEnd);
    float angle = GLKQuaternionAngle(_slerpEnd);
    //NSLog(@"%f %f %f %f",vec.x,vec.y,vec.z,angle);

    NSLog(@"Quat end:");
    [self printMatrix:_currentSatelliteLocation];
    //[self printMatrix:self.effect.transform.modelviewMatrix];

}

補間は機能し、スムーズな回転が得られますが、終了位置は入力した XYZ ではありません。これは、地球が球体であり、Lat Lon から XYZ を計算しているためです。回転後の地球の表面の緯度/経度の位置から、地球の中心に向かって「lookAt」ベクトルを直接見下ろしたいと思います。アップベクトルと関係があると思いますが、意味のあることはすべて試しました。

何が間違っているのですか - 回転が終了したときに地球の表面の XYZ にベクトルを見下ろす最終的な四元数を定義するにはどうすればよいですか? ありがとう!

4

2 に答える 2

0

この質問に対する答えは、次のrotateTo関数とRayのチュートリアルのコードへの変更の組み合わせです( http://www.raywenderlich.com/12667/how-to-rotate-a-3d-object-using- touches-with-opengl )。その記事のコメントの 1 つに、GLKQuaternion Q_rot = GLKQuaternionMakeWithAngleAndVector3Axis(angle * 2.0, axis); で乗算される任意の係数 2.0 があると書かれています。その「2」を削除し、次の関数を使用して _slerpEnd を作成します。その後、グローブは指定された XYZ にスムーズに回転します。

// Rotate the globe using Slerp interpolation to an XYZ coordinate
- (void)rotateToLocationX:(float)x andY:(float)y andZ:(float)z {

    // Turn on the interpolation for smooth rotation
    _slerping = YES; // Begin auto rotating to this location
    _slerpCur = 0;
    _slerpMax = 1.0;
    _slerpStart = _quat;

    // Create a look at vector for which we will create a GLK4Matrix from
    float xEye = x;
    float yEye = y;
    float zEye = z;
    _currentSatelliteLocation = GLKMatrix4MakeLookAt(xEye, yEye, zEye, 0, 0, 0, 0, 1, 0);

    // Turn our 4x4 matrix into a quat and use it to mark the end point of our interpolation
    _slerpEnd = GLKQuaternionMakeWithMatrix4(_currentSatelliteLocation);

}
于 2013-06-08T00:02:42.320 に答える