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

Appendix D. Scene Graph Tuning With the opoptimize Application

The opoptimize application illustrates the basic structure of a scene-graph tuning application. Scene graph tuning is typically done before rendering. As a result, opoptimize is usually used in batch processing mode. However, opoptimize does allow scene-graph rendering interactions using an opViewer (see “Viewing Class: opViewer”). The output of the application is typically a scene graph that can be easily manipulated in an application like opviewer, which was discussed in Chapter 2.

This chapter presents lines of code that are essentially the same as those of /usr/share/Optimizer/src/sample/opoptimize/main.cxx. Comments highlight OpenGL Optimizer features when they are used by the code, and direct you to detailed discussions that appear in this guide.

The main tools not included in opoptimize are tools for multiprocessing, which are discussed in Chapter 14, “Managing Multiple Processors.”

This appendix discusses opoptimize in the following sections:

Values Returned by Scene Graph Tools

When you use OpenGL Optimizer methods that construct scene graphs and csGeoSets, you must not use input pointers after the method call. Input objects may change as a result of applying the method or they may be included in the output. This may occur, for example, with the simplifiers, tessellators, and spatialization tools.

If an input object is included in the output, subsequent changes to the original input may affect the output object. For example, if you generate a level of detail node by simplifying a csGeoSet and you want to use color to distinguish the levels of detail, but the simplifier could not change the input because of the criteria you used, then a color change applied to input will also change the color of the output.

If you want to use an input scene graph or csGeoSet after a call to any modifying method, make a copy first.

Compiling and Running opoptimize

To compile opoptimize, enter the command make while in the directory /usr/share/Optimizer/src/sample/opoptimize.

To run opoptimize, recall that command-line options are listed if you invoke the application without any command-line arguments. To print a list of interactive program controls into your command shell while you run opoptimize, place the mouse cursor in the rendering window and enter h.

Figure D-1 illustrates simplification of the original model of 19474 polygons to 10902 to 4938 polygons. The three panels in the figure correspond from left to right to the following three commands:

# opoptimize kittyHawk.iv -rotation 1 0 0 1

# opoptimize kittyHawk.iv -rotation 1 0 0 1 -simpPercent 50 0 1 0

# opoptimize kittyHawk.iv -rotation 1 0 0 1 -simpPercent 15 1 2 1

The simplifier used for these images is discussed in “Methods in opSimplify”.

Figure D-1. Simplifying a Model With opoptimize

Figure D-1 Simplifying a Model With opoptimize

The rest of this chapter is a running commentary on the code in main.cxx.

opoptimize Code


Note: The sequence in which tools are applied to the scene graph in opoptimize is not fundamental to a scene-graph tuning application; if you use opoptimize as a template, other orderings may be more appropriate for your needs.


Inclusions

 

 

 

These headers include the necessary objects from Cosmo3D.

 

#include <stdio.h>

#include <Cosmo3D/csFields.h>
#include <Cosmo3D/csGroup.h>
#include <Cosmo3D/csCsb.h>
#include <Cosmo3D/csLOD.h>
#include <Cosmo3D/csTriStripSet.h>
#include <Cosmo3D/csTriFanSet.h>
#include <Cosmo3D/csTransform.h>

See “Command-Line Parser: opArgParser”.

 

 

#include <Optimizer/opArgs.h>

You can simplify the rendering task by culling small features from the scene. See “Detail Culling”.

 

 

#include <Optimizer/opDetailSimplify.h>

See “Saving and Loading Scene-Graph Files”.

 

 

#include <Optimizer/opGenLoader.h>

This header provides various functions that control specific features of the scene graph and accelerate rendering. For example, see “Display Lists”, “Vertex Arrays”, and “Methods in opCollapseAppearances”.

 

 

#include <Optimizer/opGFXSpeed.h>

See “Calling opInit()”.

 

 

#include <Optimizer/opInit.h>

See “Error Handling and Notification”.

 

 

#include <Optimizer/opNotify.h>

 

Inclusions (cont.)

 

 

 

The basic control of interactive rendering, including keyboard commands and the ability to manipulate selected portions of the scene graph, are provided by the classes in these files. See “opDrawImpl Subclasses Used In Sample Applications” and “Interacting With a Rendered Object: opPickDrawImpl”.

 

 

#include <Optimizer/opDefDrawImpl.h>
#include <Optimizer/opPickDrawImpl.h>

To make scene graph traversals more efficient, you can organize nodes spatially. See Chapter 6, “Organizing the Scene Graph Spatially.”

 

 

