org.proteinshader.graphics
Class Sphere

java.lang.Object
  extended by org.proteinshader.graphics.Shape
      extended by org.proteinshader.graphics.Sphere

public class Sphere
extends Shape

Knows how to draw a sphere with texture coordinates, a surface normal, and a tangent vector for each vertex. To speed up rendering, methods are provided for creating and using OpenGL display lists.

The draw() method and its helper method, drawVertex(), are ultimately based on the algorithm found in the C++ file

bump_mapping.cpp by Cass Everitt - cass@r3.nu
Copyright (c) 2000 Cass Everitt
Copyright (c) 2000 NVIDIA Corporation


bump_mapping.cpp has, therefore, been included in the same directory as this class, and includes a copyright notice that allows it to be redistributed with certain restrictions. The draw() method is now in a rather different form, but the copyright notice may still apply, so bump_mapping.cpp should be kept with this file.

The basic concept of drawing one stack at a time is taken from bump_mapping.cpp, but there are several changes. The first difference has to do with how slices and stacks are defined, and is related to what is sometimes referred to as the fence-post problem. If you build a fence of rails and posts, and each rail has to have a post at both the beginning and end, then the length of the fence has a slightly different meaning whether you define it in terms of the number of rails or posts: if you say that the fence is length n in rails, then the fence must have n + 1 posts. On the other hand, if you say that the fence has a length of n posts, then it must have n - 1 rails, not n rails.

Apparently, a similar issue comes up in interpreting what the number of slices and stacks means in a sphere. In the gluSphere() method of the glu.h library, if you have n stacks, there are n + 1 lattitude lines (strictly speaking, the first and last lattitude lines are really points at the North and South pole rather than lines), so these lattitude lines divide the sphere into n parts (stacks). However, in bump_mapping.cpp the number of stacks is taken as the number of lattitude lines, so n stacks results in dividing the sphere into n - 1 parts (rather than n parts).

In the code below, the definition being used by the glu library (n stacks gives n + 1 lattitude lines) is being used rather than the slightly different approach in bump_mapping.cpp. The same issue comes up for slices, and, again, the glu library definition is being used, so n slices give n + 1 longitude lines, not the n longitude lines used in bump_mapping.cpp (note that when drawing a sphere or cylinder the first and last longitude lines are in the same place so that a closed shape is created).

Other than the stacks and slices issue mentioned above, the mathematics in draw() are essentially the same as in bump_mapping.cpp, but the way information is sent to the vertex shader is different, in that existing OpenGL variables are used to send the vertex coordinates, texture coordinates, surface normals, and even tangent coordinates to the vertex shader, rather than with glVertexAttrib() functions. The binormal vector is not calculated, as this can easily be determined in a vertex shader as the cross-product of the surface normal and the tangent.


Field Summary
static int MIN_TILING
          The minimum tiling is 3, and it is used to set the minimum number of slices and stacks for a sphere.
 
Fields inherited from class org.proteinshader.graphics.Shape
HALF_PI, PI, SPECULAR_COLOR, TWO_PI
 
Constructor Summary
Sphere()
          Constructs a Sphere.
 
Method Summary
 int createDisplayList(GL gl, double radius, int slices, int stacks)
          Creates an OpenGL display list that holds the commands for drawing a sphere.
 SphereListInfo createDisplayList(GL gl, SphereListInfo info)
          Creates an OpenGL display list for drawing a sphere with the radius, number of slices, and number of stacks specified in the SphereListInfo object given as an argument.
 void draw(GL gl, double radius, int slices, int stacks)
          Draws a sphere with texture coordinates, normals, and tangents.
 
Methods inherited from class org.proteinshader.graphics.Shape
deleteDisplayList, executeDisplayList, executeDisplayList, setMaterial
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

MIN_TILING

public static final int MIN_TILING
The minimum tiling is 3, and it is used to set the minimum number of slices and stacks for a sphere.

See Also:
Constant Field Values
Constructor Detail

Sphere

public Sphere()
Constructs a Sphere.

Method Detail

createDisplayList

public SphereListInfo createDisplayList(GL gl,
                                        SphereListInfo info)
Creates an OpenGL display list for drawing a sphere with the radius, number of slices, and number of stacks specified in the SphereListInfo object given as an argument.

The name of the display list (an integer) will be stored in the SphereListInfo object given as an argument, and this same object is the return value of this method.

If the SphereListInfo object given as an argument already has a valid reference to an OpenGL display list, that old display list will be deleted before the new display list is created. If the number of slices or stacks is less than MIN_TILING, the number will be reset to the minimum.

Parameters:
gl - the current GL object.
info - a SphereListInfo object with values for radius, slices, and stacks.
Returns:
The same SphereListInfo object given as an argument, but now it has a reference to a newly created OpenGL display list.

createDisplayList

public int createDisplayList(GL gl,
                             double radius,
                             int slices,
                             int stacks)
Creates an OpenGL display list that holds the commands for drawing a sphere.

For most purposes, a radius of 1.0 is the best choice because that will allow the sphere to be easily scaled to any desired final radius by using the desired final radius as a scaling factor.

If the number of slices or stacks is less than MIN_TILING, the value will be set to the minimum.

Parameters:
gl - the current GL object.
radius - the radius of the sphere.
slices - the number of slices in the sphere.
stacks - the number of stacks in the sphere.
Returns:
The name (an integer) of the OpenGL display list.

draw

public void draw(GL gl,
                 double radius,
                 int slices,
                 int stacks)
Draws a sphere with texture coordinates, normals, and tangents. If the number of slices or stacks is less than MIN_TILING, the value will be set to the minimum. If the radius is zero or negative, a point will be drawn instead of a sphere.

ALGORITHM:

If there are n stacks, there will be n + 1 lattitude lines, with the first and last longitude "lines" really being a point at the South or North pole, respectively. The South pole is at the phi angle -90 degrees, while the North pole is at phi angle 90 degrees.

If there are n slices, there will be n + 1 longitude lines. The first longitude line will be at 0 degrees, while the last will be at 360 degrees.

An outer for-loop will draw each stack (the segment between two lattitude lines) as a GL_TRIANGLE_STRIP. For example, if only 4 stacks were used, the first stack would be between phi angles -90 and -45 degrees, the second stack would be between -45 and 0 degrees, the third stack would be between 0 and 45 degrees, and the fourth stack would be between 45 and 90 degrees.

An inner for-loop will draw the vertices. If the number of slices is only 4, the first pair of vertices drawn would have a theta angle of 0 degrees, the next pair would have a theta of 90 degrees, the next pair a theta of 180, the next next pair a theta of 270, and e last pair a theta of 360. Because there is an alternation beteen the low and high phi angle of each stack, the pattern can get a little hard to follow, so it is summarized below for the first stack (first GL_TRIANGLE_STRIP) of a sphere with 4 stacks and 4 slices.

Vertex: (phi, theta)
--------------------
1: (-90, 0)
2: (-45, 0)
3: (-90, 90)
4: (-45, 90)
5: (-90, 180)
6: (-45, 180)
7: (-90, 270)
8: (-45, 270)
9: (-90, 360)
10: (-45, 360)

Parameters:
gl - the current GL object.
radius - the radius of the sphere to draw.
slices - the number of slices to draw the sphere with.
stacks - the number of stacks to draw the sphere with.


Copyright © 2007-2008