Celestia: Open-source Masterpiece!
A Conversation with
Chris Laurel!
Well let me tell you a little story 'bout a man named Chris! Chris Laurel that is... Now, I'm not
in awe of any man or woman, but that does not mean that I'm not in complete and total awe of some their
accomplishments. Chris Laurel would fall into that category for me. Chris is the creator of
Celestia, an incredible open-source 3D space
simulation written in the C++ programming language. Chris' resume
speaks for itself. Chris has a love for astronomy and science that is easily proven by even a brief glance at
Celestia's code base.
Celestia has been downloaded over 6,265,449 times! Celestia's core authors form a team of highly-skilled and
educated developers whose huge contributions to the project and code base have made Celestia the defacto standard in space simulation. Celestia
is a true open-source project and the authors are located across the globe, once again demonstrating the power of ""transparency of
process and distributed peer review." Chris has a loyal and dedicated community
of contributors and helpers that continuously add to the already amazing functionality that Celestia offers. (I hope to write more about some
of the Celestia authors, supporters and their efforts in the near future!)
My interest in Celestia began a few months ago after watching a Discovery Channel
show regarding the New Horizon's mission to Pluto. A couple of years ago I had thought to myself "wouldn't it be cool to write a
3D space simulation of the solar system?" The problem was I did not have the 3D programming knowledge to pull it off,
not to mention the mathematical ability to convert physics equations to code. Chris is a master at this as far as I'm concerned.
Chris sat down and said, "I think I'll write a 3D simulation of the universe!" How's that for a challenge?
And he pulled it off!
Now, I'm paraphrasing Chris here, but I read some comments by Chris in an interview with an Italian magazine. The reason Mr. Laurel decided to release his master project as an open-source project: so he could get input and contributions from all over the world. Imagine having NASA or the European Space Agency (ESA) using your software! Celestia is used by NASA and the ESA for testing sims (simulations). It shows once again the power of open-source and dedication to a goal.
If you read the news page about Chris Laurel, I mentioned our "conversation." This may sound unrelated, but it' not, in a few weeks I'll be releasing another free GPL JavaTM Swing source distribution for a simple yet useful color application that I wrote about six years ago. Not too long ago I downloaded all the Celestia 1.5.0 version source code from sourceforge.net and started attempting to compile this masterpiece of software artistry and science. I began scouring the source code seeing how I was going to make my "great contribution" to a great program. My head nearly exploded! It was some of the most complex code I've ever seen and yet some of the most concise and well-written. I felt like the neophyte apprentice looking at the master's code.
I finally ended up in a lonely little directory named celutil. I found a source code C++ class
file named color.cpp. Yippeee! Something I can understand! There was a TODO comment in the Color
class that I knew I could handle. In my overzealous zeal to contribute to Celestia, I had emailed Chris a few times with
some "ideas." Many of them juvenile in comparison to converting Euler Angles to
Quaternions, which is child's play for the Celestia developers! It's common
to find in the Celestia Forums the author and co-authors engaging
in intense scientific discussions concerning advanced subjects like
Lorentz invariance
or reference frame transformations, for example, and how to best implement such
complex mathematical concepts into code.
Chris is a busy man, so I realized I needed to send some code. Here's what transpired,
" Thanks for taking the time to work on the Celestia code. What you have looks good except for one big problem: you're recreating the map every time Color::parse() is called. You really want to do this just once. What I recommend is to create a static map (file scope, not function scope.) Then, the first thing the parse function does is check whether this table is empty--if it is, it fills it with color values. On subsequent calls, the table will not be empty and you can just do a lookup. The good thing is that you avoided the trap most people fall into when they use an STL map: expecting that the array index operator will return the equivalent of NULL if the object isn't in the table." Chris Laurel
OOooops! Ironically, my JavaTM color application does just that -- creates the collection statically and is called at file scope! I was afraid I was starting to look like an idiot to this guy! I quickly rewrote the code and resent it to Chris.
"Brent, Some more colors would be useful (and that new code you wrote looks fine.) One thing to do is find out the source of that color list that you have--there's a standard list (based on the X11 colors, I think) that are part of the HTML spec (I think.) Anyhow, it'd be nice if they were based on some sort of standard so I could link to it in the celx docs." Chris Laurel
Ok, cool, I have a static Java array list of X11 colors, I'll convert it over to a C++ STL (Standard Template Library) Map collection and I just might get some code in Celestia!
"I checked in your code for the x11 color table, but I found one serious bug. For the color table, you were using map<char*, Color>. The problem with that is the map template will just compare the char pointers as pointers, not with a string compare. Unless the two char* variables are pointing to exactly the same spot in memory, the comparison will fail. Compilers will do an optimization called string constant folding, so only one string is actually stored in memory when there are multiple instances of the same string constant. This saves a little bit of space. And it means that two character pointers set to identical string constants (i.e. quoted character sequences in the source code) will actually point to the same place. That's probably why the tests of your code worked. But, when one of the strings is read from a file or otherwise constructed at run time, the code fails. There's a simple solution: switch to using a C++ string. So instead of
map<char*, Color>
use:
map<string, Color>
The C++ string class is almost always what you want. It's good to understand C's strings-are-just-char-pointers approach, but it's rarely a good idea to use plain old char* any more. The problem that you ran into is only one of many unexpected things that can happen with char* strings. The string class has a constructor that accepts a char*, so conversions from char* to string are implicit. So, this code works just fine:
string s = "hello, world";
There were a couple unnecessary casts in your code that I got rid of. The static_cast was unnecessary: you were casting to a Color, but the object was already a Color.
As for building the Qt version, go to the src directory and type:
qmake -t vcapp celestia.pro
Then, load the resulting celestia-qt4.vcproj into Visual Studio and compile. Once you've got Qt4.3 and VS2005 working together, that's all there is to it!" Chris Laurel
I actually meant to use const char* which is a fairly efficient
way to store strings C++ strings, but I'll follow Chris' advice and stick with
the STL string class instead! By the way, if you're new to C++, start
learning to use the STL libraries. They're industry-tested.
Honestly, is Chris great or what? He takes the time to write all this? I'm thrilled! I'm honored that Chris Laurel would except a code contribution from me. I'm honored and humbled! The whole experience only proves that true open-source is "transparency of process and distrubuted peer review!"
Unfortunately, I had to reach the following conclusion regarding the grand hopes I had for contributing more to the Celestia project as outlined in my letter to Chris below,
"I've come to a conclusion: Celestia is over my head both programmatically and scientifically! Honestly, I can't even consider myself an "advanced user," considering all the scripting possibilities. Hopefully, as my education continues I may be able to contribute more significantly in the future, but I have a lot to learn about 3D applications and C++." Brent Allen Parrish
Chris' reply was both realistic and encouraging,
"You are of course more than welcome to dive headfirst into the Celestia code base to make further changes. But as you've observed, it is a difficult task to become acquainted with a new language while simultaneously trying to make sense of over 100,000 lines of existing code (especially in a project like Celestia where a lot of the code is fairly mathematical.)" Chris Laurel
Man is that ever the truth! Chris did encourage me to possibly take a stab at a helper app for Celestia written in C++ and Qt4. If anyone is interested in Celestia and has suggestions or ideas for such an application please let me know!
Thanks Chris et al!
- Brent P.