Overview-The Alias Rendering Process

This describes terms used in this document.

Object space The coordinates of an object before any transformations, rotations and/or scalings have been applied to it.
World space The coordinates of an object after all transformations, rotations and/or scalings have been applied to it. This includes transformations to properly place the object in front of the camera.
Prototype An outline of a C Code Module (or a data structure) that has locations for a programmer to add customized C code (or data fields).
ALIAS OpenRender Template File
A file that contains a number of prototypes.
Application Program Interface
A collection of routines we supply for you to use in the ALIAS OpenRender C code modules you write. There are four basic steps involved in rendering each image from an SDL file:

Parse

The renderer reads the SDL file once per render. At that time, the NODE structure is created and initialized with a special kind of data structure, called an RR_ExpNode, that can represent any type of data, including expressions, animation statements, literals, variables, scalars, triples, and textures. All of the NODE structures are kept together in an internal representation of the SDL file, which can then be evaluated.

SDL NODE data structure

shader shiny ( typedef struct NODE_TYPE {

model = my_ocr_shader, PARSE .

pattern = texture(...), ----> RR_ExpNode *pattern

. .

. .

. .

); } NODE_TYPE;

Evaluate

During the Evaluation phase, the NODE structure is evaluated into the INFO structure; the current value of the variable is determined and placed into the INFO structure. For example, if intensity is set to an expression:

light bright (
model = my_ocr_light_model,
intensity = (4.0*5.5)/3.2,
.
.
.
}

then the evaluation step takes the RR_ExpNode and evaluates the intensity of the light to be 6.875. The following diagram shows the relationship between the NODE and INFO data structures.

Created at Parse Time: Created at Evaluation Time:

typedef struct AR_LightNode { typedef struct AR_LightInfo {

. .

. EVALUATION .

RR_ExpNode *color; ---------> AR_TextureType color;

. .

. .

} AR_LightNode; } AR_LightInfo;

Relationship between NODE and INFO data structures

The content of the RR_ExpNode structure is unimportant-ALIAS OpenRender provides you with a function to perform the evaluation for any type of RR_ExpNode, and if the ALIAS OpenRender Template File is used in the ALIAS OpenRender C code module, this evaluation is done automatically. In general, there should be one field in the NODE structure for each field in the INFO structure, and the two fields should have the same or similar names for the sake of clarity.

Initialize

The INFO structure can have additional fields (that are not in the NODE structure) to store information that does not change during a frame, and so only needs to be set once for that frame at initialization time. For example, with Alias lights, the Alias defined INFO structure has an extra field called transformed_color, which is the combination of the light's intensity and the light's color for the current frame.

pInfo->transformed_color.r = pInfo->color.out.r * pInfo->intensity;
pInfo->transformed_color.g = pInfo->color.out.g * pInfo->intensity;
pInfo->transformed_color.b = pInfo->color.out.b * pInfo->intensity;
Similarly, if you have any texturable fields in one of your data structures, this is the time to initialize them. For example, if your data structures look like:

#define NODE_TYPE myShaderNode #define INFO_TYPE myShaderInfo
typedef struct NODE_TYPE { typedef struct INFO_TYPE {
RR_ExpNode *pattern; AR_TextureType pattern;
.
.
.
.
} NODE_TYPE; } INFO_TYPE;

then your initialization routine should look like:

AR_Boolean INIT( INFO_TYPE *pInfo )
{
OCR_initialize_texture( pInfo->pattern.map );
.
.
.
return ( TRUE );
}

In many cases with your ALIAS OpenRender C code modules, the initialize function can be an empty function.

Forward Referencing Positional Information

If your ALIAS OpenRender C code module uses a positional point variable (like the Alias spot light does for the shine_along and up fields), then your INIT routine must do some extra work to bind some variables together. This is to allow the positional variables to be defined at any point in the SDL file.

To get around the problem of a possible forward reference, here is what Alias does with spot lights. (Alias calls the variable shine_along even though it really is a shine AT point. The direction of the spot light is calculated by subtracting the shine_along point from the position of the light.)

The first thing to do is place a forward() statement around your possibly forward-referenced field in the SDL file as shown below (to see exactly what the SDL looks like, generate a small SDL file with a spot light in it and look at the layout-then try grouping the spotview with another object, move and rotate that object and see what the SDL looks like):

light spotlight#1 ( model = spot,
.
.
.
shine_along = forward( spotview#1 ),
.
.
.
);
.
.
.
MODEL
.
.
.
{
translate( 4.5, 9.8, 2.3 );
rotate( yaxis, 34.0 );
spotview#1 = current_position( 0.0, 0.0, 0.0 );
}
.
.
.
The forward() statement is added automatically when you write out an SDL file from the Alias interactive package. If you have a positional field in your ALIAS OpenRender C code module, you must add the forward() statement yourself by editing the SDL file.

