فهرست منبع

Merge pull request #2411 from abow/viewPhysicsImposters

created Debug.PhysicsViewer
David Catuhe 8 سال پیش
والد
کامیت
5b924b32c1

+ 7 - 6
Babylon.csproj

@@ -138,6 +138,7 @@
     <TypeScriptCompile Include="src\Debug\babylon.boneAxesViewer.ts" />
     <TypeScriptCompile Include="src\Debug\babylon.skeletonViewer.ts" />
     <TypeScriptCompile Include="src\Debug\babylon.debugLayer.ts" />
+    <TypeScriptCompile Include="src\Debug\babylon.physicsViewer.ts" />
     <TypeScriptCompile Include="src\Layer\babylon.highlightlayer.ts" />
     <TypeScriptCompile Include="src\Loading\babylon.sceneLoader.ts" />
     <TypeScriptCompile Include="src\Loading\Plugins\babylon.babylonFileLoader.ts" />
@@ -562,11 +563,11 @@
     <PostBuildEvent>
     </PostBuildEvent>
   </PropertyGroup>
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
   -->
 </Project>

+ 1 - 0
Tools/Gulp/config.json

@@ -807,6 +807,7 @@
                 "../../src/Debug/babylon.boneAxesViewer.js",
                 "../../src/Debug/babylon.rayHelper.js",
                 "../../src/Debug/babylon.debugLayer.js",
