Papervision3D Essentials 要点整理

二、构建你的第一个应用
我们需要一个 场景,摄像机,观察口,有材质的3d对象,和一个渲染引擎.
scene.addChild(sphere);
addChild(viewport);
renderEngine.renderScene(scene,camera,viewport);

BasicView类
startRendering();
override protected function onRenderTick(e:Event=null):void
{
sphere.localRotationX +=1;
super.onRenderTick();
}
BasicView构造方法
 
    参数    数据类型    默认值    说明      
1    viewportWidth    Number    640    观察口的宽度      
2    viewportHeight    Number    480    观察口的高度      
3    scaleToStage    Boolean    true    true时观察口的尺寸随舞台进行缩放,用来建立全舞台的观察口时很有用     
设置观察口的大小为800*600,在BasicView子类的构造器中输入:
Super(800,600,false);

三、基本几何体
类Vertices3D负责创建顶点,TriangleMesh3D类负责创建由顶点和三角面组成的3d对象.

将3d信息转换到2d屏幕,这个过程的顺序称为:渲染管道(rendering pipeline).
初始化  à 投影 à 渲染
投影:投影的过程只处理顶点,不处理三角面和材质.
渲染:此过程用附着的材质信息组成2d投影数据.

纸飞机(PaperPlane):为开发者提供一种用来执行全面测试的简单对象.

显示双面材质的一种方式是设置plane的meterial属性,将doubleSided属性设为true.
plane.material.doubleSided = true;

圆柱 Cylinder

圆锥体Cone

立方体Cube
Cube的构造器第一个参数不是材质,是材质列表(materials list).
var materialsList:MaterialsList = new MaterialsList();
materialsList.addMaterial(red,"front");
materialsList.addMaterial(red,"back");
materialsList.addMaterial(blue,"left");
materialsList.addMaterial(blue,"right");
materialsList.addMaterial(green,"top");
materialsList.addMaterial(green,"bottom");

materialsList.addMaterial( green,"all");

Cube的参数insideFaces指定立方体内部可见的面;参数excludeFaces指定不创建的面.
例如Cube.ALL-CUBE.LEFT;Cube.NONE

获取3d对象的尺寸(包围盒)
trace(paperPlane.boundingBox().size);

箭头 Arrow:
默认值是宽400,高100,深600.

嵌套 Nesting:
使用DisplayObject3D

访问顶点:每个3D对象的顶点都存放在一个数组中.
do3D.geometry.vertices

访问对象的三角面片:
do3D.geometry.faces

四、材质
基础材质类叫做MaterialObject3D

纹理和材质的区别在于纹理是被用作材质的图像源。
材质可以修改属性从而影响纹理贴到物体上的效果,你也可以这样理解材质,就是扩充了的纹理。
让物体不丢失性能且能增加一些额外的细节的技巧叫做烘焙纹理。
PV3d 将材质成2D方式扭曲,造成透视的假象。变形、扭曲后的图片贴在3D物体上看上去就很逼真了,这种PV3D的贴图方式我们叫做仿射贴图。

material.doubleSided = true;
material.oneSide = false;
material.opposite = true;
material.smooth = true;
material.interactive = true;

BitmapFileMaterial:
在文件加载好时,BitmapFileMaterial对象会发出一个FileLoadEvent.LOAD_COMPLETE事件
l    FileLoadEvent.LOAD_COMPLETE: 外部位图加载完成时,发出该事件。
l    FileLoadEvent.LOAD_PROGRESS: 外部位图加载过程中,发出该事件。
l    FileLoadEvent.LOAD_ERROR: 外部位图找不到时,发出该事件。
l    FileLoadEvent.SECURITY_LOAD_ERROR: 安全错误发生时,发出该事件。

precise 精细度 当设置为true时,就会动态的创建额外的三角面用更精细的方式来绘制材质

阻止材质扭曲:
当precise属性设置为true时,这会引起文本晃动和闪烁。
定义精度模式来避免摇晃闪烁效果。精度模式默认为:PrecisionMode.NORMAL,我们将它设置为:PrecisionMode.STABLE。
material.precisionMode = PrecisionMode.STABLE;

CompositeMaterial:
将不同的材质组合起来当做一种材质来使用
var material:CompositeMaterial = new CompositeMaterial();
material.addMaterial(bmpMaterial);
material.addMaterial(wireMaterial);

interactivity 交互:
要与材质或者3D对象进行鼠标交互必须先设置viewport的interactive属性为true。
viewport.interactive = true;
super(640,480,false,true);
var viewport:Viewport3D = new Viewport3D(640,480,false,true);
material.interactive = true;

Using ButtonMode 按钮模式:
private function mouseOver(e:MouseEvent):void
{
viewport.buttonMode = true;
}
private function mouseOut(e:MouseEvent):void
{
viewport.buttonMode = false;
}
viewport.getChildLayer(cube_1).buttonMode = true;

l    InteractiveScene3DEvent.OBJECT_ADDED
l    InteractiveScene3DEvent.OBJECT_CLICK
l    InteractiveScene3DEvent.OBJECT_DOUBLE_CLICK
l    InteractiveScene3DEvent.OBJECT_MOVE
l    InteractiveScene3DEvent.OBJECT_OUT
l    InteractiveScene3DEvent.OBJECT_OVER
l    InteractiveScene3DEvent.OBJECT_PRESS
l    InteractiveScene3DEvent.OBJECT_RELEASE
l    InteractiveScene3DEvent.OBJECT_RELEASE_OUTSIDE

