Sfoglia il codice sorgente

Merge pull request #1672 from jbousquie/feature.FacetData

Feature.facet data
David Catuhe 8 anni fa
parent
commit
c8b98cd761

+ 73 - 39
src/Mesh/babylon.mesh.ts

@@ -128,6 +128,7 @@
         private _partitioningSubdivisions: number = 10; // number of subdivisions per axis in the partioning space  
         private _partitioningBBoxRatio: number = 1.01;  // the partioning array space is by default 1% bigger than the bounding box
         private _facetDataEnabled: boolean = false;     // is the facet data feature enabled on this mesh ?
+        private _facetParameters: any;                  // keep a reference to the object parameters to avoid memory re-allocation
 
         /**
          * Read-only : the number of facets in the mesh
@@ -135,18 +136,15 @@
         public get facetNb(): number {
             return this._facetNb;
         }
-
         /**
          * The number of subdivisions per axis in the partioning space
          */
         public get partitioningSubdivisions(): number {
             return this._partitioningSubdivisions;
         }
-
         public set partitioningSubdivisions(nb: number) {
             this._partitioningSubdivisions = nb;
         } 
-
         /**
          * The ratio to apply to the bouding box size to set to the partioning space.  
          * Ex : 1.01 (default) the partioning space is 1% bigger than the bounding box.
@@ -154,10 +152,15 @@
         public get partitioningBBoxRatio(): number {
             return this._partitioningBBoxRatio;
         }
-
         public set partitioningBBoxRatio(ratio: number) {
             this._partitioningBBoxRatio = ratio;
         }
+        /**
+         * Read-only : is the feature facetData enabled ?
+         */
+        public get isFacetDataEnabled(): boolean {
+            return this._facetDataEnabled;
+        }
 
         // Will be used to save a source mesh reference, If any
         private _source: BABYLON.Mesh = null; 
@@ -1753,10 +1756,10 @@
         }
 
         /**
-         * Optimization of the mesh's indices, in case a mesh has duplicated vertices.
-         * The function will only reorder the indices and will not remove unused vertices to avoid problems with submeshes.
-         * This should be used together with the simplification to avoid disappearing triangles.
-         * @param successCallback an optional success callback to be called after the optimization finished.
+         * Optimization of the mesh's indices, in case a mesh has duplicated vertices.   
+         * The function will only reorder the indices and will not remove unused vertices to avoid problems with submeshes.   
+         * This should be used together with the simplification to avoid disappearing triangles.   
+         * @param successCallback an optional success callback to be called after the optimization finished.   
          */
         public optimizeIndices(successCallback?: (mesh?: Mesh) => void) {
             var indices = this.getIndices();
@@ -1818,8 +1821,9 @@
         }
 
         /**
-         * Updates the mesh facetData arrays and the internal partitioning when the mesh is morphed or updated.
-         * This method can be called within the render loop.
+         * Updates the mesh facetData arrays and the internal partitioning when the mesh is morphed or updated.  
+         * This method can be called within the render loop.  
+         * You don't need to call this method by yourself in the render loop when you update/morph a mesh with the methods CreateXXX() as they automatically manage this computation.  
          */
         public updateFacetData(): Mesh {
             if (!this._facetDataEnabled) {
@@ -1828,21 +1832,13 @@
             var positions = this.getVerticesData(VertexBuffer.PositionKind);
             var indices = this.getIndices();
             var normals = this.getVerticesData(VertexBuffer.NormalKind);
-            var options = {
-                facetNormals: this.getFacetLocalNormals(), 
-                facetPositions: this.getFacetLocalPositions(), 
-                facetPartitioning: this._facetPartitioning, 
-                bInfo: this.getBoundingInfo(),
-                ratio: this._partitioningBBoxRatio,
-                partitioningSubdivisions: this._partitioningSubdivisions
-            };
+            var options = this.getFacetDataParameters();
             VertexData.ComputeNormals(positions, indices, normals, options);
-            this.updateVerticesData(VertexBuffer.NormalKind, normals, false, false);
             return this;
         }
         /**
-         * Returns the facetLocalNormals array.
-         * The normals are expressed in the mesh local space.
+         * Returns the facetLocalNormals array.  
+         * The normals are expressed in the mesh local space.  
          */
         public getFacetLocalNormals(): Vector3[] {
             if (!this._facetNormals) {
@@ -1851,8 +1847,8 @@
             return this._facetNormals;
         }
         /**
-         * Returns the facetLocalPositions array.
-         * The facet positions are expressed in the mesh local space.
+         * Returns the facetLocalPositions array.  
+         * The facet positions are expressed in the mesh local space.  
          */
         public getFacetLocalPositions(): Vector3[] {
             if (!this._facetPositions) {
@@ -1861,8 +1857,17 @@
             return this._facetPositions;           
         }
         /**
-         * Returns the i-th facet position in the world system.
-         * This method allocates a new Vector3 per call.
+         * Returns the facetLocalPartioning array
+         */
+        public getFacetLocalPartitioning(): number[][] {
+            if (!this._facetPartitioning) {
+                this.updateFacetData();
+            }
+            return this._facetPartitioning;
+        }
+        /**
+         * Returns the i-th facet position in the world system.  
+         * This method allocates a new Vector3 per call.  
          */
         public getFacetPosition(i: number): Vector3 {
             var pos = Vector3.Zero();
@@ -1870,8 +1875,8 @@
             return pos;
         }
         /**
-         * Sets the reference Vector3 with the i-th facet position in the world system.
-         * Returns the mesh.
+         * Sets the reference Vector3 with the i-th facet position in the world system.  
+         * Returns the mesh.  
          */
         public getFacetPositionToRef(i: number, ref: Vector3): Mesh {
             var localPos = (this.getFacetLocalPositions())[i];
@@ -1880,8 +1885,8 @@
             return this;
         }
         /**
-         * Returns the i-th facet normal in the world system.
-         * This method allocates a new Vector3 per call.
+         * Returns the i-th facet normal in the world system.  
+         * This method allocates a new Vector3 per call.  
          */
         public getFacetNormal(i: number): Vector3 {
             var norm = Vector3.Zero();
@@ -1889,8 +1894,8 @@
             return norm;
         }
         /**
-         * Sets the reference Vector3 with the i-th facet normal in the world system.
-         * Returns the mesh.
+         * Sets the reference Vector3 with the i-th facet normal in the world system.  
+         * Returns the mesh.  
          */
         public getFacetNormalToRef(i: number, ref: Vector3) {
             var localNorm = (this.getFacetLocalNormals())[i];
@@ -1920,9 +1925,9 @@
             return this._facetPartitioning[ox + this._partitioningSubdivisions * oy + this._partitioningSubdivisions * this._partitioningSubdivisions * oz];
         }
         /** 
-         * Returns the closest mesh facet index at (x,y,z) World coordinates, null if not found
-         * If the parameter projected (vector3) is passed, it is set as the (x,y,z) World projection on the facet
-         * If onlyFacing is true, only the facet "facing" (x,y,z) are returned : positive dot normal * (x,y,z)
+         * Returns the closest mesh facet index at (x,y,z) World coordinates, null if not found.  
+         * If the parameter projected (vector3) is passed, it is set as the (x,y,z) World projection on the facet.  
+         * If onlyFacing is true, only the facet "facing" (x,y,z) are returned : positive dot normal * (x,y,z).  
          */
         public getClosestFacetAtCoordinates(x: number, y: number, z: number, projected?: Vector3, onlyFacing?: boolean): number {
             var world = this.getWorldMatrix();
@@ -1939,9 +1944,9 @@
             return closest;
         }
         /** 
-         * Returns the closest mesh facet index at (x,y,z) local coordinates, null if not found
-         * If the parameter projected (vector3) is passed, it is set as the (x,y,z) local projection on the facet
-         * If onlyFacing is true, only the facet "facing" (x,y,z) are returned : positive dot normal * (x,y,z)
+         * Returns the closest mesh facet index at (x,y,z) local coordinates, null if not found.   
+         * If the parameter projected (vector3) is passed, it is set as the (x,y,z) local projection on the facet.  
+         * If onlyFacing is true, only the facet "facing" (x,y,z) are returned : positive dot normal * (x,y,z).  
          */
         public getClosestFacetAtLocalCoordinates(x: number, y: number, z: number, projected?: Vector3, onlyFacing?: boolean) {
             var closest = null;
@@ -1998,10 +2003,39 @@
             }
             return closest;
         }
+        /**
+         * Returns the object "parameter" set with all the expected parameters for facetData computation by ComputeNormals()  
+         */
+        public getFacetDataParameters(): any {
+            if (!this._facetParameters) {
+                this._facetParameters = {
+                    facetNormals: this.getFacetLocalNormals(), 
+                    facetPositions: this.getFacetLocalPositions(),
+                    facetPartitioning: this.getFacetLocalPartitioning(),
+                    bInfo: this.getBoundingInfo(),
+                    partitioningSubdivisions: this.partitioningSubdivisions,
+                    ratio: this.partitioningBBoxRatio
+                };
+            }
+            return this._facetParameters;
+        }
+        /** 
+         * Disables the feature FacetData and frees the related memory.  
+         * Returns the mesh.  
+         */
+        public disableFacetData(): Mesh {
+            this._facetDataEnabled = false;
+            this._facetPositions = null;
+            this._facetNormals = null;
+            this._facetPartitioning = null;
+            this._facetParameters = null;
+            return this;
+        }
+
         // Statics
         /**
-         * Returns a new Mesh object what is a deep copy of the passed mesh. 
-         * The parameter `parsedMesh` is the mesh to be copied.
+         * Returns a new Mesh object what is a deep copy of the passed mesh.   
+         * The parameter `parsedMesh` is the mesh to be copied.   
          * The parameter `rootUrl` is a string, it's the root URL to prefix the `delayLoadingFile` property with
          */
         public static Parse(parsedMesh: any, scene: Scene, rootUrl: string): Mesh {

+ 10 - 9
src/Mesh/babylon.mesh.vertexData.ts

@@ -2023,6 +2023,7 @@
                 var xSubRatio = 0.0;        // tmp x divider
                 var ySubRatio = 0.0;        // tmp x divider
                 var zSubRatio = 0.0;        // tmp x divider  
+                var subSq = options.partitioningSubdivisions * options.partitioningSubdivisions;
                 options.facetPartitioning.length = 0;
             }
         
@@ -2097,15 +2098,15 @@
                     b3y = Math.floor((positions[v3y] - options.bInfo.minimum.y * options.ratio) * ySubRatio);
                     b3z = Math.floor((positions[v3z] - options.bInfo.minimum.z * options.ratio) * zSubRatio);
                     
-                    block_idx_v1 = b1x + options.partitioningSubdivisions * b1y + options.partitioningSubdivisions * options.partitioningSubdivisions * b1z;
-                    block_idx_v2 = b2x + options.partitioningSubdivisions * b2y + options.partitioningSubdivisions * options.partitioningSubdivisions * b2z;
-                    block_idx_v3 = b3x + options.partitioningSubdivisions * b3y + options.partitioningSubdivisions * options.partitioningSubdivisions * b3z;
-                    block_idx_o = ox + options.partitioningSubdivisions * oy + options.partitioningSubdivisions * options.partitioningSubdivisions * oz;
-
-                    options.facetPartitioning[block_idx_o] = (options.facetPartitioning[block_idx_o]) ? options.facetPartitioning[block_idx_o] :new Array();
-                    options.facetPartitioning[block_idx_v1] = (options.facetPartitioning[block_idx_v1]) ? options.facetPartitioning[block_idx_v1] :new Array();
-                    options.facetPartitioning[block_idx_v2] = (options.facetPartitioning[block_idx_v2]) ? options.facetPartitioning[block_idx_v2] :new Array();
-                    options.facetPartitioning[block_idx_v3] = (options.facetPartitioning[block_idx_v3]) ? options.facetPartitioning[block_idx_v3] :new Array();
+                    block_idx_v1 = b1x + options.partitioningSubdivisions * b1y + subSq * b1z;
+                    block_idx_v2 = b2x + options.partitioningSubdivisions * b2y + subSq * b2z;
+                    block_idx_v3 = b3x + options.partitioningSubdivisions * b3y + subSq * b3z;
+                    block_idx_o = ox + options.partitioningSubdivisions * oy + subSq * oz;
+
+                    options.facetPartitioning[block_idx_o] = options.facetPartitioning[block_idx_o] ? options.facetPartitioning[block_idx_o] :new Array();
+                    options.facetPartitioning[block_idx_v1] = options.facetPartitioning[block_idx_v1] ? options.facetPartitioning[block_idx_v1] :new Array();
+                    options.facetPartitioning[block_idx_v2] = options.facetPartitioning[block_idx_v2] ? options.facetPartitioning[block_idx_v2] :new Array();
+                    options.facetPartitioning[block_idx_v3] = options.facetPartitioning[block_idx_v3] ? options.facetPartitioning[block_idx_v3] :new Array();
 
                     // push each facet index in each block containing the vertex
                     options.facetPartitioning[block_idx_v1].push(index);

+ 6 - 4
src/Mesh/babylon.meshBuilder.ts

@@ -187,10 +187,11 @@
                 instance._boundingInfo = new BoundingInfo(Tmp.Vector3[0], Tmp.Vector3[1]);
                 instance._boundingInfo.update(instance._worldMatrix);
                 instance.updateVerticesData(VertexBuffer.PositionKind, positions, false, false);
-                if (!(instance.areNormalsFrozen)) {
+                if (!instance.areNormalsFrozen || instance.isFacetDataEnabled) {
                     var indices = instance.getIndices();
                     var normals = instance.getVerticesData(VertexBuffer.NormalKind);
-                    VertexData.ComputeNormals(positions, indices, normals);
+                    var params = instance.isFacetDataEnabled ? instance.getFacetDataParameters() : null;
+                    VertexData.ComputeNormals(positions, indices, normals, params);
 
                     if ((<any>instance)._closePath) {
                         var indexFirst: number = 0;
@@ -211,8 +212,9 @@
                             normals[indexLast + 2] = normals[indexFirst + 2];
                         }
                     }
-
-                    instance.updateVerticesData(VertexBuffer.NormalKind, normals, false, false);
+                    if (!(instance.areNormalsFrozen)) {
+                        instance.updateVerticesData(VertexBuffer.NormalKind, normals, false, false);
+                    }
                 }
 
                 return instance;

+ 21 - 13
src/Particles/babylon.solidParticleSystem.ts

@@ -562,13 +562,17 @@
             }
 
             Matrix.IdentityToRef(this._rotMatrix);
-            var idx = 0;
-            var index = 0;
-            var colidx = 0;
-            var colorIndex = 0;
-            var uvidx = 0;
-            var uvIndex = 0;
-            var pt = 0;
+            var idx = 0;            // current position index in the global array positions32
+            var index = 0;          // position start index in the global array positions32 of the current particle
+            var colidx = 0;         // current color index in the global array colors32
+            var colorIndex = 0;     // color start index in the global array colors32 of the current particle
+            var uvidx = 0;          // current uv index in the global array uvs32
+            var uvIndex = 0;        // uv start index in the global array uvs32 of the current particle
+            var pt = 0;             // current index in the particle model shape
+
+            if (this.mesh.isFacetDataEnabled) {
+                this._computeBoundingBox = true;
+            }
 
             if (this._computeBoundingBox) {
                 Vector3.FromFloatsToRef(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, this._minimum);
@@ -653,7 +657,8 @@
                             }
                         }
 
