Jelajahi Sumber

Updated what's new, added namespace for glTF exporter; bug in export

Kacey Coley 7 tahun lalu
induk
melakukan
2dca9cd9fe

+ 1 - 1
Tools/Gulp/config.json

@@ -1850,7 +1850,7 @@
                     "../../serializers/src/glTF/2.0/babylon.glTFUtilities.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFExporterExtension.ts",
                     "../../serializers/src/glTF/babylon.glTFFileExporter.ts",
-                    "../../serializers/src/glTF/2.0/Extensions/Exporter_KHR_texture_transform.ts"
+                    "../../serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts"
                 ],
                 "shaderFiles": [
                     "../../serializers/src/glTF/2.0/shaders/textureTransform.fragment.fx"

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

@@ -118,6 +118,9 @@
 - Added support for MSFT_audio_emitter ([najadojo](http://www.github.com/najadojo))
 - Added support for custom loader extensions ([bghgary](http://www.github.com/bghgary))
 
+### glTF Serializer
+- Added support for exporting the scale, rotation and offset texture properties ([kcoley](http://www.github.com/kcoley))
+
 ### Viewer
 
 - No fullscreen button on small devices ([RaananW](https://github.com/RaananW))

+ 16 - 10
serializers/src/glTF/2.0/Extensions/Exporter_KHR_texture_transform.ts

@@ -1,6 +1,6 @@
 /// <reference path="../../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
 
-module BABYLON.GLTF2.Extensions {
+module BABYLON.GLTF2.Exporter.Extensions {
     const NAME = "KHR_texture_transform";
 
     /**
@@ -17,7 +17,7 @@ module BABYLON.GLTF2.Extensions {
     /**
      * @hidden
      */
-    export class Exporter_KHR_texture_transform implements IGLTFExporterExtension {
+    export class KHR_texture_transform implements IGLTFExporterExtension {
         /** Name of this extension */
         public readonly name = NAME;
 
@@ -51,13 +51,13 @@ module BABYLON.GLTF2.Extensions {
                 }
 
                 if (babylonTexture.wAng !== 0) {
-                        texture_transform_extension.rotation = babylonTexture.wAng;
+                    texture_transform_extension.rotation = babylonTexture.wAng;
                 }
 
                 if (!Object.keys(texture_transform_extension).length) {
                     resolve(babylonTexture);
                 }
-                
+
                 const scale = texture_transform_extension.scale ? new Vector2(texture_transform_extension.scale[0], texture_transform_extension.scale[1]) : Vector2.One();
                 const rotation = texture_transform_extension.rotation != null ? texture_transform_extension.rotation : 0;
                 const offset = texture_transform_extension.offset ? new Vector2(texture_transform_extension.offset[0], texture_transform_extension.offset[1]) : Vector2.Zero();
@@ -69,7 +69,7 @@ module BABYLON.GLTF2.Extensions {
                     this.textureTransformTextureAsync(babylonTexture, offset, rotation, scale, scene).then(texture => {
                         resolve(texture as Texture);
                     });
-                }                
+                }
             });
         }
 
@@ -88,17 +88,23 @@ module BABYLON.GLTF2.Extensions {
                     Tools.Log(`Cannot create procedural texture for ${babylonTexture.name}!`);
                     resolve(babylonTexture);
                 }
-                
+
                 proceduralTexture.setTexture("textureSampler", babylonTexture);
                 proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());
 
-                // Note: onLoadObservable would be preferable but it does not seem to be resolving...
-                scene.whenReadyAsync().then(() => {
+                if (!proceduralTexture.isReady()) {
+                    proceduralTexture._effect.onCompiled = () => {
+                        proceduralTexture.render();
+                        resolve(proceduralTexture);
+                    }
+                }
+                else {
+                    proceduralTexture.render();
                     resolve(proceduralTexture);
-                });
+                }
             });
         }
     }
 
-    _Exporter.RegisterExtension(NAME, exporter => new Exporter_KHR_texture_transform(exporter));
+    _Exporter.RegisterExtension(NAME, exporter => new KHR_texture_transform(exporter));
 }

+ 110 - 0
serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts

@@ -0,0 +1,110 @@
+/// <reference path="../../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+
+module BABYLON.GLTF2.Exporter.Extensions {
+    const NAME = "KHR_texture_transform";
+
+    /**
+     * Interface for handling KHR texture transform
+     * @hidden
+     */
+    interface IKHRTextureTransform {
+        offset?: number[];
+        rotation?: number;
+        scale?: number[];
+        texCoord?: number;
+    }
+
+    /**
+     * @hidden
+     */
+    export class KHR_texture_transform implements IGLTFExporterExtension {
+        /** Name of this extension */
+        public readonly name = NAME;
+
+        /** Defines whether this extension is enabled */
+        public enabled = true;
+
+        /** Defines whether this extension is required */
+        public required = false;
+
+        /** Reference to the glTF exporter */
+        private _exporter: _Exporter;
+
+        constructor(exporter: _Exporter) {
+            this._exporter = exporter;
+        }
+
+        public dispose() {
+            delete this._exporter;
+        }
+
+        public preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>> {
+            return new Promise((resolve, reject) => {
+                const texture_transform_extension: IKHRTextureTransform = {};
+
+                if (babylonTexture.uOffset !== 0 || babylonTexture.vOffset !== 0) {
+                    texture_transform_extension.offset = [babylonTexture.uOffset, babylonTexture.vOffset];
+                }
+
+                if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {
+                    texture_transform_extension.scale = [babylonTexture.uScale, babylonTexture.vScale];
+                }
+
+                if (babylonTexture.wAng !== 0) {
+                    texture_transform_extension.rotation = babylonTexture.wAng;
+                }
+
+                if (!Object.keys(texture_transform_extension).length) {
+                    resolve(babylonTexture);
+                }
+
+                const scale = texture_transform_extension.scale ? new Vector2(texture_transform_extension.scale[0], texture_transform_extension.scale[1]) : Vector2.One();
+                const rotation = texture_transform_extension.rotation != null ? texture_transform_extension.rotation : 0;
+                const offset = texture_transform_extension.offset ? new Vector2(texture_transform_extension.offset[0], texture_transform_extension.offset[1]) : Vector2.Zero();
+                const scene = babylonTexture.getScene();
+                if (!scene) {
+                    reject(`${context}: "scene" is not defined for Babylon texture ${babylonTexture.name}!`);
+                }
+                else {
+                    this.textureTransformTextureAsync(babylonTexture, offset, rotation, scale, scene).then(texture => {
+                        resolve(texture as Texture);
+                    });
+                }
+            });
+        }
+
+        /**
+         * Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
+         * @param babylonTexture 
+         * @param offset 
+         * @param rotation 
+         * @param scale 
+         * @param scene 
+         */
+        public textureTransformTextureAsync(babylonTexture: Texture, offset: Vector2, rotation: number, scale: Vector2, scene: Scene): Promise<BaseTexture> {
+            return new Promise((resolve, reject) => {
+                const proceduralTexture = new ProceduralTexture(`${babylonTexture.name}`, babylonTexture.getSize(), "textureTransform", scene);
+                if (!proceduralTexture) {
+                    Tools.Log(`Cannot create procedural texture for ${babylonTexture.name}!`);
+                    resolve(babylonTexture);
+                }
+
+                proceduralTexture.setTexture("textureSampler", babylonTexture);
+                proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());
+
+                if (!proceduralTexture.isReady()) {
+                    proceduralTexture._effect.onCompiled = () => {
+                        proceduralTexture.render();
+                        resolve(proceduralTexture);
+                    }
+                }
+                else {
+                    proceduralTexture.render();
+                    resolve(proceduralTexture);
+                }
+            });
+        }
+    }
+
+    _Exporter.RegisterExtension(NAME, exporter => new KHR_texture_transform(exporter));
+}

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFAnimation.ts

@@ -1,6 +1,6 @@
 /// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
-module BABYLON.GLTF2 {
+module BABYLON.GLTF2.Exporter {
     /**
      * @hidden
      * Interface to store animation data.

+ 1 - 2
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -1,6 +1,6 @@
 /// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
-module BABYLON.GLTF2 {
+module BABYLON.GLTF2.Exporter {
     /** 
      * Utility interface for storing vertex attribute data
      * @hidden
@@ -207,7 +207,6 @@ module BABYLON.GLTF2 {
          * @param factory The factory function that creates the exporter extension
          */
         public static RegisterExtension(name: string, factory: (exporter: _Exporter) => IGLTFExporterExtension): void {
-            Tools.Log(`Registering extension ${name}`);
             if (_Exporter.UnregisterExtension(name)) {
                 Tools.Warn(`Extension with the name ${name} already exists`);
             }

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFExporterExtension.ts

@@ -1,6 +1,6 @@
 /// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
 
-module BABYLON.GLTF2 {
+module BABYLON.GLTF2.Exporter {
     /**
      * Interface for a glTF exporter extension
      * @hidden

+ 3 - 3
serializers/src/glTF/2.0/babylon.glTFMaterialExporter.ts

@@ -1,6 +1,6 @@
 /// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
-module BABYLON.GLTF2 {
+module BABYLON.GLTF2.Exporter {
     /** 
      * Interface for storing specular glossiness factors
      * @hidden
@@ -512,7 +512,7 @@ module BABYLON.GLTF2 {
                                 fileReader.readAsDataURL(blob);
                             }
                             else {
-                                reject("Failed to get blob from image canvas!");
+                                reject("gltfMaterialExporter: Failed to get blob from image canvas!");
                             }
                         });
                     }
@@ -1036,7 +1036,7 @@ module BABYLON.GLTF2 {
         private setMetallicRoughnessPbrMaterial(metallicRoughness: Nullable<_IPBRMetallicRoughness>, babylonPBRMaterial: PBRMaterial, glTFMaterial: IMaterial, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void> {
             const materialMap = this._exporter._materialMap;
             const materials = this._exporter._materials;
-            let promises = [];
+            let promises = [];  
             if (metallicRoughness) {
                 let alphaMode: Nullable<MaterialAlphaMode> = null;
                 if (babylonPBRMaterial.transparencyMode != null) {

+ 33 - 4
serializers/src/glTF/2.0/babylon.glTFSerializer.ts

@@ -15,6 +15,11 @@ module BABYLON {
          * The sample rate to bake animation curves
          */
         animationSampleRate?: number;
+
+        /**
+         * Begin serialization without waiting for the scene to be ready
+         */
+        exportWithoutWaitingForScene?: boolean;
     };
 
     /**
@@ -32,11 +37,33 @@ module BABYLON {
         public static GLTFAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData> {
             return scene.whenReadyAsync().then(() => {
                 const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
-                const gltfGenerator = new GLTF2._Exporter(scene, options);
+                const gltfGenerator = new GLTF2.Exporter._Exporter(scene, options);
                 return gltfGenerator._generateGLTFAsync(glTFPrefix);
             });
         }
 
+        private static _PreExportAsync(scene: Scene, options?: IExportOptions): Promise<void> {
+            return Promise.resolve().then(() => {
+                if (options && options.exportWithoutWaitingForScene) {
+                    return Promise.resolve();
+                }
+                else {
+                    return scene.whenReadyAsync();
+                }
+            });
+        }
+
+        private static _PostExportAsync(scene: Scene, glTFData: GLTFData, options?: IExportOptions): Promise<GLTFData> {
+            return Promise.resolve().then(() => {
+                if (options && options.exportWithoutWaitingForScene) {
+                    return glTFData;
+                }
+                else {
+                    return glTFData;
+                }
+            });
+        }
+
         /**
          * Exports the geometry of the scene to .glb file format asychronously
          * @param scene Babylon scene with scene hierarchy information
@@ -45,10 +72,12 @@ module BABYLON {
          * @returns Returns an object with a .glb filename as key and data as value
          */
         public static GLBAsync(scene: Scene, filePrefix: string, options?: IExportOptions): Promise<GLTFData> {
-            return scene.whenReadyAsync().then(() => {
+            return this._PreExportAsync(scene, options).then(() => {
                 const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
-                const gltfGenerator = new GLTF2._Exporter(scene, options);
-                return gltfGenerator._generateGLBAsync(glTFPrefix);
+                const gltfGenerator = new GLTF2.Exporter._Exporter(scene, options);
+                return gltfGenerator._generateGLBAsync(glTFPrefix).then(glTFData => {
+                    return this._PostExportAsync(scene, glTFData, options);
+                });
             });
         }
     }

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFUtilities.ts

@@ -1,6 +1,6 @@
 /// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
-module BABYLON.GLTF2 {
+module BABYLON.GLTF2.Exporter {
     /**
      * @hidden
      */

+ 1 - 0
serializers/src/glTF/babylon.glTFFileExporter.ts

@@ -3,6 +3,7 @@
 module BABYLON {
     /**
      * Interface for extending the exporter
+     * @hidden
      */
     export interface IGLTFExporterExtension {
         /**

+ 3 - 2
src/Materials/Textures/Procedurals/babylon.proceduralTexture.ts

@@ -16,7 +16,8 @@
 
         private _vertexBuffers: { [key: string]: Nullable<VertexBuffer> } = {};
         private _indexBuffer: Nullable<WebGLBuffer>;
-        private _effect: Effect;
+        /** get the internal effect */
+        public _effect: Effect;
 
         private _uniforms = new Array<string>();
         private _samplers = new Array<string>();
@@ -153,7 +154,7 @@
 
                     this._fallbackTextureUsed = true;
                 });
-
+                
             return this._effect.isReady();
         }