GPUmesh - Easy Cross-Plateform Cross-API Mesh Management for GPUs


Version 1.0 (updated 2004-05-04)

See also the GPUmesh FAQ

Content

1. What is GPUmesh ?

Nowadays there exist multiple ways of sending geometry to GPUs: displays lists, vertex buffer objects, indexed primitives are some of them. This changes from Direct3D to OpenGL, and new ways of managing geometry appear as APIs evolve. It is difficult to determine which method is the best. This depends on numerous factors (mesh size, number of vertex attributes, and some unknown driver/hardware mechanisms). Moreover some ways of sending the geometry are slow but very convenient (e.g. the OpenGL function calls).

The purpose of GPUmesh is to provide developers with a simple mechanism to send geometry to the GPU. The user chooses which type of mesh storage is desired (display list, vertex buffer, indexed vertex buffer, ...) and GPUmesh automatically performs the required conversions. The chosen mechanism can be changed very easily by changing only one typedef. This makes performance test with various storage solutions very easy. Since the whole library is built upon templates, only the code corresponding to the chosen storage is generated. Their is no runtime overhead.

GPUmesh offers the same mesh specification mechanism under Direct3D and OpenGL, thus simplifying the task of writing mesh loaders. GPUmesh relies on a mechanism similar to the begin/end approach of standard OpenGL. This mechanism has proven to be easy to use and very convenient. Thanks to GPUmesh it now also produces efficient meshes. A complete vertex format specification mechanism is also provided to manage vertex attributes.

2. Installation

2.1. Using GPUmesh

Since GPUmesh is only a set of header files, there is nothing to compile. Just include D3DGPUmesh.h or GLGPUmesh.h depending on the graphics API you are using.

By default GPUmesh uses gluX for the extension loading mechanism. gluX can be disabled by defining GPUMESH_NO_GLUX.

2.2. Compatibility

GPUmesh is a template library. Unfortunately all compilers do not support all template functionnalities. GPUmesh is compatible with the following compilers:

2.3. Sample programs

The included OpenGL examples use glut, gluX, and libTexture.

Under Windows, a Visual C++ 7 2002 project is included. The binaries of the libraries are also included (for Visual C++ 7 2002).

Under Linux, please download and install the libraries (glut, gluX, libTexture). The Loki library is already included in the libs/loki directory. Before compiling please edit tutorial/Makefile and update the library path. By default they are set to:


LIBRARY_PATH    = $(HOME)/lib.linux
GLUX_PATH       = $(LIBRARY_PATH)/glux
LIBTEXTURE_PATH = $(LIBRARY_PATH)/libtexture
LOKI_PATH       = $(LIBRARY_PATH)/loki

3. A simple example

The first step is to include the appropriate header file. This depends whether your are using OpenGL or Direct3D.


#ifdef OPENGL
// include GPUmesh for OpenGL
#  include "GLGPUmesh.h"
#else
// include GPUmesh for Direct3D
#  include "D3DGPUmesh.h"
#endif

Then, a vertex format and a mesh type must be chosen and associated.


// GPUmesh is encapsulated in a namespace

using namespace GPUmesh;

// define vertex format (2D vertex and RGBA color)

typedef GPUMESH_MVF2(mvf_vertex_2f,mvf_color0_rgba) mvf_mesh;

// associate mesh and chosen vertex format

#ifdef OPENGL
typedef GPUmesh_GL_DisplayList<mvf_mesh> SimpleMesh;
#else
typedef GPUmesh_D3D<mvf_mesh>            SimpleMesh;
#endif

// pointer to mesh object

SimpleMesh         *g_Object=NULL;

From now, nothing else depends on the API (OpenGL or Direct3D). The following code creates a simple quad with a color at each vertex:


void initScene()
{
  // ...

  g_Object = new SimpleMesh();

  g_Object->begin(GPUMESH_TRIANGLELIST);

  g_Object->color0_4(0,0,255,0);
  g_Object->vertex_2(0.1,0.1);

  g_Object->color0_4(255,0,0,0);
  g_Object->vertex_2(0.1,0.9);

  g_Object->color0_4(0,255,0,0);
  g_Object->vertex_2(0.9,0.9);

  g_Object->color0_4(0,0,255,0);
  g_Object->vertex_2(0.1,0.1);

  g_Object->color0_4(0,255,0,0);
  g_Object->vertex_2(0.9,0.9);

  g_Object->color0_4(64,0,255,0);
  g_Object->vertex_2(0.9,0.1);

  g_Object->end();

  // ...
}

