Misc fixes and updates
authorAntonio Ospite <ospite@studenti.unina.it>
Fri, 14 Apr 2006 13:34:31 +0000 (15:34 +0200)
committerAntonio Ospite <ospite@studenti.unina.it>
Thu, 24 Sep 2009 11:24:15 +0000 (13:24 +0200)
 * Fix projection
 * Fix face color rendering and add a way to disable wireframe
 * Use a scene for the transformed object so we don't touch the
   original user data
 * Add a better visibility routine
 * A little better depth sorting
 * Add support for batch mode

Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
vrm.py

diff --git a/vrm.py b/vrm.py
index 871131e..00c8ed4 100755 (executable)
--- a/vrm.py
+++ b/vrm.py
@@ -84,14 +84,12 @@ class Projector:
         else:
             m2 = self._calcPerspectiveMatrix(fovy, aspect, near, far) 
         
         else:
             m2 = self._calcPerspectiveMatrix(fovy, aspect, near, far) 
         
-        m1 = Matrix()
-        mP = Matrix()
 
         # View transformation
 
         # View transformation
-        cam = cameraObj.getInverseMatrix()
+        cam = Matrix(cameraObj.getInverseMatrix())
         cam.transpose() 
 
         cam.transpose() 
 
-        m1 = obMesh.getMatrix()
+        m1 = Matrix(obMesh.getMatrix())
         m1.transpose()
         
         mP = cam * m1
         m1.transpose()
         
         mP = cam * m1
@@ -117,11 +115,11 @@ class Projector:
         mH = self.size[1]/2
         
         if p[3]<=0:
         mH = self.size[1]/2
         
         if p[3]<=0:
-            p[0] = int(p[0]*mW)+mW
-            p[1] = int(p[1]*mH)+mH
+            p[0] = round(p[0]*mW)+mW
+            p[1] = round(p[1]*mH)+mH
         else:
         else:
-            p[0] = int((p[0]/p[3])*mW)+mW
-            p[1] = int((p[1]/p[3])*mH)+mH
+            p[0] = round((p[0]/p[3])*mW)+mW
+            p[1] = round((p[1]/p[3])*mH)+mH
             
         # For now we want (0,0) in the top-left corner of the canvas
         # Mirror and translate along y
             
         # For now we want (0,0) in the top-left corner of the canvas
         # Mirror and translate along y
@@ -259,10 +257,11 @@ class SVGVectorWriter(VectorWriter):
 
         self._printHeader()
         
 
         self._printHeader()
         
-        for obj in scene:
+        Objects = scene.getChildren()
+        for obj in Objects:
             self.file.write("<g>\n")
             
             self.file.write("<g>\n")
             
-            for face in obj.faces:
+            for face in obj.getData().faces:
                 self._printPolygon(face)
 
             self.file.write("</g>\n")
                 self._printPolygon(face)
 
             self.file.write("</g>\n")
@@ -290,30 +289,33 @@ class SVGVectorWriter(VectorWriter):
 
     def _printPolygon(self, face):
         """Print our primitive, finally.
 
     def _printPolygon(self, face):
         """Print our primitive, finally.
-
-        There is no color Handling for now, *FIX!*
         """
         """
-
-        stroke_width=1
+        
+        wireframe = False
+        
+        stroke_width=0.5
         
         self.file.write("<polygon points=\"")
 
         
         self.file.write("<polygon points=\"")
 
-        i = 0
         for v in face:
         for v in face:
-            if i != 0:
-                self.file.write(", ")
-
-            i+=1
-            
-            self.file.write("%g, %g" % (v[0], v[1]))
+            self.file.write("%g,%g " % (v[0], v[1]))
         
         
-        color = [ int(c*255) for c in face.col]
-
+        self.file.seek(-1,1) # get rid of the last space
         self.file.write("\"\n")
         self.file.write("\"\n")
