David catuhe пре 10 година
родитељ
комит
c3756302b2

+ 2 - 1
Tools/Gulp/config.json

@@ -143,7 +143,8 @@
       "../../src/PostProcess/babylon.lensRenderingPipeline.js",
       "../../src/PostProcess/babylon.colorCorrectionPostProcess.js",
       "../../src/Cameras/babylon.stereoscopicCameras.js",
-      "../../src/PostProcess/babylon.hdrRenderingPipeline.js"
+      "../../src/PostProcess/babylon.hdrRenderingPipeline.js",
+      "../../src/Rendering/babylon.edgesRenderer.js"
     ]
   },
   "shadersDirectories": [

Разлика између датотеке није приказан због своје велике величине
+ 805 - 785
dist/preview release - beta/babylon.2.2.d.ts


Разлика између датотеке није приказан због своје велике величине
+ 25 - 29
dist/preview release - beta/babylon.2.2.js


Разлика између датотеке није приказан због своје велике величине
+ 157 - 2
dist/preview release - beta/babylon.2.2.max.js


Разлика између датотеке није приказан због своје велике величине
+ 28 - 32
dist/preview release - beta/babylon.2.2.noworker.js


+ 4 - 1
src/Animations/babylon.animation.js

@@ -10,6 +10,7 @@ var BABYLON;
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._stopped = false;
+            this.allowMatricesInterpolation = false;
             this.targetPropertyPath = targetProperty.split(".");
             this.dataType = dataType;
             this.loopMode = loopMode === undefined ? Animation.ANIMATIONLOOPMODE_CYCLE : loopMode;
@@ -187,7 +188,9 @@ var BABYLON;
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                // return this.matrixInterpolateFunction(startValue, endValue, gradient);
+                                    if (this.allowMatricesInterpolation) {
+                                        return this.matrixInterpolateFunction(startValue, endValue, gradient);
+                                    }
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
                                     return startValue;
                             }

+ 5 - 1
src/Animations/babylon.animation.ts

@@ -10,6 +10,8 @@
         public targetPropertyPath: string[];
         public currentFrame: number;
 
