图片显示不出来:
【续】
其他章节有其他的人的人翻译:详情在下面这个网址:
Layering your renders :
为了增加3D对象的显示效果,可以增加多个三角形平面(即创建更多的segment),但它不是最好的解决方案。因为当多个三角形平面的顶点(vertex)投影到scene上时,三角形平面越多,投影到scene上的点也越多,因而消耗的cpu也越多 . 更好的解决办法是用viewport(视口) 层,这些viewport(视口)层被嵌套在viewport里(因为viewport可以多方位旋转,因而有多个viewport层)。 这些viewport(视口)层的概念与photoshop和flash里层的概念一样,他们的工作原理一样 ,最上层的总是显示在最前面 。在photoshop里,每层只是放一种元素或者一种混合元素。在Pv3d里也是一样,每层只放一种元素。例如:我们可以将椅子放在某一层,然后将桌子放在另一层。每层的排列顺序可以通过pv3d
里算法实现。<该段主要是讲pv3d层的概念:每个层只能放一种元素,该元素既可以是单一的,也可以是混合的>
为了演示上述方法,我们将重用在第八章介绍过了的animatedMill模型。下面将展示一些Z-sorting(深度排序)的问题 。下面的代码将作为本章的模板。
package {
import flash.events.Event;
import org.papervision3d.core.animation.clip.AnimationClip3D;
import org.papervision3d.events.FileLoadEvent;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.special.CompositeMaterial;
import org.papervision3d.objects.parsers.DAE;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.view.BasicView;
private class ViewportLayersExample extends BasicView
{
private var mill:DAE;
private var floor:Plane;
private var rotX:Number = 0.1;
private var rotY:Number = 0.1;
private var camPitch:Number = 90;
private var camYaw:Number = 270;
private var easeOut:Number = 0.1;
public function ViewportLayersExample()
{
stage.frameRate = 40;
init();
}
private function init():void
{
mill = new DAE(true,null,true);
mill.addEventListener(FileLoadEvent.LOAD_COMPLETE, modelLoaded);
mill.load("assets/animatedMill.dae");
var colorMat:ColorMaterial = new ColorMaterial(0x006600);
var wireMat:WireframeMaterial = new WireframeMaterial();
var floorMat:CompositeMaterial = new CompositeMaterial();
floorMat.addMaterial(colorMat);
floorMat.addMaterial(wireMat);
floorMat.doubleSided = true;
floor = new Plane(floorMat,1000,1000,1,1);
floor.y = -410;
scene.addChild(floor);
floor.rotationX = 90;
}
private function modelLoaded(e:FileLoadEvent):void
{
scene.addChild(mill);
var animationLeft:AnimationClip3D = new AnimationClip3D ("right",0,6);
var animationRight:AnimationClip3D = new AnimationClip3D ("left",6,12);
mill.animation.addClip(animationRight);
mill.animation.addClip(animationLeft);
mill.play("right");
startRendering();
}
override protected function onRenderTick(e:Event=null):void
{
var xDist:Number = mouseX - stage.stageWidth * 0.5;
var yDist:Number = mouseY - stage.stageHeight * 0.5;
camPitch += ((yDist * rotX) - camPitch + 90) * easeOut;
camYaw += ((xDist * rotY) - camYaw + 270) * easeOut;
camera.orbit(camPitch, camYaw);
super.onRenderTick();
}
}
}
在init()方法里,我们加载了外部模型,并把它添加到了scene里。为地板floor对象添加了由WireframeMaterial和ColorMaterial组成的混合材质(floorMat)。
最后onRenderTick(e:Event=null)方法里的几段代码是创建鼠标的交互性。移动鼠标,Camera将会绕scene原点进行旋转 ,因而我们就能看到多个方位 。
测试代码,将会是下面这样的画面 ,下面的地板floor有一些Z-sorting(深度排序)问题。
因为从底部看,模型mill在floor的后面,我们看不到mill模型 。为了能让我们在floor后面看到mill模型,下面我们用层的概念分析一下该问题 :
为了解决该问题,我们在此提出上面讲述了很多的层问题。 用层的方法可以解决mill模型不可见的问题 。 因为从底部看,模型mill在floor的后面,即floor在最上层,而mill模型在floor的下一层,因而我们看不到mill模型。 为了使mill模型在从底部看可见,我们只需改变floor和mill模型 层的顺序的即可 。下面有一些改变层顺序的方法:
用useOwnContainer属性创建一个viewport层
设置3D对象的useOwnContainer为true(3dDisplayObject. useOwnContainer=true;),将会创建一个新的层,该层在所有层的上面(即该层在最上面)。并且该3d对象被画在了该层上。因而该3d对象将不会被遮住。
在上面的代码中为了使我们从底部看mill模型可见,只需在modelLoaded()方法里加上下面一句代码:
mill.useOwnContainer = true;
加上上句代码后再次测试,发现现在的效果更好,图片如下:
换多个方位看,我们会发现不存在Z-sorting问题了。其图片显示如下:右图是从较低的点的视口看的(即看它的底部)。
把useOwnContainer设为true后,mill模型始终在最上层,因而我们始终能看到mill模型。但这是不符合真实的,
并且该属性很耗cpu。下面我们将介绍另外两种方法来代替useOwnContainer方法。下面的两种方法更符合现实。
用getChildLayer方法创建viewport层并给viewport层排序
通过viewport3D类的getChildLayer方法得到ViewportLayer的实例。
var millLayer:ViewportLayer = viewport.getChildLayer(mill);
为了使它运行,我们还需要导入ViewportLayer类:
import org.papervision3d.view.layer.ViewportLayer;
getChildLayer()的三个参数:
参数 数据类型 默认值 用法描述
do3d DisplayObject3D ———— 获得的do3d的所在层
或者为do3d创建一个新的
层(创建新的层需要第二个参数)
createNew Boolean true 是否为do3d创建一个新的
viewport层(该值一般设
为true,这样才能创建
一个新的层,因为新层
在所有层的最上面)
Recurse Boolean true 是否将do3d里的子对象也
添加到该层
当你得到新的viewport层的实例,你也可以将其他的3D对象添加到同一个层中。例如我们可以将大量mill模型添加到同一层. 作为用法演示: 我们在先前的代码的基础上 ,将floor添加到millLayer 层里 。当然这是没有意义的,这和不用层得到的效果是一样的。因为添加floor以后,floor就又在最上面了。
我们在这里只是介绍用法:
millLayer.addDisplayObject3D(floor);
实例化ViewportLayer来创建 viewport 层
下面是用法:
var millLayer:ViewportLayer = new ViewportLayer(viewport,null);
viewport.containerSprite.addLayer(millLayer);
millLayer.addDisplayObject3D(mill,true);
ViewportLayer类的构造函数的三个参数 :
参数 数据类型 默认值 用法描述
Viewport Viewport3D ———— Viewport3D实例对象
do3d DisplayObject3D ———— 被添加进层的3d对象
在getChildLayer()
方法里可以设置Recurse为
true,将3d对象的子对象全部添加到层中。但是在
ViewportLayer构造函数中并没有Recurse这个参数,因此
在上面的代码中将do3d属性设为null,然后用addDisplayObject3D() 方法将do3d对象添加到层,
addDisplayObject3D()方法的第二参数为Recurse ,故可以在这里进行设置
isDynamic Boolean false 是否要去除层在接
下来的渲染。这个参数时pv3d内部决定的,不能在外部修改,只能在源码处进行修改
addDisplayObject3D()的一个参数为do3d 第二个为Recurse 。