Selaa lähdekoodia

Merge pull request #1035 from RaananW/joint-param-setting

Joint param setting
David Catuhe 9 vuotta sitten
vanhempi
commit
ebd247cc9b

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

@@ -173,6 +173,7 @@
             }*/
             switch (impostorJoint.joint.type) {
                 case PhysicsJoint.HingeJoint:
+                case PhysicsJoint.Hinge2Joint:
                     constraint = new CANNON.HingeConstraint(mainBody, connectedBody, constraintData);
                     break;
                 case PhysicsJoint.DistanceJoint:
@@ -447,7 +448,47 @@
         public wakeUpBody(impostor: PhysicsImpostor) {
             impostor.physicsBody.wakeUp();
         }
-
+        
+        public updateDistanceJoint(joint: PhysicsJoint, maxDistance:number, minDistance?: number) {
+            joint.physicsJoint.distance = maxDistance;
+        }
+        
+        private enableMotor(joint: IMotorEnabledJoint, motorIndex?: number) {
+            if(!motorIndex) {
+                joint.physicsJoint.enableMotor();
+            }
+        }
+        
+        private disableMotor(joint: IMotorEnabledJoint, motorIndex?: number) {
+            if(!motorIndex) {
+                joint.physicsJoint.disableMotor();
+            }
+        }
+        
+        public setMotor(joint: IMotorEnabledJoint, speed?: number, maxForce?: number, motorIndex?: number) {
+            if(!motorIndex) {
+                joint.physicsJoint.enableMotor();
+                joint.physicsJoint.setMotorSpeed(speed);
+                if(maxForce) {
+                    this.setLimit(joint, maxForce);
+                }
+                //a hack for force application
+                /*var torque = new CANNON.Vec3();
+                var axis = joint.physicsJoint.axisB;
+                var body = joint.physicsJoint.bodyB;
+                var bodyTorque = body.torque;
+
+                axis.scale(force, torque);
+                body.vectorToWorldFrame(torque, torque);
+                bodyTorque.vadd(torque, bodyTorque);*/
+            }
+        }
+        
+        public setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number) {
+            joint.physicsJoint.motorEquation.maxForce = upperLimit;
+            joint.physicsJoint.motorEquation.minForce = lowerLimit || -upperLimit;
+        }        
+        
         public dispose() {
             //nothing to do, actually.
         }