+        public allowMatricesInterpolation = false;
+
         public static CreateAndStartAnimation(name: string, mesh: AbstractMesh, targetProperty: string,
             framePerSecond: number, totalFrame: number,
             from: any, to: any, loopMode?: number, easingFunction?: EasingFunction) {
@@ -227,7 +229,9 @@
                             switch (loopMode) {
                                 case Animation.ANIMATIONLOOPMODE_CYCLE:
                                 case Animation.ANIMATIONLOOPMODE_CONSTANT:
-                                // return this.matrixInterpolateFunction(startValue, endValue, gradient);
+                                    if (this.allowMatricesInterpolation) {
+                                        return this.matrixInterpolateFunction(startValue, endValue, gradient);
+                                    }
                                 case Animation.ANIMATIONLOOPMODE_RELATIVE:
                                     return startValue;
                             }

+ 27 - 1
src/Mesh/babylon.abstractMesh.js

@@ -53,6 +53,10 @@ var BABYLON;
             this._oldPositionForCollisions = new BABYLON.Vector3(0, 0, 0);
             this._diffPositionForCollisions = new BABYLON.Vector3(0, 0, 0);
             this._newPositionForCollisions = new BABYLON.Vector3(0, 0, 0);
+            // Edges
+            this.edgesEpsilon = 0.95;
+            this.edgesWidth = 1.0;
+            this.edgesColor = BABYLON.Color3.Red();
             // Cache
             this._localScaling = BABYLON.Matrix.Zero();
             this._localRotation = BABYLON.Matrix.Zero();
@@ -123,9 +127,26 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        Object.defineProperty(AbstractMesh.prototype, "isBlocked", {
+        Object.defineProperty(AbstractMesh.prototype, "renderEdges", {
             // Methods
             get: function () {
+                return this._edgesRenderer !== undefined;
+            },
+            set: function (value) {
+                if (value && this._edgesRenderer === undefined) {
+                    this._edgesRenderer = new BABYLON.EdgesRenderer(this);
+                    return;
+                }
+                if (!value && this._edgesRenderer !== undefined) {
+                    this._edgesRenderer.dispose();
+                    this._edgesRenderer = undefined;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(AbstractMesh.prototype, "isBlocked", {
+            get: function () {
                 return false;
             },
             enumerable: true,
@@ -815,6 +836,11 @@ var BABYLON;
                 other._intersectionsInProgress.splice(pos, 1);
             }
             this._intersectionsInProgress = [];
+            // Edges
+            if (this._edgesRenderer) {
+                this._edgesRenderer.dispose();
+                this._edgesRenderer = null;
+            }
             // SubMeshes
             this.releaseSubMeshes();
             // Remove from scene

+ 28 - 0
src/Mesh/babylon.abstractMesh.ts

@@ -86,6 +86,12 @@
         // Attach to bone
         private _meshToBoneReferal: AbstractMesh;
 
+        // Edges
+        public edgesEpsilon = 0.95;
+        public edgesWidth = 1.0;
+        public edgesColor = Color3.Red();
+        public _edgesRenderer: EdgesRenderer;
+
         // Cache
         private _localScaling = Matrix.Zero();
         private _localRotation = Matrix.Zero();
@@ -128,6 +134,22 @@
         }
 
         // Methods
+        public get renderEdges(): boolean {
+            return this._edgesRenderer !== undefined;
+        }
+
+        public set renderEdges(value: boolean) {
+            if (value && this._edgesRenderer === undefined) {
+                this._edgesRenderer = new EdgesRenderer(this);
+                return;
+            }
+
+            if (!value && this._edgesRenderer !== undefined) {
+                this._edgesRenderer.dispose();
+                this._edgesRenderer = undefined;
+            }
+        }
+
         public get isBlocked(): boolean {
             return false;
         }
@@ -968,6 +990,12 @@
 
             this._intersectionsInProgress = [];
 
+            // Edges
+            if (this._edgesRenderer) {
+                this._edgesRenderer.dispose();
+                this._edgesRenderer = null;
+            }
+
             // SubMeshes
             this.releaseSubMeshes();
 

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

@@ -762,7 +762,7 @@
                 scene.getOutlineRenderer().render(subMesh, batch);
                 engine.setColorWrite(true);
             }
-
+            
             // Overlay
             if (this.renderOverlay) {
                 var currentMode = engine.getAlphaMode();

+ 125 - 0
src/Rendering/babylon.edgesRenderer.js

@@ -0,0 +1,125 @@
+var BABYLON;
+(function (BABYLON) {
+    var FaceAdjacencies = (function () {
+        function FaceAdjacencies() {
+            this.edges = new Array();
+            this.edgesConnectedCount = 0;
+        }
+        return FaceAdjacencies;
+    })();
+    var EdgesRenderer = (function () {
+        function EdgesRenderer(source) {
+            this._lines = new Array();
+            this._source = source;
+            this._material = new BABYLON.StandardMaterial(this._source.name + "EdgeMaterial", this._source.getScene());
+            this._material.emissiveColor = this._source.edgesColor;
+            this._material.diffuseColor = BABYLON.Color3.Black();
+            this._material.specularColor = BABYLON.Color3.Black();
+            this._generateEdgesLines();
+        }
+        EdgesRenderer.prototype.dispose = function () {
+            for (var index = 0; index < this._lines.length; index++) {
+                this._lines[index].dispose();
+            }
+            this._lines = new Array();
+        };
+        EdgesRenderer.prototype._processEdgeForAdjacencies = function (pa, pb, p0, p1, p2) {
+            if (pa === p0 && pb === p1 || pa === p1 && pb === p0) {
+                return 0;
+            }
+            if (pa === p1 && pb === p2 || pa === p2 && pb === p1) {
+                return 1;
+            }
+            if (pa === p2 && pb === p0 || pa === p0 && pb === p2) {
+                return 2;
+            }
+            return -1;
+        };
+        EdgesRenderer.prototype._checkEdge = function (faceIndex, edge, faceNormals, p0, p1) {
+            var needToCreateLine;
+            if (edge === undefined) {
+                needToCreateLine = true;
+            }
+            else {
+                var dotProduct = BABYLON.Vector3.Dot(faceNormals[faceIndex], faceNormals[edge]);
+                needToCreateLine = dotProduct < this._source.edgesEpsilon;
+            }
+            if (needToCreateLine) {
+                var scene = this._source.getScene();
+                var lineMesh = BABYLON.Mesh.CreateTube(this._source.name + "edge", [p0, p1], this._source.edgesWidth / 100.0, 5, null, BABYLON.Mesh.CAP_ALL, scene, false, BABYLON.Mesh.DEFAULTSIDE);
+                this._lines.push(lineMesh);
+            }
+        };
+        EdgesRenderer.prototype._generateEdgesLines = function () {
+            var positions = this._source.getVerticesData(BABYLON.VertexBuffer.PositionKind);
+            var indices = this._source.getIndices();
+            // First let's find adjacencies
+            var adjacencies = new Array();
+            var faceNormals = new Array();
+            var index;
+            var faceAdjacencies;
+            // Prepare faces
+            for (index = 0; index < indices.length; index += 3) {
+                faceAdjacencies = new FaceAdjacencies();
+                var p0Index = indices[index];
+                var p1Index = indices[index + 1];
+                var p2Index = indices[index + 2];
+                faceAdjacencies.p0 = new BABYLON.Vector3(positions[p0Index * 3], positions[p0Index * 3 + 1], positions[p0Index * 3 + 2]);
+                faceAdjacencies.p1 = new BABYLON.Vector3(positions[p1Index * 3], positions[p1Index * 3 + 1], positions[p1Index * 3 + 2]);
+                faceAdjacencies.p2 = new BABYLON.Vector3(positions[p2Index * 3], positions[p2Index * 3 + 1], positions[p2Index * 3 + 2]);
+                var faceNormal = BABYLON.Vector3.Cross(faceAdjacencies.p1.subtract(faceAdjacencies.p0), faceAdjacencies.p2.subtract(faceAdjacencies.p1));
+                faceNormal.normalize();
+                faceNormals.push(faceNormal);
+                adjacencies.push(faceAdjacencies);
+            }
+            // Scan
+            for (index = 0; index < adjacencies.length; index++) {
+                faceAdjacencies = adjacencies[index];
+                for (var otherIndex = index + 1; otherIndex < adjacencies.length; otherIndex++) {
+                    if (faceAdjacencies.edgesConnectedCount === 3) {
+                        break;
+                    }
+                    var otherP0 = indices[otherIndex * 3];
+                    var otherP1 = indices[otherIndex * 3 + 1];
+                    var otherP2 = indices[otherIndex * 3 + 2];
+                    for (var edgeIndex = 0; edgeIndex < 3; edgeIndex++) {
+                        var otherEdgeIndex;
+                        switch (edgeIndex) {
+                            case 0:
+                                otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3], indices[index * 3 + 1], otherP0, otherP1, otherP2);
+                                break;
+                            case 1:
+                                otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 1], indices[index * 3 + 2], otherP0, otherP1, otherP2);
+                                break;
+                            case 2:
+                                otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 2], indices[index * 3], otherP0, otherP1, otherP2);
+                                break;
+                        }
+                        if (otherEdgeIndex === -1) {
+                            continue;
+                        }
+                        faceAdjacencies.edges[edgeIndex] = otherIndex;
+                        adjacencies[otherIndex].edges[otherEdgeIndex] = index;
+                        faceAdjacencies.edgesConnectedCount++;
+                        adjacencies[otherIndex].edgesConnectedCount++;
+                    }
+                }
+            }
+            // Create lines
+            for (index = 0; index < adjacencies.length; index++) {
+                // We need a line when a face has no adjacency on a specific edge or if all the adjacencies has an angle greater than epsilon
+                var current = adjacencies[index];
+                this._checkEdge(index, current.edges[0], faceNormals, current.p0, current.p1);
+                this._checkEdge(index, current.edges[1], faceNormals, current.p1, current.p2);
+                this._checkEdge(index, current.edges[2], faceNormals, current.p2, current.p0);
+            }
+            // Merge into a single mesh
+            this._renderMesh = BABYLON.Mesh.MergeMeshes(this._lines, true, true);
+            this._renderMesh.parent = this._source;
+            this._renderMesh.material = this._material;
+            this._renderMesh.name = this._source.name + "edge";
+        };
+        return EdgesRenderer;
+    })();
+    BABYLON.EdgesRenderer = EdgesRenderer;
+})(BABYLON || (BABYLON = {}));

+ 157 - 0
src/Rendering/babylon.edgesRenderer.ts

@@ -0,0 +1,157 @@
+module BABYLON {
+
+    class FaceAdjacencies {
+        public edges = new Array<number>();
+        public p0: Vector3;
+        public p1: Vector3;
+        public p2: Vector3;
+        public edgesConnectedCount = 0;
+    }
+
+    export class EdgesRenderer {
+        private _source: AbstractMesh;
+        private _lines = new Array<Mesh>();
+        private _renderMesh: Mesh;
+        private _material: StandardMaterial;
+
+        constructor(source: AbstractMesh) {
+            this._source = source;
+
+            this._material = new StandardMaterial(this._source.name + "EdgeMaterial", this._source.getScene());
+            this._material.emissiveColor = this._source.edgesColor;
+            this._material.diffuseColor = Color3.Black();
+            this._material.specularColor = Color3.Black();
+
+            this._generateEdgesLines();
+        }
+
+        public dispose(): void {
+            for (var index = 0; index < this._lines.length; index++) {
+                this._lines[index].dispose();
+            }
+
+            this._lines = new Array<LinesMesh>();
+        }
+
+        private _processEdgeForAdjacencies(pa: number, pb: number, p0: number, p1: number, p2: number): number {
+            if (pa === p0 && pb === p1 || pa === p1 && pb === p0) {
+                return 0;
+            }
+
+            if (pa === p1 && pb === p2 || pa === p2 && pb === p1) {
+                return 1;
+            }
+
+            if (pa === p2 && pb === p0 || pa === p0 && pb === p2) {
+                return 2;
+            }
+
+            return -1;
+        }
+
+        private _checkEdge(faceIndex: number, edge: number, faceNormals: Array<Vector3>, p0: Vector3, p1: Vector3): void {
+            var needToCreateLine;
+
+            if (edge === undefined) {
+                needToCreateLine = true;
+            } else {
+                var dotProduct = Vector3.Dot(faceNormals[faceIndex], faceNormals[edge]);
+
+                needToCreateLine = dotProduct < this._source.edgesEpsilon;
+            }
+
+            if (needToCreateLine) {
+                var scene = this._source.getScene();
+                var lineMesh = BABYLON.Mesh.CreateTube(this._source.name + "edge", [p0, p1], this._source.edgesWidth / 100.0, 5, null, BABYLON.Mesh.CAP_ALL, scene, false, BABYLON.Mesh.DEFAULTSIDE);
+
+                this._lines.push(lineMesh);
+            }
+        }
+
+        _generateEdgesLines(): void {
+            var positions = this._source.getVerticesData(VertexBuffer.PositionKind);
+            var indices = this._source.getIndices();
+
+            // First let's find adjacencies
+            var adjacencies = new Array<FaceAdjacencies>();
+            var faceNormals = new Array<Vector3>();
+            var index: number;
+            var faceAdjacencies: FaceAdjacencies;
+
+            // Prepare faces
+            for (index = 0; index < indices.length; index += 3) {
+                faceAdjacencies = new FaceAdjacencies();
+                var p0Index = indices[index];
+                var p1Index = indices[index + 1];
+                var p2Index = indices[index + 2];
+
+                faceAdjacencies.p0 = new Vector3(positions[p0Index * 3], positions[p0Index * 3 + 1], positions[p0Index * 3 + 2]);
+                faceAdjacencies.p1 = new Vector3(positions[p1Index * 3], positions[p1Index * 3 + 1], positions[p1Index * 3 + 2]);
+                faceAdjacencies.p2 = new Vector3(positions[p2Index * 3], positions[p2Index * 3 + 1], positions[p2Index * 3 + 2]);
+                var faceNormal = Vector3.Cross(faceAdjacencies.p1.subtract(faceAdjacencies.p0), faceAdjacencies.p2.subtract(faceAdjacencies.p1));
+
+                faceNormal.normalize();
+
+                faceNormals.push(faceNormal);
+                adjacencies.push(faceAdjacencies);
+            }
+
+            // Scan
+            for (index = 0; index < adjacencies.length; index++) {
+                faceAdjacencies = adjacencies[index];
+
+                for (var otherIndex = index + 1; otherIndex < adjacencies.length; otherIndex++) {
+                    if (faceAdjacencies.edgesConnectedCount === 3) {
+                        break;
+                    }
+
+                    var otherP0 = indices[otherIndex * 3];
+                    var otherP1 = indices[otherIndex * 3 + 1];
+                    var otherP2 = indices[otherIndex * 3 + 2];
+
+                    for (var edgeIndex = 0; edgeIndex < 3; edgeIndex++) {
+                        var otherEdgeIndex: number;
+
+                        switch (edgeIndex) {
+                            case 0:
+                                otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3], indices[index * 3 + 1], otherP0, otherP1, otherP2);
+                                break;
+                            case 1:
+                                otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 1], indices[index * 3 + 2], otherP0, otherP1, otherP2);
+                                break;
+                            case 2:
+                                otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 2], indices[index * 3], otherP0, otherP1, otherP2);
+                                break;
+                        }
+
+                        if (otherEdgeIndex === -1) {
+                            continue;
+                        }
+
+                        faceAdjacencies.edges[edgeIndex] = otherIndex;
+                        adjacencies[otherIndex].edges[otherEdgeIndex] = index;
+
+                        faceAdjacencies.edgesConnectedCount++;
+                        adjacencies[otherIndex].edgesConnectedCount++;
+                    }
+                }
+            }
+            
+            // Create lines
+            for (index = 0; index < adjacencies.length; index++) {
+                // We need a line when a face has no adjacency on a specific edge or if all the adjacencies has an angle greater than epsilon
+                var current = adjacencies[index];
+
+                this._checkEdge(index, current.edges[0], faceNormals, current.p0, current.p1);
+                this._checkEdge(index, current.edges[1], faceNormals, current.p1, current.p2);
+                this._checkEdge(index, current.edges[2], faceNormals, current.p2, current.p0);
+            }
+
+            // Merge into a single mesh
+            this._renderMesh = Mesh.MergeMeshes(this._lines, true, true);
+            this._renderMesh.parent = this._source;
+            this._renderMesh.material = this._material;
+            this._renderMesh.name = this._source.name + "edge";
+        }
+    }
+}