| 12345678910111213141516171819202122232425262728293031 |
- 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'}))
|