Tiling 平铺:
使用平铺得置三个属性第一个属性tiled为True第二个和第三个是水平和纵向重复次数。
material.tiled = true;
material.maxU = 8;
material.maxV = 4;

Flipping your material 翻转材质:
Sprite 对象翻转:
给scaleX设置一个负值,横向翻转显示对象:
flippedSprite.scaleX = -1;
材质翻转:
BitmapMaterialTools.mirrorBitmapY()为纵向翻转.
BitmapMaterialTools.mirrorBitmapX(material.bitmap);

Power of two textures 2的幂数纹理:
你可以将位图的长宽随意设置为两个2的幂数组合。
我们可以使用PV3D实现的自动细化功能,这是BitmapMaterial类的一个静态属性。
BitmapMaterial.AUTO_MIP_MAPPING = true;

五、摄像机
Camera3D继承自CameraObject3D,CameraObject3D继承自DisplayObject3D.

moveForward(): 沿自身z轴向前移动对象.
moveBackward(): 沿自身z轴向后移动对象.
moveLeft(): 沿自身x轴向左移动对象
moveRight(): 沿自身x轴向右移动对象
moveUp(): 沿y轴向上移动对象
moveDown(): 沿y轴向下移动对象

分辨物体处于圆台内的过程及圆台之外的物体不渲染的过程称为:剔除(culling)
圆台剔除:这是刚才我们看过的-任何处于圆台之外的物体被剔除.Pv3d包含
背面剔除:背离摄影机的三角面被剔除.Pv3d包含
分配剔除:物体太小或距离太远不能附着材质,被剔除.Papervision3D不包含,但是可以告诉Papervision3D剔除与远景面相交的物体.
闭合剔除:一个对象完全的在另一个对象之后将被剔除,通常称其为隐面去除,Papervision3D不包含

开启圆台剔除:
只有完全的在圆台之外才被剔除camera.useCulling = true; 基于对象而非三角,当do3d开始剔除时打印true;
trace(do3d.culled);

开启观察孔级的剔除:
viewport.autoCulling = true;
此属性默认为true,所以完全可以不设置. 基于三角

剪裁:
通过将被剔除的三角分离到新的三角中的方式来解决此问题.
用FrustumClipping处理Papervision3D里的剪裁
它确保圆台之外的三角不被绘制
三角的顶点不被投影,提高性能
renderer.clipping = new FrustumClipping(FrustumClipping.NEAR);
FrustumClipping.ALL – 所有的便都进行剪裁处理
FrustumClipping.NEAR – 只有近景面不剪裁
FrustumClipping.TOP – 只有 顶部面不剪裁
FrustumClipping.BOTTOM – 只有底部面不剪裁
FrustumClipping.LEFT – 只有左边面不剪裁
FrustumClipping.RIGHT – 只有右边面不剪裁
使用FrustumClipping.NEAR就可以满足大部分情况.
因此出于性能的考虑,最好将圆台内对象的useClipping属性设为false.不过在camera.useCulling为true时,之后的操作便是多余的了.
使用圆台剪裁配合摄影机剔除.有2个好处:
因为对象处于圆台之外早已被剔除,他们不再需要剪裁测试了.
完全在圆台内的对象不需要剪裁测试.

precise在剔除和剪裁测试完毕之后.
precise的目的在于增加附着材质时的透视修正而不是为了阻止不必要的剔除.

l    缩放Zoom:缩放的默认值是40.
l    焦距Focus:减少焦距将增大视野.
l    视野Field of view,通常称其为fov或FoV:视野是摄影机在视图中的垂直角度. 默认值是60.
l    远景平面和近景平面 near,far:近景面与远景面定义了摄影机到2个面的距离.焦距是摄影机与近面之间的距离,near和focus相等.

只要继承自BasicView,就可以通过传递BasicView类构造器一个参数来选择摄影机类型.
super(stage.stageWidth,stage.stageHeight,true,false,
      CameraType.TARGET);
CameraType.TARGET
是一直注视一个目标的摄影机.目标只要是DisplayObject3D的实例就可以
camera.target = myTarget;
DisplayObject3D.ZERO返回一个空的,坐标为(0,0,0)的DsiplayObject3D对象
CameraType.FREE
行为与目标摄影机完全一样,不过没有注视的目标.自由摄影机一直向前看,方向是本地z轴.如果选择CameraType.FREE类型,目标便是null.
在目标与自由摄影机之间进行切换
很简单,2者的区别是有否有注视的目标.切换到自由摄影机,将目标设为null即可:
camera.target = null;
如果想切换到目标摄影机,为摄影机设定一个DisplayObject3D目标即可.
CameraType.DEBUG
注意到左上角显示的信息:坐标、旋转、视野、近与远
用W,A,S,D或箭头键来移动摄影机.同时还可以拖动鼠标来操作摄影机绕x,y轴旋转.用Q,E使其绕z轴旋转.
CameraType.SPRING
第三人称或狩猎的摄影机
var camera:SpringCamera3D = SpringCamera3D(camera);
camera.mass = 20;
camera.damping = 4;
camera.stiffness = 1;
camera.positionOffset = new Number3D(0,150,-500);
camera.lookOffset = new Number3D(0,0,100);
camera.target = paperPlane;
 
