iPad上でOpenGL ESを使用してオブジェクトを表示しました。モデルは、頂点、法線、および頂点へのインデックスによって定義されます。モデルの原点は0,0,0です。 UIGestureRecognizerを使用して、さまざまなジェスチャーを検出できます.2本の指で水平方向にスワイプしてyについて回転し、xについては垂直にスワイプします。 yを中心に回転するための2指の回転ジェスチャ。パンでモデルを移動します。ピンチ/ズームジェスチャーをスケールします。私は、視聴者がモデルを操作して、モデルの逆や一気に見ることができるようにしたい。タッチポイントによって定義された軸の周りに回転を適用する
基本的な方法はRay Wenderlich's tutorialですが、私はこれをSwiftに書き直しました。
四元数はベクトルと角度であると私は理解しています。 up
、right
とfront
三の軸表すベクトル:
front = GLKVector3Make(0.0, 0.0, 1.0)
right = GLKVector3Make(1.0, 0.0, 0.0)
up = GLKVector3Make(0.0, 1.0, 0.0)
ようクォータニオンリンゴ三の軸(dx
の一方のみしかし、dy
の各々の周りに回転し、dz
ジェスチャ認識によって決定値を有します。)
func rotate(rotation : GLKVector3, multiplier : Float) {
let dx = rotation.x - rotationStart.x
let dy = rotation.y - rotationStart.y
let dz = rotation.z - rotationStart.z
rotationStart = GLKVector3Make(rotation.x, rotation.y, rotation.z)
rotationEnd = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(dx * multiplier, up), rotationEnd)
rotationEnd = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(dy * multiplier, right), rotationEnd)
rotationEnd = GLKQuaternionMultiply((GLKQuaternionMakeWithAngleAndVector3Axis(-dz, front)), rotationEnd)
state = .Rotation
}
図面は、以下の関数によって計算modelViewMatrix、使用:
func modelViewMatrix() -> GLKMatrix4 {
var modelViewMatrix = GLKMatrix4Identity
// translation and zoom
modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, translationEnd.x, translationEnd.y, -initialDepth);
// rotation
let quaternionMatrix = GLKMatrix4MakeWithQuaternion(rotationEnd)
modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, quaternionMatrix)
// scale
modelViewMatrix = GLKMatrix4Scale(modelViewMatrix, scaleEnd, scaleEnd, scaleEnd);
// rotation
return modelViewMatrix
}
ほとんどの場合、これが動作します。しかし、すべてが原点に相対的です。 モデルを回転させると、ピボットは常に原点を通る軸になります。原点から離れたモデルの端を拡大して回転して回転させると、モデルは急速に見えなくなります。モデルが拡大縮小されている場合、原点は固定小数点で常に大きくなります。原点がオフスクリーンでスケールが縮小されていると、モデルは原点に向かって崩壊するとビューから消えます。
何が起こるべきかは、現在のビューが何であっても、モデルは現在のビューに対して相対的に回転または拡大します。 y軸を中心とする回転の場合、回転が発生するy軸を現在のビューの中央を通って垂直に通過するように定義することを意味します。スケール操作の場合、モデルの固定小数点は画面の中央にあり、モデルはその点に向かって縮むか、その点から外側に伸びます。
私は2Dで解決策が常に原点に変換されることを知っています。回転を適用し、最初の平行移動の逆を適用します。私はなぜこれが3Dで違うべきか分かりませんが、私は四元数だけの行列でこれを行う例は見つけられません。回転の周りに平行移動と逆平行を適用しようとしましたが、何も効果がありません。
だから私は、回転機能でこれを実行しようとしました:
let xTranslation : Float = 300.0
let yTranslation : Float = 300.0
let translation = GLKMatrix4Translate(GLKMatrix4Identity, xTranslation, yTranslation, -initialDepth);
rotationEnd = GLKQuaternionMultiply(GLKQuaternionMakeWithMatrix4(translation) , rotationEnd)
rotationEnd = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(dx * multiplier, up), rotationEnd)
rotationEnd = GLKQuaternionMultiply(GLKQuaternionMakeWithAngleAndVector3Axis(dy * multiplier, right), rotationEnd)
rotationEnd = GLKQuaternionMultiply((GLKQuaternionMakeWithAngleAndVector3Axis(-dz, front)), rotationEnd)
// inverse translation
let inverseTranslation = GLKMatrix4Translate(GLKMatrix4Identity, -xTranslation, -yTranslation, -initialDepth);
rotationEnd = GLKQuaternionMultiply(GLKQuaternionMakeWithMatrix4(inverseTranslation) , rotationEnd)
翻訳は300300ですが、何の効果は全くありません、私はあることを、原点を知っている場所、それはまだ周りに旋回します。私はサンプルコードのために長い時間を捜してきましたが、何も見つかりませんでした。
modelViewMatrixを有する)(更新に適用される:
effect?.transform.modelviewMatrix = modelViewMatrix
0,0,0が中心点に収まるように、私は、モデルのすべての値を調整することにより、カンニングができた - それは希望依然として固定された起源であり、ほんのわずかしか改善されないであろう。
行列の乗算は非常に直感的であることができます - 私の最初の思考(私は何度もこれを混乱させてしまったので)は、間違った順序で行列を掛けているということです。 私はあなたが探している動作が正確ではないと思います。ビューに対して固定原点を維持する[このモデル表示サイト](https://sketchfab.com/models/7355bbb7edf14fed9273eedadf513f5c)と比較してください。これはあなたのために起こっているのでしょうか、あなたはどうやって違うのですか? –
固定原点の良い例です。自転車を中心から離れて動かすと、中央の周りに広い円弧でスイングします。私は回転の軸を回転のジェスチャーを作る2本の指の間の点にしたいと思います。今は2次元の点しか定義していませんが、回転の原点と同じzを維持することは問題ありません。 –
あなたが望むものをさらに明確にすることはできますか?たとえば、質問のリストを入力できますか? – ELKA