#include <Optimizer/opSpatialize.h>#include <Optimizer/opGeoSpatialize.h>

A sophisticated simplification tool is provided by this file. See “Methods in opSimplify”.

 

 

#include <Optimizer/opSRASimplify.h>

You can collect statistics about the numbers of vertices, triangles and connected primitives in your scene graph. See “Gathering Triangle Statistics”.

 

 

#include <Optimizer/opTriStats.h>

Includes classes to develop connected primitives from a set of triangles in a csGeoSet. See “Merging Triangles Into Both Strips and Fans: opTriFanAndStrip” and “Merging Triangles Using Multiple Processors: opMPTriFanAndStrip”.

 

#include <Optimizer/opTriFanAndStrip.h>

This file holds the basic rendering class opViewer, discussed in “Viewing Class: opViewer”.

 

 

#include <Optimizer/opViewer.h>

 

Inclusions (cont.)

 

 

 

Tessellators convert abstract geometries into renderable collections of triangles. See “Tessellating Parametric Surfaces”.

This application focuses mainly on simplifying the rendering task by using tessellations with differing levels of resolution, by removing triangles from tessellated objects, and by reorganizing the distribution of triangles in the scene graph.

 

#include <Optimizer/opTessParaSurfaceAction.h>

#include <Optimizer/opTessNurbSurfaceAction.h>

To guarantee consistent tessellations between adjacent surfaces, that is, surfaces rendered without cracks, OpenGL Optimizer provides topology maintenance tools. See Chapter 10, “Creating and Maintaining Surface Topology.”

 

 

#include <Optimizer/opTopo.h>

These files are in the opoptimize directory.

 

 

#include “colorTag.h”
#include “deleteSurf.h”
#include “removeEmpty.h”
#include “simplify.h”
#include “convert.h”

 

Initialize

 

 

 

You can use either of the algorithms to remove triangles from a mesh. See “Creating LODs: opSRASimplify” and “Rossignac Simplification Algorithm: opLatticeSimplify”.

Here the application initializes the control parameter for one of the simplification tools and creates an instance of the other.

 

// Global simplifier paramaters for passing to
// app-defined key bindings
float gridSpacing = 0.08;
opSRASimplifier simplfier;

You have three ways to develop surface connectivity information. The values enumerated list from best to worst. See Chapter 10, “Creating and Maintaining Surface Topology.”

 

 

int LODoffset;enum opTopoOption
{TOPO_TWO_PASS, TOPO_ONE_PASS, TOPO_NO};

 

Define a Key Handler

 

 

 

The key handler extends the default keyboard controls available during rendering. See “opDrawImpl Subclasses Used In Sample Applications”.

 

// SimplifyViewer extends opViewer by adding new // key bindings:
// `g' : (go) simplify the scene graph
// `c' : (go) tristrip the scene graph w/ random // colors
// `C' : (go) tristrip the scene graph w/o random // colors

 

