呵呵,最近工作比较忙,所以都没怎么动PV3D了。正好今晚出门回来,看Blog上Colorfulee在《入门第3步》给我留言,问我怎么分别相应鼠标事件,于是我就顺便研究了下 :) ,花了半个多小时,终于被我找到办法。今天入门第5步就讲“3D交互”吧 :D
PV3D中提供了一组专门负责3D交互的类,这些类都是以Interactive为开头,其中有InteractiveSprite,InteractiveScene3D,InteractiveSceneManager,InteractiveWireframeMaterial 等等。要实现3D交互功能我们就需要用到这些类。
我们这一讲的代码是基于《入门第3步》当中的Cube代码修改的,所以如果你可能需要参考《入门第3步》的代码。
首选,我们需要把3D场景的容器对象,改成InteractiveSprite类型:
//...
import org.papervision3d.utils.InteractiveSprite;
//...
[SWF(width='200',height='200',backgroundColor='0xFFFFFF',frameRate='30')]
public class Main extends Sprite
{
//...
private function Init3D():void {
//...
// 创建3D舞台的容器
_container = new InteractiveSprite(); //原先的代码:new Sprite();
//...
}
//...
}
接着我们要把3D舞台改成支持交互操作的InteractiveScene3D类型:
//...
import org.papervision3d.scenes.InteractiveScene3D;
//...
[SWF(width='200',height='200',backgroundColor='0xFFFFFF',frameRate='30')]
public class Main extends Sprite
{
//...
private var _scene:InteractiveScene3D; //原先的代码::MovieScene3D;
private function Init3D():void {
//...
// 创建3D舞台
_scene = new InteractiveScene3D(_container); //原先的代码:new MovieScene3D(_container);
//...
}
//...
}
比起普通的PV3D动画程序,PV3D的3D交互程序多了一个InteractiveSceneManager对象,它负责所有的3D事件。所以代码中需要增加一个私有变量:
//...
import org.papervision3d.utils.InteractiveSceneManager;
//...
[SWF(width='200',height='200',backgroundColor='0xFFFFFF',frameRate='30')]
public class Main extends Sprite
{
//...
private var _interactiveSceneManager:InteractiveSceneManager;
private function Init3D():void {
//...
_interactiveSceneManager = _scene.interactiveSceneManager;
_interactiveSceneManager.faceLevelMode = true;
//注册3D鼠标事件
_interactiveSceneManager.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, OnObj3DMouseOver);
_interactiveSceneManager.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, OnObj3DMouseOut);
//...
}
private function OnObj3DMouseOver(event:InteractiveScene3DEvent):void{
event.face3d.material = this._material2; //换材质,突出显示被选中的face
}
private function OnObj3DMouseOut(event:InteractiveScene3DEvent):void{
event.face3d.material = this._material1; //换回原来材质
}
//...
}
你可以看到上面的代码将InteractiveSceneManager对象的faceLevelMode设置成true。这里需要说明下,PV3D给InteractiveSceneManager设计了两种状态,一种是对象(object)级别的交互,一种是面(face)级别的交互,对象级别的交互就是只精确到某个对象,比如一个Cube或者一个Plane,而面级别的交互可以精确到PV3D显示的最小单位face3D,面级别的交互更精确,但是执行效率比对象级别低很多,所以大家设计交互时需要考虑到这点。
另外代码中用到的贴图需要换成支持交互事件的InteractiveWireframeMaterial类型,为了突出显示,我还另外用了一个InteractiveColorMaterial类型的红色贴图。关于材质贴图的代码修改:
import org.papervision3d.materials.InteractiveWireframeMaterial;
import org.papervision3d.materials.InteractiveColorMaterial;
[SWF(width='200',height='200',backgroundColor='0xFFFFFF',frameRate='30')]
public class Main extends Sprite
{
//...
private var _material1:InteractiveWireframeMaterial;
private var _material2:InteractiveColorMaterial;
private function Init3D():void {
//...
_material1 = new InteractiveWireframeMaterial(0x000000);
_material2 = new InteractiveColorMaterial(0xFF0000);
materialList.addMaterial(_material1, "top");
materialList.addMaterial(_material1, "bottom");
materialList.addMaterial(_material1, "front");
materialList.addMaterial(_material1, "back");
materialList.addMaterial(_material1, "left");
materialList.addMaterial(_material1, "right");
//...
}
//...
}
整个程序的运行效果如下(请把鼠标放上去试试):
这个例子中只实现了face的选择,并没有做到Colorfulee问我的选择Cube某个面的效果,不过通过在鼠标事件中比对材质的id,我们是可以知道Cube的哪个面被选择的,不过需要为每个面都示例化一个材质贴图,不能像示例代码中那样几个面都共享同一个贴图实例。有兴趣的朋友可以自己试试看 :) 。我不希望看我Blog的朋友都变成懒得动手的大懒虫噢。
今天的学习就到这里,我想光通过看我的《PV3D入门》是没办法完全掌握PV3D的,因为我每一讲只能选重点的,或者朋友问得比较多的讲,有很多特性我是没办法介绍到的,所以建议大家出来看我的《PV3D入门》外,还可以通过PV3D的帮助文档,Wiki,或阅读PV3D源代码来更深入的了解PV3D。
今天的完整示例代码:
package {
import flash.display.Sprite;
import flash.events.Event;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.scenes.MovieScene3D;
import org.papervision3d.materials.MaterialsList;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.Cube;
//--New--
import org.papervision3d.utils.InteractiveSprite;
import org.papervision3d.scenes.InteractiveScene3D;
import org.papervision3d.utils.InteractiveSceneManager;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.materials.InteractiveWireframeMaterial;
import org.papervision3d.materials.InteractiveColorMaterial;
[SWF(width='200',height='200',backgroundColor='0xFFFFFF',frameRate='30')]
public class Main extends Sprite
{
private var _container :Sprite;
private var _scene:InteractiveScene3D; // :MovieScene3D;
private var _camera :Camera3D;
private var _displayObj:DisplayObject3D;
private var _material1:InteractiveWireframeMaterial;
private var _material2:InteractiveColorMaterial;
private var _interactiveSceneManager:InteractiveSceneManager;
public function Main()
{
Init3D();
}
private function Init3D():void {
// 创建3D舞台的容器
_container = new InteractiveSprite(); //new Sprite;
_container.x = 100;
_container.y = 100;
addChild( _container );
// 创建3D舞台
_scene = new InteractiveScene3D(_container); // new MovieScene3D( _container );
//--New--
_interactiveSceneManager = _scene.interactiveSceneManager;
_interactiveSceneManager.faceLevelMode = true;
_interactiveSceneManager.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, OnObj3DMouseOver);
_interactiveSceneManager.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, OnObj3DMouseOut);
// 创建摄像头
_camera = new Camera3D();
_camera.z = -500;
_camera.zoom = 5;
var materialList:MaterialsList = new MaterialsList();
_material1 = new InteractiveWireframeMaterial(0x000000);
_material2 = new InteractiveColorMaterial(0xFF0000);
materialList.addMaterial(_material1, "top");
materialList.addMaterial(_material1, "bottom");
materialList.addMaterial(_material1, "front");
materialList.addMaterial(_material1, "back");
materialList.addMaterial(_material1, "left");
materialList.addMaterial(_material1, "right");
_displayObj = new Cube(materialList, 128, 128, 128, 2, 2, 2);
_scene.addChild(_displayObj);
this.addEventListener(Event.ENTER_FRAME, OnEnterFrame);
}
private function OnEnterFrame(event:Event):void {
_displayObj.rotationX += 5;
_displayObj.rotationY += 5;
_scene.renderCamera(_camera);
}
private function OnObj3DMouseOver(event:InteractiveScene3DEvent):void{
event.face3d.material = this._material2;
}
private function OnObj3DMouseOut(event:InteractiveScene3DEvent):void{
event.face3d.material = this._material1;
}
}
}
原标签已从 2024-01-23 存档快照 恢复。本文按原站快照恢复排版,并接回已核实的本地图片。查看恢复说明