module BABYLON { /** * Creates an instance based on a source mesh. */ export class InstancedMesh extends AbstractMesh { private _sourceMesh: Mesh; private _currentLOD: Mesh; constructor(name: string, source: Mesh) { super(name, source.getScene()); source.instances.push(this); this._sourceMesh = source; this.position.copyFrom(source.position); this.rotation.copyFrom(source.rotation); this.scaling.copyFrom(source.scaling); if (source.rotationQuaternion) { this.rotationQuaternion = source.rotationQuaternion.clone(); } this.infiniteDistance = source.infiniteDistance; this.setPivotMatrix(source.getPivotMatrix()); this.refreshBoundingInfo(); this._syncSubMeshes(); } // Methods public get receiveShadows(): boolean { return this._sourceMesh.receiveShadows; } public get material(): Material { return this._sourceMesh.material; } public get visibility(): number { return this._sourceMesh.visibility; } public get skeleton(): Skeleton { return this._sourceMesh.skeleton; } public getTotalVertices(): number { return this._sourceMesh.getTotalVertices(); } public get sourceMesh(): Mesh { return this._sourceMesh; } public getVerticesData(kind: string): number[] { return this._sourceMesh.getVerticesData(kind); } public isVerticesDataPresent(kind: string): boolean { return this._sourceMesh.isVerticesDataPresent(kind); } public getIndices(): number[] { return this._sourceMesh.getIndices(); } public get _positions(): Vector3[] { return this._sourceMesh._positions; } public refreshBoundingInfo(): void { var data = this._sourceMesh.getVerticesData(VertexBuffer.PositionKind); if (data) { var extend = Tools.ExtractMinAndMax(data, 0, this._sourceMesh.getTotalVertices()); this._boundingInfo = new BoundingInfo(extend.minimum, extend.maximum); } this._updateBoundingInfo(); } public _preActivate(): void { if (this._currentLOD) { this._currentLOD._preActivate(); } } public _activate(renderId: number): void { if (this._currentLOD) { this._currentLOD._registerInstanceForRenderId(this, renderId); } } public getLOD(camera: Camera): AbstractMesh { this._currentLOD = this.sourceMesh.getLOD(this.getScene().activeCamera, this.getBoundingInfo().boundingSphere); if (this._currentLOD === this.sourceMesh) { return this; } return this._currentLOD; } public _syncSubMeshes(): void { this.releaseSubMeshes(); if (this._sourceMesh.subMeshes) { for (var index = 0; index < this._sourceMesh.subMeshes.length; index++) { this._sourceMesh.subMeshes[index].clone(this, this._sourceMesh); } } } public _generatePointsArray(): boolean { return this._sourceMesh._generatePointsArray(); } // Clone public clone(name: string, newParent: Node, doNotCloneChildren?: boolean): InstancedMesh { var result = this._sourceMesh.createInstance(name); // Deep copy Tools.DeepCopy(this, result, ["name"], []); // Bounding info this.refreshBoundingInfo(); // Parent if (newParent) { result.parent = newParent; } if (!doNotCloneChildren) { // Children for (var index = 0; index < this.getScene().meshes.length; index++) { var mesh = this.getScene().meshes[index]; if (mesh.parent === this) { mesh.clone(mesh.name, result); } } } result.computeWorldMatrix(true); return result; } // Dispoe public dispose(doNotRecurse?: boolean): void { // Remove from mesh var index = this._sourceMesh.instances.indexOf(this); this._sourceMesh.instances.splice(index, 1); super.dispose(doNotRecurse); } } }