瀏覽代碼

Merge pull request #4920 from sebavan/barteq100-master

Add EdgesLineRenderer
sebavan 7 年之前
父節點
當前提交
24ef54cf42

File diff suppressed because it is too large
+ 1104 - 1035
Playground/babylon.d.txt


+ 1 - 0
Tools/Gulp/config.json

@@ -1285,6 +1285,7 @@
             "files": [
                 "../../src/Rendering/babylon.outlineRenderer.js",
                 "../../src/Rendering/babylon.edgesRenderer.js",
+                "../../src/Rendering/babylon.lineEdgesRenderer.js",
                 "../../src/Layer/babylon.effectLayerSceneComponent.js",
                 "../../src/Layer/babylon.effectLayer.js",
                 "../../src/Layer/babylon.highlightLayer.js",

File diff suppressed because it is too large
+ 1104 - 1035
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 226 - 44
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 226 - 44
dist/preview release/babylon.no-module.max.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.worker.js


File diff suppressed because it is too large
+ 228 - 46
dist/preview release/es6.js


+ 2 - 41
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 4026,
+  "errors": 4019,
   "babylon.typedoc.json": {
-    "errors": 4026,
+    "errors": 4019,
     "AbstractMesh": {
       "Property": {
         "showBoundingBox": {
@@ -4700,35 +4700,6 @@
       }
     },
     "EdgesRenderer": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Constructor": {
-        "new EdgesRenderer": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "source": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "epsilon": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "checkVerticesInsteadOfIndices": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      },
       "Property": {
         "edgesWidthScalerForOrthographic": {
           "Comments": {
@@ -4742,16 +4713,6 @@
         }
       },
       "Method": {
-        "_generateEdgesLines": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "dispose": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "render": {
           "Comments": {
             "MissingText": true

+ 17 - 80
dist/preview release/viewer/babylon.viewer.d.ts

@@ -279,6 +279,14 @@ declare module BabylonViewer {
                 * Functions added to this observable will be executed on each frame rendered.
                 */
             readonly onFrameRenderedObservable: BABYLON.Observable<AbstractViewer>;
+            /**
+                * Observers registered here will be executed when VR more is entered.
+                */
+            readonly onEnteringVRObservable: BABYLON.Observable<AbstractViewer>;
+            /**
+                * Observers registered here will be executed when VR mode is exited.
+                */
+            readonly onExitingVRObservable: BABYLON.Observable<AbstractViewer>;
             observablesManager: ObservablesManager;
             /**
                 * The canvas associated with this viewer
@@ -374,7 +382,7 @@ declare module BabylonViewer {
                 */
             protected _configureObservers(observersConfiguration: IObserversConfiguration): void;
             /**
-                * Dispoe the entire viewer including the scene and the engine
+                * Dispose the entire viewer including the scene and the engine
                 */
             dispose(): void;
             /**
@@ -474,37 +482,6 @@ declare module BabylonViewer {
     export const telemetryManager: TelemetryManager;
 }
 declare module BabylonViewer {
-    /**
-        * An instance of the class is in charge of loading the model correctly.
-        * This class will continously be expended with tasks required from the specific loaders Babylon has.
-        *
-        * A Model loader is unique per (Abstract)Viewer. It is being generated by the viewer
-        */
-    export class ModelLoader {
-            readonly baseUrl: string;
-            /**
-                * Create a new Model loader
-                * @param _viewer the viewer using this model loader
-                */
-            constructor(_observablesManager: ObservablesManager, _configurationContainer?: ConfigurationContainer | undefined);
-            /**
-                * Adds a new plugin to the loader process.
-                *
-                * @param plugin the plugin name or the plugin itself
-                */
-            addPlugin(plugin: ILoaderPlugin | string): void;
-            /**
-                * Load a model using predefined configuration
-                * @param modelConfiguration the modelConfiguration to use to load the model
-                */
-            load(modelConfiguration: IModelConfiguration): ViewerModel;
-            cancelLoad(model: ViewerModel): void;
-            /**
-                * dispose the model loader.
-                * If loaders are registered and are in the middle of loading, they will be disposed and the request(s) will be cancelled.
-                */
-            dispose(): void;
-    }
 }
 declare module BabylonViewer {
     /**
@@ -1277,6 +1254,14 @@ declare module BabylonViewer {
                 * Functions added to this observable will be executed on each frame rendered.
                 */
             onFrameRenderedObservable: BABYLON.Observable<any>;
+            /**
+                * Will notify when VR mode is entered.
+                */
+            onEnteringVRObservable: BABYLON.Observable<any>;
+            /**
+                * Will notify when VR mode is exited.
+                */
+            onExitingVRObservable: BABYLON.Observable<any>;
             constructor();
             dispose(): void;
     }
@@ -1529,19 +1514,6 @@ declare module BabylonViewer {
     }
 }
 declare module BabylonViewer {
-    /**
-        * Get a loader plugin according to its name.
-        * The plugin will be cached and will be reused if called for again.
-        *
-        * @param name the name of the plugin
-        */
-    export function getLoaderPluginByName(name: string): ILoaderPlugin;
-    /**
-        *
-        */
-    export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
-}
-declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {
@@ -1677,41 +1649,6 @@ declare module BabylonViewer {
     }
 }
 declare module BabylonViewer {
-    export class TelemetryLoaderPlugin implements ILoaderPlugin {
-        onInit(loader: BABYLON.ISceneLoaderPlugin | BABYLON.ISceneLoaderPluginAsync, model: ViewerModel): void;
-        onLoaded(model: ViewerModel): void;
-        onError(message: string, exception: any): void;
-        onComplete(): void;
-    }
-}
-declare module BabylonViewer {
-    /**
-      * A loder plugin to use MSFT_lod extension correctly (glTF)
-      */
-    export class MSFTLodLoaderPlugin implements ILoaderPlugin {
-        onInit(loader: BABYLON.ISceneLoaderPlugin | BABYLON.ISceneLoaderPluginAsync, model: ViewerModel): void;
-        onExtensionLoaded(extension: BABYLON.IGLTFLoaderExtension): void;
-    }
-}
-declare module BabylonViewer {
-    /**
-      * Force-apply material configuration right after a material was loaded.
-      */
-    export class ApplyMaterialConfigPlugin implements ILoaderPlugin {
-        onInit(loader: BABYLON.ISceneLoaderPlugin | BABYLON.ISceneLoaderPluginAsync, model: ViewerModel): void;
-        onMaterialLoaded(material: BABYLON.Material): void;
-    }
-}
-declare module BabylonViewer {
-    /**
-      * A (PBR) material will be extended using this function.
-      * This function will hold extra default configuration for the viewer, if not implemented in Babylon itself.
-      */
-    export class ExtendedMaterialLoaderPlugin implements ILoaderPlugin {
-        onMaterialLoaded(baseMaterial: BABYLON.Material): void;
-    }
-}
-declare module BabylonViewer {
     export interface ICameraConfiguration {
         position?: {
             x: number;

File diff suppressed because it is too large
+ 2 - 2
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 4 - 4
dist/preview release/viewer/babylon.viewer.max.js


+ 18 - 108
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -321,6 +321,14 @@ declare module 'babylonjs-viewer/viewer/viewer' {
                 * Functions added to this observable will be executed on each frame rendered.
                 */
             readonly onFrameRenderedObservable: Observable<AbstractViewer>;
+            /**
+                * Observers registered here will be executed when VR more is entered.
+                */
+            readonly onEnteringVRObservable: Observable<AbstractViewer>;
+            /**
+                * Observers registered here will be executed when VR mode is exited.
+                */
+            readonly onExitingVRObservable: Observable<AbstractViewer>;
             observablesManager: ObservablesManager;
             /**
                 * The canvas associated with this viewer
@@ -416,7 +424,7 @@ declare module 'babylonjs-viewer/viewer/viewer' {
                 */
             protected _configureObservers(observersConfiguration: IObserversConfiguration): void;
             /**
-                * Dispoe the entire viewer including the scene and the engine
+                * Dispose the entire viewer including the scene and the engine
                 */
             dispose(): void;
             /**
@@ -519,42 +527,7 @@ declare module 'babylonjs-viewer/managers/telemetryManager' {
 }
 
 declare module 'babylonjs-viewer/loader/modelLoader' {
-    import { ConfigurationContainer } from 'babylonjs-viewer/configuration/configurationContainer';
-    import { IModelConfiguration } from 'babylonjs-viewer/configuration/interfaces/modelConfiguration';
-    import { ObservablesManager } from 'babylonjs-viewer/managers/observablesManager';
-    import { ViewerModel } from 'babylonjs-viewer/model/viewerModel';
-    import { ILoaderPlugin } from 'babylonjs-viewer/loader/plugins';
-    /**
-        * An instance of the class is in charge of loading the model correctly.
-        * This class will continously be expended with tasks required from the specific loaders Babylon has.
-        *
-        * A Model loader is unique per (Abstract)Viewer. It is being generated by the viewer
-        */
-    export class ModelLoader {
-            readonly baseUrl: string;
-            /**
-                * Create a new Model loader
-                * @param _viewer the viewer using this model loader
-                */
-            constructor(_observablesManager: ObservablesManager, _configurationContainer?: ConfigurationContainer | undefined);
-            /**
-                * Adds a new plugin to the loader process.
-                *
-                * @param plugin the plugin name or the plugin itself
-                */
-            addPlugin(plugin: ILoaderPlugin | string): void;
-            /**
-                * Load a model using predefined configuration
-                * @param modelConfiguration the modelConfiguration to use to load the model
-                */
-            load(modelConfiguration: IModelConfiguration): ViewerModel;
-            cancelLoad(model: ViewerModel): void;
-            /**
-                * dispose the model loader.
-                * If loaders are registered and are in the middle of loading, they will be disposed and the request(s) will be cancelled.
-                */
-            dispose(): void;
-    }
+    
 }
 
 declare module 'babylonjs-viewer/model/viewerModel' {
@@ -1364,6 +1337,14 @@ declare module 'babylonjs-viewer/managers/observablesManager' {
                 * Functions added to this observable will be executed on each frame rendered.
                 */
             onFrameRenderedObservable: Observable<any>;
+            /**
+                * Will notify when VR mode is entered.
+                */
+            onEnteringVRObservable: Observable<any>;
+            /**
+                * Will notify when VR mode is exited.
+                */
+            onExitingVRObservable: Observable<any>;
             constructor();
             dispose(): void;
     }
@@ -1626,26 +1607,6 @@ declare module 'babylonjs-viewer/configuration/interfaces/modelConfiguration' {
     }
 }
 
-declare module 'babylonjs-viewer/loader/plugins' {
-    import { TelemetryLoaderPlugin } from "babylonjs-viewer/loader/plugins/telemetryLoaderPlugin";
-    import { ILoaderPlugin } from "babylonjs-viewer/loader/plugins/loaderPlugin";
-    import { MSFTLodLoaderPlugin } from 'babylonjs-viewer/loader/plugins/msftLodLoaderPlugin';
-    import { ApplyMaterialConfigPlugin } from 'babylonjs-viewer/loader/plugins/applyMaterialConfig';
-    import { ExtendedMaterialLoaderPlugin } from 'babylonjs-viewer/loader/plugins/extendedMaterialLoaderPlugin';
-    export { TelemetryLoaderPlugin, ILoaderPlugin, MSFTLodLoaderPlugin, ApplyMaterialConfigPlugin, ExtendedMaterialLoaderPlugin };
-    /**
-        * Get a loader plugin according to its name.
-        * The plugin will be cached and will be reused if called for again.
-        *
-        * @param name the name of the plugin
-        */
-    export function getLoaderPluginByName(name: string): ILoaderPlugin;
-    /**
-        *
-        */
-    export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
-}
-
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';
@@ -1804,57 +1765,6 @@ declare module 'babylonjs-viewer/configuration/interfaces/modelAnimationConfigur
     }
 }
 
-declare module 'babylonjs-viewer/loader/plugins/telemetryLoaderPlugin' {
-    import { ILoaderPlugin } from "babylonjs-viewer/loader/plugins/loaderPlugin";
-    import { ViewerModel } from "babylonjs-viewer/model/viewerModel";
-    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs";
-    export class TelemetryLoaderPlugin implements ILoaderPlugin {
-        onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel): void;
-        onLoaded(model: ViewerModel): void;
-        onError(message: string, exception: any): void;
-        onComplete(): void;
-    }
-}
-
-declare module 'babylonjs-viewer/loader/plugins/msftLodLoaderPlugin' {
-    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync } from 'babylonjs';
-    import { IGLTFLoaderExtension } from 'babylonjs-loaders';
-    import { ViewerModel } from 'babylonjs-viewer/model/viewerModel';
-    import { ILoaderPlugin } from 'babylonjs-viewer/loader/plugins/loaderPlugin';
-    /**
-      * A loder plugin to use MSFT_lod extension correctly (glTF)
-      */
-    export class MSFTLodLoaderPlugin implements ILoaderPlugin {
-        onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel): void;
-        onExtensionLoaded(extension: IGLTFLoaderExtension): void;
-    }
-}
-
-declare module 'babylonjs-viewer/loader/plugins/applyMaterialConfig' {
-    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material } from 'babylonjs';
-    import { ViewerModel } from 'babylonjs-viewer/model/viewerModel';
-    import { ILoaderPlugin } from 'babylonjs-viewer/loader/plugins/loaderPlugin';
-    /**
-      * Force-apply material configuration right after a material was loaded.
-      */
-    export class ApplyMaterialConfigPlugin implements ILoaderPlugin {
-        onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel): void;
-        onMaterialLoaded(material: Material): void;
-    }
-}
-
-declare module 'babylonjs-viewer/loader/plugins/extendedMaterialLoaderPlugin' {
-    import { Material } from 'babylonjs';
-    import { ILoaderPlugin } from 'babylonjs-viewer/loader/plugins/loaderPlugin';
-    /**
-      * A (PBR) material will be extended using this function.
-      * This function will hold extra default configuration for the viewer, if not implemented in Babylon itself.
-      */
-    export class ExtendedMaterialLoaderPlugin implements ILoaderPlugin {
-        onMaterialLoaded(baseMaterial: Material): void;
-    }
-}
-
 declare module 'babylonjs-viewer/configuration/interfaces/cameraConfiguration' {
     export interface ICameraConfiguration {
         position?: {

+ 1 - 0
dist/preview release/what's new.md

@@ -49,6 +49,7 @@
 - All NPM packages have `latest`and `preview` streams [#3055](https://github.com/BabylonJS/Babylon.js/issues/3055) ([RaananW](https://github.com/RaananW))
 - Added New Tools Tab in the inspector (env texture and screenshot tools so far) ([sebavan](http://www.github.com/sebavan))
 - Moved to gulp 4, updated dependencies to latest ([RaananW](https://github.com/RaananW))
+- Added EdgesLineRenderer to address [#4919](https://github.com/BabylonJS/Babylon.js/pull/4919) ([barteq100](https://github.com/barteq100))
 
 ### GUI
 - Added dead key support and before key add observable to InputText. [Doc](https://doc.babylonjs.com/how_to/gui#using-onbeforekeyaddobservable-for-extended-keyboard-layouts-and-input-masks)([theom](https://github.com/theom))

+ 14 - 0
src/Mesh/babylon.linesMesh.ts

@@ -139,5 +139,19 @@
         public clone(name: string, newParent?: Node, doNotCloneChildren?: boolean): LinesMesh {
             return new LinesMesh(name, this.getScene(), newParent, this, doNotCloneChildren);
         }
+
+        /**
+         * Enables the edge rendering mode on the mesh.
+         * This mode makes the mesh edges visible
+         * @param epsilon defines the maximal distance between two angles to detect a face
+         * @param checkVerticesInsteadOfIndices indicates that we should check vertex list directly instead of faces
+         * @returns the currentAbstractMesh
+         * @see https://www.babylonjs-playground.com/#19O9TU#0
+         */
+        public enableEdgesRendering(epsilon = 0.95, checkVerticesInsteadOfIndices = false): AbstractMesh {
+            this.disableEdgesRendering();
+            this._edgesRenderer = new LineEdgesRenderer(this, epsilon, checkVerticesInsteadOfIndices);
+            return this;
+        }
     }
 } 

+ 49 - 19
src/Rendering/babylon.edgesRenderer.ts

@@ -1,5 +1,7 @@
 module BABYLON {
-
+    /**
+     * FaceAdjacencies Helper class to generate edges
+     */
     class FaceAdjacencies {
         public edges = new Array<number>();
         public p0: Vector3;
@@ -8,36 +10,48 @@
         public edgesConnectedCount = 0;
     }
 
+    /**
+     * This class is used to generate edges of the mesh that could then easily be rendered in a scene.
+     */
     export class EdgesRenderer {
         public edgesWidthScalerForOrthographic = 1000.0;
         public edgesWidthScalerForPerspective = 50.0;
-        private _source: AbstractMesh;
-        private _linesPositions = new Array<number>();
-        private _linesNormals = new Array<number>();
-        private _linesIndices = new Array<number>();
-        private _epsilon: number;
-        private _indicesCount: number;
-
-        private _lineShader: ShaderMaterial;
-        private _ib: WebGLBuffer;
-        private _buffers: { [key: string]: Nullable<VertexBuffer> } = {};
-        private _checkVerticesInsteadOfIndices = false;
+        protected _source: AbstractMesh;
+        protected _linesPositions = new Array<number>();
+        protected _linesNormals = new Array<number>();
+        protected _linesIndices = new Array<number>();
+        protected _epsilon: number;
+        protected _indicesCount: number;
+
+        protected _lineShader: ShaderMaterial;
+        protected _ib: WebGLBuffer;
+        protected _buffers: { [key: string]: Nullable<VertexBuffer> } = {};
+        protected _checkVerticesInsteadOfIndices = false;
 
         /** Gets or sets a boolean indicating if the edgesRenderer is active */
         public isEnabled = true;
 
-        // Beware when you use this class with complex objects as the adjacencies computation can be really long
-        constructor(source: AbstractMesh, epsilon = 0.95, checkVerticesInsteadOfIndices = false) {
+        /**
+         * Creates an instance of the EdgesRenderer. It is primarily use to display edges of a mesh.
+         * Beware when you use this class with complex objects as the adjacencies computation can be really long
+         * @param  source Mesh used to create edges
+         * @param  epsilon sum of angles in adjacency to check for edge
+         * @param  checkVerticesInsteadOfIndices
+         * @param  generateEdgesLines - should generate Lines or only prepare resources.
+         */
+        constructor(source: AbstractMesh, epsilon = 0.95, checkVerticesInsteadOfIndices = false, generateEdgesLines = true) {
             this._source = source;
             this._checkVerticesInsteadOfIndices = checkVerticesInsteadOfIndices;
 
             this._epsilon = epsilon;
 
             this._prepareRessources();
-            this._generateEdgesLines();
+            if(generateEdgesLines) {
+                this._generateEdgesLines();
+            }
         }
 
-        private _prepareRessources(): void {
+        protected _prepareRessources(): void {
             if (this._lineShader) {
                 return;
             }
@@ -69,6 +83,9 @@
             this._ib = engine.createIndexBuffer(this._linesIndices);
         }
 
+        /**
+         * Releases the required resources for the edges renderer
+         */
         public dispose(): void {
 
             var buffer = this._buffers[VertexBuffer.PositionKind];
@@ -86,7 +103,7 @@
             this._lineShader.dispose();
         }
 
-        private _processEdgeForAdjacencies(pa: number, pb: number, p0: number, p1: number, p2: number): number {
+        protected _processEdgeForAdjacencies(pa: number, pb: number, p0: number, p1: number, p2: number): number {
             if (pa === p0 && pb === p1 || pa === p1 && pb === p0) {
                 return 0;
             }
@@ -102,7 +119,7 @@
             return -1;
         }
 
-        private _processEdgeForAdjacenciesWithVertices(pa: Vector3, pb: Vector3, p0: Vector3, p1: Vector3, p2: Vector3): number {
+        protected _processEdgeForAdjacenciesWithVertices(pa: Vector3, pb: Vector3, p0: Vector3, p1: Vector3, p2: Vector3): number {
             if (pa.equalsWithEpsilon(p0) && pb.equalsWithEpsilon(p1) || pa.equalsWithEpsilon(p1) && pb.equalsWithEpsilon(p0)) {
                 return 0;
             }
@@ -118,7 +135,16 @@
             return -1;
         }
 
-        private _checkEdge(faceIndex: number, edge: number, faceNormals: Array<Vector3>, p0: Vector3, p1: Vector3): void {
+        /**
+         * Checks if the pair of p0 and p1 is en edge
+         * @param faceIndex
+         * @param edge
+         * @param faceNormals
+         * @param  p0
+         * @param  p1
+         * @private
+         */
+        protected _checkEdge(faceIndex: number, edge: number, faceNormals: Array<Vector3>, p0: Vector3, p1: Vector3): void {
             var needToCreateLine;
 
             if (edge === undefined) {
@@ -182,6 +208,10 @@
             }
         }
 
+        /**
+         * Generates lines edges from adjacencjes
+         * @private
+         */
         _generateEdgesLines(): void {
             var positions = this._source.getVerticesData(VertexBuffer.PositionKind);
             var indices = this._source.getIndices();

+ 127 - 0
src/Rendering/babylon.lineEdgesRenderer.ts

@@ -0,0 +1,127 @@
+module BABYLON {
+    /**
+     * FaceAdjacencies Helper class to generate edges
+     */
+    class FaceAdjacencies {
+        public edges = new Array<number>();
+        public p0: Vector3;
+        public p1: Vector3;
+        public edgesConnectedCount = 0;
+    }
+
+    /**
+     * LineEdgesRenderer for LineMeshes to remove unnecessary triangulation
+     */
+    export class LineEdgesRenderer extends EdgesRenderer {
+
+        /**
+         * This constructor turns off auto generating edges line in Edges Renderer to make it here.
+         * @param  source LineMesh used to generate edges
+         * @param  epsilon not important (specified angle for edge detection)
+         * @param  checkVerticesInsteadOfIndices not important for LineMesh
+         */
+        constructor(source: AbstractMesh, epsilon = 0.95, checkVerticesInsteadOfIndices = false) {
+                super(source, epsilon, checkVerticesInsteadOfIndices, false);
+                this._generateEdgesLines();
+        }
+
+        /**
+         * Always create the edge since its a line so only important things are p0 and p1
+         * @param  faceIndex not important for LineMesh
+         * @param  edge not important for LineMesh
+         * @param  faceNormals not important for LineMesh
+         * @param  p0 beginnig of line
+         * @param  p1 end of line
+         */
+        protected _checkEdge(faceIndex: number, edge: number, faceNormals: Array<Vector3>, p0: Vector3, p1: Vector3): void {
+                var offset = this._linesPositions.length / 3;
+                var normal = p0.subtract(p1);
+                normal.normalize();
+
+                // Positions
+                this._linesPositions.push(p0.x);
+                this._linesPositions.push(p0.y);
+                this._linesPositions.push(p0.z);
+
+                this._linesPositions.push(p0.x);
+                this._linesPositions.push(p0.y);
+                this._linesPositions.push(p0.z);
+
+                this._linesPositions.push(p1.x);
+                this._linesPositions.push(p1.y);
+                this._linesPositions.push(p1.z);
+
+                this._linesPositions.push(p1.x);
+                this._linesPositions.push(p1.y);
+                this._linesPositions.push(p1.z);
+
+                // Normals
+                this._linesNormals.push(p1.x);
+                this._linesNormals.push(p1.y);
+                this._linesNormals.push(p1.z);
+                this._linesNormals.push(-1);
+
+                this._linesNormals.push(p1.x);
+                this._linesNormals.push(p1.y);
+                this._linesNormals.push(p1.z);
+                this._linesNormals.push(1);
+
+                this._linesNormals.push(p0.x);
+                this._linesNormals.push(p0.y);
+                this._linesNormals.push(p0.z);
+                this._linesNormals.push(-1);
+
+                this._linesNormals.push(p0.x);
+                this._linesNormals.push(p0.y);
+                this._linesNormals.push(p0.z);
+                this._linesNormals.push(1);
+
+                // Indices
+                this._linesIndices.push(offset);
+                this._linesIndices.push(offset + 1);
+                this._linesIndices.push(offset + 2);
+                this._linesIndices.push(offset);
+                this._linesIndices.push(offset + 2);
+                this._linesIndices.push(offset + 3);
+        }
+
+        /**
+         * Generate edges for each line in LinesMesh. Every Line should be rendered as edge.
+         */
+        _generateEdgesLines(): void {
+            var positions = this._source.getVerticesData(VertexBuffer.PositionKind);
+            var indices = this._source.getIndices();
+
+            if (!indices || !positions) {
+                return;
+            }
+
+            // First let's find adjacencies
+            var adjacencies = new Array<FaceAdjacencies>();
+            var faceNormals = new Array<Vector3>();
+            var index: number;
+            for(let i=0; i<(positions.length / 3) - 1 ; i++){
+                const currentAdjecancy  = new FaceAdjacencies();
+                currentAdjecancy.p0 = new Vector3(positions[i*3], positions[i*3+1], positions[i*3+2]);
+                currentAdjecancy.p1 = new Vector3(positions[(i+1)*3], positions[(i+1)*3 + 1], positions[(i+1)*3 + 2]);
+                adjacencies.push(currentAdjecancy);
+            }
+            // 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);
+            }
+
+            // Merge into a single mesh
+            var engine = this._source.getScene().getEngine();
+
+            this._buffers[VertexBuffer.PositionKind] = new VertexBuffer(engine, this._linesPositions, VertexBuffer.PositionKind, false);
+            this._buffers[VertexBuffer.NormalKind] = new VertexBuffer(engine, this._linesNormals, VertexBuffer.NormalKind, false, false, 4);
+
+            this._ib = engine.createIndexBuffer(this._linesIndices);
+
+            this._indicesCount = this._linesIndices.length;
+        }
+    }
+}