diff --git a/packages/frontend/assets/room/rooms/museum/museum.blend b/packages/frontend/assets/room/rooms/museum/museum.blend index 2924daa0ae..e5ae22a648 100644 Binary files a/packages/frontend/assets/room/rooms/museum/museum.blend and b/packages/frontend/assets/room/rooms/museum/museum.blend differ diff --git a/packages/frontend/assets/room/rooms/museum/museum.glb b/packages/frontend/assets/room/rooms/museum/museum.glb new file mode 100644 index 0000000000..0a6364e5df Binary files /dev/null and b/packages/frontend/assets/room/rooms/museum/museum.glb differ diff --git a/packages/frontend/src/world/room/engine.ts b/packages/frontend/src/world/room/engine.ts index 57fbf36b8a..09c88d3c64 100644 --- a/packages/frontend/src/world/room/engine.ts +++ b/packages/frontend/src/world/room/engine.ts @@ -18,7 +18,7 @@ import { EventEmitter } from 'eventemitter3'; import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraManualInput, remap } from '../utility.js'; import { getObjectDef } from './object-defs.js'; import { findMaterial, ModelManager, SYSTEM_HEYA_MESH_NAMES, SYSTEM_MESH_NAMES } from './utility.js'; -import { SimpleHeyaManager } from './heya.js'; +import { MuseumHeyaManager, SimpleHeyaManager } from './heya.js'; import type { GridMaterial } from '@babylonjs/materials'; import type { HeyaManager, JapaneseHeyaOptions, SimpleHeyaOptions } from './heya.js'; import type { ObjectDef, RoomObjectInstance, RoomStateObject } from './object.js'; @@ -893,6 +893,10 @@ export class RoomEngine extends EventEmitter { this.heyaManager = heyaManager; } else if (this.roomState.heya.type === 'japanese') { // TODO + } else if (this.roomState.heya.type === 'museum') { + const heyaManager = new MuseumHeyaManager(onMeshUpdatedCallback); + await heyaManager.load(this.roomState.heya.options, this.scene); + this.heyaManager = heyaManager; } if (!forInit) { diff --git a/packages/frontend/src/world/room/heya.ts b/packages/frontend/src/world/room/heya.ts index dcc972f084..47c9e4bb4a 100644 --- a/packages/frontend/src/world/room/heya.ts +++ b/packages/frontend/src/world/room/heya.ts @@ -324,3 +324,63 @@ export class SimpleHeyaManager extends HeyaManager { } } } + +export type MuseumHeyaOptions = any; + +export class MuseumHeyaManager extends HeyaManager { + private loaderResult: BABYLON.ISceneLoaderAsyncResult | null = null; + private meshes: BABYLON.Mesh[] = []; + + constructor(onMeshUpdatedCallback?: ((meshes: BABYLON.AbstractMesh[]) => void) | null) { + super(onMeshUpdatedCallback); + } + + public async load(options: MuseumHeyaOptions, scene: BABYLON.Scene) { + this.loaderResult = await BABYLON.ImportMeshAsync('/client-assets/room/rooms/default/300.glb', scene); + + this.meshes = this.loaderResult.meshes.filter(m => m instanceof BABYLON.Mesh); + this.meshes[0].scaling = this.meshes[0].scaling.scale(WORLD_SCALE); + this.meshes[0].rotationQuaternion = null; + this.meshes[0].rotation = new BABYLON.Vector3(0, 0, 0); + + // instanced mesh を通常の mesh に変換 (そうしないとマテリアルが共有される) + for (const mesh of this.loaderResult.meshes) { + if (mesh instanceof BABYLON.InstancedMesh) { + const realizedMesh = mesh.sourceMesh.clone(mesh.name, null, true); + + realizedMesh.position = mesh.position.clone(); + if (mesh.rotationQuaternion) { + realizedMesh.rotationQuaternion = mesh.rotationQuaternion.clone(); + } else { + realizedMesh.rotation = mesh.rotation.clone(); + } + realizedMesh.scaling = mesh.scaling.clone(); + realizedMesh.parent = mesh.parent; + + mesh.dispose(); + scene.removeMesh(mesh); + this.meshes.push(realizedMesh); + } + } + + await this.applyOptions(options); + } + + public applyOptions(options: MuseumHeyaOptions) { + this.onMeshUpdatedCallback?.(this.meshes); + } + + public dispose() { + if (this.loaderResult != null) { + for (const m of this.loaderResult.meshes) { + m.dispose(false, true); + } + for (const t of this.loaderResult.transformNodes) { + t.dispose(false, true); + } + } + for (const m of this.meshes) { + m.dispose(false, true); + } + } +}