IRIX 6.4 » Books » Developer »
OpenGL Performer Getting Started Guide
(document number: 007-3560-002 / published: 2000-11-14)
table of contents | additional info | download find in page
Chapter 7. Creating Geometry with pfGeoSet
OpenGL Performer provides
pfGeoSets for holding low-level geometric descriptions of objects. A pfGeoSet is a collection of like-geometric primitives, such as points, line segments, triangle strips, triangles, or triangle fans. The primitives in a pfGeoSet share a state description for texture, material, and other surface attributes in a
pfGeoState.
By combining multiple pfGeoSets you can create a complex object, such as a house, car, or terrain. By manipulating the vertices of pfGeoSet elements, you can create a dynamic object, such as ocean waves.
This chapter describes how to create geometric surfaces and place them in the scene graph in the following sections:
For more information about pfGeoState, see Chapter 8, “Specifying the Appearance of Geometry with pfState and pfGeoState”.
A
pfGeoSet is a collection of one or more like primitives, such as lines or triangles. These primitives are arranged in a way that forms a geometric surface.
pfGeoSets contain:
A defined primitive type set with pfGSetPrimType().
The function pfGSetNumPrims() specifies the number of primitives in the pfGeoSet.
For stripped primitives, such as triangle strips, the number of vertices in each strip is set with a lengths array using
pfGSetPrimLengths().
Vertex coordinate attribute lists, with optional corresponding index lists set with
pfGSetAttr().
The kind of
attribute binding, also specified in pfGSetAttr(), determines whether attributes are specified as follows:
Per vertex:
PFGS_PER_VERTEX
Per primitive:
PFGS_PER_PRIM
For all the primitives in the pfGeoSet:
PFGS_OVERALL
A reference to a pfGeoState specified with pfGSetGState(), which specifies the surface appearance (lighting material, texture, transparency, etc.) of the geometry.
A simple example of
pfGeoSet creation and rendering demonstrating the concepts in this chapter can be found at /usr/share/Performer/src/pguide/libpr/gset.c.
For information about optimizing pfGeoSet performance, see “Optimizing pfGeoSet Performance” in Chapter 15.
The following sections describe how to create a
pfGeoSet.
Creating a pfGeoSet Object
To create a pfGeoSet from the shared memory arena, use the following line of code:
pfGeoSet *pfNewGSet(void *arena)
|
Setting the Primitive Type
Use the following pfGeoSet method to specify the type of
primitive in the pfGeoSet:
void pfGSetPrimType(pfGeoSet *gset, int type);
|
type is one of the primitives provided by OpenGL Performer:
PFGS_POINTS
PFGS_LINES
PFGS_LINESTRIPS
PFGS_FLAT_LINESTRIPS
PFGS_TRIS
PFGS_QUADS
PFGS_TRISTRIPS
PFGS_FLAT_TRISTRIPS
PFGS_TRIFANS
PFGS_FLAT_TRIFANS
PFGS_POLYS
PFGS_FLAT_* primitives are flat-shaded. PFGS_POLYS draws polygons of arbitrary vertex lengths.
Figure 7-1 shows some of these primitives.
The numbers in Figure 7-1 show the order in which the vertex attributes should appear in the attribute array.
Setting the Number of Primitives
Use the following pfGeoSet method to specify the number of
primitives in the pfGeoSet:
void pfGSetNumPrims(pfGeoSet *gset, int num);
|
num is the number of primitives.
Setting the Number of Vertices Per Stripped Primitive
When using one of the following pfGeoSet primitives, which have an arbitrary number of vertices, you must define the number of vertices of each
primitive in the pfGeoSet:
PFGS_LINESTRIPS
PFGS_FLAT_LINESTRIPS
PFGS_TRISTRIPS
PFGS_FLAT_TRISTRIPS
PFGS_TRIFANS
PFGS_FLAT_TRIFANS
PFGS_POLYS
Use
pfGSetPrimLengths() to specify the number of vertices of each primitive in the pfGeoSet:
void pfGSetPrimLengths(pfGeoSet* gset, int *lengths);
|
lengths is an array of the number of strips in a pfGeoSet. Each element of the lengths array is the number of vertices in a corresponding strip. For example:
lengths[0] = 8;
lengths[1] = 5;
|
These lines of code mean that the number 0 primitive has 8 vertices, and the number 1 primitive has 5 vertices. Use pfGetGSetPrimLength() to return the length of an individual primitive from the lengths array.
 | Note: pfGetGSetPrimLength() checks for NULL or negative lengths.
