Wizard Eye 3D: Architecture

Wizard Eye 3D: Architecture


Preface

This documentation describes the internals of the Wizard Eye 3D engine, its architecture, operator concepts, scripting, distributed rendering.

Document map

Overview

Wizard Eye offers a rich functionality for the developer. Many items are regulated via scripts and therefore may be adopted for the specific task.
Wizard Eye has its own programming language called the Wizard Programming Language, shortly WizPL. By its structure, this language is very close to the Renderman Shading Language, which is close to C Language.
However, WizPL has its own features and is tightly integrated into Wizard Eye architecture.
Wizard Eye has such attribute as an operator, which is a script, written for a specific task.
If you are familiar with an object oriented programming, each operator is actually an object, which implements certain virtual functions.
So, each operator, depending on its type, should have a certain set of functions, which are called from a Wizard Eye kernel corresponding to certain event.

Passes

WizEye rendering process consists of passes. There are several types of passes and each of them performs certain tasks.
Every pass has its own parameters and each parameter may have sub-parameters, allowing to attach a certain functionality, which requires several operands.
Because of WizEye executing several passes, there is a main pass which sets parameters for all passes currently being executed, meaning that if an animation is currently being rendered main pass sets a frame range to be rendered.
Each pass has a type, which is a name of operator being executed by this pass.

Operators

