Explorar el Código

First version of Oimo plugin

David Catuhe hace 11 años
padre
commit
6943f11120

+ 49 - 0
Babylon/Math/babylon.math.js

@@ -961,6 +961,55 @@
             result.m[15] = 1.0;
         };
 
+        Quaternion.prototype.fromRotationMatrix = function (matrix) {
+            var data = matrix.m;
+            var m11 = data[0], m12 = data[4], m13 = data[8];
+            var m21 = data[1], m22 = data[5], m23 = data[9];
+            var m31 = data[2], m32 = data[6], m33 = data[10];
+            var trace = m11 + m22 + m33;
+            var s;
+
+            if (trace > 0) {
+                s = 0.5 / Math.sqrt(trace + 1.0);
+
+                this.w = 0.25 / s;
+                this.x = (m32 - m23) * s;
+                this.y = (m13 - m31) * s;
+                this.z = (m21 - m12) * s;
+
+                return;
+            }
+
+            if (m11 > m22 && m11 > m33) {
+                s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
+
+                this.w = (m32 - m23) / s;
+                this.x = 0.25 * s;
+                this.y = (m12 + m21) / s;
+                this.z = (m13 + m31) / s;
+
+                return;
+            }
+
+            if (m22 > m33) {
+                s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
+
+                this.w = (m13 - m31) / s;
+                this.x = (m12 + m21) / s;
+                this.y = 0.25 * s;
+                this.z = (m23 + m32) / s;
+
+                return;
+            }
+
+            s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
+
+            this.w = (m21 - m12) / s;
+            this.x = (m13 + m31) / s;
+            this.y = (m23 + m32) / s;
+            this.z = 0.25 * s;
+        };
+
         // Statics
         Quaternion.RotationAxis = function (axis, angle) {
             var result = new Quaternion();

+ 53 - 2
Babylon/Math/babylon.math.ts

@@ -925,6 +925,58 @@
             result.m[15] = 1.0;
         }
 
+        public fromRotationMatrix(matrix: Matrix): void {
+            var data = matrix.m;
+            var m11 = data[0], m12 = data[4], m13 = data[8];
+            var m21 = data[1], m22 = data[5], m23 = data[9];
+            var m31 = data[2], m32 = data[6], m33 = data[10];
+            var trace = m11 + m22 + m33;
+            var s;
+
+            if (trace > 0) {
+                s = 0.5 / Math.sqrt(trace + 1.0);
+
+                this.w = 0.25 / s;
+                this.x = (m32 - m23) * s;
+                this.y = (m13 - m31) * s;
+                this.z = (m21 - m12) * s;
+
+                return;
+            }
+
+            if (m11 > m22 && m11 > m33) {
+
+                s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
+
+                this.w = (m32 - m23) / s;
+                this.x = 0.25 * s;
+                this.y = (m12 + m21) / s;
+                this.z = (m13 + m31) / s;
+
+                return;
+            }
+
+            if (m22 > m33) {
+
+                s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
+
+                this.w = (m13 - m31) / s;
+                this.x = (m12 + m21) / s;
+                this.y = 0.25 * s;
+                this.z = (m23 + m32) / s;
+
+                return;
+
+            }
+
+            s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
+
+            this.w = (m21 - m12) / s;
+            this.x = (m13 + m31) / s;
+            this.y = (m23 + m32) / s;
+            this.z = 0.25 * s;
+        }
+
         // Statics
         public static RotationAxis(axis: Vector3, angle: number): Quaternion {
             var result = new Quaternion();
@@ -972,7 +1024,6 @@
             result.w = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll);
         }
 
-
         public static Slerp(left: Quaternion, right: Quaternion, amount: number): Quaternion {
             var num2;
             var num3;
@@ -2026,6 +2077,6 @@
     export class Axis {
         public static X: Vector3 = new BABYLON.Vector3(1, 0, 0);
         public static Y: Vector3 = new BABYLON.Vector3(0, 1, 0);
-        public static Z: Vector3 =new BABYLON.Vector3(0, 0, 1);
+        public static Z: Vector3 = new BABYLON.Vector3(0, 0, 1);
     };
 }

+ 9 - 2
Babylon/Mesh/babylon.abstractMesh.js