+                "../../src/Debug/babylon.physicsViewer.js",
                 "../../src/Rendering/babylon.boundingBoxRenderer.js"
             ],
             "dependUpon" : [

+ 99 - 0
src/Debug/babylon.physicsViewer.ts

@@ -0,0 +1,99 @@
+module BABYLON.Debug {
+
+    export class PhysicsViewer {
+        
+        protected _impostors:Array<PhysicsImpostor> = [];
+        protected _meshes:Array<AbstractMesh> = [];
+        protected _scene:Scene;
+        protected _numMeshes = 0;
+        protected _physicsEnginePlugin:IPhysicsEnginePlugin;
+        private _renderFunction: () => void;
+
+        constructor(scene:Scene){
+
+            this._scene = scene || Engine.LastCreatedScene;
+            this._physicsEnginePlugin = this._scene.getPhysicsEngine().getPhysicsPlugin();
+
+        }
+
+        protected _updateDebugMeshes():void{
+
+            var plugin = this._physicsEnginePlugin;
+
+            for (var i = 0; i < this._numMeshes; i++){
+                if(this._impostors[i].isDisposed){
+                    this.hideImpostor(this._impostors[i--]);
+                }else{
+                    plugin.syncMeshWithImpostor(this._meshes[i], this._impostors[i]);
+                }
+            }
+
+        }
+
+        public showImpostor(impostor:PhysicsImpostor):void{
+
+            for (var i = 0; i < this._numMeshes; i++){
+                if(this._impostors[i] == impostor){
+                    return;
+                }
+            }
+
+            var debugMesh = this._physicsEnginePlugin.getDebugMesh(impostor, this._scene);
+
+            if(debugMesh){
+                this._impostors[this._numMeshes] = impostor;
+                this._meshes[this._numMeshes] = debugMesh;
+
+                if(this._numMeshes === 0){
+                    this._renderFunction = this._updateDebugMeshes.bind(this);
+                    this._scene.registerBeforeRender(this._renderFunction);
+                }
+
+                this._numMeshes++;
+            }
+
+        }
+
+        public hideImpostor(impostor:PhysicsImpostor){
+
+            var removed = false;
+
+            for (var i = 0; i < this._numMeshes; i++){
+                if(this._impostors[i] == impostor){
+                    this._scene.removeMesh(this._meshes[i]);
+                    this._meshes[i].dispose();
+                    this._numMeshes--;
+                    if(this._numMeshes > 0){
+                        this._meshes[i] = this._meshes[this._numMeshes];
+                        this._impostors[i] = this._impostors[this._numMeshes];
+                        this._meshes[this._numMeshes] = null;
+                        this._impostors[this._numMeshes] = null;
+                    }else{
+                        this._meshes[0] = null;
+                        this._impostors[0] = null;
+                    }
+                    removed = true;
+                    break;
+                }
+            }
+
+            if(removed && this._numMeshes === 0){
+                this._scene.unregisterBeforeRender(this._renderFunction);
+            }
+
+        }
+
+        public dispose(){
+            
+            for (var i = 0; i < this._numMeshes; i++){
+                this.hideImpostor(this._impostors[i]);
+            }
+
+            this._impostors.length = 0;
+            this._scene = null;
+            this._physicsEnginePlugin = null;
+            
+        }
+
+    }
+}

+ 79 - 1
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -10,6 +10,10 @@
         //See https://github.com/schteppe/cannon.js/blob/gh-pages/demos/collisionFilter.html
         private _currentCollisionGroup = 2;
 
+        private _debugBoxMesh:Mesh;
+        private _debugSphereMesh:Mesh;
+        private _debugMaterial:StandardMaterial;
+
         public constructor(private _useDeltaForWorldStep: boolean = true, iterations: number = 10) {
             if (!this.isSupported()) {
                 Tools.Error("CannonJS is not available. Please make sure you included the js file.");
@@ -469,8 +473,82 @@
             joint.physicsJoint.motorEquation.minForce = lowerLimit === void 0 ? -upperLimit : lowerLimit;
         }
 
+        private _getDebugMaterial(scene:Scene):Material{
+            if(!this._debugMaterial){
+                this._debugMaterial = new StandardMaterial('', scene);
+                this._debugMaterial.wireframe = true;
+            }
+            
+            return this._debugMaterial;
+        }
+
+        private _getDebugBoxMesh(scene:Scene):AbstractMesh{
+            if(!this._debugBoxMesh){
+                this._debugBoxMesh = MeshBuilder.CreateBox('physicsBodyBoxViewMesh', { size: 1 }, scene); 
+                this._debugBoxMesh.renderingGroupId = 1;
+                this._debugBoxMesh.rotationQuaternion = Quaternion.Identity();
+                this._debugBoxMesh.material = this._getDebugMaterial(scene);
+                scene.removeMesh(this._debugBoxMesh);             
+            }
+
+            return this._debugBoxMesh.createInstance('physicsBodyBoxViewInstance');
+        }
+
+        private _getDebugSphereMesh(scene:Scene):AbstractMesh{
+            if(!this._debugSphereMesh){
+                this._debugSphereMesh = MeshBuilder.CreateSphere('physicsBodySphereViewMesh', { diameter: 1 }, scene); 
+                this._debugSphereMesh.renderingGroupId = 1;
+                this._debugSphereMesh.rotationQuaternion = Quaternion.Identity();
+                this._debugSphereMesh.material = this._getDebugMaterial(scene);
+                scene.removeMesh(this._debugSphereMesh);
+            }
+
+            return this._debugSphereMesh.createInstance('physicsBodyBoxViewInstance');
+        }
+
+        public getDebugMesh(impostor:PhysicsImpostor, scene:Scene):AbstractMesh{
+            var body = impostor.physicsBody;
+            var shape = body.shapes[0];
+            var mesh:AbstractMesh;
+            
+            if (shape.halfExtents) {
+                mesh = this._getDebugBoxMesh(scene);
+                mesh.scaling.x = shape.halfExtents.x * 2;
+                mesh.scaling.y = shape.halfExtents.y * 2;
+                mesh.scaling.z = shape.halfExtents.z * 2;
+            } else if(shape.boundingSphereRadius){	
+                mesh = this._getDebugSphereMesh(scene);            
+                mesh.scaling.x = shape.boundingSphereRadius * 2;
+                mesh.scaling.y = shape.boundingSphereRadius * 2;
+                mesh.scaling.z = shape.boundingSphereRadius * 2;	
+            }
+
+            return mesh;
+        }
+
+        public syncMeshWithImpostor(mesh:AbstractMesh, impostor:PhysicsImpostor){
+            var body = impostor.physicsBody;
+
+            mesh.position.x = body.position.x;
+            mesh.position.y = body.position.y;
+            mesh.position.z = body.position.z;
+            
+            mesh.rotationQuaternion.x = body.quaternion.x;
+            mesh.rotationQuaternion.y = body.quaternion.y;
+            mesh.rotationQuaternion.z = body.quaternion.z;
+            mesh.rotationQuaternion.w = body.quaternion.w;
+        }
+
         public dispose() {
-            //nothing to do, actually.
+            if(this._debugBoxMesh){
+                this._debugBoxMesh.dispose();
+            }
+            if(this._debugSphereMesh){
+                this._debugSphereMesh.dispose();
+            }
+            if(this._debugMaterial){
+                this._debugMaterial.dispose();
+            }
         }
     }
 }

