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 / sl.py < prev    next >
Encoding:
Python Source  |  2007-01-11  |  14.4 KB  |  554 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. # -------------------------------------------------------------
  36. # The RenderMan (R) Interface Procedures and Protocol are:
  37. # Copyright 1988, 1989, 2000, Pixar
  38. # All Rights Reserved
  39. #
  40. # RenderMan (R) is a registered trademark of Pixar
  41. # -------------------------------------------------------------
  42. # $Id: sl.py,v 1.2 2006/02/14 19:29:39 mbaas Exp $
  43.  
  44. """RenderMan Shading Language functionality.
  45.  
  46. This module provides some of the functionality from the RenderMan
  47. Shading Language. Those functions that require an actual rendering
  48. context (surfaces, light sources, etc.) are not supported.
  49.  
  50. Most of the functions can be used just like in the Shading
  51. Language. An exception are those functions whose return type is
  52. dependant on the context as it is the case with random() or
  53. noise(). Here, those functions have to be prepended with the return
  54. type, for example float_random() or point_noise() (that is, the cast
  55. is part of the name).
  56. """
  57.  
  58. import math, random, string, re
  59. from math import acos, asin, ceil, cos, exp, floor, pow, sin, sqrt, tan
  60. import noise
  61. from cgtypes import vec3 as _vec3
  62.  
  63. # Builtin functions
  64. abs = abs
  65. max = max
  66. min = min
  67. round = round
  68.  
  69. PI = math.pi
  70.  
  71. def _tovec3(arg):
  72.     try:
  73.         a = len(arg)
  74.     except:
  75.         a = 1
  76.     if a==1:
  77.         return _vec3(arg,0.0,0.0)
  78.     elif a==2:
  79.         x,y=arg
  80.         return _vec3(x,y,0.0)
  81.     elif a==3:
  82.         x,y,z=arg
  83.         return _vec3(x,y,z)
  84.     elif a==4:
  85.         x,y,z,t=arg
  86.         return _vec3(x,y,z)
  87.     else:
  88.         return _vec3()
  89.     
  90.  
  91. def atan(*args):
  92.     """Returns the arc tangent.
  93.  
  94.     With one argument it math.atan() is called, with two arguments
  95.     math.atan2() is called.
  96.     """
  97.     
  98.     if len(args)==1:
  99.         return math.atan(args[0])
  100.     elif len(args)==2:
  101.         return math.atan2(args[0],args[1])
  102.     else:
  103.         raise TypeError,"atan only takes 1 or 2 arguments."
  104.  
  105. def log(*args):
  106.     """Returns the natural logarithm of x or the logarithm to the specified base."""
  107.  
  108.     if len(args)==1:
  109.         return math.log(args[0])
  110.     elif len(args)==2:
  111.         return math.log(args[0])/math.log(args[1])
  112.     else:
  113.         raise TypeError,"log only takes 1 or 2 arguments."
  114.     
  115.  
  116. # clamp
  117. def clamp(a, amin, amax):
  118.     """Returns amin if a < amin, amax if a > amax, otherwise a."""
  119.     return min(max(a,amin), amax)
  120.  
  121. # degrees
  122. def degrees(rad):
  123.     """Convert from radians to degrees."""
  124.     return rad*180.0/PI
  125.  
  126. # radians
  127. def radians(deg):
  128.     """Convert from degrees to radians."""
  129.     return deg*PI/180.0
  130.  
  131. def Du(p):
  132.     pass
  133.  
  134. def Dv(p):
  135.     pass
  136.  
  137. def Deriv(num, den):
  138.     pass
  139.  
  140. def filterstep(edge, s1):
  141.     pass
  142.  
  143. def inversesqrt(x):
  144.     """Returns 1/sqrt(x)."""  
  145.     return 1.0/sqrt(x)
  146.  
  147. def mix(val0, val1, t):
  148.     """Mix two values.
  149.  
  150.     For t=0 the value val0 is returned, for t=1 the value val1 is
  151.     returned. For values of t between 0 and 1 a linearly interpolated
  152.     value is returned.
  153.     """
  154.     
  155.     return (1.0-t)*val0 + t*val1
  156.  
  157. def mod(a,b):
  158.     """Returns a%b. This is just an equivalent for the %-operator."""
  159.     return a%b
  160.  
  161. def float_noise(*args):
  162.     """Returns a float value which is a (pseudo) random function of its arguments.
  163.  
  164.     This function is imported from the noise module.
  165.     """
  166.     
  167.     la = len(args)
  168.     if la==1:
  169.         return noise.noise(args[0])
  170.     elif la==2:
  171.         return noise.noise(args[0],args[1])
  172.     elif la==3:
  173.         return noise.noise(args[0],args[1],args[2])
  174.     elif la==4:
  175.         return noise.noise(args[0],args[1],args[2],args[3])
  176.     else:
  177.         raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
  178.  
  179.  
  180. def point_noise(*args):
  181.     """Returns a point whose value is a (pseudo) random function of its arguments."""
  182.     
  183.     la = len(args)
  184.     if la==1:
  185.         try:
  186.             a = len(args[0])
  187.         except:
  188.             a = 1
  189.         if a==1:
  190.             return noise.vnoise(args[0],0,0)
  191.         elif a==2:
  192.             return noise.vnoise(args[0],0)
  193.         elif a==3:
  194.             return noise.vnoise(args[0])
  195.         else:
  196.             raise ValueError,"arg1: invalid argument length"            
  197.     elif la==2:
  198.         try:
  199.             a = len(args[0])
  200.         except:
  201.             a = 1
  202.         if a==1:
  203.             return noise.vnoise(args[0],args[1],0)
  204.         elif a==3:
  205.             return noise.vnoise(args[0],args[1])
  206.         else:
  207.             raise ValueError,"arg1: invalid argument length"
  208.     elif la==3:
  209.         return noise.vnoise(args[0],args[1],args[2])
  210.     elif la==4:
  211.         x,y,z,t = noise.vnoise(args[0],args[1],args[2],args[3])
  212.         return _vec3(x,y,z)
  213.     else:
  214.         raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
  215.    
  216. color_noise = point_noise
  217. vector_noise = point_noise
  218.  
  219. def float_pnoise(*args):
  220.     """Returns a float value which is a periodic (pseudo) random function of its arguments.
  221.  
  222.     This function is imported from the noise module."""
  223.     
  224.     la = len(args)
  225.     try:
  226.         a = len(args[0])
  227.     except:
  228.         a = 1
  229.         
  230.     if la==2:
  231.         if a==1:
  232.             return noise.pnoise((args[0],),(args[1],))
  233.         else:
  234.             return noise.pnoise(args[0],args[1])
  235.     elif la==4:
  236.         if a==1:
  237.             return noise.pnoise((args[0],args[1]),(args[2],args[3]))
  238.         else:
  239.             return noise.pnoise(args[0],args[1],args[2],args[3])
  240.     else:
  241.         raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
  242.  
  243. def point_pnoise(*args):
  244.     """Returns a point whose value is a periodic (pseudo) random function of its arguments."""
  245.     
  246.     la = len(args)
  247.     try:
  248.         a = len(args[0])
  249.     except:
  250.         a = 1
  251.         
  252.     if la==2:
  253.         if a==1:
  254.             res = noise.vpnoise((args[0],),(args[1],))
  255.         else:
  256.             res = noise.vpnoise(args[0],args[1])
  257.     elif la==4:
  258.         if a==1:
  259.             res = noise.vpnoise((args[0],args[1]),(args[2],args[3]))
  260.         else:
  261.             res = noise.vpnoise(args[0],args[1],args[2],args[3])
  262.     else:
  263.         raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
  264.  
  265.     return _tovec3(res)
  266.  
  267. color_pnoise = point_pnoise
  268. vector_pnoise = point_pnoise
  269.  
  270. def float_cellnoise(*args):
  271.     """Returns a float value which is a (pseudo) random function of its arguments.
  272.  
  273.     The return value is constant between integer lattice points. This
  274.     function is imported from the noise module.
  275.     """
  276.     
  277.     la = len(args)
  278.     if la==1:
  279.         return noise.cellnoise(args[0])
  280.     elif la==2:
  281.         return noise.cellnoise(args[0],args[1])
  282.     elif la==3:
  283.         return noise.cellnoise(args[0],args[1],args[2])
  284.     elif la==4:
  285.         return noise.cellnoise(args[0],args[1],args[2],args[3])
  286.     else:
  287.         raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
  288.  
  289. def point_cellnoise(*args):
  290.     """Returns a point whose value is a (pseudo) random function of its arguments.
  291.  
  292.     The return value is constant between integer lattice points.
  293.     """
  294.     
  295.     la = len(args)
  296.     if la==1:
  297.         try:
  298.             a = len(args[0])
  299.         except:
  300.             a = 1
  301.         if a==1:
  302.             return noise.vcellnoise(args[0],0,0)
  303.         elif a==2:
  304.             return noise.vcellnoise(args[0],0)
  305.         elif a==3:
  306.             return noise.vcellnoise(args[0])
  307.         else:
  308.             raise ValueError,"arg1: invalid argument length"            
  309.     elif la==2:
  310.         try:
  311.             a = len(args[0])
  312.         except:
  313.             a = 1
  314.         if a==1:
  315.             return noise.vcellnoise(args[0],args[1],0)
  316.         elif a==3:
  317.             return noise.vcellnoise(args[0],args[1])
  318.         else:
  319.             raise ValueError,"arg1: invalid argument length"
  320.     elif la==3:
  321.         return noise.vcellnoise(args[0],args[1],args[2])
  322.     elif la==4:
  323.         x,y,z,t = noise.vcellnoise(args[0],args[1],args[2],args[3])
  324.         return _vec3(x,y,z)
  325.     else:
  326.         raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
  327.    
  328. color_cellnoise = point_cellnoise
  329. vector_cellnoise = point_cellnoise
  330.  
  331. def float_random():
  332.     """Return a random number between 0 and 1.
  333.  
  334.     This call is equivalent to random.random()."""
  335.     
  336.     return random.random()
  337.  
  338. def color_random():
  339.     """Return a color whose componenets are a random number between 0 and 1.
  340.  
  341.     The function actually returns a vec3."""
  342.     
  343.     return _vec3(random.random(), random.random(), random.random())
  344.  
  345. def point_random():
  346.     """Return a point (a vec3) whose componenets are a random number between 0 and 1."""
  347.     return _vec3(random.random(), random.random(), random.random())
  348.  
  349. def sign(x):
  350.     """Returns -1 with a negative argument, +1 with a positive argument, and 0 if its argument is zero."""
  351.     
  352.     if x<0:
  353.         return -1
  354.     elif x>0:
  355.         return 1
  356.     else:
  357.         return 0
  358.  
  359. def smoothstep(min, max, x):
  360.     """Returns the value of a smooth step function.
  361.  
  362.     Returns 0 if x < min, 1 if x > max, and performs a smooth Hermite
  363.     interpolation between 0 and 1 in the interval min to max.
  364.     """
  365.     
  366.     if x<min:
  367.         return 0.0
  368.     if x>max:
  369.         return 1.0
  370.     x = (x-min)/(max-min)
  371.     return x*x*(3.0-2.0*x)
  372.  
  373. def spline(x, knots):
  374.     """Return the value of a spline function.
  375.  
  376.     Fits a spline to the control points given and returns the value at
  377.     t which ranges from 0 to 1. At least four control points must
  378.     always be given.
  379.     """
  380.  
  381.     nknots = len(knots)
  382.     nspans = nknots-3
  383.  
  384.     if nspans<1:
  385.         raise ValueError, "spline(): there must be at least 4 control points ("+`nknots`+" given)"
  386.  
  387.     x = clamp(x, 0.0, 1.0)*nspans
  388.     span = int(x)
  389.     if span>=nknots-3:
  390.         span = nknots-4
  391.     x    -= span
  392.     knot0, knot1, knot2, knot3 = knots[span:span+4]
  393.  
  394.     c3 = -0.5*knot0 + 1.5*knot1 - 1.5*knot2 + 0.5*knot3
  395.     c2 =      knot0 - 2.5*knot1 + 2.0*knot2 - 0.5*knot3
  396.     c1 = -0.5*knot0 + 0.5*knot2
  397.     c0 =      knot1
  398.  
  399.     return ((c3*x + c2)*x + c1)*x + c0
  400.  
  401.  
  402. def step(min, x):
  403.     """Returns 0 if x < min, otherwise 1."""
  404.     if x<min:
  405.         return 0.0
  406.     else:
  407.         return 1.0
  408.  
  409.  
  410. def distance(P1,P2):
  411.     """Returns the distance between two points.
  412.  
  413.     The arguments should be of type vec3."""
  414.     return (P2-P1).length()
  415.  
  416. def ptlined(P0,P1,Q):
  417.     """Returns the distance between a point and a line segment.
  418.  
  419.     The arguments should be of type vec3.    
  420.     """
  421.     a = P1-P0
  422.     b = Q-P0
  423.     
  424.     x  = a*b
  425.     if x<=0:
  426.         return b.length()
  427.     
  428.     aa = a*a
  429.     if x>=aa:
  430.         return (Q-P1).length()
  431.     
  432.     return sqrt(b*b-(x*x/aa))
  433.  
  434. def faceforward(N,I,Nref):
  435.     """Flips N so that it faces in the direction opposite to I."""
  436.     return sign(-I*Nref)*N
  437.  
  438. def length(v):
  439.     """Returns the length of a vector.
  440.  
  441.     This is equivalent to calling v.length().
  442.     """
  443.     return v.length()
  444.  
  445. def normalize(v):
  446.     """Returns a unit vector in the direction of v.
  447.  
  448.     This is equivalent to calling v.normalize().
  449.     """
  450.     return v.normalize()
  451.  
  452. def reflect(I, N):
  453.     """Returns the reflection vector given an incident direction I and a normal N.
  454.  
  455.     This is equivalent to calling I.reflect(N).
  456.     """
  457.     return I.reflect(N)
  458.  
  459. def refract(I, N, eta):
  460.     """Returns the transmitted vector.
  461.  
  462.     Returns the transmitted vector given an incident direction I, the
  463.     normal vector N and the relative index of refraction eta. This is
  464.     equivalent to calling I.refract(N, eta).
  465.     """
  466.     
  467.     return I.refract(N,eta)
  468.  
  469. def xcomp(P):
  470.     """Return the x component of p.
  471.  
  472.     This is equivalent to p.x.
  473.     """
  474.     return P.x
  475.  
  476. def ycomp(P):
  477.     """Return the y component of p.
  478.  
  479.     This is equivalent to p.y.
  480.     """
  481.     return P.y
  482.  
  483. def zcomp(P):
  484.     """Return the z component of p.
  485.  
  486.     This is equivalent to p.z.
  487.     """
  488.     return P.z
  489.  
  490. def setxcomp(P,x):
  491.     """Set the x component of p.
  492.  
  493.     This is equivalent to p.x = x."""
  494.     P.x = x
  495.  
  496. def setycomp(P,y):
  497.     """Set the y component of p.
  498.  
  499.     This is equivalent to p.y = y."""
  500.     P.y = y
  501.  
  502. def setzcomp(P,z):
  503.     """Set the z component of p.
  504.  
  505.     This is equivalent to p.z = z."""
  506.     P.z = z
  507.  
  508. def comp(c, index):
  509.     """Get an individual color component.
  510.  
  511.     This is equivalent to c[index]."""
  512.     return c[index]
  513.  
  514. def setcomp(c, index, value):
  515.     """Set an individual color component.
  516.  
  517.     This is equivalent to c[index] = value."""
  518.     c[index]=value
  519.  
  520. def concat(*args):
  521.     """Returns a concatenated string."""
  522.     return string.join(args,"")
  523.     
  524. def match(pattern, subject):
  525.     """String pattern matching."""
  526.     return re.search(pattern, subject)!=None
  527.  
  528. def format(pattern, *args, **keyargs):
  529.     """Returns a formatted string (similar to the C function sprintf())."""
  530.     res=""
  531.     while 1:
  532.         n=pattern.find("%")
  533.         if n==-1:
  534.             res+=pattern
  535.             break
  536.         res+=pattern[0:n]+"%s"
  537.         pattern=pattern[n+2:]
  538.  
  539.     if keyargs.has_key("args"):
  540.         args=keyargs["args"]
  541.  
  542.     return res % args
  543.  
  544. def printf(pattern, *args):
  545.     """Prints the values of the specified variables."""
  546.     print format(pattern,args=args)
  547.  
  548. ######################################################################
  549.  
  550. if __name__=="__main__":
  551.  
  552.     printf("Hallo s=%f c=%c",0.5,(1,2,3))
  553.     
  554.