abse/smartwatch-flex-top-only
Three-panel flex smartwatch with two parallel R3.9 bends, all components flat-top, low-profile JST connector harnesses, split heartbeat optical windows and screw-retained PCB mounting. Modeled 39 × 50.5 × 14.5mm prototype; 100% routing, zero native DRC and shorts. Hardware qualification pending.
- Version
- 0.2.20
- License
- unset
- Stars
- 0
scripts/generate-site-previews.mjs
// Run locally after physical audits; cloud builds validate these against new outputs.
import fs from 'node:fs'
import {convertCircuitJsonToGltf,getBestCameraPosition} from 'circuit-json-to-gltf'
import {renderGLTFToPNGFromGLB} from 'poppygl'
import {geometrySha,sha} from './cloud-preview-cache.mjs'
fs.mkdirSync('mechanical/site-previews',{recursive:true})
const names=process.argv.slice(2)
const manifest=names.length?JSON.parse(fs.readFileSync('mechanical/site-previews/manifest.json','utf8')):{description:'Actual native PCB/CAD snapshots; geometry signature excludes instance IDs and rounds millimeters to 1e-9. Cloud build fails if any new physical geometry differs.',entries:{}}
for(const name of names.length?names:['index','flat','assembly','enclosure-fit','watch','pcb']){
console.log(`Rendering actual ${name} CAD`)
const source=fs.readFileSync(`dist/${name}/circuit.json`)
const circuit=JSON.parse(source)
if(circuit.some(e=>e.type.includes('error')))throw Error(`Native error in ${name}`)
const glb=await convertCircuitJsonToGltf(circuit,{format:'glb',boardTextureResolution:512})
// Native folds are anchored to the end panel. View the display face in the
// enclosure frame, while rendering the actual unmodified native scene.
const camera=['watch','assembly'].includes(name)?{lookAt:[0,-5.4,-47.19159126281738],camPos:[60,-60.4,-112.19159126281738],up:'y-'}:getBestCameraPosition(circuit)
const png=await renderGLTFToPNGFromGLB(Buffer.from(glb),{...camera,width:720,height:480,supersampling:1,backgroundColor:'#edf1f5',ambient:.7,cull:false})
fs.writeFileSync(`mechanical/site-previews/${name}.png`,png)
manifest.entries[name]={sourceCircuitSha256:sha(source),physicalGeometrySha256:geometrySha(circuit),pngSha256:sha(png)}
console.log(`Rendered ${name}`)
}
fs.writeFileSync('mechanical/site-previews/manifest.json',JSON.stringify(manifest,null,2)+'\n')