babylon.instancedMesh.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. module BABYLON {
  2. /**
  3. * Creates an instance based on a source mesh.
  4. */
  5. export class InstancedMesh extends AbstractMesh {
  6. private _sourceMesh: Mesh;
  7. private _currentLOD: Mesh;
  8. constructor(name: string, source: Mesh) {
  9. super(name, source.getScene());
  10. source.instances.push(this);
  11. this._sourceMesh = source;
  12. this.position.copyFrom(source.position);
  13. this.rotation.copyFrom(source.rotation);
  14. this.scaling.copyFrom(source.scaling);
  15. if (source.rotationQuaternion) {
  16. this.rotationQuaternion = source.rotationQuaternion.clone();
  17. }
  18. this.infiniteDistance = source.infiniteDistance;
  19. this.setPivotMatrix(source.getPivotMatrix());
  20. this.refreshBoundingInfo();
  21. this._syncSubMeshes();
  22. }
  23. /**
  24. * Returns the string "InstancedMesh".
  25. */
  26. public getClassName(): string {
  27. return "InstancedMesh";
  28. }
  29. // Methods
  30. public get receiveShadows(): boolean {
  31. return this._sourceMesh.receiveShadows;
  32. }
  33. public get material(): Material {
  34. return this._sourceMesh.material;
  35. }
  36. public get visibility(): number {
  37. return this._sourceMesh.visibility;
  38. }
  39. public get skeleton(): Skeleton {
  40. return this._sourceMesh.skeleton;
  41. }
  42. public get renderingGroupId(): number {
  43. return this._sourceMesh.renderingGroupId;
  44. }
  45. /**
  46. * Returns the total number of vertices (integer).
  47. */
  48. public getTotalVertices(): number {
  49. return this._sourceMesh.getTotalVertices();
  50. }
  51. public get sourceMesh(): Mesh {
  52. return this._sourceMesh;
  53. }
  54. /**
  55. * Returns a float array or a Float32Array of the requested kind of data : positons, normals, uvs, etc.
  56. */
  57. public getVerticesData(kind: string, copyWhenShared?: boolean): number[] | Float32Array {
  58. return this._sourceMesh.getVerticesData(kind, copyWhenShared);
  59. }
  60. /**
  61. * Sets the vertex data of the mesh geometry for the requested `kind`.
  62. * If the mesh has no geometry, a new Geometry object is set to the mesh and then passed this vertex data.
  63. * The `data` are either a numeric array either a Float32Array.
  64. * The parameter `updatable` is passed as is to the underlying Geometry object constructor (if initianilly none) or updater.
  65. * The parameter `stride` is an optional positive integer, it is usually automatically deducted from the `kind` (3 for positions or normals, 2 for UV, etc).
  66. * Note that a new underlying VertexBuffer object is created each call.
  67. * If the `kind` is the `PositionKind`, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.
  68. *
  69. * Possible `kind` values :
  70. * - BABYLON.VertexBuffer.PositionKind
  71. * - BABYLON.VertexBuffer.UVKind
  72. * - BABYLON.VertexBuffer.UV2Kind
  73. * - BABYLON.VertexBuffer.UV3Kind
  74. * - BABYLON.VertexBuffer.UV4Kind
  75. * - BABYLON.VertexBuffer.UV5Kind
  76. * - BABYLON.VertexBuffer.UV6Kind
  77. * - BABYLON.VertexBuffer.ColorKind
  78. * - BABYLON.VertexBuffer.MatricesIndicesKind
  79. * - BABYLON.VertexBuffer.MatricesIndicesExtraKind
  80. * - BABYLON.VertexBuffer.MatricesWeightsKind
  81. * - BABYLON.VertexBuffer.MatricesWeightsExtraKind
  82. *
  83. * Returns the Mesh.
  84. */
  85. public setVerticesData(kind: string, data: number[] | Float32Array, updatable?: boolean, stride?: number): Mesh {
  86. if (this.sourceMesh) {
  87. this.sourceMesh.setVerticesData(kind, data, updatable, stride);
  88. }
  89. return this.sourceMesh;
  90. }
  91. /**
  92. * Updates the existing vertex data of the mesh geometry for the requested `kind`.
  93. * If the mesh has no geometry, it is simply returned as it is.
  94. * The `data` are either a numeric array either a Float32Array.
  95. * No new underlying VertexBuffer object is created.
  96. * If the `kind` is the `PositionKind` and if `updateExtends` is true, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.
  97. * If the parameter `makeItUnique` is true, a new global geometry is created from this positions and is set to the mesh.
  98. *
  99. * Possible `kind` values :
  100. * - BABYLON.VertexBuffer.PositionKind
  101. * - BABYLON.VertexBuffer.UVKind
  102. * - BABYLON.VertexBuffer.UV2Kind
  103. * - BABYLON.VertexBuffer.UV3Kind
  104. * - BABYLON.VertexBuffer.UV4Kind
  105. * - BABYLON.VertexBuffer.UV5Kind
  106. * - BABYLON.VertexBuffer.UV6Kind
  107. * - BABYLON.VertexBuffer.ColorKind
  108. * - BABYLON.VertexBuffer.MatricesIndicesKind
  109. * - BABYLON.VertexBuffer.MatricesIndicesExtraKind
  110. * - BABYLON.VertexBuffer.MatricesWeightsKind
  111. * - BABYLON.VertexBuffer.MatricesWeightsExtraKind
  112. *
  113. * Returns the Mesh.
  114. */
  115. public updateVerticesData(kind: string, data: number[] | Float32Array, updateExtends?: boolean, makeItUnique?: boolean): Mesh {
  116. if (this.sourceMesh) {
  117. this.sourceMesh.updateVerticesData(kind, data, updateExtends, makeItUnique);
  118. }
  119. return this.sourceMesh;
  120. }
  121. /**
  122. * Sets the mesh indices.
  123. * Expects an array populated with integers or a typed array (Int32Array, Uint32Array, Uint16Array).
  124. * If the mesh has no geometry, a new Geometry object is created and set to the mesh.
  125. * This method creates a new index buffer each call.
  126. * Returns the Mesh.
  127. */
  128. public setIndices(indices: IndicesArray, totalVertices?: number): Mesh {
  129. if (this.sourceMesh) {
  130. this.sourceMesh.setIndices(indices, totalVertices);
  131. }
  132. return this.sourceMesh;
  133. }
  134. /**
  135. * Boolean : True if the mesh owns the requested kind of data.
  136. */
  137. public isVerticesDataPresent(kind: string): boolean {
  138. return this._sourceMesh.isVerticesDataPresent(kind);
  139. }
  140. /**
  141. * Returns an array of indices (IndicesArray).
  142. */
  143. public getIndices(): IndicesArray {
  144. return this._sourceMesh.getIndices();
  145. }
  146. public get _positions(): Vector3[] {
  147. return this._sourceMesh._positions;
  148. }
  149. /**
  150. * Sets a new updated BoundingInfo to the mesh.
  151. * Returns the mesh.
  152. */
  153. public refreshBoundingInfo(): InstancedMesh {
  154. var meshBB = this._sourceMesh.getBoundingInfo();
  155. this._boundingInfo = new BoundingInfo(meshBB.minimum.clone(), meshBB.maximum.clone());
  156. this._updateBoundingInfo();
  157. return this;
  158. }
  159. public _preActivate(): InstancedMesh {
  160. if (this._currentLOD) {
  161. this._currentLOD._preActivate();
  162. }
  163. return this;
  164. }
  165. public _activate(renderId: number): InstancedMesh {
  166. if (this._currentLOD) {
  167. this._currentLOD._registerInstanceForRenderId(this, renderId);
  168. }
  169. return this;
  170. }
  171. /**
  172. * Returns the current associated LOD AbstractMesh.
  173. */
  174. public getLOD(camera: Camera): AbstractMesh {
  175. this._currentLOD = <Mesh>this.sourceMesh.getLOD(this.getScene().activeCamera, this.getBoundingInfo().boundingSphere);
  176. if (this._currentLOD === this.sourceMesh) {
  177. return this;
  178. }
  179. return this._currentLOD;
  180. }
  181. public _syncSubMeshes(): InstancedMesh {
  182. this.releaseSubMeshes();
  183. if (this._sourceMesh.subMeshes) {
  184. for (var index = 0; index < this._sourceMesh.subMeshes.length; index++) {
  185. this._sourceMesh.subMeshes[index].clone(this, this._sourceMesh);
  186. }
  187. }
  188. return this;
  189. }
  190. public _generatePointsArray(): boolean {
  191. return this._sourceMesh._generatePointsArray();
  192. }
  193. /**
  194. * Creates a new InstancedMesh from the current mesh.
  195. * - name (string) : the cloned mesh name
  196. * - newParent (optional Node) : the optional Node to parent the clone to.
  197. * - doNotCloneChildren (optional boolean, default `false`) : if `true` the model children aren't cloned.
  198. *
  199. * Returns the clone.
  200. */
  201. public clone(name: string, newParent: Node, doNotCloneChildren?: boolean): InstancedMesh {
  202. var result = this._sourceMesh.createInstance(name);
  203. // Deep copy
  204. Tools.DeepCopy(this, result, ["name", "subMeshes", "uniqueId"], []);
  205. // Bounding info
  206. this.refreshBoundingInfo();
  207. // Parent
  208. if (newParent) {
  209. result.parent = newParent;
  210. }
  211. if (!doNotCloneChildren) {
  212. // Children
  213. for (var index = 0; index < this.getScene().meshes.length; index++) {
  214. var mesh = this.getScene().meshes[index];
  215. if (mesh.parent === this) {
  216. mesh.clone(mesh.name, result);
  217. }
  218. }
  219. }
  220. result.computeWorldMatrix(true);
  221. return result;
  222. }
  223. /**
  224. * Disposes the InstancedMesh.
  225. * Returns nothing.
  226. */
  227. public dispose(doNotRecurse?: boolean): void {
  228. // Remove from mesh
  229. var index = this._sourceMesh.instances.indexOf(this);
  230. this._sourceMesh.instances.splice(index, 1);
  231. super.dispose(doNotRecurse);
  232. }
  233. }
  234. }