Browse Source

Avoid GC when calling intersects

geometry._positions resets every frame (when bounding box updates) and recreates when mesh.intesects is called.
With large meshes this can be very costly, as vectors are constantly created and GCed (on each frame).
This keeps a cache of the positions, while keeping the current state as it is. _positions is still null or full, _positionsCache is updated when needed, reusing the vectors if possible
Raanan Weber 4 năm trước cách đây
mục cha
commit
7c12e3cd8f
1 tập tin đã thay đổi với 78 bổ sung70 xóa
  1. 78 70
      src/Meshes/geometry.ts

+ 78 - 70
src/Meshes/geometry.ts

@@ -1,7 +1,7 @@
 import { Nullable, FloatArray, DataArray, IndicesArray } from "../types";
 import { Nullable, FloatArray, DataArray, IndicesArray } from "../types";
 import { Scene } from "../scene";
 import { Scene } from "../scene";
 import { Vector3, Vector2 } from "../Maths/math.vector";
 import { Vector3, Vector2 } from "../Maths/math.vector";
-import { Color4 } from '../Maths/math.color';
+import { Color4 } from "../Maths/math.color";
 import { Engine } from "../Engines/engine";
 import { Engine } from "../Engines/engine";
 import { IGetSetVerticesData, VertexData } from "../Meshes/mesh.vertexData";
 import { IGetSetVerticesData, VertexData } from "../Meshes/mesh.vertexData";
 import { VertexBuffer } from "../Meshes/buffer";
 import { VertexBuffer } from "../Meshes/buffer";
@@ -13,8 +13,8 @@ import { BoundingInfo } from "../Culling/boundingInfo";
 import { Constants } from "../Engines/constants";
 import { Constants } from "../Engines/constants";
 import { Tools } from "../Misc/tools";
 import { Tools } from "../Misc/tools";
 import { Tags } from "../Misc/tags";
 import { Tags } from "../Misc/tags";
-import { DataBuffer } from './dataBuffer';
-import { extractMinAndMax } from '../Maths/math.functions';
+import { DataBuffer } from "./dataBuffer";
+import { extractMinAndMax } from "../Maths/math.functions";
 
 
 declare type Mesh = import("../Meshes/mesh").Mesh;
 declare type Mesh = import("../Meshes/mesh").Mesh;
 
 