+        
+        #take as face color the first vertex color
+        fcol = face.col[0]
+        color = [fcol.r, fcol.g, fcol.b]
+
+        stroke_col = [0, 0, 0]
+        if not wireframe:
+            stroke_col = color
+
         self.file.write("\tstyle=\"fill:rgb("+str(color[0])+","+str(color[1])+","+str(color[2])+");")
         self.file.write("\tstyle=\"fill:rgb("+str(color[0])+","+str(color[1])+","+str(color[2])+");")
-        self.file.write(" stroke:rgb(0,0,0);")
+        self.file.write(" stroke:rgb("+str(stroke_col[0])+","+str(stroke_col[1])+","+str(stroke_col[2])+");")
         self.file.write(" stroke-width:"+str(stroke_width)+";\n")
         self.file.write(" stroke-width:"+str(stroke_width)+";\n")
-        self.file.write(" stroke-linecap:round;stroke-linejoin:round\"/>\n")
+        self.file.write(" stroke-linecap:round;stroke-linejoin:round")
+        self.file.write("\"/>\n")
 
 
 # ---------------------------------------------------------------------
 
 
 # ---------------------------------------------------------------------
@@ -390,7 +392,7 @@ class Renderer:
         Objects = scene.getChildren()
         
         # A structure to store the transformed scene
         Objects = scene.getChildren()
         
         # A structure to store the transformed scene
-        newscene = []
+        newscene = Scene.New("flat"+scene.name)
         
         for obj in Objects:
             
         
         for obj in Objects:
             
@@ -402,7 +404,8 @@ class Renderer:
             proj = Projector(cameraObj, obj, self.canvasSize)
 
             # Let's store the transformed data
             proj = Projector(cameraObj, obj, self.canvasSize)
 
             # Let's store the transformed data
-            transformed_mesh = NMesh.New(obj.name)
+            transformed_mesh = NMesh.New("flat"+obj.name)
+            transformed_mesh.hasVertexColours(1)
 
             # Store the materials
             materials = obj.getData().getMaterials()
 
             # Store the materials
             materials = obj.getData().getMaterials()
@@ -412,26 +415,33 @@ class Renderer:
             for face in meshfaces:
 
                 # if the face is visible flatten it on the "picture plane"
             for face in meshfaces:
 
                 # if the face is visible flatten it on the "picture plane"
-                if self._isFaceVisible(face, obj, cameraObj):
+                if self._isFaceVisible_old(face, obj, cameraObj):
                     
                     # Store transformed face
                     
                     # Store transformed face
-                    transformed_face = []
+                    newface = NMesh.Face()
 
                     for vert in face:
 
                         p = proj.doProjection(vert.co)
 
 
                     for vert in face:
 
                         p = proj.doProjection(vert.co)
 
-                        transformed_vert = NMesh.Vert(p[0], p[1], p[2])
-                        transformed_face.append(transformed_vert)
+                        tmp_vert = NMesh.Vert(p[0], p[1], p[2])
 
 
-                    newface = NMesh.Face(transformed_face)
+                        # Add the vert to the mesh
+                        transformed_mesh.verts.append(tmp_vert)
+                        
+                        newface.v.append(tmp_vert)
+                        
                     
                     # Per-face color calculation
                     # code taken mostly from the original vrm script
                     # TODO: understand the code and rewrite it clearly
                     
                     # Per-face color calculation
                     # code taken mostly from the original vrm script
                     # TODO: understand the code and rewrite it clearly
-                    ambient = -250
-                    fakelight = [10, 10, 15]
-                    norm = face.normal
+                    ambient = -150
+                    
+                    fakelight = Object.Get("Lamp").loc
+                    if fakelight == None:
+                        fakelight = [1.0, 1.0, -0.3]
+
+                    norm = Vector(face.no)
                     vektori = (norm[0]*fakelight[0]+norm[1]*fakelight[1]+norm[2]*fakelight[2])
                     vduzine = fabs(sqrt(pow(norm[0],2)+pow(norm[1],2)+pow(norm[2],2))*sqrt(pow(fakelight[0],2)+pow(fakelight[1],2)+pow(fakelight[2],2)))
                     intensity = floor(ambient + 200*acos(vektori/vduzine))/200
                     vektori = (norm[0]*fakelight[0]+norm[1]*fakelight[1]+norm[2]*fakelight[2])
                     vduzine = fabs(sqrt(pow(norm[0],2)+pow(norm[1],2)+pow(norm[2],2))*sqrt(pow(fakelight[0],2)+pow(fakelight[1],2)+pow(fakelight[2],2)))
                     intensity = floor(ambient + 200*acos(vektori/vduzine))/200