The code to render an object is simply:


void renderScene()
{
  // ...

  g_Object->render();

  // ...
}

4. Tutorials

A set of tutorials are included in the package.

5. Reference

5.1. Vertex formats

A vertex format describes the attributes of each mesh vertex. A vertex format is a type defined as follows:

typedef GPUMESH_MVF<N>(<First attribute>,...,<Attribute N>) <vertex format name>;
For an example,
typedef GPUMESH_MVF2(mvf_vertex_2f,mvf_color0_rgba) mvf_mesh;
defines a vertex format called mvf_mesh with two attributes: a 2D vertex position and an RGBA color.

The possible attributes are:

mvf_vertex_2f mvf_vertex_2d mvf_vertex_3f mvf_vertex_3d
mvf_vertex_4f mvf_vertex_4d mvf_normal_3f mvf_normal_3d
mvf_color0_3f mvf_color0_3d mvf_color0_4f mvf_color0_4d
mvf_color0_rgba mvf_color1_3f mvf_color1_3d mvf_color1_4f
mvf_color1_4d mvf_color1_rgba mvf_texcoord0_1f mvf_texcoord0_1d
mvf_texcoord0_2f mvf_texcoord0_2d mvf_texcoord0_3f mvf_texcoord0_3d
mvf_texcoord1_1f mvf_texcoord1_1d mvf_texcoord1_2f mvf_texcoord1_2d
mvf_texcoord1_3f mvf_texcoord1_3d mvf_texcoord2_1f mvf_texcoord2_1d
mvf_texcoord2_2f mvf_texcoord2_2d mvf_texcoord2_3f mvf_texcoord2_3d
mvf_texcoord3_1f mvf_texcoord3_1d mvf_texcoord3_2f mvf_texcoord3_2d
mvf_texcoord3_3f mvf_texcoord3_3d mvf_texcoord4_1f mvf_texcoord4_1d
mvf_texcoord4_2f mvf_texcoord4_2d mvf_texcoord4_3f mvf_texcoord4_3d
mvf_texcoord5_1f mvf_texcoord5_1d mvf_texcoord5_2f mvf_texcoord5_2d
mvf_texcoord5_3f mvf_texcoord5_3d mvf_texcoord6_1f mvf_texcoord6_1d
mvf_texcoord6_2f mvf_texcoord6_2d mvf_texcoord6_3f mvf_texcoord6_3d
mvf_texcoord7_1f mvf_texcoord7_1d mvf_texcoord7_2f mvf_texcoord7_2d
mvf_texcoord7_3f mvf_texcoord7_3d
It is possible to check whether two vertex formats are compatible with the macro CHECK_COMPATIBLE_FORMAT(mvf1,mvf2). See CGenSpiral.h (tutorial directory) for an example. A vertex format mvf1 is compatible with a vertex format mvf2 if all the items of mvf1 are also in mvf2.

5.2. Available mesh types

Static meshes
Dynamic meshes

Not Yet Implemented ...

5.3. GPUmesh class reference

All the mesh are specializations of the generic class GPUmesh. This class has the following public members:
void begin(int primitive_type) Begins a mesh definition. primitive_type can be GPUMESH_TRIANGLELIST, GPUMESH_TRIANGLEFAN (OpenGL only), GPUMESH_TRIANGLESTRIP, GPUMESH_QUADS (OpenGL only). Primitive types for lines are not yet implemented.
void end() Ends a mesh definition. Data is sent to the GPU at this point.
void bind() Binds a mesh for drawing. This must be called before draw().
void unbind() Unbind the mesh. This must be called after draw().
void draw() Draws the mesh. It must be binded.
void render() Calls bind(); draw(); unbind();. Use this method if you want to draw the mesh only once.
int vertex_[2..4]( ... ) Defines vertex position. The function is available in 3 versions: 2D, 3D and 4D coordinates. Note that similarly to OpenGL, this method save the vertex with all current values of the attributes. In other word, this must be called after having defined all the other vertex attributes. The index of the added vertex is returned.
void index( ... ) Defines geometry when using an indexed mesh. If the mesh is not indexed, calling this method has no effect.
void normal( ... ) Define vertex normal. If the vertex format does not include a normal, calling this method has no effect.
void color[0..1]_[3..4]( ... ) Define vertex color0 or color1. Each function exist in two versions: RGB and RGBA. If the vertex format does not include a color, calling this method has no effect.
void texcoord[0..7]_[1..4]( ... ) Define vertex texture coordinates for texture unit 0 to 7. Each function exists in 4 versions: 1D, 2D, 3D and 4D. If the vertex format does not include texture coordinates, calling this method has no effect.