@@ -525,12 +525,19 @@ var BABYLON;
             this.getScene().getPhysicsEngine()._applyImpulse(this, force, contactPoint);
         };
 
-        AbstractMesh.prototype.setPhysicsLinkWith = function (otherMesh, pivot1, pivot2) {
+        AbstractMesh.prototype.setPhysicsLinkWith = function (otherMesh, pivot1, pivot2, options) {
             if (!this._physicImpostor) {
                 return;
             }
 
-            this.getScene().getPhysicsEngine()._createLink(this, otherMesh, pivot1, pivot2);
+            this.getScene().getPhysicsEngine()._createLink(this, otherMesh, pivot1, pivot2, options);
+        };
+
+        AbstractMesh.prototype.updatePhysicsBodyPosition = function () {
+            if (!this._physicImpostor) {
+                return;
+            }
+            this.getScene().getPhysicsEngine()._updateBodyPosition(this);
         };
 
         // Collisions

+ 10 - 2
Babylon/Mesh/babylon.abstractMesh.ts

@@ -521,14 +521,22 @@
             this.getScene().getPhysicsEngine()._applyImpulse(this, force, contactPoint);
         }
 
-        public setPhysicsLinkWith(otherMesh: Mesh, pivot1: Vector3, pivot2: Vector3): void {
+        public setPhysicsLinkWith(otherMesh: Mesh, pivot1: Vector3, pivot2: Vector3, options?: any): void {
             if (!this._physicImpostor) {
                 return;
             }
 
-            this.getScene().getPhysicsEngine()._createLink(this, otherMesh, pivot1, pivot2);
+            this.getScene().getPhysicsEngine()._createLink(this, otherMesh, pivot1, pivot2, options);
         }
 
+        public updatePhysicsBodyPosition(): void {
+            if (!this._physicImpostor) {
+                return;
+            }
+            this.getScene().getPhysicsEngine()._updateBodyPosition(this);
+        }
+
+
         // Collisions
         public moveWithCollisions(velocity: Vector3): void {
             var globalPosition = this.getAbsolutePosition();

+ 15 - 0
Babylon/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -4,6 +4,21 @@
         function CannonJSPlugin() {
             this._registeredMeshes = [];
             this._physicsMaterials = [];
+            this.updateBodyPosition = function (mesh) {
+                for (var index = 0; index < this._registeredMeshes.length; index++) {
+                    var registeredMesh = this._registeredMeshes[index];
+                    if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
+                        var body = registeredMesh.body.body;
+                        body.position.set(mesh.position.x, mesh.position.z, mesh.position.y);
+
+                        body.quaternion.x = mesh.rotationQuaternion.x;
+                        body.quaternion.z = mesh.rotationQuaternion.y;
+                        body.quaternion.y = mesh.rotationQuaternion.z;
+                        body.quaternion.w = -mesh.rotationQuaternion.w;
+                        return;
+                    }
+                }
+            };
         }
         CannonJSPlugin.prototype.initialize = function (iterations) {
             if (typeof iterations === "undefined") { iterations = 10; }

+ 16 - 0
Babylon/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -257,6 +257,22 @@
             }
         }
 
