Przeglądaj źródła

lab feature - global light rotation
The global light rotation will take the current state of the light and will rotate them around the Y axis.
It will rotate per default around 0,0,0.

Raanan Weber 7 lat temu
rodzic
commit
85f1541d38

+ 5 - 1
Viewer/src/configuration/configuration.ts

@@ -43,7 +43,10 @@ export interface ViewerConfiguration {
     skybox?: boolean | ISkyboxConfiguration;
 
     ground?: boolean | IGroundConfiguration;
-    lights?: { [name: string]: boolean | ILightConfiguration },
+    lights?: {
+        //globalRotation: number,
+        [name: string]: number | boolean | ILightConfiguration
+    },
     // engine configuration. optional!
     engine?: {
         renderInBackground?: boolean;
@@ -107,6 +110,7 @@ export interface ViewerConfiguration {
             tintLevel: number;
         }
         defaultRenderingPipelines?: boolean | IDefaultRenderingPipelineConfiguration;
+        globalLightRotation?: number;
     }
 }
 

+ 29 - 13
Viewer/src/labs/viewerLabs.ts

@@ -1,7 +1,7 @@
 import { PBREnvironment, EnvironmentDeserializer } from "./environmentSerializer";
 import { SceneManager } from '../viewer/sceneManager';
 
-import { Tools, Quaternion } from 'babylonjs';
+import { Tools, Quaternion, ShadowLight, Vector3, Axis, Matrix, SphericalPolynomial, Tmp } from 'babylonjs';
 import { ViewerConfiguration } from "../configuration/configuration";
 import { TextureUtils } from "./texture";
 
