babylon.collisionCoordinator.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. var BABYLON;
  2. (function (BABYLON) {
  3. (function (WorkerTaskType) {
  4. WorkerTaskType[WorkerTaskType["INIT"] = 0] = "INIT";
  5. WorkerTaskType[WorkerTaskType["UPDATE"] = 1] = "UPDATE";
  6. WorkerTaskType[WorkerTaskType["COLLIDE"] = 2] = "COLLIDE";
  7. })(BABYLON.WorkerTaskType || (BABYLON.WorkerTaskType = {}));
  8. var WorkerTaskType = BABYLON.WorkerTaskType;
  9. (function (WorkerReplyType) {
  10. WorkerReplyType[WorkerReplyType["SUCCESS"] = 0] = "SUCCESS";
  11. WorkerReplyType[WorkerReplyType["UNKNOWN_ERROR"] = 1] = "UNKNOWN_ERROR";
  12. })(BABYLON.WorkerReplyType || (BABYLON.WorkerReplyType = {}));
  13. var WorkerReplyType = BABYLON.WorkerReplyType;
  14. var CollisionCoordinatorWorker = (function () {
  15. function CollisionCoordinatorWorker() {
  16. var _this = this;
  17. this._scaledPosition = BABYLON.Vector3.Zero();
  18. this._scaledVelocity = BABYLON.Vector3.Zero();
  19. this.onMeshUpdated = function (mesh) {
  20. _this._addUpdateMeshesList[mesh.uniqueId] = CollisionCoordinatorWorker.SerializeMesh(mesh);
  21. };
  22. this.onGeometryUpdated = function (geometry) {
  23. _this._addUpdateGeometriesList[geometry.id] = CollisionCoordinatorWorker.SerializeGeometry(geometry);
  24. };
  25. this._afterRender = function () {
  26. var payload = {
  27. updatedMeshes: _this._addUpdateMeshesList,
  28. updatedGeometries: _this._addUpdateGeometriesList,
  29. removedGeometries: _this._toRemoveGeometryArray,
  30. removedMeshes: _this._toRemoveMeshesArray
  31. };
  32. var message = {
  33. payload: payload,
  34. taskType: 1 /* UPDATE */
  35. };
  36. var serializable = [];
  37. for (var id in payload.updatedGeometries) {
  38. if (payload.updatedGeometries.hasOwnProperty(id)) {
  39. //prepare transferables
  40. serializable.push(message.payload.updatedGeometries[id].indices.buffer);
  41. serializable.push(message.payload.updatedGeometries[id].normals.buffer);
  42. serializable.push(message.payload.updatedGeometries[id].positions.buffer);
  43. }
  44. }
  45. //this variable is here only in case the update takes longer than a frame!
  46. _this._runningUpdated++;
  47. _this._worker.postMessage(message, serializable);
  48. _this._addUpdateMeshesList = {};
  49. _this._addUpdateGeometriesList = {};
  50. _this._toRemoveGeometryArray = [];
  51. _this._toRemoveMeshesArray = [];
  52. };
  53. this._onMessageFromWorker = function (e) {
  54. var returnData = e.data;
  55. if (returnData.error != 0 /* SUCCESS */) {
  56. //TODO what errors can be returned from the worker?
  57. BABYLON.Tools.Warn("error returned from worker!");
  58. return;
  59. }
  60. switch (returnData.taskType) {
  61. case 0 /* INIT */:
  62. //TODO is init required after worker is done initializing?
  63. _this._init = true;
  64. break;
  65. case 1 /* UPDATE */:
  66. _this._runningUpdated--;
  67. break;
  68. case 2 /* COLLIDE */:
  69. _this._runningCollisionTask = false;
  70. var returnPayload = returnData.payload;
  71. if (!_this._collisionsCallbackArray[returnPayload.collisionId])
  72. return;
  73. _this._collisionsCallbackArray[returnPayload.collisionId](returnPayload.collisionId, BABYLON.Vector3.FromArray(returnPayload.newPosition), _this._scene.getMeshByUniqueID(returnPayload.collidedMeshUniqueId));
  74. //cleanup
  75. _this._collisionsCallbackArray[returnPayload.collisionId] = undefined;
  76. break;
  77. }
  78. };
  79. this._collisionsCallbackArray = [];
  80. this._init = false;
  81. this._runningUpdated = 0;
  82. this._runningCollisionTask = false;
  83. this._addUpdateMeshesList = {};
  84. this._addUpdateGeometriesList = {};
  85. this._toRemoveGeometryArray = [];
  86. this._toRemoveMeshesArray = [];
  87. }
  88. CollisionCoordinatorWorker.prototype.getNewPosition = function (position, velocity, collider, maximumRetry, excludedMesh, onNewPosition, collisionIndex) {
  89. if (this._collisionsCallbackArray[collisionIndex])
  90. return;
  91. position.divideToRef(collider.radius, this._scaledPosition);
  92. velocity.divideToRef(collider.radius, this._scaledVelocity);
  93. this._collisionsCallbackArray[collisionIndex] = onNewPosition;
  94. };
  95. CollisionCoordinatorWorker.prototype.init = function (scene) {
  96. this._scene = scene;
  97. this._scene.registerAfterRender(this._afterRender);
  98. var blobURL = URL.createObjectURL(new Blob(['(', BABYLON.CollisionWorker.toString(), ')()'], { type: 'application/javascript' }));
  99. this._worker = new Worker(blobURL);
  100. URL.revokeObjectURL(blobURL);
  101. };
  102. CollisionCoordinatorWorker.prototype.destroy = function () {
  103. this._scene.unregisterAfterRender(this._afterRender);
  104. this._worker.terminate();
  105. };
  106. CollisionCoordinatorWorker.prototype.onMeshAdded = function (mesh) {
  107. mesh.registerAfterWorldMatrixUpdate(this.onMeshUpdated);
  108. this.onMeshUpdated(mesh);
  109. };
  110. CollisionCoordinatorWorker.prototype.onMeshRemoved = function (mesh) {
  111. this._toRemoveMeshesArray.push(mesh.uniqueId);
  112. };
  113. CollisionCoordinatorWorker.prototype.onGeometryAdded = function (geometry) {
  114. //TODO this will break if the user uses his own function. This should be an array on callbacks!
  115. geometry.onGeometryUpdated = this.onGeometryUpdated;
  116. this.onGeometryUpdated(geometry);
  117. };
  118. CollisionCoordinatorWorker.prototype.onGeometryDeleted = function (geometry) {
  119. this._toRemoveGeometryArray.push(geometry.id);
  120. };
  121. CollisionCoordinatorWorker.SerializeMesh = function (mesh) {
  122. var submeshes = [];
  123. if (mesh.subMeshes) {
  124. submeshes = mesh.subMeshes.map(function (sm, idx) {
  125. return {
  126. position: idx,
  127. verticesStart: sm.verticesStart,
  128. verticesCount: sm.verticesCount,
  129. indexStart: sm.indexStart,
  130. indexCount: sm.indexCount
  131. };
  132. });
  133. }
  134. var geometryId = mesh.geometry ? mesh.geometry.id : null;
  135. return {
  136. uniqueId: mesh.uniqueId,
  137. id: mesh.id,
  138. name: mesh.name,
  139. geometryId: geometryId,
  140. sphereCenter: mesh.getBoundingInfo().boundingSphere.centerWorld.asArray(),
  141. sphereRadius: mesh.getBoundingInfo().boundingSphere.radiusWorld,
  142. boxMinimum: mesh.getBoundingInfo().boundingBox.minimumWorld.asArray(),
  143. boxMaximum: mesh.getBoundingInfo().boundingBox.maximumWorld.asArray(),
  144. worldMatrixFromCache: mesh.worldMatrixFromCache.asArray(),
  145. subMeshes: submeshes,
  146. checkCollisions: mesh.checkCollisions
  147. };
  148. };
  149. CollisionCoordinatorWorker.SerializeGeometry = function (geometry) {
  150. return {
  151. id: geometry.id,
  152. positions: new Float32Array(geometry.getVerticesData(BABYLON.VertexBuffer.PositionKind) || []),
  153. normals: new Float32Array(geometry.getVerticesData(BABYLON.VertexBuffer.NormalKind) || []),
  154. indices: new Int32Array(geometry.getIndices() || []),
  155. };
  156. };
  157. return CollisionCoordinatorWorker;
  158. })();
  159. BABYLON.CollisionCoordinatorWorker = CollisionCoordinatorWorker;
  160. var CollisionCoordinatorLegacy = (function () {
  161. function CollisionCoordinatorLegacy() {
  162. this._scaledPosition = BABYLON.Vector3.Zero();
  163. this._scaledVelocity = BABYLON.Vector3.Zero();
  164. this._finalPosition = BABYLON.Vector3.Zero();
  165. }
  166. CollisionCoordinatorLegacy.prototype.getNewPosition = function (position, velocity, collider, maximumRetry, excludedMesh, onNewPosition, collisionIndex) {
  167. position.divideToRef(collider.radius, this._scaledPosition);
  168. velocity.divideToRef(collider.radius, this._scaledVelocity);
  169. collider.retry = 0;
  170. collider.initialVelocity = this._scaledVelocity;
  171. collider.initialPosition = this._scaledPosition;
  172. this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, this._finalPosition, excludedMesh);
  173. this._finalPosition.multiplyInPlace(collider.radius);
  174. //run the callback
  175. onNewPosition(collisionIndex, this._finalPosition, collider.collidedMesh);
  176. };
  177. CollisionCoordinatorLegacy.prototype.init = function (scene) {
  178. this._scene = scene;
  179. };
  180. CollisionCoordinatorLegacy.prototype.destroy = function () {
  181. //Legacy need no destruction method.
  182. };
  183. //No update in legacy mode
  184. CollisionCoordinatorLegacy.prototype.onMeshAdded = function (mesh) {
  185. };
  186. CollisionCoordinatorLegacy.prototype.onMeshUpdated = function (mesh) {
  187. };
  188. CollisionCoordinatorLegacy.prototype.onMeshRemoved = function (mesh) {
  189. };
  190. CollisionCoordinatorLegacy.prototype.onGeometryAdded = function (geometry) {
  191. };
  192. CollisionCoordinatorLegacy.prototype.onGeometryUpdated = function (geometry) {
  193. };
  194. CollisionCoordinatorLegacy.prototype.onGeometryDeleted = function (geometry) {
  195. };
  196. CollisionCoordinatorLegacy.prototype._collideWithWorld = function (position, velocity, collider, maximumRetry, finalPosition, excludedMesh) {
  197. if (excludedMesh === void 0) { excludedMesh = null; }
  198. var closeDistance = BABYLON.Engine.CollisionsEpsilon * 10.0;
  199. if (collider.retry >= maximumRetry) {
  200. finalPosition.copyFrom(position);
  201. return;
  202. }
  203. collider._initialize(position, velocity, closeDistance);
  204. for (var index = 0; index < this._scene.meshes.length; index++) {
  205. var mesh = this._scene.meshes[index];
  206. if (mesh.isEnabled() && mesh.checkCollisions && mesh.subMeshes && mesh !== excludedMesh) {
  207. mesh._checkCollision(collider);
  208. }
  209. }
  210. if (!collider.collisionFound) {
  211. position.addToRef(velocity, finalPosition);
  212. return;
  213. }
  214. if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
  215. collider._getResponse(position, velocity);
  216. }
  217. if (velocity.length() <= closeDistance) {
  218. finalPosition.copyFrom(position);
  219. return;
  220. }
  221. collider.retry++;
  222. this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh);
  223. };
  224. return CollisionCoordinatorLegacy;
  225. })();
  226. BABYLON.CollisionCoordinatorLegacy = CollisionCoordinatorLegacy;
  227. })(BABYLON || (BABYLON = {}));
  228. //# sourceMappingURL=babylon.collisionCoordinator.js.map