+        public updateBodyPosition = function (mesh: AbstractMesh): void {
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
+                    var body = registeredMesh.body.body;
+                    body.position.set(mesh.position.x, mesh.position.z, mesh.position.y);
+
+                    body.quaternion.x = mesh.rotationQuaternion.x;
+                    body.quaternion.z = mesh.rotationQuaternion.y;
+                    body.quaternion.y = mesh.rotationQuaternion.z;
+                    body.quaternion.w = -mesh.rotationQuaternion.w;
+                    return;
+                }
+            }
+        }
+
         public createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3): boolean {
             var body1 = null, body2 = null;
             for (var index = 0; index < this._registeredMeshes.length; index++) {

+ 268 - 0
Babylon/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -0,0 +1,268 @@
+var BABYLON;
+(function (BABYLON) {
+    var OimoJSPlugin = (function () {
+        function OimoJSPlugin() {
+            this._registeredMeshes = [];
+            this.registerMeshesAsCompound = function (parts, options) {
+                var types = [], sizes = [], positions = [], rotations = [];
+
+                var initialMesh = parts[0].mesh;
+
+                for (var index = 0; index < parts.length; index++) {
+                    var part = parts[index];
+                    var bodyParameters = this._createBodyAsCompound(part, options, initialMesh);
+                    types.push(bodyParameters.type);
+                    sizes.push.apply(sizes, bodyParameters.size);
+                    positions.push.apply(positions, bodyParameters.pos);
+                    rotations.push.apply(rotations, bodyParameters.rot);
+                }
+
+                var body = new OIMO.Body({
+                    type: types,
+                    size: sizes,
+                    pos: positions,
+                    rot: rotations,
+                    move: options.mass != 0,
+                    config: [options.mass, options.friction, options.restitution],
+                    world: this.world
+                });
+
+                this._registeredMeshes.push({
+                    mesh: initialMesh,
+                    body: body
+                });
+
+                return body;
+            };
+            /**
+            * Update the body position according to the mesh position
+            * @param mesh
+            */
+            this.updateBodyPosition = function (mesh) {
+                for (var index = 0; index < this._registeredMeshes.length; index++) {
+                    var registeredMesh = this._registeredMeshes[index];
+                    if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
+                        var body = registeredMesh.body.body;
+                        body.setPosition(mesh.position.x, mesh.position.y, mesh.position.z);
+                        body.setOrientation(mesh.rotation.x, mesh.rotation.y, mesh.rotation.z);
+                        return;
+                    }
+                }
+            };
+            this.createLink = function (mesh1, mesh2, pivot1, pivot2, options) {
+                var body1 = null, body2 = null;
+                for (var index = 0; index < this._registeredMeshes.length; index++) {
+                    var registeredMesh = this._registeredMeshes[index];
+                    if (registeredMesh.mesh === mesh1) {
+                        body1 = registeredMesh.body.body;
+                    } else if (registeredMesh.mesh === mesh2) {
+                        body2 = registeredMesh.body.body;
+                    }
+                }
+                if (!body1 || !body2) {
+                    return false;
+                }
+                if (!options) {
+                    options = {};
+                }
+
+                new OIMO.Link({
+                    type: options.type,
+                    body1: body1,
+                    body2: body2,
+                    min: options.min,
+                    max: options.max,
+                    axe1: options.axe1,
+                    axe2: options.axe2,
+                    pos1: [pivot1.x, pivot1.y, pivot1.z],
+                    collision: options.collision,
+                    spring: options.spring,
+                    world: this.world
+                });
+
+                return true;
+            };
+        }
+        OimoJSPlugin.prototype.initialize = function (iterations) {
+            this._world = new OIMO.World();
+            this._world.clear();
+        };
+
+        OimoJSPlugin.prototype.setGravity = function (gravity) {
+            this._world.gravity = gravity;
+        };
+
+        OimoJSPlugin.prototype.registerMesh = function (mesh, impostor, options) {
+            var body = null;
+            this.unregisterMesh(mesh);
+            mesh.computeWorldMatrix(true);
+
+            switch (impostor) {
+                case BABYLON.PhysicsEngine.SphereImpostor:
+                    var bsphere = mesh.getBoundingInfo().boundingSphere;
+                    var size = bsphere.maximum.subtract(bsphere.minimum).scale(0.5).multiply(mesh.scaling);
+                    body = new OIMO.Body({
+                        type: 'sphere',
+                        size: [size.x],
+                        pos: [mesh.position.x, mesh.position.y, mesh.position.z],
+                        rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD],
+                        move: options.mass != 0,
+                        config: [options.mass, options.friction, options.restitution],
+                        world: this._world
+                    });
+                    this._registeredMeshes.push({
+                        mesh: mesh,
+                        body: body
+                    });
+                    break;
+
+                case BABYLON.PhysicsEngine.PlaneImpostor:
+                case BABYLON.PhysicsEngine.BoxImpostor:
+                    var bbox = mesh.getBoundingInfo().boundingBox;
+                    size = bbox.extends.scale(2).multiply(mesh.scaling);
+                    body = new OIMO.Body({
+                        type: 'box',
+                        size: [size.x || 0.1, size.y || 0.1, size.z || 0.1],
+                        pos: [mesh.position.x, mesh.position.y, mesh.position.z],
+                        rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD],
+                        move: options.mass != 0,
+                        config: [options.mass, options.friction, options.restitution],
+                        world: this._world
+                    });
+
+                    this._registeredMeshes.push({
+                        mesh: mesh,
+                        body: body
+                    });
+                    break;
+            }
+            return body;
+        };
+
+        OimoJSPlugin.prototype._createBodyAsCompound = function (part, options, initialMesh) {
+            var bodyParameters = null;
+            var mesh = part.mesh;
+
+            switch (part.impostor) {
+                case BABYLON.PhysicsEngine.SphereImpostor:
+                    var bsphere = mesh.getBoundingInfo().boundingSphere;
+                    var size = bsphere.maximum.subtract(bsphere.minimum).scale(0.5).multiply(mesh.scaling);
+                    bodyParameters = {
+                        type: 'sphere',
+                        /* bug with oimo : sphere needs 3 sizes in this case */
+                        size: [size.x, -1, -1],
+                        pos: [mesh.position.x, mesh.position.y, mesh.position.z],
+                        rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD]
+                    };
+                    break;
+
+                case BABYLON.PhysicsEngine.PlaneImpostor:
+                case BABYLON.PhysicsEngine.BoxImpostor:
+                    var bbox = part.mesh.getBoundingInfo().boundingBox;
+                    size = bbox.extends.scale(2).multiply(mesh.scaling);
+                    var relativePosition = mesh.position;
+                    bodyParameters = {
+                        type: 'box',
+                        size: [size.x || 0.1, size.y || 0.1, size.z || 0.1],
+                        pos: [relativePosition.x, relativePosition.y, relativePosition.z],
+                        rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD]
+                    };
+                    break;
+            }
+
+            return bodyParameters;
+        };
+
+        OimoJSPlugin.prototype.unregisterMesh = function (mesh) {
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
+                    if (registeredMesh.body) {
+                        this._world.removeRigidBody(registeredMesh.body.body);
+                        this._unbindBody(registeredMesh.body);
+                    }
+                    this._registeredMeshes.splice(index, 1);
+                    return;
+                }
+            }
+        };
+
+        OimoJSPlugin.prototype._unbindBody = function (body) {
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.body === body) {
+                    registeredMesh.body = null;
+                }
+            }
+        };
+
+        OimoJSPlugin.prototype.applyImpulse = function (mesh, force, contactPoint) {
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
+                    registeredMesh.body.body.applyImpulse(contactPoint.scale(OIMO.INV_SCALE), force.scale(OIMO.INV_SCALE * 0.01));
+                    return;
+                }
+            }
+        };
+
+        OimoJSPlugin.prototype.dispose = function () {
+            this._world.clear();
+            while (this._registeredMeshes.length) {
+                this.unregisterMesh(this._registeredMeshes[0].mesh);
+            }
+        };
+
+        OimoJSPlugin.prototype.isSupported = function () {
+            return OIMO !== undefined;
+        };
+
+        OimoJSPlugin.prototype._getLastShape = function (body) {
+            var lastShape = body.shapes;
+            while (lastShape.next) {
+                lastShape = lastShape.next;
+            }
+            return lastShape;
+        };
+
+        OimoJSPlugin.prototype.runOneStep = function (time) {
+            this._world.step();
+
+            // Update the position of all registered meshes
+            var i = this._registeredMeshes.length;
+            var m;
+            while (i--) {
+                var body = this._registeredMeshes[i].body.body;
+                var mesh = this._registeredMeshes[i].mesh;
+                if (!body.sleeping) {
+                    if (body.shapes.next) {
+                        var parentShape = this._getLastShape(body);
+                        mesh.position.x = parentShape.position.x * OIMO.WORLD_SCALE;
+                        mesh.position.y = parentShape.position.y * OIMO.WORLD_SCALE;
+                        mesh.position.z = parentShape.position.z * OIMO.WORLD_SCALE;
+                        var mtx = BABYLON.Matrix.FromArray(body.getMatrix());
+
+                        if (!mesh.rotationQuaternion) {
+                            mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
+                        }
+                        mesh.rotationQuaternion.fromRotationMatrix(mtx);
+                    } else {
+                        m = body.getMatrix();
+                        mtx = BABYLON.Matrix.FromArray(m);
+                        mesh.position.x = mtx.m[12];
+                        mesh.position.y = mtx.m[13];
+                        mesh.position.z = mtx.m[14];
+
+                        if (!mesh.rotationQuaternion) {
+                            mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
+                        }
+                        mesh.rotationQuaternion.fromRotationMatrix(mtx);
+                    }
+                }
+            }
+        };
+        return OimoJSPlugin;
+    })();
+    BABYLON.OimoJSPlugin = OimoJSPlugin;
+})(BABYLON || (BABYLON = {}));
+//# sourceMappingURL=babylon.oimoJSPlugin.js.map

