(原点ではなく)3Dの任意の点を中心に回転するにはどうすればよいですか?


15

四元数を使用して通常の方法で回転させたいモデルがいくつかありますが、原点を中心とした回転の代わりに、わずかにオフセットする必要があります。3D空間では、点を中心に回転するとは言わないことを知っています。軸を中心に回転すると言います。そのため、尾がローカルの原点にないベクトルを中心に回転するように視覚化しています。

レンダリング/物理エンジンのすべてのアフィン変換は、SQT(スケール、クォータニオン、翻訳、ゲームエンジンアーキテクチャの本から借用したアイデア)を使用して保存されます。したがって、これらのコンポーネントからフレームごとにマトリックスを構築し、頂点シェーダーに渡します。このシステムでは、平行移動、次に拡大縮小、回転が適用されます。

特定のケースでは、ワールド空間でオブジェクトを変換し、スケーリングし、オブジェクトのローカル原点を中心にしない頂点を中心に回転する必要があります。

質問:上記の現在のシステムの制約を考えると、原点以外の点を中心としたローカル回転をどのように実現できますか?マトリックスのみを使用してこれを行う方法を説明できる人への自動アップ投票:)


四元数はすでに任意の軸を中心とした回転を記述しています。あなたが持っているデータからそのような四元数を構築するのに問題がありますか?
マーティンソイカ

3
真剣に、回答賛成した人は実際にそれらを読むことができましたか?私は方法、効率的な式、さらにはデモンストレーションを行いました。しかし、唯一の価値のある情報(および明らかに間違った情報)を提供する唯一の賛成の答えは、これらのどれも備えておらず、質問に答えさえしません!
サムホセバー

@MartinSojka、これは約任意のポイントであり、任意の軸ではありません。
notlesh

@SamHocevar両方の答えは役に立ちました。それがより徹底的であり、解決策を見つけるのに役立ったので、私はあなたのものを選びました。あなたがた両方に感謝します。
notlesh

ああ、ごめんなさい-デュアルクォータニオンと混同してしまいました(「無料で」翻訳も入手できます)。回答の中で私が意味したことを後で書きます。他の人は、3つのコンポーネントを1つに減らすことができるため、特に複雑ではあるものの、特に便利だと思うでしょう。
マーティンソーカ

回答:


17

要するに

SQTフォームでTを変更するだけです。

並進ベクトル置き換えvv' = v-invscale(p-invrotate(p))どこv初期並進ベクトルであるが、pあなたは回転が起こるしたいの周りにポイントがあり、invrotateそしてinvscaleあなたの回転とスケールの逆です。

簡単なデモンストレーション

ましょうpあなたが周りに回転を適用する点になりますrsスケーリングパラメータとv並進ベクトルにしましょう。最終的な行列変換はT(p)R(r)T(-p)S(s)T(v)代わりにR(r)S(s)T(v)ます。

必要なのは、新しい変換パラメーターv'r'ありs'、最終的なマトリックス変換はR(r')S(s')T(v')次のとおりです。

