OpenGL - circle not being drawn smooth - c

I am drawing a circle using OpenGL, with the set of calls being:
float delta_theta = 0.001;
glBegin(GL_POLYGON); // OR GL_LINE_LOOP
glEnable( GL_LINE_SMOOTH );
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (angle = 0; angle < 2*3.1415; angle += delta_theta)
glVertex3f( radius*cos(angle), radius*sin(angle), 0 );
glEnd();
The problem is that the circle is not smooth. I am moving (translating) the circle along axes; at some points it becomes smooth, but mostly, it's like a blot, please see the attached screenshot.
Any suggestions as to what I could do to smoothen the circle?

I would suggest you not try to implement this with lines or a filled polygon for one thing.
Use a single GL_POINT and enable GL_POINT_SMOOTH. That will rasterize the point as a filled circle instead of the normal square. It will be much more efficient, provided you use a point size your implementation supports for anti-aliased points (often up to ~ 63.5 on NV implementations, more on others).

Related

GLFW3/GLU 3D world space using static pipeline

In previous projects, I enabled depth testing used gluPerspective called once on startup to set up a 3D space. Currently, I am rendering a square between -0.5 and 0.5 with 0.0 as its origin after the 3D world has initialised with code below will cause a square to cover the entire screen:
glBegin(GL_QUADS);
{
glVertex3f(-0.5, -0.5, 0);
glVertex3f(-0.5, 0.5, 0);
glVertex3f(0.5, 0.5, 0);
glVertex3f(0.5, -0.5, 0);
}
glEnd();
What I am looking is a way to set the perspective so that shapes are rendered in world space. For example, the snippet below should cause a square of 200x200 to be rendered:
glBegin(GL_QUADS);
{
glVertex3f(-100, -100, 0);
glVertex3f(-100, 100, 0);
glVertex3f(100, 100, 0);
glVertex3f(100, -100, 0);
}
glEnd();
The code below is what I am currently using to initialise a 3D world.
// WINDOW_WIDTH = 1600, WINDOW_HEIGHT = 900
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(47, WINDOW_WIDTH / WINDOW_HEIGHT, 0.01, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
Have I missed any steps in setting up a 3D space and if gluPerspective is used to do this any suggestions why it is not working?
I am able to achieve this in 2D using ortho, it is important that the world is 3D.
Everything is being written in C using OpenGL and GLU up to 1.3 with my GLFW set up identical to this. Due to technical restraints, I am unable to use the modern pipeline.
First of all, the result of WINDOW_WIDTH / WINDOW_HEIGHT is 1, because WINDOW_WIDTH and WINDOW_HEIGHT are integral values. You have to perform a floating point division ((float)WINDOW_WIDTH / WINDOW_HEIGHT) to compute the correct aspect ratio.
At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport.
The projected size of an object on the viewport depends on its distance to the camera. The different size at different distances (depths) causes the perspective effect. The perspective projection matrix defines a Viewing frustum
The ratio of projected size and the distance to the camera depends on the field of view angle:
maxDim / cameraZ = tan(FOV / 2) * 2
So there is exactly 1 distance where an object with a length of 200 covers 200 pixel. For instance, If you have a filed of view angle of 90° then an object with a z distance of half the window height (height /2) and a vertical size of 200 covers 200 pixel (vertical) because tan(90° / 2) * 2 = 2.
When you use gluPerspective, then you define the field of view angle along the y axis. The field of view along the x axis depends on the aspect ratio. If the aspect ratio is set correctly, then the projection of a square which is parallel to the xy plane of the view is still a square.
Note, if you would use orthographic projection, then the size of the object is independent on the distance.

OpenGL - glusphere not smooth

I have been experimenting with the arguments to glusphere(). The problem is that the sphere is not smooth, and looks more like a blot. Right now, my call looks like this:
glPushMatrix();
glTranslatef(0.1, 0.1, 0.0);
GLUquadricObj *quadric;
quadric = gluNewQuadric();
gluSphere(quadric, .02 , 32 , 16);
glPopMatrix();
Any suggestions as to what looks not right with this code snippet will be appreciated. My understanding is that the higher the value of 3rd and 4th argument, slices and stacks, respectively, the smoother the edges of the sphere will be.
EDIT:
Changing the translation coordinates to (0.08, 0.08, 0) results in a much smoother sphere.

GluProject Not showing Accurate coordinate in C

I am trying to find the screen coordinates from the opengl coordinates(projected in 3D space) I have used glproject call for this purpose,i have used rotation and translation to in my code
At certain point after performing some transformation, i called glproject api to get the screen coordinate of a particular projected point P(x,y,z)
glproject(x,y,z,modelMatrix,projectionmatrix,viewport,*x_s,*y_s,*z_s);
I am able to get x screen coordinate correctly in x_s , but y coordinates are different
The only change in y which is not in x is when initially i called the glperspective to set fovy(The field of view angle, in degrees, in the y-direction). gluPerspective(60.0f, Width/Height,0.0001f,1000.0f);
Let me Rephrase the question I have created a 3D point on screen and now i am getting the 2d(x,y) coordinates of that point through GLproject they come different from the mouse coordinates What could be the possible solution to get correct coordinates.
Here is the code snippet
#include<GL/glut.h> /* Header File For The GLUT Library */
GLint Window; /* The number of our GLUT window */
float tmp_x,tmp_y,tmp_z;
GLfloat w = 1200; /* Window size. Global for use in rotation routine */
GLfloat h = 1200;
GLint prevx, prevy; /* Remember previous x and y positions */
GLfloat xt=1.0,yt=1.0,zt=1.0; /* translate */
int width = 1600;
int height = 1200;
//This function will set windowing transformation
void transform(GLfloat Width , GLfloat Height )
{
glViewport(0,0, (GLfloat)Width, (GLfloat)Height);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, Width/Height,0.0001f,1000.0f);
glTranslatef(0.0, 0.0, -15.0f); /* Centre and away the viewer */
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
GLvoid draw_room()
{
int i;
glPushMatrix();
glShadeModel(GL_SMOOTH);
glLineWidth(1.0);
glPointSize(4.0); /* Add point size, to make it clear */
glBegin(GL_POINTS); /* start drawing the cube.*/
glColor3f(0.0f,0.0f,1.0f); /* Set The Color To Orange*/
glColor3f(1.0f,0.0f,0.0f); /* Set The Color To Orange*/
glVertex3f(3.1f,2.1f,2.1f);
glEnd(); /* Done Drawing The Cube*/
glEnable(GL_DEPTH_TEST);
}
//OpenGl Display callback Function It call init room
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
printf("%f %f %f\n",xt,yt,zt);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(xt,yt, zt);
draw_room();
glPopMatrix();
glutSwapBuffers(); /* Swap buffers */
glFlush();
}
GLvoid Mouse( int b , int s, int xx, int yy)
{
double a1,a2,a3;
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
//gluProject(xt+3.1f,yt+2.1f,zt+2.1f, modelview, projection, viewport, &a1, &a2, &a3);
gluProject(3.1f,2.1f,2.1f, modelview, projection, viewport, &a1, &a2, &a3);
printf("Mouse: %d %d\n",xx,yy); // Both Print are giving different coordinaes.
printf("Unproject %f %f %f\n",a1,a2,a3);
switch (b) {
case GLUT_LEFT_BUTTON: /* only stash away for left mouse */
prevx = xx - w/2;
prevy = h/2 - yy;
break;
case GLUT_MIDDLE_BUTTON:
break;
case GLUT_RIGHT_BUTTON:
break;
}
}
What could be the possible solution for this?
OpenGL uses lower left corner of screen as coordinate system orign. Window system usually uses upper left corner as coordinate system orign. You need to handle this difference. Example:
printf("Mouse: %d %d\n",xx,yy);
printf("Unproject %f %f %f\n",a1,viewport[1]-a2,a3);
A side issue:
gluPerspective(60.0f, Width/Height,0.0001f,1000.0f);
You have a very large ratio between your near and far plane distance. This is very bad for depth resolution. As a general rule you should set the near clip plane distance as far as possible, as the scene allows. The far clip plane for a projection as created by gluPerspective should be set as near as possible (it's also possible to set the far clipping plane to infinity if the projection matrix is built slightly different).
Anyway, your low depth resolution will have a negative impact on your mouse pointer screen position back projection.
Let me Rephrase the question I have created a 3D point on screen and now i am getting the 2d(x,y) coordinates of that point through GLproject they come different from the mouse coordinates What could be the possible solution to get correct coordinates.
Most window systems put the pointer coordinate system origin to the upper left. OpenGL sets the viewport coordinate system origin into the lower left. So you'll have to invert the mouse position in the window along the Y=Up axis.

Simple form with pixel manipulation with opengl in linux

i want to create a 800X600 window that just show some circle and be able to manipulate pixels of the form every milisecond and show the result to the user. there is no interaction between user and form(no click, no dblclick,…) it just shows some circles with one color and lines with different pixel colors(each line may have different pixel colors)
also i want to be able to change the coordination system, i mean change it from top-left to the center of the window. could anyone help me do that with some sample code? links? tutorial?
OpenGL doesn't have a built-in circle function, but it does have line functions, and you can simulate a circle using polygons. To draw lines, you can do something like this:
glBegin (GL_LINES);
// First line segment
glVertex2f (x0, y0);
glVertex2f (x1, y1);
// Second line segment
glVertex2f (x2, y2);
glVertex2f (x3, y3);
glEnd ();
To draw a circle, you can write a loop to draw a triangle fan. Something like:
glBegin (GL_TRIANGLE_FAN);
// Center point
glVertex2f (cx, cy);
for (segment = 0; segment < maxSegments; segment++)
{
double angle = delta * segment;
double x = cx + cos (angle) * radius;
double y = cy + sin (angle) * radius;
glVertex2f (x, y);
}
glEnd ();
In this case, delta is 2 * pi / maxSegments, and maxSegments is the number of segments you want in your circle approximation.

OpenGL - drawing 2D polygons shapes with texture

I am trying to make a few effects in a C+GL game. So far I draw all my sprites as a quad, and it works.
However, I am trying to make a large ring appear at times, with a texture following that ring, as it takes less memory than a quad with the ring texture inside.
The type of ring I want to make is not a round-shaped GL mesh ring (the "tube" type) but a "paper" 2D ring. That way I can modify the "width" of the ring, getting more of the effect than a simple quad+ring texture.
So far all my attempts have been...kind of ridiculous, as I don't understand GL's coordinates too well (and I can't really understand the available documentation...I am just a designer with no coder help or background. A n00b, basically).
glBegin(GL_POLYGON);
for(i = 0;i < 360; i += 10){
glTexCoord2f(0, 0);
glVertex2f(Cos(i)*(H-10),Sin(i)*H);
glTexCoord2f(0, HP);
glVertex2f(Sin(i)*(H-10),Cos(i)*(H-10));
glTexCoord2f(WP, HP);
glVertex2f(Cos(i)*H,Sin(i)*(H-10));
glTexCoord2f(WP, 0);
glVertex2f(Sin(i)*H,Cos(i)*H);
}
glEnd();
This is my last attempt, and it seems to generate a "sunburst" from the right edge of the circle instead of a ring. It's an amusing effect but definitely not what I want. Other results included the circle looking exactly the same as the quad textured (aka drawing a sprite literally) or something that looked like a pop-art filter, by working on this train of thought.
Seems like my logic here is entirely flawed, so, what would be the easiest way to obtain such a ring? No need to reply in code, just some guidance for a non-math-skilled user...
Edit: A different way to word what I want, would be a sequence of rotated rectangles connected to each other, forming a low-resolution ring.
So you want an annulus? That is, the area between two circles with the same center but different radii? I'd try a quad strip like this:
glBegin(GL_QUAD_STRIP);
for(i = 0; i <= 360; i += 10){
glTexCoord2f(WP*i/360, 0);
glVertex2f(Cos(i)*(H-10),Sin(i)*(H-10));
glTexCoord2f(WP*i/360, HP);
glVertex2f(Cos(i)*H,Sin(i)*H);
}
glEnd();
Each quad is a 10-degree sector of the ring. Note that if you want to draw N quads in a strip, it takes 2*(N+1) points, so we draw a total of 2*(36+1) = 74 points.
The post here on the OpenGL forums seems to do what you want. An overview of the approach:
If you want a circle filed with a
texture, you can use triangle fan.
First, draw the vertex at the center
of the circle. Then draw the vertex on
the contour of the circle, use
cos(angle)*radius for x and
sin(angle)*radius for y. Since texture
coordinates s and t are in the range
[0 1] => s = (cos(angle)+1.0)*0.5 and
t = (sin(angle)+1.0)*0.5 . The texture
coordinate for the vertex at the
center of the circle is (0.5,0.5).
GLvoid draw_circle(const GLfloat radius,const GLuint num_vertex)
{
GLfloat vertex[4];
GLfloat texcoord[2];
const GLfloat delta_angle = 2.0*M_PI/num_vertex;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,texID);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glBegin(GL_TRIANGLE_FAN);
//draw the vertex at the center of the circle
texcoord[0] = 0.5;
texcoord[1] = 0.5;
glTexCoord2fv(texcoord);
vertex[0] = vertex[1] = vertex[2] = 0.0;
vertex[3] = 1.0;
glVertex4fv(vertex);
for(int i = 0; i < num_vertex ; i++)
{
texcoord[0] = (std::cos(delta_angle*i) + 1.0)*0.5;
texcoord[1] = (std::sin(delta_angle*i) + 1.0)*0.5;
glTexCoord2fv(texcoord);
vertex[0] = std::cos(delta_angle*i) * radius;
vertex[1] = std::sin(delta_angle*i) * radius;
vertex[2] = 0.0;
vertex[3] = 1.0;
glVertex4fv(vertex);
}
texcoord[0] = (1.0 + 1.0)*0.5;
texcoord[1] = (0.0 + 1.0)*0.5;
glTexCoord2fv(texcoord);
vertex[0] = 1.0 * radius;
vertex[1] = 0.0 * radius;
vertex[2] = 0.0;
vertex[3] = 1.0;
glVertex4fv(vertex);
glEnd();
glDisable(GL_TEXTURE_2D);
}

Resources