Papervision3D
PV3D是一個開源的遵循MIT協議的使用AS3代碼寫成的3D引擎。這篇文章旨在教會各位如何使用PV3D完成一個HELLOWORD式的3D程序,同時也是這篇教程的最近更新。PV3D2.0
Alpha(也稱GW)對于初學者來說使用PV3D最大的障礙在于如何安裝PV3D,由于對版本控制軟件不熟是造成無法完成PV3D安裝的主要原因,第一部分的三節闡述了這個問題,但是不是這篇文章的主要內容,如果你對版本控制軟件不熟悉的話,那么你可以看看這部分。
【筆者注:】安裝PV3D完全沒有必要使用版本控制軟件,PV3D說白了就是一個FLEX的庫,如果你知道如何在FLEX中使用和導入庫,那么你完全沒有必要使用版本控制軟件,筆者的做法是到GOOGLE
CODE網站去下載一個ZIP包,軟后解壓縮到一個文件夾,將該文件夾包含在我的項目的庫目錄中就可以了,至于說更新,那么重新下載一個就搞定了。
再者版本控制軟件的使用教程,網上多如牛毛,我在這里也就不再累述了。第一節的三個部分都不做翻譯,在譯文中直接略去,望大家諒解
省略PV3D安裝部分。
Papervision3D
at the following link then skip to the “Foundation of Papervision3D”
section:
·
Revision
435: /trunk/branches/GreatWhite/src
If
you don’t know what to do with that link, then continue on reading the links in
the first three sections.
Download
First,
you need to download Papervision3D using subversion. Follow the instructions at
either of these sites:
·
How
Can I Download Papervision3D?
·
Downloading
Papervision3D Alpha Great White
Classpath類路徑
:為PV3D設置一個源代碼文件夾
·
如果使用的是Flash:
·
關于如何設置和修改源文件路徑
·
如果使用的是FLEX:
·
準備一個PV3D的項目
Document
Class文件類
Create
a document class to hold the required ActionScript:創建一個源文件
·
如果使用的是Flash:
·
使用AS3.0創建一個新的文檔類
·
Using
Flex: 如果使用的是FLEX:
·
創建一個新的AS工程
·
使用FLASHDEVELOP
集成環境
·
創建一個PV3D項目
Foundation
of Papervision3D PV3D基礎
.我盡量使得代碼看起來簡單以適應那些新上手AS3.0的用戶,但是我還是要假定你們知道類的基礎,如何寫方法,如何實例化對象等等,如果還不懂得這些的話,那么你可以參看OREILY的AS3.0編程基礎一書,對你非常有幫助,當我實例化對象的時候,我同時還假定了你自己會去導入那些我遺漏的包。
:每一個PV3D應用程序都至少要包含這四個類:Viewport3D,
Scene3D, Camera3D/ BasicRenderEngine(可選),在我進行詳細的講解之前請先瀏覽一下下面的代碼。

package{

import flash.display.Sprite;

import org.papervision3d.cameras.Camera3D;

import org.papervision3d.render.BasicRenderEngine;

import org.papervision3d.scenes.Scene3D;

import org.papervision3d.view.Viewport3D;


public class Main extends Sprite{

private var viewport:Viewport3D;

private var scene:Scene3D;

private var camera:Camera3D;

private var renderer:BasicRenderEngine;


public function Main(){

initPapervision3D();

}


private function initPapervision3D():void{

viewport = new Viewport3D();

addChild(viewport);

scene = new Scene3D();

camera = new Camera3D();

renderer = new BasicRenderEngine();

renderer.renderScene(scene, camera, viewport);

}

}

}


Viewport3D視口
可以將Viewport3D視口看成是PV3D的一扇窗戶,透過這扇窗戶我們才能看見PV3D世界里的東西。僅此而已,視口沒有其他的功能,你可以將窗口開在墻上,可以決定窗口的大小,僅此而已。使用這個類之要記得創建之后將其加入舞臺就可以了??纯聪旅娴拇a
private var viewport:Viewport3D = new Viewport3D();
addChild(viewport);


作為參考我將視口的缺省屬性列在下面,當然用戶可以根據各自的喜好進行修改。在未來的文章中我們將討論autoClipping
和
autoCulling
Viewport3D(viewportWidth:Number = 640, viewportHeight:Number = 480,

autoScaleToStage:Boolean = false, interactive:Boolean = false,

autoClipping:Boolean = true, autoCulling:Boolean = true)