static bool keyHandler(opDrawImpl *di, int key)
{ opViewer *viewer = di->getViewer();
bool retVal = true;

 

 

 

switch(key)
{

See “Merging Triangles Into Strips: opTriStripper”; and “Gathering Triangle Statistics”.

 

 

case `c':
case `C':
// Show different colored tristrips triStripTree( (csGroup *)viewer->getRoot(),
(key=='c')?true:false);
{
opTriStats ts(8);
ts.apply(viewer->getRoot());
ts.print();
}
retVal = false;
break;

 

Define a Key Handler (cont.)

 

 

 

See the file simplify.h and “Rossignac Simplification Algorithm: opLatticeSimplify”, and “Gathering Triangle Statistics”.

 

case `G':
opNotify(opInfo,opNull,
”Invoking Rossignac simplifier with gridSpacing = %2.3f\n”,gridSpacing);

latticeSimplifySameTree(
(csGroup *)viewer->getRoot(), gridSpacing);
gridSpacing *= 2.0;
{
opTriStats ts(14);
ts.apply(viewer->getRoot());
ts.print();
}
break;

See the file simplify.h and “Creating LODs: opSRASimplify”, and “Gathering Triangle Statistics”.

 

case `g':
opNotify(opInfo,opNull,
”Invoking SRA simplifier.”);

simplifySameTree(
(csGroup *)viewer->getRoot(), &simplfier);
{
opTriStats ts(14);
ts.apply(viewer->getRoot());
ts.print();
}
retVal = false;
break;

The LOD offset adjusts the LOD calculation when objects in the scene are moving. See “Viewing Class: opViewer”.

 

 

case `+':
changeLODOffset(
(csGroup *)viewer->getRoot(),++LODoffset);
retVal = false;
break;

case `-':
changeLODOffset(
(csGroup *)viewer->getRoot(),--LODoffset);
retVal = false;
break;

 

 

Define a Key Handler (cont.)

 

 

 

This calls a Cosmo3D function to save a scene graph to a file in .csb format. See “Saving and Loading Scene-Graph Files”.

 

case `z':
csdStoreFile_csb(
(csGroup *)viewer->getRoot(),”test.csb”);
break;

default:
break;
}
return retVal;

 

main()

 

 

 

See “Calling opInit()” and “Command-Line Parser: opArgParser”.

 

 

int main(int argc, char *argv[])
{

opInit();

opArgParser args;

int numFiles;

char *filename,*outFile;

 

Command-Line Control Parameters

 

 

 

The location on the screen (x, y) of the rendering window, and the dimensions of the window (w,h). The default x-coordinate assumes a screen of width 1280, and a rendering window of width 600 with a 10-pixel boundary. You can control these parameters from the command line.

 

bool haveX=-1, haveY=-1, haveW=-1, haveH=-1,
haveSize=-1;
int x=1280-600-10, y=0, w=600, h=600;

If TRUE, the processed scene graph is written to a .csb file and not rendered. See “Saving and Loading Scene-Graph Files”.

 

bool writeCSB;

You can use several techniques to develop connected primitives that accelerate the rendering process. See “Creating OpenGL Connected Primitives”.

 

 

bool doTriStrip, doTriFan, doTriFanStrip, doMPTriFanStrip;

int minFanSize;

bool doRandomTriStrip;
// Color the tstrips with a random color

 

Command-Line Control Parameters (cont.)

 

 

 

You can use either of two simplification algorithms to remove triangles from a mesh. See “Creating LODs: opSRASimplify” and “Rossignac Simplification Algorithm: opLatticeSimplify”.

 

bool doSRASimplify;
bool SRApercent,SRAcount,SRAestimate;
float percent;
float fAngle;
int polyCount;
bool doLatticeSimplify;

There are several techniques to rearrange triangles in a scene graph to reflect their positions in space and facilitate cull traversals. See Chapter 6, “Organizing the Scene Graph Spatially.”

 

 

bool combineGSet;

bool spatialize, geospatialize;
int minGoal,maxGoal;

 

 

 

bool writeOutput;

You can place simplified and unsimplified scene graphs under a csLOD node.

 

bool LODfiles, makeLOD;

See “Detail Culling”.

 

 

bool doDetail;
float detail_ratio;

bool doRootRadius;
float root_radius;

 

 

 

bool doScale;
float scale_factor;

 

 

 

bool showDelete;

 

 

 

bool doDeleteSurf;

You can interactively assign colors to objects. See “Interacting With a Rendered Object: opPickDrawImpl”.

 

 

bool enableColoring;
char *colorTagFile;
char *colorTag;
bool doColorTag;
colorTable *cTable = NULL;
char *colorFile;

 

 

 

bool doRemoveEmptyGrp;
bool removeColors;

 

Get Command-Line Parameters

 

 

 

Specify the threshold distance between points below which they are considered identical when building topology. See “Summary of Scene Graph Topology: opTopo” on page 180.

 

bool haveTopoTol;
opReal topoTol;

 

Specify the background color for the rendering window and the model orientation. These settings are controlled by

opViewer options. See “Viewing Class: opViewer”.

 

bool haveBackgroundColor;float backgroundRed, backgroundGreen,
backgroundBlue, backgroundAlpha;
bool haveRotation;
float vx, vy, vz, angle;
bool haveTranslation;
float tx, ty, tz;

Specify control parameters for tessellation, and the type of tessellator (for example for general parametric surfaces or for NURBS surfaces). See “Tessellating Parametric Surfaces”.

If tessType is equal to zero, no tessellation is performed. The main use for this option is in batch mode to convert file formats and possibly store topology information; you can read in a .iv file and write the scene graph without tessellations to a .csb file. Depending on the topology-build command-line option, the output could have topology information. See “Saving and Loading Scene-Graph Files”.

 

bool haveChordalTol = -1;
opReal chordalTol = 0.01; bool haveSamples;
int samples;
bool haveTessType = -1;
char *tessType = NULL;
// Initialize this since cmdline args may modify

By default, build the best topology. See Chapter 10, “Creating and Maintaining Surface Topology.”

 

 

bool isOnePass = false;

You must supply a file with the scene graph. All other command-line control parameters are optional.

 

args.defRequired( “%s”,
“<filename>”,
&filename);

 

Get Command-Line Parameters (cont.)

 

 

 

 

 

args.defOption( “-width %d”,
“-width <window width>”,
&haveW, &w );
args.defOption( “-height %d”,
“-height <window height>”,
&haveH, &h );
args.defOption( “-size %d”,
“-size <window width=hieght>”,
&haveSize, &w );
args.defOption( “-xpos %d”,
“-xpos <window x screen position>”,
&haveX, &x );
args.defOption( “-ypos %d”,
“-ypos <window y screen position>”,
&haveY, &y );

 

 

 

args.defOption( “-tristrip”,
“-tristrip”,
&doTriStrip );

 

 

 

args.defOption( “-trifan”,
“-trifan”,
&doTriFan);

 

 

 

args.defOption( “-trifanstrip %d”,
“-trifanstrip <min Fan length>”,
&doTriFanStrip, &minFanSize );

 

 

 

args.defOption( “-mptrifanstrip %d”,
“-mptrifanstrip <min Fan length>”,
&doMPTriFanStrip,&minFanSize );

 

 

 

args.defOption( “-detail %f”,
“-detail <detail ratio>”,
&doDetail, &detail_ratio);

 

 

 

args.defOption( “-rootRadius %f”,
“-rootRadius <radius>”,
&doRootRadius, &root_radius);

 

 

 

args.defOption( “-simplify”,
“-simplify”,
&doSRASimplify );

 

Get Command-Line Parameters (cont.)

 

 

 

 

 

args.defOption( “-rossignac %f”,
“-rossignac <gridSpacing>”,
&doLatticeSimplify,
&gridSpacing );

The target of the simplification can be specified as a percentage of the original number of triangles, or as a exact number. See “Creating LODs: opSRASimplify”.

 

 

args.defOption( “-simpPercent %f %f “,
“-simpPercent
<percent [0.0,100.0] of model desired>
<feature angle>”,
&SRApercent,
&percent,
&fAngle);

args.defOption( “-simpCount %d %f “,
“-simpCount <count per GeoSet> <feature angle>”,
&SRAcount,
&polyCount,
&fAngle);
args.defOption( “-simpEstimate”,
“-simpEstimate, for quick estimate of resulting model”,
&SRAestimate);

You can render individual csTriStrips in differing colors, to see their sizes.See “Creating OpenGL Connected Primitives”; and “Specifying Coloring of New csGeoSets: opColorGenerator”.

 

args.defOption( “-tristripRandom”,
“-tristripRandom, for random colors”,
&doRandomTriStrip);

 

 

 

args.defOption( “-scale %f”,
“-scale <scale factor>”,
&doScale, &scale_factor);

 

 

 

args.defOption( “-batch %s”,
“-batch <output filename>”,
&writeCSB,&outFile);

 

 

 

args.defOption( “-combine”,
“-combine”,
&combineGSet);

 

 

 

args.defOption( “-spatialize %d %d “,
“-spatialize <min tris> <max tris>”,
&spatialize,&minGoal,&maxGoal);

 

Get Command-Line Parameters (cont.)

 

 

 

 

 

args.defOption( “-geospatialize %d %d “,
“-geospatialize <min tris> <max tris>”,
&geospatialize,&minGoal,&maxGoal);

 

 

 

args.defOption( “-LODfiles”,
“-LODfiles puts listed files as children under LOD in given order”,
&LODfiles);

 

 

 

args.defOption( “-makeLOD”,
“-makeLOD creates simplified version from root then adds both to LOD”,
&makeLOD);

 

 

 

args.defOption( “-writeSG”,
“-writeSG prints out entire contents of scene graph”,
&writeOutput);

 

 

 

args.defOption( “-noColors”,
“-noColors removes color bindings from csGeoSets”,
&removeColors);

 

Get Command-Line Parameters (cont.)

 

 

 

 

 

#ifdef OP_REAL_IS_DOUBLE
args.defOption( “-ctol %l”,
“-ctol <max chordal deviation>”,
&haveChordalTol, &chordalTol );

args.defOption( “-ttol %l”,
“-ttol <topology tolerance> [setting ttol implies automatic topology building]”,
&haveTopoTol, &topoTol );

#else

args.defOption( “-ctol %f”,
“-ctol <max chordal deviation>”,
&haveChordalTol, &chordalTol );

args.defOption( “-ttol %f”,
“-ttol <topology tolerance> [setting ttol implies automatic topology building]”,
&haveTopoTol, &topoTol );

#endif

 

 

 

args.defOption( “-onePass”,
“-onePass [build topology while tessellating]”,
&isOnePass )

// Sets the type of tessellator used either by the
// loader or after building the topology.
args.defOption( “-tess %s”,
“-tess <gen[eral] nurb no>”,
&haveTessType, &tessType );

 

 

 

// Sets how many samples are used on trim curves // during the tessellation.
args.defOption( “-samples %d”,
“-samples <tessellator sample count>”,
&haveSamples, &samples);

 

Get Command-Line Parameters (cont.)

 

 

 

 

 

// enable feature to delete highlighted nodes with `X' key
args.defOption( “-showDelete”,
“-showDelete use X key to delete highlighted nodes to clean up dbase. Need to save SG for permanent change.”,
&showDelete);

 

 

 

// enable feature to color highlighted subtrees with number keys
args.defOption( “-enableColoring %s %s”,
“-enableColoring <output filename> <tag>”,
&enableColoring, &colorTagFile, &colorTag);

 

 

 

// Read in <filename>.delete to determine which parts to delete from SG
args.defOption( “-delete”,
“-delete”,
&doDeleteSurf);

 

 

 

// User defined background color
args.defOption( “-background %f %f %f %f”,
“-background <red> <green> <blue><alpha>”,
&haveBackgroundColor, &backgroundRed, &backgroundGreen, &backgroundBlue, &backgroundAlpha );
// User defined model orientation
args.defOption( “-rotation %f %f %f %f”,
“-rotation <vx> <vy> <vz> <angle>”,
&haveRotation, &vx, &vy, &vz, &angle );
args.defOption( “-translation %f %f %f”,
“-translation <tx> <ty> <tz>”,
&haveTranslation, &tx, &ty, &tz );

 

 

 

// Use colortag file to determine which color to apply to all parts
// in corresponding filename
// Assuming all nodes in file will be same color
args.defOption( “-colortag %s”, “-colortag <filename>”, &doColorTag, &colorFile);

 

 

 

// Remove group nodes with no children
args.defOption( “-remove”,”-remove”, &doRemoveEmptyGrp);

 

Get Command-Line Parameters (cont.)

 

 

 

 

 

numFiles = args.scanArgs(argc,argv);

//set topoOption
topologyOption topoOption;
if (!haveTopoTol)
{
topoOption = TOPO_NO;
//don't build topology
}
else if (isOnePass)
{
topoOption = TOPO_ONE_PASS;
//build topology while tessellating.
}
else
{
topoOption = TOPO_TWO_PASS;
//build topology in a separate pass before //tessellation
}

 

Create the Appropriate Tessellator

 

 

 

See Chapter 11, “Rendering Higher-Order Primitives: Tessellators.”

 

 

// Create a tessellator
opTessParaSurfaceAction *tess;
if ( tessType == NULL )
tess = new opTessParaSurfaceAction;
else if ( strcmp( tessType, “gen” ) == 0 )
tess = new opTessParaSurfaceAction;
else if ( strcmp( tessType, “nurb” ) == 0 )
tess = new opTessNurbSurfaceAction;
else if ( strcmp( tessType, “no” ) == 0)
tess = NULL;
elsetess = new opTessParaSurfaceAction;// Set the chordal tolerance
if(tess)
tess->setChordalDevTol( chordalTol );
// Set the sample count if the user set them
if ( haveSamples )
tess->setSampling( samples );

 

Create the Topology Data Structures

 

 

 

See Chapter 10, “Creating and Maintaining Surface Topology.”

 

//topology
opTopo *topo = new opTopo;
// Set the topology parameters
if ( haveTopoTol )
{
topo->setDistanceTol( topoTol, meter );
}

 

Load the Scene Graph Data

 

 



 




The loader manages topology in one of the following ways:

It anticipates the development of connectivity information for all surfaces in the scene graph followed by tessellating the surface. Code for these steps appears later in the application.

It develops connectivity information as surfaces load, and tessellates them.

It ignores connectivity: it simply tessellates surfaces as they load without regard for adjacencies.

See

“Saving and Loading Scene-Graph Files”; Chapter 10, “Creating and Maintaining Surface Topology”; and “Base Class opTessellateAction”.

 

 

// Create a loader
opGenLoader *loader;
if(topoOption == TOPO_TWO_PASS)
//build topology before tessellating any //surface.
{loader = new opGenLoader( true, NULL, false );
//the tessellator is not bound to the loader so //that there is no tessellation at loading. The //reason is because tessellation has to wait //until topology construction is completely done //for all the surfaces
}
else if( topoOption == TOPO_ONE_PASS )
//build topology while tessellate
{
tess->setBuildTopoWhileTess(true);
//tell the tessellator to invoke topology //construction at tessellation
//Sets the topology which will used in the //topology building at tessellation.
tess->setTopo(topo);

loader = new opGenLoader( true, tess, false );
//bind tessellator to loader so that //tessellation is invoked at loading
}
else //don't build topology{//bind tessellator to loader so that //tessellation is invoked at loadingloader = new opGenLoader( true, tess, false );

}