参数    数据类型    默认值    说明      
mass    Number    40    摄影机的质量或重量.定义了被拉动时的硬度.mass值越高越难移动      
damping    Number    4    阻尼:控制内部摩擦力或摄影机克服的弹力效果的力.值越大弹力效果越弱,促进了更平滑的移动.
将值保持在1到20间      
stiffness    Number    1    弹簧的硬度或弹簧被拉伸的程度.值越大弹簧越难以被拉伸,将值保持在1到20间      
positionOffset    Number3D    Number3D(0,5,-50)    摄影机的位置与目标局部空间的关系
      
lookOffset    Number3D    Number3D(0,2,10)    摄影机盯着目标局部空间的点.
Number3D(0,100,0)使摄影机盯着目标之上100单元处.     
target属性通常会在init()方法中设置一次而lookAt()方法需要在渲染的方法中来不断的调用.

六、物体运动
我们可以移动什么?
场景中的3d物体
摄影机
点光

基于帧的动画
帧率越高动画越平滑;但帧率过低的话,动画看起来像抽了筋.帧率越高动画越快,反之亦然.
基于时间的动画
基于时间的动画,动画的速度更依赖时间而不是帧率.此类的动画可以用ActionScript3的Timer类或补间引擎来完成.

旋转物体:
moveForward(),moveBackward(),moveLeft(),moveRight(),moveUp(),moveDown()方法,这些都可以让物体沿自身轴线移动.
localRotationX,localRotationY,和localRotationZ属性用来让物体绕自身的x,y,z轴旋转
本地旋转的另一种选择-pitch(),yaw(),和roll()
本地旋转与下面的3方法相对应:
pitch():绕自身x轴旋转物体(localRotationX)
yaw():绕自身y轴旋转物体(localRotationY)
roll():绕自身z轴旋转物体(localRotationZ)
do3D.yaw(1);
下面这话可以实现相同的功能:
plane.localRotationY++;

另一类的旋转-rotationX,rotationY,rotationZ
另一种旋转do3D物体的设置是rotationX,rotationY,totationZ.它们与本地旋转不同,它们不是让物体绕自身轴线旋转,而是绕局部空间的轴线(父对象坐标系的轴线)

当你设置旋转时,Papervision3D将欧拉角转换为四元数,最终用于旋转.
四元数可以3d物体的任何旋转及运行物体自由的绕任何轴旋转而不会出现上述问题.更多的Papervision3D里的四元数访问:
http://blog.zupko.info/?p=150

Papervision3D在y轴上加减与Flash的y轴加减是相反的.
camera.x = xDist * 2;
camera.y = -yDist * 2;

有缓动的鼠标交互:
camera.x += (xDist – camera.x * reachX) * easeOut;
easeOut变量确定了ease-out公式的强度-值越高,运动停顿时间越短.

用鼠标来旋转物体:
private var rotX:Number = 0.5;
private var rotY:Number = 0.5;
grid.rotationX += (yDist * rotX – grid.rotationX) * easeOut;
grid.rotationY += (xDist * rotY – grid.rotationY) * easeOut;

摄影机环绕物体:
摄影机环绕是让摄影机绕物体外围虚拟的球体进行旋转.这是一个比较流行的技术并且可以用camera.orbit()来完成.
camPitch = yDist * rotX + 90;
camYaw = xDist * rotY + 270;
camera.orbit(camPitch,camYaw);
 
    参数    数据类型    默认值    说明      
1    pitch    Number        环绕x轴      
2    yaw    Number        环绕y轴      
3    useDegress    Boolean    true    pitch和yaw用角度还是弧度      
4    target    DisplayObject3D    null    环绕的目标选项.如果不传递则使用摄影机的目标,若摄影机目标为null,摄影机会为(0,0,0)为目标     

我们可以调用Tweener.isTweening()方法,它会告诉你目前的对象是不是正在进行补间.
if (!Tweener.isTweening(e.displayObject3D))
{
}

摄影机调用copyTransform()来复制Player的位置和旋转,这不止复制do3d的位置也包括旋转和缩放.
camera.copyTransform(player);

八、外部模型
尽量减少模型的多边形
一般来说三角行数量不要超过3000,也就是1500个多边形(一个多边形由两个三角形组成)。

使用uvmap贴图:
如果你的模型只有少数的物体和贴图,使用uvmap是个不错的选择,他的使用方法就是把模型解包(unwrapping)并且把所有的材质定义到一张图像上

烘焙纹理:
烘焙纹理就是将高光、阴影、折射、反射以及整个3d场景整合为一张图片的过程。

物体和材质的命名:
给你的材质和物体建立一个好的命名规范,同样的为你代码中的类、方法以及属性也采取一定的命名规范。

模型的大小和位置:
一定要把物体放在默认的位置,原点位置

model = new DAE();
model.addEventListener(FileLoadEvent.LOAD_COMPLETE,modelLoaded);
DAE(model).load("assets/teapot.DAE");
scene.addChild(model);

模型:   /assets/models/
材质图片:  /assets/textures/
daeModel.addFileSearchPath("assets/textures");
 
1    autoPlay    Boolean    true    如果模型中内置动画,那么pv3d会自动的播放      
2    name    String    null    随意的名字,让你可以更便捷的使用模型      
3    loop    Boolean    false    定义动画是否循环播放,默认只播放一次     