@@ -439,21 +449,24 @@ class Renderer:
                         intensity = 0
 
                     if materials:
                         intensity = 0
 
                     if materials:
-                        newface.col = materials[face.mat].getRGBCol()
+                        tmp_col = materials[face.mat].getRGBCol()
                     else:
                     else:
-                        newface.col = [0.5, 0.5, 0.5]
+                        tmp_col = [0.5, 0.5, 0.5]
                         
                         
-                    newface.col = [ (c>0) and (c-intensity) for c in newface.col]
+                    tmp_col = [ (c>intensity) and int(round((c-intensity)*10)*25.5) for c in tmp_col ]
+
+                    vcol = NMesh.Col(tmp_col[0], tmp_col[1], tmp_col[2])
+                    newface.col = [vcol, vcol, vcol, 255]
                     
                     transformed_mesh.addFace(newface)
 
             # at the end of the loop on obj
             
                     
                     transformed_mesh.addFace(newface)
 
             # at the end of the loop on obj
             
-            #transformed_object = NMesh.PutRaw(transformed_mesh)
-            newscene.append(transformed_mesh)
+            transformed_obj = Object.New(obj.getType(), "flat"+obj.name)
+            transformed_obj.link(transformed_mesh)
+            transformed_obj.loc = obj.loc
+            newscene.link(transformed_obj)
 
 
-        # reverse the order (TODO: See how is the object order in NMesh)
-        #newscene.reverse()
         
         return newscene
 
         
         return newscene
 
@@ -462,7 +475,7 @@ class Renderer:
     # Private Methods
     #
 
     # Private Methods
     #
 
-    def _isFaceVisible(self, face, obj, cameraObj):
+    def _isFaceVisible_old(self, face, obj, cameraObj):
         """Determine if the face is visible from the current camera.
 
         The following code is taken basicly from the original vrm script.
         """Determine if the face is visible from the current camera.
 
         The following code is taken basicly from the original vrm script.
@@ -508,13 +521,40 @@ class Renderer:
         c[1] += obj.LocY - camera.LocY
         c[2] += obj.LocZ - camera.LocZ
 
         c[1] += obj.LocY - camera.LocY
         c[2] += obj.LocZ - camera.LocZ
 
-        norm = Vector([0,0,0])
+        norm = [0, 0, 0]
         norm[0] = (b[1] - a[1])*(c[2] - a[2]) - (c[1] - a[1])*(b[2] - a[2])
         norm[1] = -((b[0] - a[0])*(c[2] - a[2]) - (c[0] - a[0])*(b[2] - a[2]))
         norm[2] = (b[0] - a[0])*(c[1] - a[1]) - (c[0] - a[0])*(b[1] - a[1])
 
         d = norm[0]*a[0] + norm[1]*a[1] + norm[2]*a[2]
         norm[0] = (b[1] - a[1])*(c[2] - a[2]) - (c[1] - a[1])*(b[2] - a[2])
         norm[1] = -((b[0] - a[0])*(c[2] - a[2]) - (c[0] - a[0])*(b[2] - a[2]))
         norm[2] = (b[0] - a[0])*(c[1] - a[1]) - (c[0] - a[0])*(b[1] - a[1])
 
         d = norm[0]*a[0] + norm[1]*a[1] + norm[2]*a[2]
