jiglib3D物理引擎 + PV3d 鼠标拖拽示例(中文注释)

package
{
import flash.geom.Point;
import flash.utils.getTimer;
import flash.display.*;
import flash.events.*;
import flash.ui.Keyboard;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.core.geom.*;
import org.papervision3d.core.math.*;
import org.papervision3d.core.proto.*;
import org.papervision3d.cameras.*;
import org.papervision3d.render.*;
import org.papervision3d.events.*;
import org.papervision3d.materials.utils.*;
import org.papervision3d.materials.shadematerials.*;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.scenes.*;
import org.papervision3d.view.stats.StatsView;
import org.papervision3d.view.layer.ViewportLayer;
import org.papervision3d.view.layer.util.ViewportLayerSortMode;
import org.papervision3d.core.utils.Mouse3D;
import org.papervision3d.core.utils.InteractiveSceneManager;

import jiglib.math.*;
import jiglib.geometry.*;
import jiglib.physics.*;
import jiglib.physics.constraint.*;


public class MouseDrag extends Sprite
{
    
private var viewport:Viewport3D;
    
private var scene:Scene3D;
    
private var camera:Camera3D;
    
private var renderer:BasicRenderEngine;
    
private var mylight:PointLight3D;
    
private var mouse3D:Mouse3D;
    
private var shadeMateria:FlatShadeMaterial;
        
    
private var boxBody:Array;
    
    
private var onDraging:Boolean = false;
    
    
private var currDragBody:RigidBody;
    
private var dragConstraint:JConstraintWorldPoint;
    
private var startMousePos:JNumber3D;
    
private var planeToDragOn:Plane3D;
    
    
private var cameraTarget:DisplayObject3D;

    
public function MouseDrag()
    {
        stage.addEventListener(MouseEvent.MOUSE_UP, handleMouseRelease);
        stage.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
        
        init3D();
    }
    
    
/**
     * 初始化3D
     
*/
    
private function init3D():void
    {
        
// 初始化3D视图
        viewport = new Viewport3D(800600truetrue);
        scene 
= new Scene3D();    // 3D场景初始化
        this.addChild(viewport);
        
// 排序模式
        viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT
        
        
// 启用mouse3D
        Mouse3D.enabled = true;
        mouse3D 
= viewport.interactiveSceneManager.mouse3D;
        
        
// 初始化灯光
        mylight = new PointLight3D(truetrue);
        mylight.x 
= 0;
        mylight.y 
= 600;
        mylight.z 
= -300;
        
        
// 建立地面着色材质
        shadeMateria = new FlatShadeMaterial(mylight, 0x77ee77);
        
        
// 建立地面
        var planeSkin:Plane = new Plane(shadeMateria, 500500);
        viewport.getChildLayer(planeSkin).layerIndex 
= 1;
        scene.addChild(planeSkin);
        
        
// 建立物理世界地面
        var plane:JPlane = new JPlane(planeSkin);
        plane.MoveTo(
new JNumber3D(02500), JMatrix3D.rotationX(Math.PI / 2));
        PhysicsSystem.getInstance().AddBody(plane);
        
        
// 建立视图层
        var vplObjects:ViewportLayer = new ViewportLayer(viewport,null);
        vplObjects.layerIndex 
= 2;
        vplObjects.sortMode 
= ViewportLayerSortMode.Z_SORT;
        viewport.containerSprite.addLayer(vplObjects);
        
        
// 初始化立方体着色材质
        shadeMateria = new FlatShadeMaterial(mylight,0xeeee00);
        shadeMateria.interactive 
= true;
        var materiaList:MaterialsList 
= new MaterialsList();
        materiaList.addMaterial(shadeMateria, 
"all");
        
        
// 初始化立方体
        boxBody=new Array();
        var boxSkin:Cube;
        var xNum:
int = 6;
        var yNum:
int = 5;
        var zNum:
int = 1;
        var num:
int = 0;
        var boxSize:JNumber3D 
= new JNumber3D(403040);    // 立方体大小
        var xstart:Number = -xNum * boxSize.x / 2;
        var ystart:Number 
= plane.CurrentState.Position.y + boxSize.y / 2;
        var zstart:Number 
= -zNum * boxSize.z / 2;
        
for (var i:int = 0; i < xNum; i++ )
        {
            
for (var j:int = 0; j < yNum; j++ )
            {
                
for (var k:int = 0; k < zNum; k++ )
                {
                    
// 创建立方体
                    boxSkin = new Cube(materiaList, boxSize.x, boxSize.z, boxSize.y);
                    boxSkin.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, handleMousePress);
                    vplObjects.addDisplayObject3D(boxSkin);
                    scene.addChild(boxSkin);
                    
                    
// 创建物理世界立方体
                    boxBody[num] = new JBox(boxSkin, true, boxSize.x, boxSize.z, boxSize.y);
                    boxBody[num].MoveTo(
new JNumber3D(xstart + (boxSize.x + 1* i, ystart + boxSize.y * j, zstart + (boxSize.z + 1* k), JMatrix3D.IDENTITY);
                    PhysicsSystem.getInstance().AddBody(boxBody[num]);
                    
                    num
++;
                }
            }
        }
        
        
// 创建摄像头对象
        cameraTarget=new Cone(new FlatShadeMaterial(mylight,0xee0000),50,50,1,1);
        cameraTarget.x
=0;
        cameraTarget.y
=250;
        cameraTarget.z
=0;
         
        
// 创建摄像头对象
        camera = new Camera3D();
        camera.x 
= 0;
        camera.y 
= 500;
        camera.z 
= -400;
        camera.target 
= cameraTarget;
         
        
// 创建渲染引擎
        renderer = new BasicRenderEngine();
        
        
// 创建视图
        var stats:StatsView = new StatsView(renderer);
        addChild(stats);
        
        
// 添加循环侦听(用于调用渲染引擎与物理引擎的迭代)
        this.addEventListener(Event.ENTER_FRAME, loop3D);
    }
    
    
/**
     * 查找刚体
     * 利用渲染引擎里的对象匹对
     * 
@param    skin    渲染引擎里的对象
     * 
@return
     
*/
    
private function findSkinBody(skin:DisplayObject3D):int
    {
        
for (var i:String in PhysicsSystem.getInstance().Bodys)
        {
            
if (skin == PhysicsSystem.getInstance().Bodys[i].BodySkin)
            {
                
return int(i);
            }
        }
        
return -1;
    }
    
    
// 处理鼠标按下
    private function handleMousePress(event:InteractiveScene3DEvent):void
    {
        onDraging 
= true;
        
// 取出3D中的鼠标坐标
        startMousePos = new JNumber3D(mouse3D.x, mouse3D.y, mouse3D.z);
        
        
// 取出刚体
        currDragBody = PhysicsSystem.getInstance().Bodys[findSkinBody(event.displayObject3D)];
        
        
// 创建拖拉平面
        planeToDragOn = new Plane3D(new Number3D(00-1), new Number3D(00-startMousePos.z));
        
        
// 添加拖拉约束
        var bodyPoint:JNumber3D = JNumber3D.sub(startMousePos, currDragBody.CurrentState.Position);
        dragConstraint 
= new JConstraintWorldPoint(currDragBody, bodyPoint, startMousePos);
        PhysicsSystem.getInstance().AddConstraint(dragConstraint);
    }
    
    
// 处理鼠标移动
    private function handleMouseMove(event:MouseEvent):void
    {
        
if (onDraging)
        {
            
// 射线
            var ray:Number3D = camera.unproject(viewport.containerSprite.mouseX, viewport.containerSprite.mouseY);
            ray 
= Number3D.add(ray, new Number3D(camera.x, camera.y, camera.z));
            
            
// 更新坐标
            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 
= planeToDragOn.getIntersectionLine(cameraVertex3D, rayVertex3D);
            
            
// 更新约束位置 
            dragConstraint.WorldPosition = new JNumber3D(intersectPoint.x, intersectPoint.y, intersectPoint.z);
        }
    }

    
// 处理鼠标释放
    private function handleMouseRelease(event:MouseEvent):void
    {
        
if (onDraging)
        {
            onDraging 
= false;
            PhysicsSystem.getInstance().RemoveConstraint(dragConstraint);
            currDragBody.SetActive();
        }
    }
    
    
// 刷新
    private function loop3D( event :Event ):void
    {
        PhysicsSystem.getInstance().Integrate(
0.2);    // 调用物理引擎迭代
        renderer.renderScene( scene, camera, viewport );// 渲染
    }
}
}
posted @ 2009-11-01 22:55  大頭  阅读(2136)  评论(0编辑  收藏  举报