Explorar el Código

Simplification Queue

To Allow a constant simplification process, and to only process one mesh
at a time, a simplification queue was created. If executed, the process
will execute all pending simplifications.
Raanan Weber hace 10 años
padre
commit
5835ce1fd2

+ 90 - 1
Babylon/Mesh/babylon.meshSimplification.js

@@ -8,6 +8,71 @@ var BABYLON;
         return SimplificationSettings;
     })();
     BABYLON.SimplificationSettings = SimplificationSettings;
+    var SimplificationQueue = (function () {
+        function SimplificationQueue() {
+            this.running = false;
+            this._simplificationArray = [];
+        }
+        SimplificationQueue.prototype.executeNext = function () {
+            var task = this._simplificationArray.pop();
+            if (task) {
+                this.running = true;
+                this.runSimplification(task);
+            }
+            else {
+                this.running = false;
+            }
+        };
+        SimplificationQueue.prototype.runSimplification = function (task) {
+            var _this = this;
+            if (task.parallelProcessing) {
+                //parallel simplifier
+                task.settings.forEach(function (setting) {
+                    var simplifier = _this.getSimplifier(task);
+                    simplifier.simplify(setting, function (newMesh) {
+                        task.mesh.addLODLevel(setting.distance, newMesh);
+                        //check if it is the last
+                        if (setting.quality === task.settings[task.settings.length - 1].quality && task.successCallback) {
+                            //all done, run the success callback.
+                            task.successCallback();
+                        }
+                        _this.executeNext();
+                    });
+                });
+            }
+            else {
+                //single simplifier.
+                var simplifier = this.getSimplifier(task);
+                var runDecimation = function (setting, callback) {
+                    simplifier.simplify(setting, function (newMesh) {
+                        task.mesh.addLODLevel(setting.distance, newMesh);
+                        //run the next quality level
+                        callback();
+                    });
+                };
+                BABYLON.AsyncLoop.Run(task.settings.length, function (loop) {
+                    runDecimation(task.settings[loop.index], function () {
+                        loop.executeNext();
+                    });
+                }, function () {
+                    //execution ended, run the success callback.
+                    if (task.successCallback) {
+                        task.successCallback();
+                    }
+                    _this.executeNext();
+                });
+            }
+        };
+        SimplificationQueue.prototype.getSimplifier = function (task) {
+            switch (task.simplificationType) {
+                case 0 /* QUADRATIC */:
+                default:
+                    return new QuadraticErrorSimplification(task.mesh);
+            }
+        };
+        return SimplificationQueue;
+    })();
+    BABYLON.SimplificationQueue = SimplificationQueue;
     /**
      * The implemented types of simplification.
      * At the moment only Quadratic Error Decimation is implemented.
@@ -105,6 +170,7 @@ var BABYLON;
             this.syncIterations = 5000;
             this.aggressiveness = 7;
             this.decimationIterations = 100;
+            this.boundingBoxEpsilon = BABYLON.Engine.Epsilon;
         }
         QuadraticErrorSimplification.prototype.simplify = function (settings, successCallback) {
             var _this = this;
@@ -112,6 +178,29 @@ var BABYLON;
                 _this.runDecimation(settings, successCallback);
             });
         };
+        QuadraticErrorSimplification.prototype.isTriangleOnBoundingBox = function (triangle) {
+            var _this = this;
+            var gCount = 0;
+            triangle.vertices.forEach(function (vId) {
+                var count = 0;
+                var vPos = _this.vertices[vId].position;
+                var bbox = _this._mesh.getBoundingInfo().boundingBox;
+                if (bbox.maximum.x - vPos.x < _this.boundingBoxEpsilon || vPos.x - bbox.minimum.x > _this.boundingBoxEpsilon)
+                    ++count;
+                if (bbox.maximum.y == vPos.y || vPos.y == bbox.minimum.y)
+                    ++count;
+                if (bbox.maximum.z == vPos.z || vPos.z == bbox.minimum.z)
+                    ++count;
+                if (count > 1) {
+                    ++gCount;
+                }
+                ;
+            });
+            if (gCount > 1) {
+                console.log(triangle, gCount);
+            }
+            return gCount > 1;
+        };
         QuadraticErrorSimplification.prototype.runDecimation = function (settings, successCallback) {
             var _this = this;
             var targetCount = ~~(this.triangles.length * settings.quality);
@@ -357,7 +446,7 @@ var BABYLON;
                 var s = this.references[vertex1.triangleStart + i].vertexId;
                 var id1 = t.vertices[(s + 1) % 3];
                 var id2 = t.vertices[(s + 2) % 3];
-                if ((id1 === index2 || id2 === index2) && borderFactor < 2) {
+                if ((id1 === index2 || id2 === index2)) {
                     deletedArray[i] = true;
                     delTr.push(t);
                     continue;

+ 109 - 1
Babylon/Mesh/babylon.meshSimplification.ts

@@ -29,6 +29,84 @@
         }
     }
 
+    export interface ISimplificationTask {
+        settings: Array<ISimplificationSettings>;
+        simplificationType: SimplificationType;
+        mesh: Mesh;
+        successCallback? : () => void;
+        submesh?: number;
+        parallelProcessing: boolean;
+    }
+    
+    export class SimplificationQueue {
+        private _simplificationArray: Array<ISimplificationTask>;
+        public running;
+
+        constructor() {
+            this.running = false;
+            this._simplificationArray = [];
+        }
+
+        public executeNext() {
+            var task = this._simplificationArray.pop();
+            if (task) {
+                this.running = true;
+                this.runSimplification(task);
+            } else {
+                this.running = false;
+            }
+        }
+
+        public runSimplification(task: ISimplificationTask) {
+            if (task.parallelProcessing) {
+                //parallel simplifier
+                task.settings.forEach((setting) => {
+                    var simplifier = this.getSimplifier(task);
+                    simplifier.simplify(setting,(newMesh) => {
+                        task.mesh.addLODLevel(setting.distance, newMesh);
+                        //check if it is the last
+                        if (setting.quality === task.settings[task.settings.length - 1].quality && task.successCallback) {
+                            //all done, run the success callback.
+                            task.successCallback();
+                        }
+                        this.executeNext();
+                    });
+                });
+            } else {
+                //single simplifier.
+                var simplifier = this.getSimplifier(task);
+
+                var runDecimation = (setting: ISimplificationSettings, callback: () => void) => {
+                    simplifier.simplify(setting,(newMesh) => {
+                        task.mesh.addLODLevel(setting.distance, newMesh);
+                        //run the next quality level
+                        callback();
+                    });
+                }
+
+                AsyncLoop.Run(task.settings.length,(loop: AsyncLoop) => {
+                    runDecimation(task.settings[loop.index],() => {
+                        loop.executeNext();
+                    });
+                },() => {
+                        //execution ended, run the success callback.
+                        if (task.successCallback) {
+                            task.successCallback();
+                        }
+                        this.executeNext();
+                    });
+            }
+        }
+
+        private getSimplifier(task: ISimplificationTask) : ISimplifier {
+            switch (task.simplificationType) {
+                case SimplificationType.QUADRATIC:
+                default:
+                    return new QuadraticErrorSimplification(task.mesh);
+            }
+        }
+    }
+
     /**
      * The implemented types of simplification.
      * At the moment only Quadratic Error Decimation is implemented.
@@ -144,9 +222,12 @@
         public aggressiveness: number;
         public decimationIterations: number;
 
+        public boundingBoxEpsilon: number;
+
         constructor(private _mesh: Mesh) {
             this.aggressiveness = 7;
             this.decimationIterations = 100;
+            this.boundingBoxEpsilon = Engine.Epsilon;
         }
 
         public simplify(settings: ISimplificationSettings, successCallback: (simplifiedMeshes: Mesh) => void) {
@@ -155,6 +236,33 @@
             });
         }
 
+        private isTriangleOnBoundingBox(triangle: DecimationTriangle): boolean {
+            var gCount = 0;
+            triangle.vertices.forEach((vId) => {
+                var count = 0;
+                var vPos = this.vertices[vId].position;
+                var bbox = this._mesh.getBoundingInfo().boundingBox;
+
+                if (bbox.maximum.x - vPos.x < this.boundingBoxEpsilon|| vPos.x - bbox.minimum.x > this.boundingBoxEpsilon)
+                    ++count;
+
+                if (bbox.maximum.y == vPos.y || vPos.y == bbox.minimum.y)
+                    ++count;
+
+                if (bbox.maximum.z == vPos.z || vPos.z == bbox.minimum.z)
+                    ++count;
+
+                if (count > 1) {
+                    ++gCount;
+                };
+            });
+            if (gCount > 1) {
+                console.log(triangle, gCount);
+            }
+            return gCount > 1;
+            
+        }
+
         private runDecimation(settings: ISimplificationSettings, successCallback: (simplifiedMeshes: Mesh) => void) {
             var targetCount = ~~(this.triangles.length * settings.quality);
             var deletedTriangles = 0;
@@ -427,7 +535,7 @@
                 var id1 = t.vertices[(s + 1) % 3];
                 var id2 = t.vertices[(s + 2) % 3];
 
-                if ((id1 === index2 || id2 === index2) && borderFactor < 2) {
+                if ((id1 === index2 || id2 === index2)/* && !this.isTriangleOnBoundingBox(t)*/) {
                     deletedArray[i] = true;
                     delTr.push(t);
                     continue;