fix: resolve workspace integration blockers (#5)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { ThreeDViewer } from './viewer/ThreeDViewer';
|
||||
import { initDropzone } from './dnd/dropzone';
|
||||
import { setStatus } from './ui/progress';
|
||||
import { publicAssetUrl } from './runtimeBase';
|
||||
|
||||
/**
|
||||
* Entry point. Wires the ThreeDViewer (renderer + loaders + hydration) and the
|
||||
@@ -62,11 +63,21 @@ if (modelUrl) {
|
||||
// SSR placeholder: a pre-rendered 360° animated WebP (tools/prerender.mjs)
|
||||
// shows instantly, then the hydration gate fades it out once WebGL + model ready.
|
||||
const base = modelUrl.split('/').pop()!.replace(/\.(glb|gltf|obj|fbx|dae|ifc|ply)$/i, '');
|
||||
previewEl.src = '/previews/' + base + '.webp';
|
||||
previewEl.src = publicAssetUrl(`previews/${base}.webp`);
|
||||
previewEl.classList.remove('hidden');
|
||||
previewEl.onerror = () => previewEl.classList.add('hidden');
|
||||
viewer.loadServerAsset(modelUrl);
|
||||
}
|
||||
|
||||
// Exposed for tooling (tools/prerender.mjs captures rotating frames).
|
||||
(window as unknown as { __viewer?: ThreeDViewer }).__viewer = viewer;
|
||||
// tools/prerender.mjs가 회전 frame을 캡처할 때 사용하는 공개 reference입니다.
|
||||
const viewerWindow = window as Window & { __viewer?: ThreeDViewer };
|
||||
viewerWindow.__viewer = viewer;
|
||||
|
||||
window.addEventListener(
|
||||
'pagehide',
|
||||
() => {
|
||||
viewer.dispose();
|
||||
delete viewerWindow.__viewer;
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Vite의 배포 base 아래에 있는 public asset의 절대 URL을 반환합니다.
|
||||
*/
|
||||
export function publicAssetUrl(
|
||||
path: string,
|
||||
base = import.meta.env.BASE_URL,
|
||||
origin = window.location.origin,
|
||||
): string {
|
||||
const normalizedBase = base.endsWith('/') ? base : `${base}/`;
|
||||
const normalizedPath = path.replace(/^\/+/, '');
|
||||
return new URL(normalizedPath, new URL(normalizedBase, `${origin}/`)).href;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
||||
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
||||
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
|
||||
import { publicAssetUrl } from '../runtimeBase';
|
||||
|
||||
export interface ViewerLoaders {
|
||||
gltf: GLTFLoader;
|
||||
@@ -16,8 +17,10 @@ let _cache: ViewerLoaders | null = null;
|
||||
|
||||
export function getLoaders(renderer: THREE.WebGLRenderer): ViewerLoaders {
|
||||
if (_cache) return _cache;
|
||||
const draco = new DRACOLoader().setDecoderPath('/draco/');
|
||||
const ktx2 = new KTX2Loader().setTranscoderPath('/basis/').detectSupport(renderer);
|
||||
const draco = new DRACOLoader().setDecoderPath(publicAssetUrl('draco/'));
|
||||
const ktx2 = new KTX2Loader()
|
||||
.setTranscoderPath(publicAssetUrl('basis/'))
|
||||
.detectSupport(renderer);
|
||||
const gltf = new GLTFLoader().setDRACOLoader(draco).setKTX2Loader(ktx2);
|
||||
_cache = { gltf, draco, ktx2 };
|
||||
return _cache;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as THREE from 'three';
|
||||
import { publicAssetUrl } from '../runtimeBase';
|
||||
import { getLoaders } from './loaders';
|
||||
|
||||
/**
|
||||
@@ -244,7 +245,7 @@ async function loadIfc(url: string, onProgress?: ProgressCb): Promise<THREE.Obje
|
||||
const WebIFC = await import('web-ifc');
|
||||
if (!_ifcApi) {
|
||||
_ifcApi = new WebIFC.IfcAPI();
|
||||
_ifcApi.SetWasmPath('/web-ifc/', true);
|
||||
_ifcApi.SetWasmPath(publicAssetUrl('web-ifc/'), true);
|
||||
await _ifcApi.Init(undefined, true);
|
||||
}
|
||||
const api = _ifcApi;
|
||||
|
||||
Reference in New Issue
Block a user