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 *****
- # -------------------------------------------------------------
- # The RenderMan (R) Interface Procedures and Protocol are:
- # Copyright 1988, 1989, 2000, Pixar
- # All Rights Reserved
- #
- # RenderMan (R) is a registered trademark of Pixar
- # -------------------------------------------------------------
- # $Id: sl.py,v 1.2 2006/02/14 19:29:39 mbaas Exp $
-
- """RenderMan Shading Language functionality.
-
- This module provides some of the functionality from the RenderMan
- Shading Language. Those functions that require an actual rendering
- context (surfaces, light sources, etc.) are not supported.
-
- Most of the functions can be used just like in the Shading
- Language. An exception are those functions whose return type is
- dependant on the context as it is the case with random() or
- noise(). Here, those functions have to be prepended with the return
- type, for example float_random() or point_noise() (that is, the cast
- is part of the name).
- """
-
- import math, random, string, re
- from math import acos, asin, ceil, cos, exp, floor, pow, sin, sqrt, tan
- import noise
- from cgtypes import vec3 as _vec3
-
- # Builtin functions
- abs = abs
- max = max
- min = min
- round = round
-
- PI = math.pi
-
- def _tovec3(arg):
- try:
- a = len(arg)
- except:
- a = 1
- if a==1:
- return _vec3(arg,0.0,0.0)
- elif a==2:
- x,y=arg
- return _vec3(x,y,0.0)
- elif a==3:
- x,y,z=arg
- return _vec3(x,y,z)
- elif a==4:
- x,y,z,t=arg
- return _vec3(x,y,z)
- else:
- return _vec3()
-
-
- def atan(*args):
- """Returns the arc tangent.
-
- With one argument it math.atan() is called, with two arguments
- math.atan2() is called.
- """
-
- if len(args)==1:
- return math.atan(args[0])
- elif len(args)==2:
- return math.atan2(args[0],args[1])
- else:
- raise TypeError,"atan only takes 1 or 2 arguments."
-
- def log(*args):
- """Returns the natural logarithm of x or the logarithm to the specified base."""
-
- if len(args)==1:
- return math.log(args[0])
- elif len(args)==2:
- return math.log(args[0])/math.log(args[1])
- else:
- raise TypeError,"log only takes 1 or 2 arguments."
-
-
- # clamp
- def clamp(a, amin, amax):
- """Returns amin if a < amin, amax if a > amax, otherwise a."""
- return min(max(a,amin), amax)
-
- # degrees
- def degrees(rad):
- """Convert from radians to degrees."""
- return rad*180.0/PI
-
- # radians
- def radians(deg):
- """Convert from degrees to radians."""
- return deg*PI/180.0
-
- def Du(p):
- pass
-
- def Dv(p):
- pass
-
- def Deriv(num, den):
- pass
-
- def filterstep(edge, s1):
- pass
-
- def inversesqrt(x):
- """Returns 1/sqrt(x)."""
- return 1.0/sqrt(x)
-
- def mix(val0, val1, t):
- """Mix two values.
-
- For t=0 the value val0 is returned, for t=1 the value val1 is
- returned. For values of t between 0 and 1 a linearly interpolated
- value is returned.
- """
-
- return (1.0-t)*val0 + t*val1
-
- def mod(a,b):
- """Returns a%b. This is just an equivalent for the %-operator."""
- return a%b
-
- def float_noise(*args):
- """Returns a float value which is a (pseudo) random function of its arguments.
-
- This function is imported from the noise module.
- """
-
- la = len(args)
- if la==1:
- return noise.noise(args[0])
- elif la==2:
- return noise.noise(args[0],args[1])
- elif la==3:
- return noise.noise(args[0],args[1],args[2])
- elif la==4:
- return noise.noise(args[0],args[1],args[2],args[3])
- else:
- raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
-
-
- def point_noise(*args):
- """Returns a point whose value is a (pseudo) random function of its arguments."""
-
- la = len(args)
- if la==1:
- try:
- a = len(args[0])
- except:
- a = 1
- if a==1:
- return noise.vnoise(args[0],0,0)
- elif a==2:
- return noise.vnoise(args[0],0)
- elif a==3:
- return noise.vnoise(args[0])
- else:
- raise ValueError,"arg1: invalid argument length"
- elif la==2:
- try:
- a = len(args[0])
- except:
- a = 1
- if a==1:
- return noise.vnoise(args[0],args[1],0)
- elif a==3:
- return noise.vnoise(args[0],args[1])
- else:
- raise ValueError,"arg1: invalid argument length"
- elif la==3:
- return noise.vnoise(args[0],args[1],args[2])
- elif la==4:
- x,y,z,t = noise.vnoise(args[0],args[1],args[2],args[3])
- return _vec3(x,y,z)
- else:
- raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
-
- color_noise = point_noise
- vector_noise = point_noise
-
- def float_pnoise(*args):
- """Returns a float value which is a periodic (pseudo) random function of its arguments.
-
- This function is imported from the noise module."""
-
- la = len(args)
- try:
- a = len(args[0])
- except:
- a = 1
-
- if la==2:
- if a==1:
- return noise.pnoise((args[0],),(args[1],))
- else:
- return noise.pnoise(args[0],args[1])
- elif la==4:
- if a==1:
- return noise.pnoise((args[0],args[1]),(args[2],args[3]))
- else:
- return noise.pnoise(args[0],args[1],args[2],args[3])
- else:
- raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
-
- def point_pnoise(*args):
- """Returns a point whose value is a periodic (pseudo) random function of its arguments."""
-
- la = len(args)
- try:
- a = len(args[0])
- except:
- a = 1
-
- if la==2:
- if a==1:
- res = noise.vpnoise((args[0],),(args[1],))
- else:
- res = noise.vpnoise(args[0],args[1])
- elif la==4:
- if a==1:
- res = noise.vpnoise((args[0],args[1]),(args[2],args[3]))
- else:
- res = noise.vpnoise(args[0],args[1],args[2],args[3])
- else:
- raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
-
- return _tovec3(res)
-
- color_pnoise = point_pnoise
- vector_pnoise = point_pnoise
-
- def float_cellnoise(*args):
- """Returns a float value which is a (pseudo) random function of its arguments.
-
- The return value is constant between integer lattice points. This
- function is imported from the noise module.
- """
-
- la = len(args)
- if la==1:
- return noise.cellnoise(args[0])
- elif la==2:
- return noise.cellnoise(args[0],args[1])
- elif la==3:
- return noise.cellnoise(args[0],args[1],args[2])
- elif la==4:
- return noise.cellnoise(args[0],args[1],args[2],args[3])
- else:
- raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
-
- def point_cellnoise(*args):
- """Returns a point whose value is a (pseudo) random function of its arguments.
-
- The return value is constant between integer lattice points.
- """
-
- la = len(args)
- if la==1:
- try:
- a = len(args[0])
- except:
- a = 1
- if a==1:
- return noise.vcellnoise(args[0],0,0)
- elif a==2:
- return noise.vcellnoise(args[0],0)
- elif a==3:
- return noise.vcellnoise(args[0])
- else:
- raise ValueError,"arg1: invalid argument length"
- elif la==2:
- try:
- a = len(args[0])
- except:
- a = 1
- if a==1:
- return noise.vcellnoise(args[0],args[1],0)
- elif a==3:
- return noise.vcellnoise(args[0],args[1])
- else:
- raise ValueError,"arg1: invalid argument length"
- elif la==3:
- return noise.vcellnoise(args[0],args[1],args[2])
- elif la==4:
- x,y,z,t = noise.vcellnoise(args[0],args[1],args[2],args[3])
- return _vec3(x,y,z)
- else:
- raise TypeError, "the function takes between 1 and 4 arguments ("+`la`+" given)"
-
- color_cellnoise = point_cellnoise
- vector_cellnoise = point_cellnoise
-
- def float_random():
- """Return a random number between 0 and 1.
-
- This call is equivalent to random.random()."""
-
- return random.random()
-
- def color_random():
- """Return a color whose componenets are a random number between 0 and 1.
-
- The function actually returns a vec3."""
-
- return _vec3(random.random(), random.random(), random.random())
-
- def point_random():
- """Return a point (a vec3) whose componenets are a random number between 0 and 1."""
- return _vec3(random.random(), random.random(), random.random())
-
- def sign(x):
- """Returns -1 with a negative argument, +1 with a positive argument, and 0 if its argument is zero."""
-
- if x<0:
- return -1
- elif x>0:
- return 1
- else:
- return 0
-
- def smoothstep(min, max, x):
- """Returns the value of a smooth step function.
-
- Returns 0 if x < min, 1 if x > max, and performs a smooth Hermite
- interpolation between 0 and 1 in the interval min to max.
- """
-
- if x<min:
- return 0.0
- if x>max:
- return 1.0
- x = (x-min)/(max-min)
- return x*x*(3.0-2.0*x)
-
- def spline(x, knots):
- """Return the value of a spline function.
-
- Fits a spline to the control points given and returns the value at
- t which ranges from 0 to 1. At least four control points must
- always be given.
- """
-
- nknots = len(knots)
- nspans = nknots-3
-
- if nspans<1:
- raise ValueError, "spline(): there must be at least 4 control points ("+`nknots`+" given)"
-
- x = clamp(x, 0.0, 1.0)*nspans
- span = int(x)
- if span>=nknots-3:
- span = nknots-4
- x -= span
- knot0, knot1, knot2, knot3 = knots[span:span+4]
-
- c3 = -0.5*knot0 + 1.5*knot1 - 1.5*knot2 + 0.5*knot3
- c2 = knot0 - 2.5*knot1 + 2.0*knot2 - 0.5*knot3
- c1 = -0.5*knot0 + 0.5*knot2
- c0 = knot1
-
- return ((c3*x + c2)*x + c1)*x + c0
-
-
- def step(min, x):
- """Returns 0 if x < min, otherwise 1."""
- if x<min:
- return 0.0
- else:
- return 1.0
-
-
- def distance(P1,P2):
- """Returns the distance between two points.
-
- The arguments should be of type vec3."""
- return (P2-P1).length()
-
- def ptlined(P0,P1,Q):
- """Returns the distance between a point and a line segment.
-
- The arguments should be of type vec3.
- """
- a = P1-P0
- b = Q-P0
-
- x = a*b
- if x<=0:
- return b.length()
-
- aa = a*a
- if x>=aa:
- return (Q-P1).length()
-
- return sqrt(b*b-(x*x/aa))
-
- def faceforward(N,I,Nref):
- """Flips N so that it faces in the direction opposite to I."""
- return sign(-I*Nref)*N
-
- def length(v):
- """Returns the length of a vector.
-
- This is equivalent to calling v.length().
- """
- return v.length()
-
- def normalize(v):
- """Returns a unit vector in the direction of v.
-
- This is equivalent to calling v.normalize().
- """
- return v.normalize()
-
- def reflect(I, N):
- """Returns the reflection vector given an incident direction I and a normal N.
-
- This is equivalent to calling I.reflect(N).
- """
- return I.reflect(N)
-
- def refract(I, N, eta):
- """Returns the transmitted vector.
-
- Returns the transmitted vector given an incident direction I, the
- normal vector N and the relative index of refraction eta. This is
- equivalent to calling I.refract(N, eta).
- """
-
- return I.refract(N,eta)
-
- def xcomp(P):
- """Return the x component of p.
-
- This is equivalent to p.x.
- """
- return P.x
-
- def ycomp(P):
- """Return the y component of p.
-
- This is equivalent to p.y.
- """
- return P.y
-
- def zcomp(P):
- """Return the z component of p.
-
- This is equivalent to p.z.
- """
- return P.z
-
- def setxcomp(P,x):
- """Set the x component of p.
-
- This is equivalent to p.x = x."""
- P.x = x
-
- def setycomp(P,y):
- """Set the y component of p.
-
- This is equivalent to p.y = y."""
- P.y = y
-
- def setzcomp(P,z):
- """Set the z component of p.
-
- This is equivalent to p.z = z."""
- P.z = z
-
- def comp(c, index):
- """Get an individual color component.
-
- This is equivalent to c[index]."""
- return c[index]
-
- def setcomp(c, index, value):
- """Set an individual color component.
-
- This is equivalent to c[index] = value."""
- c[index]=value
-
- def concat(*args):
- """Returns a concatenated string."""
- return string.join(args,"")
-
- def match(pattern, subject):
- """String pattern matching."""
- return re.search(pattern, subject)!=None
-
- def format(pattern, *args, **keyargs):
- """Returns a formatted string (similar to the C function sprintf())."""
- res=""
- while 1:
- n=pattern.find("%")
- if n==-1:
- res+=pattern
- break
- res+=pattern[0:n]+"%s"
- pattern=pattern[n+2:]
-
- if keyargs.has_key("args"):
- args=keyargs["args"]
-
- return res % args
-
- def printf(pattern, *args):
- """Prints the values of the specified variables."""
- print format(pattern,args=args)
-
- ######################################################################
-
- if __name__=="__main__":
-
- printf("Hallo s=%f c=%c",0.5,(1,2,3))
-
-