babylon.collisionCoordinator.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. //TODO init worker
  99. };
  100. CollisionCoordinatorWorker.prototype.destroy = function () {
  101. this._scene.unregisterAfterRender(this._afterRender);
  102. //TODO destroy worker
  103. };
  104. CollisionCoordinatorWorker.prototype.onMeshAdded = function (mesh) {
  105. mesh.registerAfterWorldMatrixUpdate(this.onMeshUpdated);
  106. this.onMeshUpdated(mesh);
  107. };
  108. CollisionCoordinatorWorker.prototype.onMeshRemoved = function (mesh) {
  109. this._toRemoveMeshesArray.push(mesh.uniqueId);
  110. };
  111. CollisionCoordinatorWorker.prototype.onGeometryAdded = function (geometry) {
  112. //TODO this will break if the user uses his own function. This should be an array on callbacks!
  113. geometry.onGeometryUpdated = this.onGeometryUpdated;
  114. this.onGeometryUpdated(geometry);
  115. };
  116. CollisionCoordinatorWorker.prototype.onGeometryDeleted = function (geometry) {
  117. this._toRemoveGeometryArray.push(geometry.id);
  118. };
  119. CollisionCoordinatorWorker.SerializeMesh = function (mesh) {
  120. var submeshes = [];
  121. if (mesh.subMeshes) {
  122. submeshes = mesh.subMeshes.map(function (sm, idx) {
  123. return {
  124. position: idx,
  125. verticesStart: sm.verticesStart,
  126. verticesCount: sm.verticesCount,
  127. indexStart: sm.indexStart,
  128. indexCount: sm.indexCount
  129. };
  130. });
  131. }
  132. var geometryId = mesh.geometry ? mesh.geometry.id : null;
  133. return {
  134. uniqueId: mesh.uniqueId,
  135. id: mesh.id,
  136. name: mesh.name,
  137. geometryId: geometryId,
  138. sphereCenter: mesh.getBoundingInfo().boundingSphere.centerWorld.asArray(),
  139. sphereRadius: mesh.getBoundingInfo().boundingSphere.radiusWorld,
  140. boxMinimum: mesh.getBoundingInfo().boundingBox.minimumWorld.asArray(),
  141. boxMaximum: mesh.getBoundingInfo().boundingBox.maximumWorld.asArray(),
  142. worldMatrixFromCache: mesh.worldMatrixFromCache.asArray(),
  143. subMeshes: submeshes,
  144. checkCollisions: mesh.checkCollisions
  145. };
  146. };
  147. CollisionCoordinatorWorker.SerializeGeometry = function (geometry) {
  148. return {
  149. id: geometry.id,
  150. positions: new Float32Array(geometry.getVerticesData(BABYLON.VertexBuffer.PositionKind) || []),
  151. normals: new Float32Array(geometry.getVerticesData(BABYLON.VertexBuffer.NormalKind) || []),
  152. indices: new Int32Array(geometry.getIndices() || []),
  153. };
  154. };
  155. return CollisionCoordinatorWorker;
  156. })();
  157. BABYLON.CollisionCoordinatorWorker = CollisionCoordinatorWorker;
  158. var CollisionCoordinatorLegacy = (function () {
  159. function CollisionCoordinatorLegacy() {
  160. this._scaledPosition = BABYLON.Vector3.Zero();
  161. this._scaledVelocity = BABYLON.Vector3.Zero();
  162. this._finalPosition = BABYLON.Vector3.Zero();
  163. }
  164. CollisionCoordinatorLegacy.prototype.getNewPosition = function (position, velocity, collider, maximumRetry, excludedMesh, onNewPosition, collisionIndex) {
  165. position.divideToRef(collider.radius, this._scaledPosition);
  166. velocity.divideToRef(collider.radius, this._scaledVelocity);
  167. collider.retry = 0;
  168. collider.initialVelocity = this._scaledVelocity;
  169. collider.initialPosition = this._scaledPosition;
  170. this._collideWithWorld(this._scaledPosition, this._scaledVelocity, collider, maximumRetry, this._finalPosition, excludedMesh);
  171. this._finalPosition.multiplyInPlace(collider.radius);
  172. //run the callback
  173. onNewPosition(collisionIndex, this._finalPosition, collider.collidedMesh);
  174. };
  175. CollisionCoordinatorLegacy.prototype.init = function (scene) {
  176. this._scene = scene;
  177. };
  178. CollisionCoordinatorLegacy.prototype.destroy = function () {
  179. //Legacy need no destruction method.
  180. };
  181. //No update in legacy mode
  182. CollisionCoordinatorLegacy.prototype.onMeshAdded = function (mesh) {
  183. };
  184. CollisionCoordinatorLegacy.prototype.onMeshUpdated = function (mesh) {
  185. };
  186. CollisionCoordinatorLegacy.prototype.onMeshRemoved = function (mesh) {
  187. };
  188. CollisionCoordinatorLegacy.prototype.onGeometryAdded = function (geometry) {
  189. };
  190. CollisionCoordinatorLegacy.prototype.onGeometryUpdated = function (geometry) {
  191. };
  192. CollisionCoordinatorLegacy.prototype.onGeometryDeleted = function (geometry) {
  193. };
  194. CollisionCoordinatorLegacy.prototype._collideWithWorld = function (position, velocity, collider, maximumRetry, finalPosition, excludedMesh) {
  195. if (excludedMesh === void 0) { excludedMesh = null; }
  196. var closeDistance = BABYLON.Engine.CollisionsEpsilon * 10.0;
  197. if (collider.retry >= maximumRetry) {
  198. finalPosition.copyFrom(position);
  199. return;
  200. }
  201. collider._initialize(position, velocity, closeDistance);
  202. for (var index = 0; index < this._scene.meshes.length; index++) {
  203. var mesh = this._scene.meshes[index];
  204. if (mesh.isEnabled() && mesh.checkCollisions && mesh.subMeshes && mesh !== excludedMesh) {
  205. mesh._checkCollision(collider);
  206. }
  207. }
  208. if (!collider.collisionFound) {
  209. position.addToRef(velocity, finalPosition);
  210. return;
  211. }
  212. if (velocity.x !== 0 || velocity.y !== 0 || velocity.z !== 0) {
  213. collider._getResponse(position, velocity);
  214. }
  215. if (velocity.length() <= closeDistance) {
  216. finalPosition.copyFrom(position);
  217. return;
  218. }
  219. collider.retry++;
  220. this._collideWithWorld(position, velocity, collider, maximumRetry, finalPosition, excludedMesh);
  221. };
  222. return CollisionCoordinatorLegacy;
  223. })();
  224. BABYLON.CollisionCoordinatorLegacy = CollisionCoordinatorLegacy;
  225. })(BABYLON || (BABYLON = {}));
  226. //# sourceMappingURL=babylon.collisionCoordinator.js.map