+ def _calcPerspectiveMatrix(self, fovy, aspect, near, far):
+ """Return a perspective projection matrix."""
+
+ top = near * tan(fovy * pi / 360.0)
+ bottom = -top
+ left = bottom*aspect
+ right= top*aspect
+ x = (2.0 * near) / (right-left)
+ y = (2.0 * near) / (top-bottom)
+ a = (right+left) / (right-left)
+ b = (top+bottom) / (top - bottom)
+ c = - ((far+near) / (far-near))
+ d = - ((2*far*near)/(far-near))
+
+ m = Matrix(
+ [x, 0.0, a, 0.0],
+ [0.0, y, b, 0.0],
+ [0.0, 0.0, c, d],
+ [0.0, 0.0, -1.0, 0.0])
+
+ return m
+
+ def _calcOrthoMatrix(self, fovy, aspect , near, far, scale):
+ """Return an orthogonal projection matrix."""
+
+ top = near * tan(fovy * pi / 360.0) * (scale * 10)
+ bottom = -top
+ left = bottom * aspect
+ right= top * aspect
+ rl = right-left
+ tb = top-bottom
+ fn = near-far
+ tx = -((right+left)/rl)
+ ty = -((top+bottom)/tb)
+ tz = ((far+near)/fn)
+
+ m = Matrix(
+ [2.0/rl, 0.0, 0.0, tx],
+ [0.0, 2.0/tb, 0.0, ty],
+ [0.0, 0.0, 2.0/fn, tz],
+ [0.0, 0.0, 0.0, 1.0])
+
+ return m
+
+
+# ---------------------------------------------------------------------
+#
+## Mesh representation class
+#
+# ---------------------------------------------------------------------
+
+# TODO: a class to represent the needed properties of a 2D vector image
+# Just use a NMesh structure?
+
+
+# ---------------------------------------------------------------------
+#
+## Vector Drawing Classes
+#
+# ---------------------------------------------------------------------
+
+## A generic Writer
+
+class VectorWriter:
+ """
+ A class for printing output in a vectorial format.
+
+ Given a 2D representation of the 3D scene the class is responsible to
+ write it is a vector format.
+
+ Every subclasses of VectorWriter must have at last the following public
+ methods:
+ - printCanvas(mesh) --- where mesh is as specified before.
+ """
+
+ def __init__(self, fileName, canvasSize):
+ """Open the file named #fileName# and set the canvas size."""
+
+ self.file = open(fileName, "w")
+ print "Outputting to: ", fileName
+
+ self.canvasSize = canvasSize
+
+
+ ##
+ # Public Methods
+ #
+
+ def printCanvas(mesh):
+ return
+
+ ##
+ # Private Methods
+ #
+
+ def _printHeader():
+ return
+
+ def _printFooter():
+ return
+
+
+## SVG Writer
+
+class SVGVectorWriter(VectorWriter):
+ """A concrete class for writing SVG output.
+
+ The class does not support animations, yet.
+ Sorry.
+ """
+
+ def __init__(self, file, canvasSize):
+ """Simply call the parent Contructor."""
+ VectorWriter.__init__(self, file, canvasSize)
+
+
+ ##
+ # Public Methods
+ #
+
+ def printCanvas(self, scene):
+ """Convert the scene representation to SVG."""
+
+ self._printHeader()
+
+ Objects = scene.getChildren()
+ for obj in Objects:
+ self.file.write("<g>\n")
+
+ for face in obj.getData().faces:
+ self._printPolygon(face)
+
+ self.file.write("</g>\n")
+
+ self._printFooter()
+
+ ##
+ # Private Methods
+ #
+
+ def _printHeader(self):
+ """Print SVG header."""
+
+ self.file.write("<?xml version=\"1.0\"?>\n")
+ self.file.write("<svg version=\"1.2\"\n")
+ self.file.write("\txmlns=\"http://www.w3.org/2000/svg\"\n")
+ self.file.write("\twidth=\"%d\" height=\"%d\" streamable=\"true\">\n\n" %
+ self.canvasSize)
+
+ def _printFooter(self):
+ """Print the SVG footer."""
+
+ self.file.write("\n</svg>\n")
+ self.file.close()
+
+ def _printPolygon(self, face):
+ """Print our primitive, finally.
+ """
+
+ wireframe = False
+
+ stroke_width=0.5
+
+ self.file.write("<polygon points=\"")
+
+ for v in face:
+ self.file.write("%g,%g " % (v[0], v[1]))
+
+ self.file.seek(-1,1) # get rid of the last space
+ 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(" 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-linecap:round;stroke-linejoin:round")
+ self.file.write("\"/>\n")
+
+
+# ---------------------------------------------------------------------
+#
+## Rendering Classes
+#
+# ---------------------------------------------------------------------