[Android Software Development] Metastable:
I've been working on a new Live Wallpaper with a DeadMau5 theme to it. Decided to make a build thread because I don't see many around this forum and thought it would be interesting to do.

The goal is to recreate DeadMau5's current concert setup:

It is being coded in pure Java using OpenGL ES 1.0. As I am only starting to use OpenGL ES and I think 1.0 is slightly more beginner friendly due to not needing to create a custom pipeline, I choose 1.0 though may move to 2.0 later.

I initially started by creating an LED class which is basically a primitive cube:

public class Led{
public Led(float width, float height, float depth) {
width /= 2;
height /= 2;
depth /= 2;

float tempVertices[] = { -width, -height, -depth, // 0
width, -height, -depth, // 1
width, height, -depth, // 2
-width, height, -depth, // 3
-width, -height, depth, // 4
width, -height, depth, // 5
width, height, depth, // 6
-width, height, depth, // 7
};

short tempIndices[] = { 0, 4, 5, 0, 5, 1,
1, 5, 6, 1, 6, 2,
2, 6, 7, 2, 7, 3,
3, 7, 4, 3, 4, 0,
4, 7, 6, 4, 6, 5,
3, 0, 1, 3, 1, 2,};

vertices = tempVertices;
indices = tempIndices;
}

public void setColor(float red, float green, float blue, float alpha) {
super.setColor(red, green, blue, alpha);
}

private float red, green, blue, alpha = 0f;
private float[] vertices;
private short[] indices;
}

I then created a Panel class which creates a flat array of Leds 10x10 for a total of 100 leds per panel. Then finally with a Cube class that creates an array of Panels, translated and rotated to create the final Cube image, here:

Which I think is decent reproduction of the real thing:

I then set off on being able to display images onto my glorious cube of light. OpenGL allows you to change the color of the elements that you are drawing, in this case cubes.

I contemplated the best approach on doing this, ultimately settling on drawing onto a bitmap and then mapping out my Leds to individual pixels of said bitmap. I draw what I want onto a bitmap of dimensions 119x145. It only needs to be this small because the amount of data that I can display on the cube is limited to how many Leds I use. At the moment there is a total of 7500 Leds in my cube. If I ever decide to increase the amount of Leds per panel I would then need to increase the size of my bitmap.

The process of mapping the actual Leds to pixels took the longest time of the entire project so far. Having to manually map 7500 pixels is not very fun. Originally creating a byte[] containing all the coordinates I was able to start the mapping process, one... pixel... at a time. I eventually ran into a wall because apparently you can only have so many bytes in your constructor, damn. The next logical step was to move over all the mappings onto an external file and then read from it when needed.

So I created this:

public class PixelMapper {
public static void main(String[] args) throws IOException {
InputStream stream = new FileInputStream("C:/Users/Jano/Documents/DeadMau5 Audio Visualizer/cube_mapping.txt");
Scanner s = new Scanner(stream);
List<Byte> bytes = new ArrayList<Byte>();
while (s.hasNextByte()) {
bytes.add(s.nextByte());
}
byte[] byteArray = new byte[bytes.size()];
for(int i = 0; i < bytes.size(); i++)
byteArray[i] = bytes.get(i);
FileOutputStream out = new FileOutputStream(new File("C:/Users/Jano/Documents/DeadMau5 Audio Visualizer/cube_mapping"));
out.write(byteArray);

System.out.println("Completed!");
}
}

This little piece of code does two things, reads a text file containing all of my coordinates and writes them onto a binary file. I had first read straight from the text file in my wallpaper but the process would take way too long, I'm talking 3 minutes plus long. It seems my phone was simply too slow for the task and much prefers reading from a binary file, which completes in under 5 secs.

After all of the grueling mapping that had to be done, I was rewarded with this:

And here it is with a gray background to better see what's going on:

It is not a static image displayed on the cube but a dynamic image that goes to the music being played. I used the Laser Visual that I had developed for my first Live Wallpaper, Epic Audio Visualizer, to provided the lovely images.

Initially the cube would refresh very slowly, perhaps 5-10 fps, as I each Led would draw itself, making OpenGL ES crawl. So I set out to find a way to speed up the process and thus learned about Batchers.

A Batcher takes all of your vertices, in this case 8 per led, and draws them in one OpenGL call. It increased performance greatly but I lost the ability to change the color of each Led, thus no more lovely pictures. That was until I figured I could use OpenGL once again to solve this issue.

OpenGL ES allows you to assign a color to each vertex and create smooth color transitions between vertices. I don't want smooth transitions between Leds, just solid colors for each one. To remedy the problem and created a float[] and when ever I grab a color from the bitmap I copy it to the array 8 times, once per vertex. I'm not entirely sure this is the most efficient process but I couldn't find another solution that said otherwise.

Surprisingly, it worked rather well and I now get ~30 fps, which is what I currently have it hard maxed at.

With that now complete and my cube running smoothly, dancing away to Pandora, I set out to reproduce the VersaTubes(that's what I discovered they are called) in the background. They look like narrow strips of Leds together, so that's what I called my next class, Strip ;].

Similar to my Panel class, it creates an array of Leds width x height. In my case I create 2 different strips, 2x40 and 2x40. From pictures that I have looked it, it looks like the smaller strips are exactly half the size of the larger ones. Getting all of the positioning and adjustments right, I now have a decent reproduction of the VersaTubes.

My next step is going to be mapping out the strips (exciting! /sarcasm), which should not be too bad. I have already figured out that I will be needing a bitmap of dimensions 54x40, which is great because the smaller the bitmap the less time it times to draw onto it and map the colors.

And that is where I am currently in the project. Congrats on reading that giant wall of text and pictures, I hope you found some enjoyment/motivation/ideas/what ever. As you have probably seen, the cube is not a solid object in itself, but I don't plan on allowing it to rotate that far, if at all, so it really isn't visible when it's actually running.

Look for my next update and I will gladly answer any questions. Feel free to comment and give suggestions. Thanks for reading.