5.4. Legal mesh declaration

The mesh declaration should follow some rules that are depicted by some examples of legal / non-legal declarations below.

Given the following vertex format,


typedef GPUMESH_MVF2(mvf_vertex_2f,mvf_color0_rgba,mvf_texcoord0_4) mvf_mesh;

The following declaration are (legal / illegal):


g_Object->begin(GPUMESH_TRIANGLELIST);

g_Object->color0_4(0,0,255,0);
g_Object->texcoord0_4(0.0,0.5,0.1,1.0);

g_Object->vertex_2(0.1,0.1);
g_Object->vertex_2(0.1,0.9);  // legal, reuse other attributes value
g_Object->vertex_2(0.9,0.9);

g_Object->end();

g_Object->begin(GPUMESH_TRIANGLELIST);

g_Object->vertex_2(0.1,0.1);  // legal, missing attributes intialized to 0
g_Object->vertex_2(0.1,0.9);
g_Object->vertex_2(0.9,0.9);

g_Object->end();

g_Object->begin(GPUMESH_TRIANGLELIST);

g_Object->vertex_3(0.1,0.1,0.0); // ILLEGAL - do NOT compile
g_Object->vertex_3(0.1,0.9,0.0); // (vertex_2 should be used)
g_Object->vertex_3(0.9,0.9,0.0);

g_Object->end();

g_Object->begin(GPUMESH_TRIANGLELIST);

g_Object->color0_4(0,0,255,0);
g_Object->texcoord0_2(0.0,0.5); // legal, but ignored ! (differs from OpenGL behaviour)

g_Object->vertex_2(0.1,0.1);
g_Object->vertex_2(0.1,0.9);
g_Object->vertex_2(0.9,0.9);

g_Object->end();

g_Object->begin(GPUMESH_TRIANGLELIST);

g_Object->color0_4(0,0,255,0);
g_Object->normal(0.0,1.0,0.0); // legal, supplemental attribute is ignored

g_Object->vertex_2(0.1,0.1);
g_Object->vertex_2(0.1,0.9);
g_Object->vertex_2(0.9,0.9);

g_Object->end();

5.5. Indexed mesh declaration

Indexed meshes are declared as follows:
 


// define vertex format

typedef GPUMESH_MVF2(mvf_vertex_2f,mvf_color0_rgba) mvf_mesh;

// associate mesh and choosen vertex format

typedef GPUmesh_Indexed_GL_VBO<mvf_mesh,unsigned int> IndexedMesh;


void initScene()
{
  // ...
  g_Object = new IndexedMesh();

  g_Object->begin(GPUMESH_TRIANGLELIST);

  // declare vertices

  g_Object->color0_4(0,0,255,0);
  g_Object->vertex_2(0.1,0.1);

  g_Object->color0_4(255,0,0,0);
  g_Object->vertex_2(0.1,0.9);

  g_Object->color0_4(0,255,0,0);
  g_Object->vertex_2(0.9,0.9);

  g_Object->color0_4(64,0,255,0);
  g_Object->vertex_2(0.9,0.1);

  // build geometry from indices

  g_Object->index(0);
  g_Object->index(1);
  g_Object->index(2);

  g_Object->index(0);
  g_Object->index(2);
  g_Object->index(3);

  g_Object->end();
  // ...
}

6. How does it work ?

GPUmesh is based on library design techniques presented in the excellent book Modern C++ Design by Andrei Alexandrescu. The whole idea is to make the library very efficient by relying on template policies. The template mechanism can be almost totally hidden from the user. I am planning to explain more in depth how GPUmesh works, but well, time is a limited ressource ...

7. Troubleshooting

Known bugs Please also read the FAQ.
 

8. Author

)