- 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)
-
- a = []
- a.append(face[0][0])
- a.append(face[0][1])
- a.append(face[0][2])
- a = RotatePoint(a[0], a[1], a[2], obj.RotX, obj.RotY, obj.RotZ)
- a[0] += obj.LocX - camera.LocX
- a[1] += obj.LocY - camera.LocY
- a[2] += obj.LocZ - camera.LocZ
- b = []
- b.append(face[1][0])
- b.append(face[1][1])
- b.append(face[1][2])
- b = RotatePoint(b[0], b[1], b[2], obj.RotX, obj.RotY, obj.RotZ)
- b[0] += obj.LocX - camera.LocX
- b[1] += obj.LocY - camera.LocY
- b[2] += obj.LocZ - camera.LocZ
- c = []
- c.append(face[numvert-1][0])
- c.append(face[numvert-1][1])
- c.append(face[numvert-1][2])
- c = RotatePoint(c[0], c[1], c[2], obj.RotX, obj.RotY, obj.RotZ)
- c[0] += obj.LocX - camera.LocX
- c[1] += obj.LocY - camera.LocY
- c[2] += obj.LocZ - camera.LocZ
-
- norm = Vector([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]
- # d = DotVecs(norm, Vector(a))
-
- return (d<0)
-
- def _doClipping(face):
+ newObject = Object.New('Mesh', 'RawMesh_'+object.name)
+ newObject.link(me)
+
+ # If the object has no materials set a default material
+ if not me.materials:
+ me.materials = [Material.New()]
+ #for f in me.faces: f.mat = 0
+
+ newObject.setMatrix(object.getMatrix())
+
+ return newObject
+
+ def _doModelToWorldCoordinates(self, mesh, matrix):
+ """Transform object coordinates to world coordinates.
+
+ This step is done simply applying to the object its tranformation
+ matrix and recalculating its normals.
+ """
+ mesh.transform(matrix, True)
+
+ def _doObjectDepthSorting(self, mesh):
+ """Sort faces in an object.
+
+ The faces in the object are sorted following the distance of the
+ vertices from the camera position.
+ """
+ c = self._getObjPosition(self.cameraObj)
+
+ # hackish sorting of faces
+
+ # Sort faces according to the max distance from the camera
+ by_max_vert_dist = (lambda f1, f2:
+ cmp(max([(Vector(v.co)-Vector(c)).length for v in f1]),
+ max([(Vector(v.co)-Vector(c)).length for v in f2])))
+
+ # Sort faces according to the min distance from the camera
+ by_min_vert_dist = (lambda f1, f2:
+ cmp(min([(Vector(v.co)-Vector(c)).length for v in f1]),
+ min([(Vector(v.co)-Vector(c)).length for v in f2])))
+
+ # Sort faces according to the avg distance from the camera
+ by_avg_vert_dist = (lambda f1, f2:
+ cmp(sum([(Vector(v.co)-Vector(c)).length for v in f1])/len(f1),
+ sum([(Vector(v.co)-Vector(c)).length for v in f2])/len(f2)))
+
+ mesh.faces.sort(by_max_vert_dist)
+ mesh.faces.reverse()
+
+ def _doBackFaceCulling(self, mesh):
+ """Simple Backface Culling routine.
+
+ At this level we simply do a visibility test face by face and then
+ select the vertices belonging to visible faces.
+ """
+
+ # Select all vertices, so edges can be displayed even if there are no
+ # faces
+ for v in mesh.verts:
+ v.sel = 1
+
+ Mesh.Mode(Mesh.SelectModes['FACE'])
+ # Loop on faces
+ for f in mesh.faces:
+ f.sel = 0
+ if self._isFaceVisible(f):
+ f.sel = 1
+
+ # Is this the correct way to propagate the face selection info to the
+ # vertices belonging to a face ??
+ # TODO: Using the Mesh module this should come for free. Right?
+ Mesh.Mode(Mesh.SelectModes['VERTEX'])
+ for f in mesh.faces:
+ if not f.sel:
+ for v in f: v.sel = 0;
+
+ for f in mesh.faces:
+ if f.sel:
+ for v in f: v.sel = 1;
+
+ def _doColorAndLighting(self, mesh):
+ """Apply an Illumination model to the object.
+
+ The Illumination model used is the Phong one, it may be inefficient,
+ but I'm just learning about rendering and starting from Phong seemed
+ the most natural way.
+ """
+
+ # If the mesh has vertex colors already, use them,
+ # otherwise turn them on and do some calculations
+ if mesh.hasVertexColours():
+ return
+ mesh.hasVertexColours(True)
+
+ materials = mesh.materials
+
+ # TODO: use multiple lighting sources
+ light_obj = self.lights[0]
+ light_pos = self._getObjPosition(light_obj)
+ light = light_obj.data
+
+ camPos = self._getObjPosition(self.cameraObj)
+
+ # We do per-face color calculation (FLAT Shading), we can easily turn
+ # to a per-vertex calculation if we want to implement some shading
+ # technique. For an example see:
+ # http://www.miralab.unige.ch/papers/368.pdf
+ for f in mesh.faces:
+ if not f.sel:
+ continue
+
+ mat = None
+ if materials:
+ mat = materials[f.mat]
+
+ # A new default material
+ if mat == None:
+ mat = Material.New('defMat')
+
+ L = Vector(light_pos).normalize()
+
+ V = (Vector(camPos) - Vector(f.v[0].co)).normalize()
+
+ N = Vector(f.no).normalize()
+
+ R = 2 * (N*L) * N - L
+
+ # TODO: Attenuation factor (not used for now)
+ a0 = 1; a1 = 0.0; a2 = 0.0
+ d = (Vector(f.v[0].co) - Vector(light_pos)).length
+ fd = min(1, 1.0/(a0 + a1*d + a2*d*d))
+
+ # Ambient component
+ Ia = 1.0
+ ka = mat.getAmb() * Vector([0.1, 0.1, 0.1])
+ Iamb = Ia * ka
+
+ # Diffuse component (add light.col for kd)
+ kd = mat.getRef() * Vector(mat.getRGBCol())
+ Ip = light.getEnergy()
+ Idiff = Ip * kd * (N*L)
+
+ # Specular component
+ ks = mat.getSpec() * Vector(mat.getSpecCol())
+ ns = mat.getHardness()
+ Ispec = Ip * ks * pow((V * R), ns)
+
+ # Emissive component
+ ki = Vector([mat.getEmit()]*3)
+
+ I = ki + Iamb + Idiff + Ispec
+
+ # Clamp I values between 0 and 1
+ I = [ min(c, 1) for c in I]
+ I = [ max(0, c) for c in I]
+ tmp_col = [ int(c * 255.0) for c in I]
+
+ vcol = NMesh.Col(tmp_col[0], tmp_col[1], tmp_col[2], 255)
+ f.col = []
+ for v in f.v:
+ f.col.append(vcol)
+
+ def _doEdgesStyle(self, mesh, style):
+ """Process Mesh Edges.
+
+ Examples of algorithms:
+
+ Contours:
+ given an edge if its adjacent faces have the same normal (that is
+ they are complanar), than deselect it.
+
+ Silhouettes:
+ given an edge if one its adjacent faces is frontfacing and the
+ other is backfacing, than select it, else deselect.
+ """
+ #print "\tTODO: _doEdgeStyle()"