// initDB
function initDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('modelCache', 1);
request.onupgradeneeded = (event: any) => {
const db = event.target.result;
if (!db.objectStoreNames.contains('models')) {
db.createObjectStore('models', { keyPath: 'url' });
}
};
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}
// saveModel
export async function saveModel(url: any, data: any) {
const db: any = await initDB();
return new Promise<void>((resolve, reject) => {
const transaction = db.transaction('models', 'readwrite');
const store = transaction.objectStore('models');
const request = store.put({ url, data });
request.onsuccess = () => resolve();
request.onerror = (e: any) => reject(e);
});
}
// loadModelData
export async function loadModelData(url: any) {
const db: any = await initDB();
return new Promise((resolve, reject) => {
const transaction = db.transaction('models', 'readonly');
const store = transaction.objectStore('models');
const request = store.get(url);
request.onsuccess = () => {
request.result ? resolve(request.result.data) : reject('not found');
};
request.onerror = (e: any) => reject(e);
});
}
// index.vue
let engine: Engine;
let scene: Scene;
let camera: ArcRotateCamera;
let light: HemisphericLight;
let sphere: AbstractMesh;
const modelUrl = '/static/models/guangqi/cqjh.glb';
const initScene = (canvas: HTMLCanvasElement) => {
engine = new Engine(canvas, true);
scene = new Scene(engine);
camera = new ArcRotateCamera('camera1', -Math.PI / 2, Math.PI / 2, 10, Vector3.Zero(), scene);
camera.attachControl(canvas, true);
light = new HemisphericLight('light1', new Vector3(0, 1, 0), scene);
sphere = MeshBuilder.CreateSphere('sphere', { diameter: 2 }, scene);
const material = new StandardMaterial('mat', scene);
material.diffuseTexture = new Texture('/static/textures/babylon/bg2.jpg', scene);
const ground = MeshBuilder.CreateGround('ground', { width: 10, height: 10 }, scene);
ground.position.y = -1;
loadModelAsync();
render();
};
const render = () => {
engine.runRenderLoop(() => {
scene.render();
});
};
const loadModelAsync = async () => {
if (!modelUrl) return;
try {
// load from cache
const data: any = await loadModelData(modelUrl);
console.log(`data===`, data);
const blob = new Blob([data], { type: 'application/octet-stream' });
const objectUrl = URL.createObjectURL(blob);
console.log(`objectUrl===`, objectUrl);
const { meshes } = await SceneLoader.ImportMeshAsync('', objectUrl, '', scene);
URL.revokeObjectURL(objectUrl);
} catch (error) {
console.log(`not `, error);
const { meshes } = await SceneLoader.ImportMeshAsync('', modelUrl, '', scene);
const serializedScene = SceneSerializer.Serialize(scene);
await saveModel(modelUrl, JSON.stringify(serializedScene));
console.log('load model success', serializedScene);
}
};
onMounted(async () => {
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
initScene(canvas);
});
This writing method can cause the browser to freeze for a few seconds,
However, I didn’t seem to notice that it went through the cache in Indexeddb.
Modify the code to
const loadModelAsync = async () => {
if (!modelUrl) return;
try {
const arrayBuffer = await loadModelData(modelUrl);
const blob = new Blob([arrayBuffer], { type: 'model/gltf-binary' });
const objectUrl = URL.createObjectURL(blob);
await SceneLoader.ImportMeshAsync('', objectUrl, '', scene);
URL.revokeObjectURL(objectUrl);
} catch (error) {
console.log('not cache', error);
const response = await fetch(modelUrl);
const arrayBuffer = await response.arrayBuffer();
await saveModel(modelUrl, arrayBuffer);
const blob = new Blob([arrayBuffer], { type: 'model/gltf-binary' });
const objectUrl = URL.createObjectURL(blob);
await SceneLoader.ImportMeshAsync('', objectUrl, '', scene);
URL.revokeObjectURL(objectUrl);
}
};
Thank you all