def importFile(self, filename): """Import an IFS file.""" f = file(filename, "rb") # Check the header... s = self.readString(f) if s != "IFS": raise ValueError('The file "%s" is is not a IFS file.' % filename) # Read (and ignore) the version number s = f.read(4) ver = struct.unpack("<f", s)[0] # Read the model name modelname = self.readString(f) # Create the mesh geom tm = TriMeshGeom() # Read vertices... s = self.readString(f) if s != "VERTICES": raise ValueError("Vertices chunk expected, got '%s' instead." % s) s = f.read(4) numverts = int(struct.unpack("<I", s)[0]) tm.verts.resize(numverts) for i in range(numverts): s = f.read(12) x, y, z = struct.unpack("<fff", s) tm.verts[i] = vec3(x, y, z) # Read faces... s = self.readString(f) if s != "TRIANGLES": raise ValueError("Triangle chunk expected, got '%s' instead." % s) s = f.read(4) numfaces = int(struct.unpack("<I", s)[0]) tm.faces.resize(numfaces) for i in range(numfaces): s = f.read(12) a, b, c = struct.unpack("<III", s) tm.faces[i] = (int(a), int(b), int(c)) # Create a world object obj = TriMesh(name=modelname) obj.geom = tm
def importFile(self, filename): """Import an IFS file.""" f = file(filename, "rb") # Check the header... s = self.readString(f) if s!="IFS": raise ValueError('The file "%s" is is not a IFS file.'%filename) # Read (and ignore) the version number s = f.read(4) ver = struct.unpack("<f", s)[0] # Read the model name modelname = self.readString(f) # Create the mesh geom tm = TriMeshGeom() # Read vertices... s = self.readString(f) if s!="VERTICES": raise ValueError("Vertices chunk expected, got '%s' instead."%s) s = f.read(4) numverts = int(struct.unpack("<I", s)[0]) tm.verts.resize(numverts) for i in range(numverts): s = f.read(12) x,y,z = struct.unpack("<fff", s) tm.verts[i] = vec3(x,y,z) # Read faces... s = self.readString(f) if s!="TRIANGLES": raise ValueError("Triangle chunk expected, got '%s' instead."%s) s = f.read(4) numfaces = int(struct.unpack("<I", s)[0]) tm.faces.resize(numfaces) for i in range(numfaces): s = f.read(12) a,b,c = struct.unpack("<III", s) tm.faces[i] = (int(a), int(b), int(c)) # Create a world object obj = TriMesh(name=modelname) obj.geom = tm
def convertObject(self, obj): """Converts an object into a polyhedron or trimesh if necessary. The return value is a GeomObject (TriMeshGeom or PolyhedronGeom) or None. """ geom = obj.geom if isinstance(geom, TriMeshGeom): return geom if not isinstance(geom, PolyhedronGeom): # Try to convert into a polyhedron... pg = PolyhedronGeom() try: geom.convert(pg) geom = pg except: pass # Is it a PolyhedronGeom that has no polys with holes? then return # the geom... if isinstance(geom, PolyhedronGeom) and not geom.hasPolysWithHoles(): return geom # Try to convert into a triangle mesh... tm = TriMeshGeom() try: geom.convert(tm) return tm except: pass return None
def __init__(self, name="TriMesh", dynamics=True, static=False, verts=[], faces=[], **params): WorldObject.__init__(self, name=name, **params) self.geom = TriMeshGeom() self.dynamics_slot = BoolSlot(dynamics) self.static_slot = BoolSlot(static) self.addSlot("dynamics", self.dynamics_slot) self.addSlot("static", self.static_slot) tm = self.geom if len(verts) > 0: tm.verts.resize(len(verts)) i = 0 for v in verts: tm.verts.setValue(i, v) i += 1 if len(faces) > 0: tm.faces.resize(len(faces)) i = 0 for f in faces: tm.faces.setValue(i, f) i += 1
def importFile(self, filename, invertfaces=False): """Import an OFF file. If invertfaces is True the orientation of each face is reversed. """ self.invertfaces = invertfaces self.texcoord_flag = False self.color_flag = False self.normal_flag = False self.four_flag = False self.ndim_flag = False self.ndim = 3 self.is_trimesh = True self.fhandle = file(filename) # Read the header z = self.readLine() self.parseHeaderKeyWord(z) # nOFF? if self.ndim_flag: # Read the dimension of vertices z = self.readLine() self.ndim = int(z) if self.ndim>3: raise ValueError("A vertex space dimension of %d is not supported"%(self.ndim)) # Read the number of vertices and faces... z = self.readLine().split(" ") self.numverts = int(z[0]) self.numfaces = int(z[1]) # Start with a TriMeshGeom # (this will be later converted into a PolyhedronGeom if faces # with more than 3 vertices are encountered) self.geom = TriMeshGeom() self.geom.verts.resize(self.numverts) self.geom.faces.resize(self.numfaces) # Read the vertices... self.readVertices() # Read the faces... self.readFaces() self.fhandle.close() # Create the actual object... nodename = os.path.basename(filename) nodename = os.path.splitext(nodename)[0] nodename = nodename.replace(" ","_") if self.is_trimesh: n = TriMesh(name=nodename) else: n = Polyhedron(name=nodename) n.geom = self.geom
def __init__(self, parent=None): lwob.LWOBReader.__init__(self) # Parent node for the Lightwave object self.parent = parent # The TriMeshGeom that receives the triangle mesh self.trimeshgeom = TriMeshGeom() # The PolyhedronGeom that receives the mesh (if it is no triangle mesh) self.polyhedrongeom = PolyhedronGeom() # The generated WorldObject self.worldobj = None # The number of surfaces in the file self.numsurfaces = 0 # A mapping from surface name to material id # Key: Surface name / Value: Material id (0-based) self.surface_ids = {} # Message flags so that warning messages are only output once self.crv_msg = False self.patch_msg = False
def importFile(self, filename, flags=GEOM_INIT_ALL, parent=None): """Import a 3DS file.""" self.filename = filename self.ddds = _core.File3ds() self.ddds.load(filename) # f = self.ddds.current_frame f = getScene().timer().frame if f<self.ddds.segment_from: f = self.ddds.segment_from if f>self.ddds.segment_to: f = self.ddds.segment_to self.ddds.eval(f) # Create a dictionary containing all available meshes. # Key is the mesh name. This is used to check if all meshes have # been processed (i.e. if there were corresponding nodes). self.meshes = {} m = self.ddds.meshes() while m!=None: if self.meshes.has_key(m.name): print "Warning: Duplicate mesh names in 3ds file" self.meshes[m.name] = m m = m.next() # Create objects... self.materials = {} self.createObject(self.ddds.nodes(), parent=parent, flags=flags) del self.materials # Create TriMeshes for all left over meshes... for n in self.meshes: mesh = self.meshes[n] tm = TriMeshGeom() mesh.initGeom(tm, flags) worldobj = TriMesh(name = mesh.name, parent=parent) worldobj.geom = tm self.ddds.free()
class OffImporter: _protocols = ["Import"] # extension def extension(): """Return the file extensions for this format.""" return ["off"] extension = staticmethod(extension) # description def description(self): """Return a short description for the file dialog.""" return "Geomview OFF file" description = staticmethod(description) # importFile def importFile(self, filename, invertfaces=False): """Import an OFF file. If invertfaces is True the orientation of each face is reversed. """ self.invertfaces = invertfaces self.texcoord_flag = False self.color_flag = False self.normal_flag = False self.four_flag = False self.ndim_flag = False self.ndim = 3 self.is_trimesh = True self.fhandle = file(filename) # Read the header z = self.readLine() self.parseHeaderKeyWord(z) # nOFF? if self.ndim_flag: # Read the dimension of vertices z = self.readLine() self.ndim = int(z) if self.ndim>3: raise ValueError("A vertex space dimension of %d is not supported"%(self.ndim)) # Read the number of vertices and faces... z = self.readLine().split(" ") self.numverts = int(z[0]) self.numfaces = int(z[1]) # Start with a TriMeshGeom # (this will be later converted into a PolyhedronGeom if faces # with more than 3 vertices are encountered) self.geom = TriMeshGeom() self.geom.verts.resize(self.numverts) self.geom.faces.resize(self.numfaces) # Read the vertices... self.readVertices() # Read the faces... self.readFaces() self.fhandle.close() # Create the actual object... nodename = os.path.basename(filename) nodename = os.path.splitext(nodename)[0] nodename = nodename.replace(" ","_") if self.is_trimesh: n = TriMesh(name=nodename) else: n = Polyhedron(name=nodename) n.geom = self.geom # readFaces def readFaces(self): """Read the faces. """ geom = self.geom Cs = None for i in range(self.numfaces): z = self.readLine() a = z.split() # Get the number of vertices in this face Nv = int(a[0]) if Nv<3: print >>sys.stderr, "Warning: Faces must have at least three vertices" continue # Set the face... face = map(lambda x: int(x), a[1:Nv+1]) if self.invertfaces: face.reverse() if self.is_trimesh: if Nv==3: geom.faces[i] = face # geom.faces[i] = (int(a[1]), int(a[3]), int(a[2])) else: # Convert the TriMeshGeom into a PolyhedronGeom... tm = self.geom geom = self.triMesh2Polyhedron(tm) self.geom = geom self.is_trimesh = False # Get the Cs slot (if there is one) try: Cs = geom.slot("Cs") except: Cs = None # Initialize the faces processed so far... for j in range(i): self.geom.setPoly(j, [tm.faces[j]]) # ...and set the current face self.geom.setPoly(i, [face]) else: geom.setPoly(i, [face]) # Process color... ca = a[Nv+1:] if len(ca)>2: # Check and see if the rgb values are given as ints, in this # case they have to be scaled down. try: r = int(ca[0]) g = int(ca[1]) b = int(ca[2]) col = vec3(r,g,b)/255 except: r = float(ca[0]) g = float(ca[1]) b = float(ca[2]) col = vec3(r,g,b) if Cs==None: geom.newVariable("Cs", UNIFORM, COLOR) Cs = geom.slot("Cs") Cs[i] = col # triMesh2Polyhedron def triMesh2Polyhedron(self, tm): """Convert a TriMeshGeom into a PolyhedronGeom. """ pg = PolyhedronGeom() # Copy the vertices... pg.verts.resize(tm.verts.size()) tm.verts.copyValues(0, tm.verts.size(), pg.verts, 0) # Allocate polygons... pg.setNumPolys(tm.faces.size()) # Copy primitive variables... # (tm must not have any facevarying or facevertex variables) for name, storage, type, mult in tm.iterVariables(): slot = tm.slot(name) pg.newVariable(name, storage, type, mult, slot.size()) newslot = pg.slot(name) slot.copyValues(0, slot.size(), newslot, 0) return pg # readVertices def readVertices(self): """Read the vertices (and varying variables). The number of vertices must have been stored in self.numverts and the ST, C, N flags must have been initialized. self.geom must be either a TriMeshGeom or a PolyhedronGeom. """ geom = self.geom # Create primitive variables... if self.normal_flag: geom.newVariable("N", VARYING, NORMAL) N = geom.slot("N") if self.color_flag: geom.newVariable("Cs", VARYING, COLOR) Cs = geom.slot("Cs") if self.texcoord_flag: geom.newVariable("st", VARYING, FLOAT, 2) st = geom.slot("st") # Read the vertices... for i in range(self.numverts): z = self.readLine() f = map(lambda x: float(x), z.split()) geom.verts[i] = vec3(f[:self.ndim]) f = f[self.ndim:] if self.four_flag: w = f[0] geom.verts[i] /= w f = f[1:] if self.normal_flag: N[i] = vec3(f[:3]) f = f[3:] if self.color_flag: Cs[i] = vec3(f[:3]) f = f[3:] if self.texcoord_flag: st[i] = f[:2] # parseHeaderKeyWord def parseHeaderKeyWord(self, header): """Parses the first line of an OFF file. Returns True if the line actually was the header keyword (as it is optional). The method sets the ST, C, N, 4 and ndim flag to True if the according prefix is present. """ header = header.strip() if header[-3:]!="OFF": return False if header[:2]=="ST": self.texcoord_flag = True header = header[2:] if header[:1]=="C": self.color_flag = True header = header[1:] if header[:1]=="N": self.normal_flag = True header = header[1:] if header[:1]=="4": self.four_flag = True header = header[1:] if header[:1]=="n": self.ndim_flag = True header = header[1:] if header!="OFF": print >>sys.stderr, "Warning: Unknown prefixes in the header keyword" return True # readLine def readLine(self): """Read the next line. Returns the next line (without the trailing newline) that is not empty or a comment. If the end of the file was reached, an exception is thrown. """ while 1: z = self.fhandle.readline() if z=="": raise SyntaxError("premature end of file") z = z.strip() if z=="" or z[0]=='#': continue return z
class _LWOBReader(lwob.LWOBReader): """Read a Lightwave Object file (*.lwo). """ def __init__(self, parent=None): lwob.LWOBReader.__init__(self) # Parent node for the Lightwave object self.parent = parent # The TriMeshGeom that receives the triangle mesh self.trimeshgeom = TriMeshGeom() # The PolyhedronGeom that receives the mesh (if it is no triangle mesh) self.polyhedrongeom = PolyhedronGeom() # The generated WorldObject self.worldobj = None # The number of surfaces in the file self.numsurfaces = 0 # A mapping from surface name to material id # Key: Surface name / Value: Material id (0-based) self.surface_ids = {} # Message flags so that warning messages are only output once self.crv_msg = False self.patch_msg = False def handlePNTS(self, points): """Handle the points chunk. Stores the points in the TriMeshGeom. """ verts = self.trimeshgeom.verts verts.resize(len(points)) for i, p in enumerate(points): verts[i] = p def handleSRFS(self, names): """Handle the surface names chunk. """ self.numsurfaces = len(names) for i, n in enumerate(names): self.surface_ids[n] = i def handlePOLS(self, polys): """Handle the polygons. This method creates the actual object. It is assumed that the points have been read before and are stored in the TriMeshGeom. It is also assumed that a SRFS chunk was present and numsurfaces is initialized. """ # Assume the mesh is a triangle mesh and initialize the TriMeshGeom # first. If this fails, use a PolyhedronGeom instead... if self._initTriMesh(polys): geom = self.trimeshgeom else: # Copy the vertices into the polyhedron geom... numverts = self.trimeshgeom.verts.size() self.polyhedrongeom.verts.resize(numverts) self.trimeshgeom.verts.copyValues(0, numverts, self.polyhedrongeom.verts, 0) del self.trimeshgeom # Initialize the polys... self._initPolyhedron(polys) geom = self.polyhedrongeom w = WorldObject(name="lwob", parent=self.parent) w.setNumMaterials(self.numsurfaces) w.geom = geom self.worldobj = w def _initPolyhedron(self, polys): """Initialize the polys of the PolyhedronGeom. Sets the faces a poly mesh and adds a matid slot with the material indices. """ geom = self.polyhedrongeom geom.setNumPolys(len(polys)) geom.newVariable("matid", UNIFORM, INT) matid = geom.slot("matid") for i, (verts, surfid) in enumerate(polys): geom.setLoop(i, 0, verts) matid[i] = max(0, surfid - 1) def _initTriMesh(self, polys): """Initialize the faces of the TriMeshGeom. Sets the faces of a triangle mesh and adds a matid slot with the material indices. If the mesh contains faces with more than 3 vertices the method aborts and returns False. """ faces = self.trimeshgeom.faces faces.resize(len(polys)) self.trimeshgeom.newVariable("matid", UNIFORM, INT) matid = self.trimeshgeom.slot("matid") for i, (verts, surfid) in enumerate(polys): if len(verts) != 3: self.trimeshgeom.deleteVariable("matid") return False faces[i] = verts matid[i] = max(0, surfid - 1) return True def handleCRVS(self, curves): if not self.crv_msg: print("Curves are not yet supported.") self.crv_msg = True def handlePCHS(self, patches): if not self.patch_msg: print("Patches are not yet supported.") self.patch_msg = True def handleSURF(self, surface): """Handle a surface chunk. Currently this just creates a GLMaterial with the base color of the surface. Everything else is ignored so far. """ if surface.name not in self.surface_ids: raise lwob.LWOBError('Invalid surface name "%s" (name not available in SRFS chunk)' % surface.name) id = self.surface_ids[surface.name] col = surface.color if col == None: col = (255, 255, 255) mat = GLMaterial(diffuse=vec3(col) / 255) self.worldobj.setMaterial(mat, id)
def createTriMesh(self, parent=None, name=None): """Create a triangle mesh from the current set of faces. This method may only be called if the faces really have only 3 vertices. Returns the TriMesh object. """ # Build lookup tables (so that only the verts that are really # required are stored in the TriMesh) # # Key: Original vertex index - Value: New vertex index vert_lut = {} has_normals = True has_tverts = True iv = 0 for f in self.faces: for v,tv,n in f: if v not in vert_lut: vert_lut[v] = iv iv+=1 if tv==None: has_tverts = False if n==None: has_normals = False numfaces = len(self.faces) numverts = len(vert_lut) tm = TriMeshGeom() tm.verts.resize(numverts) tm.faces.resize(numfaces) # Set vertices for v in vert_lut: newidx = vert_lut[v] tm.verts[newidx] = self.verts[v] # Set faces idx = 0 for i,f in enumerate(self.faces): fi = [] for v,tv,n in f: fi.append(vert_lut[v]) tm.faces[i] = fi # Create variable N for storing the normals if has_normals: tm.newVariable("N", FACEVARYING, NORMAL) N = tm.slot("N") idx = 0 for f in self.faces: for v,tv,n in f: N[idx] = self.normals[n] idx += 1 # Set texture vertices if has_tverts: tm.newVariable("st", FACEVARYING, FLOAT, 2) st = tm.slot("st") idx = 0 for f in self.faces: for v,tv,n in f: st[idx] = self.tverts[tv] idx += 1 obj = TriMesh(name=name, parent=parent) obj.geom = tm # Set the materials self.initMaterial(obj) return obj
class _LWOBReader(lwob.LWOBReader): """Read a Lightwave Object file (*.lwo). """ def __init__(self, parent=None): lwob.LWOBReader.__init__(self) # Parent node for the Lightwave object self.parent = parent # The TriMeshGeom that receives the triangle mesh self.trimeshgeom = TriMeshGeom() # The PolyhedronGeom that receives the mesh (if it is no triangle mesh) self.polyhedrongeom = PolyhedronGeom() # The generated WorldObject self.worldobj = None # The number of surfaces in the file self.numsurfaces = 0 # A mapping from surface name to material id # Key: Surface name / Value: Material id (0-based) self.surface_ids = {} # Message flags so that warning messages are only output once self.crv_msg = False self.patch_msg = False def handlePNTS(self, points): """Handle the points chunk. Stores the points in the TriMeshGeom. """ verts = self.trimeshgeom.verts verts.resize(len(points)) for i, p in enumerate(points): verts[i] = p def handleSRFS(self, names): """Handle the surface names chunk. """ self.numsurfaces = len(names) for i, n in enumerate(names): self.surface_ids[n] = i def handlePOLS(self, polys): """Handle the polygons. This method creates the actual object. It is assumed that the points have been read before and are stored in the TriMeshGeom. It is also assumed that a SRFS chunk was present and numsurfaces is initialized. """ # Assume the mesh is a triangle mesh and initialize the TriMeshGeom # first. If this fails, use a PolyhedronGeom instead... if self._initTriMesh(polys): geom = self.trimeshgeom else: # Copy the vertices into the polyhedron geom... numverts = self.trimeshgeom.verts.size() self.polyhedrongeom.verts.resize(numverts) self.trimeshgeom.verts.copyValues(0, numverts, self.polyhedrongeom.verts, 0) del self.trimeshgeom # Initialize the polys... self._initPolyhedron(polys) geom = self.polyhedrongeom w = WorldObject(name="lwob", parent=self.parent) w.setNumMaterials(self.numsurfaces) w.geom = geom self.worldobj = w def _initPolyhedron(self, polys): """Initialize the polys of the PolyhedronGeom. Sets the faces a poly mesh and adds a matid slot with the material indices. """ geom = self.polyhedrongeom geom.setNumPolys(len(polys)) geom.newVariable("matid", UNIFORM, INT) matid = geom.slot("matid") for i, (verts, surfid) in enumerate(polys): geom.setLoop(i, 0, verts) matid[i] = max(0, surfid - 1) def _initTriMesh(self, polys): """Initialize the faces of the TriMeshGeom. Sets the faces of a triangle mesh and adds a matid slot with the material indices. If the mesh contains faces with more than 3 vertices the method aborts and returns False. """ faces = self.trimeshgeom.faces faces.resize(len(polys)) self.trimeshgeom.newVariable("matid", UNIFORM, INT) matid = self.trimeshgeom.slot("matid") for i, (verts, surfid) in enumerate(polys): if len(verts) != 3: self.trimeshgeom.deleteVariable("matid") return False faces[i] = verts matid[i] = max(0, surfid - 1) return True def handleCRVS(self, curves): if not self.crv_msg: print("Curves are not yet supported.") self.crv_msg = True def handlePCHS(self, patches): if not self.patch_msg: print("Patches are not yet supported.") self.patch_msg = True def handleSURF(self, surface): """Handle a surface chunk. Currently this just creates a GLMaterial with the base color of the surface. Everything else is ignored so far. """ if surface.name not in self.surface_ids: raise lwob.LWOBError( 'Invalid surface name "%s" (name not available in SRFS chunk)' % surface.name) id = self.surface_ids[surface.name] col = surface.color if col == None: col = (255, 255, 255) mat = GLMaterial(diffuse=vec3(col) / 255) self.worldobj.setMaterial(mat, id)
def createTriMesh(self, parent=None, name=None): """Create a triangle mesh from the current set of faces. This method may only be called if the faces really have only 3 vertices. Returns the TriMesh object. """ # Build lookup tables (so that only the verts that are really # required are stored in the TriMesh) # # Key: Original vertex index - Value: New vertex index vert_lut = {} has_normals = True has_tverts = True iv = 0 for f in self.faces: for v, tv, n in f: if v not in vert_lut: vert_lut[v] = iv iv += 1 if tv == None: has_tverts = False if n == None: has_normals = False numfaces = len(self.faces) numverts = len(vert_lut) tm = TriMeshGeom() tm.verts.resize(numverts) tm.faces.resize(numfaces) # Set vertices for v in vert_lut: newidx = vert_lut[v] tm.verts[newidx] = self.verts[v] # Set faces idx = 0 for i, f in enumerate(self.faces): fi = [] for v, tv, n in f: fi.append(vert_lut[v]) tm.faces[i] = fi # Create variable N for storing the normals if has_normals: tm.newVariable("N", FACEVARYING, NORMAL) N = tm.slot("N") idx = 0 for f in self.faces: for v, tv, n in f: N[idx] = self.normals[n] idx += 1 # Set texture vertices if has_tverts: tm.newVariable("st", FACEVARYING, FLOAT, 2) st = tm.slot("st") idx = 0 for f in self.faces: for v, tv, n in f: st[idx] = self.tverts[tv] idx += 1 obj = TriMesh(name=name, parent=parent) obj.geom = tm # Set the materials self.initMaterial(obj) return obj
def importFile(self, filename, invertfaces=False): """Import an OFF file. If invertfaces is True the orientation of each face is reversed. """ self.invertfaces = invertfaces self.texcoord_flag = False self.color_flag = False self.normal_flag = False self.four_flag = False self.ndim_flag = False self.ndim = 3 self.is_trimesh = True self.fhandle = file(filename) # Read the header z = self.readLine() self.parseHeaderKeyWord(z) # nOFF? if self.ndim_flag: # Read the dimension of vertices z = self.readLine() self.ndim = int(z) if self.ndim > 3: raise ValueError( "A vertex space dimension of %d is not supported" % (self.ndim)) # Read the number of vertices and faces... z = self.readLine().split(" ") self.numverts = int(z[0]) self.numfaces = int(z[1]) # Start with a TriMeshGeom # (this will be later converted into a PolyhedronGeom if faces # with more than 3 vertices are encountered) self.geom = TriMeshGeom() self.geom.verts.resize(self.numverts) self.geom.faces.resize(self.numfaces) # Read the vertices... self.readVertices() # Read the faces... self.readFaces() self.fhandle.close() # Create the actual object... nodename = os.path.basename(filename) nodename = os.path.splitext(nodename)[0] nodename = nodename.replace(" ", "_") if self.is_trimesh: n = TriMesh(name=nodename) else: n = Polyhedron(name=nodename) n.geom = self.geom
class OffImporter: _protocols = ["Import"] # extension def extension(): """Return the file extensions for this format.""" return ["off"] extension = staticmethod(extension) # description def description(self): """Return a short description for the file dialog.""" return "Geomview OFF file" description = staticmethod(description) # importFile def importFile(self, filename, invertfaces=False): """Import an OFF file. If invertfaces is True the orientation of each face is reversed. """ self.invertfaces = invertfaces self.texcoord_flag = False self.color_flag = False self.normal_flag = False self.four_flag = False self.ndim_flag = False self.ndim = 3 self.is_trimesh = True self.fhandle = file(filename) # Read the header z = self.readLine() self.parseHeaderKeyWord(z) # nOFF? if self.ndim_flag: # Read the dimension of vertices z = self.readLine() self.ndim = int(z) if self.ndim > 3: raise ValueError( "A vertex space dimension of %d is not supported" % (self.ndim)) # Read the number of vertices and faces... z = self.readLine().split(" ") self.numverts = int(z[0]) self.numfaces = int(z[1]) # Start with a TriMeshGeom # (this will be later converted into a PolyhedronGeom if faces # with more than 3 vertices are encountered) self.geom = TriMeshGeom() self.geom.verts.resize(self.numverts) self.geom.faces.resize(self.numfaces) # Read the vertices... self.readVertices() # Read the faces... self.readFaces() self.fhandle.close() # Create the actual object... nodename = os.path.basename(filename) nodename = os.path.splitext(nodename)[0] nodename = nodename.replace(" ", "_") if self.is_trimesh: n = TriMesh(name=nodename) else: n = Polyhedron(name=nodename) n.geom = self.geom # readFaces def readFaces(self): """Read the faces. """ geom = self.geom Cs = None for i in range(self.numfaces): z = self.readLine() a = z.split() # Get the number of vertices in this face Nv = int(a[0]) if Nv < 3: print >> sys.stderr, "Warning: Faces must have at least three vertices" continue # Set the face... face = map(lambda x: int(x), a[1:Nv + 1]) if self.invertfaces: face.reverse() if self.is_trimesh: if Nv == 3: geom.faces[i] = face # geom.faces[i] = (int(a[1]), int(a[3]), int(a[2])) else: # Convert the TriMeshGeom into a PolyhedronGeom... tm = self.geom geom = self.triMesh2Polyhedron(tm) self.geom = geom self.is_trimesh = False # Get the Cs slot (if there is one) try: Cs = geom.slot("Cs") except: Cs = None # Initialize the faces processed so far... for j in range(i): self.geom.setPoly(j, [tm.faces[j]]) # ...and set the current face self.geom.setPoly(i, [face]) else: geom.setPoly(i, [face]) # Process color... ca = a[Nv + 1:] if len(ca) > 2: # Check and see if the rgb values are given as ints, in this # case they have to be scaled down. try: r = int(ca[0]) g = int(ca[1]) b = int(ca[2]) col = vec3(r, g, b) / 255 except: r = float(ca[0]) g = float(ca[1]) b = float(ca[2]) col = vec3(r, g, b) if Cs == None: geom.newVariable("Cs", UNIFORM, COLOR) Cs = geom.slot("Cs") Cs[i] = col # triMesh2Polyhedron def triMesh2Polyhedron(self, tm): """Convert a TriMeshGeom into a PolyhedronGeom. """ pg = PolyhedronGeom() # Copy the vertices... pg.verts.resize(tm.verts.size()) tm.verts.copyValues(0, tm.verts.size(), pg.verts, 0) # Allocate polygons... pg.setNumPolys(tm.faces.size()) # Copy primitive variables... # (tm must not have any facevarying or facevertex variables) for name, storage, type, mult in tm.iterVariables(): slot = tm.slot(name) pg.newVariable(name, storage, type, mult, slot.size()) newslot = pg.slot(name) slot.copyValues(0, slot.size(), newslot, 0) return pg # readVertices def readVertices(self): """Read the vertices (and varying variables). The number of vertices must have been stored in self.numverts and the ST, C, N flags must have been initialized. self.geom must be either a TriMeshGeom or a PolyhedronGeom. """ geom = self.geom # Create primitive variables... if self.normal_flag: geom.newVariable("N", VARYING, NORMAL) N = geom.slot("N") if self.color_flag: geom.newVariable("Cs", VARYING, COLOR) Cs = geom.slot("Cs") if self.texcoord_flag: geom.newVariable("st", VARYING, FLOAT, 2) st = geom.slot("st") # Read the vertices... for i in range(self.numverts): z = self.readLine() f = map(lambda x: float(x), z.split()) geom.verts[i] = vec3(f[:self.ndim]) f = f[self.ndim:] if self.four_flag: w = f[0] geom.verts[i] /= w f = f[1:] if self.normal_flag: N[i] = vec3(f[:3]) f = f[3:] if self.color_flag: Cs[i] = vec3(f[:3]) f = f[3:] if self.texcoord_flag: st[i] = f[:2] # parseHeaderKeyWord def parseHeaderKeyWord(self, header): """Parses the first line of an OFF file. Returns True if the line actually was the header keyword (as it is optional). The method sets the ST, C, N, 4 and ndim flag to True if the according prefix is present. """ header = header.strip() if header[-3:] != "OFF": return False if header[:2] == "ST": self.texcoord_flag = True header = header[2:] if header[:1] == "C": self.color_flag = True header = header[1:] if header[:1] == "N": self.normal_flag = True header = header[1:] if header[:1] == "4": self.four_flag = True header = header[1:] if header[:1] == "n": self.ndim_flag = True header = header[1:] if header != "OFF": print >> sys.stderr, "Warning: Unknown prefixes in the header keyword" return True # readLine def readLine(self): """Read the next line. Returns the next line (without the trailing newline) that is not empty or a comment. If the end of the file was reached, an exception is thrown. """ while 1: z = self.fhandle.readline() if z == "": raise SyntaxError("premature end of file") z = z.strip() if z == "" or z[0] == '#': continue return z
def createObject(self, node, parent=None, flags=GEOM_INIT_ALL): """ \param node (\c Lib3dsNode) Current node \param parent (\c WorldObject) Parent object or None \param flags (\c int) Flags for mesh creation \todo worldtransform als Slot \todo Pivot so setzen wie in 3DS """ if node==None: return worldobj = None auto_insert = True if parent!=None: auto_insert = False # Object? if node.type==TYPE_OBJECT: if node.name!="$$$DUMMY" and node.name!="_Quader01": data = node.object_data mesh = self.ddds.meshByName(node.name) if self.meshes.has_key(mesh.name): del self.meshes[mesh.name] # print "###",node.name,"###" # print "Node matrix:" # print node.matrix # print "Pivot:",data.pivot # print "Mesh matrix:" # print mesh.matrix tm = TriMeshGeom() mesh.initGeom(tm, flags) if parent==None: PT = mat4().translation(-data.pivot) m = node.matrix*PT*mesh.matrix.inverse() else: PT = mat4().translation(-data.pivot) m = node.matrix*PT*mesh.matrix.inverse() # worldtransform von Parent bestimmen... pworldtransform = parent.worldtransform # pworldtransform = parent.localTransform() # p = parent.parent # while p!=None: # pworldtransform = p.localTransform()*pworldtransform # p = p.parent m = pworldtransform.inverse()*m worldobj = TriMesh(name=node.name, # pivot=data.pivot, transform=m, auto_insert=auto_insert) worldobj.geom = tm # Set the materials matnames = mesh.materialNames() worldobj.setNumMaterials(len(matnames)) for i in range(len(matnames)): if matnames[i]=="": material = GLMaterial() # Was the material already instantiated? elif matnames[i] in self.materials: material = self.materials[matnames[i]] else: mat = self.ddds.materialByName(matnames[i]) # print "Material:",matnames[i] # print " self_illum:",mat.self_illum # print " self_ilpct:",mat.self_ilpct material = Material3DS(name = matnames[i], ambient = mat.ambient, diffuse = mat.diffuse, specular = mat.specular, shininess = mat.shininess, shin_strength = mat.shin_strength, use_blur = mat.use_blur, transparency = mat.transparency, falloff = mat.falloff, additive = mat.additive, use_falloff = mat.use_falloff, self_illum = mat.self_illum, self_ilpct = getattr(mat, "self_ilpct", 0), shading = mat.shading, soften = mat.soften, face_map = mat.face_map, two_sided = mat.two_sided, map_decal = mat.map_decal, use_wire = mat.use_wire, use_wire_abs = mat.use_wire_abs, wire_size = mat.wire_size, texture1_map = self._createTexMap(mat.texture1_map), texture2_map = self._createTexMap(mat.texture2_map), opacity_map = self._createTexMap(mat.opacity_map), bump_map = self._createTexMap(mat.bump_map), specular_map = self._createTexMap(mat.specular_map), shininess_map = self._createTexMap(mat.shininess_map), self_illum_map = self._createTexMap(mat.self_illum_map), reflection_map = self._createTexMap(mat.reflection_map) ) self.materials[matnames[i]] = material worldobj.setMaterial(material, i) # Camera? elif node.type==TYPE_CAMERA: cam = self.ddds.cameraByName(node.name) # print "Camera:",node.name # print " Roll:",cam.roll # print node.matrix # Convert the FOV from horizontal to vertical direction # (Todo: What aspect ratio to use?) fov = degrees(atan(480/640.0*tan(radians(cam.fov/2.0))))*2.0 worldobj = TargetCamera(name = node.name, pos = cam.position, target = cam.target, fov = fov, auto_insert = auto_insert) # Light? elif node.type==TYPE_LIGHT: lgt = self.ddds.lightByName(node.name) worldobj = self._createLight(node, lgt, auto_insert) if worldobj!=None and parent!=None: parent.addChild(worldobj) if worldobj!=None: self.createObject(node.childs(), worldobj, flags=flags) else: self.createObject(node.childs(), parent, flags=flags) self.createObject(node.next(), parent, flags=flags)