Warn about negative scales
authorAntonio Ospite <ospite@studenti.unina.it>
Sat, 1 Jul 2006 14:59:37 +0000 (16:59 +0200)
committerAntonio Ospite <ospite@studenti.unina.it>
Thu, 24 Sep 2009 15:46:19 +0000 (17:46 +0200)
 * Get the Projector earlier
 * Cleanup the workspace if the rendering fails
 * Add a warning if the objects has negative scale values, blender does
   not transform normals correctly in this case

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

diff --git a/vrm.py b/vrm.py
index aa73b10..35df00c 100755 (executable)
--- a/vrm.py
+++ b/vrm.py
@@ -57,7 +57,9 @@ __bpydoc__ = """\
 #     Think to a way to merge adjacent polygons that have the same color.
 #     Or a way to use paths for silhouettes and contours.
 #   - Add Vector Writers other that SVG.
 #     Think to a way to merge adjacent polygons that have the same color.
 #     Or a way to use paths for silhouettes and contours.
 #   - Add Vector Writers other that SVG.
-#   - Consider SMIL for animation handling instead of ECMA Script?
+#   - Consider SMIL for animation handling instead of ECMA Script? (Firefox do
+#     not support SMIL for animations)
+#   - FIX the issue with negative scales in object tranformations!
 #
 # ---------------------------------------------------------------------
 #
 #
 # ---------------------------------------------------------------------
 #
@@ -408,6 +410,7 @@ class SVGVectorWriter(VectorWriter):
         self.file.write("<g id=\"frame%d\" style=\"%s\">\n" %
                 (framenumber, framestyle) )
 
         self.file.write("<g id=\"frame%d\" style=\"%s\">\n" %
                 (framenumber, framestyle) )
 
+
         for obj in Objects:
 
             if(obj.getType() != 'Mesh'):
         for obj in Objects:
 
             if(obj.getType() != 'Mesh'):
@@ -575,8 +578,6 @@ class SVGVectorWriter(VectorWriter):
             
             hidden_stroke_style = ""
             
             
             hidden_stroke_style = ""
             
-            # We consider an edge visible if _both_ its vertices are selected,
-            # hence an edge is hidden if _any_ of its vertices is deselected.
             if e.sel == 0:
                 if showHiddenEdges == False:
                     continue
             if e.sel == 0:
                 if showHiddenEdges == False:
                     continue
@@ -647,6 +648,12 @@ class Renderer:
         # Render from the currently active camera 
         self.cameraObj = self._SCENE.getCurrentCamera()
 
         # Render from the currently active camera 
         self.cameraObj = self._SCENE.getCurrentCamera()
 
+        # Get a projector for this camera.
+        # NOTE: the projector wants object in world coordinates,
+        # so we should remember to apply modelview transformations
+        # _before_ we do projection transformations.
+        self.proj = Projector(self.cameraObj, self.canvasRatio)
+
         # Get the list of lighting sources
         obj_lst = self._SCENE.getChildren()
         self.lights = [ o for o in obj_lst if o.getType() == 'Lamp']
         # Get the list of lighting sources
         obj_lst = self._SCENE.getChildren()
         self.lights = [ o for o in obj_lst if o.getType() == 'Lamp']
@@ -692,7 +699,16 @@ class Renderer:
         for f in range(startFrame, endFrame+1):
             context.currentFrame(f)
 
         for f in range(startFrame, endFrame+1):
             context.currentFrame(f)
 
-            renderedScene = self.doRenderScene(self._SCENE)
+            # Use some temporary workspace, a full copy of the scene
+            inputScene = self._SCENE.copy(2)
+            
+            try:
+                renderedScene = self.doRenderScene(inputScene)
+            except:
+                self._SCENE.makeCurrent()
+                Scene.unlink(inputScene)
+                del inputScene
+
             outputWriter.printCanvas(renderedScene,
                     doPrintPolygons = PRINT_POLYGONS,
                     doPrintEdges    = PRINT_EDGES,
             outputWriter.printCanvas(renderedScene,
                     doPrintPolygons = PRINT_POLYGONS,
                     doPrintEdges    = PRINT_EDGES,
@@ -708,22 +724,13 @@ class Renderer:
         context.currentFrame(currentFrame)
 
 
         context.currentFrame(currentFrame)
 
 
-    def doRenderScene(self, inputScene):
+    def doRenderScene(self, workScene):
         """Control the rendering process.
         
         Here we control the entire rendering process invoking the operation
         needed to transform and project the 3D scene in two dimensions.
         """
         
         """Control the rendering process.
         
         Here we control the entire rendering process invoking the operation
         needed to transform and project the 3D scene in two dimensions.
         """
         
-        # Use some temporary workspace, a full copy of the scene
-        workScene = inputScene.copy(2)
-
-        # Get a projector for this scene.
-        # NOTE: the projector wants object in world coordinates,
-        # so we should apply modelview transformations _before_
-        # projection transformations
-        proj = Projector(self.cameraObj, self.canvasRatio)
-
         # global processing of the scene
 
         self._doConvertGeometricObjToMesh(workScene)
         # global processing of the scene
 
         self._doConvertGeometricObjToMesh(workScene)
@@ -773,7 +780,7 @@ class Renderer:
 
             self._doEdgesStyle(mesh, edgeSelectionStyles[EDGE_STYLE])
 
 
             self._doEdgesStyle(mesh, edgeSelectionStyles[EDGE_STYLE])
 
-            self._doProjection(mesh, proj)
+            self._doProjection(mesh, self.proj)
             
             # Update the object data, important! :)
             mesh.update()
             
             # Update the object data, important! :)
             mesh.update()
@@ -932,11 +939,17 @@ class Renderer:
     def _joinMeshObjectsInScene(self, scene):
         """Merge all the Mesh Objects in a scene into a single Mesh Object.
         """
     def _joinMeshObjectsInScene(self, scene):
         """Merge all the Mesh Objects in a scene into a single Mesh Object.
         """
+
+        oList = [o for o in scene.getChildren() if o.getType()=='Mesh']
+
+        # FIXME: Object.join() do not work if the list contains 1 object
+        if len(oList) == 1:
+            return
+
         mesh = Mesh.New()
         bigObj = Object.New('Mesh', 'BigOne')
         bigObj.link(mesh)
 
         mesh = Mesh.New()
         bigObj = Object.New('Mesh', 'BigOne')
         bigObj.link(mesh)
 
-        oList = [o for o in scene.getChildren() if o.getType()=='Mesh']
         bigObj.join(oList)
         scene.link(bigObj)
         for o in oList:
         bigObj.join(oList)
         scene.link(bigObj)
         for o in oList:
@@ -971,6 +984,11 @@ class Renderer:
         This step is done simply applying to the object its tranformation
         matrix and recalculating its normals.
         """
         This step is done simply applying to the object its tranformation
         matrix and recalculating its normals.
         """
+        # XXX FIXME: blender do not transform normals in the right way when
+        # there are negative scale values
+        if matrix[0][0] < 0 or matrix[1][1] < 0 or matrix[2][2] < 0:
+            print "WARNING: Negative scales, expect incorrect results!"
+
         mesh.transform(matrix, True)
 
     def _doObjectDepthSorting(self, mesh):
         mesh.transform(matrix, True)
 
     def _doObjectDepthSorting(self, mesh):
@@ -1137,10 +1155,9 @@ class Renderer:
 
         for e in mesh.edges:
 
 
         for e in mesh.edges:
 
+            e.sel = 0
             if edgestyleSelect(e, mesh):
                 e.sel = 1
             if edgestyleSelect(e, mesh):
                 e.sel = 1
-            else:
-                e.sel = 0
                 
     def _doProjection(self, mesh, projector):
         """Calculate the Projection for the object.
                 
     def _doProjection(self, mesh, projector):
         """Calculate the Projection for the object.