日経ソフトウェア2011.7月号の記事から
7月号の特別レポートに、ニンテンドーDSiのBASIC「プチコン」で3次元コンピュータグラフィックスに挑戦!という記事がありました。その記事では、3次元CGプログラミングの勉強を兼ねてプチコンで立方体を回転させるプログラムを作っています。
これぐらいのプログラムなら、Luaridaでも朝めし前なので、ちょろっとLuaで書き直して移植してみました。いつものごとく、先ず動画です。
プログラムリスト
詳細説明は日経ソフトウェア2011.7月号の記事を見てください。
日経ソフトウェアのプチコンのプログラムとの違いは、投影座標を g.x 、g.y として別に用意したところと、Luaridaはキー入力を持っていないので、タッチしたときの指移動に対応してBOXの回転や移動を行うようにしたところです。画面中央で指を離すとプログラムが終了します。
3Dのいい勉強になりました。
------------------------------------------ --Wire 3D BOX DEMO --タッチ位置が画面中心から離れるほど回転が速くなります。 --横移動でY軸回転、縦移動でX軸回転します。 --タッチした指の移動方向にBOXも移動します。 --画面中央で指を離すと終了します。 ------------------------------------------ --関数宣言-------------------------------- main={} --グローバル変数宣言---------------------- ------------------------------------------ --メインプログラム ------------------------------------------ function main() local tx, ty = 0, 0 --角度 local scale = 60 --倍率 local px, py, pz = 0, 0, 0 --平行移動 local d = 250 --遠近感係数 local x={} local y={} local z={} local g={ x, y } local i local xx,yy,zz local w,h = canvas.getviewSize() --画面サイズ local siro = color(255,255,255) --白色 local kuro = color(0,0,0) --黒色 local iro = siro --線の色 local bx,by,bs --タッチ座標とタッチ状態フラグ local gx,gy,dx,dy --移動量計算用 local ntf = 1 --タッチフラグ g.x={} --投影X座標 g.y={} --投影Y座標 canvas.drawCls( kuro ) --背景を黒色にする while(true)do --ローカル座標でモデルの定義 x[1] = -1; y[1] = 1; z[1] = -1 x[2] = 1; y[2] = 1; z[2] = -1 x[3] = 1; y[3] = -1; z[3] = -1 x[4] = -1; y[4] = -1; z[4] = -1 x[5] = -1; y[5] = 1; z[5] = 1 x[6] = 1; y[6] = 1; z[6] = 1 x[7] = 1; y[7] = -1; z[7] = 1 x[8] = -1; y[8] = -1; z[8] = 1 --ワールド座標変換 for i=1,8 do --Y軸の回転 xx = x[i]*math.cos(ty) - z[i]*math.sin(ty) zz = x[i]*math.sin(ty) + z[i]*math.cos(ty) x[i] = xx z[i] = zz end for i=1,8 do --X軸の回転 yy = y[i]*math.cos(tx) - z[i]*math.sin(tx) zz = y[i]*math.sin(tx) + z[i]*math.cos(tx) y[i] = yy z[i] = zz end for i=1,8 do --拡大と平行移動 x[i] = x[i]*scale+px y[i] = y[i]*scale+py z[i] = z[i]*scale+pz end for i=1,8 do --投資投影とビューポート変換 g.x[i] = d*x[i]/(d-z[i]) + w/2 g.y[i] = d*y[i]/(d-z[i]) + h/2 end --3D BOXの描画 canvas.putCls( kuro ) canvas.putLine( g.x[1],g.y[1], g.x[2],g.y[2], iro) canvas.putLine( g.x[2],g.y[2], g.x[3],g.y[3], iro) canvas.putLine( g.x[3],g.y[3], g.x[4],g.y[4], iro) canvas.putLine( g.x[4],g.y[4], g.x[1],g.y[1], iro) canvas.putLine( g.x[5],g.y[5], g.x[6],g.y[6], iro) canvas.putLine( g.x[6],g.y[6], g.x[7],g.y[7], iro) canvas.putLine( g.x[7],g.y[7], g.x[8],g.y[8], iro) canvas.putLine( g.x[8],g.y[8], g.x[5],g.y[5], iro) canvas.putLine( g.x[1],g.y[1], g.x[5],g.y[5], iro) canvas.putLine( g.x[2],g.y[2], g.x[6],g.y[6], iro) canvas.putLine( g.x[3],g.y[3], g.x[7],g.y[7], iro) canvas.putLine( g.x[4],g.y[4], g.x[8],g.y[8], iro) canvas.putflush() --タッチ処理 bx, by, bs = touch() if( bs==1 )then --指が離れた ntf=1 if( bx>w/2-20 and bx<w/2+20 and by>h/2-20 and by<h/2+20 )then break --画面中央で指が離れたらwhileを抜ける end touch(1) --指が離れている間待機 elseif( ntf==1 )then --タッチしたので指移動量の初期化 dx = bx dy = by gx = px gy = py ntf = 0 elseif( ntf==0 )then --指移動処理 px = gx + (bx - dx) --BOX X座標 py = gy + (by - dy) --BOX Y座標 tx = tx - (by/h-0.5) --X軸回転 ty = ty - (bx/w-0.5) --Y軸回転 end end toast("画面タッチでWire 3D DEMOを終了します") touch(3) end main() system.exit()