Advertisement

Circles Manually!

Started by September 12, 2003 07:40 PM
4 comments, last by lobravo 21 years, 5 months ago
I''ve been askin myself how to create a circle, sphere, manually. I''ve been using gluSphere, but it''s time to learn more. Could someone tell me where can i found a tutorial about it? Thanx for the answer....
"There are people who live in the reality. We recreate it!"
x = cos(n) * r
y = sin(n) * r

where:

n is the angle: 0 <= n <= 360
r is the radius
x and y are coordinates of a point on the circle

By iterating n from 0 to 360 by small increments will give you m points on the circle which you can then connect with lines.
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
Advertisement
The idea for a circle is to represent it with a large number of short line segments. Any point on a circle in the xy plane can be represented in polar coordinates (radius, theta), where theta is the angle measured counterclockwise from the x axis. To convert polar coordinates to back to carteesian coordinates, use

x = radius * cos(theta)
y = radius * sin(theta)

So, the code would look like

glBegin(GL_LINE_LOOP);for(float theta = 0.0; theta < 2 * PI; theta += inc){   glVertex2f(radius * cos(theta), radius * sin(theta);}glEnd();   


I'm assuming z is inconsequential to you; you could certainly set it to a constant value for another plane, if you wanted.

One way to do a sphere is to first generate the points for half of a circle and then continually rotate this half circle around another axis building quads (or tris) as you go. For example, you could generate half a circle in the xy plane by using the above code but only going to <= PI. What you are actually doing is rotating a point around the z axis. You could then rotate this half circle around the y axis to make a sphere.

A new point on this sphere would have coordinates
(x * cos(theta), y, x * sin(theta)

Here, x and y are the values that you previously found on the half circle. What this amounts to is taking x to be the radius of a new circle that you're sweeping out.

You iterate over theta from 0 to 2 PI, sweeping out a sphere. During each iteration, you have to remember the previous half circle so that you can generate quads / tris.

Hope this helps.

Oh, one more thing. If you're new, you might want to keep in mind that this method can be used to build any surface of revolution from a profile curve. For example, if you started with a straight, vertical line instead of a half circle, you would end up with a cylinder. This is a really cheap way to make nice things like wine goblets; just define your own profile curve and go, all without having to resort to someone else's model editor...

edit::Crispy beat me to the circle part. Me so slow...

[edited by - UnIcron on September 12, 2003 9:34:42 PM]

[edited by - Unicron on September 12, 2003 9:40:51 PM]

[edited by - UnIcron on September 12, 2003 9:41:55 PM]
Another way to create a circle is to utilize a multitude of single textures to form it. For example, from math you may remember the unit circle in which x is sin() and y is cos(). From one 90/180/270/360, the signs just change so thus you can stipulate each particle''s position based on what number is being entered into x and y.

Here is a circle particle generator that I created some time ago:

Variables
//~~~~~Circle generation    #define circle_objects 500    typedef struct    {        double size;        double x_pos;        double y_pos;        double z_pos;        double red;        double green;        double blue;        double fade;    }    circle_struct;    circle_struct circle[circle_objects];    int degrees_circle;


Ini part
void ini_gen_particles(int mode, double size, double x_edit, double y_edit, double z_edit){    int loop;    if(!size || size < 0)    {        size=.005;    }    //CIRCLE GENERATION    if(mode == 0 || mode == 1)    {        for(loop=0; loop < circle_objects; loop++)        {            circle[loop].size=rand()%100*size;            circle[loop].red=rand()%100*.01;            circle[loop].green=rand()%100*.01;            circle[loop].blue=rand()%100*.01;            circle[loop].fade=1.0;        }        degrees_circle=0;    }//........


Generation of circle
void gen_circle(int pic, double diameter, double thickness, double place_x, double place_y, double place_z,double r, double g, double b, double fade_change){    glDepthMask(GL_FALSE);    glEnable(GL_BLEND);    for(int p=0; p < circle_objects; p++)    {        glPushMatrix();        if(r < 1.1 && g < 1.1 && b < 1.1)        {            glColor4f(r,g,b,circle[p].fade);        }        else        {            glColor4f(circle[p].red, circle[p].green,circle[p].blue, circle[p].fade);        }        circle[p].fade+=fade_change;        glTranslatef(place_x, place_y, place_z);        glTranslatef(diameter*sin(degrees_circle), diameter*cos(degrees_circle), place_z);        glBindTexture(GL_TEXTURE_2D, texture[pic]);        draw_particle(circle[p].size,circle[p].size);        degrees_circle+=1;        glPopMatrix();    }    glDisable(GL_BLEND);    glDepthMask(GL_TRUE);}


Square generation
void draw_particle(double size_x, double size_y){    glBegin(GL_TRIANGLE_FAN);        glTexCoord2f(0.0,0.0); glVertex3f(0.0,0.0,0.0);        glTexCoord2f(1.0,0.0); glVertex3f(size_x,0.0,0.0);        glTexCoord2f(1.0,1.0); glVertex3f(size_x,size_y,0.0);        glTexCoord2f(0.0,1.0); glVertex3f(0.0,size_y,0.0);    glEnd();}


As you can see, it is pretty simple once you realize why you learned about the unit circle in the first place. Hope that helped
Yes, it helped alot. I''ll work on it now and try to make something. Thank you for the help!
"There are people who live in the reality. We recreate it!"
You can also recursively build the faces.

void CSphere::Create(double p_radius = 1., int recurse = 4){  GLdouble a[] = {1, 0, 0};  GLdouble b[] = {0, 0, -1};  GLdouble c[] = {-1, 0, 0};  GLdouble d[] = {0, 0, 1};  GLdouble e[] = {0, 1, 0};  GLdouble f[] = {0, -1, 0};  SphereFace(recurse, p_radius, d, a, e);  SphereFace(recurse, p_radius, a, b, e);  SphereFace(recurse, p_radius, b, c, e);  SphereFace(recurse, p_radius, c, d, e);  SphereFace(recurse, p_radius, a, d, f);  SphereFace(recurse, p_radius, b, a, f);  SphereFace(recurse, p_radius, c, b, f);  SphereFace(recurse, p_radius, d, c, f);}inline void Normalize(GLdouble *v){  GLdouble len = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);  v[0] /= len;  v[1] /= len;  v[2] /= len;}void CSphere::SphereFace(int p_recurse, double p_radius, GLdouble *a, GLdouble *b, GLdouble *c){  if( p_recurse > 1 )  {    // Compute vectors halfway between the passed vectors    GLdouble d[3] = {a[0] + b[0], a[1] + b[1], a[2] + b[2]};    GLdouble e[3] = {b[0] + c[0], b[1] + c[1], b[2] + c[2]};    GLdouble f[3] = {c[0] + a[0], c[1] + a[1], c[2] + a[2]};    Normalize(d);    Normalize(e);    Normalize(f);    SphereFace(p_recurse-1, p_radius, a, d, f);    SphereFace(p_recurse-1, p_radius, d, b, e);    SphereFace(p_recurse-1, p_radius, f, e, c);    SphereFace(p_recurse-1, p_radius, f, d, e);  }  else  {    glBegin(GL_TRIANGLES);    {      glNormal3dv(a);      glVertex3d(a[0] * p_radius, a[1] * p_radius, a[2] * p_radius);      glNormal3dv(b);      glVertex3d(b[0] * p_radius, b[1] * p_radius, b[2] * p_radius);      glNormal3dv(c);      glVertex3d(c[0] * p_radius, c[1] * p_radius, c[2] * p_radius);    }    glEnd();  }}


Stick that in a display list or something and it''ll work real nice. Better yet, store the vertices for a unit sphere and multiply each vertex by your desired radius (larger radii will need a higher recursion factor to look smooth).

---
K-1 Productions: Come visit us here.
---K-1 Productions: Come visit us here.

This topic is closed to new replies.

Advertisement