T(p)R(r)T(-p)S(s)T(v) = R(r')S(s')T(v')

無限大での動作は、回転パラメーターとスケーリングパラメーターを変更できないことを示します(これは実証できます)。したがって、r = r'とがありs = s'ます。したがってv'、欠落しているパラメーターは、新しい変換ベクトルのみです。

T(p)R(r)T(-p)S(s)T(v) = R(r)S(s)T(v')

これらの行列が等しい場合、それらの逆行列は等しくなります。

T(-v)S(-s)T(p)R(-r)T(-p) = T(-v')S(-s)R(-r)

これは特にoriginに当てはまりますO

T(-v)S(-s)T(p)R(-r)T(-p)O = T(-v')S(-s)R(-r)O

原点をスケーリングおよび回転すると、原点が得られます。したがって、次のようになります。

T(-v)S(-s)T(p)R(-r)(-p) = -v'

v'は、変換をSQT形式で保存できる新しい変換ベクトルです。計算を単純化することはおそらく可能です。ただし、少なくとも必要なストレージは増加しません。


説明してくれてありがとう。ところで、SQT表現のトリックについてもっと読むことができるリソースを知っていますか?
パチャンガ

私が間違っている場合は修正してくださいが、別の解決策はQuaternionを通常どおり保存し、任意の点/軸の周りの変換を考慮する必要がある場合は、これに含まれるQ行列を構築し、単純に変換ベクトルを抽出しますこの行列(通常は最後の列)からオブジェクトのTranslationベクトルに追加し、一時的な行列を破棄します。
ジョンベーカーズ

15

回転行列の導出に使用される標準的な回転式はすべて、原点を中心とした回転用です。代わりに特定の点を中心にその回転を適用したい場合は、最初に原点をオフセットする必要があります-または、同等に、オブジェクトを移動して、回転させたい点が原点に来るようにします。

最初に2Dのケースを検討してください。これは、2Dのケースがより単純であり、技術が拡張されるためです。原点を中心とする幅2の立方体があり、その中心を中心に45度回転させたい場合、2D回転行列の簡単な適用になります。

ただし、代わりに右上隅(にある1,1)を中心に回転させたい場合は、最初にその角が原点になるように移動する必要があります。これは、の翻訳で達成できます-1,-1。その後、以前と同じようにオブジェクトを回転できますが、(byで1,1)平行移動してこれをフォローアップする必要があります。したがって、一般に、約点のR回転の回転行列を実現するには、次のようにします。rP

R = translate(-P) * rotate(r) * translate(P)

ここでtranslateおよびrotateは、それぞれ標準的な平行移動/回転行列です。偶然にも、これは3Dに簡単にスケーリングしますが、回転にも軸を指定する必要があることを除いて、標準のX、Y、またはZ軸回転行列を常に選択できますが、それは鈍いでしょう。任意の軸角度回転行列を使用する必要があります。Rしたがって、最終的な3Dは次のとおりです。

R = translate(-P) * rotate(a,r) * translate(P)

ここaで、回転軸を表す単位ベクトルでありP、回転点を表すモデル空間の3D点になります。

たまたま四元数マトリックス表現に変換たりマトリックス表現から変換たりできるので、必要に応じて連結をその方法で行うことができます。または、すべてを行列のままにしておくこともできます(クォータニオンには、適切な方法で補間するのが簡単になるなどの素晴らしい利点がありますが、必要かどうかはあなた次第です)。

また:

そのため、尾がローカルの原点にないベクトルを中心に回転するように視覚化しています。

厳密に言えば、ベクトルは原点からの変位と見なして位置を表すために使用できますが、ベクトルには位置自体がないため、そのように視覚化することは少し珍しいです。


ありがとう、これはいい返事です。それは私のシステムの制約に適合しません。「これらの制約を考慮してこれを行うことは可能ですか?」という質問に含めるべきでしたが、答えはそうではないと思います。これには2つの翻訳が必要で、1つしか提供しないからです。これは、アフィン変換の表現としてのSQTの使用の避けられない欠点ですか?
-notlesh

制約内に完全に収まります。マトリックスR(translate-rotate-translate-backとして生成)は、回転マトリックスです。「SQT」システムでQをRに置き換えると、より一般的なscale-rotate-translateパラダイムが完成します。この最後の移動は、目的の回転を生成するために行われる2つの中間移動とは無関係です。

四元数を行列に置き換えることを提案していますか?これはオブジェクトごとにさらに12バイトです(4x3マトリックスとして保存する場合は8バイト)!しかし、私は楽観主義者を黙らせ、これに旋風を巻きます。(実際には、おそらくフットプリントが2kb増加することもありません...)ご回答いただきありがとうございます。
-notlesh

また、それらの間で変換して、回転四元数をそのように構築し、既存のシステムに再び接続することもできます。

1
@SamHocevar:または、それらの任意の組み合わせを単一のネジとして表現できます。
マーティン・ソイカ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.