|
 |
A quicky in Nim, not much tested:
---%<------%<------%<------%<---
#asciistl2pov.nim
import std/[math, sequtils, strformat, strutils]
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)
# Load STL, ASCII only
proc loadSTL(path: string): (seq[Vec3], seq[Face], seq[Vec3]) =
var verts: seq[Vec3] = @[]
var faces: seq[Face] = @[]
var norms: seq[Vec3] = @[]
var curVerts: seq[int] = @[]
var curNormal = vec3(0,0,0)
for line in lines(path):
let l = line.strip()
if l.startsWith("facet normal"):
let p = l.splitWhitespace()
curNormal = vec3(p[2].parseFloat, p[3].parseFloat, p[4].parseFloat)
elif l.startsWith("vertex"):
let p = l.splitWhitespace()
let v = vec3(p[1].parseFloat, p[2].parseFloat, p[3].parseFloat)
verts.add(v)
curVerts.add(verts.len-1)
elif l.startsWith("endfacet"):
if curVerts.len == 3:
faces.add([curVerts[0], curVerts[1], curVerts[2]])
norms.add(curNormal)
curVerts.setLen(0)
return (verts, faces, norms)
proc vertexToFaces(faces: seq[Face], vertexCount: int): seq[seq[int]] =
result = newSeqWith(vertexCount, newSeq[int]())
for fIdx, f in faces:
for vi in f:
result[vi].add(fIdx)
proc computeVertexNormals(
vertexCount: int, faceNormals: seq[Vec3], v2f: seq[seq[int]]
): seq[Vec3] =
result = newSeqWith(vertexCount, vec3(0,0,0))
for vIdx in 0..<vertexCount:
var accum = vec3(0,0,0)
for fIdx in v2f[vIdx]:
accum = accum + faceNormals[fIdx]
result[vIdx] = normalize(accum)
proc mesh2ToString(
verts: seq[Vec3], faces: seq[Face], normals: seq[Vec3]
): string =
var sb = newStringOfCap(verts.len * 100) # Preallocate rough size
sb.add("#declare MSH = mesh2 {\n")
# Vertex vectors
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")
# Normal vectors
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")
# Face indices
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(outPath: string, verts: seq[Vec3], faces: seq[Face], normals:
seq[Vec3]) =
let s = mesh2ToString(verts, faces, normals)
writeFile(outPath, s)
when isMainModule:
let (verts, faces, faceNorms) = loadSTL("mesh_output.stl")
let v2f = vertexToFaces(faces, verts.len)
let vertexNorms = computeVertexNormals(verts.len, faceNorms, v2f)
writeMesh2("model.inc", verts, faces, vertexNorms)
echo "Converted STL to POV-Ray mesh2 with normals."
---%<------%<------%<------%<---
ingo
Post a reply to this message
|
 |