+ 30 - 9
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -25,7 +25,7 @@ module BABYLON {
 
         public executeStep(delta: number, impostors: Array<PhysicsImpostor>) {
 
-            impostors.forEach(function (impostor) {
+            impostors.forEach(function(impostor) {
                 impostor.beforeStep();
             });
 
@@ -36,7 +36,7 @@ module BABYLON {
                 //update the ordered impostors array
                 this._tmpImpostorsArray[impostor.mesh.uniqueId] = impostor;
             });
-            
+
             //check for collisions
             var contact = this.world.contacts;
 
@@ -103,7 +103,7 @@ module BABYLON {
 
                 var impostors = [impostor];
                 function addToArray(parent: AbstractMesh) {
-                    parent.getChildMeshes().forEach(function (m) {
+                    parent.getChildMeshes().forEach(function(m) {
                         if (m.physicsImpostor) {
                             impostors.push(m.physicsImpostor);
                             m.physicsImpostor._init();
@@ -117,7 +117,7 @@ module BABYLON {
                 }
 
                 impostors.forEach((i) => {
-                    
+
                     //get the correct bounding box
                     var oldQuaternion = i.mesh.rotationQuaternion;
                     var rot = new OIMO.Euler().setFromQuaternion({ x: impostor.mesh.rotationQuaternion.x, y: impostor.mesh.rotationQuaternion.y, z: impostor.mesh.rotationQuaternion.z, s: impostor.mesh.rotationQuaternion.w });
@@ -135,7 +135,7 @@ module BABYLON {
                         bodyConfig.pos.push(bbox.center.x);
                         bodyConfig.pos.push(bbox.center.y);
                         bodyConfig.pos.push(bbox.center.z);
-                        
+
                         //tmp solution
                         bodyConfig.rot.push(rot.x / (OIMO.degtorad || OIMO.TO_RAD));
                         bodyConfig.rot.push(rot.y / (OIMO.degtorad || OIMO.TO_RAD));
@@ -144,13 +144,13 @@ module BABYLON {
                         bodyConfig.pos.push(i.mesh.position.x);
                         bodyConfig.pos.push(i.mesh.position.y);
                         bodyConfig.pos.push(i.mesh.position.z);
-                        
+
                         //tmp solution until https://github.com/lo-th/Oimo.js/pull/37 is merged
                         bodyConfig.rot.push(0);
                         bodyConfig.rot.push(0);
                         bodyConfig.rot.push(0);
                     }
-                    
+
                     // register mesh
                     switch (i.type) {
                         case PhysicsEngine.SphereImpostor:
@@ -189,7 +189,7 @@ module BABYLON {
                             bodyConfig.size.push(sizeZ);
                             break;
                     }
-                    
+
                     //actually not needed, but hey...
                     i.mesh.rotationQuaternion = oldQuaternion;
                 });
@@ -237,7 +237,7 @@ module BABYLON {
                 max: options.max,
                 collision: options.collision || jointData.collision,
                 spring: options.spring,
-                
+
                 //supporting older version of Oimo
                 world: this.world
 
@@ -341,6 +341,27 @@ module BABYLON {
             impostor.physicsBody.awake();
         }
 
+        public updateDistanceJoint(joint: IMotorEnabledJoint, maxDistance: number, minDistance?: number) {
+            joint.physicsJoint.limitMotoe.upperLimit = maxDistance;
+            if (minDistance !== void 0) {
+                joint.physicsJoint.limitMotoe.lowerLimit = minDistance;
+            }
+        }
+
+        public setMotor(joint: IMotorEnabledJoint, force?: number, maxForce?: number, motorIndex?: number) {
+            var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor2 || joint.physicsJoint.limitMotor;
+            if (motor) {
+                motor.setMotor(force, maxForce);
+            }
+        }
+
+        public setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number) {
+            var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor2 || joint.physicsJoint.limitMotor;
+            if (motor) {
+                motor.setLimit(upperLimit, lowerLimit || -upperLimit);
+            }
+        }
+
         public dispose() {
             this.world.clear();
         }

+ 23 - 1
src/Physics/babylon.physicsEngine.ts

@@ -30,6 +30,7 @@
          * default is 1/60. 
          * To slow it down, enter 1/600 for example.
          * To speed it up, 1/30
+         * @param {number} newTimeStep the new timestep to apply to this world.
          */
         public setTimeStep(newTimeStep: number = 1 / 60) {
             this._physicsPlugin.setTimeStep(newTimeStep);
@@ -69,6 +70,11 @@
         private _impostors: Array<PhysicsImpostor> = [];
         private _joints: Array<PhysicsImpostorJoint> = [];
 
+        /**
+         * Adding a new impostor for the impostor tracking.
+         * This will be done by the impostor itself.
+         * @param {PhysicsImpostor} impostor the impostor to add
+         */
         public addImpostor(impostor: PhysicsImpostor) {
             this._impostors.push(impostor);
             //if no parent, generate the body
@@ -77,6 +83,11 @@
             }
         }
 
+        /**
+         * Remove an impostor from the engine.
+         * This impostor and its mesh will not longer be updated by the physics engine.
+         * @param {PhysicsImpostor} impostor the impostor to remove
+         */
         public removeImpostor(impostor: PhysicsImpostor) {
             var index = this._impostors.indexOf(impostor);
             if (index > -1) {
@@ -88,13 +99,20 @@
                 }
             }
         }
-
+        
+        /**
+         * Add a joint to the physics engine
+         * @param {PhysicsImpostor} mainImpostor the main impostor to which the joint is added.
+         * @param {PhysicsImpostor} connectedImpostor the impostor that is connected to the main impostor using this joint
+         * @param {PhysicsJoint} the joint that will connect both impostors.
+         */
         public addJoint(mainImpostor: PhysicsImpostor, connectedImpostor: PhysicsImpostor, joint: PhysicsJoint) {
             var impostorJoint = {
                 mainImpostor: mainImpostor,
                 connectedImpostor: connectedImpostor,
                 joint: joint
             }
+            joint.physicsPlugin = this._physicsPlugin;
             this._joints.push(impostorJoint);
             this._physicsPlugin.generateJoint(impostorJoint);
         }
@@ -166,6 +184,10 @@
         setBodyMass(impostor: PhysicsImpostor, mass: number);
         sleepBody(impostor: PhysicsImpostor);
         wakeUpBody(impostor: PhysicsImpostor);
+        //Joint Update
+        updateDistanceJoint(joint: DistanceJoint, maxDistance:number, minDistance?: number);
+        setMotor(joint: IMotorEnabledJoint, force?: number, maxForce?: number, motorIndex?: number);
+        setLimit(joint: IMotorEnabledJoint, upperLimit: number, lowerLimit?: number, motorIndex?: number);
         dispose();
     }
 }

+ 13 - 9
src/Physics/babylon.physicsImpostor.ts

@@ -31,15 +31,19 @@ module BABYLON {
         }>;
 
         constructor(private _mesh: AbstractMesh, public type: number, private _options: PhysicsImpostorParameters = { mass: 0 }) {
-            //default options params
-            this._options.mass = (_options.mass === void 0) ? 0 : _options.mass
-            this._options.friction = (_options.friction === void 0) ? 0.2 : _options.friction
-            this._options.restitution = (_options.restitution === void 0) ? 0.2 : _options.restitution
             this._physicsEngine = this._mesh.getScene().getPhysicsEngine();
-            this._joints = [];
-            //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
-            if (!this._mesh.parent) {
-                this._init();
+            if (!this._physicsEngine) {
+                Tools.Error("Physics not enabled. Please use scene.enablePhysics(...) before creating impostors.")
+            } else {
+                //default options params
+                this._options.mass = (_options.mass === void 0) ? 0 : _options.mass
+                this._options.friction = (_options.friction === void 0) ? 0.2 : _options.friction
+                this._options.restitution = (_options.restitution === void 0) ? 0.2 : _options.restitution
+                this._joints = [];
+                //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
+                if (!this._mesh.parent) {
+                    this._init();
+                }
             }
         }
 
@@ -321,7 +325,7 @@ module BABYLON {
             if (this.parent) {
                 this.parent.forceUpdate();
             } else {
-                this.mesh.getChildMeshes().forEach(function (mesh) {
+                this.mesh.getChildMeshes().forEach(function(mesh) {
                     if (mesh.physicsImpostor) {
                         if (disposeChildren) {
                             mesh.physicsImpostor.dispose();

+ 104 - 5
src/Physics/babylon.physicsJoint.ts

@@ -6,14 +6,19 @@ module BABYLON {
         connectedPivot?: Vector3;
         mainAxis?: Vector3,
         connectedAxis?: Vector3,
-        collision?: boolean 
+        collision?: boolean
         //Native Oimo/Cannon/Energy data
         nativeParams?: any;
     }
 
+    /**
+     * This is a holder class for the physics joint created by the physics plugin.
+     * It holds a set of functions to control the underlying joint.
+     */
     export class PhysicsJoint {
 
         private _physicsJoint;
+        protected _physicsPlugin: IPhysicsEnginePlugin;
 
         constructor(public type: number, public jointData: PhysicsJointData) {
             jointData.nativeParams = jointData.nativeParams || {};
@@ -31,10 +36,23 @@ module BABYLON {
 
             this._physicsJoint = newJoint;
         }
+
+        public set physicsPlugin(physicsPlugin: IPhysicsEnginePlugin) {
+            this._physicsPlugin = physicsPlugin;
+        }
         
-        
+        /**
+         * Execute a function that is physics-plugin specific.
+         * @param {Function} func the function that will be executed. 
+         *                        It accepts two parameters: the physics world and the physics joint.
+         */
+        public executeNativeFunction(func : (world: any, physicsJoint:any) => void) {
+            func(this._physicsPlugin.world, this._physicsJoint)
+        }
+
+
         //TODO check if the native joints are the same
-        
+
         //Joint Types
         public static DistanceJoint = 0;
         public static HingeJoint = 1;
@@ -45,14 +63,95 @@ module BABYLON {
         public static PrismaticJoint = 5;
         //ENERGY FTW! (compare with this - http://ode-wiki.org/wiki/index.php?title=Manual:_Joint_Types_and_Functions)
         public static UniversalJoint = 6;
-        public static Hinge2Joint = 7;
+        public static Hinge2Joint = PhysicsJoint.WheelJoint;
         //Cannon
         //Similar to a Ball-Joint. Different in params
         //TODO check!!
         public static PointToPointJoint = 8;
         //Cannon only at the moment
         public static SpringJoint = 9;
+    }
+
+    /**
+     * A class representing a physics distance joint.
+     */
+    export class DistanceJoint extends PhysicsJoint {
+        constructor(jointData: DistanceJointData) {
+            super(PhysicsJoint.DistanceJoint, jointData);
+        }
+
+        /**
+         * Update the predefined distance.
+         */
+        public updateDistance(maxDistance: number, minDistance?: number) {
+            this._physicsPlugin.updateDistanceJoint(this, maxDistance, minDistance);
+        }
+    }
+
+    /**
+     * This class represents a single hinge physics joint
+     */
+    export class HingeJoint extends PhysicsJoint implements IMotorEnabledJoint {
+        
+        constructor(jointData:PhysicsJointData) {
+            super(PhysicsJoint.HingeJoint, jointData);
+        }
+        
+        /**
+         * Set the motor values.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} force the force to apply
+         * @param {number} maxForce max force for this motor.
+         */
+        public setMotor(force?: number, maxForce?: number) {
+            this._physicsPlugin.setMotor(this, force, maxForce);
+        }
+        
+        /**
+         * Set the motor's limits.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         */
+        public setLimit(upperLimit: number, lowerLimit?: number) {
+            this._physicsPlugin.setLimit(this, upperLimit, lowerLimit);
+        }
+    }
+    
+    /**
+     * This class represents a dual hinge physics joint (same as wheel joint)
+     */
+    export class Hinge2Joint extends PhysicsJoint implements IMotorEnabledJoint {
+        
+        constructor(jointData:PhysicsJointData) {
+            super(PhysicsJoint.Hinge2Joint, jointData);
+        }
+        
+        /**
+         * Set the motor values.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} force the force to apply
+         * @param {number} maxForce max force for this motor.
+         * @param {motorIndex} the motor's index, 0 or 1.
+         */
+        public setMotor(force?: number, maxForce?: number, motorIndex: number = 0) {
+            this._physicsPlugin.setMotor(this, force, maxForce, motorIndex);
+        }
+        
+        /**
+         * Set the motor limits.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} upperLimit the upper limit
+         * @param {number} lowerLimit lower limit
+         * @param {motorIndex} the motor's index, 0 or 1.
+         */
+        public setLimit(upperLimit: number, lowerLimit?: number, motorIndex: number = 0) {
+            this._physicsPlugin.setLimit(this, upperLimit, lowerLimit, motorIndex);
+        }
+    }
 
+    export interface IMotorEnabledJoint {
+        physicsJoint: any;
+        setMotor(force?: number, maxForce?: number, motorIndex?: number);
+        setLimit(upperLimit: number, lowerLimit?: number, motorIndex?: number);
     }
 
     export interface DistanceJointData extends PhysicsJointData {
@@ -60,7 +159,7 @@ module BABYLON {
         //Oimo - minDistance
         //Cannon - maxForce
     }
-    
+
     export interface SpringJointData extends PhysicsJointData {
         length: number;
         stiffness: number;