babylon.collisionWorker.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. var BABYLON;
  2. (function (BABYLON) {
  3. var CollisionCache = (function () {
  4. function CollisionCache() {
  5. this._meshes = {};
  6. this._geometries = {};
  7. }
  8. CollisionCache.prototype.getMeshes = function () {
  9. return this._meshes;
  10. };
  11. CollisionCache.prototype.getGeometries = function () {
  12. return this._geometries;
  13. };
  14. CollisionCache.prototype.getMesh = function (id) {
  15. return this._meshes[id];
  16. };
  17. CollisionCache.prototype.addMesh = function (mesh) {
  18. this._meshes[mesh.uniqueId] = mesh;
  19. };
  20. CollisionCache.prototype.getGeometry = function (id) {
  21. return this._geometries[id];
  22. };
  23. CollisionCache.prototype.addGeometry = function (geometry) {
  24. this._geometries[geometry.id] = geometry;
  25. };
  26. return CollisionCache;
  27. })();
  28. BABYLON.CollisionCache = CollisionCache;
  29. var CollideWorker = (function () {
  30. function CollideWorker(collider, _collisionCache, finalPosition) {
  31. this.collider = collider;
  32. this._collisionCache = _collisionCache;
  33. this.finalPosition = finalPosition;
  34. this.collisionsScalingMatrix = BABYLON.Matrix.Zero();
  35. this.collisionTranformationMatrix = BABYLON.Matrix.Zero();
  36. }
  37. CollideWorker.prototype.collideWithWorld = function (position, velocity, maximumRetry, excludedMeshUniqueId) {
  38. //TODO CollisionsEpsilon should be defined here and not in the engine.
  39. var closeDistance = 0.01;
  40. //is initializing here correct? A quick look - looks like it is fine.
  41. if (this.collider.retry >= maximumRetry) {
  42. this.finalPosition.copyFrom(position);
  43. return;
  44. }
  45. this.collider._initialize(position, velocity, closeDistance);
  46. // Check all meshes
  47. var meshes = this._collisionCache.getMeshes();
  48. for (var uniqueId in meshes) {
  49. if (meshes.hasOwnProperty(uniqueId) && parseInt(uniqueId) != excludedMeshUniqueId) {
  50. var mesh = meshes[uniqueId];
  51. if (mesh.checkCollisions)
  52. this.checkCollision(mesh);
  53. }
  54. }
  55. if (!this.collider.collisionFound) {
  56. position.addToRef(velocity, this.finalPosition);
  57. return;
  58. }
  59. if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
  60. this.collider._getResponse(position, velocity);
  61. }
  62. if (velocity.length() <= closeDistance) {
  63. this.finalPosition.copyFrom(position);
  64. return;
  65. }
  66. this.collider.retry++;
  67. this.collideWithWorld(position, velocity, maximumRetry, excludedMeshUniqueId);
  68. };
  69. CollideWorker.prototype.checkCollision = function (mesh) {
  70. if (!this.collider._canDoCollision(BABYLON.Vector3.FromArray(mesh.sphereCenter), mesh.sphereRadius, BABYLON.Vector3.FromArray(mesh.boxMinimum), BABYLON.Vector3.FromArray(mesh.boxMaximum))) {
  71. return;
  72. }
  73. ;
  74. // Transformation matrix
  75. BABYLON.Matrix.ScalingToRef(1.0 / this.collider.radius.x, 1.0 / this.collider.radius.y, 1.0 / this.collider.radius.z, this.collisionsScalingMatrix);
  76. var worldFromCache = BABYLON.Matrix.FromArray(mesh.worldMatrixFromCache);
  77. worldFromCache.multiplyToRef(this.collisionsScalingMatrix, this.collisionTranformationMatrix);
  78. this.processCollisionsForSubMeshes(this.collisionTranformationMatrix, mesh);
  79. //return colTransMat;
  80. };
  81. CollideWorker.prototype.processCollisionsForSubMeshes = function (transformMatrix, mesh) {
  82. var len;
  83. var subMeshes;
  84. // No Octrees for now
  85. //if (this._submeshesOctree && this.useOctreeForCollisions) {
  86. // var radius = collider.velocityWorldLength + Math.max(collider.radius.x, collider.radius.y, collider.radius.z);
  87. // var intersections = this._submeshesOctree.intersects(collider.basePointWorld, radius);
  88. // len = intersections.length;
  89. // subMeshes = intersections.data;
  90. //} else {
  91. subMeshes = mesh.subMeshes;
  92. len = subMeshes.length;
  93. //}
  94. if (!mesh.geometryId) {
  95. console.log("no mesh geometry id");
  96. return;
  97. }
  98. var meshGeometry = this._collisionCache.getGeometry(mesh.geometryId);
  99. if (!meshGeometry) {
  100. console.log("couldn't find geometry", mesh.geometryId);
  101. return;
  102. }
  103. for (var index = 0; index < len; index++) {
  104. var subMesh = subMeshes[index];
  105. // Bounding test
  106. if (len > 1 && !this.checkSubmeshCollision(subMesh))
  107. continue;
  108. //Unneeded
  109. //subMesh['getMesh'] = function () {
  110. // return mesh.uniqueId;
  111. //}
  112. this.collideForSubMesh(subMesh, transformMatrix, meshGeometry);
  113. }
  114. };
  115. CollideWorker.prototype.collideForSubMesh = function (subMesh, transformMatrix, meshGeometry) {
  116. var positionsArray = [];
  117. for (var i = 0; i < meshGeometry.positions.length; i = i + 3) {
  118. var p = BABYLON.Vector3.FromArray([meshGeometry.positions[i], meshGeometry.positions[i + 1], meshGeometry.positions[i + 2]]);
  119. positionsArray.push(p);
  120. }
  121. subMesh['_lastColliderTransformMatrix'] = transformMatrix.clone();
  122. //The following two arrays should be initialized CORRECTLY to save some calculation time.
  123. subMesh['_lastColliderWorldVertices'] = [];
  124. subMesh['_trianglePlanes'] = [];
  125. var start = subMesh.verticesStart;
  126. var end = (subMesh.verticesStart + subMesh.verticesCount);
  127. for (var i = start; i < end; i++) {
  128. subMesh['_lastColliderWorldVertices'].push(BABYLON.Vector3.TransformCoordinates(positionsArray[i], transformMatrix));
  129. }
  130. //}
  131. // Collide
  132. this.collider._collide(subMesh['_trianglePlanes'] = [], subMesh['_lastColliderWorldVertices'], meshGeometry.indices, subMesh.indexStart, subMesh.indexStart + subMesh.indexCount, subMesh.verticesStart, subMesh.hasMaterial);
  133. };
  134. //TODO - this! :-)
  135. CollideWorker.prototype.checkSubmeshCollision = function (subMesh) {
  136. return this.collider._canDoCollision(BABYLON.Vector3.FromArray(subMesh.sphereCenter), subMesh.sphereRadius, BABYLON.Vector3.FromArray(subMesh.boxMinimum), BABYLON.Vector3.FromArray(subMesh.boxMaximum));
  137. };
  138. return CollideWorker;
  139. })();
  140. BABYLON.CollideWorker = CollideWorker;
  141. var CollisionDetectorTransferable = (function () {
  142. function CollisionDetectorTransferable() {
  143. }
  144. CollisionDetectorTransferable.prototype.onInit = function (payload) {
  145. this._collisionCache = new CollisionCache();
  146. var reply = {
  147. error: 0 /* SUCCESS */,
  148. taskType: 0 /* INIT */
  149. };
  150. postMessage(reply, undefined);
  151. };
  152. CollisionDetectorTransferable.prototype.onUpdate = function (payload) {
  153. for (var id in payload.updatedGeometries) {
  154. if (payload.updatedGeometries.hasOwnProperty(id)) {
  155. this._collisionCache.addGeometry(payload.updatedGeometries[id]);
  156. }
  157. }
  158. for (var uniqueId in payload.updatedMeshes) {
  159. if (payload.updatedMeshes.hasOwnProperty(uniqueId)) {
  160. this._collisionCache.addMesh(payload.updatedMeshes[uniqueId]);
  161. }
  162. }
  163. var replay = {
  164. error: 0 /* SUCCESS */,
  165. taskType: 1 /* UPDATE */
  166. };
  167. postMessage(replay, undefined);
  168. };
  169. CollisionDetectorTransferable.prototype.onCollision = function (payload) {
  170. var finalPosition = BABYLON.Vector3.Zero();
  171. //create a new collider
  172. var collider = new BABYLON.Collider();
  173. collider.radius = BABYLON.Vector3.FromArray(payload.collider.radius);
  174. var colliderWorker = new CollideWorker(collider, this._collisionCache, finalPosition);
  175. colliderWorker.collideWithWorld(BABYLON.Vector3.FromArray(payload.collider.position), BABYLON.Vector3.FromArray(payload.collider.velocity), payload.maximumRetry, payload.excludedMeshUniqueId);
  176. var replyPayload = {
  177. collidedMeshUniqueId: collider.collidedMesh,
  178. collisionId: payload.collisionId,
  179. newPosition: finalPosition.asArray()
  180. };
  181. var reply = {
  182. error: 0 /* SUCCESS */,
  183. taskType: 2 /* COLLIDE */,
  184. payload: replyPayload
  185. };
  186. postMessage(reply, undefined);
  187. };
  188. return CollisionDetectorTransferable;
  189. })();
  190. BABYLON.CollisionDetectorTransferable = CollisionDetectorTransferable;
  191. //check if we are in a web worker, as this code should NOT run on the main UI thread
  192. if (self && self instanceof WorkerGlobalScope) {
  193. //Window hack to allow including babylonjs native code. the <any> is for typescript.
  194. window = {};
  195. var collisionDetector = new CollisionDetectorTransferable();
  196. var onNewMessage = function (event) {
  197. var message = event.data;
  198. switch (message.taskType) {
  199. case 0 /* INIT */:
  200. collisionDetector.onInit(message.payload);
  201. break;
  202. case 2 /* COLLIDE */:
  203. collisionDetector.onCollision(message.payload);
  204. break;
  205. case 1 /* UPDATE */:
  206. collisionDetector.onUpdate(message.payload);
  207. break;
  208. }
  209. };
  210. self.onmessage = onNewMessage;
  211. }
  212. })(BABYLON || (BABYLON = {}));
  213. //# sourceMappingURL=babylon.collisionWorker.js.map