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 years ago
parent
commit
7c12e3cd8f
1 changed files with 78 additions and 70 deletions
  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 { Scene } from "../scene";
 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 { IGetSetVerticesData, VertexData } from "../Meshes/mesh.vertexData";
 import { VertexBuffer } from "../Meshes/buffer";
@@ -13,8 +13,8 @@ import { BoundingInfo } from "../Culling/boundingInfo";
 import { Constants } from "../Engines/constants";
 import { Tools } from "../Misc/tools";
 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;
 
@@ -52,9 +52,9 @@ export class Geometry implements IGetSetVerticesData {
     /** @hidden */
     public _indices: IndicesArray;
     /** @hidden */
-    public _vertexBuffers: { [key: string]: VertexBuffer; };
+    public _vertexBuffers: { [key: string]: VertexBuffer };
     private _isDisposed = false;
-    private _extend: { minimum: Vector3, maximum: Vector3 };
+    private _extend: { minimum: Vector3; maximum: Vector3 };
     private _boundingBias: Vector2;
     /** @hidden */
     public _delayInfo: Array<string>;
@@ -66,12 +66,13 @@ export class Geometry implements IGetSetVerticesData {
     public _delayLoadingFunction: Nullable<(any: any, geometry: Geometry) => void>;
     /** @hidden */
     public _softwareSkinningFrameId: number;
-    private _vertexArrayObjects: { [key: string]: WebGLVertexArrayObject; };
+    private _vertexArrayObjects: { [key: string]: WebGLVertexArrayObject };
     private _updatable: boolean;
 
     // Cache
     /** @hidden */
     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
@@ -86,8 +87,7 @@ export class Geometry implements IGetSetVerticesData {
     public set boundingBias(value: Vector2) {
         if (this._boundingBias) {
             this._boundingBias.copyFrom(value);
-        }
-        else {
+        } else {
             this._boundingBias = value.clone();
         }
 
@@ -140,8 +140,7 @@ export class Geometry implements IGetSetVerticesData {
         // vertexData
         if (vertexData) {
             this.setAllVerticesData(vertexData, updatable);
-        }
-        else {
+        } else {
             this._totalVertices = 0;
             this._indices = [];
         }
@@ -160,7 +159,7 @@ export class Geometry implements IGetSetVerticesData {
     /**
      * Gets the current extend of the geometry
      */
-    public get extend(): { minimum: Vector3, maximum: Vector3 } {
+    public get extend(): { minimum: Vector3; maximum: Vector3 } {
         return this._extend;
     }
 
@@ -351,8 +350,7 @@ export class Geometry implements IGetSetVerticesData {
             for (const mesh of meshes) {
                 if (mesh._boundingInfo) {
                     mesh._boundingInfo.reConstruct(this._extend.minimum, this._extend.maximum);
-                }
-                else {
+                } else {
                     mesh._boundingInfo = new BoundingInfo(this._extend.minimum, this._extend.maximum);
                 }
 
@@ -431,15 +429,13 @@ export class Geometry implements IGetSetVerticesData {
             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) {
                 const offset = vertexBuffer.byteOffset / 4;
                 return Tools.Slice(data, offset, offset + count);
-            }
-            else if (data instanceof ArrayBuffer) {
+            } else if (data instanceof ArrayBuffer) {
                 return new Float32Array(data, vertexBuffer.byteOffset, count);
-            }
-            else {
+            } else {
                 const offset = data.byteOffset + vertexBuffer.byteOffset;
                 if (forceCopy || (copyWhenShared && this._meshes.length !== 1)) {
                     let result = new Float32Array(count);
@@ -491,7 +487,7 @@ export class Geometry implements IGetSetVerticesData {
      * Returns all vertex buffers
      * @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()) {
             return null;
         }
@@ -580,7 +576,8 @@ export class Geometry implements IGetSetVerticesData {
             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;
         }
 
@@ -695,8 +692,7 @@ export class Geometry implements IGetSetVerticesData {
 
         if (this.isReady()) {
             this._applyToMesh(mesh);
-        }
-        else {
+        } else {
             mesh._boundingInfo = this._boundingInfo;
         }
     }
@@ -705,7 +701,7 @@ export class Geometry implements IGetSetVerticesData {
         if (this.useBoundingInfoFromGeometry && this._boundingInfo) {
             this._extend = {
                 minimum: this._boundingInfo.minimum.clone(),
-                maximum: this._boundingInfo.maximum.clone()
+                maximum: this._boundingInfo.maximum.clone(),
             };
         } else {
             if (!data) {
@@ -795,35 +791,39 @@ export class Geometry implements IGetSetVerticesData {
         }
 
         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.
      */
     public toLeftHanded(): void {
-
         // Flip faces
         let tIndices = this.getIndices(false);
         if (tIndices != null && tIndices.length > 0) {
@@ -872,12 +872,21 @@ export class Geometry implements IGetSetVerticesData {
             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;
     }
 
@@ -1156,7 +1165,6 @@ export class Geometry implements IGetSetVerticesData {
                 geometry.applyToMesh(mesh);
             }
         } else if (parsedGeometry instanceof ArrayBuffer) {
-
             var binaryInfo = mesh._binaryInfo;
 
             if (binaryInfo.positionsAttrDesc && binaryInfo.positionsAttrDesc.count > 0) {
@@ -1214,10 +1222,10 @@ export class Geometry implements IGetSetVerticesData {
                 var floatIndices = [];
                 for (var i = 0; i < matricesIndicesData.length; 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);
             }
@@ -1227,10 +1235,10 @@ export class Geometry implements IGetSetVerticesData {
                 var floatIndices = [];
                 for (var i = 0; i < matricesIndicesData.length; 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);
             }
@@ -1250,11 +1258,11 @@ export class Geometry implements IGetSetVerticesData {
 
                 mesh.subMeshes = [];
                 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);
                 }
@@ -1303,10 +1311,10 @@ export class Geometry implements IGetSetVerticesData {
                     for (var i = 0; i < parsedGeometry.matricesIndices.length; 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);
@@ -1323,10 +1331,10 @@ export class Geometry implements IGetSetVerticesData {
                     for (var i = 0; i < parsedGeometry.matricesIndicesExtra.length; 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);
@@ -1386,8 +1394,8 @@ export class Geometry implements IGetSetVerticesData {
         } else {
             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 matricesWeightsExtra = parsedGeometry.matricesWeightsExtra;
         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;
             }
             if (weight > epsilon) {
@@ -1511,4 +1519,4 @@ export class Geometry implements IGetSetVerticesData {
 
         return geometry;
     }
-}
+}