ぱらなのブログ

Siv3Dで3Dゲームを作ってみる 2 Quaternion

回転させたい

PlaneのコンストラクタにQuaternionというのがあるので、回転させるにはこいつを使えばいいんだなというのがなんとなくわかります。
毎回asMeshを使って回転させてもいいのですが、コンストラクタでスマートに回した方がメソッドチェーンよりコストも低いでしょうし、回転した状態だとtranslatedでの移動が回転した状態で行われたりしてrotatedとtranslatedの順番次第で意図しない挙動を引き起こしそうなので(まあ実際それっぽい挙動が起きたのでこうして記事を書いているんですが…)Quaternionについて軽く把握しておく必要がありそうです。

ところで、2Dで座標操作系だとTransformer2Dを用いることがあります。それにはメンバ関数にrotateなどが用意されており直感的に操作することができたりします。

恐らくQuaternionにも用意されているので、まずはメンバ関数を見てみましょう。

f:id:Para7:20181001000604p:plain

…?

くおーたにおんってなに?

行列演算で四元数ってやつらしいです。名前は聞いたことありますが当然なんのことだかわかりません。

なのでググります。

XYX軸周りの回転とは

ロールがx軸、ピッチがY軸、ヨーがz軸を中心に回転するらしいです、なるほど。ところでどの向きがどの軸なんでしょうか?

前回に引き続き座標テスト用のコードを作りました。前回は急いで記事を作ってたのでコードもだいぶ粗末なものでしたが、今回はけっこうわかりやすくなったのではないでしょうか。

f:id:Para7:20181001022721p:plain

# include <Siv3D.hpp>

void Main()
{
    Window::Resize(1000, 750);

    GUI gui(GUIStyle::Default);
    gui.setTitle(L"操作");
    gui.addln(GUIText::Create(L"Vec3"));

    gui.add(L"x", GUISlider::Create(-30, 30, 0, 150));
    gui.addln(GUIText::Create(L"x"));
    gui.add(L"y", GUISlider::Create(-30, 30, 0, 150));
    gui.addln(GUIText::Create(L"y"));
    gui.add(L"z", GUISlider::Create(-30, 30, 0, 150));
    gui.addln(GUIText::Create(L"z"));

    gui.addln(GUIText::Create(L"Quaternion"));
    gui.add(L"roll", GUISlider::Create(-180_deg, 180_deg, 0, 150)); 
    gui.addln(GUIText::Create(L"roll"));
    gui.add(L"pitch", GUISlider::Create(-180_deg, 180_deg, 0, 150)); 
    gui.addln(GUIText::Create(L"pitch"));
    gui.add(L"yaw", GUISlider::Create(-180_deg, 180_deg, 0, 150));
    gui.addln(GUIText::Create(L"yaw"));

    while (System::Update())
	{
        Plane(Vec3(gui.slider(L"x").value, gui.slider(L"y").value, gui.slider(L"z").value + 30), 50, Quaternion::Identity().rotateRollPitchYaw(gui.slider(L"roll").value, gui.slider(L"pitch").value, gui.slider(L"yaw").value)).draw(Palette::Lightgreen);
    }
}

見やすくするためにウィンドウがそこそこ大きく出るようにしてあるので小さい画面で作業している人は調整してください。

pitchで90°回転させると奥の壁になるみたいですね。
前回言ってませんでしたが、3Dだとかなり遠くまで見えてしまうのでまずは範囲を狭めるために部屋みたいな空間を作ろうと思っています。

しかし慣れない3D空間での操作なのでしょっちゅう間違えます。何度も確認しながら調整することになりそうです。

前回から内容も全然進んでませんが、連続した技術記事を書いたことがないのでどうやって書いていこうか迷っているところです。とはいえ書くことが一番大事だと思っているので、時間をかけて丁寧に文章を書くよりは、こだわらずラフにアウトプットしていきたいです。私も限られた時間を執筆より勉強に割きたいですし。ところでこんな雑談みたいなことをここに書いてしまっていいのか…?

とりあえず、次回に続くといいな。