I’m working with WebGL and as such, I’m discovering some quirks about OpenGL ES 2.0. I have been using display lists as long as I’ve been using OpenGL, but WebGL doesn’t have support for them. So, I’m buckled down and familiarized myself with vertex buffer objects, the (perhaps better) alternative.

At any rate, I need to render a regular 2D grid, and as it doesn’t support quads, either, I was forced to use triangles. In the interest of getting things running, I just provided a wasteful list of discrete triangles. This is wasteful because it references many more vertices than necessary – I ended up declaring 6n^2 vertices when in reality there are only n^2 + n + 1 unique vertices. This worked fine, until I wanted to increase the resolution. It turns out, JavaScript doesn’t like large arrays.

That’s fair, because the implementation was pretty wasteful. A triangle strip was the best choice anyway. A triangle strip is a highly compact form of representing a mesh. For n triangles, it requires only n + 2 vertices defined. Well, that’s roughly true. We’ll see another case in a minute. It’s useful when many triangles share vertices, and perhaps I’ll let Wikipedia’s explanation stand.

It wasn’t immediately obvious how to define a grid out of a single triangle strip and so I got out a pen and paper. I kept in mind a neat trick: if in a triangle strip, you need to skip the use of a vertex, a vertex can be introduced twice in a row. That is, if I need triangles (6, 3, 7) and (7, 11, 6) in that order, you can just make your strip with 6, 3, 7, 7, 11, 6. You can think of it as if there are two triangles created (3, 7, 7) and (7, 7, 11), but they have no area and a degenerate case – a line. Furthermore, these lines lie on triangles already defined.

Perhaps the obvious choice doesn’t yield any results, and in fact in this layout, it can’t be easily done (you have to have vertices appear three times in a row):

This is a bad idea for a topology if you want to use a single triangle strip.

To better convince yourself, try to come up with a good way to put this in a triangle strip. I’ll make the case that it is pretty difficult with a claim from graph theory. In order for a triangle mesh to be turned into a triangle strip, each consecutive triangle must share an edge. We can then think of the mesh as a connectivity graph (the dual of the mesh) and then the problem will emerge more clearly:

The dual graph of the bad idea.

To make the triangle strip “nice,” we ought to be able to visit each node once and exactly once. There’s good and bad news in this – it’s the same problem as finding a Hamlitonian path which is NP complete. The good news is that if we find a solution to our small problem, we’ve found a solution to all such grids (with arbitrarily many triangles). Note that we don’t need an Eulerian path.

If you stare long enough at the above connectivity graph, you’ll hopefully convince yourself that there’s no way to traverse it visiting each node once and exactly once. Go ahead and try – it’s pretty infuriating.

Looking at how we would traverse one strip (triangles a, b, c, d, e and f) actually gives us a clue. A triangular strip for that case would be 0, 4, 1, 5, 2, 6, 3, 7, and happiness ensues and we should move onto the next row. Unfortunately, in the context of this new row, we’re starting in a different place (topologically) than we started with the first strip. Vertex 0 has two connected neighbors in its row – 1 and 4. Vertex 7 has three in its row: 6, 10 and 11. It turns out we can change up the topology to remedy this simply:

A much better topology for drawing this with a single triangle strip.

A much better topology for drawing this with a single triangle strip.

We can also see that this is a much better solution by looking at this new graph’s dual:

The dual of the better topological choice.

You can probably easily find a Hamlitonian path in this case. But this still leaves us with how to determine the vertex orderings. We decided that the first row ought to be 0, 4, 1, 5, 2, 6, 3, 7, but moving on from there we need a bit of “glue” to move onto the next row. We insert 7 again, and then continue on from there: 7, 11, 6, 10, 5, 9, 4, 8. A bit more glue for the third row: 8, 12, 9, 13, 10, 14, 11, and 15:

An alternative representation of the vertex ordering

Looking at the indices from the first row, starting at 0, we can get the next index by alternately adding 4 and then subtracting 3. On the next row, we’ll continue to add 4, but then alternately subtract 5. The 4 is derived as being the number of vertices on a side (if there are n divisions, then there are n+1 vertices), and the 3 and 5 are explained by the fact that we need to change columns in the mesh, by one step at a time.

An clean implementation is not trivial, but not extremely difficult. In terms of results, I can fit more than 4 times as many vertices into the mesh than with a per-triangle implementation. And to boot, it has cut the work of the vertex shader a great deal.

Tagged with:
 

Silly Mistakes

Every programmer has had this, or at least I like to think that every programmer has experienced this – you compile, press “go,” and epic failure. And the joy doesn’t stop there – then the debugging begins. Occasionally, one encounters a bug that gets the better of them, sometimes for hours, sometimes for days, and sometimes for months.

Hairs is pulled, teeth are gnashed, and eyeballs strain, scouring line after line. You try to convince yourself that your algorithm is correct, and that each line of code is justified. And yet, it still gets the better of you.

After perhaps eight hours, you swallow your pride, and ask a trusted friend to take a look. Often the very act of explaining things to another human being is helpful, but sometimes you both have to dig into the code. Maybe a third friend happens upon the two of you, and joins in.

Then, a light bulb goes off. If you’re lucky, it’s a massive structural change that’s required, but sometimes, it’s a single line, or a single word or character, and you suddenly find yourself embarrassed. But do not be. Every programmer I’ve ever met, no matter how qualified has run into these problems. Still, I find it easy to doubt my competence afterwards.

