Bookshelf Contents Previous Next Glossary Index Search

Expressions

There are three types of expressions: Primary Expressions , Unary Operator Expressions and Binary Operator Expressions. These will be described in turn.

Functions are described in the next section.

Primary Expressions

Primary expressions may be further divided into five kinds:

1) Variables,

2) Array Elements,

3) Literals,

4) Function Calls, and

5) Parenthesized Expressions.

Array Elements

An array element may be used as an expression if 1) the subscript referencing it is in the range defined when the array was declared, and 2) the type of the element is scalar. Since the subscript itself may be a variable and the contents of an array ele-ment may be of any type, the test for the above conditions is made at reference time.

Function Calls

Only functions which return a scalar may be used as an expression. The syntax of a function call is:

<function name> ( <argument list> )

The contents of the argument list vary depending upon the function being in-voked. The reader is referred to the detailed descriptions of the individual func-tions for the specification of the arguments required by each. Note that the argu-ment list may be empty for some functions, but the delimiting parentheses are still required. As with "C", function arguments are passed by value, and the ar-guments themselves will not be affected in any way by the function call.

Literals

Only literals of type scalar may be used as an expression. The value given is used.

Parenthesized Expressions

A parenthesized expression consists of a left parenthesis, any expression, and then a right parenthesis - ( <expression> )

The purpose of the parenthesized expression is simply to delimit the enclosed ex-pression for grouping purposes. Normally the enclosed expression will be a binary operator expression, although any type of expression is valid. The classic example is a grouping to defeat the normal precedence of operators with a binary operator ex-pression - ( x + 1 ) / 2

Variables

Only variables of type scalar may be used as an expression. Since variables of that type always have a value defined, the use of a variable as an expression is just a ref-erence to that value.

Unary Operator Expressions

Two unary operators are provided, logical negation ( ! ), and arithmetic negation ( - ). In both cases the syntax is:

<operator><primary expression>

where <operator> is either "!" or "-". Any primary expression is valid, but only a primary expression. Logical negation results in a value for the expression of ei-ther 0 (FALSE) or 1 (TRUE). A value of 1 results when the <primary expression> has a value of zero. A value of 0 results when the <primary expression> has any other (non-zero) value. Arithmetic negation simply changes the sign of the value of the <primary expression>. Zero is unsigned and unaffected by this operator. Logical negation takes precedence over arithmetic negation.

Binary Operator Expressions

A binary operator expression consists of 2 expressions (of any kind) separated by a binary operator. There are 12 binary operators, which have 5 different levels of precedence, namely:

* / highest precedence

+ -

== != >= <= > <

&&

|| lowest precedence

All binary operators have a lower precedence than the unary operators. All bi-nary operators are left associative. The individual operators will be discussed in order of decreasing precedence.

Multiplication ( * ) and division ( / ) have the same precedence. All arithmetic is per-formed in single precision floating point form. Division by zero is invalid and results in a terminated execution. Addition ( + ) and subtraction ( - ) have the same prece-dence, which is lower than multiplication or division. The computa-tion is performed in single precision floating point form.

The operators "<", ">", "<=", ">=", "==" and "!=" are collectively known as trela-tion operators. They represent "less than", "greater than", "less than or equal to", "greater than or equal to", "equality", and "not equal", respectively. All the relation operators have the same precedence. The relation operators compare the values of 2 expressions. The result of such a comparison is either 1 in the case where the speci-fied relationship exists (the TRUE case) or 0 in the case where the relation does not exist (FALSE).

All comparisons are between single precision floating point numbers. The user is therefore advised to exercise care when using tests for equality. A second poten-tial problem could occur because of the left associativity combined with all rela-tion op-erators having the same precedence and the left to right evaluation order of expres-sions. The user is urged to use explicit grouping whenever more than one relation operator is needed.

Consider, for example,

a > b > 3

This will always evaluate to 0 (FALSE), because the associativity results in

( a > b ) > 3

and the result of a > b must be either 1 or 0, neither of which is greater than 3.

The logical AND operator ( && ) interprets the two expressions as truth values and performs the logical intersection. An expression is considered true if its value is non-zero, and false if its value is zero. The result of the intersection is either 1 (in the case where the expressions are both true) or 0 (for all other cases). Note that the left ex-pression is evaluated first, and if it is false then the result is deter-mined and the right expression is not inspected at all. This behavior is similar to the "C" language and is sometimes useful when the value of an expression might not be well defined (as with arrays for instance).

The logical OR operator ( || ) interprets the two expressions as truth values and performs the logical union. An expression is considered true if its value is non-zero, and false if its value is zero. The result of the union is either 1 (in the case where ei-ther of the expressions are true) or 0 (in the case where both expressions are false). Note that the left expression is evaluated first, and if it is true then the result is de-termined and the right expression is not inspected at all. This behavior is similar to the "C" language and is sometimes useful when the value of an ex-pression might not be well defined (as with arrays for instance).

