Explorar o código

Merge pull request #5475 from julien-moreau/master

Proposition: serialize and parse reflection probes
David Catuhe %!s(int64=6) %!d(string=hai) anos
pai
achega
60a913ea87

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

@@ -64,7 +64,7 @@
 - `Layer` are now supported in `RenderTargetTexture` ([Sebavan](https://github.com/Sebavan))
 - Make onscreen joystick's canvas public ([TrevorDev](https://github.com/TrevorDev))
 - Added `Tools.CustomRequestHeaders`, `Tools.UseCustomRequestHeaders`, `Tools.InjectCustomRequestHeaders` to send Custom Request Headers alongside XMLHttpRequest's i.e. when loading files (Tools.Loadfile) from resources requiring special headers like 'Authorization' ([susares](https://github.com/susares))
-
+- Added `.serialize` and `.Parse` functions in `ReflectionProbe` to retrieve reflection probes when parsing a previously serialized material ([julien-moreau](https://github.com/julien-moreau))
 ### glTF Loader
 
 - Added support for mesh instancing for improved performance when multiple nodes point to the same mesh ([bghgary](https://github.com/bghgary))

+ 13 - 0
src/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -55,6 +55,19 @@ module BABYLON {
                 }
             }
 
+            // Reflection probes
+            if (parsedData.reflectionProbes !== undefined && parsedData.reflectionProbes !== null) {
+                for (index = 0, cache = parsedData.reflectionProbes.length; index < cache; index++) {
+                    var parsedReflectionProbe = parsedData.reflectionProbes[index];
+                    var reflectionProbe = ReflectionProbe.Parse(parsedReflectionProbe, scene, rootUrl);
+                    if (reflectionProbe) {
+                        container.reflectionProbes.push(reflectionProbe);
+                        log += (index === 0 ? "\n\tReflection Probes:" : "");
+                        log += "\n\t\t" + reflectionProbe.toString(fullDetails);
+                    }
+                }
+            }
+
             // Animations
             if (parsedData.animations !== undefined && parsedData.animations !== null) {
                 for (index = 0, cache = parsedData.animations.length; index < cache; index++) {

+ 18 - 5
src/Materials/Textures/babylon.texture.ts

@@ -599,7 +599,7 @@ module BABYLON {
                 return parsedCustomTexture;
             }
 
-            if (parsedTexture.isCube) {
+            if (parsedTexture.isCube && !parsedTexture.isRenderTarget) {
                 return CubeTexture.Parse(parsedTexture, scene, rootUrl);
             }
 
@@ -619,8 +619,21 @@ module BABYLON {
 
                     return mirrorTexture;
                 } else if (parsedTexture.isRenderTarget) {
-                    var renderTargetTexture = new RenderTargetTexture(parsedTexture.name, parsedTexture.renderTargetSize, scene, generateMipMaps);
-                    renderTargetTexture._waitingRenderList = parsedTexture.renderList;
+                    let renderTargetTexture: Nullable<RenderTargetTexture> = null;
+                    if (parsedTexture.isCube) {
+                        // Search for an existing reflection probe (which contains a cube render target texture)
+                        if (scene.reflectionProbes) {
+                            for (var index = 0; index < scene.reflectionProbes.length; index++) {
+                                const probe = scene.reflectionProbes[index];
+                                if (probe.name === parsedTexture.name) {
+                                    return probe.cubeTexture;
+                                }
+                            }
+                        }
+                    } else {
+                        renderTargetTexture = new RenderTargetTexture(parsedTexture.name, parsedTexture.renderTargetSize, scene, generateMipMaps);
+                        renderTargetTexture._waitingRenderList = parsedTexture.renderList;
+                    }
 
                     return renderTargetTexture;
                 } else {
@@ -643,13 +656,13 @@ module BABYLON {
             // Update Sampling Mode
             if (parsedTexture.samplingMode) {
                 var sampling: number = parsedTexture.samplingMode;
-                if (texture._samplingMode !== sampling) {
+                if (texture && texture._samplingMode !== sampling) {
                     texture.updateSamplingMode(sampling);
                 }
             }
 
             // Animations
-            if (parsedTexture.animations) {
+            if (texture && parsedTexture.animations) {
                 for (var animationIndex = 0; animationIndex < parsedTexture.animations.length; animationIndex++) {
                     var parsedAnimation = parsedTexture.animations[animationIndex];
 

+ 110 - 8
src/Probes/babylon.reflectionProbe.ts

@@ -1,12 +1,46 @@
 module BABYLON {
-    export interface Scene {
+    export interface AbstractScene {
         /**
          * The list of reflection probes added to the scene
          * @see http://doc.babylonjs.com/how_to/how_to_use_reflection_probes
          */
         reflectionProbes: Array<ReflectionProbe>;
+
+        /**
+         * Removes the given reflection probe from this scene.
+         * @param toRemove The reflection probe to remove
+         * @returns The index of the removed reflection probe
+         */
+        removeReflectionProbe(toRemove: ReflectionProbe): number;
+
+        /**
+         * Adds the given reflection probe to this scene.
+         * @param newReflectionProbe The reflection probe to add
+         */
+        addReflectionProbe(newReflectionProbe: ReflectionProbe): void;
     }
 
+    AbstractScene.prototype.removeReflectionProbe = function(toRemove: ReflectionProbe): number {
+        if (!this.reflectionProbes) {
+            return -1;
+        }
+
+        var index = this.reflectionProbes.indexOf(toRemove);
+        if (index !== -1) {
+            this.reflectionProbes.splice(index, 1);
+        }
+
+        return index;
+    };
+
+    AbstractScene.prototype.addReflectionProbe = function(newReflectionProbe: ReflectionProbe): void {
+        if (!this.reflectionProbes) {
+            this.reflectionProbes = [];
+        }
+
+        this.reflectionProbes.push(newReflectionProbe);
+    };
+
     /**
      * Class used to generate realtime reflection / refraction cube textures
      * @see http://doc.babylonjs.com/how_to/how_to_use_reflection_probes
@@ -18,11 +52,13 @@ module BABYLON {
         private _viewMatrix = Matrix.Identity();
         private _target = Vector3.Zero();
         private _add = Vector3.Zero();
-        private _attachedMesh: AbstractMesh;
+        @serializeAsMeshReference()
+        private _attachedMesh: Nullable<AbstractMesh>;
 
         private _invertYAxis = false;
 
         /** Gets or sets probe position (center of the cube map) */
+        @serializeAsVector3()
         public position = Vector3.Zero();
 
         /**
@@ -78,7 +114,10 @@ module BABYLON {
 
                 Matrix.LookAtLHToRef(this.position, this._target, Vector3.Up(), this._viewMatrix);
 
-                scene.setTransformMatrix(this._viewMatrix, this._projectionMatrix);
+                if (scene.activeCamera) {
+                    this._projectionMatrix = Matrix.PerspectiveFovLH(Math.PI / 2, 1, scene.activeCamera.minZ, scene.activeCamera.maxZ);
+                    scene.setTransformMatrix(this._viewMatrix, this._projectionMatrix);
+                }
 
                 scene._forcedViewPosition = this.position;
             });
@@ -87,10 +126,6 @@ module BABYLON {
                 scene._forcedViewPosition = null;
                 scene.updateTransformMatrix(true);
             });
-
-            if (scene.activeCamera) {
-                this._projectionMatrix = Matrix.PerspectiveFovLH(Math.PI / 2, 1, scene.activeCamera.minZ, scene.activeCamera.maxZ);
-            }
         }
 
         /** Gets or sets the number of samples to use for multi-sampling (0 by default). Required WebGL2 */
@@ -133,7 +168,7 @@ module BABYLON {
          * Attach the probe to a specific mesh (Rendering will be done from attached mesh's position)
          * @param mesh defines the mesh to attach to
          */
-        public attachToMesh(mesh: AbstractMesh): void {
+        public attachToMesh(mesh: Nullable<AbstractMesh>): void {
             this._attachedMesh = mesh;
         }
 
@@ -162,5 +197,72 @@ module BABYLON {
                 (<any>this._renderTargetTexture) = null;
             }
         }
+
+        /**
+         * Converts the reflection probe information to a readable string for debug purpose.
+         * @param fullDetails Supports for multiple levels of logging within scene loading
+         * @returns the human readable reflection probe info
+         */
+        public toString(fullDetails?: boolean): string {
+            var ret = "Name: " + this.name;
+
+            if (fullDetails) {
+                ret += ", position: " + this.position.toString();
+
+                if (this._attachedMesh) {
+                    ret += ", attached mesh: " + this._attachedMesh.name;
+                }
+            }
+
+            return ret;
+        }
+
+        /**
+         * Get the class name of the relfection probe.
+         * @returns "ReflectionProbe"
+         */
+        public getClassName(): string {
+            return "ReflectionProbe";
+        }
+
+        /**
+         * Serialize the reflection probe to a JSON representation we can easily use in the resepective Parse function.
+         * @returns The JSON representation of the texture
+         */
+        public serialize(): any {
+            const serializationObject = SerializationHelper.Serialize(this, this._renderTargetTexture.serialize());
+            serializationObject.isReflectionProbe = true;
+
+            return serializationObject;
+        }
+
+        /**
+         * Parse the JSON representation of a reflection probe in order to recreate the reflection probe in the given scene.
+         * @param parsedReflectionProbe Define the JSON representation of the reflection probe
+         * @param scene Define the scene the parsed reflection probe should be instantiated in
+         * @param rootUrl Define the root url of the parsing sequence in the case of relative dependencies
+         * @returns The parsed reflection probe if successful
+         */
+        public static Parse(parsedReflectionProbe: any, scene: Scene, rootUrl: string): Nullable<ReflectionProbe> {
+            let reflectionProbe: Nullable<ReflectionProbe> = null;
+            if (scene.reflectionProbes) {
+                for (let index = 0; index < scene.reflectionProbes.length; index++) {
+                    const rp = scene.reflectionProbes[index];
+                    if (rp.name === parsedReflectionProbe.name) {
+                        reflectionProbe = rp;
+                        break;
+                    }
+                }
+            }
+
+            reflectionProbe = SerializationHelper.Parse(() => reflectionProbe || new ReflectionProbe(parsedReflectionProbe.name, parsedReflectionProbe.renderTargetSize, scene, parsedReflectionProbe._generateMipMaps), parsedReflectionProbe, scene, rootUrl);
+            reflectionProbe.cubeTexture._waitingRenderList = parsedReflectionProbe.renderList;
+
+            if (parsedReflectionProbe._attachedMesh) {
+                reflectionProbe.attachToMesh(scene.getMeshByID(parsedReflectionProbe._attachedMesh));
+            }
+
+            return reflectionProbe;
+        }
     }
 }

+ 10 - 0
src/Tools/babylon.sceneSerializer.ts

@@ -209,6 +209,16 @@ module BABYLON {
             // Animations
             Animation.AppendSerializedAnimations(scene, serializationObject);
 
+            // Reflection probes
+            if (scene.reflectionProbes && scene.reflectionProbes.length > 0) {
+                serializationObject.reflectionProbes = [];
+
+                for (index = 0; index < scene.reflectionProbes.length; index++) {
+                    var reflectionProbe = scene.reflectionProbes[index];
+                    serializationObject.reflectionProbes.push(reflectionProbe.serialize());
+                }
+            }
+
             // Materials
             serializationObject.materials = [];
             serializationObject.multiMaterials = [];

+ 10 - 0
src/babylon.assetContainer.ts

@@ -25,6 +25,7 @@ module BABYLON {
             this["layers"] = [];
             this["lensFlareSystems"] = [];
             this["proceduralTextures"] = [];
+            this["reflectionProbes"] = [];
         }
 
         /**
@@ -70,6 +71,9 @@ module BABYLON {
             this.textures.forEach((o) => {
                 this.scene.addTexture(o);
             });
+            this.reflectionProbes.forEach((o) => {
+                this.scene.addReflectionProbe(o);
+            });
 
             for (let component of this.scene._serializableComponents) {
                 component.addFromContainer(this);
@@ -119,6 +123,9 @@ module BABYLON {
             this.textures.forEach((o) => {
                 this.scene.removeTexture(o);
             });
+            this.reflectionProbes.forEach((o) => {
+                this.scene.removeReflectionProbe(o);
+            });
 
             for (let component of this.scene._serializableComponents) {
                 component.removeFromContainer(this);
@@ -162,6 +169,9 @@ module BABYLON {
             this.textures.forEach((o) => {
                 o.dispose();
             });
+            this.reflectionProbes.forEach((o) => {
+                o.dispose();
+            });
 
             for (let component of this.scene._serializableComponents) {
                 component.dispose();