Every type of operator has a short name ending with OP. Generally, each operator runs a Prepare function before executing.
This function should read parameters from a script and store it for future use. Some virtual functions may be called from an operator with different type.
So, light source operator should have the "Shadow" function, which may be called from a surface operator to implement the translucency.
Every virtual function has an "export" keyword before its type, allowing them to be called from outside their operator.
All operators (except RunOP's) have interface parameters, which may reside anywhere inside WizEye GUI.
The operator may receive those parameter values via FindGuiVar, FindColorGuiVar, FindStrGuiVar functions.
Interface parameters for every script should be declared inside a separate file for every operator, this file is a WizPL script, but it does not contain any functions. (link to OP install).
WizardEye has many built-in functions, which control rendering and shading. Some of them may be called only from certain operators type, especially those, which set certain settings, but there are some which may be called from virtually anywhere. It should be noted, that functions may be called before and during the rendering process. Before the rendering starts, most operators execute the Prepare function. By that time, most of the rendering data is still uninitialized and many functions may not work, such as raytracing functions. Also, accessing interface parameters during rendering process is not recommended, because it takes some time to execute and virtual functions performing rendering usually called thousand times thus, multiplying the delay.
There are also many built-in variables, which change their state during rendering process and built-in objects, which have their own variables.

Currently WizEye has follwing operator types:

  • RunOP
  • This operator executes a sequence of passes, it also defines if there will be network rendering, how passes are executed and also may prepare certain files or data for this sequence.
    For example, a number of passes may generate some Shadow Maps which are used by a final pass for animation rendering. RunOPs do not have their own parameters, they are set through the main pass.

  • PassOP
  • Pass operator organizes an execution of passes. It defines a camera for each frame, prepares objects and sets all other rendering parameters, it can also prepare some files for using during rendering.

  • LightOP
  • Light operator is actually an implementation of the light source of some type. This operator defines, which shadow type this light source will have, its color and other parameters. It is assumed that all light sources, with the exception of distant light, consist of one or more samples, as a matter of fact, during raytracing a shadow from a complex light source is being sampled and every sample rendered similar to point-light rendering method. However, light source intensity may be computed mathematically. (link Lighting)

  • MOP
  • Surface operator implemets material properties, in other words, it defines a color of the surface point. In a Renderman compatible renderer this function is performed by a surface shader. However, in WizEye, this is a most complex operator. At first, it has several virtual functions, one for displacement rendering, one for deep shadow rendering and a separate subsystem for rendering a surface point. MOP has such term as Property, which implements material properties and defines a way to render a color of the surface point. In fact it is a sequence of functions, which change according to parameters set by designer. (surfaces link)

  • LrOP
  • Layer operator is similar to LightWave procedural texture.
    Many of the renderman compatible surface shaders may be implemented as a
    layer operator. This allows to design a very complex materials. Every
    material property parameter may contain any number of layers. Volumetric
    operator may use layers inside its parameters, i.e. VlOP has not properties recently.

  • ROP
  • Rendering operator is a complex object, it implements properties of a matter surrounding all objects. In other words, it implements all volumetric objects, background effects, 2 or 3 dimensional lighting or glow effects and so on.

  • ObjOP
  • Object operator is also a complex one, aside of setting options for scene objects it also allows various object manipulations like complicated movement and similar operations.

  • POP
  • Particle operators manipulate various particle objects, they can be single points or objects. (link to ROP)

  • PcOP
  • This operator controls a movement of the specific particle. With several such operators it is possible to implement a complicated particle dynamics.

  • Utility Scripts
  • The purpose of this operator is to allow a designer to create utility scripts for specific task. They are to be executed manually by selecting them from the Scripts menu.

  • Other Scripts
  • Scripts, which may be loaded dynamically from another operators, dispatcher script and all other script without GUI.

ROP's and Buckets

WizEye divides its rendering space into an array of buckets, each bucket contains final pixels to be rendered. Every pixel is divided into sub-pixels, in renderman specification this division is controlled by the PixelSamples parameter. This allows to avoid aliasing effects.
Each pixel/sub-pixel contains samples, every sample is a rendering result of the certain object/surface. Samples, being mixed with each other form the resulting pixel value according to their z-coordinates (distance from the camera) and opacity.
ROP allows to add custom pixel sample, by setting its z-coordinate and opacity. Basically, ROP can replace a whole renderer with itself by calling a raytrace functions and by also telling the renderer not to perform standard pixel rendering. ROP may implement volumetrics, lens flare, 3D glow and other effects.

Every ROP may have following functions:

  • Frgr - puts a sample with zero z-coordinate, returns 1, if renderer is required to perform further processing of this sample, or 0, if it does not. Called only from the Camera, color and opacity returned into Ci/Oi
  • Bkgr - puts a sample with maximum z-coordinate, used to output a background image, called only from the Camera, color and opacity retured into Ci/Oi
  • Sample - puts a sample (or several ones) with specifed z-coordinate and opacity by executing AddPxSample(Color, Opacity, z)
  • VolumeIns - invoked when a ray hits some object, mixes color with object color, affects any ray, color and opacity retured into Ci/Oi
  • VolumeOut - invoked when a ray leaves scene without hitting any object, affects any ray, color and opacity retured into Ci/Oi

ROP should have at least one of above mentioned functions or, at most, may have them all.

Operator's installation, operator's interface parameters

All interface parameters for every operator are stored in a separate database: ./data/config.orn
If this file is absent, all installation scripts stored in ./scripts/update directory will be executed and all operators will be recompiled. Also, each operator may be recompiled separately via Configure->Operators menu.
Functions, which install interface parameters for operators, all work in similar way, only function name needs to be unique. First, it is required to call a function that adds a new operator of certain type; then call functions to add parameters for this operator and if necessary will add default values. If operator has subparameters, they should be added after adding a corresponding parent parameter.
After adding all parameters it is required to specify a text file with WizPL script for this operator and then the output binary file to which it will be compiled. Also, same source may be used for different operators, if it differs slightly from the common template, there is a macro-directive to help with that called #part RNDR_REGULAR, check Render.iepl source for details on how to use it.
All interface parameters are to be converted into one of WizPL basic types, such as: float, int, string, color or vector/color/normal. However, there are more notional types for interface parameters based on their meaning:

  • label - does not have any value, used to specify sub-parameters
  • check - boolean parameter, can be 1 or 0
  • float - any numeric parameter
  • color - parameter to hold a color triplet
  • vector - currently any three-component vector, may hold point or normal 3D coordinates
  • path - used to specify a path to some file, may have a list of extension filter
  • string - any string value
  • choice - a number of string values to be listed into the combo-box, if the value equals LGT_LIST, OBJ_LIST or CAM_LIST, combo-box will be filled with a list of light sources, objects or cameras accordinly

More detalied list:

  • LGT_LIST - list of light sources
  • OBJ_LIST - list of objects
  • CAM_LIST - list of cameras
  • PLC_LIST - list of policies
  • SURF_LIST - list of surfaces
  • PCON_LIST - list of particle operators
  • Common functions
  • void SetColorParmDefault(color Color);
    	- sets a default value for the color type
    void SetFloatParmDefault(float Value);
    	- sets a default value for the float type
    void SetStringParmDefault(string String);
    	- sets a default value for the string type
    void AddChoiceToParm(string Case);
    	- sets a default value for the choice type
    

  • PsOPs
  • void AddPsOP(string Name);
    void AddParmToPsOP(string ParameterType, string ParameterName);
    void SetPsOPText(string PathToSource);
    void SetPsOPBin(string PathToBinaryText);
    void SetPsOPPreproc(string Direcitve);
    void SetPsOPInstall(string PathToInstallationScript);
    

  • LOPs
  • void AddLOP(string Name);
    void AddParmToLOP(string ParameterType, string ParameterName);
    void SetLOPText(string PathToSource);
    void SetLOPBin(string PathToBinaryText);
    void SetLOPPreproc(string Direcitve);
    void SetLOPInstall(string PathToInstallationScript);
    

  • ObjOPs
  • void AddObjOP(string Name);
    void AddParmToObjOP(string ParameterType, string ParameterName);
    void SetObjOPText(string PathToSource);
    void SetObjOPBin(string PathToBinaryText);
    void SetObjOPPreproc(string Direcitve);
    void SetObjOPInstall(string PathToInstallationScript);
    

  • MOPs
  • void AddMOP(string Name); 
    void AddProperty(string Name);
    	- adds a property to the material operator
    void AddParmToProOP(string ParameterType, string ParameterName);
    	- add a parameter to the current materials property
    void SetAddFlag();
    	- when a material properties list is first loaded, a set of default properties, 
    	like opacity, is already present in the list, 
    	this flag shows if property is in that list, 
    	other properties should be added manually by designer
    void SetPropRepeatable();
    	 - some properties may have several values, meaning that it is possible 
    	to assing a value to such property several times, 
    	for example the SingleReflection property
    void SetProOPText(string PathToSource);
    	- source code of property operator
    void SetProOPBin(string PathToBinaryText);
    

  • LrOPs
  • void AddLayer(string Name); 
    void AddParmToLr(string ParameterType, string ParameterName);
    void SetLrText(string PathToSource);
    void SetLrBin(string PathToBinaryText);
    

  • POPs, PcOPs, ROPs
  • void AddPOP(string Name); 
    void AddPcOP(string Name); 
    void AddROP(string Name); 
    void SetOPText(string PathToSource); - source code of the operator
    void SetOPBin(string PathToBinaryText);
    void AddParmToOP(string ParameterType, string ParameterName);                                        
    

  • Utility and other scripts
  • void AddUtilityScript(string Name); 
    void AddOtherScript(string Name); 
    

Working with interface parameters

Any operator can obtain a value of any belonging interface parameter, however, parameters from other operators are mostly inaccessible.
Because any interface parameters may have a set of sub-parameters, they are also availiable via corresponding functions:

float FundGuiVar(string ParmName) 
returns a floating point value of the interface parameter for current frame (considering the envelope (editable by the graph editor)), because currently there is no need for interface parameters to have an integer type, float type is used also to store integers
color FundColorGuiVar(string ParmName)
returns a color/normal/point type value, there is no difference for those types in interface variables, they are passed to the operator as is
string FundStrGuiVar(string ParmName) - returns a string interface parameter

Sub-parameter search functions work the same way, before using them, the search scope must be assigned via certain operator or function (like foreach([parent parameter]).

float FundGuiSubVar(string ParmName)
color FundColorGuiSubVar(string ParmName)
string FundStrGuiSubVar(string ParmName)

If parameter's envelope function does not depend on frame number, it is possible to get its handle via GetGuiVar function, however, it is required to supply envelope function argument to obtain a resulting value via CalcGuiVar.

int GetGuiVar(string ParmName)
float CalcGuiSubVar(int ParmHandle, float Arg)
color CalcColorGuiSubVar(int ParmHandle, float Arg)

If the operator has some custom parameters, e. g. added by a user, there are special means to access them.
For example, ROP's have such parameters, therefor there is the CurROP object pointing to a ROP currently being executed. This object has two members, the CurROP.CustomParm pointing to a current custom parameter and the CurROP.CustomParmName which is a string and contains a name of current custom parameter.

Finding From Other Operators

Interface parameters can be accessed from the other operators, there are a number of common search functions for this task. All these function require an operator's handle, but there is a separate function for each operator's type. During network rendering prepare, this handle is passed to operator's prepare function which should prepare files for network render. After use, each handle must be closed to avoid memory leaks, however, it should not be done for network render. (link to netrender)

float Pl_FindGuiVar(int hOP, string ParmName);
string Pl_FindStrGuiVar(int hOP, string ParmName);
color Pl_FindClrGuiVar(int hOP, string ParmName);
vector Pl_FindVecGuiVar(int hOP, string ParmName);

All functions above require a Policy handle, which may be obtained via GetPolicy(string PolicyName) function.

int Pl_GetLOP(int hPolicy, int hLOP, string LightName);
int Pl_GetMopProp(int hPolicy, string ObjName, string SurfName, 
	int PropHandle, string PropertyName);
PropHandle should contain a handle of previously found property or 0 in the beginning of the search; property name may be ""
int Pl_GetLrOP(int hMopProp, string ParmName, int LrHandle, string LrType);
retrieves the layer's handle for the specifed parameter, LrHandle specifies previous layer or can be 0, LrType - layer's type name, may be ""
int Pl_GetROP(int hPolicy, int ROPHandle, string ROPType);
retrieves the ROP's handle, ROPHandle specifies previously found or 0, ROPType - ROP's type name or ""
void Pl_CloseHandle(int hOP);

Built-in objects

  • LOP
  •   Object functions:
      Func
      Diffuse
      Specular
      SpecularC
      Shadow
      ProcessShadow
      Visibility
    
  • MOP
  •   Object functions:
      Func
    
  • LrOP
  •   Func
      ProcessColor
      ProcessFloat
      SetUVDisplacement
    
  • CurCamera
  •   Object variables/parameters:
      Name - camera name
      FOV - camera field of view
      Pos - camera position
    
  • CurLight
  •   Object variables/parameters:
      Name - light source name
      Num - light source id number
      From - light source starting direction
      To - light source target direction
      CustomParm - light source custom parameters
    
  • CurPOP
  •   Object variables/parameters:
      CustomParm - custom parameters
    
  • CurROP
  •   Object variables/parameters:
      CustomParm - custom parameters
      CustomParmName - custom parameter names
    
  • CurObject
  •   Object variables/parameters:
      Name - geometry object name
      Pos - geometry object position
      Surfaces - a handle to iterate through object surfaces
      Layer - a handle to iterate through current surface layers
    
  • CurLayer
  •   Object variables/parameters:
      Name - name of current layer
    
  • CurSurface
  • CurProOP
  •   Object functions:
      GetFinishType
    
  • CurPcOP
  •   Object functions:
      AddParms
      SetParms
      Calculate
    
  • CurPolicy
  •   Object variables/parameters:
      Lights - the list of handles for all light sources inside current policy.
      Surfaces - the list of handles for all surfaces inside current policy.
      Cameras - the list of handles for all cameras inside current policy.
      ROP's - the list of handles for all ROPs inside current policy.
      POP's - the list of handles for all POPs inside current policy.
      PcOP's - the list of handles for all PcOPs inside current policy.
    

In that case, operator which is being called from WizEye menu will have an access to interface parameters of corresponding object (for ex. a light source) when calling FinGuiVar, FindColorGuiVar and FindStrGuiVar. The operator may use SetGuiVar, SetColorGuiVar and SetStrGuiVar to update interface parameter values.

Cache and baking

A large amount of WizEye data is stored inside the cache, i.e. when a memory usage exceeds the specified amount, a part of data is moved to the hard disk cache.
All loadable images are stored inside the cache. So, the developer should call necessary functions to load images into the cache, or generate them by himself.
That way, the meaning of the baking process is to generate an image inside the cache and then unload it into a file.

Adaptive sampling

WizEye 3D uses super-sampling, i.e. each pixel is divided into several subpixels and for each subpixel a separate ray is calculated; this allows to eliminate aliasing effects. However, in many cases, aliasing effects usually seen at the edge of objects or shadows. Adaptive sampling allows to use super-sampling only on edges, for that, it performs a pre-pass and stores all necessary information for further analisys and filtering only those pixels which are to be super-sampled.
So, WizEye 3D can use either geometry or color information to filter pixels for super-sampling. In the first case, the angle threshold should be specified, in the second case - the color threshold (between 0.0 and 1.0).
Also, a soft shadow made via Gather or Area Light does not need any super-sampling, only some extra smoothing, so it is possible to achieve soft shadows by using lesser number of rays.

Adaptive Sampling consists of two parts. The first one, built inside the renderer itself and is inaccessible to developer. This system decides at the second pass which pixel is to be rendered.
The second part is available to developer similar way as baking. An Operator may unload a pixel value into the cache and then, specify to the engine a certain threshold, after which this value should be re-rendered when in super-sampled mode. Meaning, that for the simple, non-transparent shadow only its edges should be re-rendered because a shadow is only a part of the integral pixel color.
The IsAdaptiveSampling() returns 1, if current rendering type is adaptive.

Lighting, LOPs

LOP operator preparation is a bit different from the others, instead of Prepare virtual function, one of following funtions should be implemented, depending on the type of the light source; such as: ProcessDistant, ProcessLocal, ProcessLinear, ProcessArea, ProcessUVLight and Process.
Function name specifies the type of the light source, that way the renderer expects certain functionality of light operator.
For the Linear and Area lights, the engine generates a set of samples, which are available inside the "forlsamples" loop. There are several variables passed to the ProcessLinear function, into which the light source direction and number of samples should be returned.

Virtual functions

These function should be implemented inside a light soruce operator.

  • LOP.ProcessDistant(color LightColor, vector From, vector Direction)
  • implements a distant light source, which does not have a reference point, only a direction. LightColor and From properties are not used, but may be used later on

  • LOP.ProcessLocal(color LightColor, vector From, vector Direction)
  • implements a light source with a size of a single sample, may have a direction axis. LightColor property is not used and may be used later on

  • LOP.ProcessLinear(color ptr LightColor, vector ptr From, vector ptr Direction, float ptr NoiseLev, int ptr Samples)
  • implements a light source, where all samples form a single line specified by a starting point From, vector Direction and number of samples. It is also required to specify a certain noise level value to be added to each sample coordinate

  • LOP.ProcessArea(color ptr LightColor, vector ptr From, vector ptr DirectionX, float ptr NoiseLev, int ptr SamplesX, int ptr SamplesY, vector ptr DirectionY)
  • implements a light source, where all samples are situated inside specified flat rectangle, it is required to specify world coordinates of local coordinate system reference point (i.e. From), an X-axis and Y-axis vectors, X and Y sample count and a noise level value, which will be added to each sample coordinates

  • LOP.ProcessUVLight(color ptr LightColor, float ptr NoiseLev, int ptr Samples, int ptr hUV)
  • implements a light source where all samples are placed upon a certain surface and distributed according to surface UV-coordinates; it is required to return a handle of the surface which will be used as a source

  • LOP.Process(color ptr LightColor)
  • implements a light source which have several samples in any suitable combination

  • LOP.Shadow(point Pf, vector L, color Lum)
  • a function which alters an itensity of the lighting ray, i.e. processing a shadow color. Trace begins at Pf's and goes until specified limit in L's direction

Pf is a surface point for which an illumination is being calculated;

L is a vector from the surface point to the light source.

This function is called from MOP.ProcessOcclusion, or from LOP.Diffuse and LOP.ProcessShadow, or when implementing the Translucency effect.


Important: The L vector MUST be normalized.

  • LOP.Diffuse()
  • this function calculates a Diffuse parameter for the specified light source, the ray is traced back from point P to the light source, this function sets the Ray Limit - the coordinates of the sample belonging to this light source which ray has been hit.

  • LOP.ProcessShadow(point Pf, color Lum)
  • a function which calculates a shadow being cast over the specified point from the specified light source, i.e. the ray will be traced from Pf in L's direction over to radiance point (light source sample). L should be calculated via LOP.ProcessShadow, so this function should call SetRayLimit.

  • LOP.Visibility(point Pf, color Lum)
  • this function should be implemented in LOP; it should show how the point Pf is visible for the specified light source without calculating a shadow.

Built-in lighting functions

  • diffuse()
  • this function is similar to following WizPL code:

      color diffuse(){
        color Cl = 0;
        foreach(Light){
               Cl += LOP.Diffuse();
        }
        return Cl;
    }
    
  • SetRayLimit(point Lim)
  • sets a limit for ray tracing; when MOP.Process is invoked, the ray limit is cleared, but it is restored upon exit. Inside MOP.ProcessOcclusion the Ray Limit stays unchanged, but may be modified

  • SetNoRayLimit()
  • the ray does not have a limit, this function should be executed in distant light

  • occlusion(point Pf, vector L, color Lum)
  • system function, should be executed from LOP.Shadow, calculates a shadow color in specified point, does not consider opacity, i.e. MOP.ProcessOcclusion is not executed

  • occlusion_sh2(point Pf, vector L, color Lum, float Angle, float Rays)
  • traces the specified amount of rays around the vector L from the specified point F limited by the Angle cone

  • occlusion_dsh(point Pf, vector L)
  • a system function, should be called from the LOP.Shadow, calculates a color of the shadow in the specified point, calls MOP.ProcessOcclusion, the color is return into Ci

  • occlusion_dsh2(point Pf, vector L, color Lum, float Angle, float Rays)
  • traces the specified amount of rays, like the occlusion_sh2, but in addition calls MOP.ProcessOcclusion

  • MOP.ProcessOcclusion(point Pf, vector L, color Lum)
  • should be implemented in the MOP, calculates a color of the ray which hit the specified point; so, to trace the ray from a light source to this point the LOP.Shadow should be called.
    Therefore, regardless of that the ray usually being traced from the point where camera ray has been hit, the ray which hits this point is traced from a light source point (if sufficient Trace Limit is specified)

Surfaces, MOP (detailed)

Material Operator carries out the same function as the Surface Shader in Renderman. In other words, MOP performs a shading of the surface point. As any other operator, the MOP contains a set of functions with predefined names, which are called in many different occassions:

  • Prepare()
  • called before the beginning of any pass which use surface shading

  • Displacement::Process()
  • called for point displacement

  • IsSmoothing()
  • called to determine smooth surface

  • GetSmootingAngle()
  • gets a smoothing angle

  • IsDisplacement()
  • returns if displacement is enabled for the specified surface

  • ProcessOcclusion(vector ptr From, vector ptr L)
  • used to change a ray color which passed through the surface

  • IsTransparent()
  • returns if there is any transparency on the specified surface

Any other functions are added by the desinger for additional functionality and shading.

Shading

Shading contains sections. Each section is a sequence of MOP functions, specified in Prepare().
Section may be called by the renderer in random order, any number of times.

Currently, there are 6 section types:

  • starting section, zeroes all MOP parameters ("Start");
  • sections which calculate lighting, every light source must have its own ("Light") section;
  • transparency section ("Transparency");
  • raytracing section ("Raytrace");
  • shading section, calculating a surface color without diffusion, transparency and raytracing ("Shade");
  • finishing section, summarizes all material properties ("Finish");

Properties

Properties may be built inside the MOP or may be as separate operators. Because each property use same variables, built-in properties may not be repeatable. But properties implemeted in separate operator may repeat, because data segment is stored separately for each one.
For example, Single Object's Reflection property may be specified several times for several objects and for each one it is possible to specify different Max and Fade distances.

Properties must be declated at the beginning of the MOP.

property Reflection{
  color  Clr;
  color  SvClr;
  int    MParmHandle;
  int    bSoft;
}

Every variable is unique for the current property, they are accessible within property functions and by the scope resolution operation from another properties or from a global functions.

ProOPs

Each ProOP should have the following virtual functions:

void Prepare() 
	- call for property preparation
string GetFinishType() 
	- should return property type; color, transparency or else...
Process() 
	- caluculates a property value for the sample
color FinishSection() 
	- returns the calculated value

Properties are defined separately for each MOP, therefore in some way the MOP itself defines property behavior. It means that the MOP decides when to recieve a property value and how it will be integrated into the MOP's shading formulae.

To attach ProOPs to the MOP several step are necesarry:
firstly, call the InitProOPs() to initialize all properties,
then, add property functions to each MOP's section:
for that call: foreach(ProOPs)
then AddProOPFinishSection(string FuncName) - this function specifies the current property function name which should add a final color extraction to the MOP's "finish" section.

Calling ProOPFinish() will get a current property value.

Properties define a section type where they execute in the Prepare function by themselves using BeginSection/AddToSection/EndSection.

Properties are executed in the order they were initialized.

Shading functions

The Prepare function must supply the renderer with a MOP function sequence, which are to be called inside a section. So, if a surface is reflective, MOP will have the Reflection property and prepare function should add the Reflection::Process function, which will calculate surface reflections.
During the surface point rendering, the engine calls a section with the specified set of MOP functions.
These functions cannot return any values and may not have any operands, however, inside themselves they may call another MOP functions, passing any operands and getting results.

Global variables/parameters

Global variables are unique for each surface point, so any changes to global variables during shading process will not be available to another surface point, or even to the same point with different TraceLevel.
However, any data stored during the Prepare() is available for every surface point.
Therefore, a material's parameter handle stored during Prepare() into the global variable named MParm may be used during shading for any surface point.
But MOP should not change any variables which has been set during Prepare(), because that memory may be used again to save time for allocation and clearing. That is because it is required to zero all global variables before shading process. Same approach should be used for local ones too.

DLLs and Custom Scripts

There is a way to call any Windows dynamic library function from the script or load another script and call its functions.
For example on using Dso check the .\DLLTest directory: DLLTest.iepl is an installation script, DLLTest.epl is a ROP all other files are Visual Studio 6.0 project.

The DLL function should be in following format:

DLL_API void Distance(unsigned int *Adr, unsigned int NumOfOpr, void *Ret) - the address of function's
operands, their quantity and return result address should be supplied.

Note that passing invalid or improper values as operands may result a fatal error.


It is possible to pass any number of operands in the script, e.g. to access 2-nd and 3-rd operands use following:

double *Color = (double*)Adr[1];
Color[0] = 1.0; Color[1] = 1.0; Color[2] = 0.0; - we'll have a yellow color here.

Similar way any other script may be called, it is expected that it belongs to the "Other Scripts" category, the only difference is that it is compiled by the WizEye itself.

DLL operation functions

int DLL_Load(string Path) 
	- loads the specified DLL and returns its handle or 0 if there is an error.
int DLL_GetFunc(int hLib, string FuncName) 
	- looks up the specified function the DLL and returns its handle.
float DLL_fFunc(int hFunc, ...) 
	- calls the DLL function, assuming the return type is float.
float DLL_iFunc(int hFunc, ...) 
	- calls the DLL function, assuming the return type is int.
color DLL_cFunc(int hFunc, ...) 
	- calls the DLL function, assuming the return type is color.
vector DLL_vFunc(int hFunc, ...) 
	- calls the DLL function, assuming the return type is vector.
void DLL_fFunc(int hFunc, ...) 
	- calls the DLL function, assuming no return value.

Script operation functions

int SCR_Load(string Path) 
	- loads the specified script and returns its handle or 0 if there is an error.
int SCR_GetFunc(int hLib, string FuncName) 
	- looks up the specified function the script and returns its handle.
float SCR_fFunc(int hFunc, ...) 
	- calls the script function, assuming the return type is float.
float SCR_iFunc(int hFunc, ...) 
	- calls the script function, assuming the return type is int.
color SCR_cFunc(int hFunc, ...) 
	- calls the script function, assuming the return type is color.
vector SCR_vFunc(int hFunc, ...) 
	- calls the script function, assuming the return type is vector.
void SCR_fFunc(int hFunc, ...) 
	- calls the script function, assuming no return value.

Particle Arrays

There are several ways to operate particles, one of them is called "Particle Array". Currently, this array is stored completely in the system memory and do not use the cache. The array may have any number of following parameters: float, int, color, vector, tpos.
The tpos type contains texture coordinates, i.e. two doubles: s and t.
The array is created by the p_open function, after that, all required parameters should be added. These functions return a parameter's handle, after which it may be modified for any particle.
After adding parameters, the p_init function should be called, it will initialize the array.
The array itself may have following types:

P_TXT - contains particles situated inside a texture, expected to be used in layers.

P_ITEM - particles which have a set of some information: color, rotation, etc. Also there is an essential position parameter needs to be specified and accessible via p_getpos/p_setpos.

P_OBJECT - particles which are objects, each particle may clone any object in the scene, also there are essential parameters: position and rotation, they are accessed via p_getpos/p_setpos/p_getrot/p_setrot functions.

int p_open(int ParticleNum, int ArrayType)
int p_add(int hPArray, string ParmType) 
	- adds a parameter of the specified type, returns its handle.
int p_add(int hPArray, "tpos", int XSize, int YSize) 
	- adds particels for a texture map with XSize, YSize dimensions.
int p_init(int hPArray) - initializes the particle array.

p_findfor(int hPArray, int ParmNum, float s, float t, float Radius){
 like the foreach cycle, searches a particle inside 
 the specified shpere radius at the specifed coordinates.
}

float p_GetVar(int hPArray, int ParmNum) 
	- works inside the p_findfor, returns a float value of the specifed particle parameter.
color p_GetColorVar(int hPArray, int ParmNum) 
	- works inside the p_findfor, returns a color value of the specifed particle parameter.
vector p_GetVectorVar(int hPArray, int ParmNum) 
	- works inside the p_findfor, returns a vector value of the specifed particle parameter.
color p_GetIntVar(int hPArray, int ParmNum) 
	- works inside the p_findfor, returns an integer value of the specifed particle parameter.
void p_GetTxVar(int hPArray, int ParmNum, float ptr ss, float ptr tt) 
	- works inside the p_findfor, returns a texture coordinates of the particle.
float p_getdist(int hPArray) 
	- works inside the p_findfor, returns a distance from the particle to the search sphere center.
float p_getangle(int hPArray) 
	- works inside the p_findfor, returns an angle between 
	the particle and search coordinates, assuming that s and t as x and y.
int p_getnum(int hPArray) 
	- works inside the p_findfor, returns an index for the particle.
void p_settpos(int hPArray, int ParticleNum, int ParmNum, float s, float t) 
	- sets a texture coordinates of the specified parameter's particle.
void p_setpos(int hPArray, int ParticleNum, point ptr PP) 
	- sets a position of the specified particle.
void p_setrot(int hPArray, int ParticleNum, vector ptr PP) 
	- sets a rotation of the specified particle.
void p_setparm(int hPArray, int ParticleNum, point/color/float/int) 
	- sets the parameter's value according to its type, make sure the type is correct.
void p_setobj(int hPArray, int ParticleNum, int hObj) 
	- sets the object for the particle, an object hanlde should be supplied, 
	it may be obtained by using GetObjectByName.
point p_getpos(int hPArray, int ParticleNum) 
	- gets a particle's position.
vector p_getrot(int hPArray, int ParticleNum) 
	- gets a particle's rotation.
int p_getintparm(int hPArray, int ParticleNum)
color p_getcolorparm(int hPArray, int ParticleNum)
vector p_getvectorparm(int hPArray, int ParticleNum)
float p_getparm(int hPArray, int ParticleNum)

UV Rendering

For UV-rendering the property uses UVR_AddSurf(string Guide) or UVR_AddGuide(int hGuide) functions; all objects containing this surface will be processed, because objects may be duplicated by the particle subsystem.

A guide-layer's name (in case of UVR_AddSurf) or layer's handle should be supplied. It may be obtained via the int CurLayer2Guide function, called inside the foreach(Layer) cycle. A property function, which performs the UV-rendering should recieve an object ID, it may be passed to the Obj_GetParm function to obtain an object parameters, or to the GetNameByObjId function.
Other parameters are standard: P, I, N, Nf, Ng.
s, t specifies current coordinates inside a guide texture (0.0 - 1.0)
s_img, t_img specifies pixel coordinates according to selected width. To make the property executable in UV-rendering, it should add itself for execution inside the Prepare function via the UVR_AddProcessing(int Width, int Height) function. This function will return a handle, which may be used to add functions to execute on every cell of the texture texture that being processed (width and height are specified during UVR_AddProcessing call).

The UVR_Func(hProc, "Prepare", string FuncName) defines a name of the function, which should be added to perform an object preparation for UV-rendering, it should receive an object ID and return 1 if UV-rendering is to be performed for this object. If this function is not specified, an object will be prepared by default.

Because UV-rendering supports also antialiasing and adaptive sampling, there are two functions which should be specified: UVR_Func(hProc, "GetSample", string FuncName), which returns a value of current sample and UVR_Func(hProc, "SetColor", string FuncName), which returns to the UV-rendering handler a final value after sampling.

The UVR_Samples(hProc, SamplesX, SamplesY) function defines a number of samples for the specified surface texture and the UVR_AS(hProc, Thrs) function defines a threshold after which the texture cell should be re-rendered, similar to the camera adaptive sampling.

The UVR_IsNow function is used to check, if UV-rendering is currently in progress.

Extensions

Extensions allow more information to be included with an operator. Usually it can be surface list, or other elements helping the operator to perform its functions.
Extensions may be used in any operator, e.g. light or property. User must specify an extension name, which will be used by the FindExtension function which will return the handle of the operator. This handle may be used with the Pl_FindGuiVar function. In that case the policy handle should be null, because extensions do no depend on Policy.

List objects may be reached via Custom Parameters, to do that, SetCustomParm is to be called, then it is possible to iterate through the list with foreach(CurExtension.CustomParm).

int FindExtension(string ExtensionName);

RunOPs

RunOP may perform a frame rendering immideately after being invoked, or it may enter the one of extended modes, allowing some additional functionality.
E.g, the networked mode allows a designer to render the scene over a network as many times as required.
RunOP should have the Process virtual function, which calls the SetMode function.
The SetMode function may have a number of parameters, currently there are flag (or flags) and RunOP's actions:

SetMode("flag", "Net", "action", "Render Current Frame", "Render Scene", "Close");

Actions are implemented within RunOP there are may be any number of them.
Flags are used to direct renderer to what to do next:
"Run" - rendering starts immediatly, in that case, the RunOP's OnAction is called.
"Close" - leave the RunOP and return to normal state.
"Net" - enter the networked mode.
"DM" - enter the design mode.

Each RunOP should have the OnAction(string sAction) virtual function, which receives an action, specified by a user, via its parameter.

Network Rendering

Supervisor - a workstation where a scene is opened (or recieved from LW) and also the interface, where scene and rendering parameters can be set.
Worker - a workstation without interface which performs rendering by supervisor order.
Dispatcher - a script, which discovers if workstation is available for rendering.

RunOP

RunOP performs a pass rendering, each pass may contain some number of frames. RunOP distributes them between rendering workstations. It looks for a free workstation, accesses it and performs rendering.

A general layout of RunOP's operations:

Enter into networked mode.

Invoke N_Start() in any event of choosing to render scene of frame.

Invoke N_WaitForReq when one of the workers becomes free after rendering is complete or invoke N_End() if rendering is aborted.

N_WaitForReq function has a handle as parameter, which is a handle of virtual function inside RunOP to be executed when a free worker is required for rendering. This function should transfer a scene to a worker and specify which frame and pass to render.

Important: Remember that N_WaitForReq is multi-threaded and runs as separate copy for each worker, that requires extra caution, so all critical RunOP variables should be accessed only via thread-safe functions.

Worker's RunOP

Worker's RunOP should have the Worker virtual function, which will be called by a rendering supervisor.

Worker(string ptr PassName, float ptr Frame) - requires a pass name and frame number, usually calls RenderPass inside itself.
Worker's RunOP performs rendering of specified pass and frame.

Worker's network functions

int N_SetRunOP(int hWrk, string RunOPName) 
	- specifies which RunOP a worker should execute to render the specified frame in a pass.
int N_SendScene(int hWrk) 
	- sends the scene to a worker, 
	it will be accepted by a worker automatically, 
	returns 1 if operation was successfull.
int N_SetPass(int hWrk, string PassName, float Frame) 
	- specefies the pass and the frame to render.
int N_SetRegion(int hWrk, int Left, int Top, int Width, int Height) 
	- sets a rendering region allowing a same frame to be rendered on several workers.
int N_Run(int hWrk) 
	- starts a rendering proccess on the worker, 
	returns 1 if rendering was successfull.
void N_Start() 
	- initializes network rendering.
void N_End() 
	- gracefully ends network rendering.
void N_WaitForReq(int FuncHandle, int ptr Tag) 
	- awaits while the specified worker becomes free, 
	requires a virtual function address for connection and a tag 
	to obtain the worker information (usually a recordset handle).

Function, necessary for the RunOP

int OpenCurPassForReq() 
	- make the pass operator available for networked RunOP, returns the handle of the pass.

void CallPassFunc(int hPass, string ParmName, int ptr Value) 
	- calls the FuncForReq function from the PassOP that it could 
	return a data from the pass (image size and etc), 
	parameter name should be supplied and also a variable name to recieve data.

void CallPassFuncFl(int hPass, string ParmName, float ptr Value) 
	- same as CallPassFunc, but calls FuncForReqFl; returns float data.

void ClosePassHandle(int hPass) 
	- closes the pass and releases the memory.

string GetCurPassName() 
	- return an unique name for currently selected pass.

Dispatcher

The Dispather is loaded with WizEye 3D engine, therefore, in case of any changes in its code it should be recompiled and WizEye 3D should be restarted.
The Dispatcher script is inside the "Other Scripts" group and has a constant name: "Dispatcher".
When loading, the Dispatcher executes the Process function, which should load an information about all workers and add them to the dispatcher interface, available via "Configuration/Net" menu.

It is assumed, that dispatcher will use recordsets for storing its worker data, therefore if it is necessary to store a connection between interface and recordset parameter, the interface parameter handle may be stored inside the recordset. Besides, the dispatcher may specify custom parameters, which a user may add in any quantity (workstation addresses for example).

Any interface parameter may have subparameters. When RunOP switches to the network mode (SetMode("flags", "Net")), dispatcher executes the OnOpenMode virtual function. It is expected that this function will call ND_Connect to connect each worker, this function expects a handle for connection, that handle can be obtained via ND_RegisterConnect function. Same way works the OnCloseMode virtual function.

The ND_Connect function should receive names of virtual functions to execute upon worker load, unload and loss of connection with a worker, all of them are executed in separated threads.
The ND_IsClosing function shows a reason of worker's disconnection, such as, the network mode shutdown or the connection was lost. The Dispather may set a trigger which will try to connect worker after some timeout; also,
the dispatcher defines user actions (visible in the menu) to add a worker.
On each action being invoked, the OnAction virtual function is called, which recieves an action name as parameter.
Because the dispatcher's GUI is dependent on parameters related to workers, when creating GUI parameter, a virtual function should be specified by dispatcher, which will be invoked on any GUI-parameter changes.

Network paths

A worker's RunOP should have two virtual functions: OnGetFile and OnSaveFile.
The OnGetFile function should tell the system where to get a file if certain path is specified in the scene.
The OnSaveFile, like the OnGetFile, should tell the system where to save a file.

OnGetFile(string ptr OldPath, string ptr NewPath, int iAction) - specifies a new path to a file and action to be performed via the old path (iAction).

NET_FILE_NOTHING  
	- do nothing
NET_FILE_SPVR     
	- recieve from supervisor and save to specified path.
NET_FILE_SPVR_TMP 
	- recieve from supervisor and save to temporary (system generated) path.

OnSaveFile(string ptr OldPath, string ptr NewPath, int iAction) - a file has not been created, the RunOP handler should specify a new path and what to do.

NET_FILE_SAVE     
	- save into specified path.
NET_FILE_SPVR     
	- upload a file to the supervisor and it will save a file into specified path.

In the stand-alone mode, for compatibility with networked mode, RunOP functions are called also, but the iAction parameter is ignored, the function should return a file path only.
Thus, the OnGetFile function is called during image or map loading via such function as: LoadImage, LoadHdrImage, I_LoadImage, I_LoadMap and the OnSaveFile when saving or extracting.

The OnSaveFile is not called when saving plain (non-HDR) rendered image, but called when saving HDR, Alpha or Z-map.

All scripts are loaded using paths specifed for a worker, they should be accessible either locally or via windows network by a full UNC path.

File paths

During the network rendering files are processed in two stages:

  • if the file (e.g. texture) is ready to use, it should be transferred to the specified destination where it will be available to the worker. In the second stage the worker should obtain the path to that file.
  • if the file is generated (during baking or rendering), it is stored into some temporary file and then transferred to the master.

For both stages it is required to supply two function names, the first one: OnCopy should copy the file to worker or master, the second one: OnGetPath should determine a file path. Thus, for ready to use file, the OnCopy is called first to copy the file, then the OnGetPath to get a path. For generated file, the OnGetPath is called first (for temporary file path on worker), then the OnCopy (to copy the file to the master).
Both functions recieve the bCreate flag, which defines if the destination is already exists or should be generated, the path is passed as it is. If the rendering takes place at the master, only the OnGetPath is called.

When rendering starts, the unique Session Id is generated, so that if the same node is called for several frames no additional file-copying occur. It is also possible to force scene copying even if it has not been changed.

Dispatcher's callable functions

It is assumed that the dispatcher keeps all its data in the recordset; during loading, the dispatcher creates interface parameters according to records inside the recordset.

Dispatcher creates actions that will be visible in its menu. If Dispatcher
operates with recordsets then it creates records(computer names, addresses,
ports, etc.) and save recordset to a file. It may load the file inside "Process"
function that is executing during Wizard Eye's start.

int ND_AddGuiSet(string Name)
	- adds a set of variables, returns its handle or 0 if an error occured.
int ND_AddGuiParm(int GuiSetHandle, string ParmName, float ParmValue, int Tag, string OnChange) 
	- adds an interface parameter of specified type, 
	returns its handle which may be used later 
	in such functions as ND_SetGuiVar and ND_GetGuiVar; 
	OnChange is the name of dispatcher's function 
	which will be executed on any parameter changes, 
	if it is an empty string or function not found, no code will be executed.

int ND_AddStrGuiParm(int GuiSetHandle, string ParmName, string ParmValue, int Tag, string OnChange) 

int ND_AddClrGuiParm(int GuiSetHandle, string ParmName, color ParmValue, int Tag, string OnChange) 

int ND_AddVecGuiParm(int GuiSetHandle, string ParmName, vector ParmValue, int Tag, string OnChange) 

void N_AddGuiAction(string ptr sAction) 
	- adds a dispatcher's action into the menu.
void ND_RefreshGUI() 
	- when adding an interface parameter it is necessary to call this function to refresh the window.
int ND_AddGuiSubParm(int GuiParmHandle, string ParmName, float ParmValue, string OnChange) 
	- creates a subparameter for the specified parameter.
int ND_AddStrGuiSubParm(int GuiParmHandle, string ParmName, string ParmValue, string OnChange) 
int ND_AddClrGuiSubParm(int GuiParmHandle, string ParmName, color ParmValue, string OnChange) 
int ND_AddVecGuiSubParm(int GuiParmHandle, string ParmName, vector ParmValue, string OnChange) 
int ND_RegisterConnect(string Adr) 
	- registers the specified address for connection and returns its handle.

void ND_Connect(int ConnectHandle, int Tag, string FuncName) 
	- connects to a worker; upon connection 
	the dispatcher's virtual function with specified name 
	and tag (recordset handle is expected) will be called.

void ND_Disconnect(int ConnectHandle) 
	- closes connection with the worker if it is open.

int ND_SetTrigger(int FuncHandle, int Tag, int Time) 
	- specifies that a certain function (a handle is required)
	will be executed after specified time period and specified tag will be passed to it.

int ND_IsClosing() 
	- returns 1 if network mode is currently shutting down.

Built-in variables, Trace Stack, Gather

The renderes has a set of built-in variables which are used by operators in final shading processes, lighting and volumetrics.

Each ray is processed separately, therefore there can be only one ray being processed instantly. The ray begins at the camera and traced until it hits any non-reflective surface (i.e. any surface which does not perform raytracing) or until the trace limit (set by a user) is reached. The renderer provides an information about every trace level from current to zero and, most important, about the next to current trace level.

When a ray hits some surface point at the current trace level, the set of several variables becames available from any operator, e.g. MOP, LOP or volumetric:

P 
	- current surface point.
Ng 
	- geometric normal of current surface point.
N 
	- shading normal of current surface point.
Nf 
	- shading of current surface point, pointed to camera, 
	i.e. of N is opposite to camera it will be multiplied by -1.
I 
	- direction vector, it is either from surface point to camera, 
	or from surface point where trace will be executed.
Ci 
	- color value which should be set by the MOP for this surface.
Oi 
	- opacity, set by the MOP for this surface, 
	usable for surfaces which utilize z-buffer to calculate transparency (without raytracing).
Cm 
	- camera vector for current subpixel.
E 
	- camera coordinates.
s, t 
	- UV-coordinates of current surface point, 
	for volumetric effects these values are set by 
	a volumetric operator for layers operators to function properly, 
	therefore these coordinates depend on the surface texture projection type.
s_cam, t_cam 
	- current pixel coordinates normalized within (-1.0, 1.0).
s_img, t_img 
	- current pixel coordinates in terms of image size.
SubpxX, SubpxY 
	- each subpixel has coordinates inside its parent pixel.
TraceLevel 
	- current trace level, necessary to access the trace stack.
bTraceEnd 
	- shows that trace is over.
bOutsideRay 
	- current ray did not hit anything or goes outside world limits, 
	used inside ROPs (volumetric operators).
PhE, PhLev, PhD, PhC 
	- variables used in photon processing.
R_FrameRate 
	- current framerate.
R_CurFrame 
	- current frame number.
IPassType 
	- current subpass type. (see Adaptive sampling)

When using trace level related functions, also the ObjId is available; it is an unique identifier of the object which is hit by the ray.

Following functions recieve data according to the trace level:

int is_trace_processed(int TraceLevel); 
	- checks if a MOP was executed for a point where the ray hit, 
	not all tracing functions perform that check.

int    is_trace_hit(int TraceLevel); 
	- does the ray hit the specified surface.
color  get_trace_color(int TraceLevel); 
	- returns the color calculated by a MOP.
point  get_trace_P(int TraceLevel); 
	- returns P for current trace level.
normal get_trace_Ng(int TraceLevel); 
	- returns Ng for current trace level.
normal get_trace_N(int TraceLevel); 
	- returns Nf for current trace level.
normal get_trace_Nf(int TraceLevel); 
	- returns Nf for current trace level.
int    get_trace_Surf(int TraceLevel); 
	- returns SurfId for current trace level.
int    get_trace_ObjId(int TraceLevel);
	 - returns ObjId for current trace level.

There are several types of functions performing single ray tracing:

color trace(const vector ptr, const vector ptr); 
	- traces the ray from the specified point in specified direction and executes 
	a MOP of a point where ray hits.

color trace_tr(const vector ptr, const vector ptr, const color ptr); 
	- this function traces the ray through transparent objects, 
	it is neccessary to correctly calculate transparency 
	level of each next object on the ray's path.

color trace_rfl(const vector ptr, const vector ptr, const color ptr); 
	- calls the reflect function and then the trace function.

int trace_test(const point ptr, const vector ptr); 
	- traces the ray from the specified point in specified 
	direction but does NOT execute a MOP at the destination point.

So, a trace stack provides an easy way to implement volumetric effects inside an object or implement subscattering, because all trace functions are passed through ROPs.

The Gather function emits a number of directed rays from some point and inside some cone; so it is required to specify: the number of rays, the cone angle, the cone axis and the number of samples.

The process should be initiazlized by the init_gather function, then ray are traced inside the "forgather" cycle, its body is called for each ray; then the free_gather should be called to free up memory.

int gthr_Handle = init_gather(P, V, LookAngle, LookSamples);
	forgather(gthr_Handle){...}
free_gather(gthr_Handle);

The information about a point where the Gather rays hit is available via following functions:

int    is_gather_hit(int GatherHandle); 
	- checks if the ray hits any surface.
color  get_gather_color(int GatherHandle); 
	- returns a color calculated by a surface MOP.
point  get_gather_P(int GatherHandle); 
	- returns P for the point where ray hits.
normal get_gather_Ng(int GatherHandle); 
	- returns Ng for the point where ray hits.
normal get_gather_N(int GatherHandle); 
	- returns Nf for the point where ray hits.
normal get_gather_Nf(int GatherHandle); 
	- returns Nf for the point where ray hits.
int    get_gather_Surf(int GatherHandle); 
	- returns SurfId for the point where ray hits.
int    get_gather_ObjId(int GatherHandle); 
	- returns ObjId for the point where ray hits.

Thread-Safe functions

A thread-safe operation requires a certain set of functions to help managing variables and code execution during multi-threaded processing.

ThrHandle Thr_Register(ptr Var) 
	- registers a memory location for thread-safe operation.
void Thr_Unregister(ThrHandle Handle) 
	- unregisters a memory location, previously registered by the Thr_Register.

Functions below provide compare operations for different variable types:

int Thr_CmpInt(ThrHandle Var1, int Var2)
int Thr_CmpFloat(ThrHandle Var1, float Var2)
int Thr_CmpVec(ThrHandle Var1, vector Var2)
int Thr_CmpClr(ThrHandle Var1, color Var2)

These functions provide conditioned branching similar to x86 machine code, i.e. compare and jump:

Jump if above:

int Thr_JaInt(ThrHandle Var1, int Var2)
int Thr_JaFloat(ThrHandle Var1, float Var2)

Jump if below:

int Thr_JbInt(ThrHandle Var1, int Var2)
int Thr_JbFloat(ThrHandle Var1, float Var2)

Jump if above or equal:

int Thr_JaeInt(ThrHandle Var1, int Var2)
int Thr_JaeFloat(ThrHandle Var1, float Var2)

Jump if below or equal:

int Thr_JbeInt(ThrHandle Var1, int Var2)
int Thr_JbeFloat(ThrHandle Var1, float Var2)

These functions read and write thread-safe variables:

void Thr_SetInt(ThrHandle Destination, int Source)
void Thr_SetFloat(ThrHandle Destination, float Source)
void Thr_SetVec(ThrHandle Destination, vector Source)
void Thr_SetClr(ThrHandle Destination, color Source)

int Thr_GetInt(ThrHandle Var)
float Thr_GetFloat(ThrHandle Var)
vector Thr_GetVec(ThrHandle Var)
color Thr_GetClr(ThrHandle Var)

These are simple arithmetic increment and decrement functions:

void Thr_IncInt(ThrHandle Var)
void Thr_IncFloat(ThrHandle Var)
void Thr_DecInt(ThrHandle Var)
void Thr_DecFloat(ThrHandle Var)