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 / objmaterial.py < prev    next >
Encoding:
Python Source  |  2007-01-11  |  16.4 KB  |  538 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: objmaterial.py,v 1.7 2005/08/28 19:42:43 mbaas Exp $
  36.  
  37. ## \file objmaterial.py
  38. ## Contains the OBJMaterial class.
  39.  
  40. import os.path, sys
  41. import protocols
  42. from Interfaces import *
  43. from slots import *
  44. from material import Material
  45. import ribexport
  46. import _Image as Image
  47. from expression import Expression
  48. import _core
  49. from cgtypes import *
  50.  
  51. # OBJTextureMap
  52. class OBJTextureMap:
  53.     """A texture map definition as it appears in OBJ/MTL files.
  54.     """
  55.  
  56.     def __init__(self,
  57.                  filename,
  58.                  offset = (0,0,0),
  59.                  scale = (1,1,1),
  60.                  turb = (0,0,0),
  61.                  mm = (0.0, 1.0),
  62.                  clamp = False,
  63.                  blendu = True,
  64.                  blendv = True,
  65.                  bumpsize = None,
  66.                  refltype = None):
  67.         
  68.         self.filename = filename
  69.         self.offset = offset
  70.         self.scale = scale
  71.         self.turb = turb
  72.         self.mm = mm
  73.         self.clamp = clamp
  74.         self.blendu = blendu
  75.         self.blendv = blendv
  76.         if bumpsize!=None:
  77.             self.bumpsize = bumpsize
  78.         if refltype!=None:
  79.             self.refltype = refltype
  80.         
  81.         
  82. # OBJMaterial
  83. #class OBJMaterial(Material):
  84. class OBJMaterial(_core.GLMaterial):
  85.     """This class represents a material as it appears in OBJ (or rather MTL) files.
  86.  
  87.     """
  88.  
  89.     protocols.advise(instancesProvide=[ribexport.IMaterial])
  90.     
  91.     def __init__(self,
  92.                  name="OBJMaterial",
  93.                  illum = 2,
  94.                  Ka = (0.2, 0.2, 0.2),
  95.                  Kd = (0.8, 0.8, 0.8),
  96.                  Ks = (0.0, 0.0, 0.0),
  97.                  Ke = (0.0, 0.0, 0.0),
  98.                  Ns = 0.0,
  99.                  Ni = 1.0,
  100.                  d = 1.0,
  101.                  Tr = 1.0,
  102.                  Tf = (1.0, 1.0, 1.0),
  103.                  sharpness = 0.0,
  104.                  map_Ka = None,
  105.                  map_Kd = None,
  106.                  map_Ks = None,
  107.                  map_Ke = None,
  108.                  map_Ns = None,
  109.                  map_d = None,
  110.                  map_Bump = None,
  111.                  refl = None,  # one single map or a list of maps
  112.                  density = 1.0,
  113.                  ):
  114.  
  115. #        Material.__init__(self, name=name, density=density)
  116.         _core.GLMaterial.__init__(self, name, density)
  117.  
  118.         # Create a Kd slot and connect it with the GL diffuse slot
  119.         self.Kd_slot = Vec3Slot(vec3(Kd))
  120.         self.addSlot("Kd", self.Kd_slot)
  121.         self.diffuse_adapter = Expression("(col.x,col.y,col.z,1)", col=vec3())
  122.         self.Kd_slot.connect(self.diffuse_adapter.col_slot)
  123.         self.diffuse_adapter.output_slot.connect(self.diffuse_slot)
  124.  
  125.         self.illum = illum
  126.         self.Ka = Ka
  127. #        self.Kd = Kd
  128.         self.Ks = Ks
  129.         self.Ke = Ke
  130.         self.Ns = Ns
  131.         self.Ni = Ni
  132.         self.d = d
  133.         self.Tr = Tr
  134.         self.Tf = vec3(Tf)
  135.         self.sharpness = sharpness
  136.         self.map_Ka = map_Ka
  137.         self.map_Kd = map_Kd
  138.         self.map_Ks = map_Ks
  139.         self.map_Ke = map_Ke
  140.         self.map_Ns = map_Ns
  141.         self.map_d = map_d
  142.         self.map_Bump = map_Bump
  143.  
  144.         if refl==None:
  145.             refl = []
  146.         else:
  147.             # Turn refl into a list
  148.             try:
  149.                 refl = list(refl)
  150.             except:
  151.                 refl = [refl]
  152.         self.refl = refl
  153.  
  154.         # "Hide" the GLMaterial slots
  155.         self.removeSlot("ambient")
  156.         self.removeSlot("diffuse")
  157.         self.removeSlot("specular")
  158.         self.removeSlot("shininess")
  159.         self.removeSlot("emission")
  160.  
  161.     exec slotPropertyCode("Kd")
  162.  
  163.     def mtlDefinition(self):
  164.         s = """illum %d
  165. Ka %f %f %f
  166. Kd %f %f %f
  167. Ks %f %f %f
  168. Ke %f %f %f
  169. Ns %f
  170. Ni %f
  171. """%(self.illum,
  172.      self.Ka[0], self.Ka[1], self.Ka[2],
  173.      self.Kd[0], self.Kd[1], self.Kd[2],
  174.      self.Ks[0], self.Ks[1], self.Ks[2],
  175.      self.Ke[0], self.Ke[1], self.Ke[2],
  176.      self.Ns,
  177.      self.Ni)
  178.         if self.d!=1.0:
  179.             s += "d %f\n"%self.d
  180.         if self.Tr!=1.0:
  181.             s += "Tr %f\n"%self.d
  182.         if self.Tf[0]!=1.0 or self.Tf[1]!=1.0 or self.Tf[2]!=1.0:
  183.             s += "Tf %f %f %f\n"%(self.Tf[0], self.Tf[1], self.Tf[2])
  184.         s += self.mapDefinition("map_Ka", self.map_Ka)
  185.         s += self.mapDefinition("map_Kd", self.map_Kd)
  186.         s += self.mapDefinition("map_Ks", self.map_Ks)
  187.         s += self.mapDefinition("map_Ke", self.map_Ke)
  188.         s += self.mapDefinition("map_Ns", self.map_Ns)
  189.         s += self.mapDefinition("map_d", self.map_d)
  190.         s += self.mapDefinition("map_Bump", self.map_Bump)
  191.         for map in self.refl:
  192.             s += self.mapDefinition("refl", map)
  193.         return s
  194.  
  195.     # mapDefinition
  196.     def mapDefinition(self, mapname, map):
  197.         """Return the map defintion line or an empty string.
  198.         """
  199.         if map==None:
  200.             return ""
  201.  
  202.         onoff = {True:"on", False:"off"}
  203.  
  204.         res = mapname
  205.         # -o
  206.         u,v,w = map.offset
  207.         if u!=0 or v!=0 or w!=0:
  208.             res += " -o %f %f %f"%(u,v,w)
  209.         # -s
  210.         u,v,w = map.scale
  211.         if u!=1 or v!=1 or w!=1:
  212.             res += " -s %f %f %f"%(u,v,w)
  213.         # -t
  214.         u,v,w = map.turb
  215.         if u!=0 or v!=0 or w!=0:
  216.             res += " -t %f %f %f"%(u,v,w)
  217.         # -mm
  218.         base, gain = map.mm
  219.         if base!=0 or gain!=1:
  220.             res += " -mm %f %f"%(base, gain)
  221.         # -clamp
  222.         if map.clamp:
  223.             res += " -clamp %s"%onoff[map.clamp]
  224.         # -blendu
  225.         if not map.blendu:
  226.             res += " -blendu %s"%onoff[map.blendu]
  227.         # -blendv
  228.         if not map.blendv:
  229.             res += " -blendv %s"%onoff[map.blendv]
  230.         # -bm
  231.         if mapname=="map_Bump" and getattr(map, "bumpsize", 1)!=1:
  232.             res += " -bm %f"%map.bumpsize
  233.         # -type
  234.         if mapname=="refl":
  235.             res += " -type %s"%getattr(map, "refltype", "sphere")
  236.  
  237.         return res+" %s\n"%map.filename        
  238.         
  239.         
  240.     def createPasses(self):
  241.         """Returns a list of RenderPass objects."""
  242.         texdefs = []
  243.         if self.map_Ka!=None:
  244.             texdefs.append((self.map_Ka.filename, "periodic", "periodic", "gaussian", 0.01, 0.01, {}))
  245.         if self.map_Kd!=None:
  246.             texdefs.append((self.map_Kd.filename, "periodic", "periodic", "gaussian", 0.01, 0.01, {}))
  247.         if self.map_Ks!=None:
  248.             texdefs.append((self.map_Ks.filename, "periodic", "periodic", "gaussian", 0.01, 0.01, {}))
  249.         if self.map_d!=None:
  250.             texdefs.append((self.map_d.filename, "periodic", "periodic", "gaussian", 0.01, 0.01, {}))
  251.         if self.map_Bump!=None:
  252.             texdefs.append((self.map_Bump.filename, "periodic", "periodic", "gaussian", 0.01, 0.01, {}))
  253.         
  254.         if texdefs!=[]:
  255.             return [ribexport.TexPass(maps=texdefs)]
  256.         else:
  257.             return []
  258.  
  259.     def preProcess(self, exporter):
  260.         """Preprocessing method.
  261.  
  262.         This method is called before the image is rendered and can be used
  263.         to create or copy image maps.
  264.         """
  265.         pass
  266.             
  267.  
  268.     def color(self):
  269.         """Return the color for the RiColor() call or None.
  270.         """
  271.         return None
  272. #        return self.Kd
  273.  
  274.     def opacity(self):
  275.         """Return the opacity for the RiOpacity() call or None.
  276.         """
  277.         return None
  278. #        a = self.Tr*self.d
  279. #        return (a,a,a)
  280.  
  281.     def surfaceShaderName(self):
  282.         """Returns the name of the corresponding surface shader or None.
  283.         """
  284.         return "matobj"
  285.  
  286.     def surfaceShaderSource(self):
  287.         """Returns surface shader source code as a string or None.
  288.  
  289.         If the return value is None, then shaderName() must return
  290.         the name of the shader to use.
  291.         """
  292.         return """// OBJ/MTL material shader
  293.         
  294. surface $SHADERNAME(float illum = 2;
  295.            color Ka = color "rgb" (0.2, 0.2, 0.2);
  296.            color Kd = color "rgb" (0.8, 0.8, 0.8);
  297.            color Ks = color "rgb" (0.8, 0.8, 0.8);
  298.            color Ke = color "rgb" (0, 0, 0);
  299.            float Ni = 0.0;
  300.            float Ns = 0.0;
  301.            float d = 1.0;
  302.            float Tr = 1.0;
  303.            color Tf = color "rgb" (1.0, 1.0, 1.0);
  304.            
  305.            string map_Ka = "";
  306.            float map_Ka_offset[3] = {0, 0, 0};
  307.            float map_Ka_scale[3] = {1, 1, 1};
  308.            
  309.            string map_Kd = "";
  310.            float map_Kd_offset[3] = {0, 0, 0};
  311.            float map_Kd_scale[3] = {1, 1, 1};
  312.            
  313.            string map_Ks = "";
  314.            float map_Ks_offset[3] = {0, 0, 0};
  315.            float map_Ks_scale[3] = {1, 1, 1};
  316.  
  317.            string map_Ke = "";
  318.            float map_Ke_offset[3] = {0, 0, 0};
  319.            float map_Ke_scale[3] = {1, 1, 1};
  320.  
  321.            string map_Ns = "";
  322.            float map_Ns_offset[3] = {0, 0, 0};
  323.            float map_Ns_scale[3] = {1, 1, 1};
  324.  
  325.            string map_d = "";
  326.            float map_d_offset[3] = {0, 0, 0};
  327.            float map_d_scale[3] = {1, 1, 1};
  328.  
  329.            varying point Pref = point(0,0,0);
  330.            )
  331. {
  332.   BAKE_BEGIN
  333.   normal Nf = BAKE_NORMAL(N);
  334.   color _Ka = Ka;
  335.   color _Kd = Kd;
  336.   color _Ks = Ks;
  337.   color _Ke = Ke;
  338.   float _Ns = Ns;
  339.   float _d = d;
  340.  
  341.   if (map_Ka!="")
  342.   {
  343.     _Ka = texture(map_Ka,
  344.                   s*map_Ka_scale[0]+map_Ka_offset[0],
  345.                   (1-t)*map_Ka_scale[1]+map_Ka_offset[1]);
  346.   }
  347.  
  348.   if (map_Kd!="")
  349.   {
  350.     _Kd = texture(map_Kd,
  351.                   s*map_Kd_scale[0]+map_Kd_offset[0],
  352.                   (1-t)*map_Kd_scale[1]+map_Kd_offset[1]);
  353.   }
  354.  
  355.   if (map_Ks!="")
  356.   {
  357.     _Ks = texture(map_Ks,
  358.                   s*map_Ks_scale[0]+map_Ks_offset[0],
  359.                   (1-t)*map_Ks_scale[1]+map_Ks_offset[1]);
  360.   }
  361.  
  362.   if (map_Ke!="")
  363.   {
  364.     _Ke = texture(map_Ke,
  365.                   s*map_Ke_scale[0]+map_Ke_offset[0],
  366.                   (1-t)*map_Ke_scale[1]+map_Ke_offset[1]);
  367.   }
  368.  
  369.   if (map_Ns!="")
  370.   {
  371.     _Ns = texture(map_Ns,
  372.                   s*map_Ns_scale[0]+map_Ns_offset[0],
  373.                   (1-t)*map_Ns_scale[1]+map_Ns_offset[1]);
  374.   }
  375.  
  376.   if (map_d!="")
  377.   {
  378.     _d = texture(map_d,
  379.                  s*map_d_scale[0]+map_d_offset[0],
  380.                  (1-t)*map_d_scale[1]+map_d_offset[1]);
  381.   }
  382.  
  383.   if (illum==0)
  384.   {
  385.     Ci = _Kd;
  386.   }
  387.   else if (illum==1)
  388.   {
  389.     Ci = _Ka + _Kd*diffuse(Nf);
  390.   }
  391.   else
  392.   {
  393.     // Ns==0? then disable specular part
  394.     if (_Ns<1E-6)
  395.     {
  396.       _Ks = color "rgb" (0,0,0);
  397.     }
  398.     Ci = _Ka*ambient() + _Kd*diffuse(Nf) + _Ks*specular(Nf,-normalize(I),1/_Ns) + _Ke;
  399.   }  
  400.  
  401.   Oi = _d*Tr*Tf;
  402.   Ci *= Oi;
  403.   BAKE_END
  404. }        
  405.         """
  406.  
  407.     def surfaceShaderParams(self, passes):
  408.         """Return a dictionary with shader parameters and their values."""
  409.         res = {"uniform float illum" : self.illum,
  410.                "uniform color Ka" : self.Ka,
  411.                "uniform color Kd" : self.Kd,
  412.                "uniform color Ks" : self.Ks,
  413.                "uniform color Ke" : self.Ke,
  414.                "uniform float Ns" : self.Ns,
  415.                "uniform float Ni" : self.Ni,
  416.                "uniform float d" : self.d,
  417.                "uniform float Tr" : self.Tr,
  418.                "uniform color Tf" : self.Tf
  419.                }
  420.  
  421.         if self.map_Ka!=None:
  422.             texname = os.path.basename(self.map_Ka.filename)
  423.             name, ext = os.path.splitext(texname)
  424.             res["uniform string map_Ka"] = name+".tex"       
  425.             res["uniform float[3] map_Ka_offset"] = self.map_Ka.offset
  426.             res["uniform float[3] map_Ka_scale"] = self.map_Ka.scale
  427.  
  428.         if self.map_Kd!=None:
  429.             texname = os.path.basename(self.map_Kd.filename)
  430.             name, ext = os.path.splitext(texname)
  431.             res["uniform string map_Kd"] = name+".tex"       
  432.             res["uniform float[3] map_Kd_offset"] = self.map_Kd.offset
  433.             res["uniform float[3] map_Kd_scale"] = self.map_Kd.scale
  434.  
  435.         if self.map_Ks!=None:
  436.             texname = os.path.basename(self.map_Ks.filename)
  437.             name, ext = os.path.splitext(texname)
  438.             res["uniform string map_Ks"] = name+".tex"       
  439.             res["uniform float[3] map_Ks_offset"] = self.map_Ks.offset
  440.             res["uniform float[3] map_Ks_scale"] = self.map_Ks.scale
  441.  
  442.         if self.map_Ke!=None:
  443.             texname = os.path.basename(self.map_Ke.filename)
  444.             name, ext = os.path.splitext(texname)
  445.             res["uniform string map_Ke"] = name+".tex"  
  446.             res["uniform float[3] map_Ke_offset"] = self.map_Ke.offset
  447.             res["uniform float[3] map_Ke_scale"] = self.map_Ke.scale
  448.  
  449.         if self.map_Ns!=None:
  450.             texname = os.path.basename(self.map_Ns.filename)
  451.             name, ext = os.path.splitext(texname)
  452.             res["uniform string map_Ns"] = name+".tex"
  453.             res["uniform float[3] map_Ns_offset"] = self.map_Ns.offset
  454.             res["uniform float[3] map_Ns_scale"] = self.map_Ns.scale
  455.  
  456.         if self.map_d!=None:
  457.             texname = os.path.basename(self.map_d.filename)
  458.             name, ext = os.path.splitext(texname)
  459.             res["uniform string map_d"] = name+".tex"       
  460.             res["uniform float[3] map_d_offset"] = self.map_d.offset
  461.             res["uniform float[3] map_d_scale"] = self.map_d.scale
  462.  
  463.         return res
  464.         
  465.     def surfaceShaderTransform(self):
  466.         return mat4(1)
  467.  
  468.     def displacementShaderName(self):
  469.         if self.map_Bump==None:
  470.             return None
  471.         
  472.         return "matobj_bump"
  473.  
  474.    
  475.     def displacementShaderSource(self):
  476.         if self.map_Bump==None:
  477.             return None
  478.         
  479.         return """// OBJ/MTL material shader (bump)
  480.         
  481. displacement $SHADERNAME(
  482.            string map_Bump = "";
  483.            float bump_size = 1.0;
  484.            float map_Bump_offset[3] = {0, 0, 0};
  485.            float map_Bump_scale[3] = {1, 1, 1};
  486.            )
  487. {
  488.   float amount = 0;
  489.   
  490.   if (map_Bump!="")
  491.   {
  492.     color bc = texture(map_Bump,
  493.                        s*map_Bump_scale[0]+map_Bump_offset[0],
  494.                       (1-t)*map_Bump_scale[1]+map_Bump_offset[1]);
  495.     amount = (comp(bc,0)+comp(bc,1)+comp(bc,2))/3;
  496.   }
  497.  
  498.   P = P + bump_size*amount*normalize(N);
  499.   N = calculatenormal(P);
  500. }
  501.         """
  502.     
  503.     def displacementShaderParams(self, passes):
  504.         if self.map_Bump==None:
  505.             return {}
  506.  
  507.         res = {}
  508.         texname = os.path.basename(self.map_Bump.filename)
  509.         name, ext = os.path.splitext(texname)
  510.         res["uniform string map_Bump"] = name+".tex"
  511.         res["uniform float bump_size"] = getattr(self.map_Bump, "bumpsize", 1.0)
  512.         res["uniform float[3] map_Bump_offset"] = self.map_Bump.offset
  513.         res["uniform float[3] map_Bump_scale"] = self.map_Bump.scale
  514.         return res
  515.  
  516.     def displacementShaderTransform(self):
  517.         return mat4(1)
  518.  
  519.     def displacementBound(self):
  520.         if self.map_Bump==None:
  521.             return "current", 0
  522.         else:
  523.             return "current", abs(getattr(self.map_Bump, "bumpsize", 1.0))
  524.     
  525.     def interiorShaderName(self):
  526.         return None
  527.     
  528.     def interiorShaderSource(self):
  529.         return None
  530.     
  531.     def interiorShaderParams(self, passes):
  532.         return {}
  533.  
  534.     def interiorShaderTransform(self):
  535.         return mat4(1)
  536.       
  537.         
  538.