动画裁剪:
AnimationClip3D类为我们提供了这个方法。
 
    参数    数据类型    默认值    描述      
1    Name    String    -    动画剪辑名,制定动画片段的唯一名称      
2    starTime    Number    0.0    定义动画的开始时间,不能大于总的时间以及结束时间,你可以从daeModel.animation.endTime这个属性里面找到模型的总动画时间      
3    endTime    Number    0.0    定义动画的结束时间,不能超过总的动画时间     
var animationRight:AnimationClip3D = new AnimationClip3D("right",0,6);
var animationLeft:AnimationClip3D = new AnimationClip3D("left",6,12);
DAE(model).animation.addClip(animationRight);
DAE(model).animation.addClip(animationLeft);
如果你想播放向右旋转的动画的话,只要调用play()方法
DAE(model).play("right");
如果你想停止动画,你就这么写
DAE(model).stop();

加载3DS模型:
model = new Max3DS();
model.addEventListener(FileLoadEvent.LOAD_COMPLETE,modelLoaded);
Max3DS(model).load("assets/teapot.3ds", null, "./assets/");
在这里load()函数有两个方法,第一个是要调用的文件的路径,第二个参数定义的是一个材质文件的列表,在这个案例中我们略过不填,第三个参数定义的是材质存放的目录,这个目录是相对与发布swf文件目录的。

九、深度排序
Z-sorting(深度排序)方法将决定每个平面在scene里的显示深度,其深度位置是按照scene里的平面(即3D对象的某一面)距camera的距离来决定的 。

为了增加3D对象的显示效果,可以增加多个三角形平面(即创建更多的segment),但它不是最好的解决方案。

更好的解决办法是用viewport(视口) 层,这些viewport(视口)层被嵌套在viewport里(因为viewport可以多方位旋转,因而有多个viewport层)。
每个层只能放一种元素,该元素既可以是单一的,也可以是混合的

用useOwnContainer属性创建一个viewport层
设置3D对象的useOwnContainer为true(3dDisplayObject. useOwnContainer=true;),将会创建一个新的层,该层在所有层的上面(即该层在最上面)。

用getChildLayer方法创建viewport层并给viewport层排序:
var millLayer:ViewportLayer = viewport.getChildLayer(mill);
getChildLayer()的三个参数:
 参数        数据类型           默认值                   用法描述   

do3d      DisplayObject3D         ————                获得的do3d的所在层
                                                        或者为do3d创建一个新的
层(创建新的层需要第二个参数)
createNew     Boolean             true                    是否为do3d创建一个新的
viewport层(该值一般设
                                                        为true,这样才能创建
                                                        一个新的层,因为新层
                                                        在所有层的最上面)
Recurse       Boolean               true                 是否将do3d里的子对象也
                                                         添加到该层

实例化ViewportLayer来创建 viewport 层:
var millLayer:ViewportLayer = new ViewportLayer(viewport,null);
viewport.containerSprite.addLayer(millLayer);
millLayer.addDisplayObject3D(mill,true);

用ViewportLayerSortMode.Z_SORT给viewport 层排序:
默认的,这些viewport 层是按照Z-sorting深度排序的算法进行排序的.
他们排序的方式是基于层上的每个点(vertices)的Z坐标距camera的平均值来决定(即层内所有的点在Z轴上距camera的距离/点的总数)。
强制为某个viewport 层设置深度(即距camera的距离)
floorLayer.forceDepth = true;
floorLayer.screenDepth = 2000;

用 ViewportLayerSortMode.ORIGIN_SORT给层排序:
第二种算法是基于每个三D对象的原点进行的
当一个层中包含很多3D对象时,他们的原点将会取平均值 。

用ViewportLayerSortMode.INDEX_SORT给viewport 层(ViewportLayer)排序:
var millLayer:ViewportLayer = viewport.getChildLayer(mill);
var floorLayer:ViewportLayer = viewport.getChildLayer(floor);
millLayer.layerIndex = 1;
floorLayer.layerIndex = 2;
viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;

不仅viewport支持viewport层(ViewportLayer),viewport 层他们自己也可以嵌套层(即层中再包含层)

四叉树渲染引擎(Quadtree rendering):
实例化QuadrantRenderEngine只需要一个参数 该参数指定你要选择哪种排序的方法。这些方法是QuadrantRenderEngine类的静态常量。
QuadrantRenderEngine.CORRECT_Z_FILTER: :为不交叉的平面进行正确的排序。
QuadrantRenderEngine.QUAD_SPLIT_FILTER:  为交叉的平面进行排序,引擎将会自动的分割交叉的平面,然后进行正确的排序。
QuadrantRenderEngine.ALL_FILTERS:这个是上面两种类型的组合。它是默认值(即不传参数时默认是它)
我们可以不让3D对象不被四叉树渲染引擎(Quadtree rendering)进行渲染,因而该3D对象将会被默认的BasicRenderEngine引擎进行渲染。 我们可以用设置3D对象的testQuad属性为false来实现。
mill.getChildByName("Blades",true).testQuad = false;
mill.getChildByName("Stand",true).testQuad = false;
mill.getChildByName("House",true).testQuad = false;
因为直接设置mill.testQuad = false;对子对对象不会产生任何影响.

