Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing Sphere in OpenGL without using gluSphere()?

Are there any tutorials out there that explain how I can draw a sphere in OpenGL without having to use gluSphere()?

Many of the 3D tutorials for OpenGL are just on cubes. I have searched but most of the solutions to drawing a sphere are to use gluSphere(). There is also a site that has the code to drawing a sphere at this site but it doesn't explain the math behind drawing the sphere. I have also other versions of how to draw the sphere in polygon instead of quads in that link. But again, I don't understand how the spheres are drawn with the code. I want to be able to visualize so that I could modify the sphere if I need to.

like image 678
Carven Avatar asked Oct 07 '11 12:10

Carven


People also ask

How do you draw a sphere in OpenGL?

In order to draw the surface of a sphere in OpenGL, you must triangulate adjacent vertices to form polygons. It is possible to use a single triangle strip to render the whole sphere. However, if the shared vertices have different normals or texture coordinates, then a single triangle strip cannot be used.


2 Answers

One way you can do it is to start with a platonic solid with triangular sides - an octahedron, for example. Then, take each triangle and recursively break it up into smaller triangles, like so:

recursively drawn triangles

Once you have a sufficient amount of points, you normalize their vectors so that they are all a constant distance from the center of the solid. This causes the sides to bulge out into a shape that resembles a sphere, with increasing smoothness as you increase the number of points.

Normalization here means moving a point so that its angle in relation to another point is the same, but the distance between them is different. Here's a two dimensional example.

enter image description here

A and B are 6 units apart. But suppose we want to find a point on line AB that's 12 units away from A.

enter image description here

We can say that C is the normalized form of B with respect to A, with distance 12. We can obtain C with code like this:

#returns a point collinear to A and B, a given distance away from A.  function normalize(a, b, length):     #get the distance between a and b along the x and y axes     dx = b.x - a.x     dy = b.y - a.y     #right now, sqrt(dx^2 + dy^2) = distance(a,b).     #we want to modify them so that sqrt(dx^2 + dy^2) = the given length.     dx = dx * length / distance(a,b)     dy = dy * length / distance(a,b)     point c =  new point     c.x = a.x + dx     c.y = a.y + dy     return c 

If we do this normalization process on a lot of points, all with respect to the same point A and with the same distance R, then the normalized points will all lie on the arc of a circle with center A and radius R.

bulging line segment

Here, the black points begin on a line and "bulge out" into an arc.

This process can be extended into three dimensions, in which case you get a sphere rather than a circle. Just add a dz component to the normalize function.

normalized polygons

level 1 bulging octahedronlevel 3 bulging octahedron

If you look at the sphere at Epcot, you can sort of see this technique at work. it's a dodecahedron with bulged-out faces to make it look rounder.

like image 160
Kevin Avatar answered Oct 04 '22 04:10

Kevin


I'll further explain a popular way of generating a sphere using latitude and longitude (another way, icospheres, was already explained in the most popular answer at the time of this writing.)

A sphere can be expressed by the following parametric equation:

F(u, v) = [ cos(u)*sin(v)*r, cos(v)*r, sin(u)*sin(v)*r ]

Where:

  • r is the radius;
  • u is the longitude, ranging from 0 to 2π; and
  • v is the latitude, ranging from 0 to π.

Generating the sphere then involves evaluating the parametric function at fixed intervals.

For example, to generate 16 lines of longitude, there will be 17 grid lines along the u axis, with a step of π/8 (2π/16) (the 17th line wraps around).

The following pseudocode generates a triangle mesh by evaluating a parametric function at regular intervals (this works for any parametric surface function, not just spheres).

In the pseudocode below, UResolution is the number of grid points along the U axis (here, lines of longitude), and VResolution is the number of grid points along the V axis (here, lines of latitude)

var startU=0 var startV=0 var endU=PI*2 var endV=PI var stepU=(endU-startU)/UResolution // step size between U-points on the grid var stepV=(endV-startV)/VResolution // step size between V-points on the grid for(var i=0;i<UResolution;i++){ // U-points  for(var j=0;j<VResolution;j++){ // V-points  var u=i*stepU+startU  var v=j*stepV+startV  var un=(i+1==UResolution) ? EndU : (i+1)*stepU+startU  var vn=(j+1==VResolution) ? EndV : (j+1)*stepV+startV  // Find the four points of the grid  // square by evaluating the parametric  // surface function  var p0=F(u, v)  var p1=F(u, vn)  var p2=F(un, v)  var p3=F(un, vn)  // NOTE: For spheres, the normal is just the normalized  // version of each vertex point; this generally won't be the case for  // other parametric surfaces.  // Output the first triangle of this grid square  triangle(p0, p2, p1)  // Output the other triangle of this grid square  triangle(p3, p1, p2)  } } 
like image 41
Peter O. Avatar answered Oct 04 '22 06:10

Peter O.