-        # d = DotVecs(norm, Vector(a))
+        #d = DotVecs(Vector(norm), Vector(a))
+
+        return (d<0)
+    
+    def _isFaceVisible(self, face, obj, cameraObj):
+        """Determine if the face is visible from the current camera.
+
+        The following code is taken basicly from the original vrm script.
+        """
+
+        camera = cameraObj
+
+        numvert = len(face)
+
+        # backface culling
+
+        # translate and rotate according to the object matrix
+        # and then translate according to the camera position
+        m = obj.getMatrix()
+        m.transpose()
+        
+        a = m*Vector(face[0]) - Vector(cameraObj.loc)
+        b = m*Vector(face[1]) - Vector(cameraObj.loc)
+        c = m*Vector(face[numvert-1]) - Vector(cameraObj.loc)
+
+        norm = m*Vector(face.no)
+
+        d = DotVecs(norm, a)
 
         return (d<0)
 
 
         return (d<0)
 
@@ -529,10 +569,24 @@ class Renderer:
 # ---------------------------------------------------------------------
 
 
 # ---------------------------------------------------------------------
 
 
-# hackish sorting of faces according to the max z value of a vertex
-def zSorting(scene):
-    for o in scene:
-        o.faces.sort(lambda f1, f2:
+# FIXME: really hackish code, just to test if the other parts work
+def depthSorting(scene):
+
+    cameraObj = Scene.GetCurrent().getCurrentCamera()
+    Objects = scene.getChildren()
+
+    Objects.sort(lambda obj1, obj2: 
+            cmp(Vector(Vector(cameraObj.loc) - Vector(obj1.loc)).length,
+                Vector(Vector(cameraObj.loc) - Vector(obj2.loc)).length
+                )
+            )
+    
+    # hackish sorting of faces according to the max z value of a vertex
+    for o in Objects:
+
+        mesh = o.data
+        mesh.faces.sort(
+            lambda f1, f2:
                 # Sort faces according to the min z coordinate in a face
                 #cmp(min([v[2] for v in f1]), min([v[2] for v in f2])))
 
                 # Sort faces according to the min z coordinate in a face
                 #cmp(min([v[2] for v in f1]), min([v[2] for v in f2])))
 
@@ -541,30 +595,37 @@ def zSorting(scene):
                 
                 # Sort faces according to the avg z coordinate in a face
                 #cmp(sum([v[2] for v in f1])/len(f1), sum([v[2] for v in f2])/len(f2)))
                 
                 # Sort faces according to the avg z coordinate in a face
                 #cmp(sum([v[2] for v in f1])/len(f1), sum([v[2] for v in f2])/len(f2)))
-        o.faces.reverse()
+        mesh.faces.reverse()
+        mesh.update()
+        
+    # update the scene
+    for o in scene.getChildren():
+        scene.unlink(o)
+    for o in Objects:
+        scene.link(o)
     
     
-from Blender import sys
 def vectorize(filename):
 
     print "Filename: %s" % filename
 def vectorize(filename):
 
     print "Filename: %s" % filename
-    print
-    filename = filename.replace('/', sys.sep)
-    print filename
-    print
     
     
-    scene   = Scene.GetCurrent()
+    scene = Scene.GetCurrent()
     renderer = Renderer()
 
     flatScene = renderer.doRendering(scene)
     canvasSize = renderer.getCanvasSize()
 
     renderer = Renderer()
 
     flatScene = renderer.doRendering(scene)
     canvasSize = renderer.getCanvasSize()
 
-    zSorting(flatScene)
+    depthSorting(flatScene)
 
     writer = SVGVectorWriter(filename, canvasSize)
     writer.printCanvas(flatScene)
 
     writer = SVGVectorWriter(filename, canvasSize)
     writer.printCanvas(flatScene)
-    
-try:
-    Blender.Window.FileSelector (vectorize, 'Save SVG', "proba.svg")
-except:
-    vectorize("proba.svg")
+
+    Blender.Scene.unlink(flatScene)
+    del flatScene
+
+# Here the main
+if __name__ == "__main__":
+    try:
+        Blender.Window.FileSelector (vectorize, 'Save SVG', "proba.svg")
+    except:
+        vectorize("proba.svg")