Scene3D場景
繼續我們的窗口比喻,Scene3D通過窗口展示所有你能看見的3D物體:天空,大地,以及這之間的一切。然而Scene3D只是一個空的場景。要顯示的內容需要創建后逐一添加到場景,場景如下創建:
private
var scene:Scene3D = new Scene3D();
Camera3D鏡頭
如果沒有一個人來欣賞著窗戶和窗戶外的美景的話,那真的是沒有什么價值。很幸運,PV3D的開發者創建了鏡頭來捕捉動作,鏡頭也與許你設置X,Y,Z坐標來確定你從哪個角度來欣賞這個美景,想象一個第一人稱設計或者飛行游戲,你移動著你的位置來觀察現有的場景,對于Camera3D來說也是這樣的,你移動鏡頭,那么整個Scene3D根據你當前的位置調整
Papervision3D
provides three cameras with varying functionalities:PV3D提供了3只能夠鏡頭來適應你不同的需求
·
•要求目標朝著而且永遠朝著對象看,而不管他自己當前的位置
·
•提供了自由的可以在空間任意角度方向觀察的方法,例如yaw(),
pitch(), 和
roll()來調整鏡頭的角度,而moveForward(),
moveBackward(); moveLeft(), moveRight(), moveUp(), 和
moveDown()來調整鏡頭的位置,例如如果你要將鏡頭放置在直接朝向某人臉部的話那么你需要調用moveBackward(),雖然你一直盯著那個人的臉看,但是你離他越來越遠。換個角度說,如果你把鏡頭放在那個人的頭上,調用pitch()對著那個人看,然后再調用moveBackward(),這時雖然你在空中慢慢上升,但是你仍然朝著那個人看。
·
•截鏡頭-能夠像FreeCamera3D自由鏡頭那樣移動,但是它只能渲染你所決定的近距離或者是遠距離的物體。
BasicRenderEngine基本渲染引擎
:在PV3D的世界里,你就是上帝,也就是說你得來決定世界什么時候開始存在,如果沒有BasicRenderEngine來渲染你的世界,那么你的世界就不會存在,因此你可以自己有的決定這個引擎的開始和結束,BasicRenderEngine通過你設置的鏡頭的位置來渲染你的場景里的所有的物品
private var renderer:BasicRenderEngine = new BasicRenderEngine();

//Usually within an Event.ENTER_FRAME handler so the scene

renders in each frame
renderer.renderScene( scene, camera,

viewport );

即使你有許多的場景,視口,或者鏡頭你還是只需要一個渲染引擎來渲染所有的東西
//A snippet of multiple scenes, cameras, and viewport handled by one

renderer renderer.renderScene( scene, camera, viewport );

renderer.renderScene( scene2, camera2, viewport2 );

3D
Objects3D物體
3D
Coordinates3D坐標
在我們進入創建對象之前,讓我們先了解一下物體在3D的空間里,是如何放置的。
在FLASH的2D世界里,你在舞臺里放置對象的時候,坐標系是傳統的計算機坐標系:左上角是原點,X軸向右增加,Y軸向下增加,然而在PV3D的世界里這一切就被顛覆了,原點位于場景的中心,鏡頭默認放置在(0,0,-1000)位置處。
【筆者注:】我想3D的坐標系對于我們中國的開發者來說就不必累述了吧,我們在高中學過的立體幾何遠比這個復雜許多,外國人的數學一般都比較爛,所以他們需要詳細的學習這方面的知識,但是對于中國人來說真的是可以免了。
同時也要記住,你能看見的物體移動的距離和你鏡頭放置的位置是很有關系的,越近物體看起來就移動的越多,你不能在依賴于你在傳統的2D世界里積累起來的項目或是經驗,鏡頭放置在缺省的位置上再來考慮下面的例子
·
•
x = 10; //也就是場景中心右方10個單位
·
•
x = -10; //場景中心左方10個單位
·
•
y = -10; //場景中心下方10個單位
·
•
z = -10; //場景中心前方(離鏡頭近)10個單位
如果你非要弄清楚在2D的屏幕上3D是怎么實現的,那么準備你肚子里的數學貨色去閱讀下面的文章
http://en.wikipedia.org/wiki/Quarterion
http://www.adobe.com/devnet/flash/articles/3d_classes_03.html
http://www.isner.com/tutorials/quatSpells/quaternion_spells_14.htm
即使你不懂得文章中提到的數學知識,你應該大致懂得了3D對象是在3D坐標的基礎上創建起來的,這些3D的坐標或者說是頂點是通過三角形,傾斜之后的繪制使得物體看上去具有3D效果的。PV3D使用畫家算法來排序那些三角形的可見度,對于FP來說畫家算法效率很高,但是如果三角形發生重疊的話,畫家算法就會失效,要解決這個問題只有創建更多的段來減少三角形重疊的問題
Plane平面
我認為對于PV3D來說屏幕是所有項目中最有用的3D物體,特別是如果該項目是交互式的,但是奇怪的是,嚴格的來說平面不能被稱為3D物體因為他沒有厚度,PV3D里平面的形象表示是兩個直角三角形沾在一塊兒就成了一塊平面,記住場景保存了你所能觀察到的所有的物體,如果你要使用平面,那么不要忘了,創建了它之后將其添加到場景里去
var plane:Plane = new Plane();

scene.addChild(plane);