@@ -52,9 +52,9 @@ export class Geometry implements IGetSetVerticesData {
     /** @hidden */
     /** @hidden */
     public _indices: IndicesArray;
     public _indices: IndicesArray;
     /** @hidden */
     /** @hidden */
-    public _vertexBuffers: { [key: string]: VertexBuffer; };
+    public _vertexBuffers: { [key: string]: VertexBuffer };
     private _isDisposed = false;
     private _isDisposed = false;
-    private _extend: { minimum: Vector3, maximum: Vector3 };
+    private _extend: { minimum: Vector3; maximum: Vector3 };
     private _boundingBias: Vector2;
     private _boundingBias: Vector2;
     /** @hidden */
     /** @hidden */
     public _delayInfo: Array<string>;
     public _delayInfo: Array<string>;
@@ -66,12 +66,13 @@ export class Geometry implements IGetSetVerticesData {
     public _delayLoadingFunction: Nullable<(any: any, geometry: Geometry) => void>;
     public _delayLoadingFunction: Nullable<(any: any, geometry: Geometry) => void>;
     /** @hidden */
     /** @hidden */
     public _softwareSkinningFrameId: number;
     public _softwareSkinningFrameId: number;
-    private _vertexArrayObjects: { [key: string]: WebGLVertexArrayObject; };
+    private _vertexArrayObjects: { [key: string]: WebGLVertexArrayObject };
     private _updatable: boolean;
     private _updatable: boolean;
 
 
     // Cache
     // Cache
     /** @hidden */
     /** @hidden */
     public _positions: Nullable<Vector3[]>;
     public _positions: Nullable<Vector3[]>;
+    private _positionsCache: Vector3[] = [];
 
 
     /**
     /**
      *  Gets or sets the Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y
      *  Gets or sets the Bias Vector to apply on the bounding elements (box/sphere), the max extend is computed as v += v * bias.x + bias.y, the min is computed as v -= v * bias.x + bias.y
@@ -86,8 +87,7 @@ export class Geometry implements IGetSetVerticesData {
     public set boundingBias(value: Vector2) {
     public set boundingBias(value: Vector2) {
         if (this._boundingBias) {
         if (this._boundingBias) {
             this._boundingBias.copyFrom(value);
             this._boundingBias.copyFrom(value);
-        }
-        else {
+        } else {
             this._boundingBias = value.clone();
             this._boundingBias = value.clone();
         }
         }
 
 
@@ -140,8 +140,7 @@ export class Geometry implements IGetSetVerticesData {
         // vertexData
         // vertexData
         if (vertexData) {
         if (vertexData) {
             this.setAllVerticesData(vertexData, updatable);
             this.setAllVerticesData(vertexData, updatable);
-        }
-        else {
+        } else {
             this._totalVertices = 0;
             this._totalVertices = 0;
             this._indices = [];
             this._indices = [];
         }
         }
@@ -160,7 +159,7 @@ export class Geometry implements IGetSetVerticesData {
     /**
     /**
      * Gets the current extend of the geometry
      * Gets the current extend of the geometry
      */
      */
-    public get extend(): { minimum: Vector3, maximum: Vector3 } {
+    public get extend(): { minimum: Vector3; maximum: Vector3 } {
         return this._extend;
         return this._extend;
     }
     }
 
 
@@ -351,8 +350,7 @@ export class Geometry implements IGetSetVerticesData {
             for (const mesh of meshes) {
             for (const mesh of meshes) {
                 if (mesh._boundingInfo) {
                 if (mesh._boundingInfo) {
                     mesh._boundingInfo.reConstruct(this._extend.minimum, this._extend.maximum);
                     mesh._boundingInfo.reConstruct(this._extend.minimum, this._extend.maximum);
-                }
-                else {
+                } else {
                     mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
                     mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
                 }
                 }
 
 
@@ -431,15 +429,13 @@ export class Geometry implements IGetSetVerticesData {
             return copy;
             return copy;
         }
         }
 
 
-        if (!((data instanceof Array) || (data instanceof Float32Array)) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
+        if (!(data instanceof Array || data instanceof Float32Array) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
             if (data instanceof Array) {
             if (data instanceof Array) {
                 const offset = vertexBuffer.byteOffset / 4;
                 const offset = vertexBuffer.byteOffset / 4;
                 return Tools.Slice(data, offset, offset + count);
                 return Tools.Slice(data, offset, offset + count);
-            }
-            else if (data instanceof ArrayBuffer) {
+            } else if (data instanceof ArrayBuffer) {
                 return new Float32Array(data, vertexBuffer.byteOffset, count);
                 return new Float32Array(data, vertexBuffer.byteOffset, count);
-            }
-            else {
+            } else {
                 const offset = data.byteOffset + vertexBuffer.byteOffset;
                 const offset = data.byteOffset + vertexBuffer.byteOffset;
                 if (forceCopy || (copyWhenShared && this._meshes.length !== 1)) {
                 if (forceCopy || (copyWhenShared && this._meshes.length !== 1)) {
                     let result = new Float32Array(count);
                     let result = new Float32Array(count);
@@ -491,7 +487,7 @@ export class Geometry implements IGetSetVerticesData {
      * Returns all vertex buffers
      * Returns all vertex buffers
      * @return an object holding all vertex buffers indexed by kind
      * @return an object holding all vertex buffers indexed by kind
      */
      */
-    public getVertexBuffers(): Nullable<{ [key: string]: VertexBuffer; }> {
+    public getVertexBuffers(): Nullable<{ [key: string]: VertexBuffer }> {
         if (!this.isReady()) {
         if (!this.isReady()) {
             return null;
             return null;
         }
         }
@@ -580,7 +576,8 @@ export class Geometry implements IGetSetVerticesData {
             this._indexBuffer = this._engine.createIndexBuffer(this._indices, updatable);
             this._indexBuffer = this._engine.createIndexBuffer(this._indices, updatable);
         }
         }
 
 
-        if (totalVertices != undefined) { // including null and undefined
+        if (totalVertices != undefined) {
+            // including null and undefined
             this._totalVertices = totalVertices;
             this._totalVertices = totalVertices;
         }
         }
 
 
@@ -695,8 +692,7 @@ export class Geometry implements IGetSetVerticesData {
 
 
         if (this.isReady()) {
         if (this.isReady()) {
             this._applyToMesh(mesh);
             this._applyToMesh(mesh);
-        }
-        else {
+        } else {
             mesh._boundingInfo = this._boundingInfo;
             mesh._boundingInfo = this._boundingInfo;
         }
         }
     }
     }
@@ -705,7 +701,7 @@ export class Geometry implements IGetSetVerticesData {
         if (this.useBoundingInfoFromGeometry && this._boundingInfo) {
         if (this.useBoundingInfoFromGeometry && this._boundingInfo) {
             this._extend = {
             this._extend = {
                 minimum: this._boundingInfo.minimum.clone(),
                 minimum: this._boundingInfo.minimum.clone(),
-                maximum: this._boundingInfo.maximum.clone()
+                maximum: this._boundingInfo.maximum.clone(),
             };
             };
         } else {
         } else {
             if (!data) {
             if (!data) {
@@ -795,35 +791,39 @@ export class Geometry implements IGetSetVerticesData {
         }
         }
 
 
         scene._addPendingData(this);
         scene._addPendingData(this);
-        scene._loadFile(this.delayLoadingFile, (data) => {
-            if (!this._delayLoadingFunction) {
-                return;
-            }
+        scene._loadFile(
+            this.delayLoadingFile,
+            (data) => {
+                if (!this._delayLoadingFunction) {
+                    return;
+                }
 
 
-            this._delayLoadingFunction(JSON.parse(data as string), this);
+                this._delayLoadingFunction(JSON.parse(data as string), this);
 
 
-            this.delayLoadState = Constants.DELAYLOADSTATE_LOADED;
-            this._delayInfo = [];
+                this.delayLoadState = Constants.DELAYLOADSTATE_LOADED;
+                this._delayInfo = [];
 
 
-            scene._removePendingData(this);
+                scene._removePendingData(this);
 
 
-            var meshes = this._meshes;
-            var numOfMeshes = meshes.length;
-            for (var index = 0; index < numOfMeshes; index++) {
-                this._applyToMesh(meshes[index]);
-            }
+                var meshes = this._meshes;
+                var numOfMeshes = meshes.length;
+                for (var index = 0; index < numOfMeshes; index++) {
+                    this._applyToMesh(meshes[index]);
+                }
 
 
-            if (onLoaded) {
-                onLoaded();
-            }
-        }, undefined, true);
+                if (onLoaded) {
+                    onLoaded();
+                }
+            },
+            undefined,
+            true
+        );
     }
     }
 
 
     /**
     /**
      * Invert the geometry to move from a right handed system to a left handed one.
      * Invert the geometry to move from a right handed system to a left handed one.
      */
      */
     public toLeftHanded(): void {
     public toLeftHanded(): void {
-
         // Flip faces
         // Flip faces
         let tIndices = this.getIndices(false);
         let tIndices = this.getIndices(false);
         if (tIndices != null && tIndices.length > 0) {
         if (tIndices != null && tIndices.length > 0) {
@@ -872,12 +872,21 @@ export class Geometry implements IGetSetVerticesData {
             return false;
             return false;
         }
         }
 
 
-        this._positions = [];
+        for (let index = 0, arrayIdx = 0; index < data.length; index += 3, ++arrayIdx) {
+            if (this._positionsCache[arrayIdx]) {
+                this._positionsCache[arrayIdx].set(data[0 + index], data[1 + index], data[2 + index]);
+            } else {
+                this._positionsCache[arrayIdx] = Vector3.FromArray(data, index);
+            }
+        }
 
 
-        for (var index = 0; index < data.length; index += 3) {
-            this._positions.push(Vector3.FromArray(data, index));
+        // just in case the number of positions was reduced, splice the array
+        if (this._positionsCache.length > data.length / 3) {
+            this._positionsCache.splice(data.length / 3);
         }
         }
 
 
+        this._positions = this._positionsCache;
+
         return true;
         return true;
     }
     }
 
 
@@ -1156,7 +1165,6 @@ export class Geometry implements IGetSetVerticesData {
                 geometry.applyToMesh(mesh);
                 geometry.applyToMesh(mesh);
             }
             }
         } else if (parsedGeometry instanceof ArrayBuffer) {
         } else if (parsedGeometry instanceof ArrayBuffer) {
-
             var binaryInfo = mesh._binaryInfo;
             var binaryInfo = mesh._binaryInfo;
 
 
             if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
             if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
@@ -1214,10 +1222,10 @@ export class Geometry implements IGetSetVerticesData {
                 var floatIndices = [];
                 var floatIndices = [];
                 for (var i = 0; i < matricesIndicesData.length; i++) {
                 for (var i = 0; i < matricesIndicesData.length; i++) {
                     var index = matricesIndicesData[i];
                     var index = matricesIndicesData[i];
-                    floatIndices.push(index & 0x000000FF);
-                    floatIndices.push((index & 0x0000FF00) >> 8);
-                    floatIndices.push((index & 0x00FF0000) >> 16);
-                    floatIndices.push((index >> 24) & 0xFF); // & 0xFF to convert to v + 256 if v < 0
+                    floatIndices.push(index & 0x000000ff);
+                    floatIndices.push((index & 0x0000ff00) >> 8);
+                    floatIndices.push((index & 0x00ff0000) >> 16);
+                    floatIndices.push((index >> 24) & 0xff); // & 0xFF to convert to v + 256 if v < 0
                 }
                 }
                 mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, false);
                 mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, false);
             }
             }
@@ -1227,10 +1235,10 @@ export class Geometry implements IGetSetVerticesData {
                 var floatIndices = [];
                 var floatIndices = [];
                 for (var i = 0; i < matricesIndicesData.length; i++) {
                 for (var i = 0; i < matricesIndicesData.length; i++) {
                     var index = matricesIndicesData[i];
                     var index = matricesIndicesData[i];
-                    floatIndices.push(index & 0x000000FF);
-                    floatIndices.push((index & 0x0000FF00) >> 8);
-                    floatIndices.push((index & 0x00FF0000) >> 16);
-                    floatIndices.push((index >> 24) & 0xFF); // & 0xFF to convert to v + 256 if v < 0
+                    floatIndices.push(index & 0x000000ff);
+                    floatIndices.push((index & 0x0000ff00) >> 8);
+                    floatIndices.push((index & 0x00ff0000) >> 16);
+                    floatIndices.push((index >> 24) & 0xff); // & 0xFF to convert to v + 256 if v < 0
                 }
                 }
                 mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, false);
                 mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, false);
             }
             }
@@ -1250,11 +1258,11 @@ export class Geometry implements IGetSetVerticesData {
 
 
                 mesh.subMeshes = [];
                 mesh.subMeshes = [];
                 for (var i = 0; i < binaryInfo.subMeshesAttrDesc.count; i++) {
                 for (var i = 0; i < binaryInfo.subMeshesAttrDesc.count; i++) {
-                    var materialIndex = subMeshesData[(i * 5) + 0];
-                    var verticesStart = subMeshesData[(i * 5) + 1];
-                    var verticesCount = subMeshesData[(i * 5) + 2];
-                    var indexStart = subMeshesData[(i * 5) + 3];
-                    var indexCount = subMeshesData[(i * 5) + 4];
+                    var materialIndex = subMeshesData[i * 5 + 0];
+                    var verticesStart = subMeshesData[i * 5 + 1];
+                    var verticesCount = subMeshesData[i * 5 + 2];
+                    var indexStart = subMeshesData[i * 5 + 3];
+                    var indexCount = subMeshesData[i * 5 + 4];
 
 
                     SubMesh.AddToMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, <AbstractMesh>mesh);
                     SubMesh.AddToMesh(materialIndex, verticesStart, verticesCount, indexStart, indexCount, <AbstractMesh>mesh);
                 }
                 }
@@ -1303,10 +1311,10 @@ export class Geometry implements IGetSetVerticesData {
                     for (var i = 0; i < parsedGeometry.matricesIndices.length; i++) {
                     for (var i = 0; i < parsedGeometry.matricesIndices.length; i++) {
                         var matricesIndex = parsedGeometry.matricesIndices[i];
                         var matricesIndex = parsedGeometry.matricesIndices[i];
 
 
-                        floatIndices.push(matricesIndex & 0x000000FF);
-                        floatIndices.push((matricesIndex & 0x0000FF00) >> 8);
-                        floatIndices.push((matricesIndex & 0x00FF0000) >> 16);
-                        floatIndices.push((matricesIndex >> 24) & 0xFF); // & 0xFF to convert to v + 256 if v < 0
+                        floatIndices.push(matricesIndex & 0x000000ff);
+                        floatIndices.push((matricesIndex & 0x0000ff00) >> 8);
+                        floatIndices.push((matricesIndex & 0x00ff0000) >> 16);
+                        floatIndices.push((matricesIndex >> 24) & 0xff); // & 0xFF to convert to v + 256 if v < 0
                     }
                     }
 
 
                     mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, parsedGeometry.matricesIndices._updatable);
                     mesh.setVerticesData(VertexBuffer.MatricesIndicesKind, floatIndices, parsedGeometry.matricesIndices._updatable);
@@ -1323,10 +1331,10 @@ export class Geometry implements IGetSetVerticesData {
                     for (var i = 0; i < parsedGeometry.matricesIndicesExtra.length; i++) {
                     for (var i = 0; i < parsedGeometry.matricesIndicesExtra.length; i++) {
                         var matricesIndex = parsedGeometry.matricesIndicesExtra[i];
                         var matricesIndex = parsedGeometry.matricesIndicesExtra[i];
 
 
-                        floatIndices.push(matricesIndex & 0x000000FF);
-                        floatIndices.push((matricesIndex & 0x0000FF00) >> 8);
-                        floatIndices.push((matricesIndex & 0x00FF0000) >> 16);
-                        floatIndices.push((matricesIndex >> 24) & 0xFF); // & 0xFF to convert to v + 256 if v < 0
+                        floatIndices.push(matricesIndex & 0x000000ff);
+                        floatIndices.push((matricesIndex & 0x0000ff00) >> 8);
+                        floatIndices.push((matricesIndex & 0x00ff0000) >> 16);
+                        floatIndices.push((matricesIndex >> 24) & 0xff); // & 0xFF to convert to v + 256 if v < 0
                     }
                     }
 
 
                     mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, parsedGeometry.matricesIndicesExtra._updatable);
                     mesh.setVerticesData(VertexBuffer.MatricesIndicesExtraKind, floatIndices, parsedGeometry.matricesIndicesExtra._updatable);
@@ -1386,8 +1394,8 @@ export class Geometry implements IGetSetVerticesData {
         } else {
         } else {
             return;
             return;
         }
         }
-        let matricesIndices = (<FloatArray>mesh.getVerticesData(VertexBuffer.MatricesIndicesKind));
-        let matricesIndicesExtra = (<FloatArray>mesh.getVerticesData(VertexBuffer.MatricesIndicesExtraKind));
+        let matricesIndices = <FloatArray>mesh.getVerticesData(VertexBuffer.MatricesIndicesKind);
+        let matricesIndicesExtra = <FloatArray>mesh.getVerticesData(VertexBuffer.MatricesIndicesExtraKind);
         let matricesWeights = parsedGeometry.matricesWeights;
         let matricesWeights = parsedGeometry.matricesWeights;
         let matricesWeightsExtra = parsedGeometry.matricesWeightsExtra;
         let matricesWeightsExtra = parsedGeometry.matricesWeightsExtra;
         let influencers = parsedGeometry.numBoneInfluencer;
         let influencers = parsedGeometry.numBoneInfluencer;
@@ -1412,7 +1420,7 @@ export class Geometry implements IGetSetVerticesData {
                     }
                     }
                 }
                 }
             }
             }
-            if (firstZeroWeight < 0 || firstZeroWeight > (influencers - 1)) {
+            if (firstZeroWeight < 0 || firstZeroWeight > influencers - 1) {
                 firstZeroWeight = influencers - 1;
                 firstZeroWeight = influencers - 1;
             }
             }
             if (weight > epsilon) {
             if (weight > epsilon) {
@@ -1511,4 +1519,4 @@ export class Geometry implements IGetSetVerticesData {
 
 
         return geometry;
         return geometry;
     }
     }
-}
+}