3D初心者の俺がThree.jsの基本をオススメ本とともにザーッとおさらいする記事



[WebGL Advent Calendar 2014](http://qiita.com/advent-calendar/2014/webgl)の13日目の記事です。


3Dのスキルなんてものは1mmもないわたくしが、お勉強したログをまとめてみます。

Three.jsのバージョンは68時点のものです。




# 参考にしたもの

* [three.jsのドキュメント](http://threejs.org/docs/)
* [three.jsのサンプル](http://threejs.org/examples/)

[![Three本](https://qiita-image-store.s3.amazonaws.com/0/2631/1ae58dde-7560-e602-cbfe-d16c775ea5d4.png "貼り付けた画像_2014_12_25_19_28.png")]( http://www.amazon.co.jp/dp/4877833242)

[three.jsによるHTML5 3Dグラフィックス〈上〉―ブラウザで実現するOpenGL(WebGL)の世界 ]( http://www.amazon.co.jp/dp/4877833242)

ドキュメントとサンプルがしっかりしてるので、それだけでも事足りそうだけど、本を読んだほうが早い。記事中で`上巻`と書いているのはこの本のことです。ただし、2013年9月に出版されたものなので、ちょっと古いところもあります。



# Three.jsの超基本

## こんなノリだと動く！

* renderer作成
* scene作成
* camera作成
* lightをsceneに置く
* meshをsceneに置く
	* meshは素材のmaterialと形状のgeometoryを内包する
* renderer.render(scene, camera)をループ
*  **表示されてる！**



## 3Dオブジェクトなど基本データ

### Mesh

以下を内包している

* geometry: 形
* material: 材質

``` mesh.js
var mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
```

入れ子にするときは`Object3D`でくるんであげる

```nest.js
var parent = THREE.Object3D;
parent.add(new THREE.Mesh(geometry1, material1))
parent.add(new THREE.Mesh(geometry2, material2))
```

## Objectの基本的な動かし方

* position: 位置
* rotation: 回転(オイラー角)
* scale: スケール


それぞれ、`THREE.Vector3`。x,y,zそれぞれ代入だけでなく、set(x, y, z)で一括で代入もできる。


``` move.js
mesh.position.x = 100
mesh.rotation.y = 60 / Math.PI;
mesh.scale.set(1, 1, 2)
```

Vectorなのでそれっぽいメソッドもある

* add(vector)
* distanseTo(vector)

### 回転

* オイラー角での回転
* クォータニオンでの回転

の二種類ある。rotationはオイラー角での回転。

オイラー角はx,y,zの回転の順番によって、結果がかわる(上巻p181)

クォータニオンでやるときは以下のような感じ。
回転軸のベクトル+回転角度を指定してあげる。

```quaternion.js
mesh.useQuaternion = true;
var axis = new THREE.Vector3(1, 1, 1).normalize();
var angle = Math.PI / 3;
vaar q = new THREE.Quaternion().setFromAxisAngle(axis, angle);
mesh.quaternion.copy(q);
```


# Renderer

レンダリングエンジン。上巻P54あたり

* WebGLRenderer
* CanvasRenderer

基本は`renderer.render(scene, camera)`をループするだけ。オプションがいろいろある。ほかにもCSSRendererとかSVGのやつもあるけど、今回はスルー。

## WebGLRenderer

いつか使いそうなメソッド/プロパティ

| プロパティ | 内容  |
| ----- | --- |
| precision | シェーダーの計算精度の指定。'highp', 'midiump', 'lowp' |
| antialias | アンチエイリアスの設定 |
| stencil | ステンシルバッファ |
| domElement | rendererのcanvas要素 |
| devicePixelRatio | ディスプレイの1ピクセルとthree.jsでの長さの単位との比 |

| メソッド | 内容  |
| ---- | --- |
| seClearColor(hex, allpha) | clearColorの設定 |
| setSize(width, height) | canvasの縦横 |
| setViewport(x,y,width,height) |  |
| setScissor(x,y,width,height) | シザーボックス |
| setFaceCulling() | カリングの設定 |

地味に、コンストラクタ経由でしか渡せないのもあるので、ドキュメントをちらっと見ておきたい(よくわかんないけど)
http://threejs.org/docs/#Reference/Renderers/WebGLRenderer

* canvas — A Canvas where the renderer draws its output.
* precision — shader precision. Can be "highp", "mediump" or "lowp".
* alpha — Boolean, default is false.
* premultipliedAlpha — Boolean, default is true.
* antialias — Boolean, default is false.
* stencil — Boolean, default is true.
* preserveDrawingBuffer — Boolean, default is false.
* maxLights — Integer, default is 4.





# カメラ

| クラス | 内容 | 本のページ | ドキュメント |
| -------- | --- | ----- | ------ |
| PerspectiveCamera | 透視投影(パースがついてるやつ)。視体積(四角錐)を設定する。<br>fov, aspect, near, far | 上巻 P50, 64 |  |
| OrthographicCamera | 正投影。パラメータに直方体を渡す。 | 上巻P65 |  |

# シーン
Sceneクラスのみ。上巻p60。
http://threejs.org/docs/#Reference/Scenes/Scene

メソッドはなく、プロパティのみ。

| プロパティ | 内容 |
| -------- | --- |
| fog | フォグ効果。視点から遠くにある物体のいろを霞がかかってるみたいにする |
| overrideMaterial  | このプロパティにmaterialが設定されると、そのmaterialで全部のobjectのmaterialを上書きしちゃう |

など。


# ヘルパー

わかりにくいのをわかりやすくしてくれる、便利なやつら

|  クラス | 内容など | 本のページ |
| --- | ---- | ----- |
| AxisHelper | Object3Dのxyz軸を見やすくする | 上巻P61 |
| ArrowHelper |  |  上巻P62 |
| PointLightHelper | PointLightの光源の位置がわかる | 上巻P264 |
| SpotLightHelper | スポットライトの光線や位置がわかる | 上巻P273 |


などなど他にもいっぱいある。


* BoundingBoxHelper
* CameraHelper
* DirectionalLightHelper
* EdgesHelper
* FaceNormalsHelper
* GridHelper
* HemisphereLightHelper
* VertexNormalsHelper
* VertexTangentsHelper
* WireframeHelper

[helperのサンプル](http://threejs.org/examples/#webgl_helpers)

# 数学系クラス

本にメソッドの日本語訳がずらっと並んでるので、読んでおきたい(理解はできないけど)。

| クラス | 内容など | 本のページ | 
| ----- | ------- | -------- | 
| Vector2 | 二次元ベクトル| 上巻p164 |
| Vector3 | 三次元ベクトル| 上巻p165 |
| Vector4 | 四次元ベクトル| 上巻p167 |
| Matrix3 | 3x3行列 | 上巻p169 |
| Matrix4 | 4x4行列 | 上巻p170 |
| Quaternion | クォータニオン。制御姿勢の取扱いクラス。 | 上巻p169 |
| Math | 各種数学的演算クラス。degToRad, smoothstepとか | 上巻p173 |

# 便利系クラス

| クラス | 内容など | 本のページ | 
| ----- | ------- | -------- | 
| Color | 色Util。setHSLとか、色で便利なメソッド群。| 上巻p164 |

# Geometry

上巻p74から。
3Dオブジェクトの形状。いっぱいある。公式サンプルの`geometry`あたりを見るのが速い。

* BoxGeometry
* CircleGeometry
* CubeGeometry
* CylinderGeometry
* DodecahedronGeometry
* ExtrudeGeometry
* IcosahedronGeometry
* LatheGeometry
* OctahedronGeometry
* ParametricGeometry
* PlaneGeometry
* PolyhedronGeometry
* RingGeometry
* ShapeGeometry
* SphereGeometry
* TetrahedronGeometry
* TextGeometry
* TorusGeometry
* TorusKnotGeometry
* TubeGeometry

## 大元のGeometryクラス

上巻p121

よく使いそうなプロパティとメソッド。さらによく使うのは **太字**。

| プロパティ | 型 | 内容 |
| -------- | --- |--- |
| id | int | id |
| **vertices**| [vector3] | 頂点座標の配列 |
| colors | [vector4]| 頂点色の配列。PointCloud, Line, Ribbonで使う  |
| normals | [float] | 頂点法線配列。Ribbonのみ |
| faces | [face3 or face4] | 面を指定するためのインデックス配列 |
| faceUvs | [[vector2]] | テクスチャ座標配列 |
| faceVertexUvs | [[vector2]] | テクスチャ座標の4つの頂点配列 |
| **verticesNeedUpdate** | boolean | verticeのアップデートをするかどうか。頂点を動かしてもこれをtrueにしないと反映されない |
| elementsNeedUpdate | boolean | faceをアップデートするかどうか |
| uvsNeedUpdate | boolean | faceUvsをアップデートするかどうか |
| normalseedUpdate | boolean | 法線のアップデートするかどうか |
| colorsNeedUpdate | boolean | colorsをアップデートするかどうか |

| メソッド | 内容 |
| -------- |--- |
| **applyMatrix(matrix)** | 頂点座標にmatrixをかける |
| mergeVertices() | 頂点が重複してたら結合する |
| clone() | |
| dispose() | |


# Material
上巻p68。

3Dオブジェクトの材質。いっぱいある。


代表的なものは

| クラス | 内容など | 本のページ | 
| ----- | ------- | -------- | 
| MeshBasicMaterial| 発行材質| 上巻p116 |
| MeshLambertMaterial |ランバート反射材質。カメラの位置によらず、おなじ明るさになる。マット。||
| MeshPhongMaterilal | Lambertの拡張版。カメラの位置によって明るさが変わる。テカテカする。鏡面指数で変わる。||
| MeshNormalMaterial| 法線材質。カメラに対する法線方向によって、表面色が異なる。| |

## 大元のMaterialクラス

上巻p114

よく使いそうなプロパティとメソッド。さらによく使うのは **太字**。

| プロパティ | 型 | 内容 |
| -------- | --- |--- |
| **side** | ステート | 適用する面を指定。FrontSide, BackSide, DoubleSide |
| opacity | float | 不透明度。transparent=trueのときに有効 |
| **blending** | ステート | transparen=trueのときに有効。乗算、加算などがある。 |
| depthTest | boolean | デプステスト(Zテスト)。奥行きの重なりがおかしいな？っていうときにtrueにするとなおる.transparentしてるとうまくいかないことも。 |
| depthWrite | boolean | デプスバッファへの書き込み可否 |
| alphaTest | float | αテスト。一定のopacityがないものは表示しないみたいな。 |
| visible | boolean | 表示/非表示 |
| **needUpdate** | boolean | 材質の変更を反映するかどうか |



# カメラコントロール系

本家gitの`/examples/js/controls`にいろいろ入っている。

| クラス | 内容など | 本のページ | サンプル |
| ----- | ------- | -------- | ------ |
| TrackballControls | マウスドラッグ・タッチムーブなどで、カメラの移動・拡縮・回転 | 上巻P194 | [サンプル](http://threejs.org/examples/misc_controls_trackball) |
| FlyControls | マウス・キーボードでカメラの上下左右移動 | 上巻P198 | [サンプル](http://threejs.org/examples/misc_controls_fly) |
| PointerLockControls | マウスでカメラの方向、キーボードでカメラの位置座標移動。マウスが非表示になる。 |  | [サンプル](http://threejs.org/examples/misc_controls_pointerlock) |
| OrbitControls | マウスドラッグでカメラ位置座標の移動。TrackballControlsとほぼ同じ。クォータニオンを使ってない。 |  | [サンプル](http://threejs.org/examples/misc_controls_orbit)|
| PathControls | パスに沿ってカメラを移動させる |  | |
| FirstPersonControls |  |  | |




# ライト

上巻p230

いい感じに陰影をつけるには

1. 光源の設定
2. 反射材質の設定
3. 法線の設定

というのをしないといけないらしい。

## 光源

* 平行光源(太陽光みたいな、めっちゃ遠くから照らすやつ)
* 点光源
* スポット光源(スポットライトみたいなの)
* 環境光源 

## 反射材質とは

* Lambert カメラの位置によらず、おなじ明るさになる。マット。
* Phone Lambertの拡張版。カメラの位置によって明るさが変わる。テカテカする。鏡面指数で変わる。

## Lightの種類

いっぱいあるので、説明は割愛！そのうち書くかも(確率は2%くらい)

* DirectionalLight
* PointLight
* SpotLight
* AmbientLight
* HemisphereLight



# まとめ

とりあえず、本を買って、公式のサンプルを眺めているだけで、個人で遊ぶ範囲では困らないはず！

おもしろ3Dコンテンツを作って競争しましょう！ウェ～イ！！ｳｪｰｲwwwwwwｳｪｪｪｪｪｪｪｪｪｪｪｪｰｰｰｰｰｰｰｰｰｰｰｰｰｲwwwww


![9a3850be1e33be777bc71e105baff010.gif](https://qiita-image-store.s3.amazonaws.com/0/2631/6b33ba83-0e03-3c9a-604f-093287780a39.gif "9a3850be1e33be777bc71e105baff010.gif")


![6bc6dc2919117ab2ee4831299e8b1f84.gif](https://qiita-image-store.s3.amazonaws.com/0/2631/b28a1e58-789b-ccb4-f808-e610e805828d.gif "6bc6dc2919117ab2ee4831299e8b1f84.gif")