2008-02-28 | 20:22

カメラから視錐台の近平面までの距離をn(ear)、遠平面までの距離をf(ar)、近平面の上辺をt(op)、下辺をb(ottom)、左辺をl(eft)、右辺をr(ight)とした時、 透視射影変換行列は

で表される。
3次元での座標にこの行列を適用すれば2次元上の座標に変換できる。
(この説明は、カメラがワールド座標のz軸上のマイナス方向にあり、原点の方向を向いていることを前提としている。カメラの位置や向きが変化する場合については次回)
package { import flash.display.*; import flash.events.*; import org.papervision3d.core.*; import org.papervision3d.core.geom.*; import org.papervision3d.core.math.*; [SWF(width="400", height="400", frameRate="10", backgroundColor="#ffffff")] public class Projection extends Sprite{ private var LEN:int = 80; private var initialPoints:Array = [new Number3D(LEN, +LEN, LEN), new Number3D(LEN, +LEN, -LEN), new Number3D(-LEN, +LEN, -LEN), new Number3D(-LEN, +LEN, LEN), new Number3D(LEN, -LEN, LEN), new Number3D(LEN, -LEN, -LEN), new Number3D(-LEN, -LEN, -LEN), new Number3D(-LEN, -LEN, LEN) ]; private var ff:int = 0; private var m:Matrix3D = new Matrix3D(); public function Projection():void { var r:Number = 500; var l:Number = -500; var t:Number = 500; var b:Number = -500; var n:Number = 500; var f:Number = 1000; m.n11 = 2*n/(r-l); m.n13 = (r+l)/(r-l); m.n22 = 2*n/(t-b); m.n23 = (t+b)/(t-b); m.n33 = -(f+n)/(f-n); m.n34 = -2*n*f/(f-n); m.n43 = -1; addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(e:*):void{ // rotation axis var ra:Number3D = new Number3D(1,2,3); ra.normalize(); // rotation matrix var rotationMatrix:Matrix3D = Matrix3D.rotationMatrix(ra.x,ra.y,ra.z,(ff++)/180*Math.PI); var points2D:Array = []; for each(var pp:Number3D in initialPoints){ var p:Number3D = pp.clone(); // rotation Matrix3D.multiplyVector(rotationMatrix,p); // convert to 2D point Matrix3D.multiplyVector(m,p); p.x += 200; p.y = 200 - p.y; points2D.push(p); } graphics.clear(); graphics.lineStyle(3,0xff,0.8); graphics.drawCircle(points2D[0].x, points2D[0].y, 5); graphics.moveTo(points2D[0].x, points2D[0].y); for (var i:int = 1 ; i < 4; i++){ graphics.lineTo(points2D[i].x, points2D[i].y); } graphics.lineTo(points2D[0].x, points2D[0].y); graphics.lineStyle(3,0xff0000,0.8); graphics.moveTo(points2D[4].x, points2D[4].y); for (i = 5 ; i < 8; i++){ graphics.lineTo(points2D[i].x, points2D[i].y); } graphics.lineTo(points2D[4].x, points2D[4].y); graphics.lineStyle(3,0xff00,0.8); for (i = 0 ; i < 4; i++){ graphics.moveTo(points2D[i].x, points2D[i].y); graphics.lineTo(points2D[i+4].x, points2D[i+4].y); } } } }
スポンサーサイト
Comment
Post a comment