平面缺省使用了線幀材料(在以后的文章里討論)并且寬和高都是500,因此上面的代碼會創建一個放置在場景中心的(0,0,0)DE
寬和高都是500面對著鏡頭的平面,代碼如下:
SegmentsW
和
segmentsH,以及“段”數目,寬,高,更多數量的端避免了平面在旋轉的時候扭曲等錯誤,下面的例子展示了SW,SH兩個屬性分別為4和3時候的情況
Plane( material:MaterialObject3D=null, width:Number=0,

height:Number=0, segmentsW:Number=0, segmentsH:Number=0,

initObject:Object=null )

材料,寬,高,這些屬性很容易就能理解。在平面的方法里分別設置其“段”的
如果你創建了許多的平面,而且每一個都要進行SEGMENT的設置的話,那你可能要抓狂了,(但是SEGMENT確實提高了平面的細節程度)FP要處理的三角形的個數依賴于你的程序,但是盡量避免使這個數目超過2000
最后一個可選的屬性參數,initObject同樣能夠存儲3D對象的x,
y, z, rotationX, rotationY, rotationZ, scaleX, scaleY, scaleZ,屬性,在創建了3D對象之后你可以直接設置這個值,下面的例子快速的展現了這一點
var m:WireframeMaterial = new WireframeMaterial();

//width and height

var w:Number = 800;

var h:Number = 800;

//segmentsW and segmentsH

var sW:Number = 1;

var sH:Number = 1;

var initObject:Object = new Object();

initObject.x = 100;

initObject.rotationY = 30;

initObject.scaleZ = 20;

//Option #1 using initObject可選1使用initObject

var plane:Plane = new Plane(m, w, h, sW, sH, initObject);

scene.addChild(plane);

//Option #2 setting properties directly可選2直接設置

var plane:Plane = new Plane(m, w, h, sW, sH, initObject);

plane.x = 100;

plane.rotationY = 30;

plane.scaleZ = 20;

scene.addChild(plane);

.關于平面的最后一點,如果你釘住一個平面,你就會注意到從屏幕的另一側來看的時候平面就消失了,如果你有平面的雙面紋理材料那么你需要設置平面的doubleSided屬性,如下:
material.doubleSided
= true;
Sphere球體
你可以和創建屏幕非常類似的那樣來創建一個球體
var sphere:Sphere = new Sphere();

scene.addChild(sphere);

球體的缺省參數和平面很相似,球體初始化的時候只需要一個半徑參數,這一點和平面是不同的,【BLUR,BLUR
BLUR球體的俄數學知識介紹譯者注】缺省參數如下:
Sphere( material:MaterialObject3D=null, radius:Number=100,

segmentsW:int=8, segmentsH:int=6,

initObject:Object=null )

為了簡單起見,錐體和柱體就簡單的列出了創建方法了,原理和上面描述的也差不多:
Cone( material:MaterialObject3D=null, radius:Number=100,

height:Number=100, segmentsW:int=8, segmentsH:int=6,

initObject:Object=null )


Cylinder( material:MaterialObject3D=null, radius:Number=100,

height:Number=100, segmentsW:int=8, segmentsH:int=6,

topRadius:Number=-1,

initObject:Object=null )

Cube正方體
如果拿出6個平面并將其組裝為一個盒子,你能像到什么?一個立方體
到現在你已經懂得了如何創建3d對象,除了立方體引入了一個MaterialsList(稍侯討論),閱讀一下如何創建一個立方體你大概就明白了如何創建一個MaterialsList
var frontMaterial:WireframeMaterial = new WireframeMaterial();

var backMaterial:WireframeMaterial = new WireframeMaterial();

var leftMaterial:WireframeMaterial = new WireframeMaterial();

var rightMaterial:WireframeMaterial = new WireframeMaterial();

var topMaterial:WireframeMaterial = new WireframeMaterial();

var bottomMaterial:WireframeMaterial = new WireframeMaterial();

var materialsList:MaterialsList = new MaterialsList();

materialsList.addMaterial(frontMaterial, "front");

materialsList.addMaterial(backMaterial, "back");

materialsList.addMaterial(leftMaterial, "left");

materialsList.addMaterial(rightMaterial, "right");

materialsList.addMaterial(topMaterial, "top");

materialsList.addMaterial(bottomMaterial, "bottom");

var cube:Cube = new Cube(materialsList);

scene.addChild(cube);

