Papervision3D 教學 part 2 -- 空照
我第二篇 PaperVision3D 的教學,是針對 Camera 的基本操控,這個範例我將 Camera 移到空中 高度 2000 的位置(y=2000),在 onEnterFrame() 時,會設定 carema 的座標,繞著中心點作旋轉,有點像是衛星移動的感覺。不過若是只對著一個 myCube1 做拍照的話,可能這樣的範例會看不出到底是 myCube1 在自己旋轉,還是 camera 在繞著他旋轉,所以我另外製作了一 Plane 物件名叫 ground 作為地板,預設這個地板是 X-Y 面向的單面,我需要將他順著 X 軸做翻轉,變成 X-Z 面向。
package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.events.Event;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.objects.*
import org.papervision3d.materials.*
[SWF(backgroundColor="#000000", frameRate="60", width="400", height="400")]
public class T2step1 extends Sprite
{
private static var PI:Number = Math.PI;
private static var TH:Number = PI / 180;
[Embed(source="../assets/IMG_1054.JPG")]
private var CubeTexture:Class;
private var container:Sprite;
private var scene:Scene3D;
private var camera:Camera3D;
private var rootNode:DisplayObject3D;
private var du:Number = 0;
public function T2step1()
{
// initialize the objects
init3D();
// add a listener for the 3D loop
addEventListener(Event.ENTER_FRAME, loop3D);
}
private function init3D():void{
container = new Sprite();
addChild(container);
container.x = 200;
container.y = 200;
scene = new Scene3D(container);
camera = new Camera3D();
camera.y = 2000;
camera.z = -2000;
camera.zoom = 10;
camera.focus = 100;
rootNode = scene.addChild(new DisplayObject3D("rootNode"));
var ground:DisplayObject3D = rootNode.addChild(new Plane(new ColorMaterial(0xffcc00), 500, 500, 1, 1), "ground");
ground.rotationX = -90;
var cubeTexture:Bitmap = new CubeTexture() as Bitmap;
var myCube1:DisplayObject3D = rootNode.addChild(new Cube(new BitmapMaterial(cubeTexture.bitmapData), 100, 100, 100, 1, 1, 1), "myCube1");
myCube1.y = 50;
}
private function loop3D(event:Event):void{
du++;
if(du==360)du=0;
var newX:Number = 2000 * formatNum(Math.cos(du*TH), 3);
var newZ:Number = 2000 * formatNum(Math.sin(du*TH), 3);
camera.x = newX;
camera.z = newZ;
scene.renderCamera(camera);
}
private function formatNum(num:Number, cnt:Number):Number{
return Math.round(num * Math.pow(10, cnt)) / Math.pow(10, cnt);
}
}
}
測試畫面如下:
你可能會發現,在 camera 繞著中心旋轉拍攝時,地面 ground 與 myCube1 某些部份會有些重疊衝突的問題,你需要時時想像,其實我們看到的 " 一個面 ",並不是真的由一個面構成,而是由 PV3D engine 將這個面拆成多個三角形拼貼而成的。對於這個問題,我試圖將 myCube1 的高度拉更高一點,從 myCube1.y = 51 一直拉到 100 以上,這個問題會得到改善,但還是會出現重疊三角形。另一種做法也可以改善這個問題,就是將地面的 segments 增加,由原本的 1 改成 10 以上,這樣一來,地面就是由更多的小三角碎片所組成的,而重疊時會造成的破碎感覺會小一點點,不過想必這樣的運算會比較多,所以,就別介意這種視覺問題囉!以下是改過的程式碼:
package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.events.Event;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.objects.*
import org.papervision3d.materials.*
[SWF(backgroundColor="#000000", frameRate="60", width="400", height="400")]
public class T2step2 extends Sprite
{
private static var PI:Number = Math.PI;
private static var TH:Number = PI / 180;
[Embed(source="../assets/IMG_1054.JPG")]
private var CubeTexture:Class;
private var container:Sprite;
private var scene:Scene3D;
private var camera:Camera3D;
private var rootNode:DisplayObject3D;
private var du:Number = 0;
public function T2step2()
{
// initialize the objects
init3D();
// add a listener for the 3D loop
addEventListener(Event.ENTER_FRAME, loop3D);
}
private function init3D():void{
container = new Sprite();
addChild(container);
container.x = 200;
container.y = 200;
scene = new Scene3D(container);
camera = new Camera3D();
camera.y = 2000;
camera.z = -2000;
camera.zoom = 10;
camera.focus = 100;
rootNode = scene.addChild(new DisplayObject3D("rootNode"));
var ground:DisplayObject3D = rootNode.addChild(new Plane(new ColorMaterial(0xffcc00), 500, 500, 10, 10), "ground");
ground.rotationX = -90;
var cubeTexture:Bitmap = new CubeTexture() as Bitmap;
var myCube1:DisplayObject3D = rootNode.addChild(new Cube(new BitmapMaterial(cubeTexture.bitmapData), 100, 100, 100, 1, 1, 1), "myCube1");
myCube1.y = 50;
}
private function loop3D(event:Event):void{
du++;
if(du==360)du=0;
var newX:Number = 2000 * formatNum(Math.cos(du*TH), 3);
var newZ:Number = 2000 * formatNum(Math.sin(du*TH), 3);
camera.x = newX;
camera.z = newZ;
scene.renderCamera(camera);
}
private function formatNum(num:Number, cnt:Number):Number{
return Math.round(num * Math.pow(10, cnt)) / Math.pow(10, cnt);
}
}
}
看效果!
3 意見:
真是太酷了,加油哦!
你好,我有Flash 3d的專案,請問你接案子嗎?
沒有在接案,如果你需要 flash 3d 的接案高手,我建議你可以問問奶綠,認識他嗎?
張貼意見