HaxeとThreejsで3Dコンテンツを作る 初級編

#はじめに
私はFlash/ActionScriptしかほぼわからなかったのですが、Haxeをちょっとやってみたら、ほぼFlashと同じ感覚で、CanvasとかWebGLを使ったゲームのようにインタラクティブなものが作れるようになりました。

今回はそんな便利なHaxeとThreejsを使い、以下のようなBoxを複数配置し、マウスに反応する簡単なサンプルを作ります。初心者向けの内容です。

[![image](https://qiita-image-store.s3.amazonaws.com/0/17747/06ed8e56-d2f7-eb1d-850e-6aa1d9e1f3d0.png)](http://kitasenjudesign.com/test/1215/)

#開発環境
開発はWindowsでFlashDevelopを使ってます。インストールが終われば、コマンドラインを使わずに、コンパイルまでできるので便利です。インストールにはこの記事がとても参考になります。
http://dev.classmethod.jp/ria/html5/haxe-createjs-1/

macもいろいろありそうですが、ここではふれません。
(macで FlashDevelopを使う方法があります）
http://qiita.com/_nabe/items/662624c7b093da9195f2

##Three.jsをHaxeで使えるようにする
externというインターフェイスが定義されているファイルが必要になります。github上で公開されているもの(https://github.com/tong/three.hx )があるのでそれを使います。以下のようにコマンドラインで書くと、threejsという名でライブラリとしてインストールされ、扱えるようになります。
`haxelib git threejs https://github.com/tong/three.hx`

これでもいいんですが、パソコンが変わったり、開発環境が変わったりするとなんか面倒なので、私は下記のようにexternディレクトリを作り、そこにexternファイル群を入れ、srcパスを通しています。ご参考までに。

![image](https://qiita-image-store.s3.amazonaws.com/0/17747/558e0f78-8161-dd25-b9d1-b69713f5183e.png)

##サンプルコード
Boxをいっぱいおいて、マウスでカメラが動くという簡単なサンプルコードを書いてみました。Main.hxとMain3d.hxでできています。[できあがると、こんなかんじです](http://kitasenjudesign.com/test/1215/)

```hx:Main.hx
package ;

import js.Browser;
import js.Lib;

class Main 
{
	
	private static var _main:Main3d;
	
	static function main() 
	{
		Browser.window.onload = untyped _init;
	}
	
	static private function _init() 
	{
		_main = new Main3d();
		_main.init();
	}
	
}
```

```hx:Main3d.hx
package ;

import js.Browser;
import three.BoxGeometry;
import three.DirectionalLight;
import three.Mesh;
import three.MeshLambertMaterial;
import three.PerspectiveCamera;
import three.PointLight;
import three.Scene;
import three.Vector3;
import three.WebGLRenderer;
/**
 * ...
 * @author nabe
 */

class Main3d
{
	
	private  var _scene		:Scene;
	private  var _camera		:PerspectiveCamera;
	private  var _renderer	:WebGLRenderer;
	private  var _mouseX	:Float = 0;
	private  var _mouseY	:Float = 0;
	private  var _amp		:Float = 400;
	
	var _down:Bool=false;
	
	public function new() 
	{
	}
	
	public function init() 
	{
		
		_scene = new Scene();
		_camera = new PerspectiveCamera(60, Browser.window.innerWidth / Browser.window.innerHeight, 10, 50000);
		
		_camera.near = 5;
		_camera.far = 40000;
		
		_scene.add(new PointLight(0xffffff, 3));
		var d:DirectionalLight = new DirectionalLight(0xffffff);
		d.position.set(1000, 1000, 100);
		_scene.add(d);
		
		_renderer = new WebGLRenderer();
		_renderer.setSize(Browser.window.innerWidth, Browser.window.innerHeight);
        Browser.document.body.appendChild(_renderer.domElement);

        //マウスの座標とってる
		_renderer.domElement.onmousemove = function(e){
			_mouseX = e.clientX;
			_mouseY = e.clientY;
		}

		//箱200個おいてる
		for(i in 0...200){
			var geo:BoxGeometry = new BoxGeometry(10,10,10);
			var mat:MeshLambertMaterial = new MeshLambertMaterial( { color:0xffffff * Math.random() } );
			var mesh:Mesh = new Mesh(geo, mat);
			mesh.position.set(
				1000 * (Math.random() - 0.5),
				1000 * (Math.random() - 0.5),
				1000 * (Math.random() - 0.5)
			);
			_scene.add( mesh ); 
		}
		
		_run();

	}

	private function _run():Void
	{
		//マウスによってカメラ動かしてる
		var rad:Float = _mouseX / Browser.window.innerWidth * Math.PI * 2;
		_camera.position.x = _amp * Math.cos(rad);
		_camera.position.y = 0;
		_camera.position.z = _amp * Math.sin(rad);
		_camera.lookAt(new Vector3());

		_renderer.render(_scene, _camera, null, false);		
		Three.requestAnimationFrame( untyped _run);
	}

}
```

##おわりに
Haxeはクラス作るのも、エディタのコードの補間も、コンパイルエラーだしてくれるのも超便利です。ゲームみたいな複雑なものにとてもむくのではないでしょうか。js/htmlが分からない私でも楽しく開発できて、自然にjs/htmlもちょっとわかるようになりました。
 逆にHTMLの開発（ふつうのWebページみたいなの？）とかには向いてないのかもしれないです。