#コーディング
three.jsで地球と月を回してみた

JavaScriptのアニメーションライブラリは多数あり、どれも一長一短なようで選定が難しい。どれを使えばいいのか悩んでいたところ
http://mrdoob.com/lab/javascript/threejs/css3d/periodictable/
を見て中2心を刺激されたという理由でthree.jsを触ってみることにした。
クリックして何かイベントが起こるようなものは次段階で、とりあえず何かが規則的に動くだけなら簡単なのでは?という安易な発想の元とりあえず太陽の周りを地球が公転するアニメーションを描画してみる。
先にできあがったデモとコードを示しておく。
https://spc-jpn.co.jp/solar-system/

見ての通りES6シンタックスなのでBabelなどで要トランスパイル。
 

舞台を整える

太陽みたいな単純な形状なんてものはきっと球を描画してそれにテクスチャを貼ればいいのだろうとアタリをつけたものの、リファレンスを見るとシーンだの光源だのカメラだのを設置しろって書いてある。なんだそりゃというところでまず躓いた。
https://threejs.org/docs/index.html#manual/introduction/Creating-a-scene
言われてみれば当たり前なのだが、物体を置くには舞台が必要で、物体を視認するには光が必要で、それを映し出すにはカメラが必要だ。その辺はデフォルトでいい感じのものを用意してくれてもよくない?とか思うがこれはもうおまじない感覚で設置してあげる。
同様にどこに描画するのかを指定するためにレンダラーの設定も必須。
色々物体を追加していきたいのでクラスとしてまとめ、各物体を関数から呼び出せるようにする。最低限の要素をコンストラクタとinit関数としてまとめた。

光源はこんな感じで、平行光源と環境光源を用意してあげる。

レンダラーはこんなおまじない

これで舞台は整った。まず舞台・光源・カメラを用意してあげることと、レンダラーを用意し描画先の要素を指定してあげる必要があるということを理解してしまえばなんのことはない。
ヘルパーも表示させておくとなにかと便利なので追加。
グリグリ動かせた方が3D感が出るので、three.jsのサンプルに含まれるTrackballControls.jsを流用させてもらう。これはCDNなどから引っ張ってくることはできなさそうなので、three.jsをダウンロードした中にあるファイルを読み込ませよう。

 

太陽を回す

ここから物体を配置していく。とりあえず太陽を描画してみよう。太陽っぽいテクスチャが必要になるので探す。
https://www.solarsystemscope.com/textures
のようなサイトから拝借してこよう。
Three.jsでの物体の描画は、ジオメトリとマテリアルを作成しそれらをメッシュとして合体させることで成立する。球体のジオメトリを作成し、テクスチャをマテリアルとして作成し、それを貼り付けるという感じだろうか。

これで太陽ができあがった。このままでは微動だにしないので太陽を自転させよう。
レンダリング関数にアニメーションを追記する。

見ての通り太陽をy軸方向にローテーションさせるという命令を出すだけ。JavaScriptのMathクラスを用いても良いが、three.mathというクラスが用意されておりラジアンへの変換がこちらの方が楽そうだったのでこっちを使う。
角度の計算だが、ここで入力した数値は1フレームあたりに変化する大きさである。通常60fpsで描画するので、1秒に変化させたい角度/60を打ち込めばよい。
今回の場合1日が1秒で過ぎるように調整した。太陽の自転周期は大体25日なので25秒で360°変化すればよい。そうすると計算式は360/25/60=0.24となるわけ。
 

地球と月を追加しぶん回す!

ここまでできればあとは地球と月を同じ要領で書いていくだけ。
公転に関しても同様に角度を変化させ、x軸・z軸それぞれに対して正弦・余弦の値を取り適当な大きさになるよう定数を掛ければよい。直感的に分かりづらければ色々値を変化させて動きを眺めてみると理解が深まるだろう。
月の公転をどうすればいいのか少し悩んだが、地球が原点(太陽)を中心として回転しているのに対して月は地球を中心に回転するのだから、その分の値(地球の座標)をプラスしていってあげればよいという結論に至った。

 

オマケの星空

これで太陽・地球・月が回ってくれたわけだが、なんか寂しいので適当に星空を追加する。
適当な星っぽいテクスチャを貼った物体をランダムに配置してあげる。

 

レスポンシブ対応

トドメにレスポンシブに対応する。ウィンドウ幅が変わった時に再計算させてあげれば良い。

3D描画はかなり処理が重そうな気がするのでスマホだと厳しいかと思いきや意外とヌルヌル動く。
ちゃんと計算して大きさとか距離を現実通りにすると、太陽がデカすぎて何がなんだかわからなくなるのであくまで概念図となる。太陽と地球はもっともっと遠い。
 

太陽系制覇しようとして力尽きた結果

水金地火木までの惑星を追加してみたバージョンがこちら。
https://spc-jpn.co.jp/solar-system/sub/
公転周期と自転周期は概算で現実に近づけてあるが、やはり太陽がデカすぎて距離も遠すぎて地球などが豆粒になってしまうのでその辺りは適当に可視性を保った範囲で定めてある、繰り返すが太陽デカすぎ。太陽以外の各惑星の大きさと距離の比率はおおよそシュミレートできているはず、木星デカい。
星空はランダムに生成したが、リアルを追求するなら星の座標リストを用いて配置してあげれば良い。ヒッパルコス星表のcsvを発見したので、これをjsonに変換し流用すればいける。
http://astronomy.webcrow.jp/hip/
実際にやってみたが非常に重くなる。Web表現としては実用的ではなさそう。
 

一言

敷居が高いイメージがあった3Dだが、一度触って概念を理解すれば思っていたほど怖くない。とりあえず触ってどんな簡単なものでもいいから作ってみることが大事であることを再確認できた一例であった。
余談だが、太陽フレアをなんかこうかめはめ波的なエフェクトで描画してやろうと思って挫折したので課題としたい。

CONTACT

この度は当社へご興味お持ちいただき
ありがとうございます。
Webに関するお悩みございましたら、
是非一度お気軽にご相談ください。
平日10:00~19:00