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
 Sample1118
extends
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接口

构造函数是:

public function
 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中看到的东西就是这个镜头所拍到的,当然我们就可以通过改变这个镜头的位置,角度,焦距等属性,来显示不同的场景或做移动的动画

构造函数是:

public function
 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
 Sample1122
extends
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();
  }
  
  override 
protected 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的构造函数:

public function
 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
 Sample1130
extends
BasicView
 {
  
private var
lines:Lines3D;
  
  
public function
 Sample1130()
  {
   lines = 
new
Lines3D();
   
var
line:Line3D = 
new
Line3D(lines,
new
LineMaterial(0xFF0000,1),
2,
new
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();
  }
  
  override 
protected function
 onRenderTick(event:Event=null):
void
 
  {
   lines.rotationY += 1;
   renderer.renderScene(scene,camera,viewport);
  }
 }
}

7. Plane

代表一个平面,构造函数是:

public function
 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
 Sample1208
extends
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();
  }
  
  override 
protected 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
 Sample1211
extends
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轴的负半轴方向

除了世界坐标系外,每个物体都有一个本地坐标系,如图:

当物体旋转时,本地坐标系统也会跟着物体一起旋转,如图:

posted @ 2010-07-15 14:52  CoderWayne  阅读(1613)  评论(1编辑  收藏  举报