Wednesday, November 9, 2011

OpenGL Update

So, this semester has been a real rough one. So much work, and no time for game development! I'm still convinced no one reads this, but hey, someone might find it interesting somewhere down the line.

So, as for an update, I've learned much more in terms of OpenGL and whatnot. I intend to make a semi-Katamari clone, using my campus as the rolling area. We'll see if that goes anywhere.

Still working on Android stuff. Waiting for my artist to get a new tablet (hurry it up, Nic!).

That's it for now. Perhaps inspiration will strike.

Wednesday, August 10, 2011

OpenGL, Android, and gluUnProject

So, as you know, no one really reads what I put here. And I'm completely alright with that. This isn't a blog to entertain users so much as a place for me to put my nifty little experiments, even if they're slow to come out.

Back on topic. I've recently been toying with OpenGL more and more, and it's known that I have Android games in the works. Now, I've come across my share of annoyances that Google has been... well, not the best resource for once. This has lead me to solving a lot of my Android based problems, particularly with OpenGL.

This post is to go over the annoyance of gluUnProject, which can be found in the GLU package in the Android SDK. I'll post my example of what I was trying to achieve, and how I managed to do it.

So, I'm working on a 2D game which may end up being graphic-intensive, and as such, the Canvas method of rendering has been inadequate -- and allocating objects and deleting them, I've found, does not lend itself to speedy code. But those kind of optimizations have been discussed in a Google I/O video which I'm sure you've seen (you know the one -- it's based on game dev on Android).

The problem I had was trying to convert a screen coordinate (X, Y, touch location) to its corresponding point on a specific plane (z = some value) within the screen (in my case, the "camera_zoom" variable, which is something like z = -50). This was an issue as I had no way to judge the 'game bounds' at that z-value, so I couldn't simply do a ratio. I had to convert window coordinates to object coordinates, which gluUnProject does, but I also had to tell it, "Oh by the way, it's at z = -50.". So I'll get right to it.

Working in the Renderer subclass (the one that your GLSurfaceView has set):

First, I initialized a few static arrays to hold the ModelView matrix, Projection matrix, and Viewport matrix. Because of my application, the only place these values change where it'd impact my gluUnProject is in the "onSurfaceChanged" function.
 public static int[] viewport = new int[16];  
 public static float[] modelViewMatrix = new float[16];  
 public static float[] projectionMatrix = new float[16];  
 public static float[] pointInPlane = new float[16];  
Now, as you can see (clearly) they're all initialized to length 16. This was the first irksome thing. I AM aware that the viewport need only be length 4, and the pointInPlane (the array that will hold the output) be of length 3. But when I tried to do that, I would only get an IllegalArgumentException error from a Matrix Multiplication class stating, "length - offset < n". So, they all get to be 16. Now, again, because my application is how it is, I only alter the matrices and viewport in the "onSurfaceChanged" function. After all the settings code, simply add this block:
((GL11) gl).glGetIntegerv(GL11.GL_VIEWPORT, viewport, 0);
((GL11) gl).glGetFloatv(GL11.GL_MODELVIEW_MATRIX, modelViewMatrix, 0);
((GL11) gl).glGetFloatv(GL11.GL_PROJECTION_MATRIX, projectionMatrix, 0);
Please note that I use GL11, which you should check if your device supports. You can do this by calling:
 gl instanceof GL11  
in a conditional block.

Now, again, one of the things that kept messing up my gluUnProject is that I would forget to load the identity matrix before getting the ModelView and Projection matrix. So, now that this is done, the rest is pretty easy. In order to get the bounds of the game at a certain plane, here's the gluUnProject code:
 GLU.gluUnProject(0, viewport[3], camera_zoom, modelViewMatrix, 0, projectionMatrix, 0, viewport, 0, pointInPlane, 0);  
 gameBounds[0] = pointInPlane[0] * -camera_zoom;  
 gameBounds[1] = pointInPlane[1] * -camera_zoom;  
 GLU.gluUnProject(width, 0, camera_zoom, modelViewMatrix, 0, projectionMatrix, 0, viewport, 0, pointInPlane, 0);  
 gameBounds[2] = pointInPlane[0] * -camera_zoom;  
 gameBounds[3] = pointInPlane[1] * -camera_zoom;  
Now, since I'm working in onSurfaceChaged, width and height are going to be the same as viewport[2] and viewport[3]. The first call gets the (x, y) of the top left of the screen as OpenGL coordinates at z = camera_zoom, and stores those values into gameBounds (defined as a float[4]). The second call gets the (x, y) at the lower right. Simple enough. The last thing you need to do on the output is multiply by the zoom level * -1. That's it. Now gameBounds is filled with OpenGL coordinates for the edges of your surface at z = camera_zoom.

Now, to get a screen coordinate into an OpenGL coordinate at z = camera_zoom. This code is called from "drawFrame", since that was the only place that made sense at the time. You can probably guess it by now.
 GLU.gluUnProject(GameSurface.mouse[0], viewport[3] - GameSurface.mouse[1], camera_zoom, modelViewMatrix, 0, projectionMatrix, 0, viewport, 0, pointInPlane, 0);  
 pointInPlane[0] *= -camera_zoom;  
 pointInPlane[1] *= -camera_zoom;  
If you can't tell, GameSurface.mouse is an int[] that has the screen's mouse x at [0] and mouse y at [1]. Simple enough.

Oh, you do the "viewport[3] - winY" thing to make sure the coordinates are the same -- the top of the window is at y = 0, whereas the bottom of the window in OpenGL is y = 0.

Site note: Someone pointed out that the emulator doesn't handle OpenGL calls that well -- this should work on an actual device, however.

Sunday, July 31, 2011


So, after getting bored, I decided to make something spiffy in flash. Something involving rainbows, since, well, rainbows are spiffy.

Click the button in the lower left to load an MP3. Don't load when in fullscreen, Flash apparently cries when you do that.

Press spacebar to fullscreen.

If that doesn't look nice/work well, here's a link to the page hosting it: Link.

Tuesday, July 12, 2011

OpenGL Stuff

Since this blog isn't a place for me to complain about life, or for me to tell you about how I'm in college and whatnot, I still should apologize for updates being so few and far between. That being said, here's an update.


C++ Stuff:

I've started to learn OpenGL, so I hope I can make something worthwhile to post here that's not just a followed tutorial. Perhaps something will show its face, perhaps not. Here's to hoping.


Java Stuff:

I'm also working on a Magic: The Gathering game, Manticore, that will follow the rules and have its own AI. This has been done before (MTG Forge), but I was dissatisfied with the bugs and the poor AI (poor in how it plays -- what he managed to make is quite impressive).


Android stuff:

I am working on an Android game that is coming along quite well -- hopefully I can post something here without giving too much away, as it is still under development and not ready for the public.

Hopefully there's more to come. I know not many people read this, but hey, maybe someone will someday.

Sunday, May 15, 2011

Published my first app

So, I've finally managed to publish an Android app to the market.

My Item Get App (Post) now has a place in the Android Market!

Market Link:
Click Here to see it on the Android Market

You can also scan this QR code for the market link:

Here's a link to the .apk file, in case the market QR code won't work:
Direct .apk Link

And the QR for that as well:

I am quite excited.

Also, there is a full game in the works! I'll release it here -- trying to keep it from the public until its release.