(batchNode: Node)
| 92 | * ``` |
| 93 | */ |
| 94 | export function createInstanceNodes(batchNode: Node): Node[] { |
| 95 | const batch = batchNode.getExtension<InstancedMesh>('EXT_mesh_gpu_instancing'); |
| 96 | if (!batch) return []; |
| 97 | |
| 98 | const semantics = batch.listSemantics(); |
| 99 | if (semantics.length === 0) return []; |
| 100 | |
| 101 | const document = Document.fromGraph(batchNode.getGraph())!; |
| 102 | const instanceCount = batch.listAttributes()[0].getCount(); |
| 103 | const instanceCountDigits = String(instanceCount).length; |
| 104 | const mesh = batchNode.getMesh(); |
| 105 | const batchName = batchNode.getName(); |
| 106 | |
| 107 | const instanceNodes = []; |
| 108 | |
| 109 | // For each instance construct a Node, assign attributes, and push to list. |
| 110 | for (let i = 0; i < instanceCount; i++) { |
| 111 | const instanceNode = document.createNode().setMesh(mesh); |
| 112 | |
| 113 | // MyNode_001, MyNode_002, ... |
| 114 | if (batchName) { |
| 115 | const paddedIndex = String(i).padStart(instanceCountDigits, '0'); |
| 116 | instanceNode.setName(`${batchName}_${paddedIndex}`); |
| 117 | } |
| 118 | |
| 119 | // TRS attributes are applied to node transform; all other attributes are extras. |
| 120 | for (const semantic of semantics) { |
| 121 | const attribute = batch.getAttribute(semantic)!; |
| 122 | switch (semantic) { |
| 123 | case 'TRANSLATION': |
| 124 | instanceNode.setTranslation(attribute.getElement(i, [0, 0, 0])); |
| 125 | break; |
| 126 | case 'ROTATION': |
| 127 | instanceNode.setRotation(attribute.getElement(i, [0, 0, 0, 1])); |
| 128 | break; |
| 129 | case 'SCALE': |
| 130 | instanceNode.setScale(attribute.getElement(i, [1, 1, 1])); |
| 131 | break; |
| 132 | default: |
| 133 | _setInstanceExtras(instanceNode, semantic, attribute, i); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | instanceNodes.push(instanceNode); |
| 138 | } |
| 139 | |
| 140 | return instanceNodes; |
| 141 | } |
| 142 | |
| 143 | function _setInstanceExtras(node: Node, semantic: string, attribute: Accessor, index: number): void { |
| 144 | const value = attribute.getType() === 'SCALAR' ? attribute.getScalar(index) : attribute.getElement(index, []); |
no test coverage detected