ADC2: Fish!

Search for BETA-testers and/or promote your own Application in a decent way.

ADC2: Fish!

Postby Beowolve » Thu Sep 03, 2009 5:06 pm

Hi all,

this is my first post, but I have already found some usefull information on this forum while reading some posts in the past. I hope I can give some information back in the future and help you young guys to improve your skills *g*.

Here is my first application ("Fish!") that I submitted for the ADC2 contest. It is a cooperative work from me and my brother, and it is basically a screen saver like application with fish swimming in a virtual see. To get the hole stuff working with about 15fps, every effect activated and 5 fishes we had to do some serious optimizations. I will give you a little description of what we did.

As you can see from the screen shots, the fish are 3d rendered and the first we had to do was loading the mesh from 3DS to our application. Our first attempt was simple, we exported the model to a collada file and then wrote a XML loader. Now it wasn't that simple, because we soon had to face the facts that the device is just too slow to parse a big XML file in reasonable time.
So we created a converter to our own binary file format, that contained just the data we needed and nothing else. Now if you ever tried to load a binary file with java you might have used a DataInputStream and then used the readInt(), readFloat() functions and so on. Now this works, but it is hell slow on a mobil device. To make it fast, you need to use readFully and then convert the byte array to the values you need. To make it easier for you guys here is a small snippet for loading an int array from a file the fast way...

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.         static public int[] loadIntArray( DataInputStream dis ) throws IOException {
  3.  
  4.                 int total = dis.readInt();
  5.  
  6.                 byte bytes[] = new byte[total * 4];
  7.  
  8.                 int ints[] = new int[total];
  9.  
  10.                
  11.  
  12.                 dis.readFully(bytes);
  13.  
  14.                
  15.  
  16.                 for (int i = 0, j = 0; i < total; i++, j += 4) {
  17.  
  18.                         int result;
  19.  
  20.                         result = (bytes[j+3] & 0xFF)
  21.  
  22.                              | ((bytes[j+2] & 0xFF) << <img src="http://www.anddev.org/images/smilies/cool.png" alt="8)" title="Cool" />
  23.  
  24.                              | ((bytes[j+1] & 0xFF) << 16)
  25.  
  26.                                  | ((bytes[j+0] & 0xFF) << 24);
  27.  
  28.                         ints[i] = result;
  29.  
  30.                 }
  31.  
  32.                 return ints;
  33.  
  34.         }
  35.  
  36.  
Parsed in 0.032 seconds, using GeSHi 1.0.8.4


Since we had every frame of our animated fishes pre calculated, we had to load the full 52 frames and with this optimization we managed to bring our loading time down to just 3 seconds on the real device. The xml parsing version needed about 1minute for 1 frame. Just to let you know how important it is to prepare your data into a binary format.

So after we where done with the loading stuff, it was time to render our first fish. We got the mesh and normal values rendered quite nice, but the texture coordinates did look correct. After switching to a standard 6 sided box for the model and some debugging I found out, that the texture was mirrored and flipped in OpenGL. So if you ever want to use textures you should add this code in your initialization code. And remember, never use a complicated model for your first test like I did...

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.         gl.glMatrixMode(GL10.GL_TEXTURE);
  3.  
  4.         gl.glRotatef(180.0f,0.0f,0.0f,1.0f);
  5.  
  6.         gl.glScalef(-1.0f,1.0f,1.0f);
  7.  
  8.         gl.glMatrixMode(GL10.GL_MODELVIEW);
  9.  
  10.  
Parsed in 0.031 seconds, using GeSHi 1.0.8.4


Alright we got the fish rendered. By that time we had a green background color. I can tell you that didn't look very good *g*. By the way used the TouchRotateActivity example from ApiDemos as a starting point, because I liked to have a way to rotate my model from the beginning.

The first change to make that application look better, was using a background image instead of a plane color. I found a cheap and nice looking image for our needs on one of this pages where you can buy a image for a few dollars. I just didn't want to have any copyright problems, so thats the reason for buying it.

Now I wanted to add some particles floating around in the water. This sounded simple, and it actually isn't hard to do. You just need to find a way to draw simple 2d textures *g*. I look at the SpriteMethodTest source before I started on that project so I started using the grid class like in that example. I made that particle falling down slowly and randomly distributed over the area with different sizes. For that particle I created a simple alpha blended image of a round disc. To make your particle alpha blend nicely you have to enable blend like that. The commented blend function does not create good results. I am not an expert on that but GL_ONE does the trick.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. gl.glEnable(GL10.GL_BLEND);
  3.  
  4. gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE/*.GL_ONE_MINUS_SRC_ALPHA*/);
  5.  
  6.  
