HDS#05 Vector3型の演算その3:方向

 

こんにちは、開発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型の持っている定数XAxisYAxisZAxisです。

これらはそれぞれ、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(木)、ご期待ください。