十、粒子
一个粒子可以被描述为一个二维图形,可以相对于一个3D点缩放和定位。
可以设想为一个轻量级的平面,始终面对着摄像头。
这种用面对摄像机的2D图形代替3D物体的技术就叫告示牌。
var particles:Particles = new Particles();
scene.addChild(particles);
for(var i:uint = 0; i < numberOfParticles; i++)
{
var material:ParticleMaterial = new ParticleMaterial(Math.random()*0xFFFFFF,1,ParticleMaterial.SHAPE_CIRCLE,1);
var particle:Particle = new Particle(material,12,randPos(),randPos(),randPos());
particles.addParticle(particle);
}

十一、滤镜和效果
你不能直接对do3D应用滤镜,但是可以对它的视口层应用滤镜。

设置视口层的透明度和混合模式:
对do3D的视口层设置透明度,还可以对视口层设置混合模式。
planeLayer = viewport.getChildLayer(plane,true);
planeLayer.alpha = 0.6;
planeLayer.blendMode = BlendMode.MULTIPLY;

在视口级上应用滤镜:
var blur:BlurFilter = new BlurFilter(8,8,BitmapFilterQuality.LOW);
viewport.filters = [blur];

使用BitmapViewport3D应用滤镜到视口层:
它把每一次渲染结果放入一个bitmap对象。
bitmapViewport = new BitmapViewport3D(viewport.width,viewport.height,true,true);
这个构造器拥有以下参数:
 
    参数     数据类型     默认值     描述       
1     viewportWidth     Number     640     视口的宽度       
2     viewportHeight     Number     480     视口的高度       
3     autoScaleToStage     Boolean     false     是否自动适应舞台大小       
4     bitmapTransparent     Boolean     0×000000     定义视口是否支持透明       
5     bgColor     int     false     定义视口的背景颜色       
6     interactive     Boolean     false     定义视口是否可以交互       
7     autoCulling     Boolean     true     定义是否自动裁剪      
bitmapViewport.fillBeforeRender = false;
addChild(bitmapViewport);
当设置为false时,结果像素停留在屏幕上,会实现虚拟尾巴。

在onRenderTick()函数中,我们首先对之应用发光滤镜:
bitmapViewport.bitmapData.applyFilter(bitmapViewport.bitmapData,
bitmapViewport.bitmapData.rect,destinationPoint,glow);

applyFilter()函数继承自BitmapData类。
在源码中,视口被渲染成位图。让我们简要的说一下applyFilter中的参数。
 
    参数     数据类型     默认值     描述       
1     sourceBitmapData     BitmapData     —     使用的输入位图,在我们的例子里是位图视口的位图数据。       
2     sourceRect     Rectangle     —     定义了作为输入使用的源图像区域的矩形,在我们的例子里,它被位图视口的尺寸定义。       
3     destPoint     Point     —     目标图像里的点,对应源矩形的左上角。       
4     filter     BitmapFilter     —     你使用的滤镜对象。      
最后我们让渲染器渲染bitmapviewport:
renderer.renderScene(scene,camera,bitmapViewport);

内置Papervision3D效果:
BitmapColorEffect
BitmapFireEffect
BitmapMotionEffect
BitmapPixelateEffect

创建效果层:
var bitmapEffectLayer:BitmapEffectLayer = new BitmapEffectLayer
(viewport,viewport.width,viewport.height,
true,0,BitmapClearMode.CLEAR_PRE,true,false);
构造器有8个参数:
 
    参数     数据类型     默认值     描述       
1     viewport     Viewport3D     —     你想要渲染到位图的视口。       
2     width     int     640     绘图用的位图数据宽度。       
3     height     int     480     绘图用的位图数据高度。       
4     transparent     Boolean     true     定义位图数据的透明性。如果你想看到场景中的其它物体,设置它为true。       
5     fillColor     int     0     32位整数,定义了位图数据的初始填充颜色,当transparent设置为false时可见。       
6     clearMode     String     clear_pre     可以定义为BitmapClearMode类里的一个常数,指明什么时候清除绘图层。       
7     renderAbove     Boolean     true     定义绘图层是否显示在位图之上。如果设置为true,绘图层显示在位图之上。       
8     clearBeforeRender     Boolean     false     定义是否在每次渲染之前清除位图数据。      
viewport.containerSprite.addLayer(bitmapEffectLayer);
接下来添加立方体到效果层。
bitmapEffectLayer.addDisplayObject3D(cube);

影响效果显示的方法:
setScroll():你想产生拖尾效果的时候可以使用它。它不仅定义了尾巴的方向,还有速度。
setBitmapOffset():定义了位图的偏移
setTracking():定义了位图的相对物体的偏移

用BitmapColorEffect添加颜色效果
用BitmapFireEffect添加火焰效果
用BitmapPixelateEffect添加像素化效果
用BitmapMotionEffect添加运动效果

你首先实例化滤镜,然后简单的传递给BitmapLayerEffect的构造器:
var blur:BlurFilter = new BlurFilter(7,7);
bmLayerEffect = new BitmapLayerEffect(blur);
bitmapEffectLayer.addEffect(bmLayerEffect);

用BitmapDrawCommand调整效果:
bitmapEffectLayer.drawCommand = new BitmapDrawCommand(null,new
ColorTransform(0.1,1,0.1,0.6),BlendMode.ADD);
 
    参数     数据类型     默认值     描述       