There are rare and beautiful moments when not only does code compile on the first try, but it runs as expected. Few and far between, cherish these when they come.

This is all inspired from a recent bug I tracked down. An embarrassing one. Sure, had I read the 350 or so pages of the OpenGL ES 2.0 specification, I may have caught it earlier, but this was one of those times when it was a single word that had to change. I tell myself that I won’t keep making these kinds of mistakes, and with each conquered bug I gain a tool, an experience point, and that’s what makes one’s craft.

I’ve looked at the time I spend debugging, and I’ve noticed that the time it takes to solve a bug can often be reduced by leaving the problem for a bit. Taking a walk, getting a cup of coffee, or sometimes watching an episode of Arrested Development. The desire to find and fix a bug is a siren’s song – nearly impossible to walk away from, but often a bad idea.

Tagged with:
 

OpenGLot – Scalar Fields

I’m working on OpenGLot (my OpenGL plotting library) for a class project, and two of the features I decided to implement were contour lines and scalar fields in 2D.

A few days ago I got decent-looking contour lines working and today I got scalar fields implemented with a fragment shader. The programmer using the library can specify a function in the form of a string and have it plotted as a scalar field. Quickly. Really quickly.

Modern graphics cards support shaders, which are programs that get run on the graphics card, and in parallel. This is great for algorithms that can be run in isolation (one pixel doesn’t need to know what the others are doing), which is the case here. OpenGLot generates a fragment shader that colors a single pixel based on the value of the function. Each of the dozens or hundreds of cores on a GPU runs the same code in parallel for their particular pixel.

Contouring for a sinusoidal function with the isovalue 0.

Contouring for a sinusoidal function with the isovalue 0.

Here's a first look at the results (taken moments after this first worked for me).  It's the same sinusoidal function, and I will be improving upon the color mapping in the coming hours.

Here's a first look at the results (taken moments after this first worked for me). It's the same sinusoidal function, and I will be improving upon the color mapping in the coming hours.

The graphing program I use, Grapher.app is rapidly showing its age. The results it gives for the same function (though using a much better coloring scheme) are either grainy or extremely slow (10 or more seconds). OpenGLot is generating these in less than 0.1 seconds. (Grapher.app implements its scalar fields on the CPU, so comparing times is a little like comparing apples and oranges. Still, responsiveness in this type of matter is important.)

The quick (and grainy) plot in Grapher.app

The quick (and grainy) plot in Grapher.app

The slow (but smooth) plot in Grapher.app

The slow (but smooth) plot in Grapher.app

Tagged with:
 

OpenGLot

As a teaching tool for a course last semester, I put together an interactive plotter in openGL which I endearingly named “openGLot.” (For those who missed it, “openGL” + “plot” = “openGLot.”) See, I felt like I had to give it a very unsavory name so that if it ever became widely used, people would be forced to use its ill-sounding moniker.

At any rate, I originally wrote in Ruby, but have been slowly porting it to C++ with high hopes for its use and applicability. I still have a bunch of interactive demos for numerical methods (from Newton’s method to the trapezoidal rule for numerical integration) in the Ruby version, but I’ll be bringing those to the C++ version one of these days. I started a sourceforge project for it a while ago, which was kind of exciting.

At any rate, as a brief (albeit nerdy) respite from the academic onslaught today, I added a class for parameterized curves.

A demo of a parameterized curve in openGLot

A demo of a parameterized curve in openGLot

I’ve got a bunch more primitives to add to it (scalar and vector fields, for example), but those will surely come one of these days. I’ve added adaptive mesh refinement (so that “busier” functions require more sampling to get a more accurate visual representation), but I’m still not quite happy with it.

A "busy" function with no adaptive refinement

A "busy" function with no adaptive refinement

The same "busy" function with recursive refinement.

The same "busy" function with recursive refinement.

I’ve also got a 3D version, but that’s not been polished or formalized, but everyone loves a pretty graph:
openGLot3D

Tagged with:
 

Chess

For Artificial Intelligence, in order to satisfy the final project requirement, I wrote a small chess-playing agent. It’s not horrible, but it’s not going to win any awards. Still, despite its simplicity, I’ve noticed that in games against itself, it exhibits some seemingly second-order behaviors, like forks, pins, skewers and so on. I found that interesting.

I did write a text-based interface for playing against it, but it’s tedious to actually use, and so, having done well in graphics, I decided to write a simple GUI in OpenGL. You can click-and-drag your pieces to where you want them, and then wait for the computer to play. Here’s a screenshot of a game’s conclusion:

A game's conclusion

A game's conclusion

I’d like to give the piece icons transparency on the border so that you can see the underlying square, but that will be a job for tomorrow. Even as it is, I’m pleased with it.

Tagged with:
 

Graphics Project 3

Not long ago we got our third graphics project assigned. In the first we wrote our own raytracer, and in the second we got familiar with OpenGL and implemented a trackball interface that would load a model and allow the user to rotate it around to see it from different angles. This third project deals with texturing, however.

The first part was to generate a torus and texture it with a tile-able pattern (we were given a few wood textures and one brick). Same trackball interface applies.

A torus made of bricks

A torus made of bricks

Next up was to add a way to render a model that’s seemingly made out of mirror, reflecting a virtual environment, provided to us by a teacher. This one seems to be the inside of a building near a window.

Bunny of mirrors

Bunny of mirrors

Lastly, given a 3D texture (marble), we were to “carve” a model out of that material. See Isis and the shark made of marble.

Tagged with: