Sealyu

--- 博客已迁移至: http://www.sealyu.com/blog

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  618 随笔 :: 87 文章 :: 225 评论 :: 0 Trackbacks
上一课主要学习基本3D交互场景事件的用法,这一课记录高级用法~!

    我以旋转的立方体为例,3D场景中有一个立方体,立方体的6个面每一个面都有一幅图(贴图),当鼠标点击其中的任一面时,缓动放大,再点击时缓动缩小恢复原状继续旋转。效果图如下:

鼠标未点击时不断旋转的立方体效果

鼠标点击时缓动放大效果

   效果代码如下:

 

 package 
{
 
   
    import flash.display.DisplayObject;
    import org.papervision3d.materials.BitmapFileMaterial;
    import org.papervision3d.materials.utils.MaterialsList;
    import org.papervision3d.events.InteractiveScene3DEvent;
    import org.papervision3d.objects.primitives.Cube;
   
    public class MainAdvancedInteractiveScene3dEvent extends PaperBase
 {
       //---------------------------------------------------------------6个面对应的material
       private var frontMaterial:BitmapFileMaterial = new BitmapFileMaterial("img/concretetex02.jpg");
       private var backMaterial:BitmapFileMaterial = new BitmapFileMaterial("img/concretetex03.jpg");
       private var leftMaterial:BitmapFileMaterial = new BitmapFileMaterial("img/bashi.jpg");
    private var rightMaterial:BitmapFileMaterial = new BitmapFileMaterial("img/pic12.jpg");
       private var topMaterial:BitmapFileMaterial = new BitmapFileMaterial("img/pic37.jpg");
       private var bottomMaterial:BitmapFileMaterial = new BitmapFileMaterial("img/pic43.jpg");
      
    //---------------------------------------------------------------目标旋转初始值
       private var targetrotationX:Number = 0;
       private var targetrotationY:Number = 0;
       private var targetrotationZ:Number = 0;
      
    //---------------------------------------------------------------判断是否缓动
       private var tweening:Boolean = false;
      
       private var cube:Cube;
      
       public function MainAdvancedInteractiveScene3dEvent()
    {
         init(550, 400);
       }
      
       override protected function init3d():void
    {
         frontMaterial.interactive = true;
         frontMaterial.name = "front";
  
         backMaterial.interactive = true;
         backMaterial.name = "back";
  
         leftMaterial.interactive = true;
         leftMaterial.name = "left";
  
         rightMaterial.interactive = true;
         rightMaterial.name = "right";
  
         topMaterial.interactive = true;
         topMaterial.name = "top";
  
         bottomMaterial.interactive = true;
         bottomMaterial.name = "bottom";        
   //------------------------------------------------------------Cube
         cube = new Cube(new MaterialsList(
   {
              front: frontMaterial,
              back: backMaterial,
              left: leftMaterial,
              right: rightMaterial,
              top: topMaterial,
              bottom: bottomMaterial
            } ), 500, 500, 500, 3, 3, 3);
         cube.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onPress);
         default_scene.addChild(cube);
  }
      
       private function onPress( e:InteractiveScene3DEvent ):void
    {
         if (tweening)
   {
              tweening = false;
         }
   else
   {
              switch(e.face3d.material.name)
     {
                  case "front":
                     targetrotationX = 0;
                     targetrotationY = 180;
                     targetrotationZ = 0;
                     tweening = true;
                  break;
                  case "back":
                     targetrotationX = 0;
                     targetrotationY = 0;
                     targetrotationZ = 0;
                     tweening = true;
                  break;
                  case "left":
                     targetrotationX = 0;
                     targetrotationY = -90;
                     targetrotationZ = 0;
                     tweening = true;
                  break;
                  case "right":
                     targetrotationX = 0;
                     targetrotationY = 90;
                     targetrotationZ = 0;
                     tweening = true;
                  break;
                  case "top":
                     targetrotationX = 90;
                     targetrotationY = 0;
                     targetrotationZ = 0;
                     tweening = true;
                  break;
                  case "bottom":
                     targetrotationX = -90;
                     targetrotationY = 0;
                     targetrotationZ = 180;
                     tweening = true;
                  break;
    }
   }
  }
      
       override protected function processFrame():void
    {
         if (tweening)
   {
              if (default_camera.zoom < 6.8)
     {
                  default_camera.zoom += Math.sqrt(6.8-default_camera.zoom)/5;
              }
             
              //X
              if (cube.rotationX < targetrotationX)
     {
                  cube.rotationX += Math.sqrt(targetrotationX-cube.rotationX);
                  cube.rotationX = Math.round(cube.rotationX);
              }else if (cube.rotationX > targetrotationX)
     {
                  cube.rotationX -= Math.sqrt(cube.rotationX-targetrotationX);
                  cube.rotationX = Math.round(cube.rotationX);
              }
     //Y
              if (cube.rotationY < targetrotationY)
     {
                  cube.rotationY += Math.sqrt(targetrotationY-cube.rotationY);
                  cube.rotationY = Math.round(cube.rotationY);
              }else if (cube.rotationY > targetrotationY)
     {
                  cube.rotationY -= Math.sqrt(cube.rotationY-targetrotationY);
                  cube.rotationY = Math.round(cube.rotationY);
              }
     //Z
              if (cube.rotationZ < targetrotationZ)
     {
                  cube.rotationZ += Math.sqrt(targetrotationZ-cube.rotationZ);
                  cube.rotationZ = Math.round(cube.rotationZ);
              }else if (cube.rotationZ > targetrotationZ)
     {
                  cube.rotationZ -= Math.sqrt(cube.rotationZ-targetrotationZ);
                  cube.rotationZ = Math.round(cube.rotationZ);
              }
   }
   //
   else
   {
              if (default_camera.zoom > 2)
     {
                  default_camera.zoom -= Math.sqrt(default_camera.zoom-2)/5;
              }
             
              cube.rotationX += 2;
              cube.rotationY += 2;
             
              if (cube.rotationX>= 360) cube.rotationX = 0;
              if (cube.rotationY>= 360) cube.rotationY = 0;
         }
       }
    }
}

 

    代码比较长,关键处已加以说明~!

    这段代码依然是有关InteractiveScene3DEvent类的用法,由于立方体有6个面,为了显示每个面的不同,采用了6张图片做贴图;为了能让立方体的每个面都能实现鼠标交互,在init3d()函数中设置6个面的交互属性为true:

         frontMaterial.interactive = true;
         frontMaterial.name = "front";   
         backMaterial.interactive = true;
         backMaterial.name = "back";   
         leftMaterial.interactive = true;
         leftMaterial.name = "left";   
         rightMaterial.interactive = true;
         rightMaterial.name = "right";   
         topMaterial.interactive = true;
         topMaterial.name = "top";   
         bottomMaterial.interactive = true;
         bottomMaterial.name = "bottom"; 

 

    由于要求有缓动效果,所以在帧频处理函数中通过默认相机的放大:

 

 default_camera.zoom += Math.sqrt(6.8-default_camera.zoom)/5;

 

    缩小:

 

 default_camera.zoom -= Math.sqrt(default_camera.zoom-2)/5;

 

来达到效果。接着通过判断立方体的X、Y、Z三个方向的旋转进一步设定缓动放大缩小过程效果,从而达到高级3D场景交互事件效果的运用目的。

    总结:本节主要是关于高级3D场景交互事件用法,特别是在一些缓动算法上有一定的难度,通过平方根函数求两点之间的距离达到缓动放大、缩小的效果(这个我习惯称为逼近“定点距离缓动”)。

    本教程可自由转载,请注明转载出处,谢谢~!

posted on 2008-11-19 14:52 seal 阅读(677) 评论(0)  编辑  收藏 所属分类: Flex+ActionScript

只有注册用户登录后才能发表评论。


网站导航: