babylon.subMesh.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. var BABYLON;
  2. (function (BABYLON) {
  3. var SubMesh = (function () {
  4. function SubMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, mesh, renderingMesh, createBoundingBox) {
  5. if (createBoundingBox === void 0) { createBoundingBox = true; }
  6. this.materialIndex = materialIndex;
  7. this.verticesStart = verticesStart;
  8. this.verticesCount = verticesCount;
  9. this.indexStart = indexStart;
  10. this.indexCount = indexCount;
  11. this._renderId = 0;
  12. this._mesh = mesh;
  13. this._renderingMesh = renderingMesh || mesh;
  14. mesh.subMeshes.push(this);
  15. this._trianglePlanes = [];
  16. this._id = mesh.subMeshes.length - 1;
  17. if (createBoundingBox) {
  18. this.refreshBoundingInfo();
  19. mesh.computeWorldMatrix(true);
  20. }
  21. }
  22. Object.defineProperty(SubMesh.prototype, "IsGlobal", {
  23. get: function () {
  24. return (this.verticesStart === 0 && this.verticesCount == this._mesh.getTotalVertices());
  25. },
  26. enumerable: true,
  27. configurable: true
  28. });
  29. SubMesh.prototype.getBoundingInfo = function () {
  30. if (this.IsGlobal) {
  31. return this._mesh.getBoundingInfo();
  32. }
  33. return this._boundingInfo;
  34. };
  35. SubMesh.prototype.getMesh = function () {
  36. return this._mesh;
  37. };
  38. SubMesh.prototype.getRenderingMesh = function () {
  39. return this._renderingMesh;
  40. };
  41. SubMesh.prototype.getMaterial = function () {
  42. var rootMaterial = this._renderingMesh.material;
  43. if (rootMaterial && rootMaterial instanceof BABYLON.MultiMaterial) {
  44. var multiMaterial = rootMaterial;
  45. return multiMaterial.getSubMaterial(this.materialIndex);
  46. }
  47. if (!rootMaterial) {
  48. return this._mesh.getScene().defaultMaterial;
  49. }
  50. return rootMaterial;
  51. };
  52. // Methods
  53. SubMesh.prototype.refreshBoundingInfo = function () {
  54. this._lastColliderWorldVertices = null;
  55. if (this.IsGlobal) {
  56. return;
  57. }
  58. var data = this._renderingMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
  59. if (!data) {
  60. this._boundingInfo = this._mesh._boundingInfo;
  61. return;
  62. }
  63. var indices = this._renderingMesh.getIndices();
  64. var extend;
  65. //is this the only submesh?
  66. if (this.indexStart === 0 && this.indexCount === indices.length) {
  67. //the rendering mesh's bounding info can be used, it is the standard submesh for all indices.
  68. extend = { minimum: this._renderingMesh.getBoundingInfo().minimum.clone(), maximum: this._renderingMesh.getBoundingInfo().maximum.clone() };
  69. }
  70. else {
  71. extend = BABYLON.Tools.ExtractMinAndMaxIndexed(data, indices, this.indexStart, this.indexCount, this._renderingMesh.geometry.boundingBias);
  72. }
  73. this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
  74. };
  75. SubMesh.prototype._checkCollision = function (collider) {
  76. return this.getBoundingInfo()._checkCollision(collider);
  77. };
  78. SubMesh.prototype.updateBoundingInfo = function (world) {
  79. if (!this.getBoundingInfo()) {
  80. this.refreshBoundingInfo();
  81. }
  82. this.getBoundingInfo().update(world);
  83. };
  84. SubMesh.prototype.isInFrustum = function (frustumPlanes) {
  85. return this.getBoundingInfo().isInFrustum(frustumPlanes);
  86. };
  87. SubMesh.prototype.isCompletelyInFrustum = function (frustumPlanes) {
  88. return this.getBoundingInfo().isCompletelyInFrustum(frustumPlanes);
  89. };
  90. SubMesh.prototype.render = function (enableAlphaMode) {
  91. this._renderingMesh.render(this, enableAlphaMode);
  92. };
  93. SubMesh.prototype.getLinesIndexBuffer = function (indices, engine) {
  94. if (!this._linesIndexBuffer) {
  95. var linesIndices = [];
  96. for (var index = this.indexStart; index < this.indexStart + this.indexCount; index += 3) {
  97. linesIndices.push(indices[index], indices[index + 1], indices[index + 1], indices[index + 2], indices[index + 2], indices[index]);
  98. }
  99. this._linesIndexBuffer = engine.createIndexBuffer(linesIndices);
  100. this.linesIndexCount = linesIndices.length;
  101. }
  102. return this._linesIndexBuffer;
  103. };
  104. SubMesh.prototype.canIntersects = function (ray) {
  105. return ray.intersectsBox(this.getBoundingInfo().boundingBox);
  106. };
  107. SubMesh.prototype.intersects = function (ray, positions, indices, fastCheck) {
  108. var intersectInfo = null;
  109. // LineMesh first as it's also a Mesh...
  110. if (this._mesh instanceof BABYLON.LinesMesh) {
  111. var lineMesh = this._mesh;
  112. // Line test
  113. for (var index = this.indexStart; index < this.indexStart + this.indexCount; index += 2) {
  114. var p0 = positions[indices[index]];
  115. var p1 = positions[indices[index + 1]];
  116. var length = ray.intersectionSegment(p0, p1, lineMesh.intersectionThreshold);
  117. if (length < 0) {
  118. continue;
  119. }
  120. if (fastCheck || !intersectInfo || length < intersectInfo.distance) {
  121. intersectInfo = new BABYLON.IntersectionInfo(null, null, length);
  122. if (fastCheck) {
  123. break;
  124. }
  125. }
  126. }
  127. }
  128. else {
  129. // Triangles test
  130. for (var index = this.indexStart; index < this.indexStart + this.indexCount; index += 3) {
  131. var p0 = positions[indices[index]];
  132. var p1 = positions[indices[index + 1]];
  133. var p2 = positions[indices[index + 2]];
  134. var currentIntersectInfo = ray.intersectsTriangle(p0, p1, p2);
  135. if (currentIntersectInfo) {
  136. if (currentIntersectInfo.distance < 0) {
  137. continue;
  138. }
  139. if (fastCheck || !intersectInfo || currentIntersectInfo.distance < intersectInfo.distance) {
  140. intersectInfo = currentIntersectInfo;
  141. intersectInfo.faceId = index / 3;
  142. if (fastCheck) {
  143. break;
  144. }
  145. }
  146. }
  147. }
  148. }
  149. return intersectInfo;
  150. };
  151. // Clone
  152. SubMesh.prototype.clone = function (newMesh, newRenderingMesh) {
  153. var result = new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh, newRenderingMesh, false);
  154. if (!this.IsGlobal) {
  155. result._boundingInfo = new BABYLON.BoundingInfo(this.getBoundingInfo().minimum, this.getBoundingInfo().maximum);
  156. }
  157. return result;
  158. };
  159. // Dispose
  160. SubMesh.prototype.dispose = function () {
  161. if (this._linesIndexBuffer) {
  162. this._mesh.getScene().getEngine()._releaseBuffer(this._linesIndexBuffer);
  163. this._linesIndexBuffer = null;
  164. }
  165. // Remove from mesh
  166. var index = this._mesh.subMeshes.indexOf(this);
  167. this._mesh.subMeshes.splice(index, 1);
  168. };
  169. // Statics
  170. SubMesh.CreateFromIndices = function (materialIndex, startIndex, indexCount, mesh, renderingMesh) {
  171. var minVertexIndex = Number.MAX_VALUE;
  172. var maxVertexIndex = -Number.MAX_VALUE;
  173. renderingMesh = renderingMesh || mesh;
  174. var indices = renderingMesh.getIndices();
  175. for (var index = startIndex; index < startIndex + indexCount; index++) {
  176. var vertexIndex = indices[index];
  177. if (vertexIndex < minVertexIndex)
  178. minVertexIndex = vertexIndex;
  179. if (vertexIndex > maxVertexIndex)
  180. maxVertexIndex = vertexIndex;
  181. }
  182. return new SubMesh(materialIndex, minVertexIndex, maxVertexIndex - minVertexIndex + 1, startIndex, indexCount, mesh, renderingMesh);
  183. };
  184. return SubMesh;
  185. }());
  186. BABYLON.SubMesh = SubMesh;
  187. })(BABYLON || (BABYLON = {}));