FreeVR: Virtual Reality Integration Library |
|
FreeVR: Function Reference(ie. Reference Manual)February 29, 2024 for FreeVR Version 0.7eWritten by Bill Sherman IntroductionThis guide is a supplement to the Application Development Guide. It contains a list of the FreeVR functions available to the application programmer, along with a brief description of each. The functions are broken down into the following categories:
A complete index of functions and macros is also provided: The FreeVR Tutorials package provides an introduction to the most important of the functions in a gentle step by step manner. The FreeVR Function naming schemeAs an aid for the FreeVR programmer to more rapidly figure out what a function does, or make an educated guess for the name of a desired function, FreeVR has adopted a function naming scheme for which all functions should follow. Unfortunately, some of the naming rules conflict with one another, and in these cases a precedence determination is made for each individual function.
If anyone disagrees with these rules, or whether a particular function
does not follow these rules, and therefore should be renamed: now is
the time to state your case (ie. before we get to version 1.0).
The rules for FreeVR type names are similar to the function scheme. Of course, types are much simpler, so generally consist only of the "vr" prefix, and then a name that begins with an upper case letter. FreeVR types are defined generally for multi-valued collections of data, such as a 4x4 Homogeneous matrix used for graphics operations — vrMatrix. For functions that return single values (such as the value of a button or valuator), a basic int or double type is used. Many of the FreeVR types store all the values as a single array of doubles in field "v". Common types used in VR applications include:
NOTE: Because the types vrPoint and vrVector have the same internal representation, one can be converted to the other through a simple type-cast. However, there is a good reason why both types exist. And that reason is that mathematically speaking, they are different quantities. The difference basically amounts to how each 3-quantity array is extended when converted to a 4-quantity entity that will be multiplied by a 4x4 homogeneous matrix — a point has a "1" as the fourth value, while a vector has a "0". NOTE: The use of vrEuler is not recommended. This type and related functions are provided only as a convenience for porting applications originally written with libraries that make use of Euler angles. There is one exception to this rule, and that is in the use of the billboarding functions (vrRenderGetBillboardAngles3d & vrRenderGetBillboardAnglesAd). In these cases, the relationship between the user and some location in space is returned as Euler angles which can be formulaically fed into OpenGL calls to rotate objects to face the user. Along with the above types, FreeVR defines some "macro" values for accessing type subelements in a clear way. These are:
System Operation FunctionsThe functions for controlling the system are used to configure, start, stop, and otherwise setup the application. Most of these functions will appear in every FreeVR application. A minimal VR application using these functions is demonstrated below — not yet.
The syntax is simply: vrStart(); The syntax is: vrConfigure(argc, argv, argp);The first two arguments are exactly the same format as the two arguments of main(). This is done to allow the programmer to simply pass the argc and argv values directly from main to vrConfigure.
The third argument is ...
NOTE: future versions of FreeVR may require this call rather than allowing it as an option. Therefore, it is best to include this call in the simulation loop, unless there is some specific reason which precludes its usage. The syntax is: vrFrame(); The syntax is simply: vrExit(); The syntax is: vrSystemSetName(char *description_string); The syntax is: vrSystemSetAuthors(char *description_string); The syntax is: vrSystemSetExtraInfo(char *description_string); The syntax is: vrSystemSetExtraInfo(char *description_string); The syntax is: vrCallbackCreate(func, nargs, arg1, ... argN);The first argument is the function to be called. This function should not return a value (ie. be type "void()"). The second argument is the number of arguments to pass to the callback function (currently limited to the range of [0..5]). The rest of the arguments are the arguments that will be passed to the callback function each time it is invoked.
Note that the callback function will always be called with the
same argument values. However, it is possible to pass a pointer
into shared memory as one of the arguments, allowing the programmer
to share the same data between callback functions and the primary
process.
The syntax is: vrFunctionSetCallback(operation, callback);The first argument is one of the following defined integers: The syntax is: vrSystemSimCategory(int category);where "category" is either "1" or "2". NOTE: time for each category is what is measured up until the point when the category is set (i.e. when this function is called, it is the operations that have already occurred that will be counted as part of the given category). The time from the last call to vrSystemSimCategory() to the end of the current frame is added to the statistics for category-1. The syntax is: void *pointer = vrShmemAlloc(size); void *pointer = vrShmemAlloc0(size);Where "size" is an integer indicating the size of the desired memory block in bytes. A pointer to the new memory block is returned. It is good coding practice to type-case the returned value to the proper array or pointer type. The syntax is: char *new_string = vrShmemStrDup(string);Where "string" is a character array or pointer with a C-style string. The syntax is: vrShmemFree(pointer); The syntax is: vrShmemInit(size);Where "size" is the amount of memory (in bytes) that should be set aside for the shared memory arena. Functions to Read and Document InputsThe functions for reading inputs are used to provide a means by which the user can interact with the system, to affect the state of the virtual world, and/or travel through it. For each input type there is also a function that can be used to describe how that input is used. While not required, the use of these functions is strongly encouraged in order to provide users with a live, quick-reference of how to operate your program. This information can be displayed on any of the rendering screens by pressing the period/delete (./del) key on the numeric keypad (which toggles the information on and off). The three common FreeVR-input types are:
The functions that return single-value inputs all begin with "vrGet" followed by one of the FreeVR-input types, and then the word "Value" or the word "Delta". The "Value" functions return the exact value of the input at the time of the call. The "Delta" versions return the difference between the current value, and what the value was the last time the input was read (either via a "value" or via a "delta" function call). Functions that return complex types such as a vrMatrix use pointers for passing the values. This saves a little time, but also reduces the need for functions to allocate and deallocate the memory for the type on each call. Thus, for such functions, FreeVR expects the memory to be pre-allocated, and will place the return value there, and also give the pointer as the function's return value, so the function can be used as an argument to another function. The names of these functions will always have the name of the return type immediately after the initial "vr" moniker. So, a function that gets a 6-sensor value and returns a vrMatrix type will have the name vrMatrixGet...() instead of vrGetMatrix...(). The 6-sensor form of input also has the unique feature of being relative to a particular coordinate system. The two possible coordinate systems that can be requested are that of the real-world, and of the virtual world. When an application begins, these two coordinate systems are typically coincident. The user-travel functions (described below) can be used to change the relative position between the real and virtual worlds. The real-world coordinate system is defined by the FreeVR configuration file. A typical CAVE facility sets the origin at the center of the floor, with the positive-X axis pointing to the right (when facing the front wall), and the positive-Y axis pointing up. (The positive-Z axis thus points away from the front wall in accordance to the right-hand rule.) Because the FreeVR library allows each user to have their own, independent position in the virtual world, the functions that provide the position of a user's virtual world coordinate system require an additional argument to specify which user.
The syntax is: int button_exists = vrInputSet2switchDescription(input number, string);where the value returned indicates whether that button exists on the current system configuration. (If the button did not exist, a dummy button will be created, though the user will not be able to provide an input.) The "input number" argument specifies which input of type "2switch" to describe. The syntax is: int button_value = vrGet2switchValue(input number); int button_delta = vrGet2switchDelta(input number);The "input number" argument specifies which input of type "2switch" to access. The syntax is: int valuator_exists = vrInputSetValuatorDescription(input number, string);where the value returned indicates whether that valuator exists on the current system configuration. (If the valuator did not exist, a dummy button will be created, though the user will not be able to provide an input.) The "input number" argument specifies which input of type "2switch" to describe. The syntax is: double valuator_value = vrGetValuatorValue(input number); double valuator_delta = vrGetValuatorDelta(input number);The "input number" argument specifies which input of type "valuator" to access. The syntax is: int sensor_exists = vrInputSet6sensorDescription(input number, string);where the value returned indicates whether that sensor exists on the current system configuration. (If the sensor did not exist, a dummy sensor will be created, though the user will not be able to provide an input.) The "input number" argument specifies which input of type "6sensor" to describe. The syntax is: vrMatrix *transform_value = vrMatrixGet6sensorValues(matrix *, input number);The "matrix *" argument is a pointer to memory allocated as a vrMatrix type. This memory will be overwritten with the resultant data, and the same pointer value will be given as the return value. The "input number" argument specifies which input of type "6sensor" to access. The syntax is: vrVector *vector_value = vrVectorGetRWFrom6sensorDir(vector *, input number, direction); vrVector *vector_value = vrVectorGetVWFromUser6sensorDir(vector *, user number, input number, direction);Where the vector returned is a unit vector pointing in the same direction as one of the 6 cardinal directions from the sensor — as specified in the last argument. The input number in both cases is simply the choice of which "6sensor" to access, and in the second of the two functions the second argument specified the number of the user from which to obtain the relative position between the real and virtual worlds. In most applications, individual users are not treated any differently, and thus user 0 will work fine. The last argument, specifying the cardinal direction is done by giving one of six enumerated values: The syntax is: vrPoint point_value = vrPointGetRWFrom6sensor(point *, input number); vrPoint point_value = vrPointGetVWFromUser6sensor(point *, user number, input number);The input number in both cases is simply the choice of which "6sensor" to access, and in the second of the two functions the second argument specified the number of the user from which to obtain the relative position between the real and virtual worlds. In most applications, individual users are not treated any differently, and thus user 0 will work fine. The use of Euler angles though, can be problematic, as they introduce singularities when certain rotations are performed leading to ambiguities in the values. This function is provided only as a convenience for people porting applications from other libraries that rely on Euler angles. The syntax is: vrEuler euler_value = vrEulerGetRWFrom6sensor(euler *, input number); vrEuler euler_value = vrEulerGetVWFromUser6sensor(euler *, user number, input number);The input number in both cases is simply the choice of which "6sensor" to access, and in the second of the two functions the second argument specified the number of the user from which to obtain the relative position between the real and virtual worlds. In most applications, individual users are not treated any differently, and thus user 0 will work fine. The "euler" argument is a pointer to existing memory allocated for a vrEuler type. Note that while the name "Euler" refers only to how the rotational component of a 6sensor's position, in FreeVR the vrEuler type also contains the translational component. The two components are stored in two separate array fields within the vrEuler structure: "r[3]" for rotation, and "t[3]" for translation. The order for the translation elements is: x,y,z. The values of VR_X, VR_Y, and VR_Z can be used for clarity. The order for the rotational elements is: azimuth, elevation, roll. The values VR_AZIM, VR_ELEV, and VR_ROLL can likewise be used for clarity. Functions to Control the RenderingThis group of functions can be called from within the visual rendering process to affect how things are rendered. Most of them deal with changing the active coordinate system, with rendering actions that follow taking place in the altered state. One deals with the actual rendering of an object (text), because this can differ between instantiations of OpenGL, based on the windowing system, and a couple provide default renderings of world rendering.
The syntax is: vrRenderCategory(int category);where "category" is either "1" or "2". NOTE: time for each category is what is measured up until the point when the category is set (i.e. when this function is called, it is the operations that have already occurred that will be counted as part of the given category). The time from the last call to vrRenderCategory() to the end of the current frame is added to the statistics for category-1. The syntax is: vrRenderText(render-info, string);The "render-info" argument is a handle passed to the draw routine by FreeVR, and contains relevant information for rendering the particular frame to a particular eye. The "string" argument is a standard C-style pointer to a null-terminated array of characters. To position the string, the glRasterPos3f(x, y, z) OpenGL function must first be called. Also, it is very important to note that the color of the text must be set prior to calling glRasterPos3f().
The default font is "fixed" on X11 systems. This can be
changed on a per-window or per-system basis in the FreeVR configuration
file with the "font=<font-name>" argument. For a list of
available fonts run "xlsfonts". Two other common choices are
"12x24" and "10x20" when a font larger than the default
is desired.
This function is often used to render a pointer emanating from the end of a handheld device. The syntax is: vrRenderTransform6sensor(render-info, input number);The "render-info" argument is a handle passed to the draw routine by FreeVR, and contains relevant information for rendering the particular frame to a particular eye. The "input number" argument specifies which input of type "6sensor" to access. This function is generally used once in the visual render callback at the point where all the ensuing rendering is of objects considered part of the virtual world. It is used in conjunction with the "User Travel" functions described in the next section. The syntax is: vrRenderTransformUserTravel(render-info);The "render-info" argument is a handle passed to the draw routine by FreeVR, and contains relevant information for rendering the particular frame to a particular eye. Basically all that needs to be done is to call the function, and the values of three angles will be returned. From these angles, it is an easy process to rotate the OpenGL matrix stack such that subsequently rendered objects (until the next glPopMatrix() call) will be reoriented based on the location of the user. In the case of cylindrically rendered billboards, only the azimuth angle is used, and in the case of spherically rendered billboards, both the azimuth and elevation values are used. NOTE, the roll value is also returned, but very few applications require its use. The syntax (and common usage) is: vrRenderGetBillboardAngles3d(rendinfo, &angles, object_xloc, object_yloc, object_zloc); glRotatef(angles.r[VR_AZIM], 0.0, 1.0, 0.0); glRotatef(angles.r[VR_ELEV], 1.0, 0.0, 0.0); /* use only for spherical billboarding */NOTE that the angles are always returned via a vrEuler angles type (the "&angles" argument), and that the 3d and Adsuffix refers to how the location of the object are passed to the function.
NOTE also that this function does not adhere to the naming convention
in which functions returning a complex type start with the name of
the type.
In this case the fact that this is a class of render function takes
precedence.
One situation in which this can be useful is when two or more compatriots are working together on a task, each with their own hand-held user interface controller (e.g. "wand"). For the non-tracked users to best use their controllers, they will need to be interfacing with widgets/gadgets that are rendered relative to their particular position. Thus, the application should (and can) accommodate this by rendering this portion of the virtual world from that user's perspective. The syntax (and common usage) is: vrRenderPushPerspFrom6sensor(rendinfo, USER2_HEAD); <render user #2's widgets> vrRenderPopPersp(rendinfo);NOTE that vrRenderPushPerspFrom6sensor() will return "true" if is successfully performs its operation. Failure would be the result of a stack overflow. The depth of the stack is set by the library value VR_MAXPERSPDEPTH, and is currently set to 8. In practice, it should not be necessary to go deeper than 1. This function is seldom used, and in those cases where it is used, it is typically for debugging purposes, and could perhaps be used for a minimal (and probably not desirable) user interface. The syntax is: vrRenderTransformWindow(render-info);The "render-info" argument is a handle passed to the draw routine by FreeVR, and contains relevant information for rendering the particular frame to a particular eye. The syntax is: vrRenderNullWorld(render-info);The "render-info" argument is a handle passed to the draw routine by FreeVR, and contains relevant information for rendering the particular frame to a particular eye. The syntax is: vrRenderDefaultSimulator(render-info);The "render-info" argument is a handle passed to the draw routine by FreeVR, and contains relevant information for rendering the particular frame to a particular eye. The syntax is: vrRenderSetWindowContext(render-info, (void *)graphics_context); void *gfx_context = vrRenderGetWindowContext(render-info);The "render-info" argument is a handle passed to the draw routine by FreeVR, and contains relevant information for rendering the particular frame to a particular eye. Math FunctionsThere are many math functions built into the FreeVR library. These functions typically deal with the manipulation of complex types such as matrices, vectors, points, Euler angles, and even quaternions. The time operations also fall into this category. Only a subset of the most commonly used functions are listed and described here. For a full list of functions look in the vr_math.h header file. If you feel one of these functions should be described here, send me mail.
The syntax is: double length = vrVectorLength(vrVector *vec);Where the length of the single argument is calculated, and returned as a double precision float. The syntax is: vrVector *dest = vrVectorNormalize(dest vector *, src vector *);Where "dest vector *" points to the memory of the vector to be set, and "src vector *" points to the vector to be normalized. The normalized vector is placed in the memory pointed to by the first argument. The returned vector result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for the destination and source vectors to
reference the same memory.
The syntax is: vrVector *result = vrVectorSubtract(result vector *, src1 vector *, src2 vector *);Where "dest vector *" points to the memory of the vector to be set, and the argument "src2 vector *" will be subtracted from the vector at "src1 vector *". The returned vector result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for any (and all) of the vector pointers to
refer to the same memory.
The syntax is: vrVector *result = vrVectorFromTwoPoints(result vector *, src point1 *, src point2 *);Where "result vector *" points to the memory of the vector to be set. The arguments "src point1 *" and "src point2 *" point to the memory of points 1 and 2 respectively.
The returned vector result is a duplicate of the pointer given as the
first argument.
The syntax is: vrVector *result = vrVectorAddScaledVectors(result vec *, src vec1 *, src vec2 *, scale1, scale2);Where "result vec *" points to the memory of where the result should be placed. The arguments "src vec1 *" and "src vec2 *" point to the two vectors to be summed, and "scale1" and "scale2" are the multiplication values for each of the summands respectively. The returned vector result is a duplicate of the pointer given as the first argument. NOTE: if the intent is to add a vector to a location (ie. point), then it is better to use the function vrPointAddScaledVector().
NOTE that it is safe for any (and all) of the vector pointers to
refer to the same memory.
The syntax is: vrVector *result = vrVectorScale(vector *, scale);Where "vector *" is a pointer to the vector's memory, and "scale" is the multiplicand. The returned vector result is a duplicate of the pointer given as the argument.
NOTE that unlike many of the other functions, the vector operand is
modified in place.
The syntax is: double vrVectorDotProduct(vector1 *, vector2 *);Where "vector1 *" and "vector2 *" point to the memory locations of the two vectors that are to be dotted.
NOTE that whenever a vector from the origin to a point is needed for
an operation such as the dot-product, it is often convenient to
simply type-cast the vrPoint to a vrVector.
This type-casting is possible because points and vectors have the
same internal representation in FreeVR.
The syntax is: vrVector *result = vrVectorCrossProduct(result vector *, vector1 *, vector2 *);Where "result vector *" points to the memory where the resultant vector values should be placed. The arguments "vector1 *" and "vector2 *" refer to the two multiplicands of the operation. The returned vector result is a duplicate of the pointer given as the first argument.
Note that it is safe to have either of the operand vectors
refer to the same memory as the resultant vector.
The syntax is: vrVector *result = vrVectorTransformByMatrix(result vector *, src vector *, matrix *);Where "result vector *" points to the memory where the resultant vector values should be placed. The "src vector *" operand points to the memory of the initial vector to be transformed, and "matrix *" points to the vrMatrix with the transformation. The returned vector result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for the result and src pointers to reference
the same memory.
The syntax is: vrPoint *result = vrPointTransformByMatrix(result point *, src point *, matrix *);Where "result point *" is a pointer to the memory where the resultant point values should be placed. The "src point *" operand points to the memory of the initial 3-D point to be transformed, and "matrix *" is a pointer to the vrMatrix with the transformation. The returned vector result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for the result and src pointers to reference
the same memory.
The syntax is: vrPoint *result = vrPointTransformByQuat(result point *, src point *, quaternion *);Where "result point *" is a pointer to the memory where the resultant point values should be placed. The "src point *" operand points to the memory of the initial 3-D point to be transformed, and "quaternion *" is a pointer to the vrQuat with the transformation. The returned point result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for the result and src pointers to reference
the same memory.
The syntax is: vrPoint *result = vrPointGetTransFromMatrix((vrPoint *)point, (vrMatrix *)matrix);Where "point" is a pointer to the memory where the resultant point values should be placed. The returned point result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for the result and src pointers to reference
the same memory.
The syntax is: vrMatrix *result = vrMatrixSetTransFromVector((vrMatrix *)matrix, (vrVector *)vector);Where "matrix" is a pointer to the memory where the resultant matrix values should be placed. The returned matrix result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for the result and src pointers to reference
the same memory.
The syntax is: vrVector *result = vrVectorGetTransFromMatrix((vrVector *)vector, (vrMatrix *)matrix);Where "vector" is a pointer to the memory where the resultant matrix values should be placed. The returned vector result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for the result and src pointers to reference
the same memory.
The syntax is: vrPoint *result = vrPointAddScaledVector(result point *, src point *, vector *, scale);Where the "result point *" points to the memory where the new location value should be placed, "src point *" points to the location of the current point, "vector *" points to the vector values, and scale is a double precision floating point number. The returned point result is a duplicate of the pointer given as the first argument.
NOTE that it is safe for the result and src pointers to reference
the same memory. In this case that point will be moved by the
scaled vector.
The syntax is: vrMatrix *result = vrMatrixSetIdentity(matrix *); Where "matrix *" points to the memory of the matrix to be set.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixSetTranslation3d(matrix *, x, y, z); Where "matrix *" points to the memory of a vrMatrix structure in which to place the new values. The arguments "x", "y", and "z" are double precision floating point numbers of the translation transformation.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixSetTranslationAd(matrix *, array); Where "matrix *" points to the memory of a vrMatrix structure in which to place the new values. The argument "array" is a three element array of double precision floating point numbers of the translation transformation, in the order of X, Y, and Z. The FreeVR defined values of VR_X, VR_Y, and VR_Z can be used to index the proper elements in the array.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixSetRotationId(matrix *, axis, theta); Where "matrix *" points to the memory of a vrMatrix structure in which to place the new values. The "axis" argument expects one of the defined values: VR_X, VR_Y, or VR_Z. The "theta" argument is the amount of the rotation given in degrees.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixSetRotation4d(matrix *, x, y, z, theta); Where "matrix *" points to the memory of a vrMatrix structure in which to place the new values. The "x", "y", and "z" arguments define the axis about which the rotation is to be performed, and the "theta" argument is the amount of the rotation given in degrees.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixSetRotationAd(matrix *, array); Where "matrix *" points to the memory of a vrMatrix structure in which to place the new values. The "array", argument defines both the axis about which the rotation is to be performed, and the amount of the rotation. The axis values are accessed using the VR_X, VR_Y, and VR_Z defined values as indices into the array. The "theta" value is indexed using the VR_W predefined value.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixSetRotationAd(matrix *, (vrQuat *)quaternion);Where "matrix *" points to the memory of a vrMatrix structure in which to place the new values. The "quaternion" argument is also passed by reference as a pointer to an existing vrQuat type containing the 4-tuple components of the quaternion.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixSetFromQuat(matrix *, (vrQuat *)quaternion);Where "matrix *" points to the memory of a vrMatrix structure in which to place the new values. The "quaternion" argument is also passed by reference as a pointer to an existing vrQuat type containing the 4-tuple components of the quaternion.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrQuat *result = vrQuatSetFromMatrix(quat *, (vrMatrix *)matrix);Where "quat *" points to the memory of a vrQuat structure in which to place the new values. The "matrix" argument is also passed by reference as a pointer to an existing vrMatrix type containing the 4x4 array of the matrix.
The returned quaternion value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixSetScale3d(matrix *, x, y, z); Where "matrix *" points to the memory of a vrMatrix structure in which to place the new values. The "x", "y", and "z" arguments define the amount of scaling to be performed along each axis. A negative value for an axis will flip the transformation about that axis.
The returned matrix value is a duplicate of the pointer given as
the argument.
Mleft' = Mright * Mleft The syntax is: vrMatrix *result = vrMatrixPreMult(matrix1 *, matrix2 *); Where "matrix1" is the matrix to be modified by the transformation of "matrix2". Thus, the value of "matrix1" will be changed after returning from the function, and the returned matrix value is a duplicate of the pointer given as the argument. This function is used by first creating a specific transformation with other functions, and then using this function to apply that transformation to another matrix. There are also several functions that combine both operations into a single function call. These functions have names similar to those above, but beginning with vrMatrixPre instead of vrMatrix, and the initial matrix argument is modified instead of replaced. Those functions are: vrMatrix mat_left = vrMatrixPreTranslate3d(mat_left, x, y, z); vrMatrix mat_left = vrMatrixPreRotateId(mat_left, axis, theta); vrMatrix mat_left = vrMatrixPreRotate4d(mat_left, x, y, z, theta); vrMatrix mat_left = vrMatrixPreScale3d(mat_left, x, y, z); Mleft' = Mleft * Mright The syntax is: vrMatrix *result = vrMatrixPostMult(matrix1 *, matrix2 *); Where "matrix1" is the matrix to be modified by the transformation of "matrix2". Thus, the value of "matrix1" will be changed after returning from the function, and the returned matrix value is a duplicate of the pointer given as the argument. This function is used by first creating a specific transformation with other functions, and then using this function to apply that transformation to another matrix. There are also several functions that combine both operations into a single function call. These functions have names similar to those above, but beginning with vrMatrixPost instead of vrMatrix, and the initial matrix argument is modified instead of replaced. Those functions are: vrMatrix mat_left = vrMatrixPostTranslate3d(mat_left, x, y, z); vrMatrix mat_left = vrMatrixPostRotateId(mat_left, axis, theta); vrMatrix mat_left = vrMatrixPostRotate4d(mat_left, x, y, z, theta); vrMatrix mat_left = vrMatrixPostScale3d(mat_left, x, y, z); The syntax is: vrMatrix *result = vrMatrixInvert(dst_matrix *, src_matrix *); vrMatrix *result = vrMatrixInvertInPlace(src_matrix *);
Where "dst_matrix" is the matrix to be modified by the inversion
of "src_matrix".
Thus, the value of "dst_matrix" will be changed after returning from
the function, and the returned matrix value is a duplicate of the
pointer given as the argument.
The syntax is: vrTime time = vrCurrentSimTime();
Where no arguments are required, and the value returned is typed as
a vrTime value.
However, vrTime is currently implemented as a double,
so the value returned can be used in any place a floating point
number can be used.
As access to individual elements of a vrMatrix are typically not required at the application-programmer level, this macro is intended for the internal use of the FreeVR library. However, there may be occasions for using it in an application. The syntax is: double element = VRMAT_ROWCOL(row, col); Where the "row" and "col" arguments are values between 0 and 3, inclusive, but generally accessed by the values: VR_X, VR_Y, VR_Z, and VR_W. The returned value of the specified element is a double precision floating point number. NOTE: because VRMAT_ROWCOL is a macro there is no checking to verify the appropriateness of the arguments, so invalid values for "row" or "col" may cause unforeseen problems. Special Math Functions for Converting Between VW & RWThis collection of mathematical operations are expressly for the purpose of converting points, vectors and matrices between the real world and virtual world coordinate systems. Thus, if the location of a user's head is known in real-world values, there is a function to find the head's location with respect to the virtual world coordinate system. The relationship between the real and virtual world coordinate systems may be specific to each user. This is because FreeVR applications can allow individual users to travel through the virtual world independently. Thus, as with the User-travel functions, a user number must be specified to indicate which virtual world transformation to use. Applications not designed to handle more than one user should simply specify user number 0, which exists in all configurations.
The syntax is: vrPoint *result = vrPointGetVWUserFromRWPoint(*vw_point, user_num, *rw_point); Where the first argument is a memory pointer to the vrPoint into which the virtual world coordinate values should be placed. The second argument is the number of the user whose travel matrix should be used (use '0' for applications that do not distinguish users). The third argument is the existing value for the point in real world coordinates. The returned point result is a duplicate of the pointer given as the first argument.
NOTE: The two vrPoint* arguments may safely point to the same
memory location, in which case the point will be changed from real
world coordinates to virtual world coordinates in place.
The syntax is: vrPoint *result = vrPointGetRWFromVWUserPoint(*rw_point, user_num, *vw_point); Where the first argument is a memory pointer to the vrPoint into which the real world coordinate values should be placed. The second argument is the number of the user whose travel matrix should be used (use '0' for applications that do not distinguish users). The third argument is the existing value for the point in virtual world coordinates. The returned point result is a duplicate of the pointer given as the first argument.
NOTE: The two vrPoint* arguments may safely point to the same
memory location, in which case the point will be changed from real
world coordinates to virtual world coordinates in place.
The syntax is: vrPoint *result = vrPointGetRWLocationFromMatrix(*rw_point, *matrix); Where, the first argument is a memory pointer to the vrPoint where the result should be placed, and the second argument is the vrMatrix from which to extract the values.
The returned point result is a duplicate of the pointer given as the
first argument.
The syntax is: vrPoint *result = vrPointGetVWFromUserMatrix(*vw_point, user_num, *matrix); Where, the first argument is a memory pointer to the vrPoint where the result should be placed, the second argument is the number of the user whose travel matrix should be used (use '0' for applications that do not distinguish users), and the third argument is the vrMatrix from which to extract the values.
The returned point result is a duplicate of the pointer given as the
first argument.
The syntax is: vrMatrix *result = vrMatrixGetRWFromUserHead(*matrix, usernum);Where the first argument is a memory pointer to the vrMatrix into which the values will be placed, and the second argument specifies which user's head position to extract. NOTE: "NULL" is returned if the given user does not exist, and the matrix pointed to by the first argument will not be affected.
The returned matrix value is a duplicate of the pointer given as
the argument.
The syntax is: vrMatrix *result = vrMatrixGetVWUserFromRWMatrix(*matrix, usernum, *rw_matrix); NOTE: this function is to be called from the simulation process. ... User Travel FunctionsFreeVR includes functions to move the virtual world relative to the real world — from the perspective of a user. These are the "User Travel Functions". These functions allow the programmer to rotate the virtual world relative to the real world, to translate it, to reset it to the identity operation, and to set it to any matrix desired. This is referred to as the "travel matrix" in this section. Calls to the User Travel functions are cumulative. That is, specifying a translation followed by a rotation results in a matrix with both operations integrated. All the User Travel functions perform pre-multiplies to the existing travel matrix. FreeVR is unique from other VR libraries in that it can keep track of multiple users (as specified in the configuration file). Therefore, it would not make sense for applications to be forced to move all users together, so the User Travel functions can affect any particular individual user. There is also the option to move all users as one, with the special "VR_ALLUSERS" tag. Note though that for users to move independently, the application must be specifically programmed to allow this.
The syntax is: vrUserTravelLockSet(user_num); [travel operations that should appear atomic] vrUserTravelLockRelease(user_num);Where "user_num" is an integer specifying which user should be moved, or the value VR_ALLUSERS to move everybody as one. The syntax is: vrUserTravelReset(user_num);Where "user_num" is an integer specifying which user should be moved, or the value VR_ALLUSERS to move everybody as one. The syntax is: vrUserTravelTranslate3d(user_num, x, y, z);Again "user_num" is the integer specifying the particular user that should be moved, or the value VR_ALLUSERS to move everybody as one. The "x", "y", and "z" arguments specify the distance to move along each of the Cartesian axes. The syntax is: vrUserTravelTranslateAd(user_num, (double *)xyz_array[]); vrUserTravelTranslateVec(user_num, (vrVector *)go_vector);Again "user_num" is the integer specifying the particular user that should be moved, or the value VR_ALLUSERS to move everybody as one. The "xyz_array" argument specifies the distance to move along each of the Cartesian axes as an array of three values in the order of X, Y, and Z. The syntax is: vrUserTravelRotateId(user_num, axis, theta);Again "user_num" is the integer specifying the particular user that should be moved, or the value VR_ALLUSERS to move everybody as one. Axis is an integer macro that declares which of the three primary Cartesian axes about which the rotation is performed: VR_X, VR_Y, or VR_Z. Theta is a double-precision floating point value (aka "double") specifying how much rotation should occur in degrees. The syntax is: vrUserTraveScale(user_num, (double)scale_factor);Again "user_num" is the integer specifying the particular user that should be moved, or the value VR_ALLUSERS to move everybody as one. The syntax is: vrMatrix matrix* = vrUserTravelTransformMatrix(user_num, matrix*);Again "user_num" is the integer specifying the particular user that should be moved, or the value VR_ALLUSERS to move everybody as one. The "matrix*" argument is a pointer to a variable of type vrMatrix. The same address of the vrMatrix pointer is returned as the result of this function. This is sometimes useful for using this function call as an argument of other functions. The syntax is: vrMatrix matrix* = vrMatrixGetUserTravel(matrix*, user_num);Once again, "user_num" is the integer specifying the particular user that should be moved, or the value VR_ALLUSERS to move everybody as one. And, as with vrUserTravelTransformMatrix() above, the "matrix*" argument is a pointer to a vrMatrix type where the value will be placed. Also, the pointer will be returned as the result of the function call to allow this function to be used as argument to another function that takes a vrMatrix argument. Debugging and Printing FunctionsThis collection of miscellaneous functions are frequently used to help debug a FreeVR application, or the FreeVR library. Most of them directly deal with printing text to a command shell. The FreeVR printing functions are designed to help indicate from which process each message is generated. This is done by color coding the outputs. Typically output from the main (ie. simulation) process is the default foreground text color, and text from other processes are colored based on specifications in the configuration file. It is worth noting that because the application user will typically be watching the VR displays, and not the command shells, print statement are only useful as a debugging tool, and not to print out constantly changing values. Therefore, efficiency of these functions was not a concern, and they are fairly inefficient. In fact, printing to the shell is always slow in C, and in FreeVR it is slower. Thus once the print statements have served their usefulness, it is wise to remove them from the compiled code.
The syntax is: if (vrDbgDo(debug_level)) { /* do debugging stuff here */ }
Where the one argument is the debug level at which the condition
should be satisfied.
The syntax is: vrDbgPrintfN(debug_level, format, args...);
Where the first argument is the debug level at which the condition
to print must be satisfied, and the format and any arguments
associated with the format following.
The format and following arguments are given exactly the same as
for the C printf() function.
The syntax is: vrPrintf(format, args...);Where the format and following args are given exactly as with the standard C printf() function. The syntax is: vrFprintContext(*fp, style);
Where the first argument is a pointer to an open FILE
stream, and the second argument is the style (ie. verbosity)
of how the information should be presented.
The syntax is: vrFprintConfig(fp, style);
Where the first argument is a pointer to an open FILE
stream, and the second argument is the style (ie. verbosity)
of how the information should be presented.
The syntax is: vrFprintInput(fp, style); Where the first argument is a pointer to an open FILE stream, and the second argument is the style (ie. verbosity) of how the information should be presented. Functions for Locking OperationsThe locking functions of FreeVR are very important for smooth operation in a multi-processor machine. The use of locks prevents separate processes/threads from reading and writing to the same section of memory at the same time, which would produce unknown (perhaps damaging) results. Whenever reading or writing to memory locations that are accessed from more than one process, locks should be used to guarantee safe reading and writing.
The syntax is: vrLock lock = vrLockCreate();Note that the vrLock type is a generic memory pointer, and thus does not require an additional specification to indicate that it is a pointer. The syntax is: vrLock lock = vrLockCreateName(name string);The function takes a standard C-string as the argument and returns a vrLock type. Note that the vrLock type is a generic memory pointer, and thus does not require an additional specification to indicate that it is a pointer. The syntax is: vrLockTrace(lock, state);The "lock" argument is the value returned by the call to vrLockCreate() creating the lock. The "state" argument is a boolean that indicates whether tracing should be activated (1) or deactivated (0). The syntax is: vrLockFree(lock);The "lock" argument is a value returned by a previous call to vrLockCreate(). The syntax is: vrLockWriteSet(lock);
Where the argument is the vrLock that is to be locked.
The syntax is: vrLockWriteRelease(lock);
Where the argument is the vrLock that is to be released.
The syntax is: vrLockReadSet(lock);
Where the argument is the vrLock that is to be locked.
The syntax is: vrLockReadRelease(lock);
Where the argument is the vrLock that is to be released.
The syntax is: vrLockReadToWrite(lock); Where the argument is the vrLock that is to be switched. Functions for Barrier OperationsThe barrier functions of FreeVR are also very important for smooth operation in a multi-processor machine. The use of barriers allows multiple processes doing related activities to synchronize their operation. This is especially important for the rendering processes. For example, the visual rendering processes should all swap front and back buffers at precisely the same moment. To operate correctly, a barrier must know how many processes are grouped together (a "barrier-group"). If there are less processes than the barrier expects, then it will hang waiting for the extra (non-existent) processes to reach the barrier. If there are more processes, then it will release the barrier before all the processes have arrived at the barrier point. Care must also be taken with barriers, to assure that no process is waiting for the other process to reach the same barrier while the other process is waiting for some other event from a process in the same barrier-group.
The syntax is: vrBarrier *barrier = vrBarrierCreate(context, name, clients);The function takes the context handle as the first argument, the name of the barrier (as an array of characters) as the second argument, and the number of clients in the group of processes that will use this barrier. A pointer to a vrBarrier type is returned. The syntax is: vrBarrierIncrement(barrier, increment);The function takes a pointer to the barrier, and ... The syntax is: vrBarrierDecrement(barrier, decrement);The function takes a pointer to the barrier, and ... The syntax is: vrBarrierSync(barrier);... The syntax is: int value = vrBarrierLastToSync(barrier);... The syntax is: int value = vrBarrierFirstToSync(barrier);... Special Functions for Performer library usageObviously, as of 2021, there's not much need to continue development of the Performer interface, so consider this a historical section.The Performer version of the FreeVR library requires one or two extra function calls to operate correctly within the scheme of how the Performer library works. Primarily, this requires calls to the pfSync() and pfFrame() Performer routines as part of the simulation loop, along with functions for initializing and terminating operation of Performer. There are also some additional FreeVR routines specifically for working with the Performer library. The primary two routines necessary are vrPfPreFrame() and vrPfMasterChannel(). The other functions listed in this section are also commonly used in Performer-FreeVR applications. NOTE: a special concern with Performer applications is that the coordinate system used by Performer differs from the standard OpenGL system. While OpenGL uses a Y-up convention, Performer uses a Z-up convention. Thus, to transform objects (eg. vrPoint, vrVector, vrMatrix) from one coordinate system to the other, a 90 degree rotation about the X-axis is required. For example, to read the location of the wand and convert into Performer coordinates: /* create the point variable */ vrPoint wand_point; /* create a conversion matrix */ vrMatrix *pos90x = vrMatrixSetRotationId(vrMatrixCreate(), VR_X, 90.0); /* read the wand location in Y-up coordinates */ vrPointGetVWFromUser6sensor(&wand_point, 0, WAND_SENSOR); /* convert the wand location to Z-up coordinates */ vrPointTransformByMatrix(&wand_point, &wand_point, pos90x); NOTE Further: I am now in the process of eliminating the need for the application programmer to deal with the conversion between Y-up and Z-up coordinate systems. However, please note that this is a transitional period for this, so to use the improved method, the function names have been altered slightly, and beginning with version 0.6a, the old functions names should be used to gain the new functionality. So if you skip the transition, all you'll need to do is remove your lines that manually convert from Y-up to Z-up coordinates. There are now new "Pf" versions of all the inputs that respond with sensor values. These functions pre-convert the values into Z-up coordinates (typically, one would use only the first 4 of these): vrPointGetRWFrom6sensor() — vrPfPointGetRWFrom6sensor() vrPointGetVWFromUser6sensor() — vrPfPointGetVWFromUser6sensor() vrVectorGetRWFrom6sensorDir() — vrPfVectorGetRWFrom6sensorDir() vrVectorGetVWFromUser6sensorDir() — vrPfVectorGetVWFromUser6sensorDir() vrMatrixGet6sensorValues() — vrPfMatrixGet6sensorValues() vrMatrixGet6sensorValuesDirect() — vrPfMatrixGet6sensorValuesDirect() vrMatrixGet6sensorValuesDirectNoLastUpdate() — vrPfMatrixGet6sensorValuesDirectNoLastUpdate() vrMatrixGet6sensorRawValuesDirect() — vrPfMatrixGet6sensorRawValuesDirect() vrVectorfGetRWFrom6sensorDir() — vrPfVectorfGetRWFrom6sensorDir() vrVectorfGetVWFromUser6sensorDir() — vrPfVectorfGetVWFromUser6sensorDir() vrPointfGetRWFrom6sensor() — vrPfPointfGetRWFrom6sensor() vrPointfGetVWFromUser6sensor() — vrPfPointfGetVWFromUser6sensor() vrEulerGetRWFrom6sensor() — vrPfEulerGetRWFrom6sensor() vrEulerGetVWFromUser6sensor() — vrPfEulerGetVWFromUser6sensor()And, the callback used to specify a DCS that transitions from the real world coordinate system to the virtual world has "_zup" appended to the name: vrPfDCSTransformUserTravel() — vrPfDCSTransformUserTravel_zup()And let me reiterate that all these new functions will go away with version 0.6a, and the old function names should again be used, but without the need for converting to Performer's Z-up coordinate system.
The syntax is: vrPfPreFrame();Calling vrPfPreFrame() must be done between calls to pfSync() and pfFrame(). The syntax is: vrPfPostFrame(void);Calling vrPfPostFrame() should be done after the call to pfFrame(). The syntax is: pfChannel *chan = vrPfMasterChannel(void);There are no arguments, and the returned value is a pointer to the master channel. This value need not be stored however, it can be used immediately, such as: pfScene *scene = createScene(); vrPfMasterChannel()->setScene(scene); The syntax is: vrPfDCSTransform6sensor(pfDCS *, sensor_num);The first argument is a pointer to the pfDCS node that will be altered, and the second argument the number of the 6-sensor. NOTE that any transformation value already in the pfDCS node will be overwritten. The syntax is: dcsnode->setTravFuncs(PFTRAV_CULL, vrPfDCSTransformUserTravelCB, NULL);Note that the arguments should be specified exactly as listed. The vrPfDCSTransformUserTravelCB() function is assigned as part of the CULL traversal, in order to make sure that the culling process takes the user travel transformation into account when pruning the world.
The syntax is: pfMatrix *mat = vrPfMatrixFromVrMatrix(pfMatrix *pfmat, vrMatrix *vrmat); vrMatrix *mat = vrMatrixFromPfMatrix(vrMatrix *vrmat, pfMatrix *pfmat);The first argument in both cases is the one that will receive the data, and the second argument is the matrix that will be copied. In both cases, the function will return a duplicate of the pointer to the first matrix argument.
Alphabetical Index Listing of Functions and Macros
© Copyright William R. Sherman, 2024. |