質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

Q&A

解決済

1回答

2204閲覧

回転アニメーションで遠回り方向に回すためには?

b7n

総合スコア30

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

0グッド

0クリップ

投稿2016/12/09 11:52

編集2016/12/10 16:25

3D空間に画像を配置するプログラムを作っています。
ユーザーは、X軸、Y軸、Z軸の中から、好きな軸を好きな順序で選び、前のフレームとの角度の差を指定して、選んだ軸と角度を組み合わせて画像をワールドの軸で回転することができます。

ここでこのようにクォータニオンを使うとスムーズに回転できます。
この例は、X軸を中心に90°固定、Y軸を中心に45°から1回転90°まで回転させようとしています。

java

1import javax.vecmath.AxisAngle4f; 2import javax.vecmath.Quat4f;

java

1public static Quat4f toQuat(final AxisAngle4f axis) { 2 final Quat4f q = new Quat4f(); 3 q.set(axis); 4 return q; 5}

java

1Quat4f a; 2Quat4f b; 3 4{ 5 a = new Quat4f(0, 0, 0, 1); // 例としてX軸を中心に90°傾けてY軸を中心に45°傾けてみた「a」 6 a.mul(toQuat(new AxisAngle4f((float) Math.toRadians(90), 1, 0, 0))); 7 a.mul(toQuat(new AxisAngle4f((float) Math.toRadians(45), 0, 1, 0))); 8 9 b = new Quat4f(0, 0, 0, 1); // 例としてX軸を中心に90°傾けてY軸を中心に1回転と90°傾けてみた「b」 10 b.mul(toQuat(new AxisAngle4f((float) Math.toRadians(90), 1, 0, 0))); 11 b.mul(toQuat(new AxisAngle4f((float) Math.toRadians(360+90), 0, 1, 0))); 12} 13 14// このメソッドのpercentを0~1まで動かす 15public Quat4f getAnimation(float percent) { 16 Quat4f c = new Quat4f(); 17 c.interpolate(a, b, percent); 18 return c; 19}

しかし、実際には45°しか回転しません。
NG例
これは180°以上回転してしまうと、interpolateしたときにより距離の短い方向に補完されてしまうことが原因だと考えています。

この例の場合は以下のように、45°から405°に変化させるので一回転と45°回転してほしいわけです。要するに今回は遠回りしてほしいわけです。
OK例

どのようにすれば半回転以上のキーフレームによってアニメーションさせることができるでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

以前Quaternionの解説をよんで自分なりに「こうなっているんじゃないか」と理解したつもりの内容で(推測で)書いてます。間違いがあったらご指摘いただければと思います。

Quaternionの性質から任意の2つの補完は球面上の2点の最短距離に対する補完として計算されると思います。

b.mul(toQuat(new AxisAngle4f((float) Math.toRadians(360+90), 0, 1, 0)));
b.mul(toQuat(new AxisAngle4f((float) Math.toRadians(90), 0, 1, 0)));
多分、上の2つのケースではbの値は(計算誤差を除き)等しくなるのではないでしょうか。

対処方法ですが少なくとも期待通りのパスを通過させるためには補完する2つのQuaternionはパスに沿って180度未満の回転角となってないといけないと思いますので

  1. interpolateの媒介変数を1.0より大きい数値まで用いる

interpolateの仕様を正確にわかってないので使えるかどうか自信なしです。a,bの角度差が90度だとして、0~4.0まで変化させると1回転してくれたりしないでしょうか?
2. 複数のキーフレームを設定し媒介変数の範囲によって異なるQuaternionを選び補完する
望むパスを通過するような180度未満のQuaternionを複数個用意し媒介変数の範囲によって補完する対象のQuaternionを切り替えます。こちらの方は確実にできると思います。


追記:キーフレームの分割について
X,Y,Z軸それぞれの回転角度tx1,ty1,tz1とtx2,ty2,tz2のような形で初期状態と終了状態を指定するという考え方だと「実際に何回転させたいのか」がユーザにとって直感的にわかりにくいと思います。例えば、それぞれをdegree単位で0,0,0->360,360,360と指定したとして実際には何回転させたいのか自分には即座にピンときません。

それよりもQuaternionの考え方に従い「初期位置へQIで変換後、回転軸ax,ay,az(単位ベクトル)の周りにωだけ回転させるQr(ω)を施した位置が最終位置」という指定にしたほうが自然であるように思います。そういうやりかたにするとQr(ω)=(cos(ω/2),ax,ay,az)として決まりますしωが回転角そのものなのでキーフレーム間の回転をπ未満に抑えるためのキーフレームの分割数Dはceiling(ω/(π-ε))とすればよさそうです(εは理論上は0<ε<πであるような任意の値ということになりますが計算誤差を考えるとπ/4~π/2ぐらいがいいのかも知れません)。
キーフレーム#を初期状態=0、終了状態=Dとすると、各キーフレームの変換Q(i)は
Q(i)=QI・Qr(i・ω/D)
で計算できると思います。

投稿2016/12/09 12:53

編集2016/12/10 18:52
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

b7n

2016/12/10 16:23

ユーザーは、X軸、Y軸、Z軸の中から、好きな軸を好きな順序で選び、角度を指定するので、そのわからない角度から、どのように①1.0より大きい数値を算出するか、②複数のキーフレームを決定すればいいのかがわかりません。ユーザーには差分を指定してもらうので、その差分からそれらの値を算出できればと思います。どのようにすれば180度以上スムーズに回転させられるのでしょうか。
b7n

2016/12/12 14:38 編集

>それよりもQuaternionの考え方に従い そうですね。スムーズに回転する方法をいろいろ試しましたが、やはりXYZ軸回転の指定方法に問題があるようです。 ここはきっぱりとあきらめて軸指定と回転を取り入れてみようと思います。
KSwordOfHaste

2016/12/12 15:30

回答に書くかどうか迷ったのですが、X,Y,Z軸の回転角で初期・終了位置を指定させた上で回転させたい範囲を2Nπ<ω<(2N+1)π{Nは整数}として別途指定させるという方法も(計算は多少面倒になりますが)面白いと思いました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問