Like GLUT, Pez lets you quickly build simple OpenGL apps that will run on any platform. Unlike GLUT, it never makes any OpenGL calls on your behalf. This makes it easy to write demos that conform to the forward-compatible profile in OpenGL 3.0+.

Pez doesn’t require you to register callbacks like GLUT does. Instead, your program simply provides definitions for four functions:

That’s it! Pez defines main() (or WinMain on Microsoft platforms) and runs a game loop for you. Additionally, Pez defines a handful of utility functions that serve as alternatives to printf, exceptions, and asserts:

On Windows, strings get sent to the debugger, so use the VS debugger window or dbgview to see them.

Pez doesn’t handle keyboard stuff and resizable windows. If you want to do anything fancy, just edit the Pez source and treat it as a starting point. Pez is written in ANSI C and released under the MIT License.

The only outside library that Pez depends on is GLEW, which is also so tiny that you can plop it down directly into your project. Usage of glew is especially nice on Windows platforms, since it lets you avoid including the huge windows.h header, and it loads up function pointers on your behalf. Pez calls glewInit() for you.

GLEW is included in the downloadable Pez package at the end of the post, along with a few other super-light libraries such as GLSW and pnglite. Together, these libraries form the “Pez Ecosystem”, which I’ll discuss later. You don’t need to use the entire ecosystem to use Pez; GLEW is the only required library.

You can configure some aspects of Pez (most importantly, window size) by editing pez.h and modifying one of these constants:

Ghandi Texture

Aside from Pez itself, so far we’ve pulled in two other libraries to facilitate our sample code: GLEW and GLSW. We’re slowly forming the “Pez Ecosystem” that I’ll cover later. We now need a library to help us load textures from an external file. I like pnglite since it’s yet another “one C file, one H file” solution. Here’s how to use pnglite to load in our Gandhi texture:

The above code assumes that the PNG image is RGB only (does not contain alpha). I don’t advise hardcoding stuff like this in production code, but we’re just listing out some simple examples. Here’s the effect file:

Mesh Viewer

For the per-pixel lighting effect, see my other blog post. For loading the “headless giant” mesh, we’ll use OpenCTM, which supports good compression and has a nice & simple API. Here’s how we’ll use it to load the model and create a VBO:

The other lightweight library we’ll pull in for this example is the Sony Vector Library, which has nice APIs for C and C++, and supports the various matrix operations from old-school OpenGL that are no longer in the core specification. For example, here’s how you’d use their C++ API to compute a projection matrix from a viewing frustum:

Pez Ecosystem

While developing these tutorials, I’ve selected a variety of libraries to help us along. OpenGL is a low-level API and it (sensibly) doesn’t attempt to do things like decode image files and whatnot.

I’ve made sure that all these libraries have fairly liberal licenses (specifically, they’re not LGPL) and that they’re all very tiny. Here’s the complete list:

Pez itself

OpenGL Extension Wrangler

OpenGL Shader Wrangler (uses bstrlib)

pnglite (uses zlib)

OpenCTM Mesh Format (uses lzma)

Sony Vector Library (extracted from Bullet)

Downloads

You can get a package that has all the demos on this page and the complete Pez ecosystem. It uses CMake for the build system. CMake is easy to use and very popular (Blender, KDE, and Boost use it). It’s similar to autoconf in that it can generate makefiles, but it can also generate actual project files which you can open with IDE’s like Visual Studio and Xcode.

The OpenCTM file format for compressed triangle meshes looks very promising. To celebrate my gigasecond birthday, I wrote a .x to .ctm converter that exports positions and normals. It currently discards texture coordinates, but it shouldn’t be hard to extend it. I can’t guarantee that this tool is super robust, but it worked well enough for the test cases that I ran across.

I simply used ID3DXMesh to load in the .x file and the OpenCTM API to write out the .ctm file. Unfortunately, the usage of ID3DXMesh makes this tool Windows-only.

It’s a command line tool that works like this:

Usage: x2ctm [sourcefile] [sourcefile] ...

To form a destination filename, it simply replaces the existing file extension with .ctm and preserves the folder path.

At a high level, here’s how it works: (if you want, skip to the downloads section)

void ExportCTM(ID3DXMesh* pMesh, const char* destFile)
{
// 1. Find where the positions, normals, and texture coordinates live.
// 2. Check that we support the format of the data.
// 3. Obtain vertex & index counts from the D3D mesh; allocate memory for the CTM mesh.
// 4. Lock down the verts and pluck out the positions and normals.
// 5. Lock down the indices and convert them to unsigned 32-bit integers.
// 6. Instance the OpenCTM mesh and save it to disk.
// 7. Free the OpenCTM buffers.
}