Kaynağa Gözat

Merge pull request #3121 from jbousquie/FacetData.depthSort

Added facet depth sort in FacetData
David Catuhe 7 yıl önce
ebeveyn
işleme
38d57b1535

+ 87 - 9
src/Mesh/babylon.abstractMesh.ts

@@ -36,19 +36,27 @@
         // facetData private properties
         private _facetPositions: Vector3[];             // facet local positions
         private _facetNormals: Vector3[];               // facet local normals
-        private _facetPartitioning: number[][];           // partitioning array of facet index arrays
+        private _facetPartitioning: number[][];         // partitioning array of facet index arrays
         private _facetNb: number = 0;                   // facet number
         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
+        private _facetParameters: any = {};             // keep a reference to the object parameters to avoid memory re-allocation
         private _bbSize: Vector3 = Vector3.Zero();      // bbox size approximated for facet data
-        private _subDiv = {                         // actual number of subdivisions per axis for ComputeNormals()
+        private _subDiv = {                             // actual number of subdivisions per axis for ComputeNormals()
             max: 1,
             X: 1,
             Y: 1,
             Z: 1
         };
+        private _facetDepthSort: boolean = false;                           // is the facet depth sort enabled
+        private _originalIndices: IndicesArray;                             // copy of the original indices array
+        private _depthSortedFacets: {ind: number, sqDistance: number}[];    // array of depth sorted facets
+        private _facetDepthSortFunction: (f1: {ind: number, sqDistance: number}, f2: {ind: number, sqDistance: number}) => number;  // facet depth sort function
+        private _facetDepthSortFrom: Vector3;                               // location where to depth sort from
+        private _facetDepthSortOrigin: Vector3;                             // same as facetDepthSortFrom but expressed in the mesh local space
+        private _invertedMatrix: Matrix;                                    // Mesh inverted World Matrix
+
         /**
          * Read-only : the number of facets in the mesh
          */
@@ -75,6 +83,27 @@
             this._partitioningBBoxRatio = ratio;
         }
         /**
+         * Boolean : must the facet be depth sorted on next call to `updateFacetData()` ?  
+         * Works only for updatable meshes.  
+         */
+        public get mustDepthSortFacets(): boolean {
+            return this._facetDepthSort;
+        }
+        public set mustDepthSortFacets(sort: boolean) {
+            this._facetDepthSort = sort;
+        }
+        /**
+         * The location (Vector3) where the facet depth sort must be computed from.  
+         * By default, the active camera position.  
+         * Used only when facet depth sort is enabled.  
+         */
+        public get facetDepthSortFrom(): Vector3 {
+            return this._facetDepthSortFrom;
+        }
+        public set facetDepthSortFrom(location: Vector3) {
+            this._facetDepthSortFrom = location;
+        }
+        /**
          * Read-only boolean : is the feature facetData enabled ?
          */
         public get isFacetDataEnabled(): boolean {
@@ -2187,7 +2216,7 @@
             if (!this._facetPartitioning) {
                 this._facetPartitioning = new Array<number[]>();
             }
-            this._facetNb = (<IndicesArray>this.getIndices()).length / 3;
+            this._facetNb = ((<IndicesArray>this.getIndices()).length / 3)|0;
             this._partitioningSubdivisions = (this._partitioningSubdivisions) ? this._partitioningSubdivisions : 10;   // default nb of partitioning subdivisions = 10
             this._partitioningBBoxRatio = (this._partitioningBBoxRatio) ? this._partitioningBBoxRatio : 1.01;          // default ratio 1.01 = the partitioning is 1% bigger than the bounding box
             for (var f = 0; f < this._facetNb; f++) {
@@ -2210,13 +2239,33 @@
             }
             var positions = this.getVerticesData(VertexBuffer.PositionKind);
             var indices = this.getIndices();
+            var indicesForComputeNormals = indices;
             var normals = this.getVerticesData(VertexBuffer.NormalKind);
             var bInfo = this.getBoundingInfo();
-
+            
             if (!bInfo) {
                 return this;
             }
 
+            if (this._facetDepthSort && !this._originalIndices) {
+                // init arrays, matrix and sort function on first call
+                this._originalIndices = new Uint32Array(indices!);
+                this._facetDepthSortFunction = function(f1, f2) {
+                    return (f2.sqDistance - f1.sqDistance);
+                };
+                if (!this._facetDepthSortFrom) {
+                    var camera = this.getScene().activeCamera;
+                    this._facetDepthSortFrom = (camera) ? camera.position : Vector3.Zero();
+                }
+                this._depthSortedFacets = [];
+                for (var f = 0; f < this._facetNb; f++) {
+                    var depthSortedFacet = {ind: f * 3, sqDistance: 0.0};
+                    this._depthSortedFacets.push(depthSortedFacet);
+                }
+                this._invertedMatrix = Matrix.Identity();
+                this._facetDepthSortOrigin = Vector3.Zero();
+            }
+
             this._bbSize.x = (bInfo.maximum.x - bInfo.minimum.x > Epsilon) ? bInfo.maximum.x - bInfo.minimum.x : Epsilon;
             this._bbSize.y = (bInfo.maximum.y - bInfo.minimum.y > Epsilon) ? bInfo.maximum.y - bInfo.minimum.y : Epsilon;
             this._bbSize.z = (bInfo.maximum.z - bInfo.minimum.z > Epsilon) ? bInfo.maximum.z - bInfo.minimum.z : Epsilon;
@@ -2237,7 +2286,27 @@
             this._facetParameters.bbSize = this._bbSize;
             this._facetParameters.subDiv = this._subDiv;
             this._facetParameters.ratio = this.partitioningBBoxRatio;
-            VertexData.ComputeNormals(positions, indices, normals, this._facetParameters);
+            this._facetParameters.depthSort = this._facetDepthSort;
+            if (this._facetDepthSort) {
+                this.computeWorldMatrix(true);
+                this._worldMatrix.invertToRef(this._invertedMatrix);
+                Vector3.TransformCoordinatesToRef(this._facetDepthSortFrom, this._invertedMatrix, this._facetDepthSortOrigin);   
+                this._facetParameters.distanceTo = this._facetDepthSortOrigin;
+                indicesForComputeNormals = this._originalIndices;
+            }
+            this._facetParameters.depthSortedFacets = this._depthSortedFacets;
+            VertexData.ComputeNormals(positions, indicesForComputeNormals, normals, this._facetParameters);
+
+            if (this._facetDepthSort) {
+                this._depthSortedFacets.sort(this._facetDepthSortFunction);
+                for (var sorted = 0; sorted < this._facetNb; sorted++) {
+                    var sind = this._depthSortedFacets[sorted].ind;
+                    indices![sorted * 3] = this._originalIndices[sind];
+                    indices![sorted * 3 + 1] = this._originalIndices[sind + 1];
+                    indices![sorted * 3 + 2] = this._originalIndices[sind + 2];
+                }
+                this.updateIndices(indices!);
+            }
 
             return this;
         }