+ 79 - 0
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -6,6 +6,10 @@ module BABYLON {
         public world: any;
         public name: string = "OimoJSPlugin";
 
+        private _debugBoxMesh:Mesh;
+        private _debugSphereMesh:Mesh;
+        private _debugMaterial:StandardMaterial;
+        
         constructor(iterations?: number) {
             this.world = new OIMO.World(1 / 60, 2, iterations, true);
             this.world.worldscale(1);
@@ -388,7 +392,82 @@ module BABYLON {
             }
         }
 
+        private _getDebugMaterial(scene:Scene):Material{
+            if(!this._debugMaterial){
+                this._debugMaterial = new StandardMaterial('', scene);
+                this._debugMaterial.wireframe = true;
+            }
+            
+            return this._debugMaterial;
+        }
+
+        private _getDebugBoxMesh(scene:Scene):AbstractMesh{
+            if(!this._debugBoxMesh){
+                this._debugBoxMesh = MeshBuilder.CreateBox('physicsBodyBoxViewMesh', { size: 1 }, scene); 
+                this._debugBoxMesh.renderingGroupId = 1;
+                this._debugBoxMesh.rotationQuaternion = Quaternion.Identity();
+                this._debugBoxMesh.material = this._getDebugMaterial(scene);
+                scene.removeMesh(this._debugBoxMesh);             
+            }
+
+            return this._debugBoxMesh.createInstance('physicsBodyBoxViewInstance');
+        }
+
+        private _getDebugSphereMesh(scene:Scene):AbstractMesh{
+            if(!this._debugSphereMesh){
+                this._debugSphereMesh = MeshBuilder.CreateSphere('physicsBodySphereViewMesh', { diameter: 1 }, scene); 
+                this._debugSphereMesh.renderingGroupId = 1;
+                this._debugSphereMesh.rotationQuaternion = Quaternion.Identity();
+                this._debugSphereMesh.material = this._getDebugMaterial(scene);
+                scene.removeMesh(this._debugSphereMesh);
+            }
+
+            return this._debugSphereMesh.createInstance('physicsBodyBoxViewInstance');
+        }
+
+        public getDebugMesh(impostor:PhysicsImpostor, scene:Scene):AbstractMesh{
+            var body = impostor.physicsBody;
+            var shape = body.shapes;
+            var mesh:AbstractMesh;
+            
+            if (shape.halfWidth) {
+                mesh = this._getDebugBoxMesh(scene);
+                mesh.scaling.x = shape.halfWidth * 2;
+                mesh.scaling.y = shape.halfHeight * 2;
+                mesh.scaling.z = shape.halfDepth * 2;
+            } else if(shape.radius){	
+                mesh = this._getDebugSphereMesh(scene);            
+                mesh.scaling.x = shape.radius * 2;
+                mesh.scaling.y = shape.radius * 2;
+                mesh.scaling.z = shape.radius * 2;	
+            }
+
+            return mesh;
+        }
+
+        public syncMeshWithImpostor(mesh:AbstractMesh, impostor:PhysicsImpostor){
+            var body = impostor.physicsBody;
+
+            mesh.position.x = body.position.x;
+            mesh.position.y = body.position.y;
+            mesh.position.z = body.position.z;
+            
+            mesh.rotationQuaternion.x = body.orientation.x;
+            mesh.rotationQuaternion.y = body.orientation.y;
+            mesh.rotationQuaternion.z = body.orientation.z;
+            mesh.rotationQuaternion.w = body.orientation.s;
+        }
+
         public dispose() {
+            if(this._debugBoxMesh){
+                this._debugBoxMesh.dispose();
+            }
+            if(this._debugSphereMesh){
+                this._debugSphereMesh.dispose();
+            }
+            if(this._debugMaterial){
+                this._debugMaterial.dispose();
+            }
             this.world.clear();
         }
     }

+ 2 - 0
src/Physics/babylon.physicsEngine.ts

@@ -183,6 +183,8 @@
         updateDistanceJoint(joint: PhysicsJoint, maxDistance:number, minDistance?: number);
         setMotor(joint: IMotorEnabledJoint, speed: number, maxForce?: number, motorIndex?: number);
         setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number);
+        getDebugMesh(impostor:PhysicsImpostor, scene:Scene);
+        syncMeshWithImpostor(mesh:AbstractMesh, impostor:PhysicsImpostor);
         dispose();
     }
 }

+ 8 - 0
src/Physics/babylon.physicsImpostor.ts

@@ -44,6 +44,12 @@ module BABYLON {
         //If set, this is this impostor's parent
         private _parent: PhysicsImpostor;
 
+        private _isDisposed = false;
+
+        get isDisposed():boolean{
+            return this._isDisposed;
+        }
+
         //set by the physics engine when adding this impostor to the array.
         public uniqueId: number;
 
@@ -436,6 +442,8 @@ module BABYLON {
                     }
                 })*/
             }
+
+            this._isDisposed = true;
         }
 
         public setDeltaPosition(position: Vector3) {