import assert from 'node:assert/strict' import { instanceRepeatedMeshes, parseGlb, packGlb, accessorValues, meshSignature } from './instance-repeated-meshes.mjs' const bin = Buffer.alloc(84) const pos = [0,0,0,1,0,0,0,1,0], nor = [0,0,1,0,0,1,0,0,1] pos.concat(nor).forEach((v,i)=>bin.writeFloatLE(v,i*4)); [0,1,2].forEach((v,i)=>bin.writeUInt32LE(v,72+i*4)) const json = {asset:{version:'2.0'},scene:0,scenes:[{nodes:[0,1,2]}],nodes:[ {name:'a',mesh:0,translation:[1,2,3],rotation:[0,0,0,1],scale:[1,1,1]}, {name:'b',mesh:1,translation:[4,5,6]}, {name:'c',mesh:2}], meshes:[0,0,1].map(material=>({primitives:[{attributes:{POSITION:0,NORMAL:1},indices:2,material}]})), materials:[{name:'wall'},{name:'roof'}],buffers:[{byteLength:84}], bufferViews:[{buffer:0,byteOffset:0,byteLength:36},{buffer:0,byteOffset:36,byteLength:36},{buffer:0,byteOffset:72,byteLength:12}], accessors:[{bufferView:0,componentType:5126,count:3,type:'VEC3'},{bufferView:1,componentType:5126,count:3,type:'VEC3'},{bufferView:2,componentType:5125,count:3,type:'SCALAR'}]} const result=instanceRepeatedMeshes(packGlb(json,bin)), parsed=parseGlb(result.bytes) assert.equal(result.report.originalNodes,3); assert.equal(result.report.outputNodes,2) assert.equal(result.report.instanceGroups,1); assert.equal(result.report.instancedPlacements,2) const node=parsed.json.nodes.find(n=>n.extensions), attrs=node.extensions.EXT_mesh_gpu_instancing.attributes assert.deepEqual(node.extras.instanceNames,['a','b']) assert.deepEqual(accessorValues(parsed.json,parsed.bin,attrs.TRANSLATION),[[1,2,3],[4,5,6]]) assert.equal(attrs.SCALE,undefined) assert.equal(attrs.ROTATION,undefined) assert.equal(meshSignature(json,bin,json.meshes[0]),meshSignature(parsed.json,parsed.bin,parsed.json.meshes[node.mesh])) assert.equal(parsed.json.nodes.find(n=>!n.extensions).name,'c','different materials must stay separate') for(const mutate of [j=>{j.nodes[0].scale=[-1,1,1]}, j=>{j.nodes[0].matrix=Array(16).fill(0)}, j=>{j.scenes[0].nodes=[0,1]}]){ const j=structuredClone(json); mutate(j); assert.throws(()=>instanceRepeatedMeshes(packGlb(j,bin))) } for (const mutate of [ j=>{j.meshes[0].primitives[0].targets=[{POSITION:0}]}, j=>{j.nodes[0].weights=[1]}, j=>{j.scenes.push({nodes:[]})}, j=>{j.nodes[0].scale=[1.1,1,1]}, j=>{j.nodes[0].rotation=[0,0.6,0,0.8]}, ]) {const j=structuredClone(json);mutate(j);assert.throws(()=>instanceRepeatedMeshes(packGlb(j,bin)))} console.log(JSON.stringify({passed:true,scope:'shared geometry only, per-material grouping, lossless TRS and rejection paths'}))