Goodbye Hypr3D

It seems the sun has set on the good old Hypr3D app. This was the first commercial app to use a licensed copy of my 3D Engine back in 2011.

Hypr3D's help page showing the viewer's recognized gestures.

Hypr3D’s help page showing the viewer’s recognized gestures.

Hypr3D rendering a reconstructed pineapple model on an iPhone.

Hypr3D rendering a reconstructed pineapple model on an iPhone.

Back in the day, the Vortex Engine was on its 1.0 version and it was pretty much done when the App was developed. Although this made using it almost a “plug and play” experience, there were some interesting problems that had to be resolved during the App development process.

On problem in particular was how to integrate a HTML UI with the Objective-C Front Controller of the App. This was way before any of the modern “hybrid app” toolchains existed and I remember I was on a trip to Seattle when I started to lay down the main concepts.

Goodbye Hypr3D, I’ll always remember the countless hours staring at the cookies reference model while debugging!

Hypr3D's model viewed rendering a reconstructed model featuring a pile of rocks on an iPad

Hypr3D’s model viewed rendering a reconstructed model featuring a pile of rocks on an iPad

I’ve created a dedicated page in the memory of Hypr3D with a short feature list and some more screenshots. You can visit it here.

Although Hypr3D may not be available anymore, Vortex Engine 1.0 is anything but dead. Stay tuned ;)

MD2 Library 2.0

MD2 Library 2.0 has been out for a while now (download here), but I haven’t had the time to update this blog! It’s a free download for all iPad users, and, at the time of writing, all iOS versions are supported (from 3.2 up to 7).

MD2 Library 2.0.

MD2 Library 2.0, powered by Vortex 3D Engine 2.0.

The App has been revamped to use the latest version of my custom 3D Renderer: Vortex 3D Engine, bringing new features to the table, including:

  • Per-pixel lighting with specular highlights.
  • Realtime Shadows (on iOS ≥4).
  • Antialiasing (on iOS ≥4).
  • User experience enhancements.
  • General bug fixes.

I took advantage of this due update to vastly improve the internal architecture of the App. The latest features in the Vortex Engine enable providing a much better user experience from an easier codebase and leveraging a simplified resource management scheme.

Head to iTunes to install for free or, if you have version 1.1 installed, just open up the App Store to update the App.

Shadow Mapping on iPad

I’ve implemented shadow mapping on the MD2 Library using the Vortex Engine for iOS wrapper. Shadow mapping is a technique originally proposed in a paper called “Casting Curved Shadows on Curved Surfaces” [1], and it brought a whole new approach to implementing realtime shadows in 3D Apps.

Shadow mapping on iPad. The shadow is calculated in realtime and animates as the model moves.

Shadow mapping on iPad. The shadow is calculated in realtime and animates as the model moves.

Implementing shadow mapping on iOS is by nature a problem that spans several programming languages. Objective-C for creating the UI, C/C++ for interfacing with OpenGL and GLSL for implementing the technique in the GPU’s fragment shader.

The math involved in shadow mapping spans all of these languages, with different coordinate space transformations being implemented in the language appropriate to the pipeline stage we’re working on. This makes the technique a little tricky to implement the first time you attempt to.

Here is another screenshot of the technique running on an actual iPad. Notice how the shadow is cast on the floor as well as on top of the crate in the background.

Upfront capture of the shadow mapping technique running on the iPad simulator.

Upfront capture of the shadow mapping technique running on the iPad simulator.

Shadow mapping will be coming up in the next version of the MD2 Library app.

[1] – Lance Williams – Casting Curved Shadows on Curved Surfaces. http://artis.imag.fr/~Cyril.Soler/DEA/Ombres/Papers/William.Sig78.pdf

A short detour along the way…

I wanted to improve the Stencil Shadow Volumes code a little bit and enable it for the Programmable Pipeline in Vortex, however, I had to take a small detour to fix an issue related to mobile device support.

It turns out that OpenGL ES, the 3D library that Vortex uses to render its graphics on mobile devices, does not support rendering indexed geometry for indices larger than 16 bits. Keep this in mind when developing for mobile devices such as the iPhone or iPad.

I can completely understand the reasoning behind this decision. 32-bit indices could be considered too much data to submit to the GPU in a mobile device. Furthermore, they are not strictly necessary, as they could be replaced (if needed) by splitting the geometry into two groups defined by 16-bit indices.

The solution I devised, which is now part of Vortex 2.0, is to allow the user to specify the data size for the indices when defining the geometry. This provides the flexibility to use 32, 16 or 8 bit indices. You can even have several geometric objects with different index sizes in a scene.

The advantage of leveraging this mechanism is that now it is very easy to fine-tune the number of bytes used for index representation for improving performance. For example, using 16-bit indices instead of 32-bit indices would make no difference for representing models composed of less than 65536 vertices, while requiring a copy of just half the number of bytes to the GPU.

In the extreme case of 8-bit indices we would be constrained to only 256 vertices, but we would be sending only one fourth of the data to the GPU.

This was mostly plumbing work, so no new picture this time. Stay tuned for more updates!

Objective-C Blocks

Lately, I have been playing with Objective-C blocks.

These are easy to use constructs that enable defining functions “on the fly” when programming in Objective-C and are very similar to Python’s lambdas.

The syntax might look a little weird at first, but it is not that different from working with function pointers in C.

Here’s a simple example of a function f that receives a block b as a parameter and calls it. The only restriction imposed on b by f is that it must be a block that takes an int argument and returns an int.

#include <stdio.h>

// f is a function that receives a block:
void f(int (^b)(int))
{
	b(0); //call the block
}

int main(int argc, char* argv[])
{
	// Define and pass a block to f():
	f(^(int p){ printf("%d\n", p); return 0; });

	return 0;
}

The output of this program is just the int supplied by f to the block b.

Let’s try a more interesting example. Here, as inspired by this post, we use blocks to define a general-purpose for_each function that receives a list of objects and a block and then applies the block on each element of the list.

In order to define a general-purpose for_each function, we take advantage of Objective-C’s dynamic typing and name our types id.

void for_each(NSArray* array, void (^b)(id))
{
	for (id obj in array)
	{
		b(obj);
	}
}

Now, let’s develop a short program to test the for_each. This program creates a list of strings and uses the for_each function to output all of its contents.

int main(int argc, char* argv[])
{
	// Default autorelease pool:
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
	
	// Create an array. The contents could be anything,
	// as long as the block can handle them:
	NSArray* array = 
	[NSArray arrayWithObjects:@"a", @"b", @"c", @"d", @"e", nil];

	// Print every string instance:
	for_each(array, 
		^(id str){ printf("%s\n", [str UTF8String]); });

	[pool release];
	
	return 0;
}

Suppose now that we wanted to print out strings in uppercase. No problem, we can keep all the same structure, we just need to change the block:

	for_each(array, 
		^(id str){ 
			printf("%s\n", [[str uppercaseString] UTF8String]); 
		});

So, what happens if we place an object of a type different from a NSString instance in the array? Well, the for_each is very general and doesn’t know anything about the array’s elements or the block’s internals. Thus, if there is a problem, it will be triggered inside the block code.

Imagine we attempt to send uppercaseString to an object that does not recognize that message. If this happens, an error will be triggered at runtime and abort() will be called, canceling our program.

As we move into dynamic coding, the code becomes more flexible, but we must be more careful not to trigger runtime errors in our programs. It’s important that we develop our blocks to be consistent with our data structures.

iPhone OpenGL Retina Support

When Steve Jobs introduced the Retina Display feature for iPhone 4 and iPod Touch, he mentioned media content should be now adapted to the new devices, in order to make the most out of the high resolution available.

The introduction of Retina Displays took the resolution of the iPhone and iPod Touch devices from a 320×480 pixel screen up to a whooping 640×960 canvas. That’s 4 times more pixels to render. You can see the difference it produces in the following image: notice the area around the silhouette of the Gunner model.


A Retina Display-enabled OpenGL viewer (left) vs a Non-Retina Display Viewer (right).



While listening to the Keynote, I didn’t think OpenGL applications would have to be adapted, as OpenGL renders “on the fly” and I would’ve thought it would be enough just to set a bigger viewport.¬†After testing one of my Apps on a Retina-enabled iPod touch however, I realized my Vortex-Engine Apps were not making use of the Retina Display, falling back to a low-res display mode.

After a little Googl’ing, I found the problem. It seems the EAGLView class I was using to create and manage my OpenGL contexts (taken from the Xcode OpenGL ES template) was accounting for the higher resolution by making every pixel 4 times as big! I guess this is something necessary to prevent content that would work fine on older devices to be shown using 1/4th of the screen size on Retina-enabled devices. On the other hand, it was wasting 3/4 of the pixels available on the newer devices, so something had to be made for this special case.

I found the solution to this problem in David Amador’s blog, (here’s the link: http://www.david-amador.com/2010/09/setting-opengl-view-for-iphone-4-retina-hi-resolution/). The idea he presents is to make use of the extra available pixels in Retina Displays by scaling the content up to 2X the size, that way we get rid of this “backwards-compatible” display mode. I rather think about it more like “halfing the pixels” in both directions.

In any case, here’s the code snippet needed to do that. Once we know the screen width and height (using the UIScreen singleton), we can add the following snippet to the EAGLView initWithCoder: method:

if (width == 640 && height == 960)
{
    // We have a Retina Display:
    self.contentScaleFactor = 2.0f;
    eaglLayer.contentsScale = 2.0f;
}

This will automatically make your OpenGL application take advantage of the extra pixels available in Retina Display devices. No further changes in your OpenGL code are needed, as long as you keep the binding from the EAGLLayer instance to your Viewport and RenderBuffer(s).

You can notice the difference these three lines make in the image above. Click on the image to see it in full size and prevent browser smoothing; you will notice the difference between Retina Display enabled OpenGL content (left) and non-Retina content (right).

Vortex-Engine has been patched and now happily supports newer and older generation devices ; )

Corona Game Engine looks really easy

The Corona Game Engine looks like a really easy to use solution for developing iOS and Android applications.

From what I could see in the video, the scripting language it’s using must be Lua, or at least Lua-like. It sports a crystal clear syntax and provides access to the Game Engine’s power without hassle.

Here’s the promotional video featured at their website. It looks completely amazing.