こんにちは、開発Gの杉原です。
最近、暖かい日はほんと暖かいですね。
「桜が咲いてる」とか言われ、「いやいや、まだ早いでしょ」とか言いながら指し示すほうを見たら、本当に咲いててびっくりしました。
さて【How to Demo3D Scripting】の第五回は「Vector3型の演算その3:方向」をお送りします。
Vector3型では次のように「方向」を取得することができます。
var loc = new Vector3(2, 3, 4); var normal = Vector3.Normalize(loc); print(normal); // X:0.3713907 Y:0.557086 Z:0.7427813
Vector3 loc = new Vector3(2, 3, 4); Vector3 normal = Vector3.Normalize(loc); print(normal.ToString()); // X:0.3713907 Y:0.557086 Z:0.7427813
この「方向」として取得された値、なんだかよくわからない値ですね。
これがどんな値なのかがよくわかる計算を紹介します。
var loc = new Vector3(2, 3, 4); // 元の座標 var len = loc.Length(); // 距離 var normal = Vector3.Normalize(loc); // 方向 var p = normal * len; print(p); // X:2 Y:3 Z:4
Vector3 loc = new Vector3(2, 3, 4); // 元の座標 double len = loc.Length; // 距離 Vector3 normal = Vector3.Normalize(loc); // 方向 Vector3 p = normal * len; print(p.ToString()); // X:2 Y:3 Z:4
Vector3型の値の「距離」と「方向」を取得し、「方向」に対して「距離」分のスカラー倍を取ると、なんと元の座標が取得されるではありませんか。
ということは、この「方向」という値に、進みたい「距離」を与えることで、目的の「座標」が得られるというわけです。
で、これはあくまで「ある1点の、原点から見た方向」となります。
先の図のように、「点Aから見た点Bの方向」を求めたい場合はどうするのかというと、前回の「距離」と同じ考え方をすればいいわけです。
// 2点の定義 var loc1 = new Vector3(2, 3, 4); var loc2 = new Vector3(4, 5, 6); // loc1が原点になるよう補正 var offset = loc2 - loc1; // 「loc2.Subtruct(loc1)」だとloc2を書き換えるので注意。第3回参照。 // 方向を算出 var normal = Vector3.Normalize(offset); print(normal); // X:0.5773503 Y:0.5773503 Z:0.5773503
// 2点の定義 Vector3 loc1 = new Vector3(2, 3, 4); Vector3 loc2 = new Vector3(4, 5, 6); // loc1が原点になるよう補正 Vector3 offset = loc2 - loc1; // 「loc2.Subtruct(loc1)」だとloc2を書き換えるので注意。第3回参照。 // 方向を算出 Vector3 normal = Vector3.Normalize(offset); print(normal.ToString()); // X:0.5773503 Y:0.5773503 Z:0.5773503
これで、ある点Aから見た、別な点Bの方向がわかりました。
さてこの「方向」、なかなか使う機会がない気がしつつも、いろんなところで登場します。
まず、Vector3型の持っている定数XAxis、YAxis、ZAxisです。
これらはそれぞれ、X軸、Y軸、Z軸の「方向」を表す値を取得できます。
例えばこれを使って、「実行時にY軸方向に5m移動する」処理を作成してみます。
function Box2_OnInitialize( sender : Demo3D.Visuals.BoxVisual ) { var offset = Vector3.YAxis * 5; // Y方向に5m移動したオフセット位置 var target = sender.WorldLocation + offset; // オフセット位置分移動した座標 sender.MoveTo(target, 1); // 1m/sで移動 }
[Auto] void OnInitialize(Visual sender) { Vector3 offset = Vector3.YAxis * 5; // Y方向に5m移動したオフセット位置 Vector3 target = sender.WorldLocation + offset; // オフセット位置分移動した座標 sender.MoveTo(target, 1); // 1m/sで移動 }
実行すると次のようになりました。
この計算では「ワールド座標のY軸方向」に向けて移動をしていました。
上下の移動はだいたいワールド座標でいいと思うのですが、Visualから見て「前」に進みたいといったとき、その「前」がX軸なのかZ軸なのかがわかりません。
もしかすると、斜めを向いていて、X軸にもZ軸にも沿っていないかもしれません。
そこで、Visualの持つメソッドTransfromToWorldNormalを使用します。
これはVisualから見た方向を、ワールド座標での方向に置き換えることができるメソッドです。
「前」というのがZ軸だとして処理を作成してみます。
function Box2_OnInitialize( sender : Demo3D.Visuals.BoxVisual ) { var worldNormal = sender.TransformToWorldNormal(Vector3.ZAxis); // ローカルZ方向をワールド系に変換 var offset = worldNormal * 5; // ローカルZ方向に5m移動したオフセット位置 var target = sender.WorldLocation + offset; // オフセット位置分移動した座標 sender.MoveTo(target, 1); // 1m/sで移動 }
[Auto] void OnInitialize(Visual sender) { Vector3 worldNormal = sender.TransformToWorldNormal(Vector3.ZAxis); // ローカルZ方向をワールド系に変換 Vector3 offset = worldNormal * 5; // ローカルZ方向に5m移動したオフセット位置 Vector3 target = sender.WorldLocation + offset; // オフセット位置分移動した座標 sender.MoveTo(target, 1); // 1m/sで移動 }
Visualを斜めにして実行してみると、それぞれから見たZ軸方向に移動することが確認できます。
このように、なかなか使いどころがあるようなないような、微妙な内容ではあるのですが、いざ必要になったときに「Normalって何」みたいにならないようにはしておきたい、そんな感じですね。
次回の【How to Demo3D Scripting】は「WorldLocationの罠」です。なんかタイトルの趣が違うような?
更新は3/29(木)、ご期待ください。
コメントをお書きください