ベクトル演算についてまとめながら、three.jsのベクトルクラスの実装を見ていきたいと思います。
three.jsには2次元ベクトルを表すVector2クラス、3次元ベクトルを表すVector3クラス、4次元ベクトルを表すVector4クラスが存在します。それぞれVector2.js、Vector3.js、Vector4.jsで実装されています。
基本的にはベクトルの演算は次元数によらず同じなので3D CGで最もよく使用する3次元ベクトル(Vector3
)について見ていきます。
three.jsは現時点(2019/11/09)において最新のバージョンであるr110を参考にしています。
ベクトルは特に断りのない限り、列ベクトルです。実数は小文字(e.g. $x$)、ベクトルは上付き矢印(e.g. $\vec{v}$)、行列は大文字(e.g. $M$)、クォータニオンは上付きハット(e.g. $\hat{q}$)で表します。
ベクトルの要素
3次元ベクトルは3つの実数を持つベクトルです。各要素を順に$x$、$y$、$z$で表します。
\vec{v} = \left(\begin{array}{c}x \\ y\\ z \end{array}\right)
Vector3
クラスでは、インスタンス変数x
、y
、z
で各要素を保持します。引数として値が与えられない場合はデフォルト値として0
を設定しています。
function Vector3( x, y, z ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
}
set、setScalarメソッドでVector3
インスタンスの要素を変更できるほか、setX、setY、setZメソッドで一つの要素のみを変更することも可能です。
set: function ( x, y, z ) {
this.x = x;
this.y = y;
this.z = z;
return this;
},
setScalar: function ( scalar ) {
this.x = scalar;
this.y = scalar;
this.z = scalar;
return this;
},
setX: function ( x ) {
this.x = x;
return this;
},
setY: function ( y ) {
this.y = y;
return this;
},
setZ: function ( z ) {
this.z = z;
return this;
},
そのほかにインデックス値で各要素を取得・設定できるgetComponentメソッドとsetCompoenntメソッドがVector3
クラスには存在しています。
setComponent: function ( index, value ) {
switch ( index ) {
case 0: this.x = value; break;
case 1: this.y = value; break;
case 2: this.z = value; break;
default: throw new Error( 'index is out of range: ' + index );
}
return this;
},
getComponent: function ( index ) {
switch ( index ) {
case 0: return this.x;
case 1: return this.y;
case 2: return this.z;
default: throw new Error( 'index is out of range: ' + index );
}
},
cloneメソッドで同じ値を持つ新たなVector3
インスタンスを生成でき、copyメソッドで引数に与えたVector3
インスタンスと同じ値を持つようにすることができます。
clone: function () {
return new this.constructor( this.x, this.y, this.z );
},
copy: function ( v ) {
this.x = v.x;
this.y = v.y;
this.z = v.z;
return this;
},
ベクトルの和
2つのベクトルの和は各要素同士の和になります。
\vec{v_1} + \vec{v_2} =
\left(\begin{array}{c}x_1 \\ y_1\\ z_1 \end{array}\right) +
\left(\begin{array}{c}x_2 \\ y_2\\ z_2 \end{array}\right) =
\left(\begin{array}{c}x_1 + x_2 \\ y_1 + y_2\\ z_1 + z_2 \end{array}\right)
Vector3
クラスでは2つのベクトルの和を求めるaddメソッドとaddVectorsメソッドが存在しています。
add: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
return this.addVectors( v, w );
}
this.x += v.x;
this.y += v.y;
this.z += v.z;
return this;
},
addVectors: function ( a, b ) {
this.x = a.x + b.x;
this.y = a.y + b.y;
this.z = a.z + b.z;
return this;
},
ベクトルとスカラーの和は数学的には定義されていませんが、Vector3
にはベクトルの各要素にスカラー値を足すaddScalarメソッドとaddScaledVectorメソッドが利便性のために存在しています。
addScalar: function ( s ) {
this.x += s;
this.y += s;
this.z += s;
return this;
},
addScaledVector: function ( v, s ) {
this.x += v.x * s;
this.y += v.y * s;
this.z += v.z * s;
return this;
},
ベクトルの差
2つのベクトルの差は各要素同士の差になります。
\vec{v_1} - \vec{v_2} =
\left(\begin{array}{c}x_1 \\ y_1\\ z_1 \end{array}\right) -
\left(\begin{array}{c}x_2 \\ y_2\\ z_2 \end{array}\right) =
\left(\begin{array}{c}x_1 - x_2 \\ y_1 - y_2\\ z_1 - z_2 \end{array}\right)
Vector3
には2つのベクトルの差を求めるsubメソッドとsubVectorsメソッドが存在しています。
sub: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
return this.subVectors( v, w );
}
this.x -= v.x;
this.y -= v.y;
this.z -= v.z;
return this;
},
subVectors: function ( a, b ) {
this.x = a.x - b.x;
this.y = a.y - b.y;
this.z = a.z - b.z;
return this;
},
和と同様にベクトルとスカラーの差は数学的に定義されていませんが、Vector3
にはsubScalarメソッドが利便性のために存在しています。
subScalar: function ( s ) {
this.x -= s;
this.y -= s;
this.z -= s;
return this;
},
ベクトルの積
2つのベクトルの積はベクトルの各要素の積になります。
\vec{v_1}\vec{v_2} =
\left(\begin{array}{c}x_1 \\ y_1\\ z_1 \end{array}\right)
\left(\begin{array}{c}x_2 \\ y_2\\ z_2 \end{array}\right) =
\left(\begin{array}{c}x_1x_2 \\ y_1y_2\\ z_1z_2 \end{array}\right)
Vector3
には2つのベクトルの積を求めるmultiplyメソッドと multiplyVectorsメソッドが存在しています。
multiply: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
return this.multiplyVectors( v, w );
}
this.x *= v.x;
this.y *= v.y;
this.z *= v.z;
return this;
},
multiplyVectors: function ( a, b ) {
this.x = a.x * b.x;
this.y = a.y * b.y;
this.z = a.z * b.z;
return this;
},
ベクトルとスカラーの積はベクトルの各要素にスカラーをかけることで求まります。
a\vec{v} =
a\left(\begin{array}{c}x \\ y\\ z \end{array}\right) =
\left(\begin{array}{c}ax \\ ay\\ az \end{array}\right)
Vector3
にはベクトルとスカラーの積を求めるmultiplyScalarメソッドが存在しています。
multiplyScalar: function ( scalar ) {
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
return this;
},
ベクトルの商
2つのベクトルの商はベクトルの各要素の商になります。
\vec{v_1} / \vec{v_2} =
\left(\begin{array}{c}x_1 \\ y_1\\ z_1 \end{array}\right) /
\left(\begin{array}{c}x_2 \\ y_2\\ z_2 \end{array}\right) =
\left(\begin{array}{c}x_1 / x_2 \\ y_1 / y_2\\ z_1 / z_2 \end{array}\right)
Vector3
には2つのベクトルを商を求めるdivideメソッドが存在します。
divide: function ( v ) {
this.x /= v.x;
this.y /= v.y;
this.z /= v.z;
return this;
},
ベクトルとスカラーの商はベクトルの各要素をスカラーで割ることで求まります。
\vec{v} / a =
\left(\begin{array}{c}x \\ y\\ z \end{array}\right) / a =
\left(\begin{array}{c}x / a \\ y / a\\ z / a \end{array}\right)
Vector3
にはベクトルとスカラーの商を求めるdivideScalarメソッドが存在します。
divideScalar: function ( scalar ) {
return this.multiplyScalar( 1 / scalar );
},
逆ベクトル
ベクトル${\vec{v}}$に対して大きさが同じで向きが逆のベクトルを逆ベクトルと呼びます。逆ベクトルは以下のように$-1$を掛けることで求まります。
-\vec{v} = \left(\begin{array}{c}-x \\ -y\\ -z \end{array}\right)
Vector3
ではnegateメソッドで逆ベクトルを求めることができます。
negate: function () {
this.x = - this.x;
this.y = - this.y;
this.z = - this.z;
return this;
},
ベクトルのドット積 (内積)
2つのベクトルのドット積は各要素同士の積の和になります。
\vec{v_1} \cdot \vec{v_2} =
\left(\begin{array}{c}x_1 \\ y_1\\ z_1 \end{array}\right) \cdot
\left(\begin{array}{c}x_2 \\ y_2\\ z_2 \end{array}\right) =
x_1x_2 + y_1y_2 + z_1z_2
Vector3
ではdotメソッドで求めることができます。
dot: function ( v ) {
return this.x * v.x + this.y * v.y + this.z * v.z;
},
3次元ベクトルのクロス積 (外積)
3次元ベクトルのクロス積は以下の方法で求めることができます。
クロス積は3次元ベクトルのみで定義されており、2次元ベクトルや4次元ベクトルには存在ません。
\vec{v_1} \times \vec{v_2} =
\left(\begin{array}{c}x_1 \\ y_1\\ z_1 \end{array}\right) \times
\left(\begin{array}{c}x_2 \\ y_2\\ z_2 \end{array}\right) =
\left(\begin{array}{c}y_1z_2 - z_1y_2 \\ z_1x_2 - x_1z_2\\ x_1y_2 - y_1x_2 \end{array}\right)
Vector3
にはクロス積を求めるcrossメソッドとcrossVectorsメソッドが存在しています。
cross: function ( v, w ) {
if ( w !== undefined ) {
console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
return this.crossVectors( v, w );
}
return this.crossVectors( this, v );
},
crossVectors: function ( a, b ) {
var ax = a.x, ay = a.y, az = a.z;
var bx = b.x, by = b.y, bz = b.z;
this.x = ay * bz - az * by;
this.y = az * bx - ax * bz;
this.z = ax * by - ay * bx;
return this;
},
ベクトルの大きさ
ベクトル$\vec{v}$の大きさ$|\vec{v}|$は以下の式で求めることができます。
|\vec{v}| = \sqrt{xx + yy + zz}
Vector3
ではlengthメソッドで求めることができます。
2つのベクトルの大きさを比較する場合などには平方根を計算する必要がないため、効率化のためにベクトルの大きさの2乗を返すlengthSqメソッドも存在しています。
length: function () {
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
},
lengthSq: function () {
return this.x * this.x + this.y * this.y + this.z * this.z;
},
ベクトルの正規化
ベクトルの向きを変更せずに大きさのみを$1$にすることをベクトルの正規化と呼びます。ベクトル$\vec{v}$を正規化したベクトル$\vec{v_{norm}}$は以下のように求めることができます。
\vec{v_{norm}} = \frac{\vec{v}}{|\vec{v}|}
Vector3
ではnormalizeメソッドで正規化を行うことができます。ゼロ除算が発生しないようにthis.length()
が0
のときは1
で割るようになっています。
normalize: function () {
return this.divideScalar( this.length() || 1 );
},
2つのベクトルの距離
2つのベクトルの距離は2つのベクトルの差の大きさになります。
\vec{v_1} = \left(\begin{array}{c}x_1 \\ y_1\\ z_1 \end{array}\right),
\vec{v_2} = \left(\begin{array}{c}x_2 \\ y_2\\ z_2 \end{array}\right)\\
\vec{v'} = \vec{v_1} - \vec{v_2}\\
d = |\vec{v'}|
Vector3
ではdistanceToメソッドで2つのベクトルの距離を求めることがあります。ベクトルの大きさと同様に平方根を取る必要がない場合があるので、2つのベクトルの距離の2乗を返すdistanceToSquaredも存在しています。
distanceTo: function ( v ) {
return Math.sqrt( this.distanceToSquared( v ) );
},
distanceToSquared: function ( v ) {
var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
return dx * dx + dy * dy + dz * dz;
},
2つのベクトルのなす角
ドット積の定義より2つのベクトルのなす角$\theta$は以下のように求めることができます。
\vec{v_1}\cdot\vec{v_2} = |\vec{v_1}||\vec{v_2}|cos\theta\\
\theta = acos(\frac{\vec{v_1}\cdot\vec{v_2}}{|\vec{v_1}||\vec{v_2}|})
Vector3
ではangleToメソッドが対応しています。
angleTo: function ( v ) {
var denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
if ( denominator === 0 ) console.error( 'THREE.Vector3: angleTo() can\'t handle zero length vectors.' );
var theta = this.dot( v ) / denominator;
// clamp, to handle numerical problems
return Math.acos( _Math.clamp( theta, - 1, 1 ) );
},
ベクトルの正射影
ベクトル$\vec{v_1}$をベクトル$\vec{v_2}$に正射影したベクトル$\vec{v_{proj}}$は以下のように求めることができあます。
\vec{v_{proj}} = \frac{\vec{v_1}\cdot\vec{v_2}}{|\vec{v_2}|}\vec{v_2}
またベクトル$\vec{v}$を法線ベクトル$\vec{n}$を持つ平面に対して正射影する場合には、$\vec{v}$を平面に平行な成分$\vec{v_{\parallel}}$と平面に垂直な成分$\vec{v_{\perp}}$に分けて考えます。まず、$\vec{v}$を$\vec{n}$に正射影することで$\vec{v_{\perp}}$を求め、その後$\vec{v}$から$\vec{v_{\perp}}$を引くことで$\vec{v_{\parallel}}$を求めることができます。
\vec{v} = \vec{v_{\parallel}} + \vec{v_{\perp}}\\
\vec{v_{\perp}} = \frac{\vec{v}\cdot\vec{n}}{|\vec{n}|}\vec{n}\\
\vec{v_{\parallel}} = \vec{v} - \vec{v_{\perp}} = \vec{v} - \frac{\vec{v}\cdot\vec{n}}{|\vec{n}|}\vec{n}
Vector3
ではprojectOnVectorメソッドでベクトルへの正射影を、projectOnPlaneメソッドで平面への正射影を求めることができます。
projectOnVector: function ( v ) {
// v cannot be the zero v
var scalar = v.dot( this ) / v.lengthSq();
return this.copy( v ).multiplyScalar( scalar );
},
projectOnPlane: function ( planeNormal ) {
_vector.copy( this ).projectOnVector( planeNormal );
return this.sub( _vector );
},
反射ベクトル
入射ベクトル$\vec{v}$、法線ベクトル$\vec{n}$としたときに反射ベクトル$\vec{r}$は以下のように求まります。
\vec{r} = \vec{v} - 2(\vec{v}\cdot\vec{n})\vec{n}
Vector3
ではreflectメソッドで自身(this
)を入射ベクトルにしたときの反射ベクトルを求めることができます。
reflect: function ( normal ) {
// reflect incident vector off plane orthogonal to normal
// normal is assumed to have unit length
return this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
},
行列とベクトルの積
3x3行列と3次元列ベクトルの積は以下のようになります。
M\vec{v} =
\left(
\begin{array}{ccc}
e_{11} & e_{12} & e_{13} \\
e_{21} & e_{22} & e_{23} \\
e_{31} & e_{32} & e_{33}
\end{array}
\right)
\left(\begin{array}{c}x \\ y\\ z \end{array}\right) =
\left(\begin{array}{c}
e_{11}x + e_{12}y + e_{13}z\\
e_{21}x + e_{22}y + e_{23}z\\
e_{31}x + e_{32}y + e_{33}z \end{array}\right)
Three.jsではapplyMatrix3メソッドが定義されているほか、最後に正規化を行うtransformDirectionメソッドがあります。
Three.jsの行列は列オーダーなのでm.elements
には$[e_{11}, e_{21}, e_{31}, e_{12}, e_{22}, e_{32}, e_{13}, e_{23}, e_{33}]$という順番で要素が入っていることに注意してください。
applyMatrix3: function ( m ) {
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
return this;
},
transformDirection: function ( m ) {
// input: THREE.Matrix4 affine matrix
// vector interpreted as a direction
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
return this.normalize();
},
4x4行列と3次元ベクトルの積は数学的には定義できませんが、Three.jsには3次元ベクトルを同次座標系に拡張して4x4行列との積を求めるapplyMatrix4メソッドがあります。
具体的には引数として与えられた3次元ベクトルの$w$要素を$1$として4次元ベクトルに拡張して4x4行列との積(次式の$\vec{v'}$)を求めます。その後、各要素を$w$の値で割って3次元ベクトル(次式の$\vec{v''}$)に戻します。
\vec{v'} = \left(\begin{array}{c}x' \\ y'\\ z' \\w' \end{array}\right) = M\vec{v} =
\left(
\begin{array}{ccc}
e_{11} & e_{12} & e_{13} & e_{14} \\
e_{21} & e_{22} & e_{23} & e_{24} \\
e_{31} & e_{32} & e_{33} & e_{34} \\
e_{41} & e_{42} & e_{43} & e_{44} \\
\end{array}
\right)
\left(\begin{array}{c}x \\ y\\ z\\ 1 \end{array}\right) =
\left(\begin{array}{c}
e_{11}x + e_{12}y + e_{13}z + e_{14}\\
e_{21}x + e_{22}y + e_{23}z + e_{24}\\
e_{31}x + e_{32}y + e_{33}z + e_{34}\\
e_{41}x + e_{42}y + e_{43}z + e_{44} \end{array}\right)\\
\vec{v''} = \left(\begin{array}{c}x' / w' \\ y' / w' \\ z' / w' \end{array}\right)
applyMatrix4: function ( m ) {
var x = this.x, y = this.y, z = this.z;
var e = m.elements;
var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
return this;
},
クォータニオンによるベクトルの回転
単位クォータニオンは3次元空間での回転を表すことができます。クォータニオン$\hat{q}$の逆クォータニオンを$\hat{q^{-1}}$とすると$\hat{q}$によるベクトル$\vec{v}$の回転は以下のように表すことができます。ベクトルを一度クォータニオンと見なして演算していることに注意してください。
\vec{v} = \left(\begin{array}{c}x \\ y\\ z \end{array}\right)\\
\hat{v} = (x, y, z, 0)\\
\hat{v'} = (x', y', z', 0) = \hat{q}\hat{v}\hat{q}^{-1}\\
\vec{v'} = \left(\begin{array}{c}x' \\ y'\\ z' \end{array}\right)
2つのクォータニオンの積は以下のようになります。
\hat{p} = (p_x, p_y, p_z, p_w)\\
\hat{q} = (q_x, q_y, q_z, q_w)\\
\hat{p}\hat{q} = \left(\begin{array}{c}
p_wq_x - p_zq_y + p_yq_z + p_xq_w,\\
p_zq_x + p_wq_y - p_xq_z + p_yq_w,\\
p_yq_x + p_xq_y + p_wq_z + p_zq_w,\\
-p_xq_x - p_yq_y - p_zq_z + p_wq_w
\end{array}\right)
Vector3
ではapplyQuaternionメソッドでクォータニオンによりベクトルを回転させることができます。applyEulerメソッドとapplyAxisAngleメソッドも内部的にはapplyQuaternion
メソッドを使用しています。
applyQuaternion: function ( q ) {
var x = this.x, y = this.y, z = this.z;
var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
// calculate quat * vector
var ix = qw * x + qy * z - qz * y;
var iy = qw * y + qz * x - qx * z;
var iz = qw * z + qx * y - qy * x;
var iw = - qx * x - qy * y - qz * z;
// calculate result * inverse quat
this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
return this;
},
applyEuler: function ( euler ) {
if ( ! ( euler && euler.isEuler ) ) {
console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
}
return this.applyQuaternion( _quaternion.setFromEuler( euler ) );
},
applyAxisAngle: function ( axis, angle ) {
return this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );
},
球座標系からの直交座標系への変換
動径$r$と2つの偏角$\phi$、$\theta$で表された球座標を直交座標に変換するには以下のようにします。
\vec{v} = \left(\begin{array}{c}
rsin\phi sin\theta \\
rcos\phi \\
rsin\phi cos\theta \end{array}\right)
Vector3
クラスではsetFromSphericalメソッドとsetFromSphericalCoordsメソッドで球座標から直交座標を求めることができます。
setFromSpherical: function ( s ) {
return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
},
setFromSphericalCoords: function ( radius, phi, theta ) {
var sinPhiRadius = Math.sin( phi ) * radius;
this.x = sinPhiRadius * Math.sin( theta );
this.y = Math.cos( phi ) * radius;
this.z = sinPhiRadius * Math.cos( theta );
return this;
},
円柱座標系から直交座標系への変換
動径$r$、偏角$\theta$でy方向に延びる円柱座標を直交座標に変換するには以下のようにします。
\vec{v} = \left(\begin{array}{c}
rsin\theta \\
y \\
rcos\theta \end{array}\right)
Vector3
ではsetFromCylindricalメソッドとsetFromCylindricalCoordsメソッドで円柱座標から直交座標を求めることができます。
setFromCylindrical: function ( c ) {
return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
},
setFromCylindricalCoords: function ( radius, theta, y ) {
this.x = radius * Math.sin( theta );
this.y = y;
this.z = radius * Math.cos( theta );
return this;
},
その他数学メソッド
Vector3
では利便性のためにJavaScriptのMath内のメソッドをベクトルの各要素に適用するようなメソッドが存在しています。
min: function ( v ) {
this.x = Math.min( this.x, v.x );
this.y = Math.min( this.y, v.y );
this.z = Math.min( this.z, v.z );
return this;
},
max: function ( v ) {
this.x = Math.max( this.x, v.x );
this.y = Math.max( this.y, v.y );
this.z = Math.max( this.z, v.z );
return this;
},
floor: function () {
this.x = Math.floor( this.x );
this.y = Math.floor( this.y );
this.z = Math.floor( this.z );
return this;
},
ceil: function () {
this.x = Math.ceil( this.x );
this.y = Math.ceil( this.y );
this.z = Math.ceil( this.z );
return this;
},
round: function () {
this.x = Math.round( this.x );
this.y = Math.round( this.y );
this.z = Math.round( this.z );
return this;
},
roundToZero: function () {
this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
return this;
},
終わりに
ベクトル演算についてまとめながら、three.jsのVector3
クラスを見てきました。Vector3
クラスの一部のメソッドには今回は触れていません。個人的にはすべてのメソッドがインスタンスメソッドとして定義されており、クラスメソッドがないのが特徴的に感じました。