C Helper Applications
|
|
|
#include <stdio.h> void add(float *ptr) { *ptr=2+3; } void main () }
#include <stdio.h> Two sample C scripts we wrote to learn the syntax of the language. Most importantly, the concept of pointers (passing the memeroy address of a variable rather than its numeric value) was introduced |
|
#include <stdio.h>
void main () while (gets(buffer)) { } |
// These reproduce the data types found in MEL float srandBetween(unsigned seed, float min, float max);
#include "library.h" float srandBetween(unsigned seed, float min, float max) float randBetween(float min, float max) //_____________________________________________________ //_____________________________________________________
Before getting "Hot and Heavy" into the visual aspect of scripting we wrote a small library of predefined functions to include when writing our later code. C has no knowledge of MEL's so called vector variable (a floating point array of 3 values) so we defined this variable using typedef . We also wrote several small functions for adding subtracting and multiplying vectors to save time as well. Another flaw in C is that the rand function returns an integer between 0 and RAND_MAX, a *very* large number. To combat this we created our own version, randBetween, which allows us to specify a range for the random numbers and can return floats. FInally, I wrote the srandbetween to be able to seed the randbetween generator to receive predicatable results. This was essential in order to animate the plams and have them render consistenly every frame (more on this below)... |
|
||
| The first test of a simple helper app was to use a bounding box in maya as a template for generating many spheres within it. Because the C app send the information to the renderer in memory (the instructions are never stored as or part of a .rib file) the render time, even for tens of thousands of spheres, is very fast. |
/* The Ribbox code would be the following line: Procedural \"RunProgram\" \[\"H:/vsfx705/C/spheres/spheres\" \"100 .05 2 2 2\"\] \[-1 1 -1 1 -1 1\] void main () while (gets(buffer)) { } |
|
/*
Procedural \"RunProgram\" \[\"H:/vsfx705/C/spheres/spheres\" \"100 .05 2 2 2\"\] \[-1 1 -1 1 -1 1\] void normalize(float pnt[3], float radius) void main () while (gets(buffer)) { } |
||
| By normalizing the vector formed by the origin and each of these randomly generated points, the spheres can be constrained to form a spherical mass. |
Rather than generating spheres for all of the random points, generating points allows the oppertunity to futher manipulate attrubites such as color...plus they render even faster becuase they are simply point values the MTOR adds a "width" to. |
/* void normalize(float pnt[3], float radius) void main () while (gets(buffer)) { for(n = 0; n < num; n++) printf("] \n"); //tell prman we're done } |
||
|
/*Procedural \"RunProgram\" \[\"H:/vsfx705/C/spheres/spheres\" \"100 .05 2 2 2\"\] \[-1 1 -1 1 -1 1\] */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include "H:/vsfx705/C/lib/library.h" void normalize(float pnt[3], float radius) void main () while (gets(buffer)) { printf("] \n"); //tell prman we're done } |
||
| Everything up to now has been based off of point rendering work done by our professor, Malcolm Kesson. I found the random point colors unappealing, so I thought it might be interesting to try to base the point's color off of it's world space position. The code to do this is shown at right...rather than assign a totally random color, an array of three floating point number elements (essentially a matrix of a user specified number of rows with 3 columns, the RGB values). These values were stored in the first loop when position was determined, then later repeated in the color statement. I made the mistake of thinking the values had to be made to conform to a 0 to 1 range, resulting in the first image above. By allowing them to retain the full numeric randomness inherent in their coordinates a natural spectrum is created (bottom). |
|
||
| Points, of course, are flat so I tried the render with the original box configurationto see some depth. |
| /* Procedural \"RunProgram\" \[\"H:/vsfx705/C/spheres/spheres\" \"100 .05 2 2 2\"\] \[-1 1 -1 1 -1 1\] */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include "H:/vsfx705/C/lib/library.h" void normalize(float pnt[3], float radius) void main () while (gets(buffer)) { //get a random color value based off the random position printf("] \n"); //tell prman we're done } |
||
The Full implementation of the point generator. Depending on which part are commented out, the code at right can produce a cube, sphere, cone, flat disk or cylinder shape full of points. These can be randomly colored, or colored by using world space coordinates (roll over each image to compare). |
|
#include <stdio.h> char* transformation(void); void main() |
||
| Just for FUN I also did A brief excercise in creating MTOR blobbie surfaces using C. All of these tutorials are under Malcolm Kesson's CG References and Tutorials. URL: http://sfdm.ca.scad.edu/vsfx/faculty/malcolm/tutorials/index.html |
|
int $n; for($n = 0; $n < 30; $n++) { string $Cube[] = `polyCube`; string $nextCube = $Cube[0]; //translate, move pivot to base, scale move 0 .5 0; xform -os -piv 0 -0.5 0; scale 2 2 2; //freeze transforms makeIdentity -apply true -t 1 -r 1 -s 1; //add attributes the tclbox can use addAttr -ln leafCount -at long -min 1 -max 150 -dv (rand(10, 50)) -k true $nextCube; addAttr -ln leafCv -at long -min 4 -max 13 -dv 37 -k true $nextCube; addAttr -ln leafBase -at double -min .01 -max 1 -dv .1 -k true $nextCube; addAttr -ln leafTip -at double -min .005 -max .5 -dv .005 -k true $nextCube; addAttr -ln leafColor -at double3 -k true $nextCube; addAttr -ln red -at double -min 0 -max 1 -dv (rand(0.05, 0.3)) -parent leafColor -k true $nextCube; addAttr -ln green -at double -min 0 -max 1 -dv (rand(0.3, 0.6)) -parent leafColor -k true $nextCube; addAttr -ln blue -at double -min 0 -max 1 -dv (rand(0, 0.1)) -parent leafColor -k true $nextCube; addAttr -ln leafX -at double -min .01 -max 10 -dv (rand(.5,2.5)) -k true $nextCube; addAttr -ln leafY -at double -min .01 -max 10 -dv (rand(.5,2.5)) -k true $nextCube; addAttr -ln leafDroop -at double -min -5 -max 5 -dv (rand(1, 10)) -k true $nextCube; move (rand(-10, 10)) 0 (rand(-10, 10)); } |
|
Enough of that, our next task was to begin to transfer the Code from our original MEL script generator (Click here to see that Page). This would have been a nightmarishly long process except for two things: we created variables in C to mimic those in MEL such as a typedef for vector, and we had a highly intellignet and ridiculously motivated professor who helped and/or personally did much of the transition to C for us.
We decided to base the palm generator off of a poly cube proxy object that could serve as a bounding box in conjunction with a ribbox combined with a tcl box to call the external App we were writing. A mel script was created to generate cubes with attributes created for them. This would allow the user to control a variety of the parameters of the appearance of a rendered palm. |
|
#include <stdio.h>
#include "plant.h"
int main()
{
char buffer[512];
int n;
vector end;
PlantDB db;
while(gets(buffer))
{
// 12 inputs, therefore, RIB must provide 11 values
sscanf(buffer, "%f %d %d %d %f %f %f %f %f %f %f %f",
&db.pixels, &db.seed, &db.leafCount, &db.leafCv,
&db.leafBase, &db.leafTip,
&db.leafRGB.x, &db.leafRGB.y, &db.leafRGB.z,
&db.leafX, &db.leafY,
&db.leafDroop);
// Generate a single leaf
end.x = srandBetween(db.seed,0, db.leafX);
end.y = db.leafY;
end.z = 0.0;
for(n = 0; n < db.leafCount; n++)
{
printf("TransformBegin\n");
printf("Rotate %f 0 1 0\n", randBetween(0,360));
leaf(db, end);
printf("TransformEnd\n");
}
printf("%c", '\377');
fflush(stdout);
}
return 0;
}
|
||
| A render without randomness of color and normals..... The code at right represents the main help app function (the actual executable, which can be understood as a bridge or doorway between our MTOR coding, and the external C file). It takes the data originally collected from the cube by the TCLBOx that is then picked up by the Ribbox and sent to the TCL file. This TCL code sets up several supporting functions to collect the data in Maya. It has among these a function called getRibString which then calls the C file while passing the user data in. IT IS VERY IMPORTANT to note the srandBetween() function call when initializing end.x This is a function I wrote that can seed the rand() function which allows the plants to be animated. If random end points for the leaves weer calculated each time the leaves will be different every frame. This allows the same set of random end points to be generated per plant every frame. |
|
// Declarations of functions implemented in typedef struct { void leaf(PlantDB plant, vector end);
#include "plant.h" void leaf(PlantDB plant, vector end) // Generate some xyz's using our subdivide routine /* "open" the Curves statement */ /* add the list of cv's */ printf("\"N\" ["); //_____________________________________________________ for(n = 0; n < num; n++) temp = scalar(add(end, B), u); |
||
| A fully randomized plant, ready for animation (if possilble). The core function of the palm generator takes data about color thickness size, etc and uses it to calculate, draw, apply thickness, and render the curves. Specifically, the function takes in the detail of each plant based on screen size, a random seed number based on the name of each poly cube, the numbner of cvs for each curve, the number of leaves, the width of base and tip, the primary colors for the leaves (randomness adde within the script) the x and y scale of the plant, and finally the amount of droop, or gravity, it experiences. The program then constructs a rib statement MTOR can understand and execute, one piece at a time. Mike figured our how to set, then randomize the normals, resulting in an interesting twisting effect on the leaves. This also locks the leaves into postion, allowing the camera to rotate around them, as shown by the animation below (COURTESY OF MIKE CABRERA) : |
|
||
We put MTOR to the test by using the MEL script to create a thousand random boxes with an 10X10 gird space. This is the scene as it appears in Maya.... |
||
|
||
| And this is the rendered image. Here the randomness can really be appreciated. The next goal was to animated them slightly by using the Skew command in the RIBBOX, this proved difficult because the leaves used to be generated completely randomly every frame. The seed fixed this and the results is the animation shown below: |
|
||
The final product of this labor is a short animation where the skew finally works to give some gentle sway to the plants. Nothing amazing, but a confident start towards further animation.
I definately want to explore further poential in randomizing and animating the palm plants. I also would like to further integrate it with the original MEL script I wrote to create additional functionality. The goal would be to have a UI that could feed into the helper app, making the code as user friendly as possible. |