前回の続きです。
初心者用フライスルーカメラの基礎の基礎(超入門編)ってことで。
前回同様、知ってるよー、興味無いって方はスルーして下さいね。
又、墓穴を掘ってるかもしれません、ご指摘ご指南あらばお願いします。
珍しく連載的になった「Vectorって何じゃい」も取り敢えず今回で終了します。
って何人の方に読んで頂いたかはともかく、ここまで来ればもっと優秀なサンプルがありますし、数学嫌いの限界か?サンプルは最後に紹介します。
■まずは前回のおまけ的一例からです。
ghostさんに
御指南を受け早速コード変更してみる。
おっ!ちょっとワンパターンかなと思っていたランダムカメラも結構いろんなアングルになりヨシヨシ。広大なレイアウトになる程、いがいなアングルを発見できるかもしれない。なんせ皆様のレイアウトプレーヤですから〜。まともなレイアウトは未だに1つも完成せず・・・無念。
余談:
だがしかし1、細かい検証はしていないが、set xx, 0.0 とか setf xx,0 と誤って命令した場合 set か setf なのかで変数の属性が決まるようである。ぶち込む値は関係ないようだ。
だがしかし2、おっ!結構いいじゃんって思ったカメラアングルも、運転を終了して再度起動すると同じパターンでアングルが推移する。要するに乱数生成のパターンが常に同じってことであろう。時間等を使って生成パターンを変えられればいいのにな〜。
■今回の目的はある1点を中心にカメラを回転させてみようです。
今回も既にやってきた内容は細かく書きませんので・・・。前回以前をご参照下さい。
回転となると三角関数が出てきます。中学生・・・いや高校の数Tだったか?
でも分かる用に極力簡単な形で進めてみます。
sin cos を使いますが、(おー記号を見ただけでイヤって人も多いかもしれませんが、実は書いてる人間もイヤ(笑))
難しい理論はさておき、sin cos を使えば簡単に数値を導き出してくれる物って理解で進めましょう。有難いことにVRMにもちゃんとsin cos が用意されています。

