コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

日経ソフトウェア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()