とりあえず,半透明の立方体と球体を置いて,カメラ視点を変化させてアニメーションにしてみる.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アニメーションで表示すると以下のとおりになった.
// 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 件のコメント:
コメントを投稿