2007年6月13日星期三

Papervision3D 教學 part 2.3 -- 用外部圖檔做貼圖材質

貼圖材質,除了可以貼純色 (ColorMaterial) 與 BitmapData (BitmapMaterial) 之外,還可以直接拿外部圖檔 (BitmapFileMaterial) 進行貼圖,以下這個範例我就是採用 BitmapFileMaterial 貼圖,並且每隔 3000 微秒就將圖片重新載入貼過!程式碼如下:


package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.events.*;
import flash.utils.*;

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 T2step4 extends Sprite
{
private static var PI:Number = Math.PI;
private static var TH:Number = PI / 180;

private var container:Sprite;
private var scene:Scene3D;
private var camera:Camera3D;
private var rootNode:DisplayObject3D;

private var du:Number = 0;

private var movingRadius:int = 2000;
private var movingHeight:int = 2000;

private var photoIdx:int = 1;
private var photoCount:int = 9;

private var timer:Timer;

public function T2step4()
{
// initialize the objects
init3D();

// add a listener for the 3D loop
addEventListener(Event.ENTER_FRAME, loop3D);
addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
}

private function init3D():void{

container = new Sprite();
addChild(container);

container.x = 200;
container.y = 200;

scene = new Scene3D(container);

camera = new Camera3D();
camera.y = movingHeight;
camera.z = -movingRadius;
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 myCube1:DisplayObject3D = rootNode.addChild(new Cube(new BitmapFileMaterial(getFileName()), 100, 100, 100, 1, 1, 1), "myCube1");
myCube1.y = 50;

timer = new Timer(3000, 0);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
}

private function loop3D(event:Event):void{

/*
du++;
if(du==360)du=0;
*/

du = 360 * (this.mouseX / stage.stageWidth);

var newX:Number = movingRadius * formatNum(Math.cos(du*TH), 3);
var newY:Number = movingHeight;
var newZ:Number = movingRadius * formatNum(Math.sin(du*TH), 3);

camera.x = newX;
camera.y = newY;
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);
}

private function onMouseWheel(event:MouseEvent):void{

//event.delta = 3 | -3

movingRadius -= event.delta*10;
if(movingRadius<=0)movingRadius=1;

movingHeight -= event.delta*10;
if(movingHeight<=200)movingHeight=200;
}

private function onTimer(event:TimerEvent):void{
var myCube1:DisplayObject3D = rootNode.getChildByName("myCube1");
myCube1.material = new BitmapFileMaterial(getFileName());
}

private function getFileName():String{
return "http://ben.rb.chang.googlepages.com/photos"+(Math.floor(Math.random()*photoCount)+1)+".JPG";
}
}
}


測試畫面如下:





同樣的機制,我把先前教過的範例再加上這個週期換圖的效果,感覺又更絢麗了!程式碼如下,每個 Cube 都有自己的 Timer 控制,換圖時間不一定,以亂數決定的!


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.* import flash.utils.Timer;
import flash.events.TimerEvent;

[SWF(backgroundColor="#000000", frameRate="60", width="400", height="400")]

public class Step8 extends Sprite
{
private var container:Sprite;
private var scene:Scene3D;
private var camera:Camera3D;
private var rootNode:DisplayObject3D;

private var AMOUNT:int = 50;
private var rotationSettingArray:Array = new Array();
private var timerArray:Array = new Array();

private var photoCount:int = 9;

public function Step8()
{
// 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.z = -3000;
camera.zoom = 10;
camera.focus = 100;

rootNode = scene.addChild(new DisplayObject3D("rootNode"));

for(var i:int=0; i<AMOUNT; i++){
var myCube:DisplayObject3D = rootNode.addChild(new Cube(new BitmapFileMaterial(getFileName()), 100, 100, 100, 1, 1, 1), "myCube" + i);

myCube.moveBackward(Math.random() * (3000-100/2+1));

if(Math.random()*2>1)
myCube.moveLeft(Math.random()*500);
else
myCube.moveRight(Math.random()*500);

if(Math.random()*2>1)
myCube.moveUp(Math.random()*500);
else
myCube.moveDown(Math.random()*500);

rotationSettingArray.push({rX:(Math.random()-Math.random())*2
, rY:(Math.random()-Math.random())*2
, rZ:(Math.random()-Math.random())*2});

var timer:Timer = new Timer((Math.round(Math.random()*5)+5)*1000, 0);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
timerArray.push(timer);
}
}

private function loop3D(event:Event):void{

for(var i:int=0; i<AMOUNT; i++){
var myCube:DisplayObject3D = rootNode.getChildByName("myCube" + i);

if(myCube!=null){
myCube.rotationX+=rotationSettingArray[i].rX;
myCube.rotationY+=rotationSettingArray[i].rY;
myCube.rotationZ+=rotationSettingArray[i].rZ;
}
}

scene.renderCamera(camera);
}

private function onTimer(event:TimerEvent):void{
for(var i:int=0; i<timerArray.length; i++){
if(event.target==timerArray[i]){
var myCube:DisplayObject3D = rootNode.getChildByName("myCube"+i);
var fileName:String = getFileName();
trace(fileName);
myCube.material = new BitmapFileMaterial(fileName);
}
}
}

private function getFileName():String{
return "http://ben.rb.chang.googlepages.com/photos"+(Math.floor(Math.random()*photoCount)+1)+".JPG";
}
}
}


看效果!

3 意見:

Victor 提到...

邦大,請問一下

我跑BitmapFileMaterial時,會下列發生錯誤
【強制轉型失敗: 無法將 "assets/images/big1.jpg" 轉換成 org.papervision3d.materials.BitmapFileMaterial。】

我的程式碼如下
var texture:BitmapFileMaterial = BitmapFileMaterial("assets/images/big1.jpg");

看了網路上BitmapFileMaterial的範例也是這樣寫,但不知為何我跑會產生錯誤

麻煩邦大出手相救一下 >"<

Ben Chang 提到...

var a:* = new MyClass("xxx");
建立 MyClass 這個類別的物件 a,建立時需要提供參數 "xxx"

var a:* = MyClass("xxx");
將 "xxx" 轉型成為 MyClass 類別,並將參考指派給 a

差別就只在於一個 new 關鍵字

Victor 提到...

沒發覺我少了一個new....

抱歉我耍笨了... XD