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