@@ -2407,6 +2476,7 @@
             }
             return closest;
         }
+
         /**
          * Returns the object "parameter" set with all the expected parameters for facetData computation by ComputeNormals()  
          */
@@ -2420,13 +2490,21 @@
         public disableFacetData(): AbstractMesh {
             if (this._facetDataEnabled) {
                 this._facetDataEnabled = false;
-                this._facetPositions = new Array<Vector3>();;
-                this._facetNormals = new Array<Vector3>();;
-                this._facetPartitioning = new Array<number[]>();;
+                this._facetPositions = new Array<Vector3>();
+                this._facetNormals = new Array<Vector3>();
+                this._facetPartitioning = new Array<number[]>();
                 this._facetParameters = null;
+                this._originalIndices = new Uint32Array(0);
             }
             return this;
         }
+        /**
+         * Updates the AbstractMesh indices array. Actually, used by the Mesh object.
+         * Returns the mesh.
+         */
+        public updateIndices(indices: IndicesArray): AbstractMesh {
+            return this;
+        }
 
         /**
          * Creates new normals data for the mesh.

+ 22 - 1
src/Mesh/babylon.mesh.vertexData.ts

@@ -2216,9 +2216,14 @@
          * ratio : optional partitioning ratio / bounding box, required for facetPartitioning computation
          * bbSize : optional bounding box size data, required for facetPartitioning computation
          * bInfo : optional bounding info, required for facetPartitioning computation
+         * useRightHandedSystem: optional boolean to for right handed system computation
+         * depthSort : optional boolean to enable the facet depth sort computation
+         * distanceTo : optional Vector3 to compute the facet depth from this location
+         * depthSortedFacets : optional array of depthSortedFacets to store the facet distances from the reference location
          */
         public static ComputeNormals(positions: any, indices: any, normals: any,
-            options?: { facetNormals?: any, facetPositions?: any, facetPartitioning?: any, ratio?: number, bInfo?: any, bbSize?: Vector3, subDiv?: any, useRightHandedSystem?: boolean }): void {
+            options?: { facetNormals?: any, facetPositions?: any, facetPartitioning?: any, ratio?: number, bInfo?: any, bbSize?: Vector3, subDiv?: any, 
+                useRightHandedSystem?: boolean, depthSort?: boolean, distanceTo?: Vector3, depthSortedFacets?: any }): void {
 
             // temporary scalar variables
             var index = 0;                      // facet index     
@@ -2244,14 +2249,24 @@
             var computeFacetNormals = false;
             var computeFacetPositions = false;
             var computeFacetPartitioning = false;
+            var computeDepthSort = false;
             var faceNormalSign = 1;
             let ratio = 0;
+            var distanceTo: Nullable<Vector3> = null;
             if (options) {
                 computeFacetNormals = (options.facetNormals) ? true : false;
                 computeFacetPositions = (options.facetPositions) ? true : false;
                 computeFacetPartitioning = (options.facetPartitioning) ? true : false;
                 faceNormalSign = (options.useRightHandedSystem === true) ? -1 : 1;
                 ratio = options.ratio || 0;
+                computeDepthSort = (options.depthSort) ? true : false;
+                distanceTo = <Vector3>(options.distanceTo);
+                if (computeDepthSort) {
+                    if (distanceTo === undefined) {
+                        distanceTo = Vector3.Zero();
+                    } 
+                    var depthSortedFacets = options.depthSortedFacets;
+                }
             }
 
             // facetPartitioning reinit if needed
@@ -2377,6 +2392,12 @@
                     }
                 }
 
+                if (computeDepthSort && options && options.facetPositions) {
+                    var dsf = depthSortedFacets[index];
+                    dsf.ind = index * 3;
+                    dsf.sqDistance = Vector3.DistanceSquared(options.facetPositions[index], distanceTo!)
+                }
+
                 // compute the normals anyway
                 normals[v1x] += faceNormalx;                         // accumulate all the normals per face
                 normals[v1y] += faceNormaly;