The following are additional math functions which have been defined for use in the tcl command
\b expr
\b0 . Many of them are modeled after RenderMan shading language functions.\
\b pi
\b0 \
returns the exact value (to 32 bit IEEE precision) value of PI\
\b radians
\b0
\i angleInDegrees
\i0 \
returns angleInDegrees converted to units of radians.\
\b degrees
\b0
\i angleInRadians
\i0 \
returns angleInRadians converted to units of degrees.\
\b sign
\b0
\i arg
\i0 \
returns -1 if arg is negative, 0 if zero, and +1 is arg is positive\
\b min
\b0
\i arg1 arg2\
\i0 returns the minimum of arg1 and arg2\
\b max
\b0
\i arg1 arg2\
\i0 returns the maximum of arg1 and arg2\
\b clamp
\b0
\i val min max\
\i0 returns val clamped between min and max\
\b step
\b0
\i min val\
\i0 returns 0 if val is less than min, otherwise it returns 1\
\b spline
\b0
\i u pt1 pt2 pt3 pt4\
\i0 returns to point along the spline specified by the 4 control pts at u (0<=u<=1) on the curve. Note that for a more flexible spline routine, use the new tcl command spline.\
\b smoothstep
\b0\i min max value\
\i0 if value is less than min, it returns min, if it's above max, it returns max, otherwise it smoothly interpolates between them\
\b\i0 lerpDown
\b0\i u min max\
\i0 if u is less than or equal 0, it returns max, if it's above or equal 1, it returns min, otherwise it smoothly interpolates between them, downwards\
\b lerpUp
\b0
\i u min max\
\i0 if u is less than or equal 0, it returns min, if it's above or equal 1, it returns max, otherwise it smoothly interpolates between them, upwards\
\b noise
\b0
\i x y z\
\i0 it returns some value between 0 and 1 which is a pseudorandom function of its argument using Perlin's noise function - see Ch 2 of "Texturing and Modeling: A Procedural Approach" by David Ebert et.al. for more info.\
\b gvnoise
\b0
\i x y z\
\i0 it returns some value between 0 and 1 which is a pseudorandom function of its argument using a gradient value noise function - see Ch 2 of "Texturing and Modeling: A Procedural Approach" by David Ebert et.al. for more info.\
\b scnoise
\b0
\i x y z\
\i0 it returns some value between 0 and 1 which is a pseudorandom function of its argument using a sparse convolution noise function - see Ch 2 of "Texturing and Modeling: A Procedural Approach" by David Ebert et.al. for more info.\
\b vcnoise
\b0
\i x y z\
\i0 it returns some value between 0 and 1 which is a pseudorandom function of its argument using another noise function - see Ch 2 of "Texturing and Modeling: A Procedural Approach" by David Ebert et.al. for more info.\
\pard\tx620\tx1240\tx1860\tx2480\tx3100\tx3720\tx4340\tx4980\tx5600\tx6220\fs40\fc0\cf0 The core tcl 7.4 commands\
\b0 The bulk of this code was written during the summer of 1993 out in CA on my personal Color NeXTStation, filmNoir, while I was
\b not
\b0 employed by the MIT Media Lab. The original design of the WWTCLWidgets and WW3D palettes and implementation are therefore
\b copyright 1993 Michael B. Johnson
\b0 . Subsequent debugging and interface frobbage, as well as most of the current crop of examples was done as a research assistant at the MIT Media Lab, and therefore are
\b copyright 1994 MIT
\b0 .\
First and foremost, a big thanks go out to
\b John Ousterhout
\b0 and the whole tcl/Tk community, without which none of this code would exist. \
The WavesWorld "design identity" (The icons, the layout of the papers and thesis, many overall art directorial decisions) is an ongoing collaboration with the designer
\b Elizabeth Glenewinkel
\b0 . If you like the "look and feel" of WavesWorld, you can thank Elizabeth. If there are parts you don't, they're probably parts I did myself...\
Thanks to
\b Ed Catmull
\b0 , who gave me the opportunity to go hack 2D stuff for Pixar and do 3D stuff in my copious free time. Thanks to
\b Dana Batali
\b0 for keeping me well fed and highly conversationally engaged all summer. A big hug to my office mate
\b Annabella Serra
\b0 , animator, modeler, and designer extraordinare, who gave me great insight into the relationship between modeling and animation, as well as good bread.
\b Tony Apodaca
\b0 and
\b Dan McCoy
\b0 provided me with key insights into RenderMan-as-implemented-by-Pixar, as well as being great across-the-hall-mates.
\b Eben Ostby
\b0 gave me some of his valuable time in the Spring of 1994 to talk about articulated variables and ML
hopefully I've correctly incorporated some of the suggestions he made. Thanks to all the rest of the fine folks at Pixar who made my summer a great time, especially
\b Bill Carson
\b0 , who kept the machines running, the T1 link up, and the screening room hopping.\
Many folks at the Media Lab have contributed to these objects, whether by direct suggestions or just be allowing me to blather at them about what I was doing. My advisor,
\b David Zeltzer
\b0 , has always been amazingly supportive of all of my work, as I veered all over the map the last six years. The various denizens of the SnakePit have also been wonderful, especially
\b Steve Drucker
\b0 who was always willing to listen to my rants and offer useful suggestions. \
Thanks to
\b Thomas Burkholder
\b0 and
\b Jeff Martin
\b0 of NeXT (at the time), for their SwitchView & TTTimer and PAThumbWheel objects, respectively. Awesomely useful code...\
\b Ian Wilkinson
\b0 of Canon UK Research, who wrote the WW3DText object and the BugWave app, and is actually trying to
\i use
\i0 this stuff... \
\b Larry Gritz
\b0 has been great help in understanding RenderMan, especially pointing out what is Pixar-specific and what is part of the standard. Larry has also become my one stop shop for shader info and source. Also, Larry's awesome rendrib rendering has been great fun for rendering images with... \
\b Andrew Stone
\b0 and
\b Bruce Blumberg
\b0 , especially when I was just starting on the code that would end up here, gave me lots of great NeXTSTEP help.
\b0 The whole point of the WW3DWell is to drop stuff in it, manipulate it, and inspect it. To this end, probably the first piece of information any user needs to know is what kind of files you can drop into the WW3DWell. \
The following icons assume that you have installed the BuildaDudeII.app, which binds the following extensions to their appropriate icons. If you haven't done this already, please do so now...\
This file contains eve code, which is immediately evaluated by the eve interpreter built into the WW3DWell. If it has any startShape/endShape pairs in it, they will replace the current shape.\
This is a file wrapper which can contain a variety of different files, but the one requirement is that it have at least one .
\b eve
\b0 file in it named
\b model.eve
\b0 . It first frees the current rootShape and closes any windows containing UI elements associated with that rootShape.\
Before it evaluates the contents of the model.eve file, it sets the value of the global tcl variable
\b modelPath
\b0 to be the complete path of the .mdl file wrapper. This allows any code in the model.eve file to reference this to source other files in the file wrapper. The eve interpreter in the 3DWell "sources" the model.eve, and attempts to build a new root shape to put in the 3DWell. If the "source" is successful, the new root shape takes the place of the old one. If there was an error, an error panel pops up. \
A .mdlTemplate file wrapper is exactly the same as a
\b .wwModel
\b0 , with the exception that the 3DWell doesn't expect to build up a new model when it's done. The idea is that this holds the "template" for a new model. \
A .cam file contains commands which are interpreted by the 3DWell's camera interpreter. The camera interpreter uses a still-under-construction extension to tcl to allow camera stuff to be specified. Right now, the best way to learn more about the specific commands are to either look at the source code of WW3DCamera.m or type "info commands" to the camera's tcl interpreter on this control panel and then try out various commands.\
ASCII RenderMan Interface Bytestream protocol files (.rib) can be dropped into the 3DWell with a high chance of being understood. The 3DWell does this by first converting a .rib file into an equivalent .eve file and then sourcing that file. \
I fixed most of the copyFromZone: bugs. yow. Animation should basically (more than basically) work now....\
\b v2.1
\b0 \
I put some rudimentary support for SGI's OpenInventor 2.0 file format. Polygons and uniform patches aren't supported yet, but quadrics and NURBS are. Trimming may be buggy... I've also incorporated tcl7.4b2, which fixed the one bug I found in 7.3 (trying to do math on a number with a space at the end wouldn't work). \
Folks with WWW access might enjoy my thesis diary, accessible via \
http://wave.www.media.mit.edu/people/wave/\
There are more examples now, as always...\
I also added new support for several RenderMan commands, namely Sides, MakeTexture, TextureCoordinates. It also has better, smarter support Larry Gritz's renderer. I've also shot down the last (to my knowledge) crasher bug that was left in the WW3DKit - there are still parts that aren't implemented fully, but I don't think there are any crashers left.\
\pard\tx620\tx1240\tx1860\tx2480\tx3100\tx3720\tx4340\tx4980\tx5600\tx6220\f0\b\i0\ulnone\fs40\fc0\cf0 General Info & Background\
\b0\fs24 \
This is the control panel for the WavesWorld 3DWell object. It's a big, nasty object (which is really just a cover for a
\b really
\b0
\b big
\b0 ,
\i nasty
\i0 collection of objects). I hope you find it useful; it's become invaluable to my work.\
The basic idea of the WW3DWell came from my needs in building an animation system (my PhD, which is WavesWorld) and being unhappy with all the 3D systems I had access to at the Media Lab. I flirted with the notion of using a commercial app on the NeXT to give me what I needed but I was dissatisfied with all of them. To me, the neat thing about 3D on the NeXT is the fact that two things that are a nightmare on other platforms were dead simple on the NeXT: a uniform 3D imaging model that allowed both interactive and photorealistic rendering, attaching 2D UI controls to things. With RenderMan, the first part was easy, and with IB, the second part was also easy.\
Also, because of the economics of the NeXT market, I couldn't really blame the app developers - they had bigger fish to fry. So I decided to take matters into my own hands, and develop my own stuff.\
The first problem was one of file formats. RIB files are great, but they're more akin to EPS files than Adobe Illustrator files. In other words, they're usually treated as a black box which is stuck somewhere in the scene, and you usually don't edit them drastically. Potentially, though, you could treat them more as more malleable media. The difficulty arises from the fact that writing a RIB parser (that really, really, really parses the whole file) is a non-trivial undertaking. Under NeXTSTEP, this isn't really a problem, because for the first time, you can override the Ri* commands and stick your own function pointers in. Unfortunately for me, I like NeXTSTEP, but it ain't the only pond I swim in. I needed a more portable solution. I also needed a more extensible one (I'll get into that later).\
So I went out to Pixar summer of '93 and bit the bullet - I wrote my own RIB parser. I did it in kind of a sneaky way, though. I really wrote a complete RenderMan binding for tcl, the "tool command language" from Berkeley (see comp.lang.tcl for more info). Once I had the binding written, I just needed to write some code to convert a valid RIB file into a valid tcl file (with RenderMan bindings). This gave me a bunch of nice things. Tcl runs on all Mac, PC, UNIX boxes, so suddenly I had a really portable RIB parser. Also, as anybody who does animation for a living can tell you, you always need a scripting language. I could use tcl as the basis for my scripting language, which made me very happy.\
Well, once you've parsed the RIB file, what do you do with it? The problem is that RIB is an "immediate mode" file format, not really an object oriented one. In other words, between
\f1\b AttributeBegin/End
\f0\b0 blocks and
\f1\b TransformBegin/End
\f0\b0 blocks, you have your own little 4x4 transformation matrix which is being transformed. Well, you say, this maps right on to NeXT's 3DKit, right? We just map each transformation operation (
\f1\b Scale
\f0 ,
\f1 Translate, Rotate
\f0\b0 , etc.) to the N3DShape's transformation Matrix, keep track of the graphical operations, and no problemo.\
Not quite so easy. What about a RIB file that looks like this:\
\f1\b AttributeBegin\
Scale 1 2 1\
Sphere 1 -1 1 360\
Scale 1 .5 1\
Translate 0 2 0\
Sphere 1 -1 1 360\
AttributeEnd\
\f0\b0 \
well, if you parse the RIB file naively, you won't get the picture you expect. Think about it...\
The problem is that you will apply the transformation operations to the N3DShape's 4x4. Unfortunately, the first Sphere call should be getting a 4x4 with a scale of 2 in Y, and the second one should be getting one with a translation in Y of 2. What they get is the same transformation matrix, which only has a translation in Y. \
Wrongo.\
The other problem is that a lot of times, we don't want to obscure that transformation infomation. Especially when writing RIB files ourselves (as opposed to having some modeler do it), we might want to remember the fact that we did some set of operations in some particular order.\
So what's the solution? Well, if we designed a class hierarchy which had an object for every rib command, and we had a shape class which stored an ordered list of these objects, we'd be in business.\
Well, that's pretty much what I did. There are some subtleties, though, because sometimes you want the parser to actually apply the transformation command directly to the current Shape's 4x4, but some times you don't. I toyed with various versions, and there are still switches in the parser to get it to behave in different ways, but the default behavior is just to store each rib command as a separate object inside the current shape.\
Some of the hardest issues arise when trying to calculate the bounding box of such a shape. Each rib command has to be able to calculate it's bounding box. For most objects this is pretty easy, but for some (a patch with some arbitrary basis matrices), it's pretty much intractable. For the known bases, though, we have ways to convert from them to a bezier bases, for which we know that it's control points have the convex hull property. I haven't totally implemented this yet, but the hard part (the traversal code up the shape hierarchy to find the current basis) is already implemented.\
Well, once you've got the rib parser and a corresponding shape hierarchy, you realize that you don't have to stop there. Since it's embedded in a language (tcl), you can have variables, right? Well, wouldn't it be cool if you called some rib command with variables, say:\
\f1\b Sphere $radius -$radius $radius $thetaMax\
\f0\b0 \
and instead of having this immediately be reduced to \
\f1\b Sphere 1 -1 1 360
\f0\b0 \
wouldn't it be cool if somehow, that command remembered what variables it was based on, and everytime any of those variables changed, the object got sent a message upon which it then reevaluated itself and redisplayed itself?\
Wouldn't it be even cooler if there were some IB-friendly sort of way to hook up UI objects to those variables, so we could have a (say) slider to control the thetaMax variable? If we did it right, we could even be controlling the thetaMax parameter of a whole bunch of primitives, each of which would be immediately updated...\
Well, that's exactly what I implemented. I made a new object, called an
\i EveCommand
\i0 , which takes one argument: a valid RIB command. The EveCommand sets up traces in the tcl interpreter object (WWTCLInterp) to trace the variables that the rib command depends on. It then evaluates the rib command and uses the resulting object. Whenever one of the variables it depends on gets a value written to it, the run-time system (in my system, that basically means tcl) sends a -resample msg to the EveCommand. The EveCommand then reevaluates itself in the current global tcl context, generating a new compiled object, which it then timestamps by asking the sceneClock for the current time. The EveCommand then adds this WWSample (i.e. a time-stamped renderable object) to its list of samples. There are a bunch of things that could go on here: the new sample could replace an old sample that had the same timestamp, the new sample could get merged with the old sample (which might have a notion of how many samples had been merged thus far, and add in the new one as a weighted sum), or it could constrain the values of the new one to some gradient, i.e. clamp it to some max representation. Because these are objects, all of these are possibilities. For now, a new sample at the same timestamp merely replaces the old one.\
I considered wrapping each RIBCommand in an EveCommand, but decided against it, since I would have had to hack Tcl_Eval() to hold onto each command it was evaluating, and this seemed like too major of a change to the tcl library for my tastes. Instead, I require an explicit use of the EveCmd to be used. \
In other words, if you have the following in a .eve file:\
\f1\b Sphere $r -$r $r $t\
\f0\b0 \
where
\f1\b (r == 1,
\f0\b0 and
\f1\b t == 360
\f0\b0 ), this would cause a RIBSphere object to be instanced with a radius of 1, a zMin of -1, a zMax of 1, and a thetaMax of 360. This RIBSphere instance would be inserted in the currentShape's ribCommand list at the end. If, on the other hand, the line in the .eve file read like this:\
\f1\b EveCmd \{Sphere $r -$r $r $t\}
\f0\b0 \
\f1 \
\f0 an EveCommand instance would be created, which would then create the above mentioned instance of RIBSphere. Additionally, the EveCommand instance would send messages to the WWTCLInterp instance to set up variable traces on the variables named "r" and "t".\
This means that if, for whatever reason, "r" or "t" changed, a msg would get sent to that EveCommand instance to resample itself. \
But alot of times, you'd like to encapsulate more functionality than can be expressed in a single RenderMan command. For these cases, I have the EveProc object. The EveProc allows you to prototype a new Objective-C object that conforms to the WWRenderable protocol by first writing it in eve. By writing a proc which has an arbitrary amount of code inside of it, you can toy with simple or complex ideas for shapes until you're happy with it, and then recode it in Obj-C.\
There are more complicated issues, but if you start to get to them, we should probably take it to e-mail...\
You also should look at the doc directory that comes with the WavesWorld software - there's more good info there. Finally, there are lots and lots of examples using this stuff that also comes with the distribution - look there too.
[2996c]{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
\margl40
\margr40
\pard\tx620\tx1240\tx1860\tx2480\tx3100\tx3720\tx4340\tx4980\tx5600\tx6220\f0\b\i0\ulnone\fs40\fc0\cf0 The RenderMan routines in eve\
\b0\fs24 \
NOTE: eve is intended to be used as a modeling language, and a kind of meta-scene description language. Many of the models that it gets started life as a RIB file, though, so eve tries to parse the entire RenderMan interface, although many of the command map to no operation (noop). In the following list,
\i italics
\i0 is used to denote a command which eve will parse, but not do anything terribly useful with. Some of these I should support more fully but haven't had a pressing need yet, and other work prevailed... Send mail (or do it yourself and send me the code) if you need something supported better.\