Pārlūkot izejas kodu

further loader plugins

Raanan Weber 7 gadi atpakaļ
vecāks
revīzija
2db3430657

+ 3 - 3
Viewer/dist/ufoExample.html

@@ -9,10 +9,10 @@
         <style>
             babylon,
             #viewport {
-                max-width: 1000px;
-                max-height: 800px;
+                max-width: 900px;
+                max-height: 600px;
                 width: 100%;
-                height: 800px;
+                height: 600px;
             }
         </style>
     </head>

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

@@ -53,7 +53,12 @@ export interface ViewerConfiguration {
     }
 
     loaderPlugins?: {
-        [propName: string]: boolean;
+        extendedMaterial?: boolean;
+        msftLod?: boolean;
+        telemetry?: boolean;
+        minecraft?: boolean;
+
+        [propName: string]: boolean | undefined;
     };
 
     // features that are being tested.
@@ -137,6 +142,11 @@ export interface IModelConfiguration {
      */
     rotationOffsetAngle?: number;
 
+    loaderConfiguration?: {
+        maxLODsToLoad?: number;
+        progressiveLoading?: boolean;
+    }
+
     // [propName: string]: any; // further configuration, like title and creator
 }
 

+ 6 - 0
Viewer/src/configuration/types/extended.ts

@@ -81,6 +81,12 @@ export let extendedConfiguration: ViewerConfiguration = {
             b: 0.8
         }
     },
