タッチが終わったら勢いをつけたい。私は iOS で Objective-C と OpenGL ES 2.0 API を使用して GLKit を使用しています。Arcball Rotation を使用して、Quaternions を使用して、ワールドの原点を中心にオブジェクトを回転させています。タッチで回転するときは、回転がなくなるまでしばらく速度を落として回転を続けたいと思います。
私の考え: 1.) クォータニオンから現在の角度を取得する 2.) クォータニオンを 4x4 マトリックスに変換する 3.) GLKit を使用して、現在のクォータニオンから減少する角度でマトリックスを回転させる 4.) ある時点でタイマーを無効にする
タッチが X、Y、Z 軸で個別に終了した後、マトリックスを回転させようとしましたが、結果として得られる回転は、クォータニオンから期待される軸の周りではありません。指を使ってオブジェクトを動かすと、アークボールの回転は問題なく機能します。一見任意の軸の周りで回転が続くのは、指を離したときだけです。指を離したときに、軸をクォータニオン回転の最後の状態と一致させるにはどうすればよいですか? また、ドキュメントから、オブジェクトが反時計回りに回転したときにクォータニオンの GetAngle 関数がラジアンの負の値を返す必要があることに気付きました。反時計回りに回転している場合でも、この関数から常に正の値が得られます。
あなたが提供できる洞察をどうもありがとうございました!
// Called when touches are ended
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
// The momentum var is initialized to a value
self.momentumVar = 0.05;
// Now since we stopped touching, decay the rotation to simulate momentum
self.momentumTimer = [NSTimer scheduledTimerWithTimeInterval:0.025
target:self
selector:@selector(decayGLKQuaternion)
userInfo:nil
repeats:YES];
}
// Rotate about the current axis after touches ended but for a greater angle ( radians )
- (void)decayGLKQuaternion {
//return;
// What is the current angle for the quaternion?
float currentQuatAngle = GLKQuaternionAngle(self.quat);
// Decay the value each time
self.momentumVar = currentQuatAngle * 0.0055;
NSLog(@"QUAT Angle %f %f",GLKQuaternionAngle(self.quat),GLKMathRadiansToDegrees(GLKQuaternionAngle(self.quat)));
GLKMatrix4 newMat = GLKMatrix4MakeWithQuaternion(self.quat);
float rotate = self.momentumVar * 0.75;
//newMat = GLKMatrix4RotateX(newMat, rotate);
//newMat = GLKMatrix4RotateY(newMat, rotate);
//newMat = GLKMatrix4RotateZ(newMat, rotate);
newMat = GLKMatrix4Rotate(newMat, rotate, 1, 0, 0);
newMat = GLKMatrix4Rotate(newMat, rotate, 0, 1, 0);
newMat = GLKMatrix4Rotate(newMat, rotate, 0, 1, 1);
self.quat = GLKQuaternionMakeWithMatrix4(newMat);
}