GameDev.netSuperQuadric Ellipsoids and Toroids, OpenGL Lighting, and Timing

SuperQuadric Ellipsoids and Toroids, OpenGL Lighting, and Timing
superquadric.zip - SuperQuadric Demo and Article(128K). ## SuperQuadric Ellipsoids and ToroidsThere has been some coverage of OpenGL's support for Quadrics via the GLU library. In this article, a superior model using Super Quadric shapes will be discussed. To start with, Super Quadrics are very similar to Quadrics except that we can control the shape with only two variables. Two, we can find if a given point is located inside, on the surface, or outside of the Super Quadric. Another useful operation that can be derived is the Inertia Tensor for rigid body equations. However, that will not be discussed in this tutorial. This code will use the code from NeHe's Lesson 1 as its basis. The two Super Quadrics we will discuss will be the Ellipsoid and the Toroid. The Hyperboloid is another shape but I don't have enough information yet about it to include it here. An ellipsoid is based on a sphere and can be manipulated to generate a variety of shapes including pillows, rounded boxes, "stars," spheres, and others. Toroids are a torus shapes and can be manipulated in the same manor to pinch or squarify its shape. As you may have already suspected, we will need a whole lot of math to generate such equations. There will be no derivations of equations, only the equations that produce these shapes. I couldn't find (or spend much time finding) the derivations for these equations at the time this tutorial was written. Anyway, I think I should explain some of the parameters first. We only need to know about 5 variables for ellipsoids and 6 variables for toroids. The first three are a, and _{2}a and are used to define the radius for the X, Y and Z axes. The next two are the most important, _{3}n and e. These two are used to define the North-South roundness/squareness/pinched and East-West roundness/squareness/pinched shapes, respectively. Plugging a value of 1 for n and e will yield a sphere. Increasing these values will make the shape more pinched, while decreasing them makes the shape more square. Finally, alpha, which is specific to the toroid only, is used for the torus's inner radius.
Anyway, let's get going. First, we will define the mathematical functions for all these shapes. ## SuperQuadric Ellipsoid:
## SuperQuadric Toroid:
If you carefully examine the above equations, you'll notice that the trig functions are raised to a power. Since the domain of the functions include possibly negative cosine and sine results we need to define a proper behavior since raising a negative number to a power is undefined. The correct way to do such an operation is to multiply the sign of that value with the absolute value raised to the desired value. Defined below are functions which do exactly that.
Now that we have those defined, we can start coding! The first thing we have to do is write some utility functions based on the equations above.
Now that those have been defined, we can implement the actual formula that will determine the surface coordinate and normal. To simplify matters, we will use pointers to the data we want to return.
Finally, we can now write the generation functions that will actually draw those shapes using OpenGL. To further optimize this example, we'll implement the ability to generate a OpenGL display list for these objects. To send all our information about the superquadric to the function we'll also define a structure to hold more advanced information.
That's pretty much all you need to generate them. Now for the other functions that can help with colision detection.
Finally, we can add some functions that generate common shapes. You can find the source code in squadric.cpp.
That's all the functions we need. ## Improved C++ Light ClassNext, let's develop a C++ class to encapsulate OpenGL's lighting features. In our implementation, we will encapsulate some of OpenGL's lighting functionality. For now we will only talk about the individual lights. Before we get to any coding, I want to explain some of OpenGL's lighting algorithms so that you know how to use the functions. When I first learned about OpenGL's lighting functions, I had a hard time learning how to use them. First, OpenGL requires that the light have either a position or direction vector. If you want the light to be located at a certain position, be sure that the Next, OpenGL has a few color parameters that can be set to adjust how the light affects primitives. A primitive can be a triangle, quad, or other basic shape that is defined for the creation of objects. There are three colors that can be set. The first of those is the The next color is The final color is As for the rest of OpenGL's lighting features, I know little about how to use them. I am investigating them however. For now, knowing about colors and directional lights will get you going in the right direction. Now, we'll implement the individual light class.
Since most of the function only set values in the class, we'll leave those alone. However, we'll take a look at the Init() and SetValues() functions. Init() simply sets the default values and is compliant with the OpenGL 1.2.1 specification. That means that the default light values are the same as OpenGL's. Init() takes one parameter and that is the same as the corresponding OpenGL ID for the light. So to use the first OpenGL light, GL_LIGHT0, you pass GL_LIGHT0.
SetValues() calls OpenGL and sets all the light parameters that the class is storing. This function must be called after changing any values in the class because it needs to notify OpenGL of the change.
As you can see, these are pretty straightforward functions. Included in the source is a 2D image library that I hacked so I could make some noise bitmaps for the SuperQuadrics. ## TimingTiming is a critical part of developing simulations. Many simulations suffer from this because they don't have support for controlling the speed of their program. Here is a sample implementation of a timing loop in Win32. In this tutorial's program, we have defined a few variables, DTick, Tick1, and Tick2. These are used to store the delta time, initial time, and final time, respectively. These are defined globally so they can be used by the entire program.
Next we have to "prime" the variables so we do this at the very beginning of our program in WinMain. We use the GetTickCount() function to return the number of milliseconds since the computer was started.
Now we go to our loop and do the same calculation except that we replace Tick1 with the value from Tick2 so we can calculate the difference in time since the last frame. We get the delta time by subtracting the two and finally divide by 30.0 to get a factor for updating our variables.
That's all you need and it should keep your simulation running smoother when the computer is faster. On slow computers, it will keep the frame up to date to ensure accuracy. If you have any questions, please free feel to e-mail me at microwerx@yahoo.com. You can also visit my website at http://www.geocities.com/microwerx/ for more information, games, articles, and more!
© 1999-2011 Gamedev.net. All rights reserved. |