123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- import { Matrix, TmpVectors } from "../Maths/math.vector.js";
- import { Logger } from "../Misc/logger.js";
- import { AbstractMesh } from "../Meshes/abstractMesh.js";
- import { Mesh } from "../Meshes/mesh.js";
- import { DeepCopier } from "../Misc/deepCopier.js";
- import { TransformNode } from "./transformNode.js";
- import { VertexBuffer } from "../Buffers/buffer.js";
- import { Tools } from "../Misc/tools.js";
- Mesh._instancedMeshFactory = (name, mesh) => {
- const instance = new InstancedMesh(name, mesh);
- if (mesh.instancedBuffers) {
- instance.instancedBuffers = {};
- for (const key in mesh.instancedBuffers) {
- instance.instancedBuffers[key] = mesh.instancedBuffers[key];
- }
- }
- return instance;
- };
- /**
- * Creates an instance based on a source mesh.
- */
- export class InstancedMesh extends AbstractMesh {
- /**
- * Creates a new InstancedMesh object from the mesh source.
- * @param name defines the name of the instance
- * @param source the mesh to create the instance from
- */
- constructor(name, source) {
- super(name, source.getScene());
- /** @internal */
- this._indexInSourceMeshInstanceArray = -1;
- /** @internal */
- this._distanceToCamera = 0;
- source.addInstance(this);
- this._sourceMesh = source;
- this._unIndexed = source._unIndexed;
- this.position.copyFrom(source.position);
- this.rotation.copyFrom(source.rotation);
- this.scaling.copyFrom(source.scaling);
- if (source.rotationQuaternion) {
- this.rotationQuaternion = source.rotationQuaternion.clone();
- }
- this.animations = source.animations.slice();
- for (const range of source.getAnimationRanges()) {
- if (range != null) {
- this.createAnimationRange(range.name, range.from, range.to);
- }
- }
- this.infiniteDistance = source.infiniteDistance;
- this.setPivotMatrix(source.getPivotMatrix());
- this.refreshBoundingInfo(true, true);
- this._syncSubMeshes();
- }
- /**
- * @returns the string "InstancedMesh".
- */
- getClassName() {
- return "InstancedMesh";
- }
- /** Gets the list of lights affecting that mesh */
- get lightSources() {
- return this._sourceMesh._lightSources;
- }
- _resyncLightSources() {
- // Do nothing as all the work will be done by source mesh
- }
- _resyncLightSource() {
- // Do nothing as all the work will be done by source mesh
- }
- _removeLightSource() {
- // Do nothing as all the work will be done by source mesh
- }
- // Methods
- /**
- * If the source mesh receives shadows
- */
- get receiveShadows() {
- return this._sourceMesh.receiveShadows;
- }
- set receiveShadows(_value) {
- if (this._sourceMesh?.receiveShadows !== _value) {
- Tools.Warn("Setting receiveShadows on an instanced mesh has no effect");
- }
- }
- /**
- * The material of the source mesh
- */
- get material() {
- return this._sourceMesh.material;
- }
- set material(_value) {
- if (this._sourceMesh?.material !== _value) {
- Tools.Warn("Setting material on an instanced mesh has no effect");
- }
- }
- /**
- * Visibility of the source mesh
- */
- get visibility() {
- return this._sourceMesh.visibility;
- }
- set visibility(_value) {
- if (this._sourceMesh?.visibility !== _value) {
- Tools.Warn("Setting visibility on an instanced mesh has no effect");
- }
- }
- /**
- * Skeleton of the source mesh
- */
- get skeleton() {
- return this._sourceMesh.skeleton;
- }
- set skeleton(_value) {
- if (this._sourceMesh?.skeleton !== _value) {
- Tools.Warn("Setting skeleton on an instanced mesh has no effect");
- }
- }
- /**
- * Rendering ground id of the source mesh
- */
- get renderingGroupId() {
- return this._sourceMesh.renderingGroupId;
- }
- set renderingGroupId(value) {
- if (!this._sourceMesh || value === this._sourceMesh.renderingGroupId) {
- return;
- }
- //no-op with warning
- Logger.Warn("Note - setting renderingGroupId of an instanced mesh has no effect on the scene");
- }
- /**
- * @returns the total number of vertices (integer).
- */
- getTotalVertices() {
- return this._sourceMesh ? this._sourceMesh.getTotalVertices() : 0;
- }
- /**
- * Returns a positive integer : the total number of indices in this mesh geometry.
- * @returns the number of indices or zero if the mesh has no geometry.
- */
- getTotalIndices() {
- return this._sourceMesh.getTotalIndices();
- }
- /**
- * The source mesh of the instance
- */
- get sourceMesh() {
- return this._sourceMesh;
- }
- /**
- * Creates a new InstancedMesh object from the mesh model.
- * @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/copies/instances
- * @param name defines the name of the new instance
- * @returns a new InstancedMesh
- */
- createInstance(name) {
- return this._sourceMesh.createInstance(name);
- }
- /**
- * Is this node ready to be used/rendered
- * @param completeCheck defines if a complete check (including materials and lights) has to be done (false by default)
- * @returns {boolean} is it ready
- */
- isReady(completeCheck = false) {
- return this._sourceMesh.isReady(completeCheck, true);
- }
- /**
- * Returns an array of integers or a typed array (Int32Array, Uint32Array, Uint16Array) populated with the mesh indices.
- * @param kind kind of verticies to retrieve (eg. positions, normals, uvs, etc.)
- * @param copyWhenShared If true (default false) and and if the mesh geometry is shared among some other meshes, the returned array is a copy of the internal one.
- * @param forceCopy defines a boolean forcing the copy of the buffer no matter what the value of copyWhenShared is
- * @returns a float array or a Float32Array of the requested kind of data : positions, normals, uvs, etc.
- */
- getVerticesData(kind, copyWhenShared, forceCopy) {
- return this._sourceMesh.getVerticesData(kind, copyWhenShared, forceCopy);
- }
- /**
- * Sets the vertex data of the mesh geometry for the requested `kind`.
- * If the mesh has no geometry, a new Geometry object is set to the mesh and then passed this vertex data.
- * The `data` are either a numeric array either a Float32Array.
- * The parameter `updatable` is passed as is to the underlying Geometry object constructor (if initially none) or updater.
- * 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).
- * Note that a new underlying VertexBuffer object is created each call.
- * If the `kind` is the `PositionKind`, the mesh BoundingInfo is renewed, so the bounding box and sphere, and the mesh World Matrix is recomputed.
- *
- * Possible `kind` values :
- * - VertexBuffer.PositionKind
- * - VertexBuffer.UVKind
- * - VertexBuffer.UV2Kind
- * - VertexBuffer.UV3Kind
- * - VertexBuffer.UV4Kind
- * - VertexBuffer.UV5Kind
- * - VertexBuffer.UV6Kind
- * - VertexBuffer.ColorKind
- * - VertexBuffer.MatricesIndicesKind
- * - VertexBuffer.MatricesIndicesExtraKind
- * - VertexBuffer.MatricesWeightsKind
- * - VertexBuffer.MatricesWeightsExtraKind
- *
- * Returns the Mesh.
- * @param kind defines vertex data kind
- * @param data defines the data source
- * @param updatable defines if the data must be flagged as updatable (false as default)
- * @param stride defines the vertex stride (optional)
- * @returns the current mesh
- */
- setVerticesData(kind, data, updatable, stride) {
- if (this.sourceMesh) {
- this.sourceMesh.setVerticesData(kind, data, updatable, stride);
- }
- return this.sourceMesh;
- }
- /**
- * Updates the existing vertex data of the mesh geometry for the requested `kind`.
- * If the mesh has no geometry, it is simply returned as it is.
- * The `data` are either a numeric array either a Float32Array.
- * No new underlying VertexBuffer object is created.
- * 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.
- * If the parameter `makeItUnique` is true, a new global geometry is created from this positions and is set to the mesh.
- *
- * Possible `kind` values :
- * - VertexBuffer.PositionKind
- * - VertexBuffer.UVKind
- * - VertexBuffer.UV2Kind
- * - VertexBuffer.UV3Kind
- * - VertexBuffer.UV4Kind
- * - VertexBuffer.UV5Kind
- * - VertexBuffer.UV6Kind
- * - VertexBuffer.ColorKind
- * - VertexBuffer.MatricesIndicesKind
- * - VertexBuffer.MatricesIndicesExtraKind
- * - VertexBuffer.MatricesWeightsKind
- * - VertexBuffer.MatricesWeightsExtraKind
- *
- * Returns the Mesh.
- * @param kind defines vertex data kind
- * @param data defines the data source
- * @param updateExtends defines if extends info of the mesh must be updated (can be null). This is mostly useful for "position" kind
- * @param makeItUnique defines it the updated vertex buffer must be flagged as unique (false by default)
- * @returns the source mesh
- */
- updateVerticesData(kind, data, updateExtends, makeItUnique) {
- if (this.sourceMesh) {
- this.sourceMesh.updateVerticesData(kind, data, updateExtends, makeItUnique);
- }
- return this.sourceMesh;
- }
- /**
- * Sets the mesh indices.
- * Expects an array populated with integers or a typed array (Int32Array, Uint32Array, Uint16Array).
- * If the mesh has no geometry, a new Geometry object is created and set to the mesh.
- * This method creates a new index buffer each call.
- * Returns the Mesh.
- * @param indices the source data
- * @param totalVertices defines the total number of vertices referenced by indices (could be null)
- * @returns source mesh
- */
- setIndices(indices, totalVertices = null) {
- if (this.sourceMesh) {
- this.sourceMesh.setIndices(indices, totalVertices);
- }
- return this.sourceMesh;
- }
- /**
- * Boolean : True if the mesh owns the requested kind of data.
- * @param kind defines which buffer to check (positions, indices, normals, etc). Possible `kind` values :
- * - VertexBuffer.PositionKind
- * - VertexBuffer.UVKind
- * - VertexBuffer.UV2Kind
- * - VertexBuffer.UV3Kind
- * - VertexBuffer.UV4Kind
- * - VertexBuffer.UV5Kind
- * - VertexBuffer.UV6Kind
- * - VertexBuffer.ColorKind
- * - VertexBuffer.MatricesIndicesKind
- * - VertexBuffer.MatricesIndicesExtraKind
- * - VertexBuffer.MatricesWeightsKind
- * - VertexBuffer.MatricesWeightsExtraKind
- * @returns true if data kind is present
- */
- isVerticesDataPresent(kind) {
- return this._sourceMesh.isVerticesDataPresent(kind);
- }
- /**
- * @returns an array of indices (IndicesArray).
- */
- getIndices() {
- return this._sourceMesh.getIndices();
- }
- get _positions() {
- return this._sourceMesh._positions;
- }
- /**
- * This method recomputes and sets a new BoundingInfo to the mesh unless it is locked.
- * This means the mesh underlying bounding box and sphere are recomputed.
- * @param applySkeleton defines whether to apply the skeleton before computing the bounding info
- * @param applyMorph defines whether to apply the morph target before computing the bounding info
- * @returns the current mesh
- */
- refreshBoundingInfo(applySkeleton = false, applyMorph = false) {
- if (this.hasBoundingInfo && this.getBoundingInfo().isLocked) {
- return this;
- }
- const bias = this._sourceMesh.geometry ? this._sourceMesh.geometry.boundingBias : null;
- this._refreshBoundingInfo(this._sourceMesh._getPositionData(applySkeleton, applyMorph), bias);
- return this;
- }
- /** @internal */
- _preActivate() {
- if (this._currentLOD) {
- this._currentLOD._preActivate();
- }
- return this;
- }
- /**
- * @internal
- */
- _activate(renderId, intermediateRendering) {
- super._activate(renderId, intermediateRendering);
- if (!this._sourceMesh.subMeshes) {
- Logger.Warn("Instances should only be created for meshes with geometry.");
- }
- if (this._currentLOD) {
- const differentSign = this._currentLOD._getWorldMatrixDeterminant() >= 0 !== this._getWorldMatrixDeterminant() >= 0;
- if (differentSign) {
- this._internalAbstractMeshDataInfo._actAsRegularMesh = true;
- return true;
- }
- this._internalAbstractMeshDataInfo._actAsRegularMesh = false;
- this._currentLOD._registerInstanceForRenderId(this, renderId);
- if (intermediateRendering) {
- if (!this._currentLOD._internalAbstractMeshDataInfo._isActiveIntermediate) {
- this._currentLOD._internalAbstractMeshDataInfo._onlyForInstancesIntermediate = true;
- return true;
- }
- }
- else {
- if (!this._currentLOD._internalAbstractMeshDataInfo._isActive) {
- this._currentLOD._internalAbstractMeshDataInfo._onlyForInstances = true;
- return true;
- }
- }
- }
- return false;
- }
- /** @internal */
- _postActivate() {
- if (this._sourceMesh.edgesShareWithInstances && this._sourceMesh._edgesRenderer && this._sourceMesh._edgesRenderer.isEnabled && this._sourceMesh._renderingGroup) {
- // we are using the edge renderer of the source mesh
- this._sourceMesh._renderingGroup._edgesRenderers.pushNoDuplicate(this._sourceMesh._edgesRenderer);
- this._sourceMesh._edgesRenderer.customInstances.push(this.getWorldMatrix());
- }
- else if (this._edgesRenderer && this._edgesRenderer.isEnabled && this._sourceMesh._renderingGroup) {
- // we are using the edge renderer defined for this instance
- this._sourceMesh._renderingGroup._edgesRenderers.push(this._edgesRenderer);
- }
- }
- getWorldMatrix() {
- if (this._currentLOD && this._currentLOD.billboardMode !== TransformNode.BILLBOARDMODE_NONE && this._currentLOD._masterMesh !== this) {
- if (!this._billboardWorldMatrix) {
- this._billboardWorldMatrix = new Matrix();
- }
- const tempMaster = this._currentLOD._masterMesh;
- this._currentLOD._masterMesh = this;
- TmpVectors.Vector3[7].copyFrom(this._currentLOD.position);
- this._currentLOD.position.set(0, 0, 0);
- this._billboardWorldMatrix.copyFrom(this._currentLOD.computeWorldMatrix(true));
- this._currentLOD.position.copyFrom(TmpVectors.Vector3[7]);
- this._currentLOD._masterMesh = tempMaster;
- return this._billboardWorldMatrix;
- }
- return super.getWorldMatrix();
- }
- get isAnInstance() {
- return true;
- }
- /**
- * Returns the current associated LOD AbstractMesh.
- * @param camera defines the camera to use to pick the LOD level
- * @returns a Mesh or `null` if no LOD is associated with the AbstractMesh
- */
- getLOD(camera) {
- if (!camera) {
- return this;
- }
- const sourceMeshLODLevels = this.sourceMesh.getLODLevels();
- if (!sourceMeshLODLevels || sourceMeshLODLevels.length === 0) {
- this._currentLOD = this.sourceMesh;
- }
- else {
- const boundingInfo = this.getBoundingInfo();
- this._currentLOD = this.sourceMesh.getLOD(camera, boundingInfo.boundingSphere);
- }
- return this._currentLOD;
- }
- /**
- * @internal
- */
- _preActivateForIntermediateRendering(renderId) {
- return this.sourceMesh._preActivateForIntermediateRendering(renderId);
- }
- /** @internal */
- _syncSubMeshes() {
- this.releaseSubMeshes();
- if (this._sourceMesh.subMeshes) {
- for (let index = 0; index < this._sourceMesh.subMeshes.length; index++) {
- this._sourceMesh.subMeshes[index].clone(this, this._sourceMesh);
- }
- }
- return this;
- }
- /** @internal */
- _generatePointsArray() {
- return this._sourceMesh._generatePointsArray();
- }
- /** @internal */
- _updateBoundingInfo() {
- if (this.hasBoundingInfo) {
- this.getBoundingInfo().update(this.worldMatrixFromCache);
- }
- else {
- this.buildBoundingInfo(this.absolutePosition, this.absolutePosition, this.worldMatrixFromCache);
- }
- this._updateSubMeshesBoundingInfo(this.worldMatrixFromCache);
- return this;
- }
- /**
- * Creates a new InstancedMesh from the current mesh.
- *
- * Returns the clone.
- * @param name the cloned mesh name
- * @param newParent the optional Node to parent the clone to.
- * @param doNotCloneChildren if `true` the model children aren't cloned.
- * @param newSourceMesh if set this mesh will be used as the source mesh instead of ths instance's one
- * @returns the clone
- */
- clone(name, newParent = null, doNotCloneChildren, newSourceMesh) {
- const result = (newSourceMesh || this._sourceMesh).createInstance(name);
- // Deep copy
- DeepCopier.DeepCopy(this, result, [
- "name",
- "subMeshes",
- "uniqueId",
- "parent",
- "lightSources",
- "receiveShadows",
- "material",
- "visibility",
- "skeleton",
- "sourceMesh",
- "isAnInstance",
- "facetNb",
- "isFacetDataEnabled",
- "isBlocked",
- "useBones",
- "hasInstances",
- "collider",
- "edgesRenderer",
- "forward",
- "up",
- "right",
- "absolutePosition",
- "absoluteScaling",
- "absoluteRotationQuaternion",
- "isWorldMatrixFrozen",
- "nonUniformScaling",
- "behaviors",
- "worldMatrixFromCache",
- "hasThinInstances",
- "hasBoundingInfo",
- ], []);
- // Bounding info
- this.refreshBoundingInfo();
- // Parent
- if (newParent) {
- result.parent = newParent;
- }
- if (!doNotCloneChildren) {
- // Children
- for (let index = 0; index < this.getScene().meshes.length; index++) {
- const mesh = this.getScene().meshes[index];
- if (mesh.parent === this) {
- mesh.clone(mesh.name, result);
- }
- }
- }
- result.computeWorldMatrix(true);
- this.onClonedObservable.notifyObservers(result);
- return result;
- }
- /**
- * Disposes the InstancedMesh.
- * Returns nothing.
- * @param doNotRecurse Set to true to not recurse into each children (recurse into each children by default)
- * @param disposeMaterialAndTextures Set to true to also dispose referenced materials and textures (false by default)
- */
- dispose(doNotRecurse, disposeMaterialAndTextures = false) {
- // Remove from mesh
- this._sourceMesh.removeInstance(this);
- super.dispose(doNotRecurse, disposeMaterialAndTextures);
- }
- /**
- * @internal
- */
- _serializeAsParent(serializationObject) {
- super._serializeAsParent(serializationObject);
- serializationObject.parentId = this._sourceMesh.uniqueId;
- serializationObject.parentInstanceIndex = this._indexInSourceMeshInstanceArray;
- }
- /**
- * Instantiate (when possible) or clone that node with its hierarchy
- * @param newParent defines the new parent to use for the instance (or clone)
- * @param options defines options to configure how copy is done
- * @param options.doNotInstantiate defines if the model must be instantiated or just cloned
- * @param options.newSourcedMesh newSourcedMesh the new source mesh for the instance (or clone)
- * @param onNewNodeCreated defines an option callback to call when a clone or an instance is created
- * @returns an instance (or a clone) of the current node with its hierarchy
- */
- instantiateHierarchy(newParent = null, options, onNewNodeCreated) {
- const clone = this.clone("Clone of " + (this.name || this.id), newParent || this.parent, true, options && options.newSourcedMesh);
- if (clone) {
- if (onNewNodeCreated) {
- onNewNodeCreated(this, clone);
- }
- }
- for (const child of this.getChildTransformNodes(true)) {
- child.instantiateHierarchy(clone, options, onNewNodeCreated);
- }
- return clone;
- }
- }
- Mesh.prototype.registerInstancedBuffer = function (kind, stride) {
- // Remove existing one
- this._userInstancedBuffersStorage?.vertexBuffers[kind]?.dispose();
- // Creates the instancedBuffer field if not present
- if (!this.instancedBuffers) {
- this.instancedBuffers = {};
- for (const instance of this.instances) {
- instance.instancedBuffers = {};
- }
- }
- if (!this._userInstancedBuffersStorage) {
- this._userInstancedBuffersStorage = {
- data: {},
- vertexBuffers: {},
- strides: {},
- sizes: {},
- vertexArrayObjects: this.getEngine().getCaps().vertexArrayObject ? {} : undefined,
- };
- }
- // Creates an empty property for this kind
- this.instancedBuffers[kind] = null;
- this._userInstancedBuffersStorage.strides[kind] = stride;
- this._userInstancedBuffersStorage.sizes[kind] = stride * 32; // Initial size
- this._userInstancedBuffersStorage.data[kind] = new Float32Array(this._userInstancedBuffersStorage.sizes[kind]);
- this._userInstancedBuffersStorage.vertexBuffers[kind] = new VertexBuffer(this.getEngine(), this._userInstancedBuffersStorage.data[kind], kind, true, false, stride, true);
- for (const instance of this.instances) {
- instance.instancedBuffers[kind] = null;
- }
- this._invalidateInstanceVertexArrayObject();
- this._markSubMeshesAsAttributesDirty();
- };
- Mesh.prototype._processInstancedBuffers = function (visibleInstances, renderSelf) {
- const instanceCount = visibleInstances ? visibleInstances.length : 0;
- for (const kind in this.instancedBuffers) {
- let size = this._userInstancedBuffersStorage.sizes[kind];
- const stride = this._userInstancedBuffersStorage.strides[kind];
- // Resize if required
- const expectedSize = (instanceCount + 1) * stride;
- while (size < expectedSize) {
- size *= 2;
- }
- if (this._userInstancedBuffersStorage.data[kind].length != size) {
- this._userInstancedBuffersStorage.data[kind] = new Float32Array(size);
- this._userInstancedBuffersStorage.sizes[kind] = size;
- if (this._userInstancedBuffersStorage.vertexBuffers[kind]) {
- this._userInstancedBuffersStorage.vertexBuffers[kind].dispose();
- this._userInstancedBuffersStorage.vertexBuffers[kind] = null;
- }
- }
- const data = this._userInstancedBuffersStorage.data[kind];
- // Update data buffer
- let offset = 0;
- if (renderSelf) {
- const value = this.instancedBuffers[kind];
- if (value.toArray) {
- value.toArray(data, offset);
- }
- else if (value.copyToArray) {
- value.copyToArray(data, offset);
- }
- else {
- data[offset] = value;
- }
- offset += stride;
- }
- for (let instanceIndex = 0; instanceIndex < instanceCount; instanceIndex++) {
- const instance = visibleInstances[instanceIndex];
- const value = instance.instancedBuffers[kind];
- if (value.toArray) {
- value.toArray(data, offset);
- }
- else if (value.copyToArray) {
- value.copyToArray(data, offset);
- }
- else {
- data[offset] = value;
- }
- offset += stride;
- }
- // Update vertex buffer
- if (!this._userInstancedBuffersStorage.vertexBuffers[kind]) {
- this._userInstancedBuffersStorage.vertexBuffers[kind] = new VertexBuffer(this.getEngine(), this._userInstancedBuffersStorage.data[kind], kind, true, false, stride, true);
- this._invalidateInstanceVertexArrayObject();
- }
- else {
- this._userInstancedBuffersStorage.vertexBuffers[kind].updateDirectly(data, 0);
- }
- }
- };
- Mesh.prototype._invalidateInstanceVertexArrayObject = function () {
- if (!this._userInstancedBuffersStorage || this._userInstancedBuffersStorage.vertexArrayObjects === undefined) {
- return;
- }
- for (const kind in this._userInstancedBuffersStorage.vertexArrayObjects) {
- this.getEngine().releaseVertexArrayObject(this._userInstancedBuffersStorage.vertexArrayObjects[kind]);
- }
- this._userInstancedBuffersStorage.vertexArrayObjects = {};
- };
- Mesh.prototype._disposeInstanceSpecificData = function () {
- if (this._instanceDataStorage.instancesBuffer) {
- this._instanceDataStorage.instancesBuffer.dispose();
- this._instanceDataStorage.instancesBuffer = null;
- }
- while (this.instances.length) {
- this.instances[0].dispose();
- }
- for (const kind in this.instancedBuffers) {
- if (this._userInstancedBuffersStorage.vertexBuffers[kind]) {
- this._userInstancedBuffersStorage.vertexBuffers[kind].dispose();
- }
- }
- this._invalidateInstanceVertexArrayObject();
- this.instancedBuffers = {};
- };
- //# sourceMappingURL=instancedMesh.js.map
|