This chapter describes tools that, although they are helpful in an OpenGL Optimizer application, have little direct relationship to the main tasks discussed in previous chapters. The chapter has the following sections:
You can control error handling with error-handling classes. You can also control the level of importance of an error. The error-handling classes can be found in the file opNotify.h, along with useful comments.
These are the main error notification functions:
| opSetNotifyHandler() |
| |||||||||||||||
| opNotify() | Generates a notification, which can be selectively suppressed, depending on the notification threshold (a value of the enumerated type opSeverity listed in Table 15-1). | |||||||||||||||
| opSetNotifyLevel() |
Table 15-1. Error Priority Levels: Lowest to Highest
|
You can set the environment variable OP_NOTIFY_LEVEL to override the value specified in opSetNotifyLevel(). If you do set OP_NOTIFY_LEVEL, you cannot change the notification threshold in your application.
Once you set the notification threshold, only messages with a priority greater than or equal to the current level are printed or handed off to your program. Fatal errors cause the program to exit unless you install a handler by calling opSetNotifyHandler().
The notification level to opFPDebug has the additional effect of trapping floating-point exceptions such as overflows or operations on invalid floating-point numbers. Consider using a notification level of opFPDebug while testing your application, so that you will be informed of all floating-point exceptions.
The classes opStopWatch and opPerfPlot provide tools to monitor the performance of an application.
The opStopWatch class allows you to observe elapsed times as a program runs. It is not safe to use in a multi-threaded program.
These are the important methods of opStopWatch:
The opPerfPlot class allows you to graph timing measurements for events occurring in possibly more than one process that run on the same processor.
opPerfPlot provides strip charts of elapsed times along with moving-average and peak information. You can observe the output of an opPerfPlot by running the application opviewer, which uses the instance of opPerfPlot created by an opViewer to monitor frame times.
opPerfPlot also printd screen graph statistic. You can print the scene graph statistics from an opViewer by pressing the <S> key.
Instances of the template class opDvector are common in OpenGL Optimizer classes. A opDvector provides a convenient, fast, and flexible device for storing and manipulating sets of objects of any data type. The class defines a vector of arbitrary objects that you can treat syntactically as you would any one-dimensional vector in C or C++.
opDvector arrays grow dynamically, responding to the storage needs of your application. You control the “step size” for data storage expansion with the constructor or with the member function setExtension().The arrays extend such that the data elements of the opDvector are stored contiguously in memory. This allows you to pass a pointer to an element in a opDvector to a routine that is expecting the address of an array.
Nested opDvectors do not create a single multidimensional array of the template argument. For example, a opDvector<opDvector< int> > is not one piece of two-dimensional integer memory. Rather, nested opDvectors create arrays of opDvectors, and the nesting sequence ends at one-dimensional arrays of opDvectors.The example just given creates an array of opDvectors, and each lowest-level opDvector is an array of integers. At every level in the nesting sequence, each opDvector is independently dynamic.
The function opPrintScene(), which is declared in opGFXSpeed.h, prints a textual listing of the scene graph under a given a root node, provides some statistical details about triangles held in each of the csGeometry nodes in the graph, and prints out csGeoSet attribute bindings.
The two tools for gathering statistical information about triangles are opTriStatsDispatch, which acts on one element in a scene graph, and opTristats, which acts on the whole graph. The statistics accumulated by these classes help you tune a scene graph and can, for example, help you assess the effect of simplification or tristripping.
opTriStatsDispatch is a csDispatch that accumulates information about elements in a scene graph: the output from each call to the method apply(), which is inherited from csDispatch and thus acts on a node, is added to previously accumulated statistical information. The method print() provides a table of the information. The methods get*() provide individual values.
The traverser that accumulates triangle statistics is opTriStats, which is discussed in “Getting Statistics About a Scene Graph: opTriStats”.
The class has the following main methods:
class opTriStatsDispatch : public csDispatch
{
public:
opTriStatsDispatch(int histogramSize = 0);
~opTriStatsDispatch();
void print();
void reset();
int getGeoSetCount();
int getTriSetCount();
int getTriStripSetCount();
int getTriFanSetCount();
int getQuadSetCount();
int getPolySetCount();
int getTriCount()
int getTriSetTriCount()
int getTriStripTriCount();
int getTriFanTriCount();
int getQuadTriCount();
int getPolyTriCount();
int getTriStripCount() ;
int getTriFanCount() ;
int getQuadCount();
int getPolyCount();
float getLengthsMean();
int getLengthsMedian();
int getLengthsMode();
};
|
| apply() | Is inherited from csDispatch. It accumulates the appropriate statistics from any one of the following objects supplied as its argument: csNode, csShape, csGeometry, csTriSet, csTriStripSet, or csTriFanSet. | |
| print() | Prints a statistical summary for all the objects for which apply() was called, providing the accumulated values in a self-descriptive listing. | |
| reset() | Sets all the accumulators to zero. |
The class opTriStats is an opActionDispatch that traverses a scene graph applying an opTriStatsDispatch to every node, thus accumulating statistics for a whole scene graph (see “Traversing a Scene Graph and Applying a csDispatch: opDispatchAction”).
The methods perform the operations that are established by opTriStatsDispatch (see “Getting Statistics About Individual Elements: opTriStatsDispatch”).
| apply( node) | Traverses scene graph below node; accumulates scene graph statistics. |
The following lines of code, taken from the application opviewer, show a simple use of an opTriStats.
Get a root node for the graph. Here the graph comes from a file read by an opGenLoader. See “Saving and Loading Scene-Graph Files”). |
| csGroup *obj = loader->load( filename ); |
Make an opTriStats. |
| opTriStats stats; |
Use the inherited function apply() to get statistics on the scene graph. |
| stats.apply(obj); |
Print the results, for example, as shown in Example 15-1. |
|
printf(“Scene statistics:\n”); stats.print(); |
Scene statistics: opTriStats: csNodes: 321 triangles per node: 13 csShapes: 319 triangles per shape: 13 csGeoSets: 319 mean prim length: 1.447 max prim length: 7 vertices to pipe: 10155 triangles to pipe: 4263 vertices per triangle: 2.382 triangles per geoset: 13 csTriFanSets: 319 total fans: 2946 triangles: 4263 |
The class opInfoNode provides a simple mechanism to present textual information about nodes in the scene graph. For example, you might show a part name and number of a picked or highlighted node.
The class has the following main methods:
class opInfoNode : public csNode
{
public:
// Creating and destroying
opInfoNode();
~opInfoNode();
// Accessor functions
void setText (const char *text);
const char *getText () const
void setTextPosition (const csVec2f& _pos)
csVec2f getTextPosition () const
};
|
| draw () | Renders text set by setText(). | |
| setText() and getText () |
|
The few lines of code below illustrate how to use an opInfoNode to write the name of a node.
Add an opInfoNode under a scene graph root. |
| infoNode = new opInfoNode (); |
Write the name of a node of interest. |
|
infoNode->setText (node->getName()); |
A subsequent rendering traversal of the scene graph calls the opInfoNode draw method, and places the node name on the screen.
The opGLSpyNode is a csShape that you can place in the scene graph and switch on to monitor the current OpenGL status. When enabled, opGLSpyNode prints the information for the current rendering traversal to the command shell, and switches itself off.
The class has the following main methods:
class opGLSpyNode : public csShape
{
public:
// Creating and destroying
opGLSpyNode();
virtual ~opGLSpyNode();
void setOn(opBool e) ;
void printStats();
};
|
The code from opViewer.cxx, shown below, illustrates how to use the reporting node.
Create the node and place it in the scene graph. For this application, the node is a child of the csTransform that controls manipulation of the scene (see Figure 2-1 for the basic structure of an opViewer scene graph). |
| spy = new opGLSpyNode; pose->addChild(spy); |
Within opDefDrawImpl, the member function of opViewer turns the node on. |
| viewer->getGLSpy()->setOn(true); |
The opArgParser class provides an command-line parser for use with OpenGL Optimizer applications. Although the parser is convenient, its syntax is not consistent with UNIX conventions. The parser is not central to the OpenGL Optimizer API; it is not guaranteed to be supported in future releases.
From a shell, run a program that uses opArgParser by typing the program name, followed by a number of required arguments, and then any optional arguments. opArgParser makes programs easy to use because the syntax and documentation for arguments can be defined in a few lines.
For more information, and an example of a simple application with opArgParser, see the reference page opArgParser(3in). The header file inArgs.H also has extensive comments.
The class has the following main methods:
class opArgParser
{
public:
opArgParser();
~opArgParser();
void defRequired(char *format,char *documentation,...);
void defOption(char *format,char *documentation, bool *active,...);
void scanArgs(int argc,char **argv);
void helpMessage(char* message, char* name);
}
|
| defRequired(format, documentation, ...) |
| |
| defOption(format, documentation, active, ...) |
| |
| scanArgs(argc, argv) |
|