1     transMat     Matrix     null     应用到绘制操作的转换矩阵       
2     colorTransform     ColorTransform     null     定义像素被绘制到位图上时,其颜色和透明度如何改变。       
3     blendMode     BlendMode     null     设置绘图层上的像素被绘制到位图上时应用的混合模式。       
4     smooth     Boolean     false     定义绘制操作是否平滑像素。      

用FogFilter添加雾:
renderer.filter = new FogFilter(new FogMaterial(0xFFFFFF),16,800,2000);
 
    参数     数据类型     默认值     描述       
1     material     FogMaterial     —     雾材质。FogMaterial类只需要一个十六进制颜色值参数。       
2     segments     uint     8     设置层数。这个值越高,层的透明度越低,雾效果越平缓。注意,加太多层会影响性能。       
3     minDepth     Number     200     设置雾滤镜开始添加层的距离。       
4     maxDepth     Number     4000     设置雾滤镜停止添加层的距离。       
5     useViewportLayer     ViewportLayer     null     可选参数,定义包含雾层的视口层。如果没有视口层被定义,这些层会直接被添加到视口。      

用ReflectionView添加倒影:
用ReflectionView代替BasicView来扩展(extend)你的文档类
要放置一个物体的倒影,你要设置surfaceHeight属性:
surfaceHeight = -20;
要添加一个模糊效果给倒影,你可以简单的添加它到倒影视口的滤镜数组。
viewportReflection.filters = [new BlurFilter(2,2,BitmapFilterQuality.HIGH)];
不用倒影添加物体
viewportReflection.viewportObjectFilter = new ViewportObjectFilter
(ViewportObjectFilterMode.EXCLUSIVE);
viewportReflection.viewportObjectFilter.addObject(sphere);
l    ViewportObjectFilterMode.INCLUSIVE:包括被添加到过滤器(filter)的物体,排除其它物体。
l    ViewportObjectFilterMode.EXCLUSIVE:排除被添加到过滤器(filter)的物体,包括其它物体。

设置反射面的颜色深度:
setReflectionColor(redMultiplier:Number = 0, greenMultiplier:Number = 0, blueMultiplier:Number = 0, redOffset:Number = 0, greenOffset:Number = 0, blueOffset:Number = 0):void
setReflectionColor(0.5, 0.5, 0.5);

十二、3D矢量绘图和3D文本
使用Letter3DMaterial创建材质
material = new Letter3DMaterial(0×000000);
这个类的构造函数有两个传入参数:
fillColor uint 0xFF00FF 定义材质的颜色,使用24位的 十六进制的数字,同时定义文本颜色也是使用该类数字
fillAlpha Number 1 设置材质的透明度
你也可以定义文本的外观。
通常是如下三属性——linethickness, linealpha, 与linecolor
text3D.material.lineThickness = 2;
text3D.material.lineAlpha = 1;
text3D.material.lineColor = 0xFF0000;

建立一个Font3D实例
Papervision3D拥有四个可选择的字体:
l    HelveticaBold
l    HelveticaLight
l    HelveticaMedium
l    HelveticaRoman

建立一个Text3D实例,传入文本,字体,材质参数,并将其添加到场景或其它的do3D。
text3D = new Text3D(text,font3D,material);
1 text String — 定义你想显示的文本
2 font Font3D — 设置文本的字体
3 material Letter3DMaterial — 设置字体材质
4 name String null Text3D实例名,可选

Text3D拥有更多的属性可选择,如下是它额外提供的参数:
l    align:left、right、center
l    letterSpacing:每个字符的间距
l    lineSpacing:用于定义文本的垂直距离

创建字体:Five3D

添加交互性到3D矢量文本和3D矢量图形:
在init()方法的首行添加:
VectorShapeHitTest.instance.assignViewport(viewport);

添加交互性到3D文本:
我们添加监听器到Text3D实例的每一个字母。
for each(var letter:VectorLetter3D in text3D.letters)
{
letter.addEventListener(InteractiveScene3DEvent.OBJECT_OVER,overLetterListener);
letter.addEventListener(InteractiveScene3DEvent.OBJECT_OUT,outLetterListener);
}
Text3D拥有一个letters的属性,其是一个数组,储存着文本的各个字母。

绘制矢量图形-线条,圆,与矩形:
它也提供名为VectorShape3D类,用其绘制基本的矢量图
形,比如线条,圆,矩形。矢量图最初以2D形态绘制,然后放入3D空间。
var line:VectorShape3D = new VectorShape3D(material);
line.graphics.lineStyle(2,0×00CCFF);
line.graphics.beginFill(0×666699)
line.graphics.moveTo(-300,-300);
line.graphics.lineTo(300,-300);
scene.addChild(line);

使用Lines3D库绘制线条:
Lines3D使用Vertex3D建立线条的起点和终点
var blueMaterial:LineMaterial = new LineMaterial(0×0000FF);
1 color Number 0xFF0000 定义线的颜色,使用24位十六进制表示颜色数值
2 alpha Number 1 设定材料的透明度
lines = new Lines3D();
scene.addChild(lines);
var blueLine:Line3D = new Line3D(lines,blueMaterial,3,v0,v1);
1 instance Lines3D — Lines3D实例会持有以及渲染线
2 material LineMaterial — 针对线的材质
3 size Number — 线的宽度(粗细)
4 vertex0 Vertex3D — 起点,它是线的起点的3D坐标
5 vertex1 Vertex3D — 终点,它是线的终点的3D坐标
lines.addLine(blueLine);

