学校で学んで以来、縁が無くなった方も多いかと思いますが、実は3Dコンテンツの制作においてベクトルは役に立つ概念なんです。本記事ではThree.jsとベクトルの基礎である足し算・引き算を使った座標の計算方法を紹介します。ベクトルと聞くだけで拒絶するエンジニアもいると思いますが、心配いりません。Three.jsが煩わしい計算をすべておこなってくれるので、ベクトルの性質だけ覚えれば誰でも扱えるようになります。基本からおさらいし、実際にThree.jsでどのようにベクトルを扱っていくか学んでいきましょう。本題に入る前にベクトルを使ったデモを作成したので紹介します。今回は以下のような物体を追従するカメラをベクトルを使って実装しています。サンプルコードもGitHubにアップしているので参考ください。デモを別ウインドウで再生するソースコードを確認する※このデモはThree.js(r88)で作成しています。ベクトルのおさらいベクトルを知っている人も知らない人もベクトルおさらいをしましょう。3次元ではなく二次元で解説します。そもそもベクトルとは?ベクトルは向き、量の2つの情報を持っています。矢印でイメージする場合、矢印の向きが向き情報、長さが量を示します。0)から伸びているベクトルは座標を示す事ができるため、そういったベクトルを位置ベクトルと言います。1)の三点が存在するとします。この時、点Oから点Aを結ぶベクトルをOAベクトルとし、点Oから点Bを結ぶベクトルをOBベクトルとします。この時OAベクトルとOBベクトル足すと以下の図のようなOCベクトルになります。OBベクトルをOAベクトルの先端までずらし、その時のOAベクトルの開始点とOBベクトルの先端を結ぶベクトルが和になります。これをThree.jsを使ったコードで表すと以下のようになります。vOA.add(vOB);和を求める場合はTHREE.Vector2クラスに用意されているadd()メソッドを使います。足し算の時と同様のOAベクトルとOBベクトルで考えていきます。OAベクトルからOBベクトルを引くと以下のようなOCベクトルになります。引き算の場合はまずOBベクトルの向きを反転させます。あとは足し算と同様の考え方で差を表現できます。これをThree.jsを使ったコードで表すと以下のようになります。vOA.sub(vOB);差を求める場合はTHREE.Vector2クラスに用意されているsub()メソッドを使います。Three.jsでベクトルを使ってみようThree.jsとベクトルを使った、実践的なコードを確認していきましょう。以下の2つのステップに分け順に解説します。動きまわる球の正面ベクトルを求めてみよう球の後ろにカメラを追従させようここからは3次元ベクトルを扱いますが、二次元の時とほぼ同じなので心配はいりません。動きまわる球の正面ベクトルを求めてみよう円運動しているsphereという球状のメッシュがあるとします。球の前方を表すベクトルを求めるには移動前と移動後の位置ベクトルの差を使います。以後本記事では前方を表すベクトルを正面ベクトルと呼びます。OBベクトルからOAベクトルを引いたものが球の正面ベクトルになります。前項の引き算の説明では原点から伸びるベクトルを導き出していましたが、ここでは点Aからの向きを表すベクトルとしたいため、上の図では点Aを始点とするようにベクトルを移動させています。仕組みが分かったのでThree.jsのコードを書いていきましょう。移動後と移動前の座標を取得します。getNewPosition()は円運動の次の位置情報(THREE.Vector3)を返却するものとします。getNewPosition();newPositionとoldPositionの差を求めます。newPosition.clone().sub(oldPosition);ここまでで正面ベクトルは求まりましたが、今回のように大きさの情報が必要ないような場合は、単位ベクトルへ直しておくと後々扱いやすくなります。単位ベクトルとは長さが1のベクトルの事を指します。最後にnormalize()メソッドで単位ベクトルへ変換しておきましょう。単位ベクトルに変換することを「正規化せいきか(英語ではNormalizeノーマライズ)」と言います。frontVector.normalize();ここまでの処理を毎フレーム行い正面ベクトルを更新すればStep1の完成です。このプレビューはTHREE.ArrowHelperを使ってベクトルを可視化しています。球の後ろにカメラを追従させようカメラの位置の計算にはさきほどの球の正面ベクトルを用います。仕組みとしては球の背後に一定距離離した位置にカメラが来るように計算します。球の正面ベクトルの逆向き、つまり背面ベクトルを計算します。THREE.Vector3クラスのnegate()というベクトルを反転させるメソッドを使用します。この時、正面ベクトルを変更してしまわないようにclone()メソッドを挟んでおきます。frontVector.clone().negate();背面ベクトルはすでに単位ベクトルとなっているので、球とカメラを離したい分だけ伸ばします。multiplyScalar()メソッドを使って拡縮をしてみましょう。背面ベクトルを距離分引き伸ばすbackVector.multiplyScalar(distance);球の位置ベクトルを足しカメラの位置を求め、位置を更新します。算出したカメラ位置を反映camera.position.copy(cameraPosition);このままではカメラが球の方向を向いていないので、lookAt()メソッドを使いカメラの向きを修正します。カメラを球に向かせるcamera.lookAt(sphere.position);これで球にカメラが追従するようになりました。この処理だけでFPSゲーム風なカメラアングルになったかと思います。意外と仕組みが分かってしまうと簡単ですね。今回はベクトルの足し算と引き算に絞った解説でしたが、内積や外積を使用することでもっと複雑な動きや処理が可能になります。本記事でベクトルがなんとなく理解できたという方は内積と外積にも是非挑戦してみてください。記事「WebGL開発に役立つ重要な三角関数の数式・概念まとめ」ではThree.jsと三角関数を使った表現の解説もしているので併せて参考ください。この記事は「Three.js入門サイト」連載の1つです。平成29年11月11日に内容をメンテナンスしています。MEDIAは株式会社ICSが運営するオウンドメディアです。ICSはインタラクションデザイン専門のプロダクション。最先端のwebテクノロジーを駆使し、オンスクリーンメディアの表現分野で活動しています。問い合わせ採用情報インタラクションコンテンツの制作や新しいことに挑戦しながら、互いにスキルを高め合えるメンバーをICSでは募集しています。詳しくは採用情報をご覧ください。MEDIAは古い記事でもメンテナンスし続けることで、常に役立つ情報発信を目指しています。