Uses a user defined C++ function to convert scalar node data into colour node data.
in | Mesh+Node_Data | Field data to be colour mapped. |
out_fld | Mesh+Node_Data | Output field with colour Node_Data. |
out_obj | DataObject | Directly renderable output object. |
The user_defined_datamap user macro takes a set of scalar Node data
and converts it into colour node data. This colour node data can be
included in a DataObject and input into a viewer. Since the AVS/Express
renderer uses this colour node data to directly colour the output this
effectively provides an alternative to using the standard AVS/Express
datamapping system. Directly creating colour node data allows the user
total control of how their data is colour mapping at the expense of
forcing the user to perform the whole datamapping process themselves.
The user_defined_datamap macro is setup so that it will always use the
C++ function UserDefinedFunc
.
The user_defined_datamap macro is intended to be used when you are first developing your own datamapping functions. The macro is hard-wired so that it always uses the first datamapping function. This reduces the complexity of the resulting macro and removes the need to decide which function to modify.
Developing new datamapping functions is reasonably straightforward
but does require some knowledge of C or C++ programming. To help get you
started we will look at a single datamapping function and see now it
operates. If you look in the datmp_fn.cxx
file you should
be able to find the following piece of code:
/*=====================================================================*/ /* Place user defined function here */ static inline void UserDefinedFunc(float val, float min, float width, float *rgb) { float norm_val, temp; float hsv[3]; norm_val = 0.6667 * NORMALIZE_VALUE; hsv[0] = 0.3333 + norm_val; hsv[1] = 1.0; hsv[2] = 1.0; convertHSVtoRGB(hsv, rgb); } /* End of user defined function */ /*=====================================================================*/
This function converts a single scalar value into a red, green and blue triplet. This conversion is done by mapping the input value to a hue and converting the HSV triplet into a RGB triplet. It returns this RGB triplet as an array of 3 floating point numbers. It does not return any other value. To summarise the UserDefinedFunc function has the following 3 input parameters and 1 output parameter:
val | Node data value to be converted. |
min | Minimum value of data range. |
width | Width of data range (i.e. max-min ) |
rgb | Output array that contains generated red, green and blue values. |
This function is always used by the user_defined_datamap macro to perform the datamapping. If you wish to modify the datamapping then you should begin by modifying this function. The main update loop expects that each datamapping function you write should have the parameters shown above. If the update loop is modified additional parameters can be added. However the parameters given here are really essential to the operation of the algorithm.
The main update loop calls this function for each node data value it finds. The update loop deals with accessing the input and output field structure and interacting with AVS/Express. This saves the programmer from having to deal with this. However it does mean that it is assumed that each datamapping function should only act on a single scalar value. The datamapping for one value must not depend upon other values.
Several utility functions and macros are provided. These are intended to ease the task of creating new datamapping functions. The details of these functions are shown below:
convertHSVtoRGB(float *hsv, float *rgb)
Converts a HSV triplet into a RGB triplet. All values should be in the range 0 to 1. In particular hue is represented as a value between 0 and 1, not 0 and 360 as is sometimes done.
convertRGBtoHSV(float *rgb, float *hsv)
Converts a RGB triplet into a HSV triplet. All values should be in the
range 0 to 1. In particular hue is represented as a value between 0 and 1,
not 0 and 360 as is sometimes done. Normally this function will not need
to be used. It is simply presented as the partner to the
convertHSVtoRGB()
function.
NORMALIZE_VALUE
Macro that returns the normalized value of the val
variable.
The min
and width
variables are used to perform the
normalization.
MIN(a, b)
Macro that returns the minimum of the two given parameters.
MAX(a, b)
Macro that returns the maximum of the two given parameters.
Generating colour node data in this way is a powerful technique
however it does suffer from a number of limitations that should be
pointed out. The most important is that creating or modifying datamap
functions requires some degree of C or C++ experience. The
project has been designed so that editing the source code is easy to do.
However changing the datamap functions requires the user to edit the
datmp_fn.cxx
file.
Another limitation is that this technique will normally increase the size of the input data. Colour data is represented by 3 floats for red, green and blue values. If we consider the worse case of the input data being bytes. This would result in the output data being 12 times as large as the input data. Whether this is important depends on the type and size of your data, and whether optimizations in the renderer mean that the colour node data is used directly.
The final limitation is that the user_defined_datamap macro does not use the standard AVS/Express datamapping system in any way. This is an intrinsic result of how the project was designed. However it does mean that none of the AVS/Express components that operate on the Datamap object can be used. These include the standard datamap editor and the Legend modules. Instead of using the standard datamap editor it is expected that uses will create user interfaces that are suitable to their own applications. A future update to this project will include a set of specialized Legend modules that work with the user_defined_datamap macro.
in
The input Field data for the user_defined_datamap user macro. This data should contain a least a single set of scalar Node Data. Vector Node Data can be present but will be ignored. The lower-level module DatamapFunctionCore is used to colour the Node_Data of the input field. This colour Node_Data is then recombined with the original Mesh (if present).
out_fld
The output field for the user_defined_datamap macro. This contains the
coloured Node_Data combined with the original Mesh (if present). The
coloured Node_Data is a vector of 3 float numbers which represents red,
green and blue intensities. The Node_Data has an id number of 667 which
indicates that the rendered should treat this node data as colour data.
Normally the out_obj
output will be used instead of this
output.
out_obj
The directly renderable output object of the user_defined_datamap macro. This contains the Field that contains the coloured Node_Data. This output can be directly connected to a viewer.
The User Macro user_defined_datamap uses the low-level module DatamapFunctionCore. It does not use any other utility macros.
Two example applications are provided with the DatamapFunction project. The DatamapFunctionEg application reads the hydrogen data-set and calculates an isosurface and orthoslice from this data. These are then coloured by two datamap_function user macros. You should be able to select between the various different datamapping functions. You should also be able to notice some stepping between different colours. This is particularly apparent with the banded datamap functions and is caused by the way that the renderer interpolates between widely different colours. It is particularly apparent in this example because of the low resolution of the data-set. This effect also occurs with the standard AVS/Express datamapping system.
The InterpolateDataEg example application shows one way of working around this problem. In this application the intep_data
module is used to interpolate between node data values and hence great a much higher resolution grid. This is then colour mapped by the datamap_function macro. This produces good results but does greatly increase the number of triangles that have to be displayed. A better solution would be to use the Scalar2Texture IAC project to apply a texture map to the scalar data. This technique does not suffer from these interpolation problems.
iac_proj/datmp_fn/dmfnmods.v contains the V definitions of the low-level module DatamapFunctionCore and the parameter block DatamapFunctionParams.
iac_proj/datmp_fn/dmfnmacs.v contains the V definitions of the Functional Macro DatamapFunctionFunc, the UI Macro DatamapFunctionUI and the User Macros datamap_function and user_defined_datamap.
iac_proj/datmp_fn/dmfnapps.v contains the V definitions of the Example Applications DatamapFunctionEg and InterpolateDataEg.
The low-level DatamapFunctionMods library containing the low-level DatamapFunctionCore module does not specify a process. By default the express process will be used.
Andrew Dodd, International AVS Centre
International AVS Centre Manchester Visualization Centre Manchester Computing University of Manchester Oxford Road Manchester United Kingdom M13 9PL