HDS#03 Vector3型の演算その1:基本の演算

 

こんにちは、開発Gの杉原です。

 

ブログの管理画面で自分の記事が探しやすくなるように「HDS」とかつけたんですが、カテゴリ別でフィルタリングできることに今になって気付いたこの頃。 

もうこれつけるのやめようかなとか思っていたら、知らないうちにカテゴリに「HDS」とかつけられてる、どういうこと!?

 

そんな【How to Demo3D Scripting】の第三回は「Vector3型の演算その1:基本の演算」をお送りします。

早くも前後篇ですらなくなった。

 

ある日のこと。

「Vector3型のXYZをまとめて加算できるような関数とかってないですか?」

という質問をうけました。

 

どういうことかというと、たとえば何かしらのVisualを

・X方向に3m

・Y方向に1m

・Z方向に6.5m

移動させた位置を取得したいのだけれど、WorldLocationプロパティから取得したVector3型の値に対して、1つずつX、Y、Zを修正するのがめんどくさい。

var loc = new Vector3(5, 5, 5);
loc.X = loc.X + 3;
loc.Y = loc.Y + 1;
loc.Z = loc.Z + 6.5;
print(loc); // X:8 Y:6 Z:11.5
Vector3 loc = new Vector3(5, 5, 5);
loc.X = loc.X + 3;
loc.Y = loc.Y + 1;
loc.Z = loc.Z + 6.5;
print(loc.ToString()); // X:8 Y:6 Z:11.5

確かに、位置座標をいくつも計算するような処理を過去に見た覚えがあるのですが、このX、Y、Zの加算がずらっと並んでいて、なんかちょっと冗長というか、少なくともすっきりはしていない印象がありました。

 

ということで、これをすっきりさせてみます。

var loc = new Vector3(5, 5, 5);
var offset = new Vector3(3, 1, 6.5);
loc = loc + offset;
print(loc); // X:8 Y:6 Z:11.5
Vector3 loc = new Vector3(5, 5, 5);
Vector3 offset = new Vector3(3, 1, 6.5);
loc = loc + offset;
print(loc.ToString()); // X:8 Y:6 Z:11.5

1行減っただけでしたね。しかも変数1つ増えてるし。

まあとにかく、このコードの是非はともかくとして、このようにX、Y、Z個別に加算しなくても、Vector3型の変数同士を加算することで、同じ結果を得ることができます。

 

減算がしたいときも同様の方法で計算が可能ですが、それ以外にも、offset変数のX、Y、Zの値を負数にして加算することでも減算できます。

X、Y、Zそれぞれについて加算するもの、減算するものが混ざっていることもあるので、基本的にはVector3型の変数同士は加算するようにしたほうがいいかと思います。

 

var loc = new Vector3(5, 5, 5);

// Vector3型の減算
var offset1 = new Vector3(3, 1, 6.5);
loc = loc - offset1;
print(loc); // X:2 Y:4 Z:-1.5

// 負数を加算
var offset2 = new Vector3(-4, -5, -6);
loc = loc + offset2;
print(loc); // X:-2 Y:-1 Z:-7.5

// 軸によって加算するか減算するかが異なる
var offset3 = new Vector3(6, -2, 10);
loc = loc + offset3;
print(loc); // X:4 Y:-3 Z:2.5
Vector3 loc = new Vector3(5, 5, 5);

// Vector3型の減算
Vector3 offset1 = new Vector3(3, 1, 6.5);
loc = loc + offset1;
print(loc.ToString()); // X:2 Y:4 Z:-1.5

// 負数を加算
Vector3 offset2 = new Vector3(-4, -5, -6);
loc = loc + offset2;
print(loc.ToString()); // X:-2 Y:-1 Z:-7.5

// 軸によって加算するか減算するかが異なる
Vector3 offset3 = new Vector3(6, -2, 10);
loc = loc + offset3;
print(loc.ToString()); // X:4 Y:-3 Z:2.5

じゃあ乗算、除算も同じようにできるのかというと、同じにはできません。

 

名前から既に察しているかもしれませんが、Vector3型は3次元ベクトルを扱う型となっています。

3次元ベクトルはその和を取ることができ、その結果は次のようになります。

 

(x1, y1) + (x2, y2) = (x1 + x2, y1 + y2)

 

先ほどのVector3型同士の「+」演算子や「-」演算子を使った加算は、これに則って実装された演算だったわけです。

 

では「*」演算子による演算は実装されていないのかというと、次のような「スカラー倍」の演算が実装されています。

 

 

