Subscribe to:

The Kiwi's TaleWitchBlasterDerelict Blow Stuff Up

3D Textured Polygons in Monkey

Edit: I moved the demo to here to stop it from slowing down the Mode 7 demo. One HTML5 app on the blog stream at a time is enough!

Viola! Drag the corners to reshape the image.

Some background: It's literally impossible to do a "perspective" transformation (such as reshaping an image to be like a trapezoid) with a six element 2D graphics matrix, such as that used by HTML5, and therefore Monkey. In other words, when transforming an image, lines that were parallel before the transformation will remain parallel after that transformation.

I discovered this when I was porting Heart of Ice. Instead of being able to generate the room backgrounds on the fly, I had to manually prefabricate them in Paint Shop Pro.

As I mentioned on my previous blog post, I've been working on a "floor caster", but it's difficult to get it running both smoothly and looking good in Monkey's HTML5 target, due to the massive amount of drawing calls I need to do. So I started to think that maybe the SNES "Mode 7" effect would be better. Instead of "casting rays" from the camera to spots in the 3D world to calculate which part of the texture to draw, Mode 7 transforms a 2D image into 3D space. Super Mario Kart, for instance, transforms a 2D map of a race track into the 3D race track itself. But even a convincing Mode 7 effect is difficult to pull off in Monkey due to, again, not being able to do perspective transforms on images.

Giving up on the idea of doing Mode 7 in pure Monkey, I thought it might be possible to do it through extending Monkey with a custom Javascript class. Eventually I stumbled upon this neat little HTML5 demo that pulls off perspective transforms very nicely with a neat trick - splitting the image into a number of rows and columns, and then rescaling, rotating and cropping each segment to approximate a perspective transformed image. A couple of hours later, I managed to make a basic clone of the demo in pure Monkey, with no additional Javascript at all (so the demo works identically on all of Monkey's export paths). The image is split up into 32 rows and 32 columns, each segment containing 8x8 pixels.

This demo's certainly not as optimal as it could be. The original pulls off a more convincing effect by clipping each segment to it's exact shape (so there is no overlaping between segments or jaggedness at the edges). I may look at doing custom Javascript to support that, but it'd only work in Monkey's HTML5 export.

There's certainly a few potential uses for the idea. Obviously attempting a full blown 3D engine would be ridiculous (very leet if you could pull it off though). But it may be useful for faking Mode 7 at least. Look out for Earok Kart, the racing game you've been waiting your entire life for!

Edit: Looking at it again, I can see that I didn't get the perspective effect right. It's because the divisions are divided up evenly, in the original they're divided up so that the divisions get closer together as it goes into the distance. I'll take another look at it some other day.



Stephen Knightly (not verified)

Cool. You can do a simple page turn animation with this easily.

Earok's picture
Joined: 02/06/2009

Yeah, it could certainly do that with a few tweaks. I wonder what usage scenerio we'd want that particular effect for? ;)