From: Antonio Ospite Date: Sun, 18 Feb 2007 22:41:35 +0000 (+0100) Subject: Implement proper View Frustum clipping X-Git-Tag: vrm-0.3~12 X-Git-Url: https://git.ao2.it/vrm.git/commitdiff_plain/58b487476c46b70b9900d613bd875a3d9d42a515 Implement proper View Frustum clipping Signed-off-by: Antonio Ospite --- diff --git a/vrm.py b/vrm.py index f4cfcbd..0338065 100755 --- a/vrm.py +++ b/vrm.py @@ -119,9 +119,8 @@ class config: edges['COLOR'] = [0, 0, 0] output = dict() - output['FORMAT'] = 'PDF' - #output['ANIMATION'] = False - output['ANIMATION'] = True + output['FORMAT'] = 'SVG' + output['ANIMATION'] = False output['JOIN_OBJECTS'] = True @@ -593,7 +592,7 @@ class HSR: makeFaces = staticmethod(makeFaces) - def splitOn(Q, P): + def splitOn(Q, P, return_positive_faces=True, return_negative_faces=True): """Split P using the plane of Q. Logic taken from the knife.py python script """ @@ -691,16 +690,20 @@ class HSR: # If vertex are all on the same half-space, return #if len(posVertList) < 3: - # print "Problem, we created a face with less that 3 verteices??" + # print "Problem, we created a face with less that 3 vertices??" # posVertList = [] #if len(negVertList) < 3: - # print "Problem, we created a face with less that 3 verteices??" + # print "Problem, we created a face with less that 3 vertices??" # negVertList = [] if len(posVertList) < 3 or len(negVertList) < 3: - print "RETURN NONE, SURE???" + #print "RETURN NONE, SURE???" return None + if not return_positive_faces: + posVertList = [] + if not return_negative_faces: + negVertList = [] newfaces = HSR.addNewFaces(posVertList, negVertList) @@ -2097,7 +2100,7 @@ class Renderer: For now clip away only objects according to their center position. """ - cpos = self._getObjPosition(self.cameraObj) + cam_pos = self._getObjPosition(self.cameraObj) view_vect = self._cameraViewVector() near = self.cameraObj.data.clipStart @@ -2111,7 +2114,10 @@ class Renderer: for o in Objects: if o.getType() != 'Mesh': continue; - obj_vect = Vector(cpos) - self._getObjPosition(o) + # TODO: use the object bounding box (that is already in WorldSpace) + # bb = o.getBoundBox() and then: for point in bb: ... + + obj_vect = Vector(cam_pos) - self._getObjPosition(o) d = obj_vect*view_vect theta = AngleBetweenVecs(obj_vect, view_vect) @@ -2402,6 +2408,70 @@ class Renderer: """Clip faces against the View Frustum. """ + # The Canonical View Volume, 8 vertices, and 6 faces, + # We consider its face normals pointing outside + + v1 = NMesh.Vert(1, 1, -1) + v2 = NMesh.Vert(1, -1, -1) + v3 = NMesh.Vert(-1, -1, -1) + v4 = NMesh.Vert(-1, 1, -1) + v5 = NMesh.Vert(1, 1, 1) + v6 = NMesh.Vert(1, -1, 1) + v7 = NMesh.Vert(-1, -1, 1) + v8 = NMesh.Vert(-1, 1, 1) + + cvv = [] + f1 = NMesh.Face([v1, v4, v3, v2]) + cvv.append(f1) + f2 = NMesh.Face([v5, v6, v7, v8]) + cvv.append(f2) + f3 = NMesh.Face([v1, v2, v6, v5]) + cvv.append(f3) + f4 = NMesh.Face([v2, v3, v7, v6]) + cvv.append(f4) + f5 = NMesh.Face([v3, v4, v8, v7]) + cvv.append(f5) + f6 = NMesh.Face([v4, v1, v5, v8]) + cvv.append(f6) + + nmesh = NMesh.GetRaw(mesh.name) + clippedfaces = nmesh.faces[:] + facelist = clippedfaces[:] + + for clipface in cvv: + + clippedfaces = [] + for f in facelist: + + newfaces = HSR.splitOn(clipface, f, return_positive_faces=False) + + if not newfaces: + # Check if the face is inside the view rectangle + # TODO: Do this test before, it is more efficient + points_outside = 0 + for v in f: + if abs(v[0]) > 1-EPS or abs(v[1]) > 1-EPS: + points_outside += 1 + + if points_outside != len(f): + clippedfaces.append(f) + else: + for nf in newfaces: + for v in nf: + nmesh.verts.append(v) + + nf.mat = f.mat + nf.sel = f.sel + nf.col = [f.col[0]] * len(nf.v) + + clippedfaces.append(nf) + + facelist = clippedfaces[:] + + nmesh.faces = facelist + nmesh.update() + + # HSR routines def __simpleDepthSort(self, mesh): """Sort faces by the furthest vertex.