|
Attributes of pfGeoSet Primitives
The vertex information of the
primitives in a pfGeoSet are described by attribute lists. Each element in an attribute list contains information for a single vertex. The vertex attributes for all vertices of all primitives of a pfGeoSet are stored in separate arrays, according to the following attribute types:
A pfGeoSet has at least one array pfVec3 of vertex coordinates. Optional attributes include colors, normals, and texture coordinates. Arrays holding these attributes for the vertices of the pfGeoSet are specified for the pfGeoSet using pfGSetAttr(). Figure 7-2 shows the arrays of
attributes.
Indexes for indexed attributes are in separate index arrays. For more information about indexed attributes, see “Indexed Arr
ays”.
You can also put all vertex attributes of a pfGeoSet in a single-packed attribute array. You may use packed attribute arrays for performance reasons or for specifying specialized custom formats of data. For more information about packed attribute arrays, see “Packed Attributes”.
To set the
attributes of a pfGeoSet, use pfGSetAttr() as follows:
void setAttr(int attr, int bind, void *alist, ushort *ilist);
|
attr specifies the
attribute array to set. The tokens for the different attribute lists are:
PFGS_COLOR4
PFGS_NORMAL3
PFGS_TEXCOORD2
PFGS_COORD3
PFGS_PACKED_ATTRS
bind is the binding type. The tokens are listed in Table 7-1.
alist is a pointer to an attribute array for appropriate, corresponding data.
ilist is a pointer to an index array for used to access the attribute array.
A
ttribute bindings specify whether attributes are as follows:
Per vertex— PFGS_PER_VERTEX
Per primitive—PFGS_PER_PRIM
For all the primitives in the pfGeoSet—PFGS_OVERALL
Unspecified—PFGS_OFF
For example, you can specify the following:
A unique color for each vertex (PFGS_PER_VERTEX).
A unique color for each primitive (PFGS_PER_PRIM).
One color for all primitives in the pfGeoSet (PFGS_OVERALL).
An unspecified color (PFGS_OFF).
Table 7-1 shows the possible bindings per attribute type.
Table 7-1. Possible Bindings Per Attribute Type
Binding Type
|
Colors
|
Normals
| Texture
Coordinates
|
Vertices
|
|---|
PFGS_OFF
| Yes
| Yes
| Yes
| No
| PFGS_OVERALL
| Yes
| Yes
| No
| No
| PFGS_PER_PRIM
| Yes
| Yes
| No
| No
| PFGS_PER_VERTEX
| Yes
| Yes
| Yes
| Yes
|
A cube has 6 sides; together those sides have 24 vertices. In a vertex
array, you could specify the primitives in the cube using 24 vertices. However, most of those vertices overlap. If more than 1 primitive can refer to the same vertex, the number of vertices can be streamlined to 8. To get more than 1 primitive to refer to the same vertex, use an index; 3 vertices of 3 primitives use the same index, which points to the same vertex information. Adding the index array adds an extra step in the determination of the attribute, as shown in Figure 7-3.
Indexing can save system memory, but rendering performance is often lost.
Whether or not
attributes should be indexed depends on how many vertices in a geometry are shared:
If attributes are shared by many primitives, the attributes should be indexed.
If attributes are not shared by many primitives, the attributes should be handled sequentially.
Consider the following two examples in Figure 7-4, in which each dot marks a vertex.
In the
triangle strip, each vertex is shared by 2 adjoining triangles. In the square, the same vertex is shared by 8 triangles. Consider moving these vertices when, for example, morphing the object. If the vertices were not indexed in the square, the application would have to search for and alter 8 triangles to change one vertex. In the case of the square, it is much more efficient to index the attributes.
On the other hand, if the attributes in the triangle strip were indexed, because each vertex is shared by only 2 triangles, the index search time would exceed the time required to simply update the vertices sequentially. In the case of the triangle strip, rendering is improved by handling the attributes sequentially.
The choice of using indexed or sequential attributes applies to all of the primitives in a pfGeoSet. All of the primitives within one pfGeoSet must be referenced sequentially or by index; you cannot mix the two.
Using p
acked attributes is an optimized way of sending formatted data to the graphics pipeline under OpenGL operation. Using packed attributes can help host traversal performance because they remove subroutine call overhead. Packed attributes can also reduce memory usage because they allow for the format specification of attributes such as normals, texture coordinates as floats, and colors as unsigned bytes. Some small additional overhead might be incurred by the geometry subsystem of the graphics pipeline, which has to unpack the data.
The packed attribute array holds the currently bound per-vertex attribute data packed into a single non-indexed array and is specified with the matching format of the data with pfGSetAttr() as follows:
pfGSetAttr(gset, PFGS_PACKED_ATTRS, PFGS_PA_C4UBN3ST2F /*the format*/);
|
V
ertex coordinate attributes can be placed in this array and do not need to be duplicated in their regular arrays. Specify NULL for the attribute list to pfGSetAttr(). Vertex coordinates themselves must always be provided in the normal vertex coordinate list. They can, based on the packed format, be duplicated in the packed array.
To create packed attributes, you can use the utility pfuTravCreatePackedAttrs(), which traverses a scene graph to create packed attributes according to the specified format for pfGeoSets and, optionally, pfDelete redundant attribute arrays. This utility packs the pfGeoSet attributes using pfuFillGSetPackedAttrs(). To then render geometry with packed attributes, use the pfGSetDrawMode(PFGS_PACKED_ATTRS) method when using OpenGL.
For more information on packed arrays, see the examples in the following: /usr/share/Performer/src/pguide/libpr/C/packedattrs.c /usr/share/Performer/src/sample/C/perfly.c /usr/share/Performer/src/sample/C++/perfly/perfly.C.
Chapter 8, “Geometry
,” in the OpenGL Performer Programmer's Guide.
Drawing and Printing a pfGeoSet
pfGeoSets are the lowest-level OpenGL Performer object that can be rendered. To directly draw a
pfGeoSet, use pfDrawGset().
pfGeoSets are pfObjects, so they can have their contents printed for debugging with different levels of verbosity via the pfObject routine, pfPrint().You can also use other pfObject methods, such as pfCopy() and pfDelete(), can also be used with pfGeoSets.
Placing Geometry in a Scene Graph
You incorporate
pfGeoSets into scene graphs using a pfGeode leaf node. A single pfGeode node can have multiple pfGeoSets associated with it if you use the pfAddGSet() method.
To place
geometry in a
scene graph, follow these steps:
Create a pfGeoSet with
pfNewGSet().
Attach the pfGeoSet to a pfGeoState using
pfGSetGstate().
Add the pfGeoSet to a pfGeode node in a scene graph using
pfAddGSet().
The result is shown in Figure 7-5.
To create a pfGeode node, associate two pfGeoSets with it, and attach the node to the scene graph using code similar to the following:
pfGeode *geode = pfNewGeode();
pfAddSet( geode, gSet1 );
pfAddSet( geode, gSet2 );
pfAddChild( GeodesParentNode, geode );
|
The structure of a scene graph impacts the performance of your application. For more information, see “Arrangement of Nodes” in Chapter 6.
Creating Common Geometric Objects
libpfdu provides routines to generate pfGeoSets for
common shapes, including
Sphere
Cube
Pyramid
Cylinder
Cone
When creating these shapes, you can specify the number of triangles that comprise them. For example, the following method sets the number of triangles comprising the sphere to 200:
pfGeoSet *sphere = pfdNewSphere(200, arena);
|
This method returns the number of vertices and normals in the shape.
The more triangles, the smoother the curves but the slower the rendering; fewer triangles allow faster rendering but produce more jagged curves.
Utilities to Create Common Geometric Objects
Table 7-2 shows the libpf utilities that generate
pfGeoSets of l
arger geometric shapes.
Table 7-2. Common Geometric Objects
Geometry
| Properties
| Utilities That Create the Geometry
|
|---|
Sphere
| Unit
| extern pfGeoSet * pfdNewSphere(int ntris, void *arena)
|
| Radius=1,
from Z=-1 to Z=1
| extern pfGeoSet * pfdNewCylinder(int ntris, void *arena)
|
| Radius=1,
from Z=0 to Z=1
| extern pfGeoSet * pfdNewCone(int ntris, void *arena)
| Cube
| Unit
| extern pfGeoSet * pfdNewCube(void *arena)
| Pyramid
| Unit square base,
from Z=0 to Z=1
| extern pfGeoSet * pfdNewPyramid (void *arena)
|
| Z=0 to Z=1
| extern pfGeoSet * pfdNewArrow (int ntris, void *arena)
|
| Z=-1 to Z=1
| extern pfGeoSet * pfdNewDoubleArrow (int ntris, void
*arena)
| Cylinder
| Without end caps
and variable radii
| extern pfGeoSet * pfdNewPipe (float botRadius, float
topRadius, int ntris, void *arena)
| Circle
| Unit circle facing +Z,
filled
| extern pfGeoSet * pfdNewCircle (int ntris, void *arena)
|
| Unit circle in Z=0
plane, lines
| extern pfGeoSet * pfdNewRing (int ntris, void *arena);
|
OpenGL Performer Getting Started Guide
(document number: 007-3560-002 / published: 2000-11-14)
table of contents | additional info | download
Front Matter
New Features in This Guide
About This Guide
Part I. Overview of OpenGL Performer
Part II. Programming With OpenGL Performer
Appendix A. Building a Visual Simulation Application
Appendix B. Image Gallery
Glossary
Index
home/search |
what's new |
help
|