Da Fish in Sea

These are the voyages of Captain Observant

A 3D Heart for Valentine's Day

| Comments

For Valentine’s Day I’ve dusted off an idea I initially submitted last year as part of the now defunct 25 Lines ActionScript contest. By tweaking the formula which generates the coordinates of the sphere, I was able to get something that more or less looked like a heart. I was able to get the heart modeled and lit within the 25 lines, but could not quite squeeze in the code to animate it. Now, without the limitation of 25 lines, I’ve done that, as well as optimize the performance using the normal map + PixelBender normal map shader that I used in my normal map tutorial. Here is the result - use the sliders to change the direction of the lighting.

flash 10 required

How it Was Done

The mechanics of this are essentially the same as the lighting of a sphere technique described in the normal map tutorial. However, since the shape of the heart is not the same as a sphere, I could not use the sphere formula to generate the normal map. So I just used the same formula to generate the normal map as I did to generate the geometry. For each point on the texture map, I determined the lat/lon of that point, and plugged it in to the formula to get its 3D position. I did the same for the pixel above and to the right. Since we now have three points, we have a triangle, and we can get the normal of the triangle by the cross-product of two of the sides (considered as vectors). This normal gets encoded as a color in the resulting normal map. This is a fairly intensive operation, but since it is only required once at the start, it doesn’t affect the running performance. I tried to optimize this process by using a PixelBender kernel to generate the normal map, but got some odd results, so returned to more familiar ActionScript territory. Using a shader to generate the normal map will become necessary if the geometry changes a lot.

I also refactored the code a lot so that it’s not all in one class. I’ve separated the model, shader and renderer into separate classes, and used a Scene to coordinate them. This is the beginnings of a primitive 3D engine, which I’ve dubbed DeepSee, so if that goes anywhere I may break it out as a separate project on GitHub.

Da Code

Heart2
DeepScene
Heart.as
IModel.as
NormalMapShader
NormalMapShader.pbk