<まずは三角関数の図>
うわーと思った人、簡単に考えましょう。本来数学って楽をする為のもですから。
教科書と違って違和感を感じるかもしれません。XとYではなくXとZで、しかもZ軸に関しては+方向が反対です。
これはVRMの仕様(3D系は全般的にそーなのかもしれませんが)上がそーなっているんで、そーいうもんだと理解しておきましょう。
まずは三角関数の図ですが、数学の講義をしようなどと思っているわけではありません。(できんし!)公式のうように暗記すればよし。
但し高度(VRMではY座標)は固定値として平面的に考えます。
半径を1とした場合、X方向の移動比率はcos(角度)で求められます。
図の場合30度の例ですが、半径:赤線の長さ=1:0.866位(√3/2)ですが、授業の様に自分で計算する必要はありません。
VRMの cos(角度)で0.866位を教えてくれます。
実際にはラジアンという単位が使われているので
deg2rad ラジアン格納変数、角度 <- 角度をラジアンの単位に変換
cos(ラジアン格納変数) となりますが、定型式と思えば難のことはない。
同様にZ方向の移動量はsin(角度)で求められます。
図の場合、半径:青線の長さ=1:0.5(1/2)です。
X方向同様にVRMでは
deg2rad ラジアン格納変数、角度
sin(ラジアン格納変数) となります。
sin も cos も半径は1としての値ですので、これに実際のカメラと目標点の距離を掛ければ赤線と青線の移動量が計算できます。(距離に関数値を掛けた方が精度は高くなると思われますけど、ここでは捨て置きます)
もちろん90度を越えた場合、各象限に応じてXとZが−なのか+なのかもsin cos の関数で教えてくれますので意識する必要はありません。
そして、大事なことは、この円では中心をX=0 Z=0としています。
レイアウト上(基本は)は左上がX=0 Z=0 なので、円の中心がレイアウト上のXとZではどの位置なのか(円の原点の位置=レイアウト上のどの位置なのかを基準点と命名しておきます)を足しこむ必要があります。
余談:
ラジアンが世界標準単位だったと思いますが、ラジアンとは円周に対して半径の長さを基準にした角度です?(弧度)。1ラジアンは約57度位で、360度=2πラジアンと言えば数学嫌いでもピンとくるのでは。
では全文を書いておきます。(実用性はありませんけどね)
Var pvVecCamera //視点Vector
Var pvVecAt //目標点Vector
Var pvAtPosX //目標点X Vectorではないよ
Var pvAtPosZ //目標点Z Vectorではないよ
Var pvAtPosY //目標点Y Vectorではないよ
Var eidChgPosKey
Var pvR
setf pvR, 250.0 //起動時の目標点迄の距離(半径・斜辺)
Var pvST
setf pvST, 0 //起動時の目標点に対するカメラ角度
//カメラ位置変更キー設定
SetEventKey this, fncChgPos, eidChgPosKey, a
SetVectorZero pvVecCamera // <- pvVecCamera に(0,0,0)を一発でセット
//カメラ位置Vector変数セット 変数の中身の推移
SetVectorX pvVecCamera,500.0 // <- pvVecCamera (500,0.0,0)
SetVectorY pvVecCamera,100.0 // <- pvVecCamera (500,100,0)
SetVectorZ pvVecCamera,100.0 // <- pvVecCamera (500,100,300)
//カメラ位置Vector変数セット 変数の中身の推移
SetVectorZero pvVecAt // <- pvVecAt に(0,0,0)を一発でセット
SetVectorX pvVecAt,250.0 // <- pvVecAt (250,0,0)
SetVectorY pvVecAt,60.0 // <- pvVecAt (250,60,0)
SetVectorZ pvVecAt,100.0 // <- pvVecAt (250,60,100)
//カメラ位置を指定
SetFlyCameraPos pvVecCamera, pvVecAt
///////////////////////////////////////////////
//カメラ位置変更
BeginFunc fncChgPos
Var vWkRad <- 度からラジアンに変換した値確保用
Var vWkX <- 計算用
Var vWkZ <- 計算用
Var vWkY <- 計算用
Var vWk <- 計算用
//フライカメラ位置取得
GetFlyCameraPos pvVecCamera, pvVecAt
//回転
GetVectorX pvAtPosX,pvVecAt <-基準点のX座標確保
GetVectorZ pvAtPosZ,pvVecAt <-基準点のZ座標確保
GetVectorY pvAtPosY,pvVecAt <-基準点のY座標確保
add pvST,30.0 <-1度aキーを押すごとに変動させる角度
if>= pvST,360.0 <-1週したら0度に戻しましょう
setf pvST,0.0
endif
DrawVar pvST <-デバック用(現在の角度を表示)
deg2rad vWkRad, pvST <-角度を計算用のラジアンに変換してるだけ
cos vWkX, vWkRad <-X軸の移動量計算
sin vWkZ, vWkRad <-Z軸の移動量計算
mul vWkX, pvR <-実際の半径を掛けて赤線の長さを計算
mul vWkZ, pvR <-実際の半径を掛けて青線の長さを計算
add vWkX,pvAtPosX <-レイアウトの基準点を加算
add vWkZ,pvAtPosZ <-レイアウトの基準点を加算
SetVectorX pvVecCamera,vWkX <-カメラ位置のX座標をワークにセット
SetVectorZ pvVecCamera,vWkZ <-カメラ位置のZ座標をワークにセット
//フライカメラ位置をセット
SetFlyCameraPos pvVecCamera, pvVecAt <-カメラに位置を教えます
EndFunc
逆にカメラ位置を固定にして目標点を移動させれば昨日登場のfoxさんとZioさんのコラボの
PANORAMAと言うコレみたいなカメラ視線を作れます。
余談:
実際には現状のカメラ位置と目標点から現在角度を算出して次に移動する場所を指定しないとNGなんですが。
■さて最後に次なるスキルアップへのご紹介。
ご存知ghostさんによる
基礎講座的な
コレ
第1弾と思われる「水平楕円軌道フライスルーカメラ」の
コレ
第2弾と思われる「まさに!フライスルーカメラ」の
コレ
等〃他にもあるかもしれません。
近ちゃんさんによる外積を使ったおもしろい記事
「C57-1を真下から見上げた図(まとめ)」の
コレ
長いお付き合い有難うございました。
明日っていうより今日からまた慌しくなるtettaでした。次回はいつ更新することやら?