Lets say I have 2 models with opaque materials merged in same scene. In some cases one of the model is small and in completely/partially hidden/encapsulated by large model. Eg (sphere inside a sphere). Is there a way to identify hidden parts and remove the textures related to the hidden portions so that unused textures can be removed and size be reduced?
Previously I had issues regarding merging of various models Multiple GLTF loading and Merging on server side which got solved using gltf-transform.
Just thing out if it can be optimized wrt to this area.
The harder part of this question is deciding how to define something like "partially hidden", and then how to detect which parts of the scene meet that criteria. Commercial tools like RapidCompact will likely do a good job of this, but without them I would expect you'll need some custom work and tuning for your specific models by a technical artist.
If you can identify the unwanted meshes somehow then yes, gltf-transform could be used to remove or downscale those textures... a fairly naive implementation would look something like this:
import { bounds } from '@gltf-transform/functions';
// Compute max dimension of scene.
const scene = document.getRoot().listScenes().pop();
const sceneSize = boundsToSize(bounds(scene));
// Find all nodes <1/100th that size.
const smallNodes = new Set();
for (const node of document.getRoot().listNodes()) {
if (!node.getMesh()) continue;
const nodeSize = boundsToSize(bounds(node));
if (sceneSize > nodeSize * 100) {
smallNodes.add(node);
}
}
// Find all materials for small nodes.
//
// NOTE: It's common for materials to be reused by many
// primitives, but this code does not check for that.
const materialsToModify = new Set();
for (const node of Array.from(smallNodes)) {
for (const prim of node.getMesh().listPrimitives()) {
materialsToModify.add(prim.getMaterial());
}
}
// Remove textures identified.
//
// NOTE: It's common for textures to be reused by many
// materials, but this code does not check for that.
for (const texture of document.getRoot().listTextures()) {
const shouldDispose = texture.listParents()
.some((material) => materialsToModify.has(material));
if (shouldDispose) {
texture.dispose();
}
}
/** Helper to get max dimension from bounding box. */
function boundsToSize(bounds) {
const dims = [
Math.abs(bounds.max[0] - bounds.min[0]),
Math.abs(bounds.max[1] - bounds.min[1]),
Math.abs(bounds.max[2] - bounds.min[2])
];
return Math.max(...dims);
}
Hopefully that is enough information to get you started. Checking more advanced criteria like occlusion and encapsulation is more complex — and glTF-Transform does not include algorithms to do this by itself. For a small number of models it may be easier to clean them up in Blender than to implement all that. If you do want to program this, and are having trouble with your implementation, asking in the discussions section here might be a good option: https://github.com/donmccurdy/glTF-Transform/discussions.