曲线:
redLine.addControlVertex(-150,-300,0);

使用addNewLine()方法添加新线:
lines.addNewLine(5,0,0,0,300,0,300);
1 size Number — 线的宽度
2 x0 Number — 起点的X坐标
3 y0 Number — 起点的Y坐标
4 z0 Number — 起点的Z坐标
5 x1 Number — 终点的X坐标
6 y1 Number — 终点的Y坐标
7 z1 Number — 终点的Z坐标

建立分割的线:
lines.addNewSegmentedLine(3,8,300,0,300,600,0,0);
1 size Number — 线的宽度
2 segments Number — 分段数
3 x0 Number — 起点的X坐标
4 y0 Number — 起点的Y坐标
5 z0 Number — 起点的Z坐标
6 x1 Number — 终点的X坐标
7 y1 Number — 终点的Y坐标
8 z1 Number — 终点的Z坐标

增加交互到Lines3D的线:
var material:LineMaterial = new LineMaterial(0×000000,0.6);
material.interactive = true;

十三、性能的优化
var stats:StatsView = new StatsView(renderer);
addChild(stats);

FPS:Frames Per Second。每秒显示帧
每秒显示帧取决于最后的渲染需要的时间。
Tri: Triangles. 三角形
最后渲染时渲染的三角形数量。
Sha: Shaders. 着色器
最后渲染时渲染的已着色的三角形。已着色的三角形不计入 Tri 值。
Lin: Lines. 直线
最后渲染时渲染的直线的数量。
Par: Particles. 微粒
最后渲染时渲染的微粒的数量。
Ren: Rendered. 已渲染的
此值尚未使用。
RT: Render Time. 渲染时间
最后的渲染所需要的时间,以毫秒计算。
PT: Projection Time. 投影时间
投影最后渲染需要的时间,以毫秒计算。
COb: Culled Objects. 剔除的物体
最后渲染时剔除物体的数量。所以真正剔除对象的数量是这个数字除以 2。
CTr: Culled Triangles. 剔除的三角形
最后的渲染剔除的三角形的数量。
CPa : Culled Particles. 剔除的粒子
最后渲染时剔除的粒子的数量。
FOb: Filtered Objects. 过滤的物体
添加到 viewport 的 viewportObjectFilter 属性的物体的数量。
Mem: Memory. 内存
Flashplayer 和浏览器使用的内存
Poly count: Polygon Count.多边形的数量
只有当你调用 statsview 里的 updatePolyCount()方法时才会更新此值。
例如: stats.updatePolyCount(scene);

Stage quality 舞台品质:stage.quality = StageQuality.LOW;
StageQuality.BEST:图像是反锯齿的,使用了 4 乘 4 像素栅格,可以使 bitmap 很平滑。
StageQuality.HIGH:图像是反锯齿的,使用了 4 乘 4 像素栅格,如果 movie 是静态的,
可以使 bitmap 很平滑。一般地,stage 的品质都设置成这个值。
StageQuality.MEDIUM:图像是反锯齿的,使用了 2 乘 2 像素栅格,这不会使 bitmap
平滑并对文本阅读有点影响,对动画会有一点优化。
StageQuality.LOW:图像不是反锯齿的,bitmap 也不平滑。对文本的显示和动画的优化
有很大的影响。

其它普通的Flash优化:
在你不需要 event 监听器时,将它移除。

删除不需要的对象:
当你不再需要 scene 中子对象时,应将它删除并且将它的引用和 material 删除。
scene.removeChild(do3d);
do3d.material.destroy();
do3d = null;

Viewport 大小

镜头视域

剔除:
Camera.useCulling = true;
将 useCulling 设为 true,所有在视域外的物体都会被忽略,这会节省性能。

优化 material:
透明度:没有透明度的图片渲染得更快
tiled:永远试着把一个 material 的 tiled 属性设成 true。根据你的情况这会轻微地提高了性能(这是 Flash 播放器存在的一性能的 bug)。
双纹理的作用:双纹理的作用是用来 mipmapping(映射),它允许你将 material 的 smoothing 设为 true而又不丢失性能。
BitmapMaterial.AUTO_MIP_MAPPING = true;
当你设为这样的时候,Papervision3D 会更正所有新建的 bitmap material。缺点就是它会比把这个属性设为 false 的时候要用更多一点内存。

material 的大小:将 material 的宽和高尽量做小。

将在 object 背后的其它 object 删除:
动态设置far plane

Level of detail(细节的级别):
Papervision3D 内建了对 LOD 的支持,但它不支持 do3D 之间的窜改。这个没有窜改功能的技术叫做 simple level of detail(细节的简单级别),或者是 SLOD。
slod = new SimpleLevelOfDetail(spheres,600,2000);
scene.addChild(slod);
实例化 SimpleLevelOfDetail 类需要 4 个参数:
object Array -一个包含 3D object 的数组。数组的第一个元素代表最近而且拥有最多 detail 的,最后的元素是最远而且最简单的 3D object。
MinDepth Number 1000定义最近而且最多 detail 的 object 应该使用的距离。
MaxDepth Number 10000定义最远而且最少 detail 的 object 应该使用的距离。
Distances Array null一个用来定义 object 数组中每个 object深度值的一个 integer 数组。默认设为 null。如果提供了该数组,它会替换 minDepth 和 maxDepth 参数。

