User Tools

Site Tools


This is an old revision of the document!


Expressions and Tables

Some material keywords take not only plain numbers as their parameters, but entire mathematical expressions that are evaluated whenever the material is employed for rendering. Expressions in turn may refer to look-up tables, which are a very simple but flexible means to approximate arbitrary mathemathical functions.

This section explains the details of expressions and tables.

Expressions

Some of the above keywords cannot only take numbers as their arguments, but entire mathematical expressions. An expression is a combination of numbers, mathematical operations, symbols, and table look-ups. Here is an example for such an expression:

    (1 + sinTable[ time*0.25 + 3 ]) / 2

Unfortunately, there is also bad news: The current parser of the Ca3DE MatSys is not yet powerful enough to parse expressions that use operator infix notation like the one above. Instead of +, -, *, … we therefore have to use explicit prefix notation, which is much easier to parse. The prefix notation is explained below. Here is the above example in prefix notation that we have to use until I can improve the parser to support infix notation:

    div(add(1, sinTable[ add(mul(time, 0.25), 3) ]), 2)

Expressions are defined recursively as follows:

  • $num A number.
  • $var A variable. Please see below for a list of all valid variables.
  • $table[ $expr ] A table look-up. The value of the table at position $expr is returned. The details of the look-up depend on the tables definition. The default tables sinTable and cosTable are always predefined. Custom tables can be defined as described in subsection Tables. Note that table look-ups are normalized. That is, all table elements are accessed by indices between 0.0 and 1.0, that is, the fractional part of $expr.
  • add($expr1, $expr2) Adds the results of $expr1 and $expr2.
  • sub($expr1, $expr2) Subtracts the results of $expr1 and $expr2.
  • mul($expr1, $expr2) Multiplies the results of $expr1 and $expr2.
  • div($expr1, $expr2) Divides the results of $expr1 and $expr2 if $expr2 is not 0. Otherwise, this evaluates to 0.

The following variables are defined:

  • time The current system time in seconds, starting from zero.
  • ambientLightRed
  • ambientLightGreen
  • ambientLightBlue The Ca3D-Engine provides the color of the ambient light that is contributed by radiosity light sources in these variables. Therefore, almost all material definitions that are employed with entities (e.g. player models, weapon and item models, etc.) normally use these variables so that the entity is colored according to the ambient radiosity light. Please see the .cmat files in Games/DeathMatch/Materials/Models/ for many examples.

Tables and table look-ups are described in subsection Tables.

Tables

A special expression is a table look-up of the form $myTable[$indexExpr], where $myTable is the name of a table that must have been defined before use, and $indexExpr is another expression that determines where in $myTable the look-up occurs.

Here is a simple but complete example with a table of four values:

    // This line defines the table "myTestTable":
    table myTestTable { { 0.2, 1.4, 0.6, 1 } }

    TestMaterialForTableLookup
    {
        diffusemap  someDiffuseMap.png
        // ...

        rgb div(myTestTable[mul(time, 0.5)], 1.2)   // equiv. to:   rgb myTestTable[time*0.5]/1.2
    }

As you can see, table definitions start with the keyword table, followed by the name of the table. Then come two {s, the table data values separated by commas (arbitrarily many), and then the closing two }s.

Note that table data values are always mapped into the range 0 to 1. Therefore, the graphical representation of myTestTable looks like this:

myTestTable[0] yields 0.2, myTestTable[0.25] yields 1.4, and so on…

You may wonder what you get for myTestTable[x] if x is smaller than 0 or greater than 0.75, or what happens if x is “between” two table values. Per default, table values are infinitely repeated outside of the range 0 to 1, and linearly interpolated between two adjacent values. Therefore, myTestTable from the above example in fact represents the following function, graphically shown in light blue color:

Observe how the values repeat with each integral number, and how intermediate values are linearly interpolated.

For special-purpose tables, you can insert the keywords snap and/or clamp between the two opening {s of the table definition. snap turns the linear interpolation off, and instead repeats the previous value until the next table value. Thus, if we changed the definition of our myTestTable above to

    table myTestTable { snap { 0.2, 1.4, 0.6, 1 } }

then our graphical representation of the table becomes:

snap turns the interpolation off, and just repeats one value until the next.

FIXME: FINISH!

Another type of object that you can define in material scripts are tables. Tables are a very powerful means to express arbitrary functions for use in expressions. Expressions are explained in detail above in subsection Expressions.

Table definitions start with the keyword table, followed by the name of the table. Then come two {s, the table data values separated by commas, and then the closing two }s. Here is an example of a table definition:

    table myFlickerTable { { 0.5, 1, 0, 0.2, 0.0, 0.8, 0.1, 0.7 } }

The elements of tables can be accessed from expressions as explained in subsection Expressions. It is important to note that the indices for table access are treated as normalized indices. That means that all values of a table are accessed with numbers that are greater or equal to 0.0 and less than 1.0. In the above table, which has eight elements, you'd get 0.5 for myFlickerTable[0.0], 1 for myFlickerTable[0.125], 0.2 for myFlickerTable[0.375] and so on.

As tables normally wrap, that is, start over when you read over their end, you will get 0.5 also for myFlickerTable[1.0] (but 0.7 for myFlickerTable[0.9999]). You may want to think of this as only the fractional part of the index being taken for the look-up, while the integer part is ignored. That means that for example the expression

    rgb myFlickerTable[time]

runs through the entire table exactly once per second, no matter how many elements the table actually has.

Between the two opening {, one or both of the keywords snap and clamp are allowed. snap defines that there is no linear interpolation between the table values. For example, we just said that myFlickerTable[0.0] yields 0.5 and myFlickerTable[0.125] yields 1.0. But what does myFlickerTable[0.0625] (the middle between 0.0 and 0.125) yield? If snap has not been specified, the value will automatically be interpolated between the table elements, and the result would be 0.75. If however snap has been defined, the result would be “snapped” to the next lower table element, and the result would be 0.5. Figure TODO demonstrates plots of two tables that differ in the use of the snap keyword but are identical otherwise. Interpolation is useful whenever you want to have a table to encode functions that have “smooth transitions”. Snapping is useful whenever you want to have a table to encode functions that have “hard transitions”. For example, in order to have LEDs flicker the SOS morse code, you'd use this table:

    table sosTable { snap { 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0,
                            1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0 } }

The clamp keywords defines what happens if a table is accessed at indices outside of the normalized range 0.0 to 1.0. Without clamp, the default behaviour is to wrap. With clamping enabled, the indices are clamped to yield the smallest or greatest table element. Figure FIXME TODO demonstrates plots of two tables that differ in the use of the clamp keyword but are identical otherwise.

Tables must be defined before their first use. As an exception, the two tables sinTable and cosTable are implicitly predefined and can always be used without prior declaration. The scope of a table begins at its definition and ends at the end of the material script. Note that although in the above examples only table element values between 0.0 and 1.0 occur, arbitrary numbers are allowed.

matsys/cmat_manual/expressionsandtables.1130699827.txt.gz · Last modified: 2013-01-07 12:07 (external edit)