var offset = new Vector3(2, 3, 5);
offset = loc * 1.5;
print(offset); // X:3 Y:4.5 Z:7.5
Vector3 offset = new Vector3(2, 3, 5);
offset = offset * 1.5;
print(offset.ToString()); // X:3 Y:4.5 Z:7.5

Demo3DではVector3型をVisualの「座標」として利用することが大多数かと思います。

そのため、なかなかこのスカラー倍を使う機会はないのかもしれません。

 

しかし、加算で位置調整するときのオフセットのような値に対して、その値を2倍にするといったときにこれが役に立ちます。

 

残った「/」演算子はというと、演算が実装されていないため、どのような値で演算しても非数値として返ってきます。

さて、ここまで演算子「+」「-」「*」を使ってきましたが、実はこれらの計算は関数を使うことでも同様に行うことができます。

// 加算その1
var loc1 = new Vector3(5, 5, 5);
var offset = new Vector3(3, 1, 6.5);
loc1.Add(offset); //「loc1 = loc1 + offset」と同義
print(loc1); // X:5 Y:4 Z:10.5

// 加算その2
var loc2 = new Vector3(5, 5, 5);
loc2 = Vector3.Add(loc2, offset); // こちらも同じ
print(loc2); // X:8 Y:6 Z:11.5

// 減算その1
var loc3 = new Vector3(5, 5, 5);
loc3.Subtract(offset); //「loc3 = loc3 - offset」と同義
print(loc); // X:2 Y:4 Z:-1.5

// 減算その2
var loc4 = new Vector3(5, 5, 5);
loc4 = Vector3.Subtract(loc4, offset); // こちらも同じ
print(loc); // X:2 Y:4 Z:-1.5

// スカラー倍その1
var offset2 = new Vector3(2, 3, 5);
offset2.Scale(1.5); // 「offset2 = offset2 * 1.5」と同義
print(offset2); // X:3 Y:4.5 Z:7.5

// スカラー倍その2
var offset3 = new Vector3(2, 3, 5);
offset3 = Vector3.Scale(offset3, 1.5); // こちらも同じ
print(offset3); // X:3 Y:4.5 Z:7.5
// 加算その1
Vector3 loc1 = new Vector3(5, 5, 5);
Vector3 offset = new Vector3(3, 1, 6.5);
loc1.Add(offset); //「loc1 = loc1 + offset」と同義
print(loc1.ToString()); // X:5 Y:4 Z:10.5

// 加算その2
Vector3 loc2 = new Vector3(5, 5, 5);
loc2 = Vector3.Add(loc2, offset); // こちらも同じ
print(loc2.ToString()); // X:8 Y:6 Z:11.5

// 減算その1
Vector3 loc3 = new Vector3(5, 5, 5);
loc3.Subtract(offset); //「loc3 = loc3 - offset」と同義
print(loc.ToString()); // X:2 Y:4 Z:-1.5

// 減算その2
Vector3 loc4 = new Vector3(5, 5, 5);
loc4 = Vector3.Subtract(loc4, offset); // こちらも同じ
print(loc.ToString()); // X:2 Y:4 Z:-1.5

// スカラー倍その1
Vector3 offset2 = new Vector3(2, 3, 5);
offset2.Scale(1.5); // 「offset2 = offset2 * 1.5」と同義
print(offset2.ToString()); // X:3 Y:4.5 Z:7.5

// スカラー倍その2
Vector3 offset3 = new Vector3(2, 3, 5);
offset3 = Vector3.Scale(offset3, 1.5); // こちらも同じ
print(offset3.ToString()); // X:3 Y:4.5 Z:7.5

 関数を使う場合は、Vector3型の変数から呼ぶ場合(上記コードのその1)と、Vector3型から直接呼ぶ場合(その2)との2種類の使い方があります。

変数から呼び出した場合は、その変数に対して計算結果が直接設定されます。

上記のコード例のように、値を書き換えるための演算であればこちらの計算の方が目的が分かりやすくていいかと思います。

しかし、計算に使った値を書き変えたくない場合もあるかと思いますので、この場合は演算子を使うか、Vector3型から直接関数を呼び出す使い方をしてください。

ここまで紹介したのはVector3型の、ベクトルとしての基本的な演算の仕方となります。

ベクトルといえば、内積や外積なんてのもあって、これらももちろん計算できるようにはなっています。

といっても、なかなか使う機会もない(なかったわけではないですが)ので、そういう演算の紹介は後回しでもいいかなと思っています。

そこで次回はVector3型の関数を使った、そこそこ実用的な演算を紹介したいと思います。


 

次回の【How to Demo3D Scripting】は「Vector3型の演算その2:位置関係」です。

更新は3/15(木)、ご期待ください。