Then, in the COPY routine, you must bind some variables together. Do this using the OCR_bind_forward_reference() function so that the forward reference gets carried over to all copies and instances of this light:

static long
OCR_Shallow_Copy(
INFO_TYPE *pTo,
INFO_TYPE *pFrom
){
pTo->field1 = pFrom->field1;
pTo->field2 = pFrom->field2;
pTo->field3 = pFrom->field3;
.
.
.
pTo->shineAlong.x = pFrom->shineAlong.x;
pTo->shineAlong.y = pFrom->shineAlong.y;
pTo->shineAlong.z = pFrom->shineAlong.z;
OCR_bind_forward_reference ( (AR_Triple*)(&(pTo->shineAlong)),
(AR_Triple*)(&(pFrom->shineAlong)) );
.
.
.
return (TRUE);
}

Then in the INIT routine, make sure that the variables are transformed properly into eye space:

AR_Boolean
Ar_init_spot_light (
AR_SpotLightInfo *pInfo
)
{
.
.
.
OCR_transform_point( &(pInfo->shineAlong),
&(pInfo->transformed_shineAlong) );
.
.
.
return( TRUE );
}

Notice how to transform shineAlong into a different field in the INFO structure, called transformed_shineAlong. It is important that the shineAlong field is transformed into a different field so that multiple copies of the light are possible. Results are unpredictable if shineAlong is OCR_transform_point()'ed into shineAlong.

Be very careful. All forward reference fields must be triple variables. A triple literal (that is, a line like shine_along = (0.0, 1.0, 3.0) in the spotlight definition) does not work, even with a forward() statement around it.

Storing information for multiple frames

If you are initializing a field of your INFO structure on the first frame of an animation, and just incrementally modifying it for each subsequent frame, be careful to modify the OCR_Shallow_Copy() (you will find this routine in the ALIAS OpenRender template) in your ALIAS OpenRender C code module so that it does not copy the fields you want to keep from frame to frame. (Lights are passed a new INFO structure each frame-do not count on being able to store information in your light INFO structure for multiple frames. For this reason, sub allocations for lights are not recommended.)

For example on the first frame of an animation, you want to allocate an array of values to be used and updated each frame. You only want to allocate the array once on the first frame. You have defined a field in the INFO structure called particle_array to store the array. Your INIT routine might do something like the following:

AR_Boolean INIT( INFO_TYPE *pInfo )
{
if (pInfo->particle_array == NULL) {
/* Allocate an array of 50 floats. */
pInfo->particle_array = OCR_allocate( sizeof(float) * 50 );
/* initialize particle_array here, somehow */
}
/* update particle_array here, somehow */
return(TRUE);
}

Here is what can go wrong with this type of arrangement:

If the above ALIAS OpenRender module is used as a variable anywhere in an SDL file, the field particle_array will be NULL each time the INIT routine is called. This is because when a variable is assigned to a field of another object, a copy of the variable is made. In this case, a copy of the INFO structure is placed in the field assigned, and the copy is passed to your INIT routine. The same process is repeated on all subsequent frames. You will be modifying the copy each time, but the original INFO structure never gets updated, and the original structure is copied over top of the copy each frame, and your sub allocated memory is lost. This is because the ALIAS OpenRender template uses a shallow copy routine (a copy routine that has no knowledge of the underlying data structure).

If you want to keep the particle_array information in the INFO structure, change the OCR_Shallow_Copy() routine so that the particle_array field is not copied:

static long
OCR_Shallow_Copy(
INFO_TYPE *pTo,
INFO_TYPE *pFrom
){
pTo->field1 = pFrom->field1;
pTo->field2 = pFrom->field2;
pTo->field3 = pFrom->field3;
/* pTo->particle_array = pFrom->particle_array; /* NO, we don't copy this. */
return (TRUE);
}

Note: Lights are a special case, since they are treated like geometry-the INIT routine is passed a new INFO structure each frame. Do not attempt to store information in your light INFO structure between frames. The FREE routine for your light must free any substructures you have allocated, and the COPY routine for lights should copy the pointer to any sub allocation from the From object to the To object, and then NULL out the From object's pointer. This must be done so that the memory is not FREE'ed twice by two separate calls to your C module FREE routine. This should only concern you for lights. Shaders and textures will not be freed dur-ing any render.

Calculate

The calculate routine:

Free

In most cases, the free routine is a NULL function. Its purpose is not to free the INFO structure itself, but to free any sub-structures that you may have allocated in your INIT or CALC routines. For example, Alias spotlights allocate a depth map array in order to do shadows, so their free routines look like:

AR_Boolean FREE( INFO_TYPE *pInfo )
{
if (pInfo->depth_map != NULL)
{
OCR_free( pInfo->depth_map );
pInfo->depth_map = NULL;
}
return( TRUE );
}





[email protected]
Copyright ©1998, Alias|Wavefront, a Silicon Graphics Company. All rights reserved.