diff --git a/src/experiences/factories/ExperienceBased.factory.ts b/src/experiences/factories/ExperienceBased.factory.ts index fc9925e..29cb514 100644 --- a/src/experiences/factories/ExperienceBased.factory.ts +++ b/src/experiences/factories/ExperienceBased.factory.ts @@ -1,11 +1,16 @@ -// +import { EventEmitter } from "events"; + +// BLUEPRINTS import type { ExperienceFactory } from "./Experience.factory"; // INTERFACES import type { ExperienceBase } from "@/interfaces/experienceBase"; /** Represent a class that depend on {@link ExperienceFactory}. */ -export abstract class ExperienceBasedFactory implements ExperienceBase { +export abstract class ExperienceBasedFactory + extends EventEmitter + implements ExperienceBase +{ protected abstract readonly _experience: ExperienceFactory; public abstract construct(): unknown; diff --git a/src/experiences/pages/Home/Camera.ts b/src/experiences/pages/Home/Camera.ts index a9ba5b0..541a973 100644 --- a/src/experiences/pages/Home/Camera.ts +++ b/src/experiences/pages/Home/Camera.ts @@ -29,7 +29,7 @@ export class Camera implements ExperienceBase { if (!(this._appCamera?.instance instanceof PerspectiveCamera)) return; this._appCamera.instance.fov = this.initialCameraFov; - this._appCamera.instance.far = 50; + this._appCamera.instance.far = 500; this._appCamera.miniCamera?.position.set(10, 8, 30); if (this._appDebug?.cameraControls) { diff --git a/src/experiences/pages/Home/Debug.ts b/src/experiences/pages/Home/Debug.ts index 8a84af9..28cb1e2 100644 --- a/src/experiences/pages/Home/Debug.ts +++ b/src/experiences/pages/Home/Debug.ts @@ -1,5 +1,6 @@ import { BufferGeometry, + CameraHelper, Line, LineBasicMaterial, Mesh, @@ -8,7 +9,7 @@ import { SphereGeometry, Vector3, } from "three"; -import GUI from "lil-gui"; +import GUI from "three/examples/jsm/libs/lil-gui.module.min.js"; // EXPERIENCE import Experience from "."; @@ -20,6 +21,7 @@ export default class Debug implements ExperienceBase { protected readonly _experience = new Experience(); protected readonly _appDebug = this._experience.app.debug; protected readonly _appCamera = this._experience.app.camera; + protected _worldSecondaryCameraHelper?: CameraHelper; /** Graphic user interface of the experience instance */ protected _gui?: GUI; @@ -50,15 +52,18 @@ export default class Debug implements ExperienceBase { if (!this._gui || !this._experience.world) return; - // this._gui.add( - // { destruct_experience: () => this._experience?.destruct() }, - // "destruct_experience" - // ); - this.cameraLookAtPointIndicator = new Mesh( new SphereGeometry(0.1, 12, 12), new MeshBasicMaterial({ color: "#ff0040" }) ); + this.cameraLookAtPointIndicator.visible = false; + + if (!this._experience.world?.secondaryCamera) return; + + this._worldSecondaryCameraHelper = new CameraHelper( + this._experience.world.secondaryCamera + ); + this._experience.app.scene.add(this._worldSecondaryCameraHelper); this._gui .add( @@ -120,17 +125,6 @@ export default class Debug implements ExperienceBase { ) .name("Toggle auto camera animation"); - this._gui - .add( - { - fn: () => { - this._experience.world?.nextScene(); - }, - }, - "fn" - ) - .name("Next Scene"); - this._experience.app.scene.add( this._cameraCurvePathLine, this.cameraLookAtPointIndicator diff --git a/src/experiences/pages/Home/Loader.ts b/src/experiences/pages/Home/Loader.ts index 9dfc373..4c4843f 100644 --- a/src/experiences/pages/Home/Loader.ts +++ b/src/experiences/pages/Home/Loader.ts @@ -1,4 +1,4 @@ -import { Mesh, MeshBasicMaterial, SRGBColorSpace, Texture } from "three"; +import { MeshBasicMaterial, Texture, SRGBColorSpace } from "three"; import EventEmitter from "events"; // --- diff --git a/src/experiences/pages/Home/Renderer.ts b/src/experiences/pages/Home/Renderer.ts index d562bd0..ef69cff 100644 --- a/src/experiences/pages/Home/Renderer.ts +++ b/src/experiences/pages/Home/Renderer.ts @@ -1,10 +1,14 @@ import { ACESFilmicToneMapping, + Box3, + Matrix4, + Mesh, PCFShadowMap, + PerspectiveCamera, SRGBColorSpace, Vector3, + WebGLRenderTarget, } from "three"; -import * as CameraUtils from "three/examples/jsm/utils/CameraUtils"; // EXPERIENCE import HomeExperience from "."; @@ -14,21 +18,33 @@ import { type ExperienceBase } from "@/interfaces/experienceBase"; export interface PortalAssets { mesh: THREE.Mesh; - texture: THREE.WebGLRenderTarget; - camera: THREE.PerspectiveCamera; + meshWebGLTexture: THREE.WebGLRenderTarget; + meshCamera: THREE.PerspectiveCamera; +} + +export interface PortalMeshCorners { + bottomLeft: Vector3; + bottomRight: Vector3; + topLeft: Vector3; + topRight: Vector3; } /** Renderer */ export default class Renderer implements ExperienceBase { protected readonly _experience = new HomeExperience(); protected readonly _appRenderer = this._experience.app.renderer; + protected readonly _appRendererInstance = + this._experience.app.renderer.instance; protected readonly _renderPortalAssets: { - [callbackName: string]: PortalAssets; + [callbackName: string]: { + assets: PortalAssets; + corners: PortalMeshCorners; + }; } = {}; - protected _currentRenderTarget = this._appRenderer.instance.getRenderTarget(); - protected _currentXrEnabled = this._appRenderer.instance.xr.enabled; + protected _currentRenderTarget = this._appRendererInstance.getRenderTarget(); + protected _currentXrEnabled = this._appRendererInstance.xr.enabled; protected _currentShadowAutoUpdate = - this._appRenderer.instance.shadowMap.autoUpdate; + this._appRendererInstance.shadowMap.autoUpdate; protected _portalBottomLeftCorner = new Vector3(); protected _portalBottomRightCorner = new Vector3(); protected _portalTopLeftCorner = new Vector3(); @@ -37,21 +53,23 @@ export default class Renderer implements ExperienceBase { constructor() {} public construct() { - this._appRenderer.instance.useLegacyLights = true; - this._appRenderer.instance.outputColorSpace = SRGBColorSpace; - this._appRenderer.instance.toneMapping = ACESFilmicToneMapping; - this._appRenderer.instance.toneMappingExposure = 1; - this._appRenderer.instance.shadowMap.enabled = false; - this._appRenderer.instance.shadowMap.type = PCFShadowMap; - this._appRenderer.instance.setClearColor("#211d20"); - this._appRenderer.instance.setSize( - this._experience.app.sizes.width, - this._experience.app.sizes.height - ); - this._appRenderer.instance.setPixelRatio( - this._experience.app.sizes.pixelRatio - ); - this._appRenderer.instance.localClippingEnabled = true; + // Configure renderer behaviors + ~(() => { + this._appRendererInstance.outputColorSpace = SRGBColorSpace; + this._appRendererInstance.toneMapping = ACESFilmicToneMapping; + this._appRendererInstance.toneMappingExposure = 1; + this._appRendererInstance.shadowMap.enabled = false; + this._appRendererInstance.shadowMap.type = PCFShadowMap; + this._appRendererInstance.setClearColor("#211d20"); + this._appRendererInstance.setSize( + this._experience.app.sizes.width, + this._experience.app.sizes.height + ); + this._appRendererInstance.setPixelRatio( + this._experience.app.sizes.pixelRatio + ); + this._appRendererInstance.localClippingEnabled = true; + })(); ~(() => { this._appRenderer.beforeRenderUpdate = () => { @@ -60,24 +78,23 @@ export default class Renderer implements ExperienceBase { Object.keys(this._renderPortalAssets).forEach((key: string) => { if (this._renderPortalAssets[key]) { this._currentRenderTarget = - this._appRenderer.instance.getRenderTarget(); - this._currentXrEnabled = this._appRenderer.instance.xr.enabled; + this._appRendererInstance.getRenderTarget(); + this._currentXrEnabled = this._appRendererInstance.xr.enabled; this._currentShadowAutoUpdate = - this._appRenderer.instance.shadowMap.autoUpdate; - // Avoid camera modification - this._appRenderer.instance.xr.enabled = false; - // Avoid re-computing shadows - this._appRenderer.instance.shadowMap.autoUpdate = false; + this._appRendererInstance.shadowMap.autoUpdate; + this._appRendererInstance.xr.enabled = false; + this._appRendererInstance.shadowMap.autoUpdate = false; this.renderPortal( - this._renderPortalAssets[key].mesh, - this._renderPortalAssets[key].texture, - this._renderPortalAssets[key].camera + this._renderPortalAssets[key].assets.mesh, + this._renderPortalAssets[key].assets.meshWebGLTexture, + this._renderPortalAssets[key].assets.meshCamera, + this._renderPortalAssets[key].corners ); // restore the original rendering properties - this._appRenderer.instance.xr.enabled = this._currentXrEnabled; - this._appRenderer.instance.shadowMap.autoUpdate = + this._appRendererInstance.xr.enabled = this._currentXrEnabled; + this._appRendererInstance.shadowMap.autoUpdate = this._currentShadowAutoUpdate; - this._appRenderer.instance.setRenderTarget( + this._appRendererInstance.setRenderTarget( this._currentRenderTarget ); } @@ -92,49 +109,78 @@ export default class Renderer implements ExperienceBase { } public renderPortal( - mesh: THREE.Mesh, - texture: THREE.WebGLRenderTarget, - portalCamera: THREE.PerspectiveCamera + mesh: Mesh, + meshWebGLTexture: WebGLRenderTarget, + portalCamera: PerspectiveCamera, + corners: PortalMeshCorners ) { - // set the portal camera position to be reflected about the portal plane - mesh.worldToLocal( - this._portalReflectedPosition.copy( - this._experience.app.camera.instance?.position ?? new Vector3() + mesh.localToWorld( + this._portalBottomLeftCorner.set( + corners.bottomLeft.x, + corners.bottomLeft.y, + corners.bottomLeft.z ) ); - this._portalReflectedPosition.x *= -1.0; - this._portalReflectedPosition.z *= -1.0; - - mesh.localToWorld(this._portalReflectedPosition); - portalCamera.position.copy(this._portalReflectedPosition); - - mesh.localToWorld(this._portalBottomLeftCorner.set(50.05, -50.05, 0.0)); - mesh.localToWorld(this._portalBottomRightCorner.set(-50.05, -50.05, 0.0)); - mesh.localToWorld(this._portalTopLeftCorner.set(50.05, 50.05, 0.0)); - - // set the projection matrix to encompass the portal's frame - CameraUtils.frameCorners( - portalCamera, - this._portalBottomLeftCorner, - this._portalBottomRightCorner, - this._portalTopLeftCorner, - false + mesh.localToWorld( + this._portalBottomRightCorner.set( + corners.bottomRight.x, + corners.bottomRight.y, + corners.bottomRight.z + ) + ); + mesh.localToWorld( + this._portalTopLeftCorner.set( + corners.topLeft.x, + corners.topLeft.y, + corners.topLeft.z + ) ); - // render the portal - texture.texture.colorSpace = this._appRenderer.instance.outputColorSpace; - - this._appRenderer.instance.setRenderTarget(texture); - this._appRenderer.instance.state.buffers.depth.setMask(true); // making sure the depth buffer is writable so it can be properly cleared, see #18897 - if (this._appRenderer.instance.autoClear === false) - this._appRenderer.instance.clear(); - mesh.visible = false; // hide this portal from its own rendering - this._appRenderer.instance.render(this._experience.app.scene, portalCamera); - mesh.visible = true; // re-enable this portal's visibility for general rendering + this._appRendererInstance.setRenderTarget(meshWebGLTexture); + this._appRendererInstance.state.buffers.depth.setMask(true); + if (this._appRendererInstance.autoClear === false) + this._appRendererInstance.clear(); + mesh.visible = false; + this._appRendererInstance.render(this._experience.app.scene, portalCamera); + mesh.visible = true; } public addPortalMeshAssets(portalName: string, assets: PortalAssets): void { - this._renderPortalAssets[portalName] = assets; + // Calculate width, height + const boundingBox = new Box3().setFromObject(assets.mesh); + const width = boundingBox.max.x - boundingBox.min.x; + const height = boundingBox.max.y - boundingBox.min.y; + const halfWidth = width / 2; + const halfHeight = height / 2; + + // Define the corners of the plane in local coordinates + const corners = [ + new Vector3(-halfWidth, -halfHeight, 0), + new Vector3(halfWidth, -halfHeight, 0), + new Vector3(-halfWidth, halfHeight, 0), + new Vector3(halfWidth, halfHeight, 0), + ]; + + // Apply the mesh's position and rotation to the corners + const matrix = new Matrix4(); + matrix.makeRotationFromQuaternion(assets.mesh.quaternion); + matrix.setPosition(assets.mesh.position); + matrix.compose( + assets.mesh.position, + assets.mesh.quaternion, + assets.mesh.scale + ); + corners.map((corner) => corner.applyMatrix4(matrix)); + + this._renderPortalAssets[portalName] = { + assets, + corners: { + bottomLeft: corners[0], + bottomRight: corners[1], + topLeft: corners[2], + topRight: corners[3], + }, + }; } public removeBeforeUpdateCallback(portalName: string): void { diff --git a/src/experiences/pages/Home/World/Scene_1.ts b/src/experiences/pages/Home/World/Scene_1.ts index 3bb267c..2eccc59 100644 --- a/src/experiences/pages/Home/World/Scene_1.ts +++ b/src/experiences/pages/Home/World/Scene_1.ts @@ -1,9 +1,14 @@ import { CatmullRomCurve3, + Color, + Group, Material, Mesh, MeshBasicMaterial, + NoColorSpace, PerspectiveCamera, + PlaneGeometry, + RawShaderMaterial, Vector3, WebGLRenderTarget, } from "three"; @@ -15,9 +20,18 @@ import { SceneFactory } from "@/experiences/factories/SceneFactory"; // CONSTANTS import { GSAP_DEFAULT_INTRO_PROPS } from "@/constants/ANIMATION"; +// SHADERS +import fragment from "./shaders/scene1/fragment.frag"; +import vertex from "./shaders/scene1/vertex.vert"; + export default class Scene_1 extends SceneFactory { protected _renderer = this._experience.renderer; + public pcScreenWebglTexture?: WebGLRenderTarget; + public pcScreen?: Mesh; + + modelScene2?: Group; + constructor() { try { super({ @@ -35,7 +49,7 @@ export default class Scene_1 extends SceneFactory { linkedTextureName: "scene_1_room_baked_texture", }, { - childName: "scene_1_room_woods", + childName: "scene_1_woods", linkedTextureName: "scene_1_room_woods_baked_texture", }, ], @@ -48,34 +62,33 @@ export default class Scene_1 extends SceneFactory { this.modelScene = this._model?.scene.clone(); if (!this.modelScene) return; - this.cameraPath.getPointAt(0, this._appCamera.instance.position); - this._appCamera.instance.position.y += 8; - this._appCamera.instance.position.x -= 2; - this._appCamera.instance.position.z += 10; - try { this.modelScene.children.forEach((child) => { - if (child.name === "scene_1_room_pc_screen") + if (child.name === "scene_1_pc_screen") throw new Error("CHILD_FOUND", { cause: child }); }); } catch (_err) { if (_err instanceof Error && _err.cause instanceof Mesh) { - const mesh = _err.cause; - const camera = new PerspectiveCamera(75, 1.0, 0.1, 500.0); - const texture = new WebGLRenderTarget(256, 256); - mesh.material = new MeshBasicMaterial({ map: texture.texture }); - - this._renderer?.addPortalMeshAssets(Scene_1.name + "_screen_pc", { - mesh, - camera, - texture, + const planeGeo = new PlaneGeometry(1.25, 0.6728); + this.pcScreenWebglTexture = new WebGLRenderTarget(4096, 4096); + this.pcScreen = new Mesh(planeGeo); + this.pcScreen.material = new MeshBasicMaterial({ + map: this.pcScreenWebglTexture.texture, }); + + // TODO:: Correctly setup the portal by passing the texture to the screen it self + this.pcScreen.rotateY(Math.PI * 0.271); + this.pcScreen.rotateX(Math.PI * -0.03); + this.pcScreen.position.z += 0.048; + this.pcScreen.position.x -= 0.01; + _err.cause.localToWorld(this.pcScreen.position); + _err.cause.removeFromParent(); + + this.modelScene.add(this.pcScreen); } } this._setModelMaterials(); - this._experience.world?.group?.add(this.modelScene); - this.emit("constructed"); } @@ -89,6 +102,7 @@ export default class Scene_1 extends SceneFactory { onComplete: () => { this.modelScene?.clear(); this.modelScene?.removeFromParent(); + this._renderer?.removeBeforeUpdateCallback(Scene_1.name + "_screen_pc"); this.emit(this.eventListNames.destructed); }, }); @@ -131,4 +145,38 @@ export default class Scene_1 extends SceneFactory { public outro(): void {} public update(): void {} + + protected _setModelMaterials() { + const TEXTURES_MESH_BASIC_MATERIALS = + this._Loader?.texturesMeshBasicMaterials; + + if (!TEXTURES_MESH_BASIC_MATERIALS) return; + + this.modelScene?.children.forEach((child) => { + this._modelChildrenTextures.forEach((item) => { + const CHILD_TEXTURE = + TEXTURES_MESH_BASIC_MATERIALS[item.linkedTextureName].clone(); + + if ( + child instanceof Mesh && + child.name === item.childName && + CHILD_TEXTURE.map + ) { + const MAP_TEXTURE = CHILD_TEXTURE.map.clone(); + MAP_TEXTURE.colorSpace = NoColorSpace; + + ~(child.material = new RawShaderMaterial({ + uniforms: { + uBakedTexture: { value: MAP_TEXTURE }, + uTime: { value: 0 }, + uColor: { value: new Color(0x00ff00) }, + }, + fragmentShader: fragment, + vertexShader: vertex, + transparent: true, + })); + } + }); + }); + } } diff --git a/src/experiences/pages/Home/World/Scene_2.ts b/src/experiences/pages/Home/World/Scene_2.ts index 3f70670..24e2215 100644 --- a/src/experiences/pages/Home/World/Scene_2.ts +++ b/src/experiences/pages/Home/World/Scene_2.ts @@ -19,31 +19,26 @@ export default class Scene_2 extends SceneFactory { new Vector3(12, 3.7, 12), new Vector3(0, 5.5, 21), ]), + modelName: "scene_1_room", modelChildrenTextures: [ { childName: "scene_1_room", linkedTextureName: "scene_1_room_baked_texture", }, + { + childName: "scene_1_woods", + linkedTextureName: "scene_1_room_woods_baked_texture", + }, ], }); } catch (error) {} } construct() { - if (!this._appCamera.instance) return; - - const ISOMETRIC_ROOM = this._experience.app.resources.items.scene_1_room as - | GLTF - | undefined; - - this.cameraPath.getPointAt(0, this._appCamera.instance.position); - this._appCamera.instance.position.y += 8; - this._appCamera.instance.position.x -= 2; - this._appCamera.instance.position.z += 10; + this.modelScene = this._model?.scene.clone(); + if (!this.modelScene) return; - this.model = ISOMETRIC_ROOM; - this.modelScene = this.model?.scene.clone(); - this.modelScene && this._experience.world?.group?.add(this.modelScene); + this.modelScene.position.set(20, 0, 0); this._setModelMaterials(); this.emit("constructed"); diff --git a/src/experiences/pages/Home/World/Scene_3.ts b/src/experiences/pages/Home/World/Scene_3.ts index 31fd225..a86ca9e 100644 --- a/src/experiences/pages/Home/World/Scene_3.ts +++ b/src/experiences/pages/Home/World/Scene_3.ts @@ -1,5 +1,4 @@ import { CatmullRomCurve3, PerspectiveCamera, Vector3 } from "three"; -import { type GLTF } from "three/examples/jsm/loaders/GLTFLoader.js"; import GSAP from "gsap"; // EXPERIENCES @@ -19,31 +18,26 @@ export default class Scene_3 extends SceneFactory { new Vector3(12, 3.7, 12), new Vector3(0, 5.5, 21), ]), + modelName: "scene_1_room", modelChildrenTextures: [ { childName: "scene_1_room", linkedTextureName: "scene_1_room_baked_texture", }, + { + childName: "scene_1_woods", + linkedTextureName: "scene_1_room_woods_baked_texture", + }, ], }); } catch (error) {} } construct() { - if (!this._appCamera.instance) return; - - const ISOMETRIC_ROOM = this._experience.app.resources.items.scene_1_room as - | GLTF - | undefined; - - this.cameraPath.getPointAt(0, this._appCamera.instance.position); - this._appCamera.instance.position.y += 8; - this._appCamera.instance.position.x -= 2; - this._appCamera.instance.position.z += 10; + this.modelScene = this._model?.scene.clone(); + if (!this.modelScene) return; - this.model = ISOMETRIC_ROOM; - this.modelScene = this.model?.scene.clone(); - this.modelScene && this._experience.world?.group?.add(this.modelScene); + this.modelScene.position.set(18, 0, 0); this._setModelMaterials(); this.emit("constructed"); diff --git a/src/experiences/pages/Home/World/index.ts b/src/experiences/pages/Home/World/index.ts index 797b865..7f6c9fc 100644 --- a/src/experiences/pages/Home/World/index.ts +++ b/src/experiences/pages/Home/World/index.ts @@ -1,5 +1,4 @@ -import { Group, Mesh, PerspectiveCamera } from "three"; -import EventEmitter from "events"; +import { Group, Mesh, PerspectiveCamera, Vector3 } from "three"; // EXPERIENCE import Experience from ".."; @@ -7,16 +6,20 @@ import Controls from "./Controls"; import Scene_1 from "./Scene_1"; import Scene_2 from "./Scene_2"; import Scene_3 from "./Scene_3"; -import { SceneFactory } from "@/experiences/factories/SceneFactory"; -// INTERFACES -import { type ExperienceBase } from "@/interfaces/experienceBase"; +// BLUEPRINTS +import { ExperienceBasedFactory } from "@/experiences/factories/ExperienceBased.factory"; -export default class World extends EventEmitter implements ExperienceBase { +export default class World extends ExperienceBasedFactory { protected readonly _experience = new Experience(); + protected readonly _appCamera = this._experience.app.camera; + protected readonly _renderer = this._experience.renderer; + private scene1?: Scene_1; + private scene2?: Scene_2; + private scene3?: Scene_3; + public secondaryCamera?: PerspectiveCamera; public controls?: Controls; - public scenes?: SceneFactory[] = []; public currentSceneIndex?: number; /** Represent the ThreeJs `Group` containing the experience. */ public group?: Group; @@ -41,9 +44,10 @@ export default class World extends EventEmitter implements ExperienceBase { } }); - this.scenes?.forEach((group) => { - group.destruct(); - }); + this.scene1?.destruct(); + this.scene2?.destruct(); + this.scene3?.destruct(); + this._experience.app.scene.remove(this.group); this.group?.clear(); @@ -52,77 +56,59 @@ export default class World extends EventEmitter implements ExperienceBase { } public construct() { - this._experience.loader?.on("load", () => { - if (!(this._experience.app.camera.instance instanceof PerspectiveCamera)) - return; + if (!(this._experience.app.camera.instance instanceof PerspectiveCamera)) + return; + + this.group = new Group(); + this.controls = new Controls(); + + this.scene1 = new Scene_1(); + this.scene2 = new Scene_2(); + // this.scene3 = new Scene_3(); + + this.scene1.construct(); + this.scene2.construct(); + // this.scene3.construct(); + + this.secondaryCamera = new PerspectiveCamera( + (this._appCamera.instance as PerspectiveCamera).fov, + (this._appCamera.instance as PerspectiveCamera).aspect, + (this._appCamera.instance as PerspectiveCamera).near, + (this._appCamera.instance as PerspectiveCamera).far + ); + + this.secondaryCamera.position.copy( + this.scene2.modelScene?.position ?? new Vector3() + ); + this.secondaryCamera.position.set( + this.scene2.modelScene?.position.x ?? 0, + 8, + 30 + ); + this.secondaryCamera.lookAt( + this.scene2.modelScene?.position ?? new Vector3() + ); + + if (this.scene1.pcScreen && this.scene1.pcScreenWebglTexture) + this._renderer?.addPortalMeshAssets(Scene_1.name + "_pc_screen", { + mesh: this.scene1.pcScreen, + meshCamera: this.secondaryCamera, + meshWebGLTexture: this.scene1.pcScreenWebglTexture, + }); - this.group = new Group(); - this.controls = new Controls(); + this.scene1.modelScene && this.group.add(this.scene1.modelScene); + this.scene2.modelScene && this.group.add(this.scene2.modelScene); - this.scenes?.push(new Scene_1(), new Scene_2(), new Scene_3()); - this._experience.app.scene.add(this.group); - this.nextScene(); - }); + this._experience.app.scene.add(this.group); } - public nextScene() { - try { - if (!this.scenes || !this.scenes.length) return; - - const PREV_INDEX = this.currentSceneIndex; - - ~(() => { - if ( - typeof this.currentSceneIndex === "number" && - this.currentSceneIndex + 2 <= this.scenes.length - ) - this.currentSceneIndex += 1; - else this.currentSceneIndex = 0; - })(); - - ~(() => { - const PrevScene = - typeof PREV_INDEX === "number" ? this.scenes[PREV_INDEX] : PREV_INDEX; - const CurrentScene = this.scenes[this.currentSceneIndex]; - - const constructCurrentScene = () => { - CurrentScene.construct(); - PrevScene?.off( - PrevScene.eventListNames.destructed, - constructCurrentScene - ); - }; - - if (PrevScene) { - PrevScene.on( - PrevScene.eventListNames.destructed, - constructCurrentScene - ); - - PrevScene.destruct(); - } else constructCurrentScene(); - })(); - } catch (error) { - // TODO: Add an error handler - console.error(`🚧 ${World.name}->${this.nextScene.name}`, error); - } - } + public nextScene() {} - public prevScene() { - if (!this.scenes) return; - if (this.currentSceneIndex === undefined) this.currentSceneIndex = 0; - } + public prevScene() {} public setScene(index: number) {} public update() { this.controls?.update(); - - // Current Scene update - // ~(() => { - // this.currentSceneIndex !== undefined && - // this.scenes !== undefined && - // this.scenes[this.currentSceneIndex]?.update(); - // })(); } } diff --git a/src/experiences/pages/Home/index.ts b/src/experiences/pages/Home/index.ts index fbf9afe..2031adc 100644 --- a/src/experiences/pages/Home/index.ts +++ b/src/experiences/pages/Home/index.ts @@ -59,14 +59,16 @@ export class HomeExperience extends ExperienceFactory { this.renderer?.construct(); this.ui?.construct(); - this.loader?.construct(); this.camera?.construct(); - this.world?.construct(); - this.debug?.construct(); - - this.app?.setUpdateCallback(HomeExperience.name, () => this.update()); + this.loader?.construct(); - this._onConstruct && this._onConstruct(); + this.loader?.on("load", () => { + this.world?.construct(); + this.world?.on("constructed", () => console.log("Launched here ==>")); + this.debug?.construct(); + this.app?.setUpdateCallback(HomeExperience.name, () => this.update()); + this._onConstruct && this._onConstruct(); + }); } public update() { diff --git a/src/layouts/default.vue b/src/layouts/default.vue index cadb01b..0d7b784 100644 --- a/src/layouts/default.vue +++ b/src/layouts/default.vue @@ -1,11 +1,11 @@ diff --git a/src/pages/index.vue b/src/pages/index.vue index 33ce6f8..3888422 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -38,7 +38,7 @@ onBeforeUnmount(() => setTimeout(() => endExperience(), 500));