babylon.oimoJSPlugin.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. var BABYLON;
  2. (function (BABYLON) {
  3. var OimoJSPlugin = (function () {
  4. function OimoJSPlugin() {
  5. this._registeredMeshes = [];
  6. /**
  7. * Update the body position according to the mesh position
  8. * @param mesh
  9. */
  10. this.updateBodyPosition = function (mesh) {
  11. for (var index = 0; index < this._registeredMeshes.length; index++) {
  12. var registeredMesh = this._registeredMeshes[index];
  13. if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
  14. var body = registeredMesh.body.body;
  15. mesh.computeWorldMatrix(true);
  16. var center = mesh.getBoundingInfo().boundingBox.center;
  17. body.setPosition(center.x, center.y, center.z);
  18. body.setOrientation(mesh.rotation.x, mesh.rotation.y, mesh.rotation.z);
  19. return;
  20. }
  21. // Case where the parent has been updated
  22. if (registeredMesh.mesh.parent === mesh) {
  23. mesh.computeWorldMatrix(true);
  24. registeredMesh.mesh.computeWorldMatrix(true);
  25. var absolutePosition = registeredMesh.mesh.getAbsolutePosition();
  26. var absoluteRotation = mesh.rotation;
  27. body = registeredMesh.body.body;
  28. body.setPosition(absolutePosition.x, absolutePosition.y, absolutePosition.z);
  29. body.setOrientation(absoluteRotation.x, absoluteRotation.y, absoluteRotation.z);
  30. return;
  31. }
  32. }
  33. };
  34. }
  35. OimoJSPlugin.prototype._checkWithEpsilon = function (value) {
  36. return value < BABYLON.PhysicsEngine.Epsilon ? BABYLON.PhysicsEngine.Epsilon : value;
  37. };
  38. OimoJSPlugin.prototype.initialize = function (iterations) {
  39. this._world = new OIMO.World();
  40. this._world.clear();
  41. };
  42. OimoJSPlugin.prototype.setGravity = function (gravity) {
  43. this._world.gravity = gravity;
  44. };
  45. OimoJSPlugin.prototype.registerMesh = function (mesh, impostor, options) {
  46. var body = null;
  47. this.unregisterMesh(mesh);
  48. mesh.computeWorldMatrix(true);
  49. switch (impostor) {
  50. case BABYLON.PhysicsEngine.SphereImpostor:
  51. var bbox = mesh.getBoundingInfo().boundingBox;
  52. var radiusX = bbox.maximumWorld.x - bbox.minimumWorld.x;
  53. var radiusY = bbox.maximumWorld.y - bbox.minimumWorld.y;
  54. var radiusZ = bbox.maximumWorld.z - bbox.minimumWorld.z;
  55. var size = Math.max(this._checkWithEpsilon(radiusX), this._checkWithEpsilon(radiusY), this._checkWithEpsilon(radiusZ)) / 2;
  56. // The delta between the mesh position and the mesh bounding box center
  57. var deltaPosition = mesh.position.subtract(bbox.center);
  58. body = new OIMO.Body({
  59. type: 'sphere',
  60. size: [size],
  61. pos: [bbox.center.x, bbox.center.y, bbox.center.z],
  62. rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD],
  63. move: options.mass != 0,
  64. config: [options.mass, options.friction, options.restitution],
  65. world: this._world
  66. });
  67. this._registeredMeshes.push({
  68. mesh: mesh,
  69. body: body,
  70. delta: deltaPosition
  71. });
  72. break;
  73. case BABYLON.PhysicsEngine.PlaneImpostor:
  74. case BABYLON.PhysicsEngine.BoxImpostor:
  75. bbox = mesh.getBoundingInfo().boundingBox;
  76. var min = bbox.minimumWorld;
  77. var max = bbox.maximumWorld;
  78. var box = max.subtract(min);
  79. var sizeX = this._checkWithEpsilon(box.x);
  80. var sizeY = this._checkWithEpsilon(box.y);
  81. var sizeZ = this._checkWithEpsilon(box.z);
  82. // The delta between the mesh position and the mesh boudning box center
  83. var deltaPosition = mesh.position.subtract(bbox.center);
  84. body = new OIMO.Body({
  85. type: 'box',
  86. size: [sizeX, sizeY, sizeZ],
  87. pos: [bbox.center.x, bbox.center.y, bbox.center.z],
  88. rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD],
  89. move: options.mass != 0,
  90. config: [options.mass, options.friction, options.restitution],
  91. world: this._world
  92. });
  93. this._registeredMeshes.push({
  94. mesh: mesh,
  95. body: body,
  96. delta: deltaPosition
  97. });
  98. break;
  99. }
  100. return body;
  101. };
  102. OimoJSPlugin.prototype.registerMeshesAsCompound = function (parts, options) {
  103. var types = [], sizes = [], positions = [], rotations = [];
  104. var initialMesh = parts[0].mesh;
  105. for (var index = 0; index < parts.length; index++) {
  106. var part = parts[index];
  107. var bodyParameters = this._createBodyAsCompound(part, options, initialMesh);
  108. types.push(bodyParameters.type);
  109. sizes.push.apply(sizes, bodyParameters.size);
  110. positions.push.apply(positions, bodyParameters.pos);
  111. rotations.push.apply(rotations, bodyParameters.rot);
  112. }
  113. var body = new OIMO.Body({
  114. type: types,
  115. size: sizes,
  116. pos: positions,
  117. rot: rotations,
  118. move: options.mass != 0,
  119. config: [options.mass, options.friction, options.restitution],
  120. world: this._world
  121. });
  122. this._registeredMeshes.push({
  123. mesh: initialMesh,
  124. body: body
  125. });
  126. return body;
  127. };
  128. OimoJSPlugin.prototype._createBodyAsCompound = function (part, options, initialMesh) {
  129. var bodyParameters = null;
  130. var mesh = part.mesh;
  131. switch (part.impostor) {
  132. case BABYLON.PhysicsEngine.SphereImpostor:
  133. var bbox = mesh.getBoundingInfo().boundingBox;
  134. var radiusX = bbox.maximumWorld.x - bbox.minimumWorld.x;
  135. var radiusY = bbox.maximumWorld.y - bbox.minimumWorld.y;
  136. var radiusZ = bbox.maximumWorld.z - bbox.minimumWorld.z;
  137. var size = Math.max(this._checkWithEpsilon(radiusX), this._checkWithEpsilon(radiusY), this._checkWithEpsilon(radiusZ)) / 2;
  138. bodyParameters = {
  139. type: 'sphere',
  140. /* bug with oimo : sphere needs 3 sizes in this case */
  141. size: [size, -1, -1],
  142. pos: [mesh.position.x, mesh.position.y, mesh.position.z],
  143. rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD]
  144. };
  145. break;
  146. case BABYLON.PhysicsEngine.PlaneImpostor:
  147. case BABYLON.PhysicsEngine.BoxImpostor:
  148. bbox = mesh.getBoundingInfo().boundingBox;
  149. var min = bbox.minimumWorld;
  150. var max = bbox.maximumWorld;
  151. var box = max.subtract(min);
  152. var sizeX = this._checkWithEpsilon(box.x);
  153. var sizeY = this._checkWithEpsilon(box.y);
  154. var sizeZ = this._checkWithEpsilon(box.z);
  155. var relativePosition = mesh.position;
  156. bodyParameters = {
  157. type: 'box',
  158. size: [sizeX, sizeY, sizeZ],
  159. pos: [relativePosition.x, relativePosition.y, relativePosition.z],
  160. rot: [mesh.rotation.x / OIMO.TO_RAD, mesh.rotation.y / OIMO.TO_RAD, mesh.rotation.z / OIMO.TO_RAD]
  161. };
  162. break;
  163. }
  164. return bodyParameters;
  165. };
  166. OimoJSPlugin.prototype.unregisterMesh = function (mesh) {
  167. for (var index = 0; index < this._registeredMeshes.length; index++) {
  168. var registeredMesh = this._registeredMeshes[index];
  169. if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
  170. if (registeredMesh.body) {
  171. this._world.removeRigidBody(registeredMesh.body.body);
  172. this._unbindBody(registeredMesh.body);
  173. }
  174. this._registeredMeshes.splice(index, 1);
  175. return;
  176. }
  177. }
  178. };
  179. OimoJSPlugin.prototype._unbindBody = function (body) {
  180. for (var index = 0; index < this._registeredMeshes.length; index++) {
  181. var registeredMesh = this._registeredMeshes[index];
  182. if (registeredMesh.body === body) {
  183. registeredMesh.body = null;
  184. }
  185. }
  186. };
  187. OimoJSPlugin.prototype.applyImpulse = function (mesh, force, contactPoint) {
  188. for (var index = 0; index < this._registeredMeshes.length; index++) {
  189. var registeredMesh = this._registeredMeshes[index];
  190. if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
  191. // Get object mass to have a behaviour similar to cannon.js
  192. var mass = registeredMesh.body.body.massInfo.mass;
  193. // The force is scaled with the mass of object
  194. registeredMesh.body.body.applyImpulse(contactPoint.scale(OIMO.INV_SCALE), force.scale(OIMO.INV_SCALE * mass));
  195. return;
  196. }
  197. }
  198. };
  199. OimoJSPlugin.prototype.createLink = function (mesh1, mesh2, pivot1, pivot2, options) {
  200. var body1 = null, body2 = null;
  201. for (var index = 0; index < this._registeredMeshes.length; index++) {
  202. var registeredMesh = this._registeredMeshes[index];
  203. if (registeredMesh.mesh === mesh1) {
  204. body1 = registeredMesh.body.body;
  205. } else if (registeredMesh.mesh === mesh2) {
  206. body2 = registeredMesh.body.body;
  207. }
  208. }
  209. if (!body1 || !body2) {
  210. return false;
  211. }
  212. if (!options) {
  213. options = {};
  214. }
  215. new OIMO.Link({
  216. type: options.type,
  217. body1: body1,
  218. body2: body2,
  219. min: options.min,
  220. max: options.max,
  221. axe1: options.axe1,
  222. axe2: options.axe2,
  223. pos1: [pivot1.x, pivot1.y, pivot1.z],
  224. pos2: [pivot2.x, pivot2.y, pivot2.z],
  225. collision: options.collision,
  226. spring: options.spring,
  227. world: this._world
  228. });
  229. return true;
  230. };
  231. OimoJSPlugin.prototype.dispose = function () {
  232. this._world.clear();
  233. while (this._registeredMeshes.length) {
  234. this.unregisterMesh(this._registeredMeshes[0].mesh);
  235. }
  236. };
  237. OimoJSPlugin.prototype.isSupported = function () {
  238. return OIMO !== undefined;
  239. };
  240. OimoJSPlugin.prototype._getLastShape = function (body) {
  241. var lastShape = body.shapes;
  242. while (lastShape.next) {
  243. lastShape = lastShape.next;
  244. }
  245. return lastShape;
  246. };
  247. OimoJSPlugin.prototype.runOneStep = function (time) {
  248. this._world.step();
  249. // Update the position of all registered meshes
  250. var i = this._registeredMeshes.length;
  251. var m;
  252. while (i--) {
  253. var body = this._registeredMeshes[i].body.body;
  254. var mesh = this._registeredMeshes[i].mesh;
  255. var delta = this._registeredMeshes[i].delta;
  256. if (!body.sleeping) {
  257. if (body.shapes.next) {
  258. var parentShape = this._getLastShape(body);
  259. mesh.position.x = parentShape.position.x * OIMO.WORLD_SCALE;
  260. mesh.position.y = parentShape.position.y * OIMO.WORLD_SCALE;
  261. mesh.position.z = parentShape.position.z * OIMO.WORLD_SCALE;
  262. var mtx = BABYLON.Matrix.FromArray(body.getMatrix());
  263. if (!mesh.rotationQuaternion) {
  264. mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
  265. }
  266. mesh.rotationQuaternion.fromRotationMatrix(mtx);
  267. } else {
  268. m = body.getMatrix();
  269. mtx = BABYLON.Matrix.FromArray(m);
  270. // Body position
  271. var bodyX = mtx.m[12], bodyY = mtx.m[13], bodyZ = mtx.m[14];
  272. if (!delta) {
  273. mesh.position.x = bodyX;
  274. mesh.position.y = bodyY;
  275. mesh.position.z = bodyZ;
  276. } else {
  277. mesh.position.x = bodyX + delta.x;
  278. mesh.position.y = bodyY + delta.y;
  279. mesh.position.z = bodyZ + delta.z;
  280. }
  281. if (!mesh.rotationQuaternion) {
  282. mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
  283. }
  284. mesh.rotationQuaternion.fromRotationMatrix(mtx);
  285. }
  286. }
  287. }
  288. };
  289. return OimoJSPlugin;
  290. })();
  291. BABYLON.OimoJSPlugin = OimoJSPlugin;
  292. })(BABYLON || (BABYLON = {}));
  293. //# sourceMappingURL=babylon.oimoJSPlugin.js.map