Prechádzať zdrojové kódy

Merge pull request #3594 from kcoley/kcoley/refactorGLTFSerializer

refactor glTF serializer to use glTF interface declaration.
David Catuhe 7 rokov pred
rodič
commit
699084bcd8

+ 23 - 20
dist/babylon.glTFInterface.d.ts

@@ -1,5 +1,8 @@
 declare module BABYLON.GLTF2 {
-    enum AccessorType {
+    /**
+     * Specifies if the attribute is a scalar, vector, or matrix.
+     */
+    const enum AccessorType {
         SCALAR = "SCALAR",
         VEC2 = "VEC2",
         VEC3 = "VEC3",
@@ -8,22 +11,22 @@ declare module BABYLON.GLTF2 {
         MAT3 = "MAT3",
         MAT4 = "MAT4",
     }
-    enum MaterialAlphaMode {
+    const enum MaterialAlphaMode {
         OPAQUE = "OPAQUE",
         MASK = "MASK",
         BLEND = "BLEND",
     }
-    enum AnimationChannelTargetPath {
+    const enum AnimationChannelTargetPath {
         TRANSLATION = "translation",
         ROTATION = "rotation",
         SCALE = "scale",
         WEIGHTS = "weights",
     }
-    enum CameraType {
+    const enum CameraType {
         PERSPECTIVE = "perspective",
         ORTHOGRAPHIC = "orthographic",
     }
-    enum AccessorComponentType {
+    const enum AccessorComponentType {
         BYTE = 5120,
         UNSIGNED_BYTE = 5121,
         SHORT = 5122,
@@ -31,12 +34,12 @@ declare module BABYLON.GLTF2 {
         UNSIGNED_INT = 5125,
         FLOAT = 5126,
     }
-    enum AnimationInterpolation {
+    const enum AnimationInterpolation {
         LINEAR = "LINEAR",
         STEP = "STEP",
         CUBICSPLINE = "CUBICSPLINE",
     }
-    enum MeshPrimitiveMode {
+    const enum MeshPrimitiveMode {
         POINTS = 0,
         LINES = 1,
         LINE_LOOP = 2,
@@ -45,15 +48,15 @@ declare module BABYLON.GLTF2 {
         TRIANGLE_STRIP = 5,
         TRIANGLE_FAN = 6,
     }
-    enum ImageMimeType {
+    const enum ImageMimeType {
         JPEG = "image/jpeg",
         PNG = "image/png",
     }
-    enum TextureMagFilter {
+    const enum TextureMagFilter {
         NEAREST = 9728,
         LINEAR = 9729,
     }
-    enum TextureMinFilter {
+    const enum TextureMinFilter {
         NEAREST = 9728,
         LINEAR = 9729,
         NEAREST_MIPMAP_NEAREST = 9984,
@@ -61,7 +64,7 @@ declare module BABYLON.GLTF2 {
         NEAREST_MIPMAP_LINEAR = 9986,
         LINEAR_MIPMAP_LINEAR = 9987,
     }
-    enum TextureWrapMode {
+    const enum TextureWrapMode {
         CLAMP_TO_EDGE = 33071,
         MIRRORED_REPEAT = 33648,
         REPEAT = 10497,
@@ -96,8 +99,8 @@ declare module BABYLON.GLTF2 {
         normalized?: boolean;
         count: number;
         type: AccessorType;
-        max: number[];
-        min: number[];
+        max?: number[];
+        min?: number[];
         sparse?: IAccessorSparse;
     }
     interface IAnimationChannel extends IProperty {
@@ -156,17 +159,17 @@ declare module BABYLON.GLTF2 {
         bufferView?: number;
     }
     interface IMaterialNormalTextureInfo extends ITextureInfo {
-        scale: number;
+        scale?: number;
     }
     interface IMaterialOcclusionTextureInfo extends ITextureInfo {
-        strength: number;
+        strength?: number;
     }
     interface IMaterialPbrMetallicRoughness {
-        baseColorFactor: number[];
-        baseColorTexture: ITextureInfo;
-        metallicFactor: number;
-        roughnessFactor: number;
-        metallicRoughnessTexture: ITextureInfo;
+        baseColorFactor?: number[];
+        baseColorTexture?: ITextureInfo;
+        metallicFactor?: number;
+        roughnessFactor?: number;
+        metallicRoughnessTexture?: ITextureInfo;
     }
     interface IMaterial extends IChildRootProperty {
         pbrMetallicRoughness?: IMaterialPbrMetallicRoughness;

+ 2 - 2
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -40,7 +40,7 @@ module BABYLON.GLTF2 {
     }
 
     export class GLTFLoader implements IGLTFLoader {
-        public _gltf: IGLTF;
+        public _gltf: _IGLTF;
         public _babylonScene: Scene;
 
         private _disposed = false;
@@ -182,7 +182,7 @@ module BABYLON.GLTF2 {
         }
 
         private _loadData(data: IGLTFLoaderData): void {
-            this._gltf = <IGLTF>data.json;
+            this._gltf = <_IGLTF>data.json;
 
             // Assign the index of each object for convinience.
             GLTFLoader._AssignIndices(this._gltf.accessors);

+ 1 - 1
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -284,7 +284,7 @@ module BABYLON.GLTF2 {
         texCoord?: number;
     }
 
-    export interface IGLTF extends IGLTFProperty {
+    export interface _IGLTF extends IGLTFProperty {
         accessors?: IGLTFAccessor[];
         animations?: IGLTFAnimation[];
         asset: IGLTFAsset;

+ 21 - 5
serializers/src/glTF/2.0/babylon.glTFData.ts

@@ -1,26 +1,36 @@
+/// <reference path="../../../../dist/babylon.glTFInterface.d.ts"/>
+
 module BABYLON {
     /**
      * Class for holding and downloading glTF file data
      */
     export class _GLTFData {
+        /**
+         * Object which contains the file name as the key and its data as the value.
+         */
         glTFFiles: { [fileName: string]: string | Blob };
 
+        /**
+         * Initializes the glTF file object.
+         */
         public constructor() {
             this.glTFFiles = {};
         }
+
         /**
-         * Downloads glTF data.
+         * Downloads the glTF data as files based on their names and data.
          */
         public downloadFiles(): void {
             /**
-            * Checks for a matching suffix at the end of a string (for ES5 and lower)
-            * @param str 
-            * @param suffix 
-            * @returns - indicating whether the suffix matches or not
+            * Checks for a matching suffix at the end of a string (for ES5 and lower).
+            * @param str - Source string.
+            * @param suffix - Suffix to search for in the source string.
+            * @returns - Boolean indicating whether the suffix was found (true) or not (false).
             */
             function endsWith(str: string, suffix: string): boolean {
                 return str.indexOf(suffix, str.length - suffix.length) !== -1;
             }
+
             for (let key in this.glTFFiles) {
                 let link = document.createElement('a');
                 document.body.appendChild(link);
@@ -38,6 +48,12 @@ module BABYLON {
                 else if (endsWith(key, ".gltf")) {
                     mimeType = { type: "model/gltf+json" };
                 }
+                else if (endsWith(key, ".jpeg" || ".jpg")) {
+                    mimeType = {type: GLTF2.ImageMimeType.JPEG};
+                }
+                else if (endsWith(key, ".png")) {
+                    mimeType = {type: GLTF2.ImageMimeType.PNG};
+                }
 
                 link.href = window.URL.createObjectURL(new Blob([blob], mimeType));
                 link.click();

+ 105 - 268
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -1,226 +1,83 @@
-module BABYLON {
-    /**
-     * glTF Asset interface
-     */
-    interface _IGLTFAsset {
-        generator: string;
-        version: string;
-    }
-
-    /**
-     * glTF Scene interface
-     */
-    interface _IGLTFScene {
-        nodes: number[];
-    }
-
-    /**
-     * glTF Node interface
-     */
-    interface _IGLTFNode {
-        mesh: number;
-        name?: string;
-        translation?: number[];
-        scale?: number[];
-        rotation?: number[];
-    }
-
-    /**
-     * glTF Mesh Primitive interface
-     */
-    interface _IGLTFMeshPrimitive {
-        attributes: { [index: string]: number };
-        indices?: number;
-        material?: number;
-    }
-
-    /**
-     * glTF Texture interface
-     */
-    interface _IGLTFTexture {
-        name?: string;
-        sampler?: number;
-        source: number;
-    }
-
-    /**
-     * glTF texture info interface
-     */
-    interface _IGLTFTextureInfo {
-        index: number;
-        texCoord?: number;
-    }
-
-    /**
-     * glTF Image mimetype enum
-     */
-    enum _EGLTFImageMimeTypeEnum {
-        PNG = "image/png",
-        JPG = "image/jpeg"
-    }
-
-    /**
-     * glTF Image interface
-     */
-    interface _IGLTFImage {
-        name?: string;
-        uri?: string;
-        bufferView?: number;
-        mimeType?: _EGLTFImageMimeTypeEnum;
-    }
-
-    /**
-     * glTF Mesh interface
-     */
-    interface _IGLTFMesh {
-        primitives: _IGLTFMeshPrimitive[];
-    }
-
-    /**
-     * glTF Alpha Mode Enum
-     */
-    export enum _EGLTFAlphaModeEnum {
-        OPAQUE = "OPAQUE",
-        MASK = "MASK",
-        BLEND = "BLEND"
-    }
-    
-    /**
-     * glTF Occlusion texture interface
-     */
-    interface _IGLTFOcclusionTexture extends _IGLTFTextureInfo {
-        strength?: number;
-    }
+/// <reference path="../../../../dist/babylon.glTFInterface.d.ts"/>
 
+/**
+ * Module for the Babylon glTF 2.0 exporter.  Should ONLY be used internally.
+ * @ignore - capitalization of GLTF2 module.
+ */
+module BABYLON.GLTF2 {
     /**
-     * glTF Normal texture interface
+     * Converts Babylon Scene into glTF 2.0.
      */
-    interface _IGLTFNormalTexture extends _IGLTFTextureInfo {
-        scale?: number;
-    }
-
-    /**
-     * glTF Material interface
-     */
-    interface _IGLTFMaterial {
-        name?: string;
-        doubleSided?: boolean;
-        alphaMode?: string;
-        alphaCutoff?: number;
-        emissiveTexture?: _IGLTFTextureInfo;
-        emissiveFactor?: number[];
-        occlusionTexture?: _IGLTFOcclusionTexture;
-        normalTexture?: _IGLTFNormalTexture;
-        pbrMetallicRoughness?: _IGLTFPBRMetallicRoughnessMaterial;
-    }
-
-    /**
-     * glTF Metallic Roughness Material interface
-     */
-    interface _IGLTFPBRMetallicRoughnessMaterial {
-        baseColorFactor?: number[];
-        baseColorTexture?: _IGLTFTextureInfo;
-        metallicFactor?: number;
-        roughnessFactor?: number;
-        metallicRoughnessTexture?: _IGLTFTexture;
-    }
-
-    /**
-     * glTF Buffer interface
-     */
-    interface _IGLTFBuffer {
-        byteLength: number;
-        uri?: string;
-    }
-
-    /**
-     * glTF BufferView interface
-     */
-    interface _IGLTFBufferView {
-        name?: string;
-        buffer: number;
-        byteOffset?: number;
-        byteLength: number;
-    }
-
-    /**
-     * glTF Accessor interface
-     */
-    interface _IGLTFAccessor {
-        name: string;
-        bufferView: number;
-        componentType: number;
-        count: number;
-        type: string;
-        min?: number[];
-        max?: number[];
-    }
-
-    /**
-     * glTF file interface
-     */
-    interface _IGLTF {
-        buffers?: _IGLTFBuffer[];
-        asset: _IGLTFAsset;
-        meshes?: _IGLTFMesh[];
-        materials?: _IGLTFMaterial[];
-        scenes?: _IGLTFScene[];
-        scene?: number;
-        nodes?: _IGLTFNode[];
-        bufferViews?: _IGLTFBufferView[];
-        accessors?: _IGLTFAccessor[];
-        textures?: _IGLTFTexture[];
-        images?: _IGLTFImage[];
-    }
-
-    /**
-     * Babylon Specular Glossiness interface
-     */
-    export interface _IBabylonSpecularGlossiness {
-        diffuse: Color3;
-        opacity: number;
-        specular: Color3;
-        glossiness: number;
-    }
-
-    /**
-     * Babylon Metallic Roughness interface
-     */
-    export interface _IBabylonMetallicRoughness {
-        baseColor: Color3;
-        opacity: number;
-        metallic: number;
-        roughness: number;
-    }
-
-    /**
-     * Converts Babylon Scene into glTF 2.0
-     */
-    export class _GLTF2Exporter {
-        private bufferViews: _IGLTFBufferView[];
-        private accessors: _IGLTFAccessor[];
-        private nodes: _IGLTFNode[];
-        private asset: _IGLTFAsset;
-        private scenes: _IGLTFScene[];
-        private meshes: _IGLTFMesh[];
-        private materials: _IGLTFMaterial[];
-        private textures: _IGLTFTexture[];
-        private images: _IGLTFImage[];
+    export class _Exporter {
+        /**
+         * Stores all generated buffer views, which represents views into the main glTF buffer data.
+         */
+        private bufferViews: IBufferView[];
+        /**
+         * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF.
+         */
+        private accessors: IAccessor[];
+        /**
+         * Stores all the generated nodes, which contains transform and/or mesh information per node.
+         */
+        private nodes: INode[];
+        /**
+         * Stores the glTF asset information, which represents the glTF version and this file generator.
+         */
+        private asset: IAsset;
+        /**
+         * Stores all the generated glTF scenes, which stores multiple node hierarchies.
+         */
+        private scenes: IScene[];
+        /**
+         * Stores all the generated mesh information, each containing a set of primitives to render in glTF.
+         */
+        private meshes: IMesh[];
+        /**
+         * Stores all the generated material information, which represents the appearance of each primitive.
+         */
+        private materials: IMaterial[];
+        /**
+         * Stores all the generated texture information, which is referenced by glTF materials.
+         */
+        private textures: ITexture[];
+        /**
+         * Stores all the generated image information, which is referenced by glTF textures.
+         */
+        private images: IImage[];
+        /**
+         * Stores the total amount of bytes stored in the glTF buffer.
+         */
         private totalByteLength: number;
+        /**
+         * Stores a reference to the Babylon scene containing the source geometry and material information.
+         */
         private babylonScene: Scene;
-        private options?: IGLTFExporterOptions;
-        private imageData: { [fileName: string]: { data: Uint8Array, mimeType: _EGLTFImageMimeTypeEnum } };
+        /**
+         * Stores the exporter options, which are optionally passed in from the glTF serializer.
+         */
+        private options?: IExporterOptions;
+        /**
+         * Stores a map of the image data, where the key is the file name and the value
+         * is the image data.
+         */
+        private imageData: { [fileName: string]: { data: Uint8Array, mimeType: ImageMimeType } };
 
-        public constructor(babylonScene: Scene, options?: IGLTFExporterOptions) {
+        /**
+         * Creates a glTF Exporter instance, which can accept optional exporter options.
+         * @param babylonScene - Babylon scene object
+         * @param options - Options to modify the behavior of the exporter.
+         */
+        public constructor(babylonScene: Scene, options?: IExporterOptions) {
             this.asset = { generator: "BabylonJS", version: "2.0" };
             this.babylonScene = babylonScene;
-            this.bufferViews = new Array<_IGLTFBufferView>();
-            this.accessors = new Array<_IGLTFAccessor>();
-            this.meshes = new Array<_IGLTFMesh>();
-            this.scenes = new Array<_IGLTFScene>();
-            this.nodes = new Array<_IGLTFNode>();
-            this.images = new Array<_IGLTFImage>();
-            this.materials = new Array<_IGLTFMaterial>();
+            this.bufferViews = new Array<IBufferView>();
+            this.accessors = new Array<IAccessor>();
+            this.meshes = new Array<IMesh>();
+            this.scenes = new Array<IScene>();
+            this.nodes = new Array<INode>();
+            this.images = new Array<IImage>();
+            this.materials = new Array<IMaterial>();
             this.imageData = {};
             if (options !== undefined) {
                 this.options = options;
@@ -240,8 +97,8 @@ module BABYLON {
          * @param {number} byteLength - byte length of the bufferView
          * @returns - bufferView for glTF
          */
-        private createBufferView(bufferIndex: number, byteOffset: number, byteLength: number, name?: string): _IGLTFBufferView {
-            let bufferview: _IGLTFBufferView = { buffer: bufferIndex, byteLength: byteLength };
+        private createBufferView(bufferIndex: number, byteOffset: number, byteLength: number, name?: string): IBufferView {
+            let bufferview: IBufferView = { buffer: bufferIndex, byteLength: byteLength };
             if (byteOffset > 0) {
                 bufferview.byteOffset = byteOffset;
             }
@@ -263,8 +120,8 @@ module BABYLON {
          * @param max 
          * @returns - accessor for glTF 
          */
-        private createAccessor(bufferviewIndex: number, name: string, type: string, componentType: number, count: number, min?: number[], max?: number[]): _IGLTFAccessor {
-            let accessor: _IGLTFAccessor = { name: name, bufferView: bufferviewIndex, componentType: componentType, count: count, type: type };
+        private createAccessor(bufferviewIndex: number, name: string, type: AccessorType, componentType: AccessorComponentType, count: number, min?: number[], max?: number[]): IAccessor {
+            let accessor: IAccessor = { name: name, bufferView: bufferviewIndex, componentType: componentType, count: count, type: type };
 
             if (min) {
                 accessor.min = min;
@@ -435,9 +292,9 @@ module BABYLON {
          * @returns - json data as string
          */
         private generateJSON(glb: boolean, glTFPrefix?: string, prettyPrint?: boolean): string {
-            let buffer: _IGLTFBuffer = { byteLength: this.totalByteLength };
+            let buffer: IBuffer = { byteLength: this.totalByteLength };
 
-            let glTF: _IGLTF = {
+            let glTF: IGLTF = {
                 asset: this.asset
             };
             if (buffer.byteLength > 0) {
@@ -641,7 +498,7 @@ module BABYLON {
          * @param babylonMesh 
          * @param useRightHandedSystem 
          */
-        private setNodeTransformation(node: _IGLTFNode, babylonMesh: AbstractMesh, useRightHandedSystem: boolean): void {
+        private setNodeTransformation(node: INode, babylonMesh: AbstractMesh, useRightHandedSystem: boolean): void {
             if (!(babylonMesh.position.x === 0 && babylonMesh.position.y === 0 && babylonMesh.position.z === 0)) {
                 if (useRightHandedSystem) {
                     node.translation = babylonMesh.position.asArray();
@@ -678,10 +535,10 @@ module BABYLON {
          * @param babylonTexture 
          * @return - glTF texture, or null if the texture format is not supported
          */
-        private exportTexture(babylonTexture: BaseTexture, mimeType: _EGLTFImageMimeTypeEnum = _EGLTFImageMimeTypeEnum.JPG): Nullable<_IGLTFTextureInfo> {
-            let textureInfo: Nullable<_IGLTFTextureInfo> = null;
+        private exportTexture(babylonTexture: BaseTexture, mimeType: ImageMimeType = ImageMimeType.JPEG): Nullable<ITextureInfo> {
+            let textureInfo: Nullable<ITextureInfo> = null;
 
-            let glTFTexture: Nullable<_IGLTFTexture>;
+            let glTFTexture: Nullable<ITexture>;
 
             glTFTexture = {
                 source: this.images.length
@@ -693,10 +550,10 @@ module BABYLON {
                 textureName = splitFilename[splitFilename.length - 1];
                 const basefile = textureName.split('.')[0];
                 let extension = textureName.split('.')[1];
-                if (mimeType === _EGLTFImageMimeTypeEnum.JPG) {
+                if (mimeType === ImageMimeType.JPEG) {
                     extension = ".jpg";
                 }
-                else if (mimeType === _EGLTFImageMimeTypeEnum.PNG) {
+                else if (mimeType === ImageMimeType.PNG) {
                     extension = ".png";
                 }
                 else {
@@ -729,8 +586,8 @@ module BABYLON {
             const imageValues = { data: arr, mimeType: mimeType };
 
             this.imageData[textureName] = imageValues;
-            if (mimeType === _EGLTFImageMimeTypeEnum.JPG) {
-                const glTFImage: _IGLTFImage = {
+            if (mimeType === ImageMimeType.JPEG) {
+                const glTFImage: IImage = {
                     uri: textureName
                 }
                 let foundIndex = -1;
@@ -740,7 +597,6 @@ module BABYLON {
                         break;
                     }
                 }
-
                 if (foundIndex === -1) {
                     this.images.push(glTFImage);
                     glTFTexture.source = this.images.length - 1;
@@ -773,12 +629,12 @@ module BABYLON {
          * @param dataBuffer 
          * @returns - bytelength of the primitive attributes plus the passed in byteOffset
          */
-        private setPrimitiveAttributes(mesh: _IGLTFMesh, babylonMesh: AbstractMesh, byteOffset: number, useRightHandedSystem: boolean, dataBuffer?: DataView): number {
+        private setPrimitiveAttributes(mesh: IMesh, babylonMesh: AbstractMesh, byteOffset: number, useRightHandedSystem: boolean, dataBuffer?: DataView): number {
             // go through all mesh primitives (submeshes)
             for (let j = 0; j < babylonMesh.subMeshes.length; ++j) {
                 let bufferMesh = null;
                 const submesh = babylonMesh.subMeshes[j];
-                const meshPrimitive: _IGLTFMeshPrimitive = { attributes: {} };
+                const meshPrimitive: IMeshPrimitive = { attributes: {} };
 
                 if (babylonMesh instanceof Mesh) {
                     bufferMesh = (babylonMesh as Mesh);
@@ -812,7 +668,7 @@ module BABYLON {
 
                         // Create accessor
                         const result = this.calculateMinMax(positions!, submesh.verticesStart, submesh.verticesCount, positionVertexBufferOffset!, positionStrideSize!);
-                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Position", "VEC3", 5126, submesh.verticesCount, result.min, result.max);
+                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Position", AccessorType.VEC3, AccessorComponentType.FLOAT, submesh.verticesCount, result.min, result.max);
                         this.accessors.push(accessor);
 
                         meshPrimitive.attributes.POSITION = this.accessors.length - 1;
@@ -840,7 +696,7 @@ module BABYLON {
                         this.bufferViews.push(bufferview);
 
                         // Create accessor
-                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Normal", "VEC3", 5126, submesh.verticesCount);
+                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Normal", AccessorType.VEC3, AccessorComponentType.FLOAT, submesh.verticesCount);
                         this.accessors.push(accessor);
 
                         meshPrimitive.attributes.NORMAL = this.accessors.length - 1;
@@ -868,7 +724,7 @@ module BABYLON {
                         this.bufferViews.push(bufferview);
 
                         // Create accessor
-                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Tangent", "VEC4", 5126, submesh.verticesCount);
+                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Tangent", AccessorType.VEC4, AccessorComponentType.FLOAT, submesh.verticesCount);
                         this.accessors.push(accessor);
 
                         meshPrimitive.attributes.TANGENT = this.accessors.length - 1;
@@ -896,7 +752,7 @@ module BABYLON {
                         this.bufferViews.push(bufferview);
 
                         // Create accessor
-                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Color", "VEC4", 5126, submesh.verticesCount);
+                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Color", AccessorType.VEC4, AccessorComponentType.FLOAT, submesh.verticesCount);
                         this.accessors.push(accessor);
 
                         meshPrimitive.attributes.COLOR_0 = this.accessors.length - 1;
@@ -924,7 +780,7 @@ module BABYLON {
                         this.bufferViews.push(bufferview);
 
                         // Create accessor
-                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Texture Coords", "VEC2", 5126, submesh.verticesCount);
+                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Texture Coords", AccessorType.VEC2, AccessorComponentType.FLOAT, submesh.verticesCount);
                         this.accessors.push(accessor);
 
                         meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
@@ -952,7 +808,7 @@ module BABYLON {
                         this.bufferViews.push(bufferview);
 
                         // Create accessor
-                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Texture Coords", "VEC2", 5126, submesh.verticesCount);
+                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Texture Coords", AccessorType.VEC2, AccessorComponentType.FLOAT, submesh.verticesCount);
                         this.accessors.push(accessor);
 
                         meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
@@ -987,7 +843,7 @@ module BABYLON {
                         this.bufferViews.push(bufferview);
 
                         // Create accessor
-                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Indices", "SCALAR", 5125, indicesCount);
+                        const accessor = this.createAccessor(this.bufferViews.length - 1, "Indices", AccessorType.SCALAR, AccessorComponentType.UNSIGNED_INT, indicesCount);
                         this.accessors.push(accessor);
 
                         meshPrimitive.indices = this.accessors.length - 1;
@@ -997,7 +853,7 @@ module BABYLON {
                     if (bufferMesh!.material instanceof StandardMaterial) {
                         const babylonStandardMaterial = bufferMesh!.material as StandardMaterial;
 
-                        const glTFMaterial: _IGLTFMaterial = { name: babylonStandardMaterial.name };
+                        const glTFMaterial: IMaterial = { name: babylonStandardMaterial.name };
                         if (!babylonStandardMaterial.backFaceCulling) {
                             glTFMaterial.doubleSided = true;
                         }
@@ -1021,27 +877,8 @@ module BABYLON {
                             }
                         }
                         // Spec Gloss
-                        const babylonSpecularGlossiness: _IBabylonSpecularGlossiness = {
-                            diffuse: babylonStandardMaterial.diffuseColor,
-                            opacity: babylonStandardMaterial.alpha,
-                            specular: babylonStandardMaterial.specularColor || Color3.Black(),
-                            glossiness: babylonStandardMaterial.specularPower / 256
-                        };
-                        if (babylonStandardMaterial.specularTexture) {
-
-                        }
-                        const babylonMetallicRoughness = _GLTFMaterial.ConvertToMetallicRoughness(babylonSpecularGlossiness);
-
-                        const glTFPbrMetallicRoughness: _IGLTFPBRMetallicRoughnessMaterial = {
-                            baseColorFactor: [
-                                babylonMetallicRoughness.baseColor.r,
-                                babylonMetallicRoughness.baseColor.g,
-                                babylonMetallicRoughness.baseColor.b,
-                                babylonMetallicRoughness.opacity
-                            ],
-                            metallicFactor: babylonMetallicRoughness.metallic,
-                            roughnessFactor: babylonMetallicRoughness.roughness
-                        };
+                        const glTFPbrMetallicRoughness = _GLTFMaterial.ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
+                        
                         glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
 
                         // TODO: Handle Textures
@@ -1050,10 +887,10 @@ module BABYLON {
                     }
                     else if (bufferMesh!.material instanceof PBRMetallicRoughnessMaterial) {
                         if (!this.textures) {
-                            this.textures = new Array<_IGLTFTexture>();
+                            this.textures = new Array<ITexture>();
                         }
                         const babylonPBRMaterial = bufferMesh!.material as PBRMetallicRoughnessMaterial;
-                        const glTFPbrMetallicRoughness: _IGLTFPBRMetallicRoughnessMaterial = {};
+                        const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {};
 
                         if (babylonPBRMaterial.baseColor) {
                             glTFPbrMetallicRoughness.baseColorFactor = [
@@ -1077,7 +914,7 @@ module BABYLON {
                             glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMaterial.roughness;
                         }
 
-                        const glTFMaterial: _IGLTFMaterial = {
+                        const glTFMaterial: IMaterial = {
                             name: babylonPBRMaterial.name
                         };
                         if (babylonPBRMaterial.doubleSided) {
@@ -1110,9 +947,9 @@ module BABYLON {
                         if (babylonPBRMaterial.transparencyMode) {
                             const alphaMode = _GLTFMaterial.GetAlphaMode(babylonPBRMaterial);
 
-                            if (alphaMode !== _EGLTFAlphaModeEnum.OPAQUE) { //glTF defaults to opaque
+                            if (alphaMode !== MaterialAlphaMode.OPAQUE) { //glTF defaults to opaque
                                 glTFMaterial.alphaMode = alphaMode;
-                                if (alphaMode === _EGLTFAlphaModeEnum.BLEND) {
+                                if (alphaMode === MaterialAlphaMode.BLEND) {
                                     glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
                                 }
                             }
@@ -1152,7 +989,7 @@ module BABYLON {
                     }
                     else {
                         // create node to hold translation/rotation/scale and the mesh
-                        const node: _IGLTFNode = { mesh: -1 };
+                        const node: INode = { mesh: -1 };
                         const babylonMesh = babylonMeshes[i];
                         const useRightHandedSystem = babylonMesh.getScene().useRightHandedSystem;
 
@@ -1160,7 +997,7 @@ module BABYLON {
                         this.setNodeTransformation(node, babylonMesh, useRightHandedSystem);
 
                         // create mesh
-                        const mesh: _IGLTFMesh = { primitives: new Array<_IGLTFMeshPrimitive>() };
+                        const mesh: IMesh = { primitives: new Array<IMeshPrimitive>() };
                         mesh.primitives = [];
                         byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer);
                         // go through all mesh primitives (submeshes)

+ 99 - 15
serializers/src/glTF/2.0/babylon.glTFMaterial.ts

@@ -1,17 +1,102 @@
-module BABYLON {
+/// <reference path="../../../../dist/babylon.glTFInterface.d.ts"/>
+
+module BABYLON.GLTF2 {
+    /**
+     * Represents the components used for representing a physically-based specular glossiness material
+     */
+    interface IBabylonPbrSpecularGlossiness {
+        /**
+         * The diffuse color of the model, whose color values should be 
+         * normalized from 0 to 1.  
+         */
+        diffuse: Color3;
+        /**
+         * Represents the transparency of the material, from a range of 0 to 1.
+         */
+        opacity: number;
+        /**
+         * Represents how specular the material is, from a range of 0 to 1.
+         */
+        specular: Color3;
+        /**
+         * Represents how glossy the material is, from a range of 0 to 1.
+         */
+        glossiness: number;
+    }
+
+    /**
+     * Represents the components used for representing a physically-based metallic roughness material.
+     */
+    interface _IBabylonPbrMetallicRoughness {
+        /**
+         * The albedo color of the material, whose color components should be normalized from 0 to 1.
+         */
+        baseColor: Color3;
+        /**
+         * Represents the transparency of the material, from a range of 0 (transparent) to 1 (opaque).
+         */
+        opacity: number;
+        /**
+         * Represents the "metalness" of a material, from a range of 0 (dielectric) to 1 (metal).
+         */
+        metallic: number;
+        /**
+         * Represents the "roughness" of a material, from a range of 0 (completely smooth) to 1 (completely rough).
+         */
+        roughness: number;
+    }
+
     /**
-     * Utility methods for working with glTF material conversion properties
+     * Utility methods for working with glTF material conversion properties.  This class should only be used internally.
      */
     export class _GLTFMaterial {
-        private static dielectricSpecular = new Color3(0.04, 0.04, 0.04);
-        private static epsilon = 1e-6;
+        /**
+         * Represents the dielectric specular values for R, G and B.
+         */
+        private static readonly dielectricSpecular = new Color3(0.04, 0.04, 0.04);
+        /**
+         * Epsilon value, used as a small tolerance value for a numeric value.
+         */
+        private static readonly epsilon = 1e-6;
+
+        /**
+         * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
+         * @param babylonStandardMaterial 
+         * @returns - glTF Metallic Roughness Material representation
+         */
+        public static ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness {
+            const babylonSpecularGlossiness: IBabylonPbrSpecularGlossiness = {
+                diffuse: babylonStandardMaterial.diffuseColor,
+                opacity: babylonStandardMaterial.alpha,
+                specular: babylonStandardMaterial.specularColor || Color3.Black(),
+                glossiness: babylonStandardMaterial.specularPower / 256
+            };
+            if (babylonStandardMaterial.specularTexture) {
+
+            }
+            const babylonMetallicRoughness = _GLTFMaterial._ConvertToMetallicRoughness(babylonSpecularGlossiness);
+
+            const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {
+                baseColorFactor: [
+                    babylonMetallicRoughness.baseColor.r,
+                    babylonMetallicRoughness.baseColor.g,
+                    babylonMetallicRoughness.baseColor.b,
+                    babylonMetallicRoughness.opacity
+                ],
+                metallicFactor: babylonMetallicRoughness.metallic,
+                roughnessFactor: babylonMetallicRoughness.roughness
+            };
+
+            return glTFPbrMetallicRoughness;
+        }
 
         /**
-         * Converts Specular Glossiness to Metallic Roughness
+         * Converts Specular Glossiness to Metallic Roughness.  This is based on the algorithm used in the Babylon glTF 3ds Max Exporter.
+         * {@link https://github.com/BabylonJS/Exporters/blob/master/3ds%20Max/Max2Babylon/Exporter/BabylonExporter.GLTFExporter.Material.cs}
          * @param  babylonSpecularGlossiness - Babylon specular glossiness parameters
          * @returns - Babylon metallic roughness values
          */
-        public static ConvertToMetallicRoughness(babylonSpecularGlossiness: _IBabylonSpecularGlossiness): _IBabylonMetallicRoughness {
+        private static _ConvertToMetallicRoughness(babylonSpecularGlossiness: IBabylonPbrSpecularGlossiness): _IBabylonPbrMetallicRoughness {
             const diffuse = babylonSpecularGlossiness.diffuse;
             const opacity = babylonSpecularGlossiness.opacity;
             const specular = babylonSpecularGlossiness.specular;
@@ -28,7 +113,7 @@ module BABYLON {
             let baseColor = new Color3();
             lerpColor.clampToRef(0, 1, baseColor);
 
-            const babylonMetallicRoughness: _IBabylonMetallicRoughness = {
+            const babylonMetallicRoughness: _IBabylonPbrMetallicRoughness = {
                 baseColor: baseColor,
                 opacity: opacity,
                 metallic: metallic,
@@ -71,16 +156,16 @@ module BABYLON {
          * @param babylonMaterial - Babylon Material
          * @returns - The Babylon alpha mode value
          */
-        public static GetAlphaMode(babylonMaterial: Material): string {
+        public static GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode {
             if (babylonMaterial instanceof StandardMaterial) {
                 const babylonStandardMaterial = babylonMaterial as StandardMaterial;
                 if ((babylonStandardMaterial.alpha != 1.0) || 
                     (babylonStandardMaterial.diffuseTexture != null && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
                     (babylonStandardMaterial.opacityTexture != null)) {
-                    return  _EGLTFAlphaModeEnum.BLEND;
+                    return  MaterialAlphaMode.BLEND;
                 }
                 else {
-                    return _EGLTFAlphaModeEnum.OPAQUE;
+                    return MaterialAlphaMode.OPAQUE;
                 }
             }
             else if (babylonMaterial instanceof PBRMetallicRoughnessMaterial) {
@@ -88,17 +173,17 @@ module BABYLON {
 
                 switch(babylonPBRMetallicRoughness.transparencyMode) {
                     case PBRMaterial.PBRMATERIAL_OPAQUE: {
-                        return _EGLTFAlphaModeEnum.OPAQUE;
+                        return MaterialAlphaMode.OPAQUE;
                     }
                     case PBRMaterial.PBRMATERIAL_ALPHABLEND: {
-                        return _EGLTFAlphaModeEnum.BLEND;
+                        return MaterialAlphaMode.BLEND;
                     }
                     case PBRMaterial.PBRMATERIAL_ALPHATEST: {
-                        return _EGLTFAlphaModeEnum.MASK;
+                        return MaterialAlphaMode.MASK;
                     }
                     case PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
                         console.warn("GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
-                        return _EGLTFAlphaModeEnum.BLEND;
+                        return MaterialAlphaMode.BLEND;
                     }
                     default: {
                         throw new Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
@@ -110,5 +195,4 @@ module BABYLON {
             }   
         }
     }
-
 }

+ 29 - 25
serializers/src/glTF/2.0/babylon.glTFSerializer.ts

@@ -1,54 +1,58 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
-    export interface IGLTFExporterOptions {
+    /**
+     * Holds a collection of exporter options and parameters
+     */
+    export interface IExporterOptions {
         /**
-         * Interface function which indicates whether a babylon mesh should be exported or not.
-         * @param mesh
+         * Function which indicates whether a babylon mesh should be exported or not.
+         * @param mesh - source Babylon mesh. It is used to check whether it should be 
+         * exported to glTF or not.
          * @returns boolean, which indicates whether the mesh should be exported (true) or not (false)
          */
         shouldExportMesh?(mesh: AbstractMesh): boolean;
     };
+
+    /**
+     * Class for generating glTF data from a Babylon scene.
+     */
     export class GLTF2Export {
         /**
-         * Exports the geometry of a Mesh array in .gltf file format.
-         * @param meshes  
-         * @param materials 
-         * @param options
-         * 
-         * @returns - Returns an object with a .gltf, .glb and associates textures
+         * Exports the geometry of the scene to .gltf file format.
+         * @param scene - Babylon scene with scene hierarchy information.
+         * @param filePrefix - File prefix to use when generating the glTF file.
+         * @param options - Exporter options.
+         * @returns - Returns an object with a .gltf file and associates texture names
          * as keys and their data and paths as values.
          */
-        public static GLTF(scene: Scene, filename: string, options?: IGLTFExporterOptions): _GLTFData {
-            const glTFPrefix = filename.replace(/\.[^/.]+$/, "");
-            const gltfGenerator = new _GLTF2Exporter(scene, options);
+        public static GLTF(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData {
+            const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
+            const gltfGenerator = new GLTF2._Exporter(scene, options);
             if (scene.isReady) {
                 return gltfGenerator._generateGLTF(glTFPrefix);
             }
             else {
                 throw new Error("glTF Serializer: Scene is not ready!");
-            }
-
-            
+            } 
         }
+
         /**
-         * 
-         * @param meshes 
-         * @param filename 
-         * 
+         * Exports the geometry of the scene to .glb file format.
+         * @param scene - Babylon scene with scene hierarchy information.
+         * @param filePrefix - File prefix to use when generating glb file.
+         * @param options - Exporter options.
          * @returns - Returns an object with a .glb filename as key and data as value
          */
-        public static GLB(scene: Scene, filename: string, options?: IGLTFExporterOptions): _GLTFData {
-            const glTFPrefix = filename.replace(/\.[^/.]+$/, "");        
-            const gltfGenerator = new _GLTF2Exporter(scene, options);
+        public static GLB(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData {
+            const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");        
+            const gltfGenerator = new GLTF2._Exporter(scene, options);
             if (scene.isReady) {
                 return gltfGenerator._generateGLB(glTFPrefix);
             }
             else {
                 throw new Error("glTF Serializer: Scene is not ready!");
-            }
-
-            
+            }  
         }
     }
 }

+ 1 - 0
tests/unit/babylon/babylonReference.ts

@@ -1,5 +1,6 @@
 /// <reference path="../../../dist/babylon.d.ts" />
 /// <reference path="../../../dist/loaders/babylon.glTF2FileLoader.d.ts" />
+/// <reference path="../../../dist/babylon.glTFInterface.d.ts"/>
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts" />
 
 /// <reference path="../node_modules/@types/chai/index.d.ts" />

+ 20 - 21
tests/unit/babylon/serializers/babylon.glTFSerializer.tests.ts

@@ -40,53 +40,50 @@ describe('Babylon glTF Serializer', () => {
             const babylonMaterial = new BABYLON.PBRMetallicRoughnessMaterial("metallicroughness", scene);
             babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
             
-            alphaMode = BABYLON._GLTFMaterial.GetAlphaMode(babylonMaterial);
+            alphaMode = BABYLON.GLTF2._GLTFMaterial.GetAlphaMode(babylonMaterial);
             alphaMode.should.be.equal('OPAQUE');
             
             babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND;
-            alphaMode = BABYLON._GLTFMaterial.GetAlphaMode(babylonMaterial);
+            alphaMode = BABYLON.GLTF2._GLTFMaterial.GetAlphaMode(babylonMaterial);
             alphaMode.should.be.equal('BLEND');
 
             babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND;
-            alphaMode = BABYLON._GLTFMaterial.GetAlphaMode(babylonMaterial);
+            alphaMode = BABYLON.GLTF2._GLTFMaterial.GetAlphaMode(babylonMaterial);
             alphaMode.should.be.equal('BLEND');
 
             babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST;
-            alphaMode = BABYLON._GLTFMaterial.GetAlphaMode(babylonMaterial);
+            alphaMode = BABYLON.GLTF2._GLTFMaterial.GetAlphaMode(babylonMaterial);
             alphaMode.should.be.equal('MASK'); 
         });
+
         it('should convert Babylon standard material to metallic roughness', () => {
             const scene = new BABYLON.Scene(subject);
             const babylonStandardMaterial = new BABYLON.StandardMaterial("specGloss", scene);
             babylonStandardMaterial.diffuseColor = BABYLON.Color3.White();
             babylonStandardMaterial.specularColor = BABYLON.Color3.Black();
+            babylonStandardMaterial.specularPower = 64;
+            babylonStandardMaterial.alpha = 1;
 
-            const specGloss: BABYLON._IBabylonSpecularGlossiness = {
-                diffuse: BABYLON.Color3.White(),
-                specular: BABYLON.Color3.Black(),
-                glossiness: 0.25,
-                opacity: 1.0
-            };
-            const metalRough = BABYLON._GLTFMaterial.ConvertToMetallicRoughness(specGloss);
+            const metalRough = BABYLON.GLTF2._GLTFMaterial.ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
 
-            metalRough.baseColor.equals(new BABYLON.Color3(1, 1, 1)).should.be.equal(true);
+            metalRough.baseColorFactor.should.deep.equal([1,1,1,1]);
 
-            metalRough.metallic.should.be.equal(0);
-            
-            metalRough.roughness.should.be.equal(0.75);
+            metalRough.metallicFactor.should.be.equal(0);
             
-            metalRough.opacity.should.be.equal(1);
+            metalRough.roughnessFactor.should.be.equal(0.75);
         });
+
         it('should solve for metallic', () => {
-            BABYLON._GLTFMaterial.SolveMetallic(1.0, 0.0, 1.0).should.be.equal(0);
-            BABYLON._GLTFMaterial.SolveMetallic(0.0, 1.0, 1.0).should.be.approximately(1, 1e-6);
+            BABYLON.GLTF2._GLTFMaterial.SolveMetallic(1.0, 0.0, 1.0).should.be.equal(0);
+            BABYLON.GLTF2._GLTFMaterial.SolveMetallic(0.0, 1.0, 1.0).should.be.approximately(1, 1e-6);
         });
+
         it('should serialize empty Babylon scene to glTF with only asset property', (done) => {
             mocha.timeout(10000);
 
             const scene = new BABYLON.Scene(subject);
             scene.executeWhenReady(function () {
-                const glTFExporter = new BABYLON._GLTF2Exporter(scene);
+                const glTFExporter = new BABYLON.GLTF2._Exporter(scene);
                 const glTFData = glTFExporter._generateGLTF('test');
                 const jsonString = glTFData.glTFFiles['test.gltf'] as string;
                 const jsonData = JSON.parse(jsonString);
@@ -98,13 +95,14 @@ describe('Babylon glTF Serializer', () => {
                 done();
             });
         });
+
         it('should serialize sphere geometry in scene to glTF', (done) => {
             mocha.timeout(10000);
             const scene = new BABYLON.Scene(subject);
             BABYLON.Mesh.CreateSphere('sphere', 16, 2, scene);
 
             scene.executeWhenReady(function () {
-                const glTFExporter = new BABYLON._GLTF2Exporter(scene);
+                const glTFExporter = new BABYLON.GLTF2._Exporter(scene);
                 const glTFData = glTFExporter._generateGLTF('test');
                 const jsonString = glTFData.glTFFiles['test.gltf'] as string;
                 const jsonData = JSON.parse(jsonString);
@@ -134,6 +132,7 @@ describe('Babylon glTF Serializer', () => {
                 done();
             });
         });
+        
         it('should serialize alpha mode and cutoff', (done) => {
             mocha.timeout(10000);
             const scene = new BABYLON.Scene(subject);
@@ -147,7 +146,7 @@ describe('Babylon glTF Serializer', () => {
             plane.material = babylonPBRMetalRoughMaterial;
 
             scene.executeWhenReady(function () {
-                const glTFExporter = new BABYLON._GLTF2Exporter(scene);
+                const glTFExporter = new BABYLON.GLTF2._Exporter(scene);
                 const glTFData = glTFExporter._generateGLTF('test');
                 const jsonString = glTFData.glTFFiles['test.gltf'] as string;
                 const jsonData = JSON.parse(jsonString);