+ 279 - 0
Babylon/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -0,0 +1,279 @@
+module BABYLON {
+    declare var OIMO;
+
+    export class OimoJSPlugin implements IPhysicsEnginePlugin {
+        private _world;
+        private _registeredMeshes = [];
+
+        public initialize(iterations: number): void {
+            this._world = new OIMO.World();
+            this._world.clear();
+        }
+
+        public setGravity(gravity: Vector3): void {
+            this._world.gravity = gravity;
+        }
+
+        public registerMesh(mesh: AbstractMesh, impostor: number, options: PhysicsBodyCreationOptions): any {
+            var body = null;
+            this.unregisterMesh(mesh);
+            mesh.computeWorldMatrix(true);
+
+            // register mesh
+            switch (impostor) {
+                case BABYLON.PhysicsEngine.SphereImpostor:
+                    var bsphere = mesh.getBoundingInfo().boundingSphere;
+                    var size = bsphere.maximum.subtract(bsphere.minimum).scale(0.5).multiply(mesh.scaling);
+                    body = new OIMO.Body({
+                        type: 'sphere',
+                        size: [size.x],
+                        pos: [mesh.position.x, mesh.position.y, mesh.position.z],
+                        rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD],
+                        move: options.mass != 0,
+                        config: [options.mass, options.friction, options.restitution],
+                        world: this._world
+                    });
+                    this._registeredMeshes.push({
+                        mesh: mesh,
+                        body: body
+                    });
+                    break;
+
+                case BABYLON.PhysicsEngine.PlaneImpostor:
+                case BABYLON.PhysicsEngine.BoxImpostor:
+                    var bbox = mesh.getBoundingInfo().boundingBox;
+                    size = bbox.extends.scale(2).multiply(mesh.scaling);
+                    body = new OIMO.Body({
+                        type: 'box',
+                        size: [size.x || 0.1, size.y || 0.1, size.z || 0.1],
+                        pos: [mesh.position.x, mesh.position.y, mesh.position.z],
+                        rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD],
+                        move: options.mass != 0,
+                        config: [options.mass, options.friction, options.restitution],
+                        world: this._world
+                    });
+
+                    this._registeredMeshes.push({
+                        mesh: mesh,
+                        body: body
+                    });
+                    break;
+
+            }
+            return body;
+        }
+
+        public registerMeshesAsCompound = function (parts: PhysicsCompoundBodyPart[], options: PhysicsBodyCreationOptions): any {
+            var types = [],
+                sizes = [],
+                positions = [],
+                rotations = [];
+
+            var initialMesh = parts[0].mesh;
+
+            for (var index = 0; index < parts.length; index++) {
+                var part = parts[index];
+                var bodyParameters = this._createBodyAsCompound(part, options, initialMesh);
+                types.push(bodyParameters.type);
+                sizes.push.apply(sizes, bodyParameters.size);
+                positions.push.apply(positions, bodyParameters.pos);
+                rotations.push.apply(rotations, bodyParameters.rot);
+            }
+
+            var body = new OIMO.Body({
+                type: types,
+                size: sizes,
+                pos: positions,
+                rot: rotations,
+                move: options.mass != 0,
+                config: [options.mass, options.friction, options.restitution],
+                world: this.world
+            });
+
+            this._registeredMeshes.push({
+                mesh: initialMesh,
+                body: body
+            });
+
+            return body;
+        }
+
+        private _createBodyAsCompound(part: PhysicsCompoundBodyPart, options: PhysicsBodyCreationOptions, initialMesh: AbstractMesh): any {
+            var bodyParameters = null;
+            var mesh = part.mesh;
+
+            switch (part.impostor) {
+                case BABYLON.PhysicsEngine.SphereImpostor:
+                    var bsphere = mesh.getBoundingInfo().boundingSphere;
+                    var size = bsphere.maximum.subtract(bsphere.minimum).scale(0.5).multiply(mesh.scaling);
+                    bodyParameters = {
+                        type: 'sphere',
+                        /* bug with oimo : sphere needs 3 sizes in this case */
+                        size: [size.x, -1, -1],
+                        pos: [mesh.position.x, mesh.position.y, mesh.position.z],
+                        rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD]
+                    };
+                    break;
+
+                case BABYLON.PhysicsEngine.PlaneImpostor:
+                case BABYLON.PhysicsEngine.BoxImpostor:
+                    var bbox = part.mesh.getBoundingInfo().boundingBox;
+                    size = bbox.extends.scale(2).multiply(mesh.scaling);
+                    var relativePosition = mesh.position;
+                    bodyParameters = {
+                        type: 'box',
+                        size: [size.x || 0.1, size.y || 0.1, size.z || 0.1],
+                        pos: [relativePosition.x, relativePosition.y, relativePosition.z],
+                        rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD]
+                    };
+                    break;
+            }
+
+            return bodyParameters;
+        }
+
+        public unregisterMesh(mesh: AbstractMesh): void {
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
+                    if (registeredMesh.body) {
+                        this._world.removeRigidBody(registeredMesh.body.body);
+                        this._unbindBody(registeredMesh.body);
+                    }
+                    this._registeredMeshes.splice(index, 1);
+                    return;
+                }
+            }
+        }
+
+        private _unbindBody(body: any): void {
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.body === body) {
+                    registeredMesh.body = null;
+                }
+            }
+        }
+
+        /**
+         * Update the body position according to the mesh position
+         * @param mesh
+         */
+        public updateBodyPosition = function (mesh: AbstractMesh): void {
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
+                    var body = registeredMesh.body.body;
+                    body.setPosition(mesh.position.x, mesh.position.y, mesh.position.z);
+                    body.setOrientation(mesh.rotation.x, mesh.rotation.y, mesh.rotation.z);
+                    return;
+                }
+            }
+        }
+
+        public applyImpulse(mesh: AbstractMesh, force: Vector3, contactPoint: Vector3): void {
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
+                    registeredMesh.body.body.applyImpulse(contactPoint.scale(OIMO.INV_SCALE), force.scale(OIMO.INV_SCALE * 0.01));
+                    return;
+                }
+            }
+        }
+
+        public createLink = function (mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3, options: any): boolean {
+            var body1 = null,
+                body2 = null;
+            for (var index = 0; index < this._registeredMeshes.length; index++) {
+                var registeredMesh = this._registeredMeshes[index];
+                if (registeredMesh.mesh === mesh1) {
+                    body1 = registeredMesh.body.body;
+                } else if (registeredMesh.mesh === mesh2) {
+                    body2 = registeredMesh.body.body;
+                }
+            }
+            if (!body1 || !body2) {
+                return false;
+            }
+            if (!options) {
+                options = {};
+            }
+
+            new OIMO.Link({
+                type: options.type,
+                body1: body1,
+                body2: body2,
+                min: options.min,
+                max: options.max,
+                axe1: options.axe1,
+                axe2: options.axe2,
+                pos1: [pivot1.x, pivot1.y, pivot1.z],
+                collision: options.collision,
+                spring: options.spring,
+                world: this.world
+            });
+
+            return true;
+
+        };
+
+        public dispose(): void {
+            this._world.clear();
+            while (this._registeredMeshes.length) {
+                this.unregisterMesh(this._registeredMeshes[0].mesh);
+            }
+        }
+
+        public isSupported(): boolean {
+            return OIMO !== undefined;
+        }
+
+        private _getLastShape(body: any): any {
+            var lastShape = body.shapes;
+            while (lastShape.next) {
+                lastShape = lastShape.next;
+            }
+            return lastShape;
+        }
+
+        public runOneStep(time: number): void {
+            this._world.step();
+
+            // Update the position of all registered meshes
+            var i = this._registeredMeshes.length;
+            var m;
+            while (i--) {
+
+                var body = this._registeredMeshes[i].body.body;
+                var mesh = this._registeredMeshes[i].mesh;
+                if (!body.sleeping) {
+
+                    if (body.shapes.next) {
+                        var parentShape = this._getLastShape(body);
+                        mesh.position.x = parentShape.position.x * OIMO.WORLD_SCALE;
+                        mesh.position.y = parentShape.position.y * OIMO.WORLD_SCALE;
+                        mesh.position.z = parentShape.position.z * OIMO.WORLD_SCALE;
+                        var mtx = BABYLON.Matrix.FromArray(body.getMatrix());
+
+                        if (!mesh.rotationQuaternion) {
+                            mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
+                        }
+                        mesh.rotationQuaternion.fromRotationMatrix(mtx);
+
+                    } else {
+                        m = body.getMatrix();
+                        mtx = BABYLON.Matrix.FromArray(m);
+                        mesh.position.x = mtx.m[12];
+                        mesh.position.y = mtx.m[13];
+                        mesh.position.z = mtx.m[14];
+
+                        if (!mesh.rotationQuaternion) {
+                            mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
+                        }
+                        mesh.rotationQuaternion.fromRotationMatrix(mtx);
+                    }
+                }
+            }
+        }
+    }
+}

