Exemple #1
0
    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
Exemple #2
0
    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
Exemple #3
0
    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
Exemple #4
0
    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
Exemple #5
0
    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
Exemple #6
0
    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 __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
Exemple #8
0
    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()
Exemple #9
0
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
Exemple #10
0
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)
Exemple #11
0
    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
Exemple #12
0
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)
Exemple #13
0
    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
Exemple #14
0
    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
Exemple #15
0
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
Exemple #16
0
    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)