home *** CD-ROM | disk | FTP | other *** search
- # ***** BEGIN LICENSE BLOCK *****
- # Version: MPL 1.1/GPL 2.0/LGPL 2.1
- #
- # The contents of this file are subject to the Mozilla Public License Version
- # 1.1 (the "License"); you may not use this file except in compliance with
- # the License. You may obtain a copy of the License at
- # http://www.mozilla.org/MPL/
- #
- # Software distributed under the License is distributed on an "AS IS" basis,
- # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- # for the specific language governing rights and limitations under the
- # License.
- #
- # The Original Code is the Python Computer Graphics Kit.
- #
- # The Initial Developer of the Original Code is Matthias Baas.
- # Portions created by the Initial Developer are Copyright (C) 2004
- # the Initial Developer. All Rights Reserved.
- #
- # Contributor(s):
- #
- # Alternatively, the contents of this file may be used under the terms of
- # either the GNU General Public License Version 2 or later (the "GPL"), or
- # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- # in which case the provisions of the GPL or the LGPL are applicable instead
- # of those above. If you wish to allow use of your version of this file only
- # under the terms of either the GPL or the LGPL, and not to allow others to
- # use your version of this file under the terms of the MPL, indicate your
- # decision by deleting the provisions above and replace them with the notice
- # and other provisions required by the GPL or the LGPL. If you do not delete
- # the provisions above, a recipient may use your version of this file under
- # the terms of any one of the MPL, the GPL or the LGPL.
- #
- # ***** END LICENSE BLOCK *****
- # $Id: offimport.py,v 1.3 2005/04/14 08:01:50 mbaas Exp $
-
- import os.path, sys
- from cgtypes import *
- from worldobject import WorldObject
- from geomobject import *
- from trimesh import TriMesh
- from trimeshgeom import TriMeshGeom
- from polyhedron import Polyhedron
- from polyhedrongeom import PolyhedronGeom
- import pluginmanager
-
- # OffImporter
- 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
-
-
- ######################################################################
-
- # Register the OffImporter class as a plugin class
- pluginmanager.register(OffImporter)
-