+ 7 - 3
Babylon/Physics/babylon.physicsEngine.js

@@ -2,7 +2,7 @@
 (function (BABYLON) {
     var PhysicsEngine = (function () {
         function PhysicsEngine(plugin) {
-            this._currentPlugin = plugin || new BABYLON.CannonJSPlugin();
+            this._currentPlugin = plugin || new BABYLON.OimoJSPlugin();
         }
         PhysicsEngine.prototype._initialize = function (gravity) {
             this._currentPlugin.initialize();
@@ -40,8 +40,12 @@
             this._currentPlugin.applyImpulse(mesh, force, contactPoint);
         };
 
-        PhysicsEngine.prototype._createLink = function (mesh1, mesh2, pivot1, pivot2) {
-            return this._currentPlugin.createLink(mesh1, mesh2, pivot1, pivot2);
+        PhysicsEngine.prototype._createLink = function (mesh1, mesh2, pivot1, pivot2, options) {
+            return this._currentPlugin.createLink(mesh1, mesh2, pivot1, pivot2, options);
+        };
+
+        PhysicsEngine.prototype._updateBodyPosition = function (mesh) {
+            this._currentPlugin.updateBodyPosition(mesh);
         };
 
         PhysicsEngine.prototype.dispose = function () {

+ 9 - 4
Babylon/Physics/babylon.physicsEngine.ts

@@ -9,9 +9,10 @@
         registerMeshesAsCompound(parts: PhysicsCompoundBodyPart[], options: PhysicsBodyCreationOptions): any;
         unregisterMesh(mesh: AbstractMesh);
         applyImpulse(mesh: AbstractMesh, force: Vector3, contactPoint: Vector3): void;
-        createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3): boolean;
+        createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3, options?: any): boolean;
         dispose(): void;
         isSupported(): boolean;
+        updateBodyPosition(mesh: AbstractMesh): void;
     }
 
     export interface PhysicsBodyCreationOptions {
@@ -31,7 +32,7 @@
         private _currentPlugin: IPhysicsEnginePlugin;
 
         constructor(plugin?: IPhysicsEnginePlugin) {
-            this._currentPlugin = plugin || new CannonJSPlugin();
+            this._currentPlugin = plugin || new OimoJSPlugin();
         }
 
         public _initialize(gravity?: Vector3) {
@@ -70,8 +71,12 @@
             this._currentPlugin.applyImpulse(mesh, force, contactPoint);
         }
 
-        public _createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3): boolean {
-            return this._currentPlugin.createLink(mesh1, mesh2, pivot1, pivot2);
+        public _createLink(mesh1: AbstractMesh, mesh2: AbstractMesh, pivot1: Vector3, pivot2: Vector3, options?: any): boolean {
+            return this._currentPlugin.createLink(mesh1, mesh2, pivot1, pivot2, options);
+        }
+
+        public _updateBodyPosition(mesh: AbstractMesh): void {
+            this._currentPlugin.updateBodyPosition(mesh);
         }
 
         public dispose(): void {