pixalynx/cm5-minimal-carrier
A 4-layer Raspberry Pi CM5 carrier board routes USB‑C 5V power through an RT9742 load switch with TVS protection and capacitive filtering, while providing ESD-protected HDMI output, CM5 connectors, test points, and ground/power planes.
- Version
- 0.1.1
- License
- unset
- Stars
- 0
scripts/normalize-cad-models.ts
// Bake the reference model's coordinate transform into the mesh. This avoids
// differences in compound Euler rotations between CAD viewers.
import occtFactory from 'occt-import-js'
const occt=await occtFactory()
const catalog=await Bun.file('models/catalog.json').json()
const unique=new Map<string,any>(Object.values(catalog).map((m:any)=>[m.file,m]))
for(const model of unique.values()){
const result=occt.ReadStepFile(new Uint8Array(await Bun.file('models/'+model.file).arrayBuffer()),null)
if(!result.success)throw Error('HDMI STEP model import failed')
const obj=['# '+model.provenance],mtl:string[]=[]
function transform(x:number,y:number,z:number,translate:boolean){
const [rx,ry,rz]=model.rotation.map((d:number)=>d*Math.PI/180)
;[y,z]=[y*Math.cos(rx)-z*Math.sin(rx),y*Math.sin(rx)+z*Math.cos(rx)]
;[x,z]=[x*Math.cos(ry)+z*Math.sin(ry),-x*Math.sin(ry)+z*Math.cos(ry)]
;[x,y]=[x*Math.cos(rz)-y*Math.sin(rz),x*Math.sin(rz)+y*Math.cos(rz)]
return [x,y,z].map((v,i)=>Number((v+(translate?model.offset[i]:0)).toFixed(6))).join(' ')
}
const materials=new Map<string,string>();let count=1
for(const mesh of result.meshes){
const positions=mesh.attributes.position.array,normals=mesh.attributes.normal.array
for(let i=0;i<positions.length;i+=3)obj.push('v '+transform(positions[i],positions[i+1],positions[i+2],true))
for(let i=0;i<normals.length;i+=3)obj.push('vn '+transform(normals[i],normals[i+1],normals[i+2],false))
for(const face of mesh.brep_faces){
const color=face.color??mesh.color??[.7,.7,.72],key=color.join(',')
if(!materials.has(key)){const name=`material_${materials.size}`;materials.set(key,name);mtl.push(`newmtl ${name}\nKd ${color.join(' ')}\nKs 0.1 0.1 0.1\nNs 20\n`)}
obj.push(`usemtl ${materials.get(key)}`)
for(let i=face.first*3;i<(face.last+1)*3;i+=3)obj.push('f '+mesh.index.array.slice(i,i+3).map((n:number)=>`${n+count}//${n+count}`).join(' '))
}
count+=positions.length/3
}
await Bun.write('models/'+model.file.replace('.step','.obj'),obj.join('\n')+'\n')
await Bun.write('models/'+model.file.replace('.step','.mtl'),mtl.join('\n'))
console.log(`Normalized ${model.file}: ${count-1} vertices, ${materials.size} materials`)
}