PV3D学习整理
1. PV3D调用的基本结构
有四个基础元素:Scene3D,Viewport3D,Camera3D,BasicRenderEngine
基本的调用如下:
package {import
flash.display.Sprite;import
flash.events.Event;import
org.papervision3d.cameras.Camera3D;import
org.papervision3d.materials.WireframeMaterial;import
org.papervision3d.objects.primitives.Sphere;import
org.papervision3d.render.BasicRenderEngine;import
org.papervision3d.scenes.Scene3D;import
org.papervision3d.view.Viewport3D; [SWF(backgroundColor="#869CA7"
)]public class
Sample1118extends
Sprite {private var
scene:Scene3D;private var
viewport:Viewport3D;private var
camera:Camera3D;private var
render:BasicRenderEngine;private var
sphere:Sphere;public function
Sample1118() { scene =new
Scene3D(); viewport =new
Viewport3D(); camera =new
Camera3D(); render =new
BasicRenderEngine(); sphere =new
Sphere(new
WireframeMaterial()); scene.addChild(sphere);this
.addChild(viewport); stage.addEventListener(Event.ENTER_FRAME,onEnterFrame); }private function
onEnterFrame(event:Event):void
{ sphere.rotationX += 2; sphere.rotationY += 2; render.renderScene(scene,camera,viewport); } } }
2. Scene3D
一个Scene3D实例是这个3D场景中所有物体的容器,它包括了整个3D场景,Scene3D这个类让所有创建在其中的3D物体得到渲染;物体要显示,该物体或它的父容器首先要加入到Scene3D的实例中
注意:虽然要显示的物体都要加入到Scene3D的实例中,但它并不是一个显示对象,也就是说它并不直接显示物体,真正显示物体的是Viewport3D
3. Viewport3D
viewport是视口的意思,可以理解为显示物体的一个窗口(矩形显示区域),它继承自Sprite,所以它可以直接被加入到显示列表中,我们PV3D中所看到的物体就是通过Viewport3D呈现的。同时它还实现了IViewport3D接口
构造函数是:
Viewport3D( viewportWidth:Number = 640, viewportHeight:Number = 480, autoScaleToStage:Boolean = false, interactive:Boolean = false, autoClipping:Boolean = true, autoCulling:Boolean = true )
参数说明:
viewportWidth -- 视口宽度,默认为640
viewportHeight -- 视口高度,默认为480
autoScaleToStage -- 是否随舞台大小改变而调整视口大小,默认为false。我的理解,一旦设置这个值为true,之前设置的 viewportWidth与viewportHeight好像就无效了,总是可以看到整个Scene3D里的内容
interactive -- 是否接受事件交互,默认为false,不接受任何交互(例如MouseEvent.Click)
autoClipping -- 是否不渲染视口外的物体,默认为true,不渲染
autoCulling -- 是否不渲染被遮挡的物体,默认为true,不渲染
4. Camera3D
可以把它理解为一个3D空间中的摄像头的镜头,我们在Viewport3D中看到的东西就是这个镜头所拍到的,当然我们就可以通过改变这个镜头的位置,角度,焦距等属性,来显示不同的场景或做移动的动画
构造函数是:
Camera3D( fov:Number = 60, near:Number = 10, far:Number = 5000, useCulling:Boolean = false, useProjection:Boolean = false )
fov -- 视场,是由zoom和focus三角计算而来的一个综合值,表示视野的广度。默认为60
后面4个参数,由于本人不懂摄影知识,花了很大气力也没完全搞明白;DDM君一篇文章说过:“后面的参数为制作大场景节约资源而使用的摄影机clipping,不懂clipping的概念可以无视”,咱就暂时先不研究这些参数了,呵呵,不过还是把含义列举一下,以后说不定会回头再研究
near和far -- 与其他三维软件相比如MAYA,感觉PV3D中没有真正意义上的near——它被设成与focus同值。near和far意即近平面和远平面,在此区间内的物体才能成像
useCulling -- 是否启用可视平截头体的裁剪(frustum culling),默认为false,不启用
useProjection -- 是否启用透视投影矩阵(projection matrix for perspective),默认为false,不启用
5. BasicView
通过继承这个类,可以很方便的创建一个包含前面那四个基本元素的3D世界,因为它是Sprite的子类,所以可以通过addChild添加到任何显示对象里
需要重写一个onRenderTick方法来处理渲染时产生的事件
override protected function onRenderTick(event:Event=null):void {}
另外还有3个方法,来控制渲染的开始与结束,分别有:
只渲染一次 -- singleRender():void
开始渲染 -- startRendering():void
停止渲染 -- stopRendering(reRender:Boolean = false, cacheAsBitmap:Boolean = false):void
package {import
flash.events.Event;import
flash.events.MouseEvent;import
org.papervision3d.materials.WireframeMaterial;import
org.papervision3d.objects.primitives.Sphere;import
org.papervision3d.view.BasicView;public class
Sample1122extends
BasicView {private var
_sphere:Sphere;public function
Sample1122() { super(); _sphere=new
Sphere(new
WireframeMaterial()); scene.addChild(_sphere);//singleRender();
startRendering(); stage.addEventListener(MouseEvent.CLICK,onClick); }private function
onClick(event:MouseEvent):void
{ stopRendering(); } overrideprotected function
onRenderTick(event:Event=null):void
{ _sphere.rotationY+=2; renderer.renderScene(scene,camera,viewport); } } }
6. Line3D和Lines3D
Lines3D可以看作是Line3D的一个容器,Line3D本身不能作为3D显示对象被直接加入到Scene3D中,只能通过Lines3D的addLine(line:Line3D)方法先加入到Lines3D以后,再把Lines3D加入到Scene3D里呈现
Line3D的构造函数:
Line3D( instance:Lines3D, material:LineMaterial, size:Number, vertex0:Vertex3D, vertex1:Vertex3D )
instance -- Lines3D实例
material -- 线条的材质(样式),new LineMaterial(color:Number=0xFF0000, alpha:Number=1)
size -- 线条的宽度
vertex0 -- 起始点坐标(x,y,z)
vertex1 -- 结束点坐标(x,y,z)
另外,Lines3D还有一个addNewLine()方法来直接添加线条,只需提供线条的宽度,起始点与结束点的坐标即可,默认生成的线条颜色是红色,并返回该线条的引用
Lines3D.addNewLine(size:Number, x0:Number, y0:Number, z0:Number, x1:Number, y1:Number, z1:Number):Line3D
package {import
flash.events.Event;import
org.papervision3d.core.geom.Lines3D;import
org.papervision3d.core.geom.renderables.Line3D;import
org.papervision3d.core.geom.renderables.Vertex3D;import
org.papervision3d.materials.special.LineMaterial;import
org.papervision3d.view.BasicView;public class
Sample1130extends
BasicView {private var
lines:Lines3D;public function
Sample1130() { lines =new
Lines3D();var
line:Line3D =new
Line3D(lines,new
LineMaterial(0xFF0000,1),new
2,
Vertex3D(0,0,0),new
Vertex3D(100,0,0)); lines.addLine(line); lines.addNewLine(3,100,100,0,200,200,0);this
.scene.addChild(lines); startRendering(); } overrideprotected function
onRenderTick(event:Event=null):void
{ lines.rotationY += 1; renderer.renderScene(scene,camera,viewport); } } }
7. Plane
代表一个平面,构造函数是:
Plane( material:MaterialObject3D = null, width:Number = 0,
height:Number = 0, segmentsW:Number = 0, segmentsH:Number = 0 )
参数说明:
material -- 材质,一般可以用ColorMaterial或BitmapFileMaterial
width -- 宽度,当材质为ColorMaterial时,需要同时设置height才能生效
height -- 高度
segmentsW -- 水平段数,适当提高可以使平面渲染更平滑
segmentsH -- 垂直段数,适当提高可以使平面渲染更平滑
package {import
flash.events.Event;import
org.papervision3d.materials.BitmapFileMaterial;import
org.papervision3d.materials.ColorMaterial;import
org.papervision3d.objects.primitives.Plane;import
org.papervision3d.view.BasicView;public class
Sample1208extends
BasicView {private var
plane:Plane;public function
Sample1208() {var
cm:ColorMaterial =new
ColorMaterial(0x00FF00,1); cm.doubleSided =true//默认是单面,须设置为true才为双面
var
bfm:BitmapFileMaterial =new
BitmapFileMaterial("map.jpg"
); bfm.doubleSided =true
; plane =new
Plane(bfm,600,600,4,4);this
.scene.addChild(plane); startRendering(); } overrideprotected function
onRenderTick(event:Event=null):void
{//沿X轴转动(世界坐标系)
//plane.rotationX+=2;
//沿Y轴转动(本地坐标系)
plane.yaw(2);//沿X轴转动(本地坐标系)
//plane.pitch(2);
renderer.renderScene(scene,camera,viewport); } } }
8. Scene3D的lookAt()和target
关于摄像机的具体细节,以后再好好研究一下,这里只做一个示例
需要注意的是,在Basicview下,只能设定target来监视物件,lookAt()无效
package {import
flash.events.Event;import
org.papervision3d.materials.ColorMaterial;import
org.papervision3d.materials.WireframeMaterial;import
org.papervision3d.objects.primitives.Plane;import
org.papervision3d.objects.primitives.Sphere;import
org.papervision3d.view.BasicView;public class
Sample1211extends
BasicView {private var
sphere:Sphere;public function
Sample1211() {var
colorMater:ColorMaterial =new
ColorMaterial(0xCCCCCC);var
plane:Plane =new
Plane(colorMater,10000,10000,8,8); plane.pitch(90);this
.scene.addChild(plane); sphere =new
Sphere(new
WireframeMaterial()); sphere.moveUp(400);this
.scene.addChild(sphere);this
.camera.moveUp(1000);this
.addEventListener(Event.ENTER_FRAME,onEnterFrame); startRendering(); }private function
onEnterFrame(event:Event):void
{ sphere.rotationY += 4; sphere.moveForward(50);this
.camera.target = sphere;//this.camera.lookAt(sphere);
} } }
9. 世界坐标系与本地坐标系
3D空间拥有一个世界坐标系,3D屏幕中的所有物体都可以在该坐标系系统下移动和旋转;对于屏幕上的所有物体来说,这个坐标系系统都是相同的,并且它不会改变。用户默认的观察视角是沿着Z轴的负半轴方向
除了世界坐标系外,每个物体都有一个本地坐标系,如图:
当物体旋转时,本地坐标系统也会跟着物体一起旋转,如图: