|
 |
kurtz le pirate <kur### [at] free fr> wrote:
>
>
> I don't know Nim very well, but the code is interesting.
> Even Yoda agrees ;)
Hahaha. Well, for Yoda then, one that reads binary stl, rather untested again,
---%<------%<------%<------%<---
import std/[streams,math, sequtils, strformat]
type
Vec3 = array[3, float]
Face = array[3, int]
proc vec3(x,y,z: float): Vec3 = [x,y,z]
proc `+`(a,b: Vec3): Vec3 = [a[0]+b[0], a[1]+b[1], a[2]+b[2]]
proc `/`(a: Vec3, s: float): Vec3 = [a[0]/s, a[1]/s, a[2]/s]
proc dot(a,b: Vec3): float = a[0]*b[0]+a[1]*b[1]+a[2]*b[2]
proc length(v: Vec3): float = sqrt(dot(v,v))
proc normalize(v: Vec3): Vec3 =
let l = length(v)
if l > 1e-9: v / l else: vec3(0,1,0)
proc readVec3(s: Stream): Vec3 =
result[0] = s.readFloat32()
result[1] = s.readFloat32()
result[2] = s.readFloat32()
proc loadBinarySTL(path: string): (seq[Vec3], seq[Face], seq[Vec3]) =
## Parse binary STL, returning vertices, faces, and per-face normals
var f = newFileStream(path, fmRead)
defer: f.close()
discard f.readStr(80) # skip header
let triCount = f.readUint32()
var verts: seq[Vec3] = @[]
var faces: seq[Face] = @[]
var faceNorms: seq[Vec3] = @[]
for i in 0..<int(triCount):
let n = readVec3(f) # face normal
let v1 = readVec3(f)
let v2 = readVec3(f)
let v3 = readVec3(f)
discard f.readUint16() # attribute byte count
let base = verts.len
verts.add(v1)
verts.add(v2)
verts.add(v3)
faces.add([base, base+1, base+2])
faceNorms.add(normalize(n))
return (verts, faces, faceNorms)
# adjecent vertises
proc vertexToFaces(faces: seq[Face], vertexCount: int): seq[seq[int]] =
result = newSeqWith(vertexCount, newSeq[int]())
for fi, f in faces:
for vi in f:
result[vi].add(fi)
# Vertex normals by averaging face normals
proc computeVertexNormals(vertexCount: int, faceNormals: seq[Vec3], v2f:
seq[seq[int]]): seq[Vec3] =
result = newSeqWith(vertexCount, vec3(0,0,0))
for vi in 0..<vertexCount:
var accum = vec3(0,0,0)
for fi in v2f[vi]:
accum = accum + faceNormals[fi]
result[vi] = normalize(accum)
proc mesh2ToString(verts: seq[Vec3], faces: seq[Face], normals: seq[Vec3]):
string =
var sb = newStringOfCap(verts.len * 100)
sb.add("mesh2 {\n")
sb.add(" vertex_vectors {\n")
sb.add(" " & $verts.len & ",\n")
for v in verts: sb.add(&" <{v[0]}, {v[1]}, {v[2]}>,\n")
sb.add(" }\n")
sb.add(" normal_vectors {\n")
sb.add(" " & $normals.len & ",\n")
for n in normals: sb.add(&" <{n[0]}, {n[1]}, {n[2]}>,\n")
sb.add(" }\n")
sb.add(" face_indices {\n")
sb.add(" " & $faces.len & ",\n")
for f in faces: sb.add(&" <{f[0]}, {f[1]}, {f[2]}>,\n")
sb.add(" }\n")
sb.add("}\n")
result = sb
proc writeMesh2(path: string, verts: seq[Vec3], faces: seq[Face], normals:
seq[Vec3]) =
writeFile(path, mesh2ToString(verts, faces, normals))
when isMainModule:
let (verts, faces, faceNorms) = loadBinarySTL("model.stl")
let v2f = vertexToFaces(faces, verts.len)
let vertexNorms = computeVertexNormals(verts.len, faceNorms, v2f)
writeMesh2("model.inc", verts, faces, vertexNorms)
echo "Binary STL converted to POV-Ray mesh2."
---%<------%<------%<------%<---
They realy should have/get a decent command line interface...
ingo
Post a reply to this message
|
 |