Functions

There are a number of functions defined for SDL that may be used in an expres-sion or in place of an expression. Most functions (there are a few exceptions) return a single (scalar) value. Most functions are simply routines from the standard UNIX math library. These will not be documented, defined, or described here. The reader is referred to the standard UNIX documentation. They are:

besselj0 besselj1 besseljn

besselyn

cos acos cosh

erf erfc

exp

fabs

floor ceil

hypot

log10

pow

sin asin sinh

sqrt

tan atan atan2 tanh

Some basic extensions to the trigonometric functions are provided so that angles may be expressed in degrees rather than radians:

cosd acosd

sind asind

tand atand atan2d

These are identical to the standard routines in all respects except that the angles are expressed in degrees.

In addition to the math library routines, SDL has the following functions defined:

animate

cl() [formerly cluster()]

constrain( )

current_position

current_transformation

ease

extract

fmod

gamma

motion

rand srand gauss

sign

Each of these is described in detail below.

animate

The animate function is used to define animated behaviors. It takes 2 arguments, and returns a scalar:

animate( <parameter_curve>, <time> )

The <parameter_curve> argument defines the parameter curve to be used for an animation. It must be the name of a <parameter_curve> variable defined in the definition section. The <time> argument specifies where along the curve to interpret the value. It is a scalar, and will nor-mally be the system defined variable frame. The animate function returns a scalar. The value re-turned is the value of the <parameter_curve> at time <time>.

Example:

translate(animate( sphere.X_Position, frame ), 0.0, 0.0);

cl() [formerly cluster()]

Returns:

CV

Syntax:

cl( <cv>, <cluster_matrix_reference>, <percentage> [, <cluster_matrix_reference>, <percentage> ] )

The cl or cluster function takes <cv> and applies the specified clusters at the given percentages.

For a description of how clusters are applied to CVs, please check the animation section of the documentation.

Example:

cl(cv((-0.928135, -0.066296, 3.525111), 1.0),
     CL_cluster#2 ,0.0,
     CL_knot100_section270_Relbow ,0.003524,
     CL_knot0_section270_Relbow ,0.879251,
     CL_knot26_section0_Relbow ,0.007034,
     CL_knot0_section0_Relbow ,0.462762) )

constrain( )

Syntax:

constrain ( start, end, by, constrain_value )

Constrain function takes 4 scalar arguments. The return value is constrained to be start, end, or (start + N * by) where (N * by) is not greater than (end - start). The start value must be less than the end value. If (constrain_value <= start) then start is returned. If (constrian_value >= end) then end is returned. If (by = 0), then the function will always return the start value. This function is useful for animating visibility exactly, or turning a smooth curve into discrete steps.

Example:

The following function will return 19, because its possible return values are 13, 16, 19, 22, and 25.


x = constrain ( 13, 25, 3, 18 ); 

current_position

This function returns a triple value corresponding to the x, y, and z coordinates of a point in space defined in the model where the function is called. It takes a triple as an argument. Its value outside the MODEL section is undefined, and any references to it outside that section are invalid and will generate an error.

Example:

<triple_variable> = current_position( x, y, z );

or

<triple_variable> = current_position( motion(
<motion_path>, animate( <timing_curve>, frame )));

current_transformation

This function returns a transformation value corresponding to its placement in the modeling hierarcy. It does not take any arguments. It is used primarily to mark the location of a solid texture or a cluster. Its value outside the MODEL section is undefined, and any references to it outside that section are invalid and will generate an error.

Example:

<texture_orientation> = current_transformation();

ease

The ease function takes 5 arguments. It returns a scalar. It is used primarily for ani-mation.

Syntax:

ease ( <start_val>, <end_val>, <keyword>, <startframe>, <endframe> )

<start_val> is the value returned when the value of frame is less than or equal to <startframe>.

<end_val> is the value returned when the value of frame is greater than or equal to <endframe>.

<keyword> determines how the value to be returned is determined when the value of frame is between <startframe> and <endframe>. It can be any of: EXPOUT, OUT, INOUT, LINEAR, IN, or EXPIN. (Note the use of full capitals.) The following chart provides the functions f(x) which define the shape of the ease curves:

keyword:

f(x) range of x

IN:

cos (x) 0 <= x <= 90

OUT:

cos (x) -90 <= x <= 0

INOUT:

-cos (x) 180 <= x <= 360

EXPOUT:

((<frame> - <start frame>)/(<end frame> - <start frame>))0.3

EXPIN:

((<frame> - <start frame>)/(<end frame> - <start frame>))1.8547

LINEAR:

x unbounded

The keyword determines the rates of acceleration and deceleration of the charac-teris-tic under animation. The computer interpolates the value being animated and makes this change across the necessary number of frames, easing in or out according to the type of curve selected.