// Load the file on the command line and get a // scene graph backcsGroup *obj = loader->load( filename );
csGroup *root = obj;

 

Load the Scene Graph Data (cont.)

 

 



 




 

 

 

if (obj)
{
// Delete parts specified in corresponding // *.delete
if (doDeleteSurf)
{
deleteSurfTree(obj,filename);
}

You can use a color tag file to specify the appearance of different parts in the scene. The format of the color tag file is:

Comments (preceded by the pound sign, #).

A line containing the number of colors.

Lines containing the colors: five digits that specify red, green, blue, alpha, and shininess values. Currently, alpha is not used, but a
value must appear for the shininess parameter to be properly interpreted.

Part names and their associated colors.

See colorTable::colorTable() in /usr/share/Optimizer/src/sample/opoptimize/
colorTag.cxx
.

 

// Color the parts as specified in color file
if (doColorTag)
{
cTable = new colorTable(colorFile);
cTable->setColorTree(obj,filename);
}

 

Load the Scene Graph Data (cont.)

 

 



 




 

 

 

if (numFiles)
{
int i;
csGroup *grp;

if (LODfiles)
{
grp = (csGroup *)new csLOD;
} else
{
grp = new csGroup;
}
grp->addChild(obj);
char **xtraFiles = args.getRemainingArgs();
for (i=0;i<numFiles;i++)
{
opNotify( opNotice, opNull,
“Loading file %d %s\n”,i,xtraFiles[i]);
obj = loader->load(xtraFiles[i]);

if (obj)
{
if (doDeleteSurf)
{
deleteSurfTree(obj,xtraFiles[i]);
}
if (doColorTag)
{
cTable = new colorTable(colorFile);
cTable->setColorTree(obj,xtraFiles[i]);
}
grp->addChild(obj);
}
}

 

Load the Scene Graph Data (cont.)

 

 



 




See addLOD.cxx.

 

if (LODfiles)
{
setupLOD((csLOD *)grp,(csSwitch::SwitchEnum)0);
}
root = grp;
}

 

 

// Throw the loader away, we're done with it
delete loader;

 

Build Topology and Tessellate

 

 



 




The most accurate topology, which yields crack-free tessellations, is created by two traversals of the scene graph: one to establish adjacencies of surfaces, and the second to tessellate the surfaces. See “Building Topology: Computing and Using Connectivity Information”.

 

 

//build topology if we haven't done it
if ( obj && topoOption == TOPO_TWO_PASS)
{

fprintf(stderr, “Building topology starts ... \n”);
topo->buildTopology( );
fprintf(stderr, “Building topology done\n”);

You can tessellate higher-order surface representations and view the scene, or in batch processing, not view the scene but write the scene graph (possibly with topology information) to a .csb file. See “Saving and Loading Scene-Graph Files”.

 

if(tess)
{
fprintf(stderr, “Tessellation starts ... \n”);
tess->apply( obj );
fprintf(stderr, “Tessellation done ... \n”);
}
else{
fprintf(stderr, “No tessellation is performed\n”);
}

 

Remove Childless Nodes and Color Bindings

 

 

 

See the files removeEmpty.h and removeEmpty.cxx.

 

 

// Run through the SG and remove groups with no
// children
if (doRemoveEmptyGrp)
{
obj = removeEmpty(root);
}

 

Remove Childless Nodes and Color Bindings (cont.)

 

 

 

 

 

csType *type = csTriFanSet::getClassType();
if ( doTriStrip || doRandomTriStrip)
{
type = csTriStripSet::getClassType();
}

See “Removing Color Bindings”.

 

 

if (removeColors)
opRemoveColorBindings(root);

 

Remove Small Objects from the Scene

 

 

 

You can remove small objects from the rendering pipeline. See “Detail Culling”.

 

csSphereBound sph;
root->getSphereBound (sph);
opNotify( opNotice, opNull,
“Root bounding sphere is %f\n”,sph.radius);
if (doDetail)
{
opDetailSimplify *dsimp = new opDetailSimplify;
// Compare radius of geosets to radius of overall
// model so more of the smaller pieces are culled.
if (doRootRadius)
{
dsimp->setRootRadius(root_radius);
}
dsimp->setSizeRatio (detail_ratio);
dsimp->apply (root);
}

 

Remove Childless Nodes After Detail Cull

 

 

 

See the files removeEmpty.h and removeEmpty.cxx.

 

 

// Run through the SG and remove groups with no children
if (doRemoveEmptyGrp)
{
root = removeEmpty(root);
}

 

Spatialize the Scene Graph

 

 

 

If you have a scene graph with too many small csGeosets, you can combine them and develop a graph consisting of a root node with one child that contains all of the triangles of the original graph. See “Merging csGeoSets in a Scene Graph: opCombineGeoSets”.

 

if (combineGSet)
{
// For now, don't generate colors
root =
(csGroup *)opCombineGeoSets::convert(root,type);
}

 

Spatialize the Scene Graph (cont.)

 

 

 

You can re-organize existing nodes to reflect their spatial relations (see “Spatializing a Scene Graph: opGeoSpatialize”) or spatially re-organize triangles in a csGeoSet (see “Spatialization Tool: opSpatialize”).

The function geoSpatializeTree() is defined in geoSpatialize.cxx and spatializeTree() is defined in spatialize.cxx. These functions apply the spatialization methods to the whole scene graph.

 

if (geospatialize)
{
// Spatialize based on combining everything below // a particular group, then chop it up into smaller
// pieces if it exceeds maxGoal
geoSpatializeTree(root,minGoal,maxGoal,type);
} else if (spatialize)
{
spatializeTree(root,minGoal,maxGoal,type);
}

 

Print Scene Graph

 

 

 

This is the Cosmo3D method to write out the scene graph.

 

if (writeOutput)
{
csOutput *output = new csOutput(stdout);
output->write(root);
}

 

Remove Triangles and Create Levels of Detail

 

 

 

You can use either of two simplification algorithms to remove triangles from a mesh. See “Creating LODs: opSRASimplify” and “Rossignac Simplification Algorithm: opLatticeSimplify”.

 

if ( doSRASimplify || makeLOD)
{
// Default is to use percentage
// of model as a target goal
if (SRAcount)
{
// Check if both -simpPercent and -simpCount
// options were used at the same time
if (SRApercent)
{
opNotify(opFatal,opUsage,”Can not use both
-simpPercent and -simpCount at the same
time. Using only -simpCount option\n”);
}
opTriStats stats;
stats.apply(root);
percent = 100.0*((float)polyCount/
(float)stats.getTriCount());
// User changes these settings
simplifier.setPercent(percent);
simplifier.setFAngle(fAngle);
} else if (SRApercent) { // User changes these settings
simplifier.setPercent(percent);
simplifier.setFAngle(fAngle);
}
if (SRAestimate)
{
simplifier.setAccurateMethod(false);
}

 

Remove Triangles and Create Levels of Detail

 

 

 

The functions simplifyTree(), simplifySameTree(), and latticeSimplifySameTree() traverse the scene graph and simplify all csGeoSets. See the files simplify.h, simplify.cxx, and simplifySameTree.cxx.

 

 

if (makeLOD)
{
fprintf(stderr,”Simplifying ...”);
csGroup *simpObj =
simplifyTree(root, &simplifier);
fprintf(stderr,”Done\n”);
// Set child0 as default LOD to be drawn
root = addLODChild(root,simpObj,0);
} else
{
fprintf(stderr,”Simplifying ...”);
csGroup *simpObj =
simplifySameTree(root, &simplifier);
fprintf(stderr,”Done\n”);
root = simpObj;
}
}
else if (doLatticeSimplify)
{
opNotify(opInfo,opNull,
”Invoking Rossignac simplifier with
gridSpacing =%2.3f\n”,gridSpacing);
csGroup *simpObj =
latticeSimplifySameTree(root, gridSpacing);
gridSpacing *= 2;
fprintf(stderr,”Done\n”);
root = simpObj;
}

 

Create OpenGL Connected Primitives

 

 

 

To reduce the load on the graphics hardware, you can reduce redundant vertex information by combining triangles into fans of a minimum size, and combining the remainder into triangle strips (using either a single or multiple processors). See “Merging Triangles Into Both Strips and Fans: opTriFanAndStrip” and “Merging Triangles Using Multiple Processors: opMPTriFanAndStrip”.

 

if (doTriFanStrip)
{
// Only create trifans if they can be of a minimum // Fan Length.
opTriFanAndStrip tfs(minFanSize);
tfs.apply(root);
}
else if (doMPTriFanStrip)
{
// Only create trifans if they can be of a minimum Fan Length.
opMPTriFanAndStrip tfs(minFanSize);
tfs.apply(root);

You can create just triangle strips to reduce redundant vertex information, rather than create both triangle fans and triangle strips. See “Merging Triangles Into Strips: opTriStripper”.

The methods of opTriStripper work only on a csGeoSet. The function triStripTree() traverses the whole scene graph, applying the methods of opTriStripper to every csGeoSet (see triStrip.cxx).

 

} else if
((doTriStrip || doRandomTriStrip) && !combineGSet )
{
bool useRandomColor;
fprintf(stderr,”TriStripping ...”);
if (doRandomTriStrip)
useRandomColor = true;
else
useRandomColor = false;
triStripTree( root,useRandomColor);
fprintf(stderr,”Done\n”);

You can create just triangle fans to reduce redundant vertex information, rather than create both triangle fans and triangle strips. See “Merging Triangles Into Fans: opTriFanner”.

The methods of opTriFanner work only on a csGeoSet. The function triFanTree() traverses the whole scene graph, applying the methods of opTriFanner to every csGeoSet. (see triFan.cxx).

 

}else if (doTriFan && !combineGSet)
{
bool useRandomColor = false;
fprintf(stderr,”TriFanning ...”);
triFanTree( root,useRandomColor);
}

 

Rescale Objects in Scene

 

 

 

 

 

if (doScale)
{
csGroup *newroot = new csGroup;
csTransform *xform = new csTransform;
xform->setScale
(scale_factor, scale_factor, scale_factor);
newroot->addChild (xform);
xform->addChild (root);
root = newroot;
}

 

Collect Vertex Statistics and Print Them

 

 

 

See “Error Handling and Notification” and “Getting Statistics About a Scene Graph: opTriStats”.

 

// Get stats on the scene graph
opTriStats stats;
stats.apply(root);
opNotify( opNotice, opNull,
“Scene statistics:\n”);
stats.print();

 

Write Scene Graph to File

 

 

 

You can run opoptimize in batch mode without viewing the effects of the scene-graph manipulation tools.

 

if ( writeCSB)
{
csdStoreFile_csb(root,outFile);

 

 

}
else
{

 

Set Parameters to Draw the Scene

 

 

 

To see the effects of the scene-graph manipulations, you can use an opViewer and register the keyboard commands defined by the keyHandler() with the interaction control class, an opDrawImpl. See “Viewing Class: opViewer”, “Controlling Rendering: opKeyCallback and opDrawImpl”, and “opDrawImpl Subclasses Used In Sample Applications”.

 

if (haveSize)
h = w;
opViewer *viewer =
new opViewer(filename, x, y, w, h);
opDefDrawImpl *di = new opDefDrawImpl( viewer );if ( haveBackgroundColor )
{
viewer->setBackgroundColor(
backgroundRed,
backgroundGreen,
backgroundBlue,
backgroundAlpha );
}di->registerKey(`c', keyHandler, “Tri-strip a shape node (random colors)”);
di->registerKey(`C', keyHandler, “Tri-strip a shape node (normal colors)”);
di->registerKey(`g', keyHandler,
“Go simplify single a shape node.” );
di->registerKey(`G', keyHandler,
“Go simplify single a shape node using Rossignac algorithm.” );
di->registerKey(`+', keyHandler,
“See next LOD, less detail.” );
di->registerKey(`-', keyHandler,
“See previous LOD, more detail.” );
di->registerKey(`z', keyHandler,
“Save scene graph of model.” );

 

 

 

// Use default DrawImpl until pick invoked
opPickDrawImpl *pi = new opPickDrawImpl(viewer);
if (showDelete)
pi->enableDelete ();
if (enableColoring)
pi->enableColoring (colorTagFile, colorTag);

 

Draw the Scene

 

 

 

You can set the model orientation. See “Viewing Class: opViewer”.

 

 

viewer->addChild(root);
viewer->setViewPoint(root);
if ( haveRotation )
{
viewer->setModelRotation( vx, vy, vz, angle );
}
if ( haveTranslation )
{
viewer->setModelTranslation( tx, ty, tz );
}

You can further reduce the load on the graphics hardware by using OpenGL display lists. See “Display Lists”.

 

opDListScene((csGroup*)viewer->getRoot());
viewer->eventLoop();
}
}
}


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