カテゴリー:3D

リスト表示へ

CANNON.jsを使って3Dに物理演算を持ち込む

2013年12月 8日 09:09

さて、今回はGraphical Web Advent Calendar 2013の第7日目です。

Graphical Webということで、前回、スマホでも動く物理演算で転がる3Dサイコロを作ったのでその解説で紹介したサイコロのデモで使用したCANNON.jsについて書いてみたいと思います。

CANNON.jsとは

CANNON.jsは、物理演算を提供してくれるいわゆる「物理エンジン」ライブラリです。
3D向けの物理エンジンライブラリはいくつかあり、有名なのは「ammo.js」というものがあります。
これは、物理エンジンの(おそらく)デファクトスタンダードとも呼べる「Bullet(弾丸)」というエンジンがあり、それをJavaScriptに変換したものです。
余談ですが、Bulletに対してammoは「弾薬」という意味です。そしてCANNONは弾丸より強くしたいということでカノン(大砲)という名が付けられたそうです。

CANNON.jsのデモもあるので、どんなものかすぐに見ることが出来ます。

物理エンジンを使うための知識

物理エンジンとは、物体が衝突したら跳ねたり回転したり、といった物理的な挙動を計算によって導き出してくれるエンジンです。
ゲームなどで使われるリアルタイムシミュレーションでは、それぞれの物体を「剛体(RigidBody)」と呼び、変形することのない物体として扱います。(瞬間的に見れば変形していないと見なせるためです)

そして剛体には位置、回転などの「姿勢情報」と、反発係数(restitution)や摩擦係数(friction)など剛体の「性質」、そしてどんな「」か、という情報が必要です。
物理エンジンを使う上で、このあたりは知っておく必要があるでしょう。

それから、大事な決め事として大体の物理エンジンは「KMS」という単位で計算が行われます。つまり、「キログラム、メートル、秒」です。
もし仮に、画面に表示するのと同じサイズ(例えば200)を剛体に設定すると、それは200m級の超巨大な物体になります。400とかを指定したら、それこそ東京タワーが落ちてくるようなサイズ感になってしまいます。

これを意識しておかないと、思ったんと違う!という結果になったりします。特に3Dは単位が存在しないため、1という数字がどれくらいのものか、というのは自分で決める必要があります。

CANNON.jsのセットアップ

さて、前提知識を書いたところで、実際にCANNON.jsを使ったデモを作ってみます。実際に作ったデモはjsdo.itに上げてあります。

なにはともあれ物理演算ワールドを作る

Three.jsでも同様ですが、まずは物理演算の対象となる剛体を管理するための「物理演算ワールド」を作成します。

いくつか設定項目がありますが、それぞれ上記の設定でほぼ問題ないでしょう。
意味を説明すると、gravityはそのまま重力ですね。重力加速度は9.8m/s^2というのは知られていると思います。それを設定しています。

続いてbroadphase(ブロードフェーズ)とは、ざっくり言うとぶつかっている「可能性のある」剛体同士を見つける作業です。
物理演算はとても処理の重い計算です。すべての物体を総当りで計算していては速度が間に合いません。
そのために、まずは衝突している可能性のある剛体同士を見つけ、その後のフェーズ(ナローフェーズと呼ばれます)で本当に衝突しているのか、衝突していたらどれくらいめり込んでいるのか、という詳細情報を計算します。(ちなみにざっくりとした物理エンジンの動作の仕組みはQiitaに「剛体シミュレーションをまとめてみる」という記事を書いたので、興味がある人は見てみてください)

次のiterationsは反復計算回数です。リアルタイムシミュレーションは実はだいぶ適当な、間引いた処理をして高速化を実現しています。
そのため不正確さがどうしても出てきてしまいます。それを、この反復計算で繰り返し計算を行うことで誤差を縮める、ということをしています。
大体5〜10回程度で不正確さは収束するようです。この間の数値を指定しておけばいいでしょう。(当然ですが、回数を増やすだけ誤差は減りますが、計算回数が増えるため処理が重くなります)

