This allows users to alter algorithms used by C++ code and makes it easy to access complicated functions (such as noise, texture maps or volume primitives) through the simple VEX interface.
The CVEX_Context class is used to handle the interface between C++ and VEX. The CVEX_Context handles
VEX has a run-time optimizer which optimizes the loaded code based on the parameters passed to the code. This means that if the parameters to the code change, the function needs to be reloaded.
On the other hand, if the parameters are constant, the same CVEX_Context may be re-used to perform evaluation on different input data. For example
// Run the same VEX function on several different color planes CVEX_Context ctx; CVEX_Value *v_clr; CVEX_Value *v_plane; initializeParameters(ctx); ctx.load(...); for (plane = 0; plane < num_planes; plane++) { // Set the input parameter to the color value for the current plane if (v_clr = ctx.findInput("iclr", CVEX_VECTOR3)) v_clr->setData( color_planes[plane], plane_size ); // Set the output parameter to the color value for the current plane if (v_clr = ctx.findOutput("oclr", CVEX_VECTOR3)) v_clr->setData( color_planes[plane], plane_size ); // Set the variable for the current plane if (v_plane = ctx.findInput("plane", CVEX_INTEGER)) v_plane->setData( &plane, 1 ); ctx.run(plane_size, true); }
export are available with in HDK_CVEX_Outputs.When building a CVEX interface, you have the opportunity to override VEX function parameters with your own values. This allows you to pass information from your code to the user's VEX function.
Prior to calling CVEX_Context::load(), your code must declare all possible C++ parameter names/types that you want to make available to the VEX function. This is done by calling CVEX_Context::addInput().
The easiest way to add an input is to declare the input by name, type and value. For example:
UT_Vector3 P[] = { UT_Vector3(1,0,0), UT_Vector3(0,1,0) } myContext.addInput("P", CVEX_VECTOR3, P, 2);
If the user VEX function has a vector P parameter, then its value will be overridden by the vector array you've passed in.
In some cases, it can be expensive to compute the input parameter values. It's possible to defer the assignment of the value until after the function has been loaded. You still need to declare the variable before calling CVEX_Context::load(), but after the function has been loaded, you can call CVEX_Context::findInput() to see if the input actually exists in the user function.
CVEX_Value *parm; UT_Vector3 P[] = { UT_Vector3(1,0,0), UT_Vector3(0,1,0) } UT_Vector3 N(0, 0, 1); // Declare the possible inputs myContext.addInput("P", CVEX_VECTOR3, true); myContext.addInput("N", CVEX_VECTOR3, false); // Load the function myContext.load(argc, argv); // Bind the values if needed if (parm = myContext.findInput("P", CVEX_VECTOR3)) parm->setData(P, 2); if (parm = myContext.findInput("N", CVEX_VECTOR3)) parm->setData(&N, 1);
If you declare a parameter but neglect to assign data to the parameter, CVEX_Context::run() will fail to run.
String parameters require special handling. For these parameters, you need to pass in a UT_StringArray of values. If the array should contain a single string for uniform parameters, or a value per array entry for varying parameters.
export parameter can be read after you call CVEX_Context::run(). However, to do this, you need to set the variable data to a local buffer before running the VEX code.
You can find export parameters by name (CVEX_Context::findOutput()) or you can get a list of all outputs (CVEX_Context::getOutputList()). These methods should be called after the VEX function has been loaded. At this time, you can also query whether the parameter will be uniform or varying by calling CVEX_Value::isVarying().
uniform data buffer to a varying output, this may result in a run-time crash.
#include <MOT/MOT_Director.h> int main(int argc, char *argv) { MOT_Director::installFullCVEX(); ... }
A more complicated example can be seen at CVEX/cvexsampleC (with corresponding VEX code CVEX/testvfl).
1.5.9