mirror of
https://github.com/yeicor-3d/yet-another-cad-viewer.git
synced 2025-12-19 22:24:17 +01:00
Add support for some gltf extensions and better multi-object updates
This commit is contained in:
@@ -2225,13 +2225,13 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
The following npm package may be included in this product:
|
The following npm package may be included in this product:
|
||||||
|
|
||||||
- three@0.162.0
|
- three@0.160.1
|
||||||
|
|
||||||
This package contains the following license and notice below:
|
This package contains the following license and notice below:
|
||||||
|
|
||||||
The MIT License
|
The MIT License
|
||||||
|
|
||||||
Copyright © 2010-2024 three.js authors
|
Copyright © 2010-2023 three.js authors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -21,7 +21,32 @@ export async function mergePartial(url: string, name: string, document: Document
|
|||||||
networkFinished();
|
networkFinished();
|
||||||
|
|
||||||
// Load the new document
|
// Load the new document
|
||||||
let newDoc = await io.readBinary(new Uint8Array(buffer));
|
let newDoc = null;
|
||||||
|
let alreadyTried: { [name: string]: boolean } = {}
|
||||||
|
while (newDoc == null) { // Retry adding extensions as required until the document is loaded
|
||||||
|
try { // Try to load fast if no extensions are used
|
||||||
|
newDoc = await io.readBinary(new Uint8Array(buffer));
|
||||||
|
} catch (e) { // Fallback to wait for download and register big extensions
|
||||||
|
if (e instanceof Error && e.message.toLowerCase().includes("khr_draco_mesh_compression")) {
|
||||||
|
if (alreadyTried["draco"]) throw e; else alreadyTried["draco"] = true;
|
||||||
|
// WARNING: Draco decompression on web is really slow for non-trivial models! (it should work?)
|
||||||
|
let {KHRDracoMeshCompression} = await import("@gltf-transform/extensions")
|
||||||
|
let dracoDecoderWeb = await import("three/examples/jsm/libs/draco/draco_decoder.js");
|
||||||
|
let dracoEncoderWeb = await import("three/examples/jsm/libs/draco/draco_encoder.js");
|
||||||
|
io.registerExtensions([KHRDracoMeshCompression])
|
||||||
|
.registerDependencies({
|
||||||
|
'draco3d.decoder': await dracoDecoderWeb.default({}),
|
||||||
|
'draco3d.encoder': await dracoEncoderWeb.default({})
|
||||||
|
});
|
||||||
|
} else if (e instanceof Error && e.message.toLowerCase().includes("ext_texture_webp")) {
|
||||||
|
if (alreadyTried["webp"]) throw e; else alreadyTried["webp"] = true;
|
||||||
|
let {EXTTextureWebP} = await import("@gltf-transform/extensions")
|
||||||
|
io.registerExtensions([EXTTextureWebP]);
|
||||||
|
} else { // TODO: Add more extensions as required
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove any previous model with the same name
|
// Remove any previous model with the same name
|
||||||
await document.transform(dropByName(name));
|
await document.transform(dropByName(name));
|
||||||
|
|||||||
@@ -93,28 +93,45 @@ export class NetworkManager extends EventTarget {
|
|||||||
|
|
||||||
private foundModel(name: string, hash: string | null, url: string, isRemove: boolean | null, disconnect: () => void = () => {
|
private foundModel(name: string, hash: string | null, url: string, isRemove: boolean | null, disconnect: () => void = () => {
|
||||||
}) {
|
}) {
|
||||||
let prevHash = this.knownObjectHashes[name];
|
|
||||||
// console.debug("Found model", name, "with hash", hash, "and previous hash", prevHash);
|
// console.debug("Found model", name, "with hash", hash, "and previous hash", prevHash);
|
||||||
if (!hash || hash !== prevHash || isRemove) {
|
// Also update buffered updates to have only the latest one per model
|
||||||
// Update known hashes
|
this.bufferedUpdates = this.bufferedUpdates.filter(m => m.name !== name);
|
||||||
if (isRemove == false) {
|
|
||||||
this.knownObjectHashes[name] = hash;
|
|
||||||
} else if (isRemove == true) {
|
|
||||||
if (!(name in this.knownObjectHashes)) return; // Nothing to remove...
|
|
||||||
delete this.knownObjectHashes[name];
|
|
||||||
// Also update buffered updates if the model is removed
|
|
||||||
this.bufferedUpdates = this.bufferedUpdates.filter(m => m.name !== name);
|
|
||||||
}
|
|
||||||
let newModel = new NetworkUpdateEventModel(name, url, hash, isRemove);
|
|
||||||
this.bufferedUpdates.push(newModel);
|
|
||||||
|
|
||||||
// Optimization: try to batch updates automatically for faster rendering
|
// Add the new model to the list of updates
|
||||||
if (this.batchTimeout !== null) clearTimeout(this.batchTimeout);
|
let newModel = new NetworkUpdateEventModel(name, url, hash, isRemove);
|
||||||
this.batchTimeout = setTimeout(() => {
|
this.bufferedUpdates.push(newModel);
|
||||||
this.dispatchEvent(new NetworkUpdateEvent(this.bufferedUpdates, disconnect));
|
|
||||||
this.bufferedUpdates = [];
|
// Optimization: try to batch updates automatically for faster rendering
|
||||||
}, batchTimeout);
|
if (this.batchTimeout !== null) clearTimeout(this.batchTimeout);
|
||||||
}
|
this.batchTimeout = setTimeout(() => {
|
||||||
|
// Update known hashes for minimal updates
|
||||||
|
for (let model of this.bufferedUpdates) {
|
||||||
|
if (model.hash && model.hash === this.knownObjectHashes[model.name]) {
|
||||||
|
// Delete this useless update
|
||||||
|
let foundFirst = false;
|
||||||
|
this.bufferedUpdates = this.bufferedUpdates.filter(m => {
|
||||||
|
if (m === model) {
|
||||||
|
if (!foundFirst) { // Remove only first full match
|
||||||
|
foundFirst = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Keep this update and update the last known hash
|
||||||
|
if (model.isRemove == true) {
|
||||||
|
if (model.name in this.knownObjectHashes) delete this.knownObjectHashes[model.name];
|
||||||
|
} else if (model.isRemove == false) {
|
||||||
|
this.knownObjectHashes[model.name] = model.hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch the event to actually update the models
|
||||||
|
this.dispatchEvent(new NetworkUpdateEvent(this.bufferedUpdates, disconnect));
|
||||||
|
this.bufferedUpdates = [];
|
||||||
|
}, batchTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
frontend/shims.d.ts
vendored
2
frontend/shims.d.ts
vendored
@@ -1,3 +1,5 @@
|
|||||||
// Avoids typescript error when importing some files
|
// Avoids typescript error when importing some files
|
||||||
declare module '@jamescoyle/vue-icon'
|
declare module '@jamescoyle/vue-icon'
|
||||||
declare module 'three-orientation-gizmo/src/OrientationGizmo'
|
declare module 'three-orientation-gizmo/src/OrientationGizmo'
|
||||||
|
declare module 'three/examples/jsm/libs/draco/draco_decoder.js'
|
||||||
|
declare module 'three/examples/jsm/libs/draco/draco_encoder.js'
|
||||||
@@ -15,7 +15,8 @@
|
|||||||
"update-licenses": "generate-license-file --input package.json --output assets/licenses.txt --overwrite"
|
"update-licenses": "generate-license-file --input package.json --output assets/licenses.txt --overwrite"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gltf-transform/core": "^3.10.0",
|
"@gltf-transform/core": "^3.10.1",
|
||||||
|
"@gltf-transform/extensions": "^3.10.1",
|
||||||
"@gltf-transform/functions": "^3.10.1",
|
"@gltf-transform/functions": "^3.10.1",
|
||||||
"@google/model-viewer": "^3.4.0",
|
"@google/model-viewer": "^3.4.0",
|
||||||
"@jamescoyle/vue-icon": "^0.1.2",
|
"@jamescoyle/vue-icon": "^0.1.2",
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
assetsDir: '.',
|
assetsDir: '.',
|
||||||
cssCodeSplit: false, // Small enough to inline
|
cssCodeSplit: false, // Small enough to inline
|
||||||
chunkSizeWarningLimit: 550, // Three.js is huge
|
chunkSizeWarningLimit: 550, // Three.js is big. Draco is even bigger but not likely to be used.
|
||||||
},
|
},
|
||||||
define: {
|
define: {
|
||||||
__APP_NAME__: JSON.stringify(name),
|
__APP_NAME__: JSON.stringify(name),
|
||||||
|
|||||||
@@ -390,7 +390,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
|
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
|
||||||
integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
|
integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
|
||||||
|
|
||||||
"@gltf-transform/core@^3.10.0", "@gltf-transform/core@^3.10.1":
|
"@gltf-transform/core@^3.10.1":
|
||||||
version "3.10.1"
|
version "3.10.1"
|
||||||
resolved "https://registry.yarnpkg.com/@gltf-transform/core/-/core-3.10.1.tgz#d99c060b499482ed2c3304466405bf4c10939831"
|
resolved "https://registry.yarnpkg.com/@gltf-transform/core/-/core-3.10.1.tgz#d99c060b499482ed2c3304466405bf4c10939831"
|
||||||
integrity sha512-50OYemknGNxjBmiOM6iJp04JAu0bl9jvXJfN/gFt9QdJO02cPDcoXlTfSPJG6TVWDcfl0xPlsx1vybcbPVGFcQ==
|
integrity sha512-50OYemknGNxjBmiOM6iJp04JAu0bl9jvXJfN/gFt9QdJO02cPDcoXlTfSPJG6TVWDcfl0xPlsx1vybcbPVGFcQ==
|
||||||
|
|||||||
Reference in New Issue
Block a user