SGI Techpubs Library

IRIX 6.5  »  Books  »  Developer  »  
OpenGL Optimizer Programmer's Guide: An Open API for Large-Model Visualization
(document number: 007-2852-002 / published: 1998-06-09)    table of contents  |  additional info  |  download
find in page

Chapter 15. Utilities

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:

Error Handling and Notification

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() 


Installs an error-handling function.

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() 


Sets the threshold for error notification to one of the values that are listed in Table 15-1 for the enumerated type opSeverity.

Table 15-1. Error Priority Levels: Lowest to Highest

Value

Meaning

opDebug

Debug information

opInfo

Information and floating-point exceptions

opNotice

Warning

opWarn

Serious warning

opFatal

Fatal error

opAlways

Always print regardless of notification level


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.

Performance Indicators

The classes opStopWatch and opPerfPlot provide tools to monitor the performance of an application.

opStopWatch

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:

start()  

Starts or restarts the clock. The constructor calls start(), so without subsequent calls, all readings show elapsed time since construction of the class.

read() 

Returns the elapsed time since the last call to start().

getResolution() 

Returns the clock resolution in seconds.

opPerfPlot

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.

opx: A Template Class for Dynamic Arrays of Contiguous Elements

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.

Printing a Scene Graph

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.

Gathering Triangle Statistics

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.

Getting Statistics About Individual Elements: opTriStatsDispatch

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();
};

Methods in opTriStatsDispatch

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.

Getting Statistics About a Scene Graph: opTriStats

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”).

Methods in opTriStats

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.

Example of Using an opTriStats

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();


Example 15-1. Stats Print Out


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

Displaying Node Information

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.

Class Declaration for opInfoNode

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             
};

Methods in opInfoNode

draw () 

Renders text set by setText().

setText() and getText () 


Set and get the text to be rendered, which is held in the private variable info_text.

Example of Using an opInfoNode

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 ();
orig_root->addChild (infoNode);

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.

Observing OpenGL Modes

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.

Class Declaration for opGLSpyNode

The class has the following main methods:

class opGLSpyNode : public csShape
{
public: 
// Creating and destroying
opGLSpyNode();
virtual ~opGLSpyNode();

void setOn(opBool e) ;
void printStats();
};

Methods in opGLSpyNode

setOn() 

Toggles the reporting node.

printStats()  

Prints the current status.

Example of Using an opGLSpyNode

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);


Command-Line Parser: opArgParser

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.

Class Declaration for opArgParser

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);
}

Methods in opArgParser

defRequired(format, documentation, ...)  


Defines the syntax of required arguments. format is a string similar to those used by printf(); the symbols %d, %f, and %s denote the types integer, float, and string, respectively. documentation is a text string that describes the required arguments. A list of pointers to the variables that hold the command-line values follows. You can call defRequired() only once.

defOption(format, documentation, active, ...)  


Defines an optional argument, which may be a list of values and is preceded by a keyword string. format and documentation are similar to those used by defRequired(). The next parameter is a pointer to a Boolean variable that is true if this option is found on the command line. The remaining arguments are pointers to the variables that hold the values of the arguments.

scanArgs(argc, argv)  


Initiates parsing. scanArgs() returns only if the arguments match definitions, in which case the arguments are initialized. If arguments do not match the definitions. ScanArgs() prints a help message (based on the defined syntax) to the stream stderr and aborts execution.

OpenGL Optimizer Programmer's Guide: An Open API for Large-Model Visualization
(document number: 007-2852-002 / published: 1998-06-09)    table of contents  |  additional info  |  download

    Front Matter
    About This Guide
    Part I. Getting Started
    Part II. High-Level Strategic Tools for Fast Rendering
    Part III. Specific Tools for Fast Rendering
    Part IV. Managing and Rendering Higher-Order Geometric Primitives
    Part V. Traversers, Low-Level Geometry Processing, and Multiprocessing
    Part VI. Utilities and Troubleshooting
    Part VII. Appendices
    Glossary
    Index


home/search | what's new | help