1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-18 20:05:26 +02:00
This commit is contained in:
syuilo
2026-04-27 09:02:49 +09:00
parent 3a5532211b
commit 88e7303779
6 changed files with 68 additions and 27 deletions

View File

@@ -269,6 +269,7 @@ const roomControllerOptions = computed<RoomControllerOptions>(() => ({
fps: fps.value, fps: fps.value,
resolution: resolution.value, resolution: resolution.value,
useVirtualJoystick, useVirtualJoystick,
workerMode: false,
})); }));
const controller = new RoomController(data, roomControllerOptions.value); const controller = new RoomController(data, roomControllerOptions.value);

View File

@@ -62,8 +62,23 @@ export class RoomController {
if (this.options.workerMode) { if (this.options.workerMode) {
const offscreen = canvas.transferControlToOffscreen(); const offscreen = canvas.transferControlToOffscreen();
this.worker = new RoomWorker(); this.worker = new RoomWorker();
this.worker.postMessage({ type: 'init', canvas: offscreen, roomState: this.roomState.value, ...this.options }, [offscreen]); this.worker.postMessage({ type: 'init', canvas: offscreen, roomState: this.roomState.value, options: this.options }, [offscreen]);
this.isReady.value = true; this.worker.onmessage = (event) => {
switch (event.data?.type) {
case 'progress': {
this.initializeProgress.value = event.data.progress;
break;
}
case 'inited': {
this.initializeProgress.value = 1;
this.isReady.value = true;
break;
}
default: {
console.warn('Unrecognized message from worker:', event.data?.type);
}
}
};
} else { } else {
const babylonEngine = new BABYLON.WebGPUEngine(canvas, { doNotHandleContextLost: true }); const babylonEngine = new BABYLON.WebGPUEngine(canvas, { doNotHandleContextLost: true });
babylonEngine.compatibilityMode = false; babylonEngine.compatibilityMode = false;
@@ -104,6 +119,14 @@ export class RoomController {
this.engine.on('playSfxUrl', ({ url, options }) => { this.engine.on('playSfxUrl', ({ url, options }) => {
sound.playUrl(url, options); sound.playUrl(url, options);
}); });
if (_DEV_) {
(window as any).showBabylonInspector = () => {
import('@babylonjs/inspector').then(({ ShowInspector }) => {
ShowInspector(this.engine.scene);
});
};
}
} }
this.canvas.addEventListener('keydown', this.onCanvasKeydown); this.canvas.addEventListener('keydown', this.onCanvasKeydown);

View File

@@ -10,9 +10,7 @@
// TODO: テクスチャ置き換え時、元のテクスチャをちゃんとdispose // TODO: テクスチャ置き換え時、元のテクスチャをちゃんとdispose
import * as BABYLON from '@babylonjs/core'; import * as BABYLON from '@babylonjs/core';
import { AxesViewer } from '@babylonjs/core/Debug/axesViewer';
import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic'; import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic';
import { BoundingBoxRenderer } from '@babylonjs/core/Rendering/boundingBoxRenderer';
import { GridMaterial } from '@babylonjs/materials'; import { GridMaterial } from '@babylonjs/materials';
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraTouchVirtualJoystickInput } from '../utility.js'; import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraTouchVirtualJoystickInput } from '../utility.js';
@@ -437,18 +435,13 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
if (_DEV_) { if (_DEV_) {
// snapshot renderingかつglow layerが有効だとなんかクラッシュする // snapshot renderingかつglow layerが有効だとなんかクラッシュする
if (!(SNAPSHOT_RENDERING && this.useGlow)) { if (!(SNAPSHOT_RENDERING && this.useGlow)) {
const axes = new AxesViewer(this.scene, 30); import('@babylonjs/core/Debug/axesViewer').then(m => {
axes.xAxis.position = new BABYLON.Vector3(0, 30, 0); const { AxesViewer } = m;
axes.yAxis.position = new BABYLON.Vector3(0, 30, 0); const axes = new AxesViewer(this.scene, 30);
axes.zAxis.position = new BABYLON.Vector3(0, 30, 0); axes.xAxis.position = new BABYLON.Vector3(0, 30, 0);
} axes.yAxis.position = new BABYLON.Vector3(0, 30, 0);
axes.zAxis.position = new BABYLON.Vector3(0, 30, 0);
if (!IN_WEB_WORKER) { });
(window as any).showBabylonInspector = () => {
import('@babylonjs/inspector').then(({ ShowInspector }) => {
ShowInspector(this.scene);
});
};
} }
} }
} }
@@ -588,7 +581,8 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
const renderLoop = (timeStamp: number) => { const renderLoop = (timeStamp: number) => {
if (this.disposed) return; if (this.disposed) return;
this.currentRafId = window.requestAnimationFrame(renderLoop); // workerで実行される可能性がある
this.currentRafId = requestAnimationFrame(renderLoop);
const delta = timeStamp - then; const delta = timeStamp - then;
if (delta <= interval) return; if (delta <= interval) return;
@@ -599,14 +593,16 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
this.engine.endFrame(); this.engine.endFrame();
}; };
this.currentRafId = window.requestAnimationFrame(renderLoop); // workerで実行される可能性がある
this.currentRafId = requestAnimationFrame(renderLoop);
} }
} }
public pauseRender() { public pauseRender() {
this.engine.stopRenderLoop(); this.engine.stopRenderLoop();
if (this.currentRafId != null) { if (this.currentRafId != null) {
window.cancelAnimationFrame(this.currentRafId); // workerで実行される可能性がある
cancelAnimationFrame(this.currentRafId);
this.currentRafId = null; this.currentRafId = null;
} }
} }
@@ -1638,7 +1634,9 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
this.scene.customRenderTargets.push(reflectionProbe.cubeTexture); this.scene.customRenderTargets.push(reflectionProbe.cubeTexture);
reflectionProbe.cubeTexture.render(); reflectionProbe.cubeTexture.render();
await new Promise(res => window.setTimeout(res, 2000)); // workerで実行される可能性がある
// eslint-disable-next-line no-restricted-globals
await new Promise(res => setTimeout(res, 2000));
const tex = reflectionProbe.cubeTexture; const tex = reflectionProbe.cubeTexture;
reflectionProbe.renderList = []; reflectionProbe.renderList = [];
@@ -1731,6 +1729,8 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
// ↑追記: engine.resizeした後に一瞬待つことで回避できることが判明 // ↑追記: engine.resizeした後に一瞬待つことで回避できることが判明
if (SNAPSHOT_RENDERING) this.sr.disableSnapshotRendering(); if (SNAPSHOT_RENDERING) this.sr.disableSnapshotRendering();
this.engine.resize(); this.engine.resize();
// workerで実行される可能性がある
// eslint-disable-next-line no-restricted-globals
setTimeout(() => { setTimeout(() => {
if (SNAPSHOT_RENDERING) this.sr.enableSnapshotRendering(); if (SNAPSHOT_RENDERING) this.sr.enableSnapshotRendering();
}, 1); }, 1);
@@ -1738,7 +1738,8 @@ export class RoomEngine extends EventEmitter<RoomEngineEvents> {
public destroy() { public destroy() {
if (this.currentRafId != null) { if (this.currentRafId != null) {
window.cancelAnimationFrame(this.currentRafId); // workerで実行される可能性がある
cancelAnimationFrame(this.currentRafId);
this.currentRafId = null; this.currentRafId = null;
} }
this.timer.dispose(); this.timer.dispose();

View File

@@ -5,7 +5,6 @@
import * as BABYLON from '@babylonjs/core'; import * as BABYLON from '@babylonjs/core';
import { applyMorphTargetsToMesh, cm, getPlaneUvIndexes, Timer } from '../utility.js'; import { applyMorphTargetsToMesh, cm, getPlaneUvIndexes, Timer } from '../utility.js';
import type { RoomEngine } from './engine.js';
export const SYSTEM_MESH_NAMES = ['__TOP__', '__SIDE__', '__PICK__', '__COLLISION__']; export const SYSTEM_MESH_NAMES = ['__TOP__', '__SIDE__', '__PICK__', '__COLLISION__'];
export const SYSTEM_HEYA_MESH_NAMES = ['__ROOM_WALL__', '__ROOM_SIDE__', '__ROOM_FLOOR__', '__ROOM_CEILING__', '__ROOM_TOP__', '__ROOM_BOTTOM__']; export const SYSTEM_HEYA_MESH_NAMES = ['__ROOM_WALL__', '__ROOM_SIDE__', '__ROOM_FLOOR__', '__ROOM_CEILING__', '__ROOM_TOP__', '__ROOM_BOTTOM__'];

View File

@@ -21,8 +21,15 @@ onmessage = async (event) => {
babylonEngine.compatibilityMode = false; babylonEngine.compatibilityMode = false;
babylonEngine.enableOfflineSupport = false; babylonEngine.enableOfflineSupport = false;
await babylonEngine.initAsync(); await babylonEngine.initAsync();
engine = new RoomEngine(roomState, { canvas, engine: babylonEngine }); if (event.data.options.resolution === 2) babylonEngine.setHardwareScalingLevel(0.5);
if (event.data.options.resolution === 0.5) babylonEngine.setHardwareScalingLevel(2);
engine = new RoomEngine(roomState, { canvas, engine: babylonEngine, ...event.data.options });
engine.on('loadingProgress', ({ progress }) => {
self.postMessage({ type: 'progress', progress });
});
await engine.init(); await engine.init();
self.postMessage({ type: 'inited' });
break; break;
} }
case 'resize': { case 'resize': {

View File

@@ -544,6 +544,8 @@ export class RecyvlingTextGrid {
} }
export function sleep(ms: number) { export function sleep(ms: number) {
// workerで実行される可能性がある
// eslint-disable-next-line no-restricted-globals
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
} }
@@ -552,7 +554,9 @@ export class Timer {
private intervalIds: number[] = []; private intervalIds: number[] = [];
public setTimeout(callback: () => void, ms: number) { public setTimeout(callback: () => void, ms: number) {
const id = window.setTimeout(() => { // workerで実行される可能性がある
// eslint-disable-next-line no-restricted-globals
const id = setTimeout(() => {
this.timeoutIds = this.timeoutIds.filter(i => i !== id); this.timeoutIds = this.timeoutIds.filter(i => i !== id);
callback(); callback();
}, ms); }, ms);
@@ -560,18 +564,24 @@ export class Timer {
} }
public setInterval(callback: () => void, ms: number) { public setInterval(callback: () => void, ms: number) {
const id = window.setInterval(callback, ms); // workerで実行される可能性がある
// eslint-disable-next-line no-restricted-globals
const id = setInterval(callback, ms);
this.intervalIds.push(id); this.intervalIds.push(id);
} }
public dispose() { public dispose() {
for (const id of this.timeoutIds) { for (const id of this.timeoutIds) {
window.clearTimeout(id); // workerで実行される可能性がある
// eslint-disable-next-line no-restricted-globals
clearTimeout(id);
} }
this.timeoutIds = []; this.timeoutIds = [];
for (const id of this.intervalIds) { for (const id of this.intervalIds) {
window.clearInterval(id); // workerで実行される可能性がある
// eslint-disable-next-line no-restricted-globals
clearInterval(id);
} }
this.intervalIds = []; this.intervalIds = [];
} }