+    loaderPlugins: {
+        extendedMaterial: true,
+        minecraft: true,
+        msftLod: true,
+        telemetry: true
+    },
     model: {
         rotationOffsetAxis: {
             x: 0,

+ 2 - 1
Viewer/src/index.ts

@@ -8,6 +8,7 @@ import { telemetryManager } from './telemetryManager';
 import { ModelLoader } from './loader/modelLoader';
 import { ViewerModel, ModelState } from './model/viewerModel';
 import { AnimationPlayMode, AnimationState } from './model/modelAnimation';
+import { ILoaderPlugin } from './loader/plugins/loaderPlugin';
 
 /**
  * BabylonJS Viewer
@@ -42,4 +43,4 @@ function disposeAll() {
 const Version = BABYLON.Engine.Version;
 
 // public API for initialization
-export { BABYLON, Version, InitTags, DefaultViewer, AbstractViewer, viewerGlobals, telemetryManager, disableInit, viewerManager, mapperManager, disposeAll, ModelLoader, ViewerModel, AnimationPlayMode, AnimationState, ModelState };
+export { BABYLON, Version, InitTags, DefaultViewer, AbstractViewer, viewerGlobals, telemetryManager, disableInit, viewerManager, mapperManager, disposeAll, ModelLoader, ViewerModel, AnimationPlayMode, AnimationState, ModelState, ILoaderPlugin };

+ 11 - 2
Viewer/src/loader/modelLoader.ts

@@ -30,8 +30,6 @@ export class ModelLoader {
         this._loaders = [];
         this._loadId = 0;
         this._plugins = [];
-
-        this.addPlugin("telemetry");
     }
 
     public addPlugin(plugin: ILoaderPlugin | string) {
@@ -97,11 +95,21 @@ export class ModelLoader {
             let gltfLoader = (<GLTFFileLoader>model.loader);
             gltfLoader.animationStartMode = GLTFLoaderAnimationStartMode.NONE;
             gltfLoader.compileMaterials = true;
+            // if ground is set to "mirror":
+            if (this._viewer.configuration.ground && typeof this._viewer.configuration.ground === 'object' && this._viewer.configuration.ground.mirror) {
+                gltfLoader.useClipPlane = true;
+            }
             Object.keys(gltfLoader).filter(name => name.indexOf('on') === 0 && name.indexOf('Observable') !== -1).forEach(functionName => {
                 gltfLoader[functionName].add((payload) => {
                     this._checkAndRun(functionName.replace("Observable", ''), payload);
                 });
             });
+
+            gltfLoader.onParsedObservable.add((data) => {
+                if (data && data.json && data.json['asset']) {
+                    model.loadInfo = data.json['asset'];
+                }
+            })
         }
 
         this._checkAndRun("onInit", model.loader, model);
@@ -138,6 +146,7 @@ export class ModelLoader {
     }
 
     private _checkAndRun(functionName: string, ...payload: Array<any>) {
+        if (this._disposed) return;
         this._plugins.filter(p => p[functionName]).forEach(plugin => {
             try {
                 plugin[functionName].apply(this, payload);

+ 79 - 0
Viewer/src/loader/plugins/extendedMaterialLoaderPlugin.ts

@@ -0,0 +1,79 @@
+import { ILoaderPlugin } from "./loaderPlugin";
+import { telemetryManager } from "../../telemetryManager";
+import { ViewerModel } from "../..";
+import { Color3, Texture, BaseTexture, Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material, PBRMaterial, Engine } from "babylonjs";
+
+export class ExtendedMaterialLoaderPlugin implements ILoaderPlugin {
+
+    private _model: ViewerModel;
+
+    public onMaterialLoaded(baseMaterial: Material) {
+        var material = baseMaterial as PBRMaterial;
+        material.alphaMode = Engine.ALPHA_PREMULTIPLIED_PORTERDUFF;
+
+        var isAlphaOnlyOne = (texture: BaseTexture) => {
+            var pixels = texture.readPixels() as Uint8Array;
+            var alphaOne = true;
+            for (var i = 3; i < pixels.length; i += 4) {
+                if (pixels[i] !== 255) {
+                    alphaOne = false;
+                    break;
+                }
+            }
+
+            return alphaOne;
+        };
+
+        if (material.albedoTexture) {
+            material.albedoColor = Color3.White();
+        }
+        else {
+            material.albedoColor = material.albedoColor.toLinearSpace();
+        }
+
+        if (material.reflectivityTexture) {
+            material.reflectivityColor = Color3.White();
+            material.microSurface = 1;
+
+            if (material.reflectivityTexture) {
+                if (material.reflectivityTexture.isReady()) {
+                    if (isAlphaOnlyOne(material.reflectivityTexture)) {
+                        material.useMicroSurfaceFromReflectivityMapAlpha = false;
+                        material.useAutoMicroSurfaceFromReflectivityMap = true;
+                    }
+                }
+                else {
+                    (<Texture>material.reflectivityTexture).onLoadObservable.add(loadedTexture => {
+                        if (isAlphaOnlyOne(loadedTexture)) {
+                            material.useMicroSurfaceFromReflectivityMapAlpha = false;
+                            material.useAutoMicroSurfaceFromReflectivityMap = true;
+                        }
+                    });
+                }
+            }
+        }
+        else {
+            material.reflectivityColor = material.reflectivityColor.toLinearSpace();
+        }
+
+        if (material.bumpTexture) {
+            material.bumpTexture.level = 1;
+            // Normal maps are currently DirectX convention instead of OpenGL.
+            material.invertNormalMapY = true;
+        }
+
+        if (material.emissiveTexture) {
+            material.emissiveColor = Color3.White();
+        }
+
+        material.useRadianceOcclusion = false;
+        material.useHorizonOcclusion = false;
+        material.useAlphaFresnel = material.needAlphaBlending();
+        material.backFaceCulling = material.forceDepthWrite;
+        material.twoSidedLighting = true;
+        material.useSpecularOverAlpha = false;
+        material.useRadianceOverAlpha = false;
+        material.usePhysicalLightFalloff = true;
+        material.forceNormalForward = true;
+    }
+}

+ 15 - 1
Viewer/src/loader/plugins/index.ts

@@ -1,5 +1,8 @@
 import { TelemetryLoaderPlugin } from "./telemetryLoaderPlugin";
 import { ILoaderPlugin } from "./loaderPlugin";
+import { MSFTLodLoaderPlugin } from './msftLodLoaderPlugin';
+import { MinecraftLoaderPlugin } from './minecraftLoaderPlugin';
+import { ExtendedMaterialLoaderPlugin } from './extendedMaterialLoaderPlugin';
 
 const pluginCache: { [key: string]: ILoaderPlugin } = {};
 
@@ -7,6 +10,17 @@ export function getLoaderPluginByName(name: string) {
     switch (name) {
         case 'telemetry':
             pluginCache[name] = new TelemetryLoaderPlugin();
-            return pluginCache[name];
+            break;
+        case 'msftLod':
+            pluginCache[name] = new MSFTLodLoaderPlugin();
+            break;
+        case 'minecraft':
+            pluginCache[name] = new MSFTLodLoaderPlugin();
+            break;
+        case 'extendedMaterial':
+            pluginCache[name] = new ExtendedMaterialLoaderPlugin();
+            break;
     }
+
+    return pluginCache[name];
 }

+ 39 - 0
Viewer/src/loader/plugins/minecraftLoaderPlugin.ts

@@ -0,0 +1,39 @@
+import { ILoaderPlugin } from "./loaderPlugin";
+import { telemetryManager } from "../../telemetryManager";
+import { ViewerModel } from "../..";
+import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material } from "babylonjs";
+import { IGLTFLoaderData, GLTF2 } from "babylonjs-loaders";
+
+
+export class MinecraftLoaderPlugin implements ILoaderPlugin {
+
+    private _model: ViewerModel;
+
+    private _minecraftEnabled: boolean;
+
+    public onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel) {
+        this._model = model;
+        this._minecraftEnabled = false;
+    }
+
+    public inParsed(data: IGLTFLoaderData) {
+        if (data && data.json && data.json['meshes'] && data.json['meshes'].length) {
+            var meshes = data.json['meshes'] as GLTF2.IMesh[];
+            for (var i = 0; i < meshes.length; i++) {
+                var mesh = meshes[i];
+                if (mesh && mesh.extras && mesh.extras.MSFT_minecraftMesh) {
+                    this._minecraftEnabled = true;
+                    break;
+                }
+            }
+        }
+    }
+
+    public onMaterialLoaded(material: Material) {
+        if (this._minecraftEnabled && material.needAlphaBlending()) {
+            material.forceDepthWrite = true;
+            material.backFaceCulling = true;
+            material.separateCullingPass = true;
+        }
+    }
+}

+ 23 - 0
Viewer/src/loader/plugins/msftLodLoaderPlugin.ts

@@ -0,0 +1,23 @@
+import { ILoaderPlugin } from "./loaderPlugin";
+import { telemetryManager } from "../../telemetryManager";
+import { ViewerModel } from "../..";
+import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs";
+import { IGLTFLoaderExtension, GLTF2 } from "babylonjs-loaders";
+
+
+export class MSFTLodLoaderPlugin implements ILoaderPlugin {
+
+    private _model: ViewerModel;
+
+    public onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel) {
+        this._model = model;
+    }
+
+    public onExtensionLoaded(extension: IGLTFLoaderExtension) {
+        if (extension.name === "MSFT_lod" && this._model.configuration.loaderConfiguration) {
+            const MSFT_lod = extension as GLTF2.Extensions.MSFT_lod;
+            MSFT_lod.enabled = !!this._model.configuration.loaderConfiguration.progressiveLoading;
+            MSFT_lod.maxLODsToLoad = this._model.configuration.loaderConfiguration.maxLODsToLoad || Number.MAX_VALUE;
+        }
+    }
+}

+ 3 - 1
Viewer/src/model/viewerModel.ts

@@ -1,5 +1,5 @@
 import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, Animatable, AbstractMesh, Tools, Scene, SceneLoader, Observable, SceneLoaderProgressEvent, Tags, ParticleSystem, Skeleton, IDisposable, Nullable, Animation, Quaternion, Material, Vector3, AnimationPropertiesOverride } from "babylonjs";
-import { GLTFFileLoader } from "babylonjs-loaders";
+import { GLTFFileLoader, GLTF2 } from "babylonjs-loaders";
 import { IModelConfiguration } from "../configuration/configuration";
 import { IModelAnimation, GroupModelAnimation, AnimationPlayMode } from "./modelAnimation";
 
@@ -78,6 +78,8 @@ export class ViewerModel implements IDisposable {
      * A loadID provided by the modelLoader, unique to ths (Abstract)Viewer instance.
      */
     public loadId: number;
+
+    public loadInfo: GLTF2.IAsset;
     private _loadedUrl: string;
     private _modelConfiguration: IModelConfiguration;
 

+ 8 - 0
Viewer/src/viewer/viewer.ts

@@ -173,6 +173,14 @@ export abstract class AbstractViewer {
             if (this._configuration.observers) {
                 this._configureObservers(this._configuration.observers);
             }
+            if (this._configuration.loaderPlugins) {
+                // TODO should plugins be removed?
+                Object.keys(this._configuration.loaderPlugins).forEach((name => {
+                    if (this._configuration.loaderPlugins && this._configuration.loaderPlugins[name]) {
+                        this.modelLoader.addPlugin(name);
+                    }
+                }))
+            }
             // initialize the templates
             let templateConfiguration = this._configuration.templates || {};
             this.templateManager.initTemplate(templateConfiguration);