如果鏡頭缺省設置的話,立方體渲染的時候看起來是劇中的,鏡頭直對著立方體,沒有任何角度的話,立方體看起來就像一個平面,你可以通過設置立方體的rotation屬性來觀察立方體的全部效果,下面是立方體的全部缺省參數
Cube(
materials:MaterialsList, width:Number=500, depth:Number=500,
height:Number=500,
segmentsS:int=1, segmentsT:int=1, segmentsH:int=1,
insideFaces:int=0,
excludeFaces:int=0, initObject:Object=null )
段需要稍加解釋,然而函數和平面的段是基本一致的。
·
•
segmentS -段徑向的數目(如果是平面的話就是和寬垂直)默認為1
·
•
segmentsT -. 段縱向的數量(如果是平面的話就是和厚度垂直),缺省和sS一樣
·
•
segmentsH -水平方向的段數量(平面的話就是和高垂直)缺省和sS一樣
insideFaces參數決定了立方體內部的面是如何渲染的,這對于將鏡頭放在立方體內部是有效的,使用以下的立方體的靜態參數來確定你想要包含的面
·
•
Cube.NONE
·
•
Cube.FRONT
·
•
Cube.BACK
·
•
Cube.LEFT
·
•
Cube.RIGHT
·
•
Cube.TOP
·
•
Cube.BOTTOM
·
•
Cube.ALL
只需要簡單的創建一個insideFaces整型常量然后將其添加到合適的地方。例如:如果你只要立方體的內部的上面那么可以這么寫
var
insideFaces:int = Cube.TOP;
var
cube:Material = new Cube(m, w, d, h, sS, sT, sH,
insideFaces);
如果你需要立方體內的左和右面那么可以這么寫
var
insideFaces:int = Cube.LEFT + Cube.RIGHT + Cube.BOTTOM;
var
cube:Material = new Cube(m, w, d, h, sS, sT, sH,
insideFaces);
如果你想要所有的面除了前面,那么可以這么寫
var
insideFaces:int = Cube.ALL - Cube.FRONT;
var
cube:Material = new Cube(m, w, d, h, sS, sT, sH,
insideFaces);
下一個參數excludeFaces原理是一樣的,但是它的作用是排除那些你不想要的面
Collada3DMAX支持的文件
這才是PV3D使人興奮的地方,你可以通過你熟悉的3D工具創建你想要的3D模型,然后將其到處為COLLADA文件然后通過PV3D的DAE類進行裝載,不幸的是這一點的討論足足需要一篇文章,但是如果你想看看的話,可以點擊下面的例子
Loading
Collada Files into Papervision3D
Testing
Kinematics with Papervision3D Collada
DCC
Tutorials
Enough
Talk, Let’s See Code!談的夠多了,看看代碼吧
我打賭你一定覺得學的夠多了,而迫不及待的要敲擊鍵盤了,下面我們就給出一個完整的PV3D的例子

package {

import flash.display.Sprite;

import flash.events.Event;

import org.papervision3d.cameras.Camera3D;

import org.papervision3d.materials.WireframeMaterial;

import org.papervision3d.materials.utils.MaterialsList;

import org.papervision3d.objects.primitives.Cube;

import org.papervision3d.render.BasicRenderEngine;

import org.papervision3d.scenes.Scene3D;

import org.papervision3d.view.Viewport3D;

[SWF ( width = '640', height = '480', backgroundColor = '#ffffff',

frameRate = '31' ) ]


public class RotatingCubeExample extends Sprite {

private var viewport:Viewport3D;

private var scene:Scene3D;

private var camera:Camera3D;

private var renderer:BasicRenderEngine;

private var cube:Cube;


public function RotatingCubeExample(){

'initPapervision3D();

createCube();

beginRender();

}


private function initPapervision3D():void{

viewport = new Viewport3D();

addChild(viewport);

scene = new Scene3D();

camera = new Camera3D();

renderer = new BasicRenderEngine();

}


private function createCube():void{

var allM:WireframeMaterial = new WireframeMaterial();

var m:MaterialsList = new MaterialsList();

m.addMaterial(allM, "all");

//width, depth, height

var w:Number = 300;

var d:Number = 500;

var h:Number = 700;

//segments S, T, and H

var sS:int = 2;

var sT:int = 3;

var sH:int = 4;

cube = new Cube(m, w, d, h, sS, sT, sH);

scene.addChild(cube);

}


private function beginRender():void{

//calls the render function every frame

addEventListener(Event.ENTER_FRAME, render);

}


private function render(e:Event):void{

//rotates around the vertical axis

cube.yaw(2);

//rotates around the lateral axis

cube.pitch(1);

renderer.renderScene(scene, camera, viewport);

}

}

}