@@ -18,15 +18,15 @@ export class ViewerLabs {
     public environment: PBREnvironment = {
         //irradiance
         irradiancePolynomialCoefficients: {
-            x: new BABYLON.Vector3(0, 0, 0),
-            y: new BABYLON.Vector3(0, 0, 0),
-            z: new BABYLON.Vector3(0, 0, 0),
-            xx: new BABYLON.Vector3(0, 0, 0),
-            yy: new BABYLON.Vector3(0, 0, 0),
-            zz: new BABYLON.Vector3(0, 0, 0),
-            yz: new BABYLON.Vector3(0, 0, 0),
-            zx: new BABYLON.Vector3(0, 0, 0),
-            xy: new BABYLON.Vector3(0, 0, 0)
+            x: new Vector3(0, 0, 0),
+            y: new Vector3(0, 0, 0),
+            z: new Vector3(0, 0, 0),
+            xx: new Vector3(0, 0, 0),
+            yy: new Vector3(0, 0, 0),
+            zz: new Vector3(0, 0, 0),
+            yz: new Vector3(0, 0, 0),
+            zx: new Vector3(0, 0, 0),
+            xy: new Vector3(0, 0, 0)
         },
 
         textureIntensityScale: 1.0
@@ -93,7 +93,7 @@ export class ViewerLabs {
         if (!this.environment) return;
 
         //set orientation
-        let rotatquatRotationionY = Quaternion.RotationAxis(BABYLON.Axis.Y, rotationY || 0);
+        let rotatquatRotationionY = Quaternion.RotationAxis(Axis.Y, rotationY || 0);
 
         // Add env texture to the scene.
         if (this.environment.specularTexture) {
@@ -106,7 +106,7 @@ export class ViewerLabs {
                 this._sceneManager.scene.environmentTexture.invertZ = true;
                 this._sceneManager.scene.environmentTexture.lodLevelInAlpha = true;
 
-                var poly = this._sceneManager.scene.environmentTexture.sphericalPolynomial || new BABYLON.SphericalPolynomial();
+                var poly = this._sceneManager.scene.environmentTexture.sphericalPolynomial || new SphericalPolynomial();
                 poly.x = this.environment.irradiancePolynomialCoefficients.x;
                 poly.y = this.environment.irradiancePolynomialCoefficients.y;
                 poly.z = this.environment.irradiancePolynomialCoefficients.z;
@@ -119,7 +119,7 @@ export class ViewerLabs {
                 this._sceneManager.scene.environmentTexture.sphericalPolynomial = poly;
 
                 //set orientation
-                BABYLON.Matrix.FromQuaternionToRef(rotatquatRotationionY, this._sceneManager.scene.environmentTexture.getReflectionTextureMatrix());
+                Matrix.FromQuaternionToRef(rotatquatRotationionY, this._sceneManager.scene.environmentTexture.getReflectionTextureMatrix());
             }
         }
     }
@@ -143,4 +143,20 @@ export class ViewerLabs {
         return returnUrl;
     }
 
+    public rotateShadowLight(shadowLight: ShadowLight, amount: number, point = Vector3.Zero(), axis = Axis.Y, target = Vector3.Zero()) {
+        axis.normalize();
+        point.subtractToRef(shadowLight.position, Tmp.Vector3[0]);
+        Matrix.TranslationToRef(Tmp.Vector3[0].x, Tmp.Vector3[0].y, Tmp.Vector3[0].z, Tmp.Matrix[0]);
+        Tmp.Matrix[0].invertToRef(Tmp.Matrix[2]);
+        Matrix.RotationAxisToRef(axis, amount, Tmp.Matrix[1]);
+        Tmp.Matrix[2].multiplyToRef(Tmp.Matrix[1], Tmp.Matrix[2]);
+        Tmp.Matrix[2].multiplyToRef(Tmp.Matrix[0], Tmp.Matrix[2]);
+
+        Tmp.Matrix[2].decompose(Tmp.Vector3[0], Tmp.Quaternion[0], Tmp.Vector3[1]);
+
+        shadowLight.position.addInPlace(Tmp.Vector3[1]);
+
+        shadowLight.setDirectionToTarget(target);
+    }
+
 }

+ 1 - 1
Viewer/src/viewer/defaultViewer.ts

@@ -481,7 +481,7 @@ export class DefaultViewer extends AbstractViewer {
      * @param lightsConfiguration the light configuration to use
      * @param model the model that will be used to configure the lights (if the lights are model-dependant)
      */
-    private _configureLights(lightsConfiguration: { [name: string]: ILightConfiguration | boolean } = {}, model?: ViewerModel) {
+    private _configureLights(lightsConfiguration: { [name: string]: ILightConfiguration | boolean | number } = {}, model?: ViewerModel) {
         // labs feature - flashlight
         if (this._configuration.lab && this._configuration.lab.flashlight) {
             let pointerPosition = Vector3.Zero();

+ 24 - 5
Viewer/src/viewer/sceneManager.ts

@@ -41,7 +41,7 @@ export class SceneManager {
     /**
      * Will notify after the lights were configured. Can be used to further configure lights
      */
-    onLightsConfiguredObservable: Observable<IPostConfigurationCallback<Array<Light>, { [name: string]: ILightConfiguration | boolean }>>;
+    onLightsConfiguredObservable: Observable<IPostConfigurationCallback<Array<Light>, { [name: string]: ILightConfiguration | boolean | number }>>;
     /**
      * Will notify after the model(s) were configured. Can be used to further configure models
      */
@@ -93,6 +93,8 @@ export class SceneManager {
     private _reflectionColor = Color3.White();
     private readonly _white = Color3.White();
 
+    private _forceShadowUpdate: boolean = false;
+
     /**
      * The labs variable consists of objects that will have their API change.
      * Please be careful when using labs in production.
@@ -137,7 +139,7 @@ export class SceneManager {
                 }
             }
             scene.registerBeforeRender(() => {
-                if (scene.animatables && scene.animatables.length > 0) {
+                if (this._forceShadowUpdate || (scene.animatables && scene.animatables.length > 0)) {
                     // make sure all models are loaded
                     updateShadows();
                 } else if (!(this.models.every((model) => {
@@ -431,6 +433,15 @@ export class SceneManager {
                 let mainColor = new Color3().copyFrom(newConfiguration.lab.environmentMainColor as Color3);
                 this.environmentHelper.setMainColor(mainColor);
             }
+
+            if (newConfiguration.lab.globalLightRotation !== undefined) {
+                // rotate all lights that are shadow lights
+                this.scene.lights.filter(light => light instanceof ShadowLight).forEach(light => {
+                    // casting and '!' are safe, due to the constraints tested before
+                    this.labs.rotateShadowLight(<ShadowLight>light, newConfiguration.lab!.globalLightRotation!);
+                });
+                this._forceShadowUpdate = true;
+            }
         }
 
         if (this._defaultRenderingPipeline && this._defaultRenderingPipeline.imageProcessing) {
@@ -989,10 +1000,12 @@ export class SceneManager {
      * @param lightsConfiguration the (new) light(s) configuration
      * @param model optionally use the model to configure the camera.
      */
-    protected _configureLights(lightsConfiguration: { [name: string]: ILightConfiguration | boolean } = {}) {
+    protected _configureLights(lightsConfiguration: { [name: string]: ILightConfiguration | boolean | number } = {}) {
 
         // sanity check!
-        if (!Object.keys(lightsConfiguration).length) {
+        let lightKeys = Object.keys(lightsConfiguration).filter(name => name !== 'globalRotation');
+
+        if (!lightKeys.length) {
             if (!this.scene.lights.length)
                 this.scene.createDefaultLight(true);
         } else {
@@ -1008,11 +1021,14 @@ export class SceneManager {
                 });
             }
 
-            Object.keys(lightsConfiguration).forEach((name, idx) => {
+            lightKeys.forEach((name, idx) => {
                 let lightConfig: ILightConfiguration = { type: 0 };
                 if (typeof lightsConfiguration[name] === 'object') {
                     lightConfig = <ILightConfiguration>lightsConfiguration[name];
                 }
+                if (typeof lightsConfiguration[name] === 'number') {
+                    lightConfig.type = <number>lightsConfiguration[name];
+                }
 
                 lightConfig.name = name;
 
@@ -1025,6 +1041,9 @@ export class SceneManager {
                 } else {
                     // available? get it from the scene
                     light = <Light>this.scene.getLightByName(name);
+                    if (typeof lightsConfiguration[name] === 'boolean') {
+                        lightConfig.type = light.getTypeID();
+                    }
                     lightsAvailable = lightsAvailable.filter(ln => ln !== name);
                     if (lightConfig.type !== undefined && light.getTypeID() !== lightConfig.type) {
                         light.dispose();