home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / cgkit / objmtl.py < prev    next >
Encoding:
Python Source  |  2007-01-11  |  19.4 KB  |  713 lines

  1. # ***** BEGIN LICENSE BLOCK *****
  2. # Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. #
  4. # The contents of this file are subject to the Mozilla Public License Version
  5. # 1.1 (the "License"); you may not use this file except in compliance with
  6. # the License. You may obtain a copy of the License at
  7. # http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS IS" basis,
  10. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. # for the specific language governing rights and limitations under the
  12. # License.
  13. #
  14. # The Original Code is the Python Computer Graphics Kit.
  15. #
  16. # The Initial Developer of the Original Code is Matthias Baas.
  17. # Portions created by the Initial Developer are Copyright (C) 2004
  18. # the Initial Developer. All Rights Reserved.
  19. #
  20. # Contributor(s):
  21. #
  22. # Alternatively, the contents of this file may be used under the terms of
  23. # either the GNU General Public License Version 2 or later (the "GPL"), or
  24. # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  25. # in which case the provisions of the GPL or the LGPL are applicable instead
  26. # of those above. If you wish to allow use of your version of this file only
  27. # under the terms of either the GPL or the LGPL, and not to allow others to
  28. # use your version of this file under the terms of the MPL, indicate your
  29. # decision by deleting the provisions above and replace them with the notice
  30. # and other provisions required by the GPL or the LGPL. If you do not delete
  31. # the provisions above, a recipient may use your version of this file under
  32. # the terms of any one of the MPL, the GPL or the LGPL.
  33. #
  34. # ***** END LICENSE BLOCK *****
  35. # $Id: objmtl.py,v 1.3 2006/03/20 19:32:12 mbaas Exp $
  36.  
  37. from cgtypes import *
  38.  
  39. # WavefrontReaderBase
  40. class WavefrontReaderBase:
  41.     """Wavefront OBJ/MTL reader base class.
  42.  
  43.     This is the base class for the OBJ and the MTL reader.
  44.     """
  45.     
  46.     def __init__(self):
  47.         """Constructor.
  48.         """
  49.         self.linenr = 0
  50.         self.line = ""
  51.  
  52.     # read
  53.     def read(self, f):
  54.         """Read the content of a file.
  55.  
  56.         f is a file like object that can be used to read the content
  57.         of the file.
  58.         The file is read and for each keyword a handle_<keyword>() method
  59.         is called with the data as argument (the number of arguments depends
  60.         on the keyword). Each argument is of type str.
  61.         A syntax error is generated if such a handler method is not available.
  62.         The task of these handler methods is to preprocess the data, check
  63.         for errors and invoke the final handler methods which are just called
  64.         after the keyword.
  65.         Before the file is read, the begin() method is called. At the end,
  66.         the end() method is called.
  67.         """
  68.  
  69.         self.linenr = 0
  70.         self.begin()
  71.         for self.line in f:
  72.             self.linenr+=1
  73.             line2 = self.line.strip()
  74.             # Ignore empty lines and comments
  75.             if line2=="" or line2[0] in ['#', '$', '!', '@']:
  76.                 continue
  77.  
  78.             a = line2.split()
  79.             cmd = a[0]
  80.             args = a[1:]
  81.             handler = getattr(self, "handle_%s"%cmd, None)
  82.             if handler!=None:
  83.                 handler(*args)
  84.             else:
  85.                 self.handleUnknown(cmd, args)
  86.  
  87.         self.end()
  88.  
  89.     # begin
  90.     def begin(self):
  91.         """Begin reading a file.
  92.  
  93.         This method is called before the file is read.
  94.         """
  95.         pass
  96.  
  97.     # end
  98.     def end(self):
  99.         """End of reading.
  100.  
  101.         This method is called after the file was read.
  102.         """
  103.         pass
  104.  
  105.     # handleUnknown
  106.     def handleUnknown(self, cmd, arglist):
  107.         """Handle unknown keywords.
  108.  
  109.         cmd is the command keyword (the 1st argument in the current line)
  110.         and arglist is the data (the remaining arguments).
  111.  
  112.         The default implementation raises a SyntaxError exception.
  113.         """
  114.         raise SyntaxError, "Unknown statement in line %d: %s"%(self.linenr, self.line)
  115.  
  116.  
  117. # MTLReader
  118. class MTLReader(WavefrontReaderBase):
  119.     """Wavefront MTL reader.
  120.  
  121.     This class can be used as base class to read a MTL file.
  122.     """
  123.     
  124.     def __init__(self):
  125.         """Constructor.
  126.         """
  127.         WavefrontReaderBase.__init__(self)
  128.  
  129. #    def handleUnknown(self, cmd, arglist):
  130. #        pass
  131. #        print "Unknown:",cmd,arglist
  132.  
  133.     # parseMapArgs
  134.     def parseMapArgs(self, args):
  135.         """Parse the arguments from a map_xyz line into options and names.
  136.  
  137.         args must be a list of strings containing the arguments (already
  138.         split).
  139.         Returns a 2-tuple (options, names) where options is a dictionary
  140.         that contains the options that were present in args (key is
  141.         the option string). names is a list of strings that were no option.
  142.         """
  143.         options = {}
  144.         names = []
  145.         while len(args)>0:
  146.             a = args[0]
  147.             # Is this an option?
  148.             if a[0]=="-":
  149.                 if a=="-s":
  150.                     val = tuple(map(lambda x: float(x), args[1:4]))
  151.                     options[a] = val
  152.                     args = args[4:]
  153.                 elif a=="-t":
  154.                     val = tuple(map(lambda x: float(x), args[1:4]))
  155.                     options[a] = val
  156.                     args = args[4:]
  157.                 elif a=="-o":
  158.                     val = tuple(map(lambda x: float(x), args[1:4]))
  159.                     options[a] = val
  160.                     args = args[4:]
  161.                 elif a=="-mm":
  162.                     val = tuple(map(lambda x: float(x), args[1:3]))
  163.                     options[a] = val
  164.                     args = args[3:]
  165.                 elif a=="-bm":
  166.                     options[a] = float(args[1])
  167.                     args = args[2:]
  168.                 elif a=="-type":
  169.                     options[a] = args[1]
  170.                     args = args[2:]
  171.                 elif a=="-clamp" or a=="-blendu" or a=="-blendv":
  172.                     options[a] = args[1].lower()=="on"
  173.                     args = args[2:]
  174.                 else:
  175.                     raise SyntaxError, "Unknown map option in line %d: %s"%(self.linenr, a)
  176.             else:  # no option
  177.                 names.append(a)
  178.                 args = args[1:]
  179.  
  180.         return options, names
  181.  
  182.     # Pre handler methods (they must be called "handle_<keyword>")
  183.  
  184.     def handle_newmtl(self, *name):
  185.         """New material command.
  186.  
  187.         name is the name of the material (all names are concatenated).
  188.         """
  189.         self.newmtl(" ".join(name))
  190.  
  191.     def handle_illum(self, model):
  192.         """Illumination model."""
  193.         self.illum(int(model))
  194.  
  195.     def handle_Ns(self, shininess):
  196.         """Shininess coefficient.
  197.         """
  198.         self.Ns(float(shininess))
  199.  
  200.     def handle_Ka(self, r, g, b):
  201.         """Ambient color.
  202.         """
  203.         self.Ka(vec3(float(r), float(g), float(b)))
  204.  
  205.     def handle_Kd(self, r, g, b):
  206.         """Diffuse color.
  207.         """
  208.         self.Kd(vec3(float(r), float(g), float(b)))
  209.  
  210.     def handle_Ks(self, r, g, b):
  211.         """Specular color.
  212.         """
  213.         self.Ks(vec3(float(r), float(g), float(b)))
  214.  
  215.     def handle_Ke(self, r, g, b):
  216.         """Emissive color.
  217.         """
  218.         self.Ke(vec3(float(r), float(g), float(b)))
  219.  
  220.     def handle_Tr(self, alpha):
  221.         """Transparency."""
  222.         self.Tr(float(alpha))
  223.  
  224.     def handle_d(self, alpha):
  225.         """Dissolve factor (transparency)."""
  226.         self.d(float(alpha))
  227.  
  228.     def handle_Tf(self, *args):
  229.         """Transparency (as color)."""
  230.         if len(args)==1:
  231.             v = vec3(float(args[0]))
  232.         else:
  233.             r,g,b = args
  234.             v = vec3(float(r), float(g), float(b))
  235.         
  236.         self.Tf(v)
  237.  
  238.     def handle_Ni(self, ref):
  239.         """Refraction index."""
  240.         self.Ni(float(ref))
  241.  
  242.     def handle_sharpness(self, v):
  243.         """Sharpness value."""
  244.         self.sharpness(float(v))
  245.  
  246.     def handle_map_Ka(self, *mapargs):
  247.         """Ambient texture file."""
  248.         opts, args = self.parseMapArgs(mapargs)
  249.         if len(args)>0:
  250.             self.map_Ka(args[0], opts)
  251.  
  252.     def handle_map_Kd(self, *mapargs):
  253.         """Diffuse texture file."""
  254.         opts, args = self.parseMapArgs(mapargs)
  255.         if len(args)>0:
  256.             self.map_Kd(args[0], opts)
  257.  
  258.     def handle_map_Ks(self, *mapargs):
  259.         """Specular texture file."""
  260.         opts, args = self.parseMapArgs(mapargs)
  261.         if len(args)>0:
  262.             self.map_Ks(args[0], opts)
  263.  
  264.     def handle_map_Ke(self, *mapargs):
  265.         """Emission texture file."""
  266.         opts, args = self.parseMapArgs(mapargs)
  267.         if len(args)>0:
  268.             self.map_Ke(args[0], opts)
  269.  
  270.     def handle_map_Ns(self, *mapargs):
  271.         """Shininess texture file."""
  272.         opts, args = self.parseMapArgs(mapargs)
  273.         if len(args)>0:
  274.             self.map_Ns(args[0], opts)
  275.  
  276.     def handle_map_d(self, *mapargs):
  277.         """Opacity texture file."""
  278.         opts, args = self.parseMapArgs(mapargs)
  279.         if len(args)>0:
  280.             self.map_d(args[0], opts)
  281.  
  282.     def handle_map_Bump(self, *mapargs):
  283.         """Bump map texture file."""
  284.         opts, args = self.parseMapArgs(mapargs)
  285.         if len(args)>0:
  286.             self.map_Bump(args[0], opts)
  287.  
  288.     def handle_refl(self, *mapargs):
  289.         """Reflection map."""
  290.         opts, args = self.parseMapArgs(mapargs)
  291.         if len(args)>0:
  292.             self.refl(args[0], opts)
  293.  
  294.     # Handler methods
  295.  
  296.     def newmtl(self, name):
  297.         pass
  298.  
  299.     def illum(self, model):
  300.         """Illumination model."""
  301.         pass
  302.  
  303.     def Ns(self, shininess):
  304.         """Shininess."""
  305.         pass
  306.  
  307.     def Ka(self, c):
  308.         """Ambient color.
  309.  
  310.         c is a vec3 containing the color.
  311.         """
  312.         pass
  313.  
  314.     def Kd(self, c):
  315.         """Diffuse color.
  316.  
  317.         c is a vec3 containing the color.
  318.         """
  319.         pass
  320.  
  321.     def Ks(self, c):
  322.         """Specular color.
  323.  
  324.         c is a vec3 containing the color.
  325.         """
  326.         pass
  327.  
  328.     def Ke(self, c):
  329.         """Emissive color.
  330.  
  331.         c is a vec3 containing the color.
  332.         """
  333.         pass
  334.  
  335.     def Tr(self, alpha):
  336.         """Transparency."""
  337.         pass
  338.  
  339.     def d(self, alpha):
  340.         """Dissolve factor (transparency)."""
  341.         pass
  342.  
  343.     def Tf(self, c):
  344.         """Transparency.
  345.  
  346.         c is a vec3 containing a color.
  347.         """
  348.         pass
  349.  
  350.     def Ni(self, ref):
  351.         """Refraction index."""
  352.         pass
  353.  
  354.     def sharpness(self, v):
  355.         """Sharpness value."""
  356.         pass
  357.  
  358.     def map_Ka(self, mapname, options):
  359.         pass
  360.  
  361.     def map_Kd(self, mapname, options):
  362.         pass
  363.  
  364.     def map_Ks(self, mapname, options):
  365.         pass
  366.  
  367.     def map_Ke(self, mapname, options):
  368.         pass
  369.  
  370.     def map_Ns(self, mapname, options):
  371.         pass
  372.  
  373.     def map_d(self, mapname, options):
  374.         pass
  375.  
  376.     def map_Bump(self, mapname, options):
  377.         pass
  378.  
  379.     def refl(self, mapname, options):
  380.         pass
  381.  
  382.  
  383. # OBJReader
  384. class OBJReader(WavefrontReaderBase):
  385.     """Wavefront OBJ reader.
  386.  
  387.     This class can be used as base class to read an OBJ file.
  388.     """
  389.     
  390.     def __init__(self):
  391.         """Constructor.
  392.         """
  393.         WavefrontReaderBase.__init__(self)
  394.         self.v_count = 0
  395.         self.vp_count = 0
  396.         self.vt_count = 0
  397.         self.vn_count = 0
  398.  
  399.     # read
  400.     def read(self, f):
  401.         self.v_count = 0
  402.         self.vp_count = 0
  403.         self.vt_count = 0
  404.         self.vn_count = 0
  405.         WavefrontReaderBase.read(self, f)
  406.  
  407.     # Pre handler methods (they must be called "handle_<keyword>")
  408.  
  409.     def handle_mtllib(self, *files):
  410.         """Material library command.
  411.  
  412.         files contains the filenames.
  413.         """
  414.         if len(files)==0:
  415.             raise SyntaxError, "No material library given in line %d: %s"%(self.linenr, self.line)
  416.         self.mtllib(*files)
  417.  
  418.     def handle_usemtl(self, *name):
  419.         """Material name.
  420.  
  421.         (all names are concatenated)
  422.         """
  423.         self.usemtl(" ".join(name))
  424.  
  425.     def handle_g(self, *groups):
  426.         """Group command.
  427.  
  428.         groups are the group names that the following geometry belongs to.
  429.         """
  430.         if len(groups)==0:
  431.             groups = ("default",)
  432. #            raise SyntaxError, "No group name given in line %d: %s"%(self.linenr, self.line)
  433.         self.g(*groups)
  434.  
  435.     def handle_s(self, group_number):
  436.         """Smoothing group command.
  437.  
  438.         group_number is a string that contains the smoothing group number
  439.         or "off".
  440.         """
  441.         group_number = group_number.lower()
  442.         if group_number=="off":
  443.             group_number = 0
  444.         try:
  445.             group_number = int(group_number)
  446.         except:
  447.             raise SyntaxError, "Invalid smoothing group number in line %d: %s"%(self.linenr, self.line)
  448.         self.s(group_number)
  449.  
  450.     def handle_v(self, x, y, z, w=1):
  451.         """Vertex definition.
  452.         """
  453.         self.v_count += 1
  454.         self.v(vec4(float(x), float(y), float(z), float(w)))
  455.  
  456.     def handle_vp(self, u, v=0, w=1):
  457.         """Vertex in parameter space.
  458.         """
  459.         self.vp_count += 1
  460.         self.vp(vec3(float(u), float(v), float(w)))
  461.  
  462.     def handle_vn(self, x, y, z):
  463.         """Normal.
  464.         """
  465.         self.vn_count += 1
  466.         self.vn(vec3(float(x), float(y), float(z)))
  467.  
  468.     def handle_vt(self, u, v=0, w=0):
  469.         """Texture vertex.
  470.         """
  471.         self.vt_count += 1
  472.         self.vt(vec3(float(u), float(v), float(w)))
  473.  
  474.     def handle_p(self, *verts):
  475.         """Points."""
  476.         
  477.         if len(verts)==0:
  478.             raise SyntaxError, "At least 1 vertex required in line %d: %s"%(self.linenr, self.line)
  479.  
  480.         vlist = []
  481.         for s in verts:
  482.             vert = int(s)
  483.             if vert<0:
  484.                 vert = self.v_count+vert+1
  485.             if vert==0:
  486.                 raise ValueError, "0-index in line %d: %s"%(self.linenr, self.line)
  487.             vlist.append(vert)
  488.             
  489.         self.p(*vlist)     
  490.  
  491.     def handle_l(self, *verts):
  492.         """Line."""
  493.  
  494.         if len(verts)<2:
  495.             raise SyntaxError, "At least 2 vertices required in line %d: %s"%(self.linenr, self.line)
  496.  
  497.         vlist = []
  498.         for s in verts:
  499.             a = s.split("/")
  500.             if len(a)==0 or len(a)>2:
  501.                 raise SyntaxError, "Syntax error in line %d: %s"%(self.linenr, self.line)
  502.             vert = int(a[0])
  503.             if vert<0:
  504.                 vert = self.v_count+vert+1
  505.             tvert = None
  506.             if len(a)>1:
  507.                 if a[1]!="":
  508.                     tvert = int(a[1])
  509.                     if tvert<0:
  510.                         tvert = self.vt_count+tvert+1
  511.             if vert==0 or tvert==0:
  512.                 raise ValueError, "0-index in line %d: %s"%(self.linenr, self.line)
  513.             vlist.append((vert, tvert))
  514.         self.l(*vlist)
  515.  
  516.     def handle_f(self, *verts):
  517.         """Polygonal face.
  518.         """
  519.         if len(verts)<3:
  520.             raise SyntaxError, "At least 3 vertices required in line %d: %s"%(self.linenr, self.line)
  521.  
  522.         vlist = []
  523.         for s in verts:
  524.             a = s.split("/")
  525.             if len(a)==0 or len(a)>3:
  526.                 raise SyntaxError, "Syntax error in line %d: %s"%(self.linenr, self.line)
  527.             vert = int(a[0])
  528.             if vert<0:
  529.                 vert = self.v_count+vert+1
  530.             tvert = None
  531.             normal = None
  532.             if len(a)>1:
  533.                 if a[1]!="":
  534.                     tvert = int(a[1])
  535.                     if tvert<0:
  536.                         tvert = self.vt_count+tvert+1
  537.                 if len(a)>2 and a[2]!="":
  538.                     normal = int(a[2])
  539.                     if normal<0:
  540.                         normal = self.vn_count+normal+1
  541.             if vert==0 or tvert==0 or normal==0:
  542.                 raise ValueError, "0-index in line %d: %s"%(self.linenr, self.line)
  543.             vlist.append((vert, tvert, normal))
  544.         self.f(*vlist)
  545.  
  546.     def handle_o(self, name):
  547.         """Object name.
  548.         """
  549.         self.o(name)
  550.  
  551.     def handle_bevel(self, on_off):
  552.         """Bevel interpolation on/off.
  553.         """
  554.         self.bevel(on_off)
  555.  
  556.     def handle_c_interp(self, on_off):
  557.         """Color interpolation on/off.
  558.         """
  559.         self.c_interp(on_off)
  560.  
  561.     def handle_d_interp(self, on_off):
  562.         """Dissolve interpolation on/off.
  563.         """
  564.         self.d_interp(on_off)
  565.  
  566.     def handle_lod(self, level):
  567.         """Level of Detail.
  568.         """
  569.         self.lod(int(level))
  570.  
  571.     def handle_shadow_obj(self, filename):
  572.         """Shadow object.
  573.         """
  574.         self.shadow_obj(filename)
  575.  
  576.     def handle_trace_obj(self, filename):
  577.         """Shadow object.
  578.         """
  579.         self.trace_obj(filename)
  580.  
  581.     # Handler methods
  582.  
  583.     def call(self, filename, *args):
  584.         pass
  585.  
  586.     def csh(self, cmd):
  587.         pass
  588.  
  589.     def mtllib(self, *files):
  590.         """Specification of material libraries.
  591.  
  592.         files is a sequence of file names that contain material definitions.
  593.         """
  594.         pass
  595.  
  596.     def usemtl(self, name):
  597.         """Material name.
  598.  
  599.         name is a string containing the name of the material to use for
  600.         the following elements.
  601.         """
  602.         pass
  603.  
  604.     def g(self, *groups):
  605.         """Grouping statement.
  606.  
  607.         groups is a sequence of group names that the following geometry
  608.         belongs to.
  609.         """
  610.         pass
  611.  
  612.     def s(self, group_number):
  613.         """Smoothing group.
  614.  
  615.         group_number is an integer containing the smoothing group number.
  616.         Smoothing groups should be turned off if the group number is 0.
  617.         """
  618.         pass
  619.  
  620.     def v(self, vert):
  621.         """Geometric vertex.
  622.  
  623.         vert is always a vec4."""
  624.         pass
  625.  
  626.     def vp(self, vert):
  627.         """A point in parameter space.
  628.  
  629.         This vertex is used for free-form curves or surfaces.
  630.         vert is always a vec3.
  631.         """
  632.         pass
  633.  
  634.     def vn(self, normal):
  635.         """Normal vector.
  636.         
  637.         normal is a vec3.
  638.         """
  639.         pass
  640.  
  641.     def vt(self, tvert):
  642.         """Texture vertex.
  643.         
  644.         tvert is always a vec3.
  645.         """
  646.         pass
  647.  
  648.     def p(self, *verts):
  649.         """Points.
  650.  
  651.         verts is a list of vertex indices. The indices are always >0
  652.         (negative indices are automatically converted to their
  653.         corresponding positive indices).
  654.         All indices are 1-based. If an index in the file was 0, an exception
  655.         was already thrown.
  656.         """
  657.         print "POINT",verts
  658.  
  659.     def l(self, *verts):
  660.         """Line.
  661.  
  662.         verts contains 2-tuples (vert, tvert) which contains the indices
  663.         to the vertexa and the texture vertex. tvert may be None.
  664.         The indices are always >0 (negative indices are automatically
  665.         converted to their corresponding positive indices).
  666.         All indices are 1-based. If an index in the file was 0, an exception
  667.         was already thrown.
  668.         """
  669.         pass
  670.  
  671.     def f(self, *verts):
  672.         """Polygonal face.
  673.         
  674.         verts contains 3-tuples (vert, tvert, normal) which contains
  675.         the indices to the vertex, the texture vertex and the normal.
  676.         tvert and normal may be None, otherwise the values are always >0
  677.         (negative indices are automatically converted to their corresponding
  678.         positive indices).
  679.         All indices are 1-based. If an index in the file was 0, an exception
  680.         was already thrown.
  681.         """
  682.         pass
  683.  
  684.     def o(self, name):
  685.         """Optional object name.
  686.  
  687.         name is a string containing the specified name for the elements
  688.         following this statement.
  689.         """
  690.         pass
  691.  
  692.     def bevel(self, on_off):
  693.         pass
  694.  
  695.     def c_interp(self, on_off):
  696.         pass
  697.  
  698.     def d_interp(self, on_off):
  699.         pass
  700.  
  701.     def lod(self, level):
  702.         """
  703.         level is an integer.
  704.         """
  705.         pass
  706.  
  707.     def shadow_obj(self, filename):
  708.         pass
  709.  
  710.     def trace_obj(self, filename):
  711.         pass
  712.  
  713.