Drawing Sphere in Opengl Without Using Glusphere()

Drawing Sphere in OpenGL without using gluSphere()?

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.

Sample Image

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.

Sample Image

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 octahedron
level 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.

unable to render sphere without using gluSphere()

I see a couple of problems here. While I haven't used python for this kind of code, I believe it produces an integer result when you divide two integers, like most programming languages. Take a close look at the following line, and a couple of other similar lines:

lat0 = math.pi*(-0.5 + (i-1)/lats)

The (i-1)/lats division will always produce 0, resulting in all of your polygons to be degenerate, and nothing being drawn.

The other main problem is your coordinate range. Your gluOrtho2D call sets the coordinate ranges to (0..640) and (0..480). But your coordinates are in the range (-1..1). So your whole geometry ends up on about one pixel.

Removing the gluOrtho2D call, and adding a type cast to execute the divisions in float, gives me a blue and mostly circular shape. This is with the code converted to C++, my system didn't have these python modules.

The code has more bugs. For example, your first loop starts the index at 0, but then subtracts one from the index to calculate the first angle. But I'm sure that you can figure out the remaining issues once you have something rendering.

Generating a sphere manually

The reason it is getting slower and slower, is because the GLU geometry meshes rendered using GLU uses immediate mode for rendering.

You could download a Java Decompiler and decompile lwjgl_util.jar, then you just follow the package paths to glu.Sphere.Sphere() and then you can lookup the draw() method. Take a look and see how the code works, and then basically create you own method but instead of using glVertex, etc methods. Just add the values to a FloatBuffer, and then create a VBO of the Sphere.

Here is a free Java Decompiler!

openGL: cannot correctly draw a sphere in front of camera

To draw something that doesn't move relative to the camera you simply start from an identity model-view matrix from scratch:

float ndiv = 2.0;
GLfloat f[]={1.0,1.0,1.0,1};

glPushMatrix();
glLoadIdentity(); // <------------- zero out transforms
glTranslated(0, 0, -5); // <------------- translate 5 units from the camera
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, f);
glShadeModel(GL_FLAT);
glBegin(GL_TRIANGLES);
for (int i=0;i<20;i++)
makeTri(vdata[tindices[i][0]], vdata[tindices[i][1]], vdata[tindices[i][2]], ndiv, 0.2);
glEnd();
glPopMatrix();

Draw doesn't works with OpenGL while drawing sphere

You are drawing a number of polygons, were each polygon contains exactly one point:

for (i = 0; i < 4; i++) {
glBegin(GL_POLYGON);
glVertex3f(x[i]*10, y[i]*10, z[i]*10);
glEnd();
}

If you want to draw one polygon with all the points, then you'll have to do something like:

glBegin(GL_POLYGON);
for (i = 0; i < 4; i++) {
glVertex3f(x[i]*10, y[i]*10, z[i]*10);
}
glEnd();

OpenGL/C++ 3D sphere

The call to glDrawElements must look like this

    glDrawElements(GL_QUADS, indices.size(), GL_UNSIGNED_SHORT, &indices[0]);

Also since the draw method is written inline, no SolidSphere:: must prefix it (that would be valid only if the method is defined outside the class.

The code you posted originates in this StackOverflow answer I gave over a year ago: https://stackoverflow.com/a/5989676/524368

And if you look at this answer the definition of draw and the glDrawElements call therein are correct and any edits to the code in the answer were to other parts, but not this. So wherever you took the code from, it got altered with mistakes.



Related Topics



Leave a reply



Submit