常見的錯誤:救命!我看不見任何東西
·
1.你恰當的導入了所有的類嗎?
·
2.你將場景加入容器了嗎?
addChild(viewport);
·
3.你將所有的對象都加入到了場景里嗎?
scene.addChild(cube);
·
4.你渲染了你的場景嗎?
renderer.renderScene(scene,
camera, viewport);
Just
Getting Started僅僅是開始
我希望你認識到這篇文章所觸及的不過是冰山的一角,下面的文章將討論紋理方面的知識,這樣你就可以做出更加好,更加漂亮的3D對象了
Thanks致謝
我想要謝謝PV3D的所有開發人員,給予我們這樣優秀的PV3D產品,我也要謝謝郵件列表中,開源社區的所有人,你們共同制造了這樣的一個優秀產品
·
Core
team
·
Carlos
Ulloa
·
John
Grden
·
Ralph
Hauwert
·
Tim
Knip
·
Andy
Zupko
·
Committer
team
·
Mr.doob
·
De'Angelo
Richardson
·
Tink
·
Seb-Lee
Delisle
·
Contributors
·
Patrick
Pietens
·
Ron
Valstar
源文檔
<http://www.insideria.com/2008/02/papervision3d-part-1-foundatio.html>
Papervision3D
Papervision3D
is an open-source, MIT licensed 3D engine written in ActionScript 3.0 for Flash.
This article will teach you how to set up your first Papervision3D application
with the most recent revision as of this writing, Papervision3D 2.0 Alpha,
otherwise known as “Great White.” The great barrier for beginners is usually
“installing” Papervision3D as they are unfamiliar with subversion, classpaths,
and documents classes. The first three sections address these issues with
off-site tutorials as that process is not within the scope of this article. So
if you’re familiar with the subversion process and setting up an ActionScript
3.0 project, check out Papervision3D at the following link then skip to the
“Foundation of Papervision3D” section:
·
Revision
435: /trunk/branches/GreatWhite/src
If
you don’t know what to do with that link, then continue on reading the links in
the first three sections.
Download
First,
you need to download Papervision3D using subversion. Follow the instructions at
either of these sites:
·
How
Can I Download Papervision3D?
·
Downloading
Papervision3D Alpha Great White
Classpath
Set
up a classpath that points to the Great White “src”
directory:
·
Using
Flash:
·
About
Setting and Modifying the Classpath
·
Using
Flex:
·
Preparing
a Papervision3D Project
Document
Class
Create
a document class to hold the required ActionScript:
·
Using
Flash:
·
Creating
a Document Class with ActionScript 3.0
·
Using
Flex:
·
New
-> ActionScript Project”
·
Using
FlashDevelop:
·
Preparing
a Papervision3D Project
Foundation
of Papervision3D
I’ll
keep the code as simple as I can for those of you new to ActionScript 3.0, but I
will assume you have a basic understanding of importing classes,
declaring/instantiating variables, and writing/calling methods. If not,
O’Reilly’s “Essential ActionScript 3.0” is a great place to start. When I instantiate
objects in code snippets, I’ll assume you understand you need to import the
relevant classes.
Every
Papervision3D application requires four classes: Viewport3D, Scene3D, Camera3D
(or alternatives), and BasicRenderEngine (or alternative). Glance at the
following typical set up of a Papervision3D project before I dive into a full
explanation:
package{
import
flash.display.Sprite;
import
org.papervision3d.cameras.Camera3D;
import
org.papervision3d.render.BasicRenderEngine;
import
org.papervision3d.scenes.Scene3D;
import
org.papervision3d.view.Viewport3D;
public class Main extends Sprite{
private var
viewport:Viewport3D;
private var
scene:Scene3D;
private var
camera:Camera3D;
private var
renderer:BasicRenderEngine;
public function Main(){
initPapervision3D();
}
private function
initPapervision3D():void{
viewport = new
Viewport3D();
addChild(viewport);
scene = new
Scene3D();
camera = new
Camera3D();
renderer = new
BasicRenderEngine();
renderer.renderScene(scene,
camera, viewport);
}
}
}
Viewport3D
Think
of a Viewport3D as a window to the world of Papervision3D. Windows allow you to
see outside, but they serve no other function. You can position a window on the
wall or change its width and height, but that’s really about it. The same is
true with Viewport3D. You can change the “x”, “y”, “width”, and “height” of the
Viewport3D, but its only true functionality is to let you look at the 3d scene
inside of it. To use a viewport, create it then add it to the
stage.
private
var viewport:Viewport3D = new Viewport3D();
addChild(viewport);
For
reference, the default parameters of Viewport3D, which you can adjust to your
liking, are as follows. I’ll cover interactive, autoClipping, and autoCulling in
a future article:
Viewport3D(viewportWidth:Number
= 640, viewportHeight:Number = 480,
autoScaleToStage:Boolean
= false, interactive:Boolean = false,
autoClipping:Boolean
= true, autoCulling:Boolean = true)
Scene3D
To
continue with the window metaphor, a Scene3D would hold everything you could see
looking through the window: the ground, the sky, and everything in-between. Yet
the Scene3D is still just empty 3D space. You have to add the ground, the sky,
the trees, etc., by adding 3d objects to your Scene3D. A scene3D is created as
follows:
private
var scene:Scene3D = new Scene3D();
Camera3D
A
window and an outside world are pretty worthless if there’s no one there to
witness their beauty. Luckily for you, the developers of Papervision3D created
cameras to capture all the action. A Camera3D allows you to set the x, y, and z
coordinates from where you want to capture the action. Imagine a first-person
shooter or flight simulator. You move your character around and the surrounding
area adjusts to your current position. The same idea applies to Camera3D
movement: you move the camera and the entire Scene3D adjusts to its current
position.
Papervision3D
provides three cameras with varying functionalities:
·
•
Camera3D- requires a target to “look at” and will always “look at” that target
regardless of position
·
•
FreeCamera3D- moves freely through 3D space in every angle and direction.
Includes methods such as yaw(), pitch(), and roll() to adjust the camera’s
viewing angle as well as moveForward(), moveBackward(); moveLeft(), moveRight(),
moveUp(), and moveDown() to adjust the camera’s position based on its viewing
angle. For example, if you position the camera looking straight at someone’s
face then call moveBackward(), you will move farther and farther back from that
person’s face while still looking straight their face. On the other hand, if you
position the camera above the person, pitch() the camera to look straight down
at their hair, and then call the same moveBackward() method, you will lift the
camera higher into the sky while continuing to look at the person’s hair.
·
•
FrustumCamera3D- moves like FreeCamera3D, but only renders the objects within a
field of view, far distance, and near distance that you determine.
BasicRenderEngine
In
the world of Papervision3D, you’re God. That means you get to decide when the
world exists. Without the BasicRenderEngine class rendering your world, it just
won’t exist. So you can start and stop the engine as you please. The
BasicRenderEngine renders a Scene3D from the Camera3D position through the
Viewport3D that you choose:
private
var renderer:BasicRenderEngine = new BasicRenderEngine();
//Usually
within an Event.ENTER_FRAME handler so the scene
renders
in each frame
renderer.renderScene( scene, camera,
viewport
);
Even
if you have multiple scenes, viewports, or cameras, you still only need one
BasicRenderEngine to handle all of the rendering:
//A
snippet of multiple scenes, cameras, and viewport handled by one
renderer
renderer.renderScene( scene, camera, viewport );
renderer.renderScene(
scene2, camera2, viewport2 );
3D
Objects
3D
Coordinates
Before
diving into creating objects, let’s take a look at how objects are positioned in
3D space as opposed to traditional Flash projects.
In
Flash, you position an object on the stage based on x:0 and y:0 being in the
upper-left corner. Increasing x moves an object to the right and increasing y
moves an object down. Conversely, in Papervison3D x:0, y:0, and z:0 are in the
center (not the upper-left) of the Scene3D. Since the Camera3D defaults to x:0,
y:0, z:-1000 and points at the origin (x:0, y:0, z:0), increasing x moves the
object right, increasing y moves the object up, and increasing z moves the
object toward the horizon.
Also,
remember the amount of movement you will see is based on how close the camera is
to the 3d object. The closer the camera the more objects will appear to move.
You cannot rely on pixels like you can in a traditional two dimensional Flash
project. Consider the following examples based on the default camera
position:
·
•
x = 10; //means 10 units right of Scene3D’s center
·
•
x = -10; //means 10 units left of Scene3D’s center
·
•
y = -10; //means 10 units below Scene3D’s center
·
•
z = -10; //means 10 units closer to the camera from Scene3D’s center (remember
Camera3D defaults to z:-1000 so moving from 0 to -10 brings the object closer to
-1000.)
If
you’re the type of person who must understand how 3D coordinates are possible
within in a 2D Flash Player, put on your math hat and read up on
quarterions:
http://en.wikipedia.org/wiki/Quarterion
http://www.adobe.com/devnet/flash/articles/3d_classes_03.html
http://www.isner.com/tutorials/quatSpells/quaternion_spells_14.htm
Even
if you don’t understand the math involved in those articles, you probably
understand that 3D objects are made up groups of 3D coordinates. These 3D
coordinates (also known as vertices) form triangles. The triangles form a
polygon mesh or, in layman’s terms, a 3D object.
On
a side note, Papervision3D uses the Painter’s Algorithm to sort the visibility
of those triangles. The Painter’s Algorithm evaluates the sorting quickly (ideal
for Flash Player), but can fail if triangles overlap. You typically resolve this
issue by creating more segments in your 3D object to give less chance that the
triangles overlap.
Plane
I
consider Planes to be the most useful 3D objects for most Papervision3D
projects, especially if the project is interactive. Oddly enough, a Plane does
not technically qualify as a 3D object as it has no depth. A Plane is simply two
triangles stuck together to form a rectangle. Remember, the Scene3D holds all of
your 3D objects. So to use a plane, create it then add it to the
Scene3D.
var
plane:Plane = new Plane();
scene.addChild(plane);
A
Plane defaults to a WireFrameMaterial (discussed in a later article) with a
width of 500 and height of 500. So using the above code will result in a
wireframe Plane centered at x:0, y:0, and z:0 with a width and height of 500
facing the camera (assuming the camera is in its default position discussed
earlier). When you pass a material with an image inside it, the Plane will
default to the width and height of the bitmap of that image. The parameters
available for a Plane are as follows:
Plane(
material:MaterialObject3D=null, width:Number=0,
height:Number=0,
segmentsW:Number=0, segmentsH:Number=0,
initObject:Object=null
)
Material,
width, and height are pretty self-explanatory. SegmentsW and segmentsH set the
number of segments in the width and height of the Plane respectively. Multiple
segments help to avoid the distortion of an image when the Plane starts rotating
as well as the depth sorting of the triangles as mentioned earlier. The
screenshot below demonstrates a Plane with four segmentsW and three
segmentsH.
Be
wary when creating many Planes as each additional width or height segment you
create tacks on two more triangles (essentially forming another rectangle inside
the Plane to give the plane more detail). The number of triangles Flash Player
can handle varies depending on your application, but generally try and keep the
triangle count below 2000.
The
last optional parameter, initObject, can store the initial x, y, z, rotationX,
rotationY, rotationZ, scaleX, scaleY, scaleZ, and “extra” parameters.
Alternatively, you can directly set the listed properties after instantiating
your Plane. A quick example will explain nicely:
var
m:WireframeMaterial = new WireframeMaterial();
//width
and height
var
w:Number = 800;
var
h:Number = 800;
//segmentsW
and segmentsH
var
sW:Number = 1;
var
sH:Number = 1;
var
initObject:Object = new Object();
initObject.x
= 100;
initObject.rotationY
= 30;
initObject.scaleZ
= 20;
//Option
#1 using initObject
var
plane:Plane = new Plane(m, w, h, sW, sH, initObject);
scene.addChild(plane);
//Option
#2 setting properties directly
var
plane:Plane = new Plane(m, w, h, sW, sH, initObject);
plane.x
= 100;
plane.rotationY
= 30;
plane.scaleZ
= 20;
scene.addChild(plane);
One
final note about Planes: if you spin a Plane, you’ll notice the plane will
disappear once you look at the other side. If you want to have a texture on both
sides of the Plane, you will need to enable the “doubleSided” property of your
material you pass into your Plane.
material.doubleSided
= true;
Sphere
You
create a Sphere very similarly to the way you create a
Plane:
var
sphere:Sphere = new Sphere();
scene.addChild(sphere);
A
Sphere’s default parameters closely resemble a Plane’s parameters as well. The
Sphere just takes a radius parameter instead of width and height. If you think
back to high school, you will probably recall the radius being the distance from
the center of the circle to the outer edge. As opposed to the simplicity of
width and height of a Plane, the Sphere now uses the radius to calculate the
distance between the center and the edges to create groups of three vertices
that make groups of triangles that make the Sphere. Pretty neat, huh? The
default parameters are as follows:
Sphere(
material:MaterialObject3D=null, radius:Number=100,
segmentsW:int=8,
segmentsH:int=6,
initObject:Object=null
)
For
brevity’s sake, a Cone and a Cylinder can be created similarly with the
following default parameters:
Cone(
material:MaterialObject3D=null, radius:Number=100,
height:Number=100,
segmentsW:int=8, segmentsH:int=6,
initObject:Object=null
)
Cylinder(
material:MaterialObject3D=null, radius:Number=100,
height:Number=100,
segmentsW:int=8, segmentsH:int=6,
topRadius:Number=-1,
initObject:Object=null
)
Cube
What
do you get when you take six Planes and organize them into the shape of a box? A
Cube!
By
now you should be getting the hang of creating 3D objects, but the Cube throws
in a curve ball by requiring a MaterialsList (discussed in a later article). You
will probably get the gist of how to use a MaterialsList by reading how to
create a Cube:
var
frontMaterial:WireframeMaterial = new WireframeMaterial();
var
backMaterial:WireframeMaterial = new WireframeMaterial();
var
leftMaterial:WireframeMaterial = new WireframeMaterial();
var
rightMaterial:WireframeMaterial = new WireframeMaterial();
var
topMaterial:WireframeMaterial = new WireframeMaterial();
var
bottomMaterial:WireframeMaterial = new
WireframeMaterial();
var
materialsList:MaterialsList = new MaterialsList();
materialsList.addMaterial(frontMaterial,
"front");
materialsList.addMaterial(backMaterial,
"back");
materialsList.addMaterial(leftMaterial,
"left");
materialsList.addMaterial(rightMaterial,
"right");
materialsList.addMaterial(topMaterial,
"top");
materialsList.addMaterial(bottomMaterial,
"bottom");
var
cube:Cube = new Cube(materialsList);
scene.addChild(cube);
The
Cube faces forward when rendered meaning, with the camera in the default z:-1000
looking at x:0, y:0, z:0 position, you will be looking directly at the back of
the Cube. Without any perspective, it will look exactly like a Plane. You can
easily set any of the Cube’s rotation properties to see the full effect (the
earlier Cube image was rotated slightly to show perspective). Now let’s cover
the default parameters of a cube:
Cube(
materials:MaterialsList, width:Number=500, depth:Number=500,
height:Number=500,
segmentsS:int=1, segmentsT:int=1, segmentsH:int=1,
insideFaces:int=0,
excludeFaces:int=0, initObject:Object=null )
The
segments require a little explaining, yet function in the same fashion as
Plane’s segments:
·
•
segmentS - Number of segments sagitally (plane perpendicular to width). Defaults
to 1.
·
•
segmentsT - Number of segments transversally (plane perpendicular to depth).
Defaults to segmentsS.
·
•
segmentsH - Number of segments horizontally (plane perpendicular to height).
Defaults to segmentsS.
The
insideFaces parameter determines which faces will be rendered on the inside of
the Cube. This is useful if you want to have the camera inside of the Cube for
the illusion of being trapped in a room. To set the faces you want to include,
use the following static public variables of Cube:
·
•
Cube.NONE
·
•
Cube.FRONT
·
•
Cube.BACK
·
•
Cube.LEFT
·
•
Cube.RIGHT
·
•
Cube.TOP
·
•
Cube.BOTTOM
·
•
Cube.ALL
Simply
create an insideFaces integer that describes which faces you want to see on the
inside and pass it as a parameter where appropriate. For example, if you want
just the top of the inside of the Cube to be rendered, write the
following:
var
insideFaces:int = Cube.TOP;
var
cube:Material = new Cube(m, w, d, h, sS, sT, sH,
insideFaces);
For
just the left, right, and bottom face:
var
insideFaces:int = Cube.LEFT + Cube.RIGHT + Cube.BOTTOM;
var
cube:Material = new Cube(m, w, d, h, sS, sT, sH,
insideFaces);
For
all the faces except the front face:
var
insideFaces:int = Cube.ALL - Cube.FRONT;
var
cube:Material = new Cube(m, w, d, h, sS, sT, sH,
insideFaces);
The
next parameter, excludeFaces, works exactly the same way, but excludes the faces
you don’t want. Think of it like taking the lid of a
shoebox.
Collada
This
is where Papervision3D gets really exciting: you create a model in your
preferred 3D modeling program (3ds max, Maya, Blender, Swift3D, etc.), export it
as a Collada file, and load it using the Papervision3D DAE class. Unfortunately,
this topic deserves an article unto itself, but here are a few demos to get you
on the right track:
Loading
Collada Files into Papervision3D
Testing
Kinematics with Papervision3D Collada
DCC
Tutorials
Enough
Talk, Let’s See Code!
I
bet you’re anxious to start tickling the keyboard to see if it laughs out a
working Papervision3D project. So let’s make a Cube and spin it using the Cube
yaw() and pitch() methods (Don’t fret, I’ll cover the details of yaw, pitch,
roll, etc. in future articles):
package
{
import
flash.display.Sprite;
import
flash.events.Event;
import
org.papervision3d.cameras.Camera3D;
import
org.papervision3d.materials.WireframeMaterial;
import
org.papervision3d.materials.utils.MaterialsList;
import
org.papervision3d.objects.primitives.Cube;
import
org.papervision3d.render.BasicRenderEngine;
import
org.papervision3d.scenes.Scene3D;
import
org.papervision3d.view.Viewport3D;
[SWF ( width = '640', height = '480',
backgroundColor = '#ffffff',
frameRate
= '31' ) ]
public class RotatingCubeExample extends
Sprite {
private var
viewport:Viewport3D;
private var
scene:Scene3D;
private var
camera:Camera3D;
private var
renderer:BasicRenderEngine;
private var
cube:Cube;
public function
RotatingCubeExample(){
'initPapervision3D();
createCube();
beginRender();
}
private function
initPapervision3D():void{
viewport = new
Viewport3D();
addChild(viewport);
scene = new
Scene3D();
camera = new
Camera3D();
renderer = new
BasicRenderEngine();
}
private function
createCube():void{
var allM:WireframeMaterial = new
WireframeMaterial();
var m:MaterialsList = new
MaterialsList();
m.addMaterial(allM,
"all");
//width, depth,
height
var w:Number =
300;
var d:Number =
500;
var h:Number =
700;
//segments S, T, and
H
var sS:int = 2;
var sT:int = 3;
var sH:int = 4;
cube = new Cube(m, w, d, h, sS, sT,
sH);
scene.addChild(cube);
}
private function
beginRender():void{
//calls the render function every
frame
addEventListener(Event.ENTER_FRAME,
render);
}
private function
render(e:Event):void{
//rotates around the vertical
axis
cube.yaw(2);
//rotates around the lateral
axis
cube.pitch(1);
renderer.renderScene(scene, camera,
viewport);
}
}
}
Common
Mistakes: Help! I Don’t See Anything!
·
1.
Did you properly import the Papervision3D classes?
·
2.
Did you “addChild()” your viewport?
addChild(viewport);
·
3.
Did you “scene.addChild()” your 3D Object?
scene.addChild(cube);
·
4.
Did you render your scene?
renderer.renderScene(scene, camera,
viewport);
Just
Getting Started
I
hope you realize that this article barely touched the tip of the Papervision3D
iceberg. The next article will cover the materials (sometimes known as textures)
so you can make your 3D objects look nice and pretty.
Thanks
I’d
like to thank all of the members of the Papervision3D team, everyone who has
ever helped anyone on the Papervision3D mailing list, and the community for
making such a wonderful open-source product:
·
Core
team
·
Carlos
Ulloa
·
John
Grden
·
Ralph
Hauwert
·
Tim
Knip
·
Andy
Zupko
·
Committer
team
·
Mr.doob
·
De'Angelo
Richardson
·
Tink
·
Seb-Lee
Delisle
·
Contributors
·
Patrick
Pietens
·
Ron
Valstar