<startframe>

is an scalar that indicates the starting frame of the ease.

<endframe>

is an scalar that indicates the ending frame of the ease.

Example:

light(intensity=ease(1.0,0.0,LINEAR,startframe,endframe), color=(255,0,0));

extract

Allows individual channels of a triple to be extracted as scalars. Most useful for getting at the individual values of a motion path. Extract has two arguments, a scalar, which specifies the element to extract and a triple from which the element will be extracted. The first scalar argument must be one of (1, 2, 3) meaning return the first, second, or third scalar of the following triple.

This function returns a scalar.

Example

x = extract(1.0, motion(motion_path, animate(param_curve.Timing, 
frame)));

fmod

The fmod function takes 2 arguments. It returns a scalar, whose value is the floating point remainder of the division of the first argument by the second ar-gument. If the divisor is zero, then an error is reported and execution terminated. The result will have the same sign as the dividend. Note that this is a custom built Animator function because not all UNIX systems provide it.

Example:

even = fmod(frame,2);

gamma

Given floating point output color (R, G, B), the user-supplied gamma_value, and the function "pow(X,Y)" which raises X to the power of Y, gamma in the renderer is applied:

R=255.0*pow((R/255.0), gamma_value);

G=255.0*pow((G/255.0), gamma_value);

B=255.0*pow((B/255.0), gamma_value);

/*Clip the value to 255.*/

if (R>255.0) R=255.0;

if (G>255.0) G=255.0;

if (B>255.0) B=255.0;

gauss

The gauss function does not take any arguments. (The syntax still requires that parentheses be included, however.) It returns a scalar whose value is a pseudo ran-dom number with a gaussian (normal) distribution. The random number function may be initialized by using the srand function to set the seed. If srand is not called, the default seed value will be used. See the description of srand for de-tails. Note that even though the routines to compute random numbers are the same, the numbers returned may be different on different machines because of differences in the under-lying hardware.

Example:

distrib = gauss();

motion

The motion function is used to define animated behaviors. It takes 2 arguments:

motion( <curve>, <distance> )

The <curve> argument defines a 3D curve to be used for an animation. It will be the name of a curve variable. The <distance> argument specifies where along the curve to interpret the value. It is a scalar, and specifies the parametric dis-tance along the curve. The parametric distance is 0 at the end of the curve corre-sponding to the first CV and 1 at the end of the curve corresponding to the last CV. Normal usage of the motion function will relate the parametric distance to frame time by way of a nested animate. For example,

	motion( some_path, animate( timing_curve, frame ))

The motion function returns a triple. The value returned is the point along the <curve> at <distance> from the end. If <distance> is outside the range 0 to 1, then the value of <curve> at one end or the other (the start if <distance> is less than 0, the end if <distance> is greater than 1) will be given.

rand

The rand function does not take any arguments. (The syntax still requires that parentheses be included, however.) It returns a scalar whose value is a pseudo ran-dom number uniformly distributed between -1.0 and 1.0. The random number func-tion may be initialized by using the srand function to set the seed. If srand is not called, the default seed value will be used. See the description of srand for de-tails. Note that even though the routines to compute random numbers are the same, the numbers returned may be different on different machines because of differences in the underlying hardware.

Example:

flake = rand();

sign

The sign function takes one argument. It returns a scalar with the value -1 if the ar-gument is negative, 0 if the argument is 0, or +1 if the argument is positive.

Example:

if (sign(byframe)) print("infinite loop");

srand

The srand function takes one argument. It returns a scalar with the constant value 0. The argument provided will be used as the initial seed for random num-ber genera-tion. The argument should be a scalar. If the argument is omitted or of the wrong type, a warning message will be generated, the default seed value will be used, and execution will continue as if everything were correct. The default seed value is

12345.

Example:

bogus = srand(54321);

warp

The warp function is used to globally change the timing of animation parameters. It takes 2 arguments:

warp( <curve>, <time> )

The <curve> argument defines the parameter curve to be used for an animation. It will normally be a <parameter_curve> <parameter_vertex>s. The <time> argument specifies where along the curve to interpret the value. It is a scalar, and will nor-mally be the system defined variable frame. The warp function returns a scalar. The value re-turned is the value of the <curve> at time <time>. If <time> is is below the first specified value of the <curve>, the value returned is:

start_value - (start_value - <time>)

If <time> is greater than the last value, then the value returned is:

end_value + (<time> - end_value)

In other words, above (or below) the valid range for a warp function, the function increases (or decreases) linearly from the end (or start) values.

Example:

animate ("transZ.curve", warp("rotateX.curve", warp(transY.curve", 
frame)));

Please note that this function is obsolete.



Bookshelf Contents Previous Next Glossary Index Search

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