import math def normalize(n): d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2] d = math.sqrt(d) if d == 0: return [0.0, 0.0, 0.0] n[0] /= d n[1] /= d n[2] /= d return n def normal3((v1, v2, v3)): n = [0.0, 0.0, 0.0] n1 = [0.0, 0.0, 0.0] n2 = [0.0, 0.0, 0.0] n1[0] = v1[0] - v2[0] n2[0] = v2[0] - v3[0] n1[1] = v1[1] - v2[1] n2[1] = v2[1] - v3[1] n1[2] = v1[2] - v2[2] n2[2] = v2[2] - v3[2] n[0] = n1[1]*n2[2] - n1[2]*n2[1] n[1] = n1[2]*n2[0] - n1[0]*n2[2] n[2] = n1[0]*n2[1] - n1[1]*n2[0] return normalize(n) def normal4((v1, v2, v3, v4)): n = [0.0, 0.0, 0.0] n1 = [0.0, 0.0, 0.0] n2 = [0.0, 0.0, 0.0] n1[0] = v1[0] - v3[0] n1[1] = v1[1] - v3[1] n1[2] = v1[2] - v3[2] n2[0] = v2[0] - v4[0] n2[1] = v2[1] - v4[1] n2[2] = v2[2] - v4[2] n[0] = n1[1]*n2[2] - n1[2]*n2[1] n[1] = n1[2]*n2[0] - n1[0]*n2[2] n[2] = n1[0]*n2[1] - n1[1]*n2[0] return normalize(n) class vGeometry: def __init__(self): self.v = {} self.f = {} self.bbox = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] def setVertex(self, id, xyz=(0.0, 0.0, 0.0)): # find an empty spot if id == -1: m = 0 for v in self.v: m = max(v, m) id = m + 1 self.v[id] = Vertex(xyz) self.bbox[0][0] = min(self.bbox[0][0], xyz[0]) self.bbox[0][1] = min(self.bbox[0][1], xyz[1]) self.bbox[0][2] = min(self.bbox[0][2], xyz[2]) self.bbox[1][0] = max(self.bbox[1][0], xyz[0]) self.bbox[1][1] = max(self.bbox[1][1], xyz[1]) self.bbox[1][2] = max(self.bbox[1][2], xyz[2]) return id def delVertex(self, id): if id in self.v: del self.v[id] def setTriangle(self, id, verts=(None, None, None)): pid = self._setFace(id, verts, 3) return pid def setQuad(self, id, verts=(None, None, None, None)): pid = self._setFace(id, verts, 4) return pid def delFace(self, id): if id in self.f: del self.f[id] def _setFace(self, id, verts, corners): face = None if id in self.f: face = self.f[id] face.setCorners(corners) else: face = Face(self, corners) for i in range(0, corners): if verts[i] == None: face.v[i] = self.setVertex(-1) else: face.v[i] = verts[i] self.f[id] = face return id class Vertex: def __init__(self, xyz=(0.0, 0.0, 0.0)): self.co = list(xyz); class Face: def __init__(self, parent, corners=3): self.parent = parent self.corners = corners self.n = [0.0, 0.0, 0.0] if corners == 3: self.v = [None, None, None] self.uv = [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0]] elif corners == 4: self.v = [None, None, None, None] self.uv = [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]] def setCorners(self, corners=3): if self.corners != corners: if (self.corners == 4) and (corners == 3): del self.v[3] del self.uv[3] else: self.v.append(None) self.uv.append([0.0, 0.0]) self.corners = corners def getCoords(self): verts = self.parent.v if None in self.v: return None, None for v in self.v: if not (v in verts): return None, None co = [] for v in self.v: co.append(verts[v].co) return co, self.uv def calcNorm(self): verts = self.parent.v if None in self.v: return for v in self.v: if not (v in verts): return if self.corners == 3: co = [None, None, None] for i in range(0, 3): co[i] = verts[self.v[i]].co self.n = normal3(co) elif self.corners == 4: co = [None, None, None, None] for i in range(0, 4): co[i] = verts[self.v[i]].co self.n = normal4(co) def getNorm(self): return self.n