diff --git a/packages/frontend/assets/room/objects/issyoubin/issyoubin.blend b/packages/frontend/assets/room/objects/issyoubin/issyoubin.blend index f9254d2706..1b2a028fe1 100644 Binary files a/packages/frontend/assets/room/objects/issyoubin/issyoubin.blend and b/packages/frontend/assets/room/objects/issyoubin/issyoubin.blend differ diff --git a/packages/frontend/assets/room/objects/issyoubin/issyoubin.glb b/packages/frontend/assets/room/objects/issyoubin/issyoubin.glb index cb904c40fb..0c813239de 100644 Binary files a/packages/frontend/assets/room/objects/issyoubin/issyoubin.glb and b/packages/frontend/assets/room/objects/issyoubin/issyoubin.glb differ diff --git a/packages/frontend/src/pages/room.vue b/packages/frontend/src/pages/room.vue index fc869198cf..99799cc312 100644 --- a/packages/frontend/src/pages/room.vue +++ b/packages/frontend/src/pages/room.vue @@ -278,13 +278,18 @@ function rotate() { } async function addObject(ev: PointerEvent) { + // 重いので止める + controller.pauseRender(); const { dispose } = await os.popupAsyncWithDialog(import('./room.add-object-dialog.vue').then(x => x.default), { }, { ok: async (res) => { controller.addObject(res); canvas.value!.focus(); }, - closed: () => dispose(), + closed: () => { + controller.resumeRender(); + dispose(); + }, }); } diff --git a/packages/frontend/src/world/room/controller.ts b/packages/frontend/src/world/room/controller.ts index 465865da58..8cecbe3e00 100644 --- a/packages/frontend/src/world/room/controller.ts +++ b/packages/frontend/src/world/room/controller.ts @@ -175,6 +175,22 @@ export class RoomController { await this.init(canvas ?? this.canvas!, workerMode); } + public pauseRender() { + if (this.worker != null) { + this.worker.postMessage({ type: 'pauseRender' }); + } else if (this.engine != null) { + this.engine.pauseRender(); + } + } + + public resumeRender() { + if (this.worker != null) { + this.worker.postMessage({ type: 'resumeRender' }); + } else if (this.engine != null) { + this.engine.resumeRender(); + } + } + public enterEditMode() { if (this.worker != null) { this.worker.postMessage({ type: 'enterEditMode' }); diff --git a/packages/frontend/src/world/room/engine.ts b/packages/frontend/src/world/room/engine.ts index 771e941695..ed7f59d214 100644 --- a/packages/frontend/src/world/room/engine.ts +++ b/packages/frontend/src/world/room/engine.ts @@ -448,30 +448,7 @@ export class RoomEngine extends EventEmitter { this.sr.enableSnapshotRendering(); } - if (this.fps == null) { - this.engine.runRenderLoop(() => { - this.scene.render(); - }); - } else { - let then = 0; - const interval = 1000 / this.fps; - - const renderLoop = (timeStamp: number) => { - if (this.disposed) return; - - window.requestAnimationFrame(renderLoop); - - const delta = timeStamp - then; - if (delta <= interval) return; - then = timeStamp - (delta % interval); - - this.engine.beginFrame(); - this.scene.render(); - this.engine.endFrame(); - }; - - window.requestAnimationFrame(renderLoop); - } + this.startRenderLoop(); this.domEvents.on('keydown', (ev) => { if (ev.code === 'KeyE') { @@ -555,6 +532,47 @@ export class RoomEngine extends EventEmitter { }); } + private currentRafId: number | null = null; + + private startRenderLoop() { + if (this.fps == null) { + this.engine.runRenderLoop(() => { + this.scene.render(); + }); + } else { + let then = 0; + const interval = 1000 / this.fps; + + const renderLoop = (timeStamp: number) => { + if (this.disposed) return; + + this.currentRafId = window.requestAnimationFrame(renderLoop); + + const delta = timeStamp - then; + if (delta <= interval) return; + then = timeStamp - (delta % interval); + + this.engine.beginFrame(); + this.scene.render(); + this.engine.endFrame(); + }; + + this.currentRafId = window.requestAnimationFrame(renderLoop); + } + } + + public pauseRender() { + this.engine.stopRenderLoop(); + if (this.currentRafId != null) { + window.cancelAnimationFrame(this.currentRafId); + this.currentRafId = null; + } + } + + public resumeRender() { + this.startRenderLoop(); + } + public selectObject(objectId: string | null) { if (SNAPSHOT_RENDERING) this.sr.disableSnapshotRendering(); // snapshot rendering中にbake/unbakeするとエラーになる。なおこのメソッドは参照カウント方式な点に留意 @@ -1659,6 +1677,10 @@ export class RoomEngine extends EventEmitter { } public destroy() { + if (this.currentRafId != null) { + window.cancelAnimationFrame(this.currentRafId); + this.currentRafId = null; + } this.timer.dispose(); this.engine.dispose(); this.disposed = true; diff --git a/packages/frontend/src/world/room/objects/issyoubin.ts b/packages/frontend/src/world/room/objects/issyoubin.ts index 77891a137f..aa8dfbe866 100644 --- a/packages/frontend/src/world/room/objects/issyoubin.ts +++ b/packages/frontend/src/world/room/objects/issyoubin.ts @@ -19,6 +19,10 @@ export const issyoubin = defineObject({ hasCollisions: false, hasTexture: true, createInstance: ({ model, options, scene }) => { + const liquidMesh = model.findMesh('__X_LIQUID__'); + const liquidMaterial = model.findMaterial('__X_LIQUID__'); + const bottleMaterial = model.findMaterial('__X_BOTTLE__'); + // 以下を行うとレンダリングのグリッチが直るが、残念ながらWebGPUかつNCMでは動作しない // https://doc.babylonjs.com/setup/support/webGPU/webGPUOptimization/webGPUNonCompatibilityMode/#dodont-in-non-compatibility-mode-ncm //for (const m of model.root.getChildMeshes()) { @@ -26,6 +30,10 @@ export const issyoubin = defineObject({ // (m.material as BABYLON.PBRMaterial).separateCullingPass = true; // } //} + + // しょうがないので不透明にする + bottleMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST; + return { onOptionsUpdated: ([k, v]) => { },