Parsed in 0.033 seconds, using GeSHi 1.0.8.4


For the bubbles and the light beams we used the same method. We also added a FOG, this made the fish look more realistic. You can see all features in one of the screen-shots that I attached. Now everything activated would result in about 5-7 frames on the device, and we started optimizing.

To make it easy for you here is a short list that makes 3d faster.
1. Don't use GL_FLOAT => use GL_FIXED, you can convert easily by multiplying with 0x10000...
2. Use Hardware-buffers (VBO), you will find how to do that in SpriteMethodTest
3. Use RGB_565 encoded textures, you can set this in the options of BitmapFactory.decodeStream, this is the native device format.
4. Use glDrawTexfOES for 2D Objects. This is definitely the fastest way to draw 2d images. This is part of GL11Ext so make sure you check for availability and add a fall back like the grid class stuff.


Finally I want to mention some SDK / Emulator stuff I found out while working on that project.
1. GL_GENERATE_MIPMAP seams to be unimplemented even on the device there is no visual change even without an error. On the emulator it throws an unimplemented exception, so don't expect it to work. Maybe I do something wrong, if anyone has a working code that would be nice
2. Many opengl functions are not yet documented...
3. Emulator and device produce different results when using glDrawTexfOES! The emulator seams to ignore the z value...
4. The device is about 2-3 times faster then the emulator, depends on your computer power of course...
5. There seams to be no performance difference if you use big textures. Using 256x and 32x textures made no difference in my testing!?
6. Garbage collection happens sometimes, but is not that big of a problem like some members in this forum posted. If you used hardwarebuffers and glDrawTexfOES there is no problem, and you should use that anyway if you care on performance.
7. Hardwarebuffers have to be reinitialized if the device orientation has changed
8. Orientation change currently is handled a little bit strange by android, the application is basically restarted, and it is a must to implement savedInstanceState. This isn't difficult but there are smarter ways to do that I guess...


Well thats all I have to say so far. I hope my english isn't too hard to read, I am from Austria so please forgive me my mistakes ;).

Enjoy coding and have a nice day,

Beo
Attachments
480x320_1.png
480x320_1.png (69.01 KiB) Viewed 3247 times
480x320_1.png
480x320_1.png (73.04 KiB) Viewed 3247 times
320x480_2.png
320x480_2.png (62.26 KiB) Viewed 3247 times
320x480_1.png
320x480_1.png (82.32 KiB) Viewed 3247 times
User avatar
Beowolve
Junior Developer
Junior Developer
 
Posts: 10
Joined: Thu Sep 03, 2009 2:49 pm

Top

Postby mad.dogg » Wed Sep 09, 2009 9:55 am

Many many thanks about the tips dude, and Good Luck with the ADC :)
If it's boring it ain't heavy enough!
mad.dogg
Developer
Developer
 
Posts: 42
Joined: Tue May 20, 2008 2:18 pm
Location: Bulgaria

Postby Beowolve » Sun Oct 04, 2009 10:42 am

Hi all,

just wanted to add that Fish! is now avaliable for download in the market.
Fish! ADC2

enjoy,

Beo
User avatar
Beowolve
Junior Developer
Junior Developer
 
Posts: 10
Joined: Thu Sep 03, 2009 2:49 pm

Top

Return to Promote your Android Application

Who is online

Users browsing this forum: No registered users and 2 guests