最後のtoleranceは「許容値」という意味の英単語です。これも不正確さに関する設定ですが、ある程度の誤差を許容することで不安定さを解消する役割があります。この許容値をどれくらいにするか、という設定です。

以上で、物理演算ワールドの設定は終わりです。あとは、計算対象となる剛体を作り、それをどんどん追加していきます。

剛体を作る

物理演算ワールドが作れたので、次は物理演算される対象となる剛体を作っていきます。
今回はシンプルにするため、地面と箱のみを作ります。

物理エンジンを使う上で必要な知識、ということで説明した通り、剛体には位置の他に形や性質を指定する必要があります。
そのため、まず「どんな形(shape)か」という情報を定義し、それと質量(mass)を指定して剛体を作ります。(new CANNON.RigidBody(mass, shape)

CANNON.jsでは、質量0の剛体をSTATICとして扱います。つまり衝突しても動かない剛体ですね。今回は地面をそれにしています。
そして落下してくる箱を定義します。こちらは質量1なので衝突したら跳ね返ったり回転したりするようになります。

生成した箱は、初期位置をY軸の10として設定しています。(body.position.y = 10;
また、初期の回転速度をZ軸に対して10だけつけています。(body.angularVelocity.set(0, 0, 10);
最後のbody.angularDamping = 0.1;は、ダンパ(減衰率)を0.1に設定しています。これを設定することで、時間が経つにつれて徐々に回転が遅くなっていきます。小さめに設定しておけば空気抵抗のような感じになりますね。

さぁ、これで準備が整いました。これを実行してみると・・画面はなにも変化しませんw
当然ですが、物理演算の結果はただの数値でしかありません。人間が見れるものになっていないんですね。
なので、結果を画面に出力してやる必要があります。今回の例では、Three.jsを使って3Dのレンダリングを行っています。

Three.jsと相性のいいCANNON.js

CANNON.jsのREADMEを読むと書いてありますが、Three.jsをインスパイアしていて、Three.jsととても相性がよく出来ています。
上記で書いた画面への出力ですが、Three.jsの剛体を生成しておけば、以下のようにするだけで簡単に位置と回転を反映することが出来てしまいます。

見たままですねw
ちなみにquaternion(クォータニオン)は四元数と呼ばれる、回転を表すのに都合のいい概念です。興味がある人は調べてみるといいでしょう。

物理演算ワールドの時間を進める

さて、これで本当に準備が整いました。
あとは作った物理演算ワールドの時間を進めるだけです。時間を進めるにはworld.step(timeStep);というように、stepメソッドに進める時間を秒で指定します。基本的には60FPS相当である0.016(16ミリ秒)を指定すればいいでしょう。

world.stepを一回実行するとその時間だけ時が進みます。setTimeoutやrequestAnimationFrameなどのループを使って時間を常に進めていけば、デモのようにリアルタイムの動きを実現することができるようになります。

いかがでしょう。基本的な部分だけであれば、それほどむずかしくなく物理エンジンを組み込むことが分かってもらえたのではないかと思います。
今回は箱がひとつだけでしたが、何個も箱を作ればそれぞれが衝突しあって、リアルな動きを再現してくれます。
やはり3Dを使うからには物理エンジンを導入してリアルな動きを見せたいですね。

ちなみにjsdo.itに上げたデモはちょっとだけ追加して、クリックすると上方向に箱が持ち上がるようになっています。
うまくクリックを調整すると箱がずっと浮いた状態になります。物理エンジンを使えば簡単なゲームも発想次第で作れそうです。

最近はQiitaでも記事を書いてます

2013年12月 5日 10:35

Qiitaは主に3Dまわりがメイン(WebGL、Three.js、Unity)

最近めっきりブログの更新が滞ってますが、実はQiitaでひっそり記事を書いていたりします。
ほんとはこっちに掲載してもいいんですが、方向性の違う記事ということと、結構メモ書きに近いものも多くあるので、さっと書いてすぐ共有、ってことでQiitaを使ってます。

こちらのブログで書いてもいいかな、という単位になったら載せようと思いますが、メモでも役に立つかもしれないので、定期的に記事へのリンクを載せていこうと思います。

スマホでも動く物理演算で転がる3Dサイコロを作ったのでその解説

2013年9月 1日 16:46

CSS3DRendererはexamplesの中

ルービックキューブの解説は少しお休みして、Three.jsのCSS3DRendererを使ってサイコロを作った話をしようと思います。といっても、ルービックキューブを作る上で使用した概念などもあるので、まったくの無関係というわけではありません。

今回のポイントは「CSS3DRenderer」です。
これ、実はThree.jsだけを読み込んでも使用できません。実験段階だからなのか、Three.jsのgithubのリポジトリ内にある「examples」の中にこっそり含まれています。

実装サンプル

なので、まずはこれを取り出してThree.jsと一緒に読み込ませます。
ちなみに今回作成したものは以下のようなサイコロです。(CANNON.jsという軽量の物理エンジンも使用しています)

見てもらうと分かりますが、こうした基本的な形状であればCSSでも問題なく表示することが出来ます。
また、Three.jsでオブジェクトを生成したりテクスチャを貼ったり、という処理すらなく、単純にDOMを生成してそれを立体に仕上げるだけです。
つまり、このデモはiPhoneでも問題なく見れます。

立体にするための回転や移動のマトリクス的な処理は全部Three.jsがやってくれるので、直感的に形を作っていくことができます。(例:dice.rotation.x = THREE.Math.degToRad(45))

コード解説

ポイントを絞って今回のコードの解説をしていこうと思います。
まずはなにはともあれ、CSSで表示できるようにするまでを見てみます。

ソースコード

各面の情報の定義

順を追って見ていきます。まず最初はサイコロの各面用の情報を用意しています。position、rotation、テクスチャURLの3つです。
cubeSizeはキューブのサイズを別の場所で定義しています。サイコロのサイズですね。
cubeSizeは位置情報として利用しているので、実際のサイズは2倍にする必要があります。(中心点からの移動量なので、左にcubeSize、右にcubeSize分移動します。そのため、各面のサイズは2倍になります)

空のCSS3DObjectをdiceの親として定義

そして情報の定義の下に見慣れた記述があります。そう、まずは普通にdiv要素を作って定義されたキューブのサイズにサイズを指定します。
このdivがサイコロの各面を内包する要素となります。
生成したあとはTHREE.CSS3DObjectに、先ほど生成したdiv要素を指定してインスタンスを作ります(関連付けます)。
こうすることでThree.jsの3Dの変換などがこのdiv要素に適用されるようになる、というわけです。

各面を生成

最後に、サイコロの各面を生成します。boxInfoに6面分の情報が入っているのでそれをfor文で回し、各面を生成します。
生成の仕方はdiv要素のときとまったく同じです。DOMを生成し、それをTHREE.CSS3DObjectに関連付けるだけです。
生成後、boxInfoで定義された位置と回転情報を適用します。(face.position.fromArray(info.position)) そして生成された各面をdiceに追加します。(dice.add(face);

サイコロの生成はこれだけです。
あとはここで生成したdiceをThree.jsのsceneオブジェクトにaddし、rendererでレンダリングしてあげればサイコロが出現します。
Three.jsの使い方はここでは長くなってしまうので割愛します。使い方については「THREE.js で WebGL>」に詳しく書かれているのでこちらを参考にするといいと思います。
SceneやCamera、Rendererの生成の仕方はまったく一緒です。(ただし、今回の目的でもあるCSSでレンダリングさせるために使用するレンダラーは「CSS3DRenderer」を利用する必要があります)

サイコロのどの面が上かを判定する

実はここが一番書きたくてこの記事を書いていますw
今回はCANNON.jsというのを使って物理演算させていますが、これの使い方についてはまた別の機会にしたいと思います。(まだそこまでちゃんと使ってないし)

さて、どの面が上を向いているかどう判別したらいいでしょうか。人間であれば見たまま一目瞭然ですね。
しかし、コンピュータはそれを数値で表さないとなりません。なので、なんらかの計算をした上で、その数値から判断する必要があります。

では、どうしたらそれを判別できるか。まずは「なにがどうなっていたらそれは上を向いていると見なせるか」を考えてみます。
下の画像は、サイコロと座標系の軸を表示したものです。(最近ハマっているので、無駄にBlenderで作りましたw)
サイコロを置いて、XYZ軸の向きを表示したもの。Y軸正の向きに1、X軸正の向きに3が向いている
画像を見ると「1」が上を向いていますね。そして軸の情報を見てみると、「Y軸の正の向き」が上向きと一致しています。

では次の画像はどうでしょうか。今度はサイコロが回転して、X軸の正の向きが上を向いています。
上記画像のサイコロが回転し、今度は3とX軸正の向きが画面上を向いている状態
どうやらどの軸のどの向きが上を向いているか、が分かれば上を向いている面が判別できそうです。
しかし、サイコロはCANNON.jsの物理演算によってぐるぐるとたくさん回転してしまっています。実際それが今どうなっているかはどうしたら分かるでしょうか。

Three.jsはワールド空間座標での変換行列を持っている

実はThree.jsのCSS3DObjectは(もちろん、WebGLとして作る場合のObject3Dオブジェクトも)、このワールド空間座標でどの位置にどんな向きでモデルが配置されているか、という情報を持っています。
それはmatrixWorldというプロパティに保存されています。
この変換行列を適用すると、とある点がワールド空間上でどの位置にあるか、が分かります。
つまり、この行列を使えば現時点のワールド空間座標系で軸や頂点がどういう向きになっているかが計算できるというわけです。

X軸正の向きで試してみる

実際にやってみましょう。試しにX軸正の向きがどちらを向いているかやってみます。
jsdo.itに上がっているサンプルで、「2」が上向きの状態で試してみます。

まずX軸の正の向きを表すベクトルを作ります。ベクトルを作るには、今回はTHREE.Vector4クラスを使います。THREE.Vector4クラスにはapplyMatrix4というメソッドがあり、自身のベクトルに行列を適用することができるようになっています。
実際にベクトルを生成している部分は以下です。

このベクトルに対して行列を適用すると結果は「x: -0.00044029735727235675, y: -0.9999998807907104, z: 0.00009558126475894824, w: 0」となりました。この値が意味するところはなんでしょうか。
これは、行列適用後X軸正の向きがワールド空間座標系でどの方向を向いているか、というベクトル情報です。

本来なら「1」が向いている方向となりますが、ものすごーくわずかに真上からずれた方向を向いているようです。

実はプログラムで数値を計算する以上、どうしても限界があります。細かい数値はある程度切り捨てられます。無限の桁数では計算できませんからね。
なので、数回の計算を行ううちに、この切り捨てられた数値部分の誤差がどうしても出てしまいます。
それが、この「-0.9999998807907104」という数値になって現れたのです。

とはいえ、他の数値に目を向けてみると明らかに値が違います。ここは誤差を許容して0.99以上、とすることで判別ができそうです。

その判定を行っているのが「if (px.applyMatrix4(dice.matrixWorld).y > UP) {...}」の部分です。(UPは0.99を変数に入れているだけです)
この「y」は上で説明した通り、計算後のX軸正の向きの現状の向きです。つまり、yの値が-0.99ということはマイナス値、すなわち下を向いている、ということになります。

すべての軸・方向についてチェックする

これを、各軸各方向すべてに対して確認することで、どの面が上をむいているかを判別しています。
実際のソースは以下です。

実際のソースを見てみると、各軸の各方向について計6種類のベクトルを生成し、それに行列を適用させてその結果の判定を行っています。
もしyの値が0.99以上の値を持つものが見つかったら、それを面の上の結果として判断しその面に描かれているサイコロの目を出力する、という流れです。
どの軸の方向がどの数字か、は作ったサイコロによるのでそこは事前に決めておかないとなりません。
そこがしっかりと定義できていれば、あとは判別した軸と合わせて該当する数字を使うだけです。

まとめ

いかがだったでしょうか。
実際にスマホで見てみても、PCとまったく遜色なく動くと思います。(特にiPhoneは)
CSSで問題なく作れる形状に関してはスマホでも動くものが比較的簡単に作れます。
CSSということは表示しているものはDOMそのものなので、画像を表示するもコンテンツを表示するも自由自在です。

CSS3DRendererはだいぶ夢があるなぁと思いました。(まぁ、iPhoneでWebGLが動いてくれるようになれば話しは早いんですけどね・・)
コンテンツにちょっとした驚きを追加するにはとてもいい選択だと思うので、ぜひ色々試してみてください。

さて、次回はまたルービックキューブの話に戻ろうと思います。(ちなみに今回のこの軸の方向がどちらを向いているか、というのはルービックキューブの制作でも使用しました)

CSSで本当にクリアできるルービックキューブを作ったので3Dについて色々解説してみる その2

2013年8月28日 19:04

前回はこれから解説していくルービックキューブの紹介と、3D関連の学習に利用した記事などの紹介をしました。
いよいよ実際にルービックキューブについて解説をしていきたいと思います。
まずは基本的なところから始めて行くので、人によっては今回の記事はほぼ知ってることだらけになるかもしれません。

要素の変形 - transformプロパティの基礎

上でも書いた通り、まずはtransformプロパティの基礎から解説していきます。
すでに使ったことがある人ならおなじみだと思いますが、transformプロパティ(WebKit/Blink系はまだ-webkit-のプレフィクスが必要です)にはいくつかの値が指定できます。

実際にtransformプロパティに指定できる関数をいくつか適用したサンプルをjsdo.itにアップしておきました。
以下のサンプルを見てもらうとそれぞれがどういう動きをするか分かると思います。

translate関数

translate関数は平行移動をさせる関数です。translate(30px, 40px);と指定すれば、その要素は右に30px、下に40px移動します。
ただし、marginと違いposition: relative; left: 30px; top: 40px;の指定とほぼ同じ動作をします。つまり、移動結果で他の要素に影響を与えることがありません。

rotate関数

rotate関数は回転をさせる関数です。rotate(30deg);と指定すれば、その要素は時計回りに30度(degrees)回転します。
translate関数同様、移動後の結果は他の要素に影響を与えません。

scale関数

scale関数は拡大・縮小をさせる関数です。scale(2, 2);と指定すれば、その要素は縦横ともに2倍に拡大されます。
仮にscale(1, 2);とすれば、縦だけが2倍に拡大されます。
scale関数も他と同様、結果は他要素に影響を与えません。

skew関数

skew関数はせん断する関数です。skew(30deg);と指定すれば、その要素は30度分、せん断されます。実際にどうなるかは上記のサンプルを見てください。
skew関数も結果は他要素に影響を与えません。

関数まとめ

これら関数は単独で使う以外にも、組み合わせて使うこともできます。 回転させた後に拡大、みたいなことがやりたい場合はtrnasform: rotate(30deg) scale(2);とすることでふたつを組み合わせた変形をすることができます。
その他、関数を任意の数指定することでそれぞれの変形を重ねあわせることもできます。

ただしひとつ注意点があります。それは、関数の組み合わせる順番に意味がある、ということです。
詳しくはこの先の行列あたりの話でする予定ですが、移動してから回転させるのか、回転してから移動させるのかで当然結果が変わってきます。
なぜかと言うと、例えばX軸方向に移動させたい場合、rotate関数はX軸自体も回転させてしまうからです。つまり、回転したあとのX軸方向に移動してしまうため結果が変わってしまうのです。
実際のサンプルは以下です。
rotate x translatetranslate x rotateの違いを表しています。

回転の角度は同じで若干分かりづらいので、元の位置を点線で表しています。元の位置からの違いを確かめてみてください。

実は関数は2D用と3D用の2種類

さて、すでにお気づきの人もいるかと思いますが、上で説明していたのは実は2Dに対しての変形でした。
だって、パラメータをふたつしか渡していないですからね。(e.g. translate(30px, 40px))

3Dは3軸に対しての変換なので3つのパラメータが必要です。(XYZ軸ですね)
ただし、上記の関数に単純に3つのパラメータを渡してもダメです。3D用には専用の関数があります。
といっても大した違いはなく、上で説明した関数名の最後に3dをつけるだけです。
つまりtranslate3d(10px, 10px, 10px)という具合です。(この例みたいに3つの値すべてが同じ場合は引数ひとつでも同じ動作になります)

3Dの変換にはパースが必要

さて、実際に3dをつけて変換を行ってみるとおかしなことに気づくと思います。どういうことかと言うと、3Dっぽくない。
なぜ3Dっぽくないのか。理由は、パース(遠近感)がついていないから、です。
遠近感は人が目にするものは(現実世界であれば)すべてに必ずついているものです。遠くのものほど小さく見える、というあれです。

しかし、コンピュータの世界はそれらもしっかりと数値で指定してあげないと解釈ができません。つまり、3Dの指定だけではダメで、ちゃんとパースをどれくらいつけるか、という指定も同時に必要になります。(注意点として、パースの指定は回転を指定した要素の親要素に指定する必要があります)

実際にその違いを以下のサンプルに用意してみました。実際にどれくらい違いがあるのか見てみてください。

並べてみてみるとその違いは一目瞭然ですね。下のほうがより自然に回転しているように見えます。
今回はパースの値を300pxで設定しましたが、この値をいじることで少しまた違った見え方になるので色々いじってみてください。

変換の要、マトリクス

さて、今回はまだ続きます。でもこれが最後です。そして難関です。
最後はマトリクスです。または行列と言います。

マトリクスのむずかしい点は、まずその引数の多さでしょう。2D用のものでも引数は9個、3D用に至っては16個もの数値を指定しないとなりません。
さらに、それぞれの数値は分かりやすい数値にはなっていません。例えば、X軸に対して30度回転させたい、となった場合でも、どこにも30という数字は出てきません。

実際に指定するとmatrix3d(1, 0, 0, 0, 0, 0.8660254, 0.4999999, 0, 0, -0.4999999, 0.8660254, 0, 0, 0, 0, 1)という数値になります。30なんて数字はどこにも出てきていませんね。
なぜこんな複雑な数値を指定する必要があるのでしょうか。それは、これが回転や拡大・縮小、平行移動などの処理をひとまとめにしたものだからです。(上のサンプルは回転ひとつだけですが、いくつも回転や平行移動などを掛けあわせても、指定するのはひとつのマトリクスだけになります)
実際、今回作成したルービックキューブでは、今キューブのそれぞれの面はどこを向いているのか、というのをこのマトリクスを使って表現しました。なぜなら、ユーザの操作によってキューブは常に姿勢が変わってしまいます。その都度、rotateXがいくつで、rotateYがいくつで・・などとやっていたら、style属性に指定する関数があっという間にとんでもない数になってしまいます。

しかし、このマトリクスを使うことで、何回回転されたとしてもひとつのマトリクスでそれを表現することができます。これが、ひとつにまとめられるメリットです。
行列に関しては別で説明しますが、こうした理由からマトリクスを使って姿勢制御をするという選択を取りました。

実際に指定したものは以下になります。
matrix3dに指定する数値の桁を若干省略したので微妙に角度が違いますが、しっかりと数値を指定すれば同じ見た目になります。

まとめ

いかがだったでしょうか。だいぶ基本的なところなので、知っている人が多かったかと思います。
ただ、マトリクスは普段あまり使わないのではないでしょうか。ルービックキューブでは逆にこれを多用しているので、使ったことない人はぜひ、使い方を知って活用してみてください。

だいぶ長くなりましたが、transformについてまとめました。次回は座標変換や行列について書きたいと思います。(CSSまったく関係なくなっちゃいますが・・)

CSSで本当にクリアできるルービックキューブを作ったので3Dについて色々解説してみる その1

2013年8月20日 09:04

しばらくぶりの更新です。
最近はWebGLやCSS Shaderを始め、3D関係のことをメインに勉強しています。
おかげでだいぶ詳しくなってきました。

ちなみに、CSSでクリアできる、と書いていますが「CSSだけで」ではないので当然JavaScriptもてんこ盛りですw

最近はインプットばかりだったので、備忘録も兼ねて以前案件で制作したCSS Rubik Cubeを解説を交えながら書いていきたいと思います。
CSS Rubik CubeはMaxellの商品のキャンペーンで、エビ中キューブと名付けられたコンテンツです。

エビ中キューブは、エビ中というアイドルグループの動画を、ルービックキューブで操作して自分好みのものに揃えて見る、というものです。
PCだけでも操作可能ですが、これをWebSocketでスマホと接続してスマホからPCに表示されているルービックキューブを操作する、というのがメインコンテンツです。
この「スマホでルービックキューブ」のコントローラ部分の制作を担当しました。

今回はこの「スマホ向けルービックキューブコントローラ」を細かく解説していこうと思っています。(ただ、結構長くなりそうなので何回かに分けて書く予定です)
ちなみにこのコントローラ部分をjsdo.itにあげて、さらに何分でクリアできるか、というゲーム仕立てにしたものをアップしておきました。

以下のデモは、マウスでドラッグするか、スマホでフリップすることでルービックキューブを操作することができます。画面外をドラッグすることでルービックキューブ自体を回転することができるので、全体の状態がどうなっているかも確認することができます。(ただ、これでクリアは相当大変ですが・・w)

実際のルービックキューブサンプル

3Dに関するメモ書き

3Dグラフィクスに関してはインターネット上の記事をメインに、書籍などを参考にしつつ勉強しました。
そのときに集めたメモ書きをqiitaに投稿しているので、そちらも参考にしてみてください。

自作3Dライブラリのデモ

勉強の理解を深めるために、1から自作の3Dライブラリを作ってみたものが以下のデモです。
座標変換、ライティングがメインなので複雑なモデルは作れていませんが、ドラッグなどで3Dの感じを味わえる作りになっています。
またデモは、2D Canvasにレンダリングするものなので、(かなり重いですが)スマホでも見ることができます。

参考書籍

書籍は以下のもの(実例で学ぶゲーム3D数学)を熟読しました。

参考記事リンク

自分が勉強してきた記事で、ブックマークしたものをまとめておきました。
ただひとつ注意点があって、ググって出てくる記事には2通りの種類があるということを覚えておいてください。

どういうことかというと、OpenGLをベースに解説している記事なのか、DirectXをベースにしている記事なのか、です。
次回以降で詳しく解説する予定ですが、このふたつはどちらも3Dを実現する技術です。
なにを注意するかというと、実はこのふたつ、どちらも同じ3D関係の技術ではあるものの、3Dには欠かせない行列による計算がまったく逆なのです。

そのため、これを知らずに行列を計算すると期待と違った結果になってしまいます。
色々な記事を参考にしていて、実はここが地味に大変でした。この行列はどっちのなの!? というw
なので、ここに挙げた記事以外に他のものを参考にする際はその点に注意して参考にしてください。(ちなみに解説する予定の行列の計算はOpenGLの方式をベースにしています)

今回は参考リンクや触り部分だけになりましたが、意外と参考記事を見つけるだけでも大変だったので有用だと思うものをまとめておきました。
次回はいよいよ本格的に解説に入って行きたいと思います。

1