3D Graphics

Using the new double buffered graphic library (see previous post) we can now create simple animations. In chapter 12 we have already seen how to visualize a 2D function using a grid and a bit of perspective (isometric). The next obvious step is to look into 3D objects and how to animate them by moving and rotating them in space.

The movement of a 3D object (cube) composed of poligons (squares) is actually pretty simple.  It is a matter of performing a few linear transformations (matrix multiplications) on each of the points (vertexes) of each polygon composing the object.  Each point in space can be considered in his turn a matrix (composed of a single column and three rows: x, y, z) and rotations can be performed by creating a rotation matrix with the appropriate coefficients (actually you will discover soon how using a 4D matrix and 4D coordinates, it is easy to describe translations and rotations in a single pass).

Before drawing each segment composing each polygon, just like we did in the 2D graph example in the book, we will have to apply a simple perspective projection to obtain the screen coordinates.

In particular, to compute the correct coefficients of the rotation matrix, we will have to use trigonometric functions and therefore use the floating point arithmetic libraries. But if we are aiming at a real time animation, this could be a problem as we have seen in chapter 5 that floating point operations are more “expensive” than integer operations and trigonometric functions are among the heaviest of all!

One common approach to this problem is that of replacing floating point arithmetic with fixed point “fractional arithmetic”. Unfortunately the PIC24 standard libraries (and the MPLAB C30 compiler) do not support any fractional format and creating such a library from scratch would require a lot of work and debugging/validation time.

So I suggest we  take a much simpler approach to the problem. A bit too simplistic some will say, but definitely adequate for the application.  After all if we apply an adequate scaling factor to each value, we can discard any fractional part and use just integer math.

The scaling factor will decide our precision, for example, by applying a scaling factor of 100 we will limit all our calculations to the precision equivalent to 2 decimal places.

For example if x is a coordinate, we will use only the integer part of x*100 in all our calculations.

NOTE: When multiplying two scaled values we will have to remember to divide the result once by the scaling factor to maintain the “scale” true.

The trigonometric functions can then be approximated by using degrees instead of radians and by taking only integer values in the range from 0 to 359, or for all practical purposes 0-90, and tabulating just the sin function. Cosine and tangent would be derive easily.

Here is the highly simplified integer geometry library that we will use:

geometry.c and its include file geometry.h

And in a few lines of code, here is an animation of a (partial) cube carrying an inscription on one face: cube.c

Put it all together with the graphicDB.c library in a project and test the new 3D capabillities  of the PIC24!

This entry was posted in AV16/32, Graphics, Tips and Tricks. Bookmark the permalink.