p5.jsがWebGL＆3D対応。軽くいじってみます


地味に拡張しているp5.js。久々にウォッチしてみると2015/10/05のリリースでWebGL対応していて、それに伴い3Dのサポートもはじめたようです。他のライブラリには色々先を越されていると思いますが、いじってみました。

最後は、時間がなかったのでシンプルなUFO作って終了
![29g51155224222822233323233.gif](https://qiita-image-store.s3.amazonaws.com/0/57193/b3195501-99bc-622f-2abf-c0269eba7d14.gif)

##基本テンプレート
見るところは公式サイトのチュートリアル、あとはリファレンスにはそれに載り切らない実装がありました。まずは基本テンプレを
p5パッケージのサンプルファイルの、コメント冒頭にはShiffmanのサイトへのリンクが。宣伝乙であります

```js

// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com

// Example 1-1: stroke and fill

function setup() {
  createCanvas(windowWidth, windowHeight, WEBGL);
}

function draw(){
  background(255);
  box();
}

```
結果
![スクリーンショット 2015-11-27 0.02.47.png](https://qiita-image-store.s3.amazonaws.com/0/57193/a825ec3f-ca25-0f57-fb69-47a57033b6a8.png)

・・・？ 2Dかな？
きっとカメラがあるのだろう。と思いつつ・・・


##回してみると・・・

```js

function setup(){
  createCanvas(windowWidth, windowHeight, WEBGL);
}

function draw(){
  background(200);
  rotateX(frameCount * 0.01);
  rotateY(frameCount * 0.01);
  box(200, 200, 200);
}

```

動いた
![29g5115522422282.gif](https://qiita-image-store.s3.amazonaws.com/0/57193/e314f56d-d009-1587-abf2-2e82a9be71d3.gif)


frameCount（=進んだフレーム数に応じて増える）
windowWidth（ブラウザの横幅）
windowHeight（縦幅）
と見慣れない便利変数が出てきました。前無かった気がする・・


~~どうやらグローバル空間はどんどん汚染していく方針のようです。プレイグラウンド用途に特化ですね。まぁ、それもいいと思います。~~
※2015/12/22 注※
グローバル汚染は回避可能なことが判明しました。
「p5.js を instance mode で使う」
http://qiita.com/turusuke/items/c92a13602523d6378cc0


##プリミティブ立体勢揃い＆小ネタ
リファレンスにそろっと入ってましたが、drawの中に「orbitControl();」と入れるとドラッグでカメラを動かせるようになります。Threeインスパイアかな
立体を勢揃いさせる時、そのままだと重なるので、translateで座標をずらします。これはまさにProcessingスタイル。コード短いな〜。

```js
function setup(){
  createCanvas(windowWidth, windowHeight, WEBGL);
}

function draw(){

  //ドラッグでカメラ動かす
  orbitControl();

  //ボックス（立方体）
  box(50, 50, 50);

  //動け
  translate(200,200,-100);
  //コーン（三角錐）
  cone(100, 100);

  //プレーン（平面）
  translate(-150,200,-200);
  rotateX(radians(-90)); //-90度回転
  plane(500, 500);

  //スフィア（球）
  sphere(200);

  //シリンダー（円柱）
  translate(-350,100,150);
  rotateX(radians(-90)); //-90度回転
  cylinder(100, 100);

  //トーラス（ドーナツ）
  translate(0,0,350);
  torus(200, 60);

}

```

転校生たち。初々しいですね
![29g511552242228222.gif](https://qiita-image-store.s3.amazonaws.com/0/57193/1e695197-054d-0f97-4678-6d838d694523.gif)


##カメラとライト
長くなってきたので、紹介だけにします。
リファレンスに実装があります。http://p5js.org/reference/
Three.js,Unityのようなスタイルを踏襲しているようです。プロパティはそれらをやっていれば言わずもがなでしょう（丸投げ）


**カメラの種類**
・シンプルカメラ
camera(x,y,z)

・パースペクティブ（透視投影）カメラ
perspective(fovy, aspect, near, far)

・オーソグラフィック（正投影）カメラ
ortho(left, right, bottom, top, near, far)


**ライトの種類**
・アンビエントライト（環境光）
・ディレクショナルライト
・ポイントライト

##テクスチャを貼る
画像ファイルのオリジンポリシーにより、ローカルの画像は使えません。
ここで ```python -m SimpleHTTPServer``` の登場。

```js
var img;

function setup(){
  createCanvas(windowWidth, windowHeight, WEBGL);
  img = loadImage("sc.png");
}

function draw(){
  texture(img);

  // ... 以下同 ...
}

```


貼れました。短いなぁ。
![スクリーンショット 2015-11-27 0.56.05.png](https://qiita-image-store.s3.amazonaws.com/0/57193/af0293c6-56a4-ebf9-ff1e-48cda99a906a.png)




##マテリアルとライトを組み合わせる
マウスの座標に合わせてディレクショナルライトをあてます。それに呼応してくれるように、マテリアルをセットします。これもProcessingらしいプロセスです。

```js

function setup(){
  createCanvas(windowWidth, windowHeight, WEBGL);
}

function draw(){

  //マウスの座標
  var dirY = (mouseY / height - 0.5) *2;
  var dirX = (mouseX / width - 0.5) *2;

  //マウスに合わせてライト強弱
  directionalLight(250, 250, 250, dirX, -dirY, 0.25);

  //マテリアルをセット
  ambientMaterial(250);

  // ... 以下同 ...
}

```

![29g511552242228222333.gif](https://qiita-image-store.s3.amazonaws.com/0/57193/7516c0a1-9495-6c86-2988-6567583500d9.gif)


##表現してみよう
締めとして何か表現してみます。
ドーナツと球でUFO、＋時間に合わせて光の明滅。そろそろ寝なきゃいけないのでｗ

どーん。
![29g51155224222822233323233.gif](https://qiita-image-store.s3.amazonaws.com/0/57193/b3195501-99bc-622f-2abf-c0269eba7d14.gif)

時間経過と三角関数に関しては↓の記事に書きました
メディアアート系で重要な数式・概念 & p5.jsで遊ぶ
http://qiita.com/hp0me/items/8f43ad146744310664ae

```js

function setup(){
  createCanvas(windowWidth, windowHeight, WEBGL);
}

function draw(){

  orbitControl();

  //時間ライト＆マテリアル
  var intensity = Math.sin(frameCount * 0.1);
  directionalLight(250, 250, 250, intensity, intensity, 0.25);
  ambientMaterial(250);

  //地面
  translate(0,300,-200);
  rotateX(radians(-90)); //-90度回転
  plane(500, 500);

  //UFO
  var x =  Math.cos(frameCount * 0.03) * 300;
  var y =  Math.sin(frameCount * 0.06) * 300;
  translate(x,y,300);
  torus(200, 60);
  translate(0,0,100);
  sphere(150);

}

```

##主な情報源
以下の２つにほとんど全ての情報があります。
公式チュートリアル(github)
https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5
公式リファレンス
http://p5js.org/reference/

##感想
かなりインスタントに3Dビジュアライゼーションができました。Processingらしいです。あとは何を作るかです。でもThreeがあるからなぁ。
カスタムシェーダーには今後対応予定のようです。