I have been playing with some Java code recently, while working on C# support for BHM files. My old Java 3d engine used BHM, and I wanted to backport some of the new C# parsing magic to Java. It was also an easy platform to test with, as the engine was already fully functional for BHM, whereas I did not yet have that luxury in C#.
One thing led to another, and I decided to look at JavaME, to see if I could port the Java engine to phones. While it is theoretically possible, the simple test of porting PictureParticles to JavaME was not that convincing. Java performance on phones is not that great… also, some of the major smartphones today (such as iPhone and Android-based phones) don’t support Java.
So then I thought: What if I developed for iPhone? When I tried my BHM sample in OS X, I already familiarized myself with XCode, and noticed that you could also develop iPhone/iPad applications with that. The iPhone also supports OpenGL ES. Since the BHM sample is using OpenGL, it should not be that difficult to port it to OpenGL ES.
Objective-C? No thanks
XCode comes with a template for a simple OpenGL ES application. The first thing I noticed was: it is written in Objective-C. I am not familiar with that language, and I don’t feel like learning the language, and then porting my C++ code over to Objective-C. That’s a bit too much for just a simple port for fun.
So I started looking for ways to get C++ working on the iPhone. Officially, they don’t support it, and the iOS framework generally uses ObjC code. However, the underlying compiler is gcc, and that supports C++ just as well. If you just add .cpp files to your project, it will compile them as C++ code, and link them to your application.
Objective-C++? Hmm, better!
The problem then was: how do you call this code? If I included a C++ header file from an ObjC file, it would trip over any C++-specific code, such as class definitions. It also did not seem to be able to handle mangled names.
So my first try was to use some raw C as an entrypoint for the C++ code. By exporting it as extern “C”, ObjC was able to call into this entrypoint. Once inside this function, I could do any C++ I wanted. Nice, but not quite there yet.
Looking a bit further on the internet, I found that there is also a thing known as Objective-C++. That makes sense in some ways, but not in others. It makes sense because Objective-C is indeed C, not C++. Which explains why it can handle raw C code, but not C++. Objective-C++ is the C++-equivalent of that: it also supports C++ code. It doesn’t make sense though that Objective-C is a way to add object-oriented programming to C, just as C++ is. So a language that combines both, is a bit much. I suppose that is why Apple doesn’t support it. XCode will allow you to add Objective-C files to your project, or C++, but there is no mention of Objective-C++ anywhere.
In our case, however, it is the best of both worlds: Objective-C++ allows you to seamlessly use C++ code from within Objective-C. It is also very easy to use: analogous to .c and .cpp, there are the .m and .mm extensions, which will automatically make the compiler treat it as Objective-C or Objective-C++ respectively. So all I had to do was rename the .m files in my project to .mm and I could call C++ from them.
OpenGL ES is not OpenGL
Now that I could compile my code, I still had to make it work. The first problem I ran into is that my OpenGL code was written for maximum backward compatibility, and as such, it used quite a bit of legacy functionality. A lot of legacy has been removed from OpenGL ES, especially the 2.0 version that runs on the latest iPhones. So I had to do quite a bit of rewriting to get the code working. I decided to first force the Windows version to the OpenGL 4.1 core profile, and take it from there. With the core profiles, introduced in OpenGL 3.0, you get a legacy-free version of OpenGL as well. The latest versions are also compatible with OpenGL ES 2.0, and you can even compile your shaders in OpenGL ES mode, by specifying #version 100 at the top of your source.
After a lot of rewriting and testing/debugging, I managed to get everything working legacy-free. Now the final problem was that I needed to load a texture. Initially I just tried to port FreeImage to iPhone, as that is what I use in the regular portable version as well. That turned out to be a bit of an undertaking, since I had to set the code up in XCode, and remove any excess crud for legacy platforms, that will in no way compile (DOS, Atari, even classic Mac).
After I got it to compile, it still didn’t work right. So I decided to instead google for how to load a JPG on iPhone. I found a nice example, which loaded a JPG into an OpenGL ES texture using the Core Graphics framework. It still didn’t quite work… but then I noticed that I had forgotten to set the max-level for the texture. Once I did that, it worked. So then I went back to the FreeImage version… After all, I already did all the hard work of getting it to build, so I wondered if it would actually work. And indeed, the JPG loaded correctly. I just had to do a few small tweaks to the OpenGL calls to make a proper texture out of it (also found some minor bugs in GLUX in the process). Et voila, I now have a full-fledged OpenGL ES framework, working on iPhones (and iPads)!