|
@@ -15,7 +15,7 @@ var BABYLON;
|
|
|
mesh.computeWorldMatrix(true);
|
|
|
var center = mesh.getBoundingInfo().boundingBox.center;
|
|
|
body.setPosition(new OIMO.Vec3(center.x, center.y, center.z));
|
|
|
- body.setRotation(new OIMO.Vec3(mesh.rotation.x, mesh.rotation.y, mesh.rotation.z));
|
|
|
+ body.setQuaternion(mesh.rotationQuaternion);
|
|
|
body.sleeping = false;
|
|
|
return;
|
|
|
}
|
|
@@ -24,10 +24,9 @@ var BABYLON;
|
|
|
mesh.computeWorldMatrix(true);
|
|
|
registeredMesh.mesh.computeWorldMatrix(true);
|
|
|
var absolutePosition = registeredMesh.mesh.getAbsolutePosition();
|
|
|
- var absoluteRotation = mesh.rotation;
|
|
|
body = registeredMesh.body.body;
|
|
|
body.setPosition(new OIMO.Vec3(absolutePosition.x, absolutePosition.y, absolutePosition.z));
|
|
|
- body.setRotation(new OIMO.Vec3(absoluteRotation.x, absoluteRotation.y, absoluteRotation.z));
|
|
|
+ body.setQuaternion(mesh.rotationQuaternion);
|
|
|
body.sleeping = false;
|
|
|
return;
|
|
|
}
|
|
@@ -38,31 +37,34 @@ var BABYLON;
|
|
|
return value < BABYLON.PhysicsEngine.Epsilon ? BABYLON.PhysicsEngine.Epsilon : value;
|
|
|
};
|
|
|
OimoJSPlugin.prototype.initialize = function (iterations) {
|
|
|
- this._world = new OIMO.World();
|
|
|
+ this._world = new OIMO.World(null, null, iterations);
|
|
|
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);
|
|
|
- var initialRotation = null;
|
|
|
- if (mesh.rotationQuaternion) {
|
|
|
- initialRotation = mesh.rotationQuaternion.clone();
|
|
|
- mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
|
|
|
- mesh.computeWorldMatrix(true);
|
|
|
+ if (!mesh.rotationQuaternion) {
|
|
|
+ mesh.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(mesh.rotation.y, mesh.rotation.x, mesh.rotation.z);
|
|
|
}
|
|
|
+ mesh.computeWorldMatrix(true);
|
|
|
var bbox = mesh.getBoundingInfo().boundingBox;
|
|
|
// The delta between the mesh position and the mesh bounding box center
|
|
|
var deltaPosition = mesh.position.subtract(bbox.center);
|
|
|
- // Transform delta position with the rotation
|
|
|
- if (initialRotation) {
|
|
|
- var m = new BABYLON.Matrix();
|
|
|
- initialRotation.toRotationMatrix(m);
|
|
|
- deltaPosition = BABYLON.Vector3.TransformCoordinates(deltaPosition, m);
|
|
|
- }
|
|
|
+ //calculate rotation to fit Oimo's needs (Euler...)
|
|
|
+ var rot = new OIMO.Euler().setFromQuaternion({ x: mesh.rotationQuaternion.x, y: mesh.rotationQuaternion.y, z: mesh.rotationQuaternion.z, s: mesh.rotationQuaternion.w });
|
|
|
+ //get the correct bounding box
|
|
|
+ var oldQuaternion = mesh.rotationQuaternion;
|
|
|
+ mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
|
|
|
+ mesh.computeWorldMatrix(true);
|
|
|
+ var bodyConfig = {
|
|
|
+ pos: [bbox.center.x, bbox.center.y, bbox.center.z],
|
|
|
+ rot: [rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD],
|
|
|
+ move: options.mass != 0,
|
|
|
+ config: [options.mass, options.friction, options.restitution],
|
|
|
+ world: this._world
|
|
|
+ };
|
|
|
// register mesh
|
|
|
switch (impostor) {
|
|
|
case BABYLON.PhysicsEngine.SphereImpostor:
|
|
@@ -70,15 +72,8 @@ var BABYLON;
|
|
|
var radiusY = bbox.maximumWorld.y - bbox.minimumWorld.y;
|
|
|
var radiusZ = bbox.maximumWorld.z - bbox.minimumWorld.z;
|
|
|
var size = Math.max(this._checkWithEpsilon(radiusX), this._checkWithEpsilon(radiusY), this._checkWithEpsilon(radiusZ)) / 2;
|
|
|
- body = new OIMO.Body({
|
|
|
- type: 'sphere',
|
|
|
- size: [size],
|
|
|
- pos: [bbox.center.x, bbox.center.y, bbox.center.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
|
|
|
- });
|
|
|
+ bodyConfig.type = 'sphere';
|
|
|
+ bodyConfig.size = [size];
|
|
|
break;
|
|
|
case BABYLON.PhysicsEngine.PlaneImpostor:
|
|
|
//Oimo "fakes" a cylinder as a box, so why don't we!
|
|
@@ -90,30 +85,25 @@ var BABYLON;
|
|
|
var sizeX = this._checkWithEpsilon(box.x);
|
|
|
var sizeY = this._checkWithEpsilon(box.y);
|
|
|
var sizeZ = this._checkWithEpsilon(box.z);
|
|
|
- body = new OIMO.Body({
|
|
|
- type: 'box',
|
|
|
- size: [sizeX, sizeY, sizeZ],
|
|
|
- pos: [bbox.center.x, bbox.center.y, bbox.center.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
|
|
|
- });
|
|
|
+ bodyConfig.type = 'box';
|
|
|
+ bodyConfig.size = [sizeX, sizeY, sizeZ];
|
|
|
break;
|
|
|
}
|
|
|
- //If quaternion was set as the rotation of the object
|
|
|
- if (initialRotation) {
|
|
|
- //We have to access the rigid body's properties to set the quaternion.
|
|
|
- //The setQuaternion function of Oimo only sets the newOrientation that is only set after an impulse is given or a collision.
|
|
|
- body.body.orientation = new OIMO.Quat(initialRotation.w, initialRotation.x, initialRotation.y, initialRotation.z);
|
|
|
- //update the internal rotation matrix
|
|
|
- body.body.syncShapes();
|
|
|
- }
|
|
|
+ var body = new OIMO.Body(bodyConfig);
|
|
|
+ //We have to access the rigid body's properties to set the quaternion.
|
|
|
+ //The setQuaternion function of Oimo only sets the newOrientation that is only set after an impulse is given or a collision.
|
|
|
+ //body.body.orientation = new OIMO.Quat(mesh.rotationQuaternion.w, mesh.rotationQuaternion.x, mesh.rotationQuaternion.y, mesh.rotationQuaternion.z);
|
|
|
+ //TEST
|
|
|
+ //body.body.resetQuaternion(new OIMO.Quat(mesh.rotationQuaternion.w, mesh.rotationQuaternion.x, mesh.rotationQuaternion.y, mesh.rotationQuaternion.z));
|
|
|
+ //update the internal rotation matrix
|
|
|
+ //body.body.syncShapes();
|
|
|
this._registeredMeshes.push({
|
|
|
mesh: mesh,
|
|
|
body: body,
|
|
|
delta: deltaPosition
|
|
|
});
|
|
|
+ //for the sake of consistency.
|
|
|
+ mesh.rotationQuaternion = oldQuaternion;
|
|
|
return body;
|
|
|
};
|
|
|
OimoJSPlugin.prototype.registerMeshesAsCompound = function (parts, options) {
|
|
@@ -136,6 +126,9 @@ var BABYLON;
|
|
|
config: [options.mass, options.friction, options.restitution],
|
|
|
world: this._world
|
|
|
});
|
|
|
+ //Reset the body's rotation to be of the initial mesh's.
|
|
|
+ var rot = new OIMO.Euler().setFromQuaternion({ x: initialMesh.rotationQuaternion.x, y: initialMesh.rotationQuaternion.y, z: initialMesh.rotationQuaternion.z, s: initialMesh.rotationQuaternion.w });
|
|
|
+ body.resetRotation(rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD);
|
|
|
this._registeredMeshes.push({
|
|
|
mesh: initialMesh,
|
|
|
body: body
|
|
@@ -143,10 +136,23 @@ var BABYLON;
|
|
|
return body;
|
|
|
};
|
|
|
OimoJSPlugin.prototype._createBodyAsCompound = function (part, options, initialMesh) {
|
|
|
- var bodyParameters = null;
|
|
|
var mesh = part.mesh;
|
|
|
+ if (!mesh.rotationQuaternion) {
|
|
|
+ mesh.rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(mesh.rotation.y, mesh.rotation.x, mesh.rotation.z);
|
|
|
+ }
|
|
|
// We need the bounding box/sphere info to compute the physics body
|
|
|
- mesh.computeWorldMatrix();
|
|
|
+ mesh.computeWorldMatrix(true);
|
|
|
+ var rot = new OIMO.Euler().setFromQuaternion({ x: mesh.rotationQuaternion.x, y: mesh.rotationQuaternion.y, z: mesh.rotationQuaternion.z, s: mesh.rotationQuaternion.w });
|
|
|
+ var bodyParameters = {
|
|
|
+ pos: [mesh.position.x, mesh.position.y, mesh.position.z],
|
|
|
+ //A bug in Oimo (Body class) prevents us from using rot directly.
|
|
|
+ rot: [0, 0, 0],
|
|
|
+ //For future reference, if the bug will ever be fixed.
|
|
|
+ realRot: [rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD]
|
|
|
+ };
|
|
|
+ var oldQuaternion = mesh.rotationQuaternion;
|
|
|
+ mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
|
|
|
+ mesh.computeWorldMatrix(true);
|
|
|
switch (part.impostor) {
|
|
|
case BABYLON.PhysicsEngine.SphereImpostor:
|
|
|
var bbox = mesh.getBoundingInfo().boundingBox;
|
|
@@ -154,15 +160,11 @@ var BABYLON;
|
|
|
var radiusY = bbox.maximumWorld.y - bbox.minimumWorld.y;
|
|
|
var radiusZ = bbox.maximumWorld.z - bbox.minimumWorld.z;
|
|
|
var size = Math.max(this._checkWithEpsilon(radiusX), this._checkWithEpsilon(radiusY), this._checkWithEpsilon(radiusZ)) / 2;
|
|
|
- bodyParameters = {
|
|
|
- type: 'sphere',
|
|
|
- /* bug with oimo : sphere needs 3 sizes in this case */
|
|
|
- size: [size, -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]
|
|
|
- };
|
|
|
+ bodyParameters.type = 'sphere';
|
|
|
+ bodyParameters.size = [size, size, size];
|
|
|
break;
|
|
|
case BABYLON.PhysicsEngine.PlaneImpostor:
|
|
|
+ case BABYLON.PhysicsEngine.CylinderImpostor:
|
|
|
case BABYLON.PhysicsEngine.BoxImpostor:
|
|
|
bbox = mesh.getBoundingInfo().boundingBox;
|
|
|
var min = bbox.minimumWorld;
|
|
@@ -171,15 +173,11 @@ var BABYLON;
|
|
|
var sizeX = this._checkWithEpsilon(box.x);
|
|
|
var sizeY = this._checkWithEpsilon(box.y);
|
|
|
var sizeZ = this._checkWithEpsilon(box.z);
|
|
|
- var relativePosition = mesh.position;
|
|
|
- bodyParameters = {
|
|
|
- type: 'box',
|
|
|
- size: [sizeX, sizeY, sizeZ],
|
|
|
- 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]
|
|
|
- };
|
|
|
+ bodyParameters.type = 'box';
|
|
|
+ bodyParameters.size = [sizeX, sizeY, sizeZ];
|
|
|
break;
|
|
|
}
|
|
|
+ mesh.rotationQuaternion = oldQuaternion;
|
|
|
return bodyParameters;
|
|
|
};
|
|
|
OimoJSPlugin.prototype.unregisterMesh = function (mesh) {
|
|
@@ -257,6 +255,18 @@ var BABYLON;
|
|
|
OimoJSPlugin.prototype.isSupported = function () {
|
|
|
return OIMO !== undefined;
|
|
|
};
|
|
|
+ OimoJSPlugin.prototype.getWorldObject = function () {
|
|
|
+ return this._world;
|
|
|
+ };
|
|
|
+ OimoJSPlugin.prototype.getPhysicsBodyOfMesh = function (mesh) {
|
|
|
+ for (var index = 0; index < this._registeredMeshes.length; index++) {
|
|
|
+ var registeredMesh = this._registeredMeshes[index];
|
|
|
+ if (registeredMesh.mesh === mesh) {
|
|
|
+ return registeredMesh.body;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ };
|
|
|
OimoJSPlugin.prototype._getLastShape = function (body) {
|
|
|
var lastShape = body.shapes;
|
|
|
while (lastShape.next) {
|
|
@@ -272,41 +282,22 @@ var BABYLON;
|
|
|
while (i--) {
|
|
|
var body = this._registeredMeshes[i].body.body;
|
|
|
var mesh = this._registeredMeshes[i].mesh;
|
|
|
- var delta = this._registeredMeshes[i].delta;
|
|
|
+ if (!this._registeredMeshes[i].delta) {
|
|
|
+ this._registeredMeshes[i].delta = BABYLON.Vector3.Zero();
|
|
|
+ }
|
|
|
if (!body.sleeping) {
|
|
|
+ //TODO check that
|
|
|
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);
|
|
|
- mesh.computeWorldMatrix();
|
|
|
}
|
|
|
else {
|
|
|
- m = body.getMatrix();
|
|
|
- mtx = BABYLON.Matrix.FromArray(m);
|
|
|
- // Body position
|
|
|
- var bodyX = mtx.m[12], bodyY = mtx.m[13], bodyZ = mtx.m[14];
|
|
|
- if (!delta) {
|
|
|
- mesh.position.x = bodyX;
|
|
|
- mesh.position.y = bodyY;
|
|
|
- mesh.position.z = bodyZ;
|
|
|
- }
|
|
|
- else {
|
|
|
- mesh.position.x = bodyX + delta.x;
|
|
|
- mesh.position.y = bodyY + delta.y;
|
|
|
- mesh.position.z = bodyZ + delta.z;
|
|
|
- }
|
|
|
- if (!mesh.rotationQuaternion) {
|
|
|
- mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
|
|
|
- }
|
|
|
- BABYLON.Quaternion.FromRotationMatrixToRef(mtx, mesh.rotationQuaternion);
|
|
|
- mesh.computeWorldMatrix();
|
|
|
+ mesh.position.copyFrom(body.getPosition()).addInPlace(this._registeredMeshes[i].delta);
|
|
|
}
|
|
|
+ mesh.rotationQuaternion.copyFrom(body.getQuaternion());
|
|
|
+ mesh.computeWorldMatrix();
|
|
|
}
|
|
|
}
|
|
|
};
|