123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- import * as React from "react";
- import { GlobalState } from '../globalState';
- import { Engine } from 'babylonjs/Engines/engine';
- import { SceneLoader } from 'babylonjs/Loading/sceneLoader';
- import { GLTFFileLoader } from "babylonjs-loaders/glTF/glTFFileLoader";
- import { Scene } from 'babylonjs/scene';
- import { Vector3 } from 'babylonjs/Maths/math.vector';
- import { ArcRotateCamera } from 'babylonjs/Cameras/arcRotateCamera';
- import { FramingBehavior } from 'babylonjs/Behaviors/Cameras/framingBehavior';
- import { EnvironmentTools } from '../tools/environmentTools';
- import { Tools } from 'babylonjs/Misc/tools';
- import { FilesInput } from 'babylonjs/Misc/filesInput';
- import {Animation} from 'babylonjs/Animations/animation';
- require("../scss/renderingZone.scss");
- interface IRenderingZoneProps {
- globalState: GlobalState;
- assetUrl?: string;
- cameraPosition?: Vector3;
- expanded: boolean;
- }
- export class RenderingZone extends React.Component<IRenderingZoneProps> {
- private _currentPluginName: string;
- private _engine: Engine;
- private _scene: Scene;
- private _canvas: HTMLCanvasElement;
- public constructor(props: IRenderingZoneProps) {
- super(props);
- }
- initEngine() {
- this._canvas = document.getElementById("renderCanvas") as HTMLCanvasElement;
- this._engine = new Engine(this._canvas, true, { premultipliedAlpha: false, preserveDrawingBuffer: true });
-
- this._engine.loadingUIBackgroundColor = "#2A2342";
- // Resize
- window.addEventListener("resize", () => {
- this._engine.resize();
- });
- this.loadAsset();
- // File inputs
- let filesInput = new FilesInput(this._engine, null,
- (sceneFile: File, scene: Scene) => {
- this._scene = scene;
- this.onSceneLoaded(sceneFile.name);
- },
- null, null, null,
- () => {
- Tools.ClearLogCache();
- if (this._scene) {
- this.props.globalState.isDebugLayerEnabled = this.props.globalState.currentScene.debugLayer.isVisible();
- if (this.props.globalState.isDebugLayerEnabled) {
- this._scene.debugLayer.hide();
- }
- }
- }, null, (file, scene, message) => {
- this.props.globalState.onError.notifyObservers({ message : message});
- });
- filesInput.onProcessFileCallback = (file, name, extension) => {
- if (filesInput.filesToLoad && filesInput.filesToLoad.length === 1 && extension) {
- if (extension.toLowerCase() === "dds" ||
- extension.toLowerCase() === "env" ||
- extension.toLowerCase() === "hdr") {
- FilesInput.FilesToLoad[name] = file;
- EnvironmentTools.SkyboxPath = "file:" + (file as any).correctName;
- return false;
- }
- }
- return true;
- };
- filesInput.monitorElementForDragNDrop(this._canvas);
- this.props.globalState.filesInput = filesInput;
- window.addEventListener("keydown", (event) => {
- // Press R to reload
- if (event.keyCode === 82 && event.target && (event.target as HTMLElement).nodeName !== "INPUT" && this._scene) {
- if (this.props.assetUrl) {
- this.loadAssetFromUrl();
- }
- else {
- filesInput.reload();
- }
- }
- });
- }
- prepareCamera() {
- let camera: ArcRotateCamera;
- // Attach camera to canvas inputs
- if (!this._scene.activeCamera || this._scene.lights.length === 0) {
- this._scene.createDefaultCamera(true);
- camera = this._scene.activeCamera! as ArcRotateCamera;
- if (this.props.cameraPosition) {
- camera.setPosition(this.props.cameraPosition);
- }
- else {
- if (this._currentPluginName === "gltf") {
- // glTF assets use a +Z forward convention while the default camera faces +Z. Rotate the camera to look at the front of the asset.
- camera.alpha += Math.PI;
- }
- // Enable camera's behaviors
- camera.useFramingBehavior = true;
- var framingBehavior = camera.getBehaviorByName("Framing") as FramingBehavior;
- framingBehavior.framingTime = 0;
- framingBehavior.elevationReturnTime = -1;
- if (this._scene.meshes.length) {
- camera.lowerRadiusLimit = null;
- var worldExtends = this._scene.getWorldExtends(function (mesh) {
- return mesh.isVisible && mesh.isEnabled();
- });
- framingBehavior.zoomOnBoundingInfo(worldExtends.min, worldExtends.max);
- }
- }
- camera.pinchPrecision = 200 / camera.radius;
- camera.upperRadiusLimit = 5 * camera.radius;
- camera.wheelDeltaPercentage = 0.01;
- camera.pinchDeltaPercentage = 0.01;
- }
- this._scene.activeCamera!.attachControl(this._canvas);
- }
- handleErrors() {
- // In case of error during loading, meshes will be empty and clearColor is set to red
- if (this._scene.meshes.length === 0 && this._scene.clearColor.r === 1 && this._scene.clearColor.g === 0 && this._scene.clearColor.b === 0) {
- this._canvas.style.opacity = "0";
- this.props.globalState.onError.notifyObservers({scene: this._scene, message: "No mesh found in your scene"});
- }
- else {
- if (Tools.errorsCount > 0) {
- this.props.globalState.onError.notifyObservers({scene: this._scene, message: "Scene loaded but several errors were found"});
- }
- // this._canvas.style.opacity = "1";
- let camera = this._scene.activeCamera! as ArcRotateCamera;
- if (camera.keysUp) {
- camera.keysUp.push(90); // Z
- camera.keysUp.push(87); // W
- camera.keysDown.push(83); // S
- camera.keysLeft.push(65); // A
- camera.keysLeft.push(81); // Q
- camera.keysRight.push(69); // E
- camera.keysRight.push(68); // D
- }
- }
- }
- prepareLighting() {
- if (this._currentPluginName === "gltf") {
- if (!this._scene.environmentTexture) {
- this._scene.environmentTexture = EnvironmentTools.LoadSkyboxPathTexture(this._scene);
- }
- if (this._scene.environmentTexture) {
- this._scene.createDefaultSkybox(this._scene.environmentTexture, true, (this._scene.activeCamera!.maxZ - this._scene.activeCamera!.minZ) / 2, 0.3, false);
- }
- }
- else {
- var pbrPresent = false;
- for (var i = 0; i < this._scene.materials.length; i++) {
- if (this._scene.materials[i].transparencyMode !== undefined) {
- pbrPresent = true;
- break;
- }
- }
- if (pbrPresent) {
- if (!this._scene.environmentTexture) {
- this._scene.environmentTexture = EnvironmentTools.LoadSkyboxPathTexture(this._scene);
- }
- }
- else {
- this._scene.createDefaultLight();
- }
- }
- }
- onSceneLoaded(filename: string) {
- this._engine.clearInternalTexturesCache();
- this._scene.skipFrustumClipping = true;
- this.props.globalState.onSceneLoaded.notifyObservers({scene: this._scene, filename: filename});
- this.prepareCamera();
- this.prepareLighting();
- this.handleErrors();
- if (this.props.globalState.isDebugLayerEnabled) {
- this.props.globalState.showDebugLayer();
- }
- }
- loadAssetFromUrl() {
- let assetUrl = this.props.assetUrl!;
- let rootUrl = Tools.GetFolderPath(assetUrl);
- let fileName = Tools.GetFilename(assetUrl);
- SceneLoader.LoadAsync(rootUrl, fileName, this._engine).then((scene) => {
- if (this._scene) {
- this._scene.dispose();
- }
- this._scene = scene;
- this.onSceneLoaded(fileName);
- scene.whenReadyAsync().then(() => {
- this._engine.runRenderLoop(() => {
- scene.render();
- });
- });
- }).catch((reason) => {
- this.props.globalState.onError.notifyObservers({ message : reason.message});
- //TODO sceneError({ name: fileName }, null, reason.message || reason);
- });
- }
- loadAsset() {
- if (this.props.assetUrl) {
- this.loadAssetFromUrl();
- return;
- }
- }
- componentDidMount() {
- if (!Engine.isSupported()) {
- return;
- }
- Engine.ShadersRepository = "/src/Shaders/";
- // This is really important to tell Babylon.js to use decomposeLerp and matrix interpolation
- Animation.AllowMatricesInterpolation = true;
-
- // Setting up some GLTF values
- GLTFFileLoader.IncrementalLoading = false;
- SceneLoader.OnPluginActivatedObservable.add((plugin) =>{
- this._currentPluginName = plugin.name;
- if (this._currentPluginName === "gltf") {
- (plugin as GLTFFileLoader).onValidatedObservable.add((results) =>{
- if (results.issues.numErrors > 0) {
- this.props.globalState.showDebugLayer();
- }
- });
- }
- });
- this.initEngine();
- }
- shouldComponentUpdate(nextProps: IRenderingZoneProps) {
- if (nextProps.expanded !== this.props.expanded) {
- setTimeout(() => this._engine.resize());
- return true;
- }
- return false;
- }
- public render() {
- return (
- <div id="canvasZone" className={this.props.expanded ? "expanded" : ""}>
- <canvas id="renderCanvas" touch-action="none"
- onContextMenu={evt => evt.preventDefault()}></canvas>
- </div>
- )
- }
- }
|