jiglibflash是為Flash 3D開發的物理引擎,支援常見的3D引擎,包括PV3D、Away3D,由於寫起來是直接使用3D座標,所以撰寫方便,也支援不規則模形的物件,比我之前看過的WOW引擎功能多很多,但缺點還是太吃CPU資源
package { import flash.display.Bitmap; import flash.events.Event; import flash.events.MouseEvent; import jiglib.math.JNumber3D; import jiglib.physics.PhysicsSystem; import jiglib.physics.RigidBody; import jiglib.physics.constraint.JConstraintWorldPoint; import jiglib.plugin.papervision3d.Papervision3DPhysics; import org.papervision3d.core.geom.renderables.Vertex3D; import org.papervision3d.core.math.Number3D; import org.papervision3d.core.math.Plane3D; import org.papervision3d.core.utils.Mouse3D; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.lights.PointLight3D; import org.papervision3d.materials.BitmapMaterial; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.shadematerials.FlatShadeMaterial; import org.papervision3d.materials.utils.MaterialsList; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.view.BasicView; import org.papervision3d.view.layer.ViewportLayer; import org.papervision3d.view.layer.util.ViewportLayerSortMode; /** * * @author GD * */ [SWF (width = "950", height = "500", frameRate = "30", backgroundColor = "0xFFFFFF")] public class Main extends BasicView { private static const WORLD_WIDTH:uint = 950; private var physics:Papervision3DPhysics; private var pointLight:PointLight3D; private var mouse3D:Mouse3D; private var currentBody:RigidBody; private var planeToDragOn:Plane3D; private var dragConstraint:JConstraintWorldPoint [Embed (source = "assets/floor.jpg")] private var floorAsset:Class; public function Main() { super(950, 500, true, true); initPV3D(); initJiglib(); createFloor(); createBox(5); stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); startRendering(); } private function initJiglib():void { //創銉物理world並指定元件要加入的scene physics = new Papervision3DPhysics(scene, 8); } private function initPV3D():void { pointLight = new PointLight3D(); pointLight.y = 1000; pointLight.z = -800; viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT; Mouse3D.enabled = true; mouse3D = viewport.interactiveSceneManager.mouse3D; camera.z = -1200; camera.y = 300; camera.rotationX = 45; } private function createFloor():void { var colorMat:ColorMaterial = new ColorMaterial(0xCCCCCC); var imageMat:BitmapMaterial = new BitmapMaterial(Bitmap(new floorAsset()).bitmapData); var listMat:MaterialsList = new MaterialsList({all:colorMat, top:imageMat}); //createCube會創建物理的body跟實際的pv3d元件(會自動加入至pv3d scene) var floorBody:RigidBody = physics.createCube(listMat, 1600, 1200, 10); var floor3D:DisplayObject3D = physics.getMesh(floorBody); //fix floorBody.movable = false; floorBody.moveTo(new JNumber3D(0, -300, 0)); floorBody.restitution = .8; floorBody.friction = .2; //重調整layer層次 viewport.getChildLayer(floor3D).layerIndex = 1; } private function createBox(num:uint):void { //重調整layer層次,在floor前,內部照z軸排序 var modelLayer:ViewportLayer = new ViewportLayer(viewport, null); modelLayer.sortMode = ViewportLayerSortMode.Z_SORT; modelLayer.layerIndex = 2; viewport.containerSprite.addLayer(modelLayer); var cubeWidth:uint = 150; var cubeHeight:uint = 150; var cubeDepth:uint = 150; for (var i:uint; i < num; i++) { var ranX:Number = Math.random() * 1200 - 600; var ranY:Number = Math.random() * 500 + 500; var ranZ:Number = Math.random() * 800 - 400; var flatMat:FlatShadeMaterial = new FlatShadeMaterial(pointLight, Math.random() * 0x1000000, 0x111111); var listMat:MaterialsList = new MaterialsList({all:flatMat}); var cube:RigidBody = physics.createCube(listMat, cubeWidth, cubeDepth, cubeHeight); var cube3D:DisplayObject3D = physics.getMesh(cube); cube.moveTo(new JNumber3D(ranX, ranY, ranZ)); modelLayer.addDisplayObject3D(cube3D); flatMat.interactive = true; cube3D.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, mousePressHandler); } } private function findBody(obj3D:DisplayObject3D):RigidBody { var bodys:Array = PhysicsSystem.getInstance().bodys; var rigidBody:RigidBody; for each (var body:RigidBody in bodys) { var skinObj:DisplayObject3D = physics.getMesh(body); if (skinObj == obj3D) { rigidBody = body; break; } } return rigidBody; } private function mousePressHandler(event:InteractiveScene3DEvent):void { trace("press"); //創立constraint var startPos:JNumber3D = new JNumber3D(mouse3D.x, mouse3D.y, mouse3D.z); currentBody = findBody(event.displayObject3D); planeToDragOn = new Plane3D(new Number3D(0, 0, -1), new Number3D(0, 0, -startPos.z)); var bodyPoint:JNumber3D = JNumber3D.sub(startPos, currentBody.currentState.position); dragConstraint = new JConstraintWorldPoint(currentBody, bodyPoint, startPos); PhysicsSystem.getInstance().addConstraint(dragConstraint); stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); } private function mouseUpHandler(evnet:MouseEvent):void { if (dragConstraint) { PhysicsSystem.getInstance().removeConstraint(dragConstraint); dragConstraint = null; currentBody.setActive(); stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); } } private function mouseMoveHandler(event:MouseEvent):void { 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); } override protected function onRenderTick(event:Event=null):void { physics.step(); super.onRenderTick(event); } } }
jiglibflash google code:http://code.google.com/p/jiglibflash/
0 意見 :: [練習]3D物理引擎 jiglibflash
張貼留言