-                        // normals : if the particles can't be morphed then just rotate the normals, what if much more faster than ComputeNormals()
+                        // normals : if the particles can't be morphed then just rotate the normals, what is much more faster than ComputeNormals()
+                        // the same for the facet data
                         if (!this._computeParticleVertex) {
                             this._normal.x = this._fixedNormal32[idx];
                             this._normal.y = this._fixedNormal32[idx + 1];
@@ -666,7 +671,7 @@
 
                             this._normals32[idx] = this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
                             this._normals32[idx + 1] = this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
-                            this._normals32[idx + 2] = this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
+                            this._normals32[idx + 2] = this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;                          
                         }
 
                         if (this._computeParticleColor) {
@@ -757,15 +762,18 @@
                     this.mesh.updateVerticesData(VertexBuffer.UVKind, this._uvs32, false, false);
                 }
                 this.mesh.updateVerticesData(VertexBuffer.PositionKind, this._positions32, false, false);
-                if (!this.mesh.areNormalsFrozen) {
-                    if (this._computeParticleVertex) {
+                if (!this.mesh.areNormalsFrozen || this.mesh.isFacetDataEnabled) {
+                    if (this._computeParticleVertex || this.mesh.isFacetDataEnabled) {
                         // recompute the normals only if the particles can be morphed, update then also the normal reference array _fixedNormal32[]
-                        VertexData.ComputeNormals(this._positions32, this._indices, this._normals32);
+                        var params = this.mesh.isFacetDataEnabled ? this.mesh.getFacetDataParameters() : null;
+                        VertexData.ComputeNormals(this._positions32, this._indices, this._normals32, params);
                         for (var i = 0; i < this._normals32.length; i++) {
                             this._fixedNormal32[i] = this._normals32[i];
                         }
                     }
-                    this.mesh.updateVerticesData(VertexBuffer.NormalKind, this._normals32, false, false);
+                    if (!this.mesh.areNormalsFrozen) {
+                        this.mesh.updateVerticesData(VertexBuffer.NormalKind, this._normals32, false, false);
+                    }
                 }
             }
             if (this._computeBoundingBox) {