2019年8月10日土曜日

Processing言語で3Dグラフィック ー 視点を回転させるアニメーション

Processing言語で3次元グラフィックが描けるので試してみた.

とりあえず,半透明の立方体と球体を置いて,カメラ視点を変化させてアニメーションにしてみる.XYZ軸も描いて,向きがわかるようにしてみた.

Processingの座標系は,左上が原点,右向きがX軸の正方向,下向きがY軸の正方向,手前向きがZ軸の正方向という左手系の座標系になっている.行列を使って座標軸を変換する方法が良くわからなかったので,とりあえず,右手系のまま,画面中心を原点にして,画面の上方向がZ軸になるように回転すると,X軸が右方向,Y軸が手前方向になった.回転だけでは,X軸が右方向,Y軸が画面の奥方向,Z軸が上方向という右手系にできないので,とりあえずこの座標系で話を進めることにする.

アニメーションの際は,座標系,物体の座標は変化させずに,カメラの座標と向きだけを変化させている,カメラの位置はZ軸方向300の高さで,半径300の円周上を動かし,向きは常に原点方向.

こうやって書いたソースが以下のとおり.

// 2019/8/9

int loopCount; // draw()が呼ばれるたびにインクリメントされる変数

void setup() {
  size(400, 400, P3D); // 400x400のウィンドウに3D描画
  loopCount = 0;
  // 日本語フォント
  PFont font = createFont("MS Gothic", 48, true);
  textFont(font);
  textSize(24);
  hint(ENABLE_DEPTH_SORT); // z bufferが視点方向で正常に機能するように
}

void draw() {
  loopCount++;
  background(192); // light grayの背景
  // ウィンドウの中心が(x, y)の原点になる
  translate(width/2, height/2, 0); // 原点を画面の中身にずらす
  // 座標軸を回転する(Processingは左手系)
  // x:右, y:下, z:手前 -> x:右, y:手前, z:上
  rotateX(PI/2);
  // この座標系で視点だけ回転させる
  // z軸が上の斜め上方向から原点を眺める
  camera(300.0*cos(radians(loopCount)),
          300.0*sin(radians(loopCount)),
          300.0,
          0.0, 0.0, 0.0,
          0.0, 0.0, -1.0);

  // 座標軸の描画
  fill(255, 0, 0); // 赤
  textAlign(CENTER); // x方向をセンタリング,y方向の座標はベースライン
  text("x軸", 150, 0, 0); // XY平面上に書く
  text("y軸", 0, 150, 0); // XY平面上に書く 
  text("z軸", 0, 0, 150); // Z=150のXY平面上に書く
  stroke(0, 0, 0); // 黒線
  line(0, 0, 0, 130, 0, 0); // X軸
  line(0, 0, 0, 0, 130, 0); // Y軸
  line(0, 0, 0, 0, 0, 145); // Z軸

  // 3Dオブジェクトの描画
  fill(0x7F0000FF); // 青の塗り潰し,透明度半分
  stroke(0, 255, 0); // 緑線
  box(100, 100, 100); // 原点中心,一辺のサイズ100のの立方体

  translate(-100, -100, 0); // 原点をずらす
  stroke(0, 0, 255); // 青線
  fill(0x7F00FFFF); // シアンの塗り潰し,透明度半分
  sphere(100); // 原点中心,半径100の球
}


これをGIFアニメーションで表示すると以下のとおりになった.

Processingのアニメーションからgifアニメーション画像を保存する方向はこちらを参照した.ここで使うgifAnimationライブラリは,Processing Ver.3では動かず,Processing Ver.2で動かす必要がある(Ver.3対応版はこちらにあった).追加ライブラリgifAnimationライブラリの置き場のディレクトリは,自分のスケッチブックの保存ディレクトリの中のlibrariesディレクトリである.ここに,拾ってきたアーカイブファイルを解凍して出てきたgifAnimationディレクトリ以下をコピーすれば良い.書き換えた後のソースコードは以下のとおり.

// 2019/8/10

import gifAnimation.*;

GifMaker gifExport;
int loopCount; // draw()が呼ばれるたびにインクリメントされる変数

void setup() {
  size(400, 400, P3D); // 400x400のウィンドウに3D描画
  loopCount = 0;
  // 日本語フォント
  PFont font = createFont("MS Gothic", 48, true);
  textFont(font);
  textSize(24);
  hint(ENABLE_DEPTH_SORT); // z bufferが視点方向で正常に機能するように
  gifExport = new GifMaker(this, "export.gif");
  gifExport.setRepeat(0); // 無限ループ
  gifExport.setQuality(10); // default値
  gifExport.setDelay(30); // 30ms単位で1コマ(1秒33コマ)
  gifExport.setTransparent(0, 0, 0); // 黒は透過色
}


void draw() {
  loopCount++;
  background(192); // light grayの背景
  // ウィンドウの中心が(x, y)の原点になる
  translate(width/2, height/2, 0); // 原点を画面の中身にずらす
  // 座標軸を回転する(Processingは左手系)
  // x:右, y:下, z:手前 -> x:右, y:手前, z:上
  rotateX(PI/2);
  // この座標系で視点だけ回転させる
  // z軸が上の斜め上方向から原点を眺める
  camera(300.0*cos(radians(loopCount)),
          300.0*sin(radians(loopCount)),
          300.0,
          0.0, 0.0, 0.0,
          0.0, 0.0, -1.0);

  // 座標軸の描画
  fill(255, 0, 0); // 赤
  textAlign(CENTER); // x方向をセンタリング,y方向の座標はベースライン
  text("x軸", 150, 0, 0); // XY平面上に書く
  text("y軸", 0, 150, 0); // XY平面上に書く 
  text("z軸", 0, 0, 150); // Z=150のXY平面上に書く
  stroke(0, 0, 0); // 黒線
  line(0, 0, 0, 130, 0, 0); // X軸
  line(0, 0, 0, 0, 130, 0); // Y軸
  line(0, 0, 0, 0, 0, 145); // Z軸

  // 3Dオブジェクトの描画
  fill(0x7F0000FF); // 青の塗り潰し,透明度半分
  stroke(0, 255, 0); // 緑線
  box(100, 100, 100); // 原点中心,一辺のサイズ100のの立方体

  translate(-100, -100, 0); // 原点をずらす
  stroke(0, 0, 255); // 青線
  fill(0x7F00FFFF); // シアンの塗り潰し,透明度半分
  sphere(100); // 原点中心,半径100の球
  
  gifExport.addFrame(); // gifアニメーションに現在のフレームを追加
  if (loopCount >= 360) {
    gifExport.finish(); // 1回転したらアニメーション終了
  }
}


0 件のコメント:

コメントを投稿