渲染的优化:
只有在需要的时候渲染:可以使用 stopRendering() 方法停止渲染器。也可以用startRendering() 方法开始渲染。

选择性地渲染:
renderer.renderLayers(scene,camera,viewport,[layerReference]);
第 4 个参数,这个参数是一个包含了需要被渲染的viewport 的层的数组。

十四、其他技巧
获取一个大致的三维空间的二维鼠标位置:
var vMouse: virtualMouse= viewport.interactiveSceneManager.virtualMouse;
……
public function onMove(evt:InteractiveScene3DEvent):void {
    if (InteractiveSceneManager.MOUSE_IS_DOWN) {
        mc1.graphics.beginFill(0xBBBBBB,1);
        mc1.graphics.drawCircle(vMouse.x, vMouse.y, 10);
        mc1.graphics.endFill();
    }
}

计算鼠标到目标物体之间的屏幕距离:
sphere.autoCalcScreenCoords = true; //允许do3d自动计算自身的屏幕坐标
var distanceX:Number = viewport.containerSprite.mouseX – sphere.screen.x;
var distanceY:Number = viewport.containerSprite.mouseY – sphere.screen.y;
var distance:Number = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
// var distance:Number = Number3D.sub(distanceX, distanceY).modulo;
// modulo 取模

父对象的应用:
private function onButtonClick(evt:MouseEvent):void {
    if (sphere1.parent==do3d1) {
        do3d1.removeChild(sphere1);
        do3d2.addChild(sphere1);
    } else {
        do3d2.removeChild(sphere1);
        do3d1.addChild(sphere1);
    }
}

鼠标获取空间坐标的基础 & 射线和平面相交:
Pv3d里面描述一个无限大的三维平面,及其相关运算,是使用Plane3D这个类
var plane3d:Plane3D=new Plane3D();
plane3d.setNormalAndPoint(法线向量,点);
然后用方法setNormalAndPoint()来描述这个平面,它必须接受两个参数:
1 法线向量,是一个三维数Number3D,比如一个XZ的平面的法线描述方法就是new Number3D(0,1,0)
2平面上的某个点,也是一个三维数Number3D,比如原点坐标就是new Number3D(0,0,0);
private var plane3D:Plane3D  = new Plane3D(XZPLANE, Number3D.ZERO);
var ray:Number3D = camera.unproject(viewport.containerSprite.mouseX, viewport.containerSprite.mouseY);
ray = Number3D.add(ray, camera.position);
var cameraVertex3D:Vertex3D = new Vertex3D(camera.x, camera.y, camera.z);
var rayVertex3D:Vertex3D = new Vertex3D(ray.x, ray.y, ray.z);
var intersectPoint:Vertex3D = plane3D.getIntersectionLine(cameraVertex3D, rayVertex3D);
之后返回来的intersectPoint这个三维数的intersectPoint.x, intersectPoint.y, intersectPoint.z既是我们鼠标点击在这个平面plane3d上反映出来的大概空间位置了。

将viewport作为遮罩层:
rover = new roverAsset() as Bitmap;
rover.mask = viewport;
addChild(rover);
&
exposedViewport.containerSprite.mask = portalViewport; // 两个viewport之间的遮罩

循环获取父对象的所有子对象:
for each(var sphere:Sphere in exposedSphere.children)
{
viewportLayer2.addDisplayObject3D(sphere); // 给viewportLayer添加对象
}

创建自己的网格三角面TriangleMesh3D:
var material:ColorMaterial = new ColorMaterial(0xcc0000);
material.doubleSided = true;
//创建三角面的三个顶点
var vertex3D_1:Vertex3D = new Vertex3D(-200, -200, 0);
var vertex3D_2:Vertex3D = new Vertex3D(200, -200, 0);
var vertex3D_3:Vertex3D = new Vertex3D(-200, 200, 0);
var triangleVertices:Array = [vertex3D_1, vertex3D_2, vertex3D_3];
//use null because we haven’t created its parent mesh yet           
var triangle3d:Triangle3D = new Triangle3D(null, triangleVertices, material);
var triangleFaces:Array = [triangle3d];
triangleMesh3d = new TriangleMesh3D(material, triangleVertices, triangleFaces, null);
triangle3d.instance = triangleMesh3d;
scene.addChild(triangleMesh3d);

四元组Quaternion和Slerp的应用:
Quaternion的四个值分别是轴向量(x,y,z)和沿该轴的转动角度,但其中不包括坐标位置的数据;
Slerp是0-1范围内的一个数,表示两个四元组之间的某个状态。
quaternion = Quaternion.slerp(startQuaternion, endQuaternion, slerp);
// 初始化四元组
planeQuat = Quaternion.createFromMatrix(plane.transform);
mouseQuat = Quaternion.createFromMatrix(mouse3D.transform);
// 逐帧变化
slerp += (1 – slerp) * .1;
slerpQuat = Quaternion.slerp(planeQuat, mouseQuat, slerp);
plane.transform = slerpQuat.matrix;
plane.moveBackward(RADIUS);
renderer.renderScene(scene, camera, viewport);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值