Project
When I received a Motorola Milestone phone, I wanted to get into Android development. I had seen ports of Quake3 to the iphone and the N900 which have similar specifications (all use a similar CPU and the PowerVR GPU), so I thought why not bring Quake3 to Android. As a start point I used the N900 version of ioquake3. It only took me a day to get the game to compile and to load the Quake3 main-function. After that it took me a few more days to get OpenGL and some input working. In the weeks following the initial port I added touchscreen support, networking and sound.
Features
* Audio
* Hardware floating-point on Neon-capable devices
* Input: keyboard, touchscreen and trackball
* OpenGL 3D rendering
* Game uses ARM optimized libcgamearm.so / libqaarm.so / libuiarm.so
* Networking
Performance
Normally when you compile C/C++ code using the Android NDK, the compiler targets a generic ARMv5 CPU which uses software floating-point. Without any optimizations and audio Quake3 runs at 22fps. Since Quake3 uses a lot of floating-point calculations. I tried a better C-compiler (GCC 4.4.0 from Android GIT) which supports modern CPUs and Neon SIMD instructions. Quake3 optimized for Cortex-A8 with Neon is about 15% faster without audio and 35% with audio compared to the generic ARMv5 build. Most likely the performance improvement compared to the ARMv5 build is not that big because the system libraries of the Milestone have been compiled with FPU support, so sin/cos/log/.. take advantage of the FPU.
One of my users also tested the game on his G1 but the device doesn't have much RAM and the CPU runs is downclocked to a little more than 300MHz. In the timedemo it scores about 10fps without audio. In game (after some tweaking) it can reach upto 20fps in not so busy areas.
Below are benchmark results of Quake3 at 854x480 in demo four at the default Quake3 settings:
ARMv5 Neon
No audio 22.0 fps 25.4 fps
Audio 14.7 fps 20.0 fps
Performance can be improved quite a bit by tweaking Quake3 settings. Setting lighting to Vertex instead of Lightmap improves performs by 20% to more than 30fps in Neon mode without audio.
Design
Android programs are written in Java and performance critical parts can be implemented in a C library and can then be called using JNI. 99.9% of the code in this project is C and the other part is Java. The small Java part initializes OpenGL, handles input and manages audio. The Kwaak3 Java code communicates with a 'libquake3.so' using a libkwaakjni wrapper. This wrapper loads either a generic ARMv5 'libquake3.so' or a Neon optimized 'libquake3_neon.so' depending on the CPU.
* Ioquake3 contains an 'infinite' loop which renders a single frame each iteration. A single iteration of this loop has been turned into a function which is called from onDrawFrame in Java.
* Input is processed by Android and is sent to the game when it is received.
* Audio is implemented on the Java side and using JNI, kwaak3 requests a number of audio samples when it needs some.
Supported devices
During development I have only had access to a Motorola Milestone. This phone has a keyboard and for this reason the game has been optimized for devices with a keyboard, so it won't work on your Nexus One or other phone at this point. One of my testers used a G1 and thanks to his testing there is also some trackball support. If I had my hands on more devices I would add support for those devices. The minimum required Android version at this point is 1.6.
Note the G1 doesn't have much RAM and due to this is very sensitive to crashing. The game might be more stable if you disable audio.
Future work
* Audio: use direct buffers to make data copying to Java more efficient and optimize the mixing code using Neon instructions
* 3D rendering: use VBOs for uploading geometry and prevent unneeded re-uploads
* Input: improve controls on phones without keyboard like the Nexus One
* Profile: profile the Quake3 code and optimize slow parts
Labels: Android
0 comments:
Post a Comment