Fisheye Lens Effect
Logi Vidarsson | Michael Sharps
Stanford University - cs348b - Spring 2001

We wanted  to generate a fisheye lens as our main effect.  Fisheye lenses have a 180 degree field of view and as such the model currently in LRT to simulate camera lenses can not handle such a large field of view correctly. This is because all lenses in lrt are flat, hence the standard frustrum projection is no longer a good approximation.

So instead of using the standard frustum, we used a hemisphere as the view space. Since a hemisphere is circular our image plane was also circular. We bumped the image plane up to a hemisphere and used the corresponding hemisphere point as the direction vector, in the coordinate system where the origin was the center of the image plane.

The Texture mapping aspect

Sadly LRT does not come with texture mapping support for primitives other than triangles. Since our scene consisted of more complex items, we needed to implement texture mapping for polygons with more triangles than 2. So how did we accomplish this? Lets start by reviewing what LRT does for texture mapping.

Normally LRT starts by finding the ray object intersections via routines in the object itself. The intersection routines return the u,v coordinates that range from 0 to 1. These are then used to look up in the texture file for the correct color value.

We noticed that for triangles the u,v coordinates given returned are the barrycentric coordinates using any three corner points for reference. This presents a problem when using texture mapping for squares. The corner points are chosen independently for the triangles, so the u,v mapping is not consistent over the common edge of the triangles. Hence it does not look realistic with our wood texture.

However it is possible to order the three corner points used in barrycentric coordinates in such a way that the u,v coordinates are consistent over the common edge. We start by choosing PO in such a way that it is the only point of the triangle that is not on the longest edge. Since in squares the longest edge is always the common edge of its two sub triangles.

Next, we chose a judge vector Vj that is chosen in such a way that it is unlikely to be orthogonal to any triangle in the scene. We use Vj to order P1 and P2 in such a way that | (P1-P0) * Vj | is always larger than | (P2-P0) * Vj |. We then note whether (P1-P0) * Vj is positive or not and then use the provided barrycentric coordinates to figure out u and v.

If (P1-P0) * Vj is negative we note that the triangle is now the "upper right" triangle of the candidate box, hence we need to change the returned u and v such that u = 1- u and v = 1-v. To make sure that the u,v couple is consistent over the common edge of the square.

Notice now that the texture looks much smoother over the edge and in fact you cannot see that these are in fact two triangles.

The Final Scene

Once the fisheye lens implementation was proven accurate on a simple test image, we needed a more detailed scene to showoff the effect. To accomplish this, we used Maya 3.0 for Windows. The tables and chairs were composed entirely of primitives to ease the translation into rib format. Searching the internet, we tested a series of textures before find a best look for the wood furniture. The can was textured using a label of of a 20 once bottle of Citra.

The Movie

What is most exciting about a fisheye lens is the profound effect of the spherical warping on the edges of the image. As objects move around their shape is radically altered. For this reason we also included a movie presentation of our lens. To do this, we needed 78 rib files and resulting images. As a significant amount of time was required to modify a rib file exported from Maya into something that lrt can interpret.  We took steps to expidite the process. First, we keyframed the animation in Maya. Second, we converted the initial rib into an lrt friendly format. For the last frame of the zoom, we exported the rib and cut out the camera transformation matrix. A short script was written to linearly interpolate between the two matricies for 30 time steps. The Matricies of each of the rotated frames were appended to the file with the initial 30 timesteps. Next another script was written to write the 78 rib files. The initial rib file was modified by the script to contain one of the matricies and the number of the animation frame as the name of the output file. A batch rendering was done on lrt. Finally, We composed the Movie in Final Cut Pro and exported it to a quicktime movie.

To Run