MCPcopy
hub / github.com/donmccurdy/glTF-Transform / instance

Function instance

packages/functions/src/instance.ts:45–145  ·  view source on GitHub ↗
(_options: InstanceOptions = INSTANCE_DEFAULTS)

Source from the content-addressed store, hash-verified

43 * @category Transforms
44 */
45export function instance(_options: InstanceOptions = INSTANCE_DEFAULTS): Transform {
46 const options = assignDefaults(INSTANCE_DEFAULTS, _options);
47
48 return createTransform(NAME, (doc: Document): void => {
49 const logger = doc.getLogger();
50 const root = doc.getRoot();
51
52 if (root.listAnimations().length) {
53 logger.warn(`${NAME}: Instancing is not currently supported for animated models.`);
54 logger.debug(`${NAME}: Complete.`);
55 return;
56 }
57
58 const batchExtension = doc.createExtension(EXTMeshGPUInstancing);
59
60 let numBatches = 0;
61 let numInstances = 0;
62
63 for (const scene of root.listScenes()) {
64 // Gather a one-to-many Mesh/Node mapping, identifying what we can instance.
65 const meshInstances = new Map<Mesh, Set<Node>>();
66 scene.traverse((node) => {
67 const mesh = node.getMesh();
68 if (!mesh) return;
69 if (node.getExtension('EXT_mesh_gpu_instancing')) return;
70 meshInstances.set(mesh, (meshInstances.get(mesh) || new Set<Node>()).add(node));
71 });
72
73 // For each Mesh, create an InstancedMesh and collect transforms.
74 const modifiedNodes = [];
75 for (const mesh of Array.from(meshInstances.keys())) {
76 const nodes = Array.from(meshInstances.get(mesh)!);
77 if (nodes.length < options.min) continue;
78 if (nodes.some((node) => node.getSkin())) continue;
79
80 // Cannot preserve volumetric effects when instancing with varying scale.
81 // See: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AttenuationTest
82 if (mesh.listPrimitives().some(hasVolume) && nodes.some(hasScale)) continue;
83
84 const batch = createBatch(doc, batchExtension, mesh, nodes.length);
85 const batchTranslation = batch.getAttribute('TRANSLATION')!;
86 const batchRotation = batch.getAttribute('ROTATION')!;
87 const batchScale = batch.getAttribute('SCALE')!;
88
89 const batchNode = doc.createNode().setMesh(mesh).setExtension('EXT_mesh_gpu_instancing', batch);
90 scene.addChild(batchNode);
91
92 let needsTranslation = false;
93 let needsRotation = false;
94 let needsScale = false;
95
96 // For each Node, write TRS properties into instance attributes.
97 for (let i = 0; i < nodes.length; i++) {
98 let t: vec3, r: vec4, s: vec3;
99 const node = nodes[i];
100
101 batchTranslation.setElement(i, (t = node.getWorldTranslation()));
102 batchRotation.setElement(i, (r = node.getWorldRotation()));

Callers 2

cli.tsFile · 0.90
instance.test.tsFile · 0.90

Calls 15

assignDefaultsFunction · 0.85
createTransformFunction · 0.85
createBatchFunction · 0.85
pruneUnusedNodesFunction · 0.85
getLoggerMethod · 0.80
getRootMethod · 0.80
listAnimationsMethod · 0.80
createExtensionMethod · 0.80
listScenesMethod · 0.80
getMeshMethod · 0.80
addMethod · 0.80
getMethod · 0.80

Tested by

no test coverage detected