Do you want to know how your customers use your applications and devices? Try Qt Insight Beta.
最新版Qt 6.3已正式发布。 了解更多。
最新バージョンQt 6.3がご利用いただけます。 詳細はこちら

Ray casting on Qt for S60

A few days ago I was curious how fast Qt for S60 (Tower release) can blit the pixels to the screen. I decided to port the simple ray caster I wrote 14 years ago to Qt for S60 and to test-drive it on a Nokia E71. The result is something that our video maestro, Alessandro, assembled for us nicely (he showed it on a Nokia Navigator), see below or directly on YouTube:

There is a gazillion ray casting implementations (and tutorials) out there, for a number of different platforms/compilers/CPU (even for the web, using HTML canvas and JavaScript). This example will add one more to the crowd. Find the code in Graphics Dojo repository and use Qt 4.3 or newer to enjoy it. The demo weighs slightly less than 300 lines of code (too short for your taste?). It does however work only with keypad navigation, the users of Nokia N97 and 5800 need to implement some kind of mouse/finger navigation (a good exercise!). Of course, try it first on the desktop, it runs just fine:

True to Wolfenstein 3-D that made ray casting popular, my example also shows a different shading between the walls facing different direction. As you may witness from the shipped textures.png (which holds all the textures, adopted from a very nice Wolfenstein 3-D alternative texture library), this is achieved by having two version of the same wall texture, the normal one and the darker one. In addition to that, each wall texture source pixmap is prerotated by 90 degrees. This is again the old trick I used for the first time in PictureFlow (the same effect that powers Qt Fluid Launcher). The basic premise: improve the cache locality, this is because during texture mapping we scan the pixels within the same horizontal row (neighboring integers), not the vertical column (which means jumping far more than the size of the cache lines).

The code can be further optimized (of course!). In fact, there is no so much Qt-specific part in it (afterall, it's ported from my old Mode X DOS-based test program). For a starter, I am sure a seasoned S60 developer know a bit or two about direct screen access (maybe via CDirectScreenBitmap aka Anti-Tearing API?), this surely improves the blitting although I don't know how less portable the code would be. On a different side, you might see that I improved the inner loop by using simple fixed-point arithmetic. The outer loop is still based on floating-point, feel free to cast some fixed-point magic there, at the potential cost of readability. Sine and cosine can be stored as look-up tables, especially if you turn the viewing angle also to fixed-point. While you are on that, notice also how I got away with finding the sine and cosine for each ray (which you can nicely solve, once the fast look-up table is at your disposal), similar to Ken's Labyrinth (afterall great cheaters think alike), at the price of a less perfect rendering. The mechanics behind ray casting is fairly easy (there are tons of tutorials in Internet), however if your math skill is rusty and parts of this example are difficult to decipher, it is time to grab a sheet of blank paper and to start scriblling, drawing, and playing with geometry. Hardware accelerated graphics, even on mobile platforms (via OpenGL ES and OpenVG), already starts to become the norm these days. This leaves classic stuff like ray casting to serve the educational purpose only.

If you are interested in doing more 3-D with Qt, don't miss the more advanced WolfenQt demo. While this simple ray casting example is pure pixel-manipulation, WolfenQt relies on perspective transformation with Graphics View. It does allow interesting features of Graphics View, like embedding a web browser, a media player, and other fun widgets, as well as exploiting the benefits of OpenGL.

And there are still many steps if you want to base a game on this example (note: there is already S60 Wolfenstein 3-D, if you just want to have a look). Sprites support is still missing, sound also does not exist. On the rendering front, you might want to add some doors (hence the opening and closing logic) for a better game play. All of them is still doable for a weekend project, so have fun if you want to bring Captain Blazkowicz to life!

Blog Topics: