A very very small OpenGL engine.
I wrote this thing ages ago for a commercial project for the now-defunct subsidiary of Sony, Sony Development. We were trying to make a giant pinball machine where you tilted the entire machine to play. To test the physical controller hardware as they worked the kinks out of the design, they needed a little 3D engine to hook up to them so they could see what it would do. So in about a week, I wrote one.
It’s a little odd as engines go in that it loads Lightwave 6.x (or greater) scene and model files and renders them, and then lets you fly a camera around and look at them. It lights the scene according to whatever lights you put in the scene, but all lights are translated as point lights. I never got spotlights or area lights working. It does respect global ambience settings in the scene, though, as well as maintain the hierarchical relationship between all the scene elements (i.e., parenting of scene elements is preserved at runtime.
It eventually ended up being listed in the news section on the now defunct Flay.com, one of the world’s more important Lightwave 3D web sites, and OpenGL.Org also had my listing. I even found a web site in Japan that linked to the original page. Too bad I can’t read Japanese! The engine has been downloaded tens of thousands of times since I posted it after SIGGRAPH 2001.
The engine does do texture maps, but only UV textures, and there are a few ways to apply the textures in Lightwave that don’t actually work. The best approach seems to be to convert whatever conventional texture mapping you might have on your models into UV maps using the “Make UVs” tool in the “Map” toolset in modeler. Since the loader doesn’t handle DMAP chunks, models using cylindrical or spherical mapping need to have the vertices split at the seam, or you’ll get mapping errors.
The source code will compile under either Windows, using Microsoft Visual C++ 6.x or greater, or under Linux using GCC. Yup, it’s cross-platform code!
Download the source code, binaries and sample data here. It’s pretty tiny by modern standards – only 3 megs, even though it includes all the model files and textures and whatnot that you get with it. It’s a fairly modest example of a 3D engine. Once I got the object and scene loaders working, the rest of the engine was done in about five days. It does give some good example code for reading objects in native Lightwave LWO2 format, though. By the way, in the ‘credit where credit is due’ department, I started with the example ‘C’ loader code written by Yoshiaki Tazaki at D-Storm.
Once you’ve gotten it to compile (it shouldn’t be difficult if you know how to use the compiler at all), run it by giving a parameter of either a model file or a scene file. If you give it a scene file as a parameter, it’ll assume all the assets are right there in the same directory with you, even if the scene file says otherwise. If you give it a model file as a parameter, it’ll just load the model file and let you spin it around and look at it from different angles. If you can’t compile the project or don’t want to bother, binary executables are included for both Linux and Windows.
A comment: this project was set up to compile from KDevelop in versions prior to 2.x. If your version is more recent than that, you’re going to have a few problems getting to compile as a project using KDevelop. I’ll may revisit this and make a newer version with new project files (thought I can’t promise when.)
Interestingly, the Linux version runs significantly faster than the Windows version does, even though it’s exactly the same code. I think Linux just works better from the standpoint of interfacing the OpenGL API with the hardware. I know I could do a lot more about optimizing the rendering pipeline, though. Right now the only thing I do is sort the polygons by material; this cuts down on having to use the GL material commands for every single darned polygon, and it sped things up a lot. It’s still not a really quick engine as engines go, but it’s quicker than it first was. I never even implemented tri-strips, and that would have sped it up at least double.
I’ve absolutely got to offer a caveat here as well: I wrote this engine as an exercise, and I stopped before I finished it. There are leftovers and leavings of various ideas in it that I never implemented. The object and scene loading classes themselves are fairly clean, however, and I did my best to keep that functionality as encapsulated as possible so they could be reused by somebody else if needed.
Could I write the same code now? No. If you don’t use linear algebra for 3D for a few years, you forget how. Could I learn to write the same code now? Absolutely. I did it before. I can do it again.
Update: It Runs on a Raspberry Pi
My Raspberry Pi 4 running OpenGL code I wrote over 20 years ago and ported to the Pi in August of 2016. The fastest of these windows is running 120 frames per second, and the CPU is barely warm to the touch.
For a lark, I decided to try compiling this on a Raspberry Pi, and to my great surprise, apart from a small tweak to one of the headers, it worked! Thinking on it, the Raspberry Pi is actually much more powerful than the big bruiser of a desktop machine I developed it on in the first place, yet the computer is no bigger than a pack of cards and draws only about 15w of power. The lightbulb in your refrigerator, if you still have one that isn’t LED based, probably draws more.
— Gene Turnbow