Optimize STL asset loading with promise-based caching

- Replace ImportMeshAsync with LoadAssetContainerAsync for person.stl
- Cache loading promise to prevent race conditions and multiple fetches
- Use instantiateModelsToScene() to create mesh instances from cached container
- Simplify buildMesh signature to use DefaultScene singleton
- Add Havok physics WASM prefetch hint to index.html

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Michael Mainguy 2025-11-20 13:19:24 -06:00
parent 0e053bf69c
commit 1098f03c7d
4 changed files with 32 additions and 9 deletions

View File

@ -10,6 +10,7 @@
<link href="/assets/dasfad/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png">
<link href="/assets/dasfad/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png">
<link href="/assets/dasfad/favicon-96x96.png" rel="icon" sizes="96x96" type="image/png">
<link rel="prefetch" href="/node_modules/.vite/deps/HavokPhysics.wasm" as="fetch">
<title>DASFAD</title>
<!-- <link as="script" href="/newRelic.js" rel="preload">
<script defer src="/newRelic.js"></script> -->

View File

@ -4,6 +4,7 @@ import {DiagramObject} from "../../diagram/diagramObject";
import log from "loglevel";
import {vectoxys} from "../../diagram/functions/vectorConversion";
import {DiagramEntityType} from "../../diagram/types/diagramEntity";
import {DefaultScene} from "../../defaultScene";
export function grabAndClone(diagramManager: DiagramManager, mesh: AbstractMesh, parent: AbstractMesh):
DiagramObject {
@ -28,7 +29,7 @@ export function grabAndClone(diagramManager: DiagramManager, mesh: AbstractMesh,
type: DiagramEntityType.ENTITY
}
const obj = new DiagramObject(parent.getScene(),
const obj = new DiagramObject(DefaultScene.Scene,
diagramManager.onDiagramEventObservable,
{
diagramEntity: entity,

View File

@ -1,16 +1,21 @@
import {ToolType} from "../types/toolType";
import {Mesh, MeshBuilder, Scene, SceneLoader} from "@babylonjs/core";
import {AssetContainer, LoadAssetContainerAsync, Mesh, MeshBuilder, SceneLoader} from "@babylonjs/core";
import {DefaultScene} from "../../defaultScene";
import log from "loglevel";
const detail = {
tesselation: 16,
subdivisions: 5
}
export async function buildMesh(type: ToolType, toolname: string, scene: Scene): Promise<Mesh> {
// Cache the loading promise to prevent multiple fetches and handle concurrent requests
let personAssetContainerPromise: Promise<AssetContainer> | null = null;
export async function buildMesh(type: ToolType, toolname: string): Promise<Mesh> {
const logger = log.getLogger('buldMesh');
const scene = DefaultScene.Scene;
switch (type) {
case ToolType.BOX:
return MeshBuilder.CreateBox(toolname, {width: 1, height: 1, depth: 1}, scene);
return MeshBuilder.CreateBox(toolname, {width: 1, height: 1, depth: 1});
case ToolType.SPHERE:
return MeshBuilder.CreateIcoSphere(toolname, {
@ -37,10 +42,26 @@ export async function buildMesh(type: ToolType, toolname: string, scene: Scene):
tessellation: detail.tesselation
}, scene);
case ToolType.PERSON:
const result = await SceneLoader.ImportMeshAsync(null, '/assets/models/', 'person.stl', DefaultScene.Scene);
result.meshes[0].id = toolname;
result.meshes[0].name = toolname;
return result.meshes[0] as Mesh;
// If not already loading, start loading and cache the promise
if (!personAssetContainerPromise) {
logger.debug('Loading person.stl for first time');
personAssetContainerPromise = LoadAssetContainerAsync(
'/assets/models/person.stl',
scene
);
}
// All concurrent calls await the same promise
const container = await personAssetContainerPromise;
// Create new instance using BabylonJS's built-in instantiation
const entries = container.instantiateModelsToScene();
const mesh = entries.rootNodes[0] as Mesh;
mesh.setParent(null);
mesh.id = toolname;
mesh.name = toolname;
return mesh;
case ToolType.PLANE:
return MeshBuilder.CreatePlane(toolname, {width: 1, height: 1}, scene);

View File

@ -24,7 +24,7 @@ export async function buildTool(tool: ToolType, colorParent: AbstractMesh, mater
}
const newItem = await buildMesh(tool, `tool-${id}`, colorParent.getScene());
const newItem = await buildMesh(tool, `tool-${id}`);
if (!newItem) {
return null;
}