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:
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.
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.
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.
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.
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
Memset() or Value Initialization to Zero Out a Struct
Is There a Non-Atomic Equivalent of Std::Shared_Ptr? and Why Isn't There One in <Memory>
Unexpected Order of Evaluation (Compiler Bug)
When Do Extra Parentheses Have an Effect, Other Than on Operator Precedence
Std::Transform() and Toupper(), No Matching Function
Why Does Gcc Compiler Output Pow(10,2) as 99 Not 100
Is There a Compiler Hint for Gcc to Force Branch Prediction to Always Go a Certain Way
Is the Memory Allocated for Struct Members Continguous? What If a Struct Member Is an Array
How to Print the Elements of a C++ Vector in Gdb
Why Do You Use Std::Move When You Have && in C++11
Why Do I Need to Use Typedef Typename in G++ But Not VS
Boost Spirit Semantic Action Parameters
Do I Need to Explicitly Call the Base Virtual Destructor
C++ Modules - Why Were They Removed from C++0X? Will They Be Back Later On