Related
I want to draw a cube of side 40 at bootom left corner. my glortho function is
glOrtho(0, // left
1000, // right
0, // bottom
1000, // top
0, // zNear
1000 // zFar
);
and lenght of x,y,z axis is up to 1000. so cube should be at bottom left and dimensions should be as i given. and what should be the gluLookAt(); function. I am not getting correct output. If there is any mistakes in the code, correct it and what function should add to the code.
#include <gl/glut.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#define GL_GLEXT_PROTOTYPES
#ifdef __APPLE__
#else
#endif
void display();
void specialKeys();
double rotate_y=0;
double rotate_x=0;
void display(){
// Clear screen and Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
// Rotate when user changes rotate_x and rotate_y
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );
// side - FRONT
glBegin(GL_POLYGON);
glColor3f( 1.0, 0.0, 0.0 );
glVertex3f( 0, 0, 0);
glVertex3f( 40,0,0);
glVertex3f(40,40,0 );
glVertex3f(0,40,0 );
glEnd();
// side - BACK
glBegin(GL_POLYGON);
glColor3f( 1.0,0.0,1.0 );
glVertex3f( 0,0,40 );
glVertex3f( 0,40,40);
glVertex3f( 40,40,40 );
glVertex3f( 40,0,40 );
glEnd();
// side - RIGHT
glBegin(GL_POLYGON);
glColor3f( 0.0, 0.0, 1.0 );
glVertex3f( 40,40,0 );
glVertex3f( 40,0,0 );
glVertex3f( 40,0,40 );
glVertex3f( 40,40,40 );
glEnd();
// side - LEFT
glBegin(GL_POLYGON);
glColor3f( 0.0, 1.0, 0.0 );
glVertex3f( 0,0,0 );
glVertex3f( 0,40,0 );
glVertex3f( 0,40,40 );
glVertex3f( 0,0,40 );
glEnd();
// side - TOP
glBegin(GL_POLYGON);
glColor3f( 0.0,0.0,1.0 );
glVertex3f( 0,40,0);
glVertex3f( 0,40,40 );
glVertex3f( 40,40,40 );
glVertex3f( 40,40,0 );
glEnd();
// side - BOTTOM
glBegin(GL_POLYGON);
glColor3f( 1.0, 0.5, 0.0 );
glVertex3f( 0,0,0 );
glVertex3f( 40,0,0 );
glVertex3f( 40,0,40 );
glVertex3f( 0,0,40);
glEnd();
glFlush();
glutSwapBuffers();
}
void init()
{
glClearColor(0.5,0.5,0.0, 0.0);
glColor3f(1,0,0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluOrtho2D(-1.0,1.0,-1.0,1.0);
glOrtho(0, // left
1000, // right
0, // bottom
1000, // top
0, // zNear
1001 // zFar
);
gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, -1000.0, 0.0, 1000.0, 0.0);
}
void specialKeys( int key, int x, int y ) {
// Right arrow - increase rotation by 5 degree
if (key == GLUT_KEY_RIGHT)
rotate_y += 5;
// Left arrow - decrease rotation by 5 degree
else if (key == GLUT_KEY_LEFT)
rotate_y -= 5;
else if (key == GLUT_KEY_UP)
rotate_x += 5;
else if (key == GLUT_KEY_DOWN)
rotate_x -= 5;
// Request display update
glutPostRedisplay();
}
int main(int argc, char* argv[]){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1000, 1000);
glutInitWindowPosition(10, 10);
// Create window
glutCreateWindow("Awesome Cube");
// Enable Z-buffer depth test
glEnable(GL_DEPTH_TEST);
glutDisplayFunc(display);
glutSpecialFunc(specialKeys);
init();
glutMainLoop();
return 0;
}
You screwed up your transformations. In Init() you set the current matrix mode to GL_PROJECTION and load some ortho matrix. Then you multiply the lookAt matrix onto this. This is wrong in principle, as the lookAt matrix should be applied to the GL_MODELVIEW stack. (The lookAt parameters you chose actually result in an identity lookAt matrix, so that call has no effect, but that is only a side note).
However, the real error is in display(). There you have glLoadIdentity() which will just overwrite your previous matrix with an identity matrix, so you lose the Ortho transform you did set up, since you still have GL_PROJECTION matrix stack active.
The correct way would be something like:
void init()
{
// ... your other stuff
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( /* your ortho params */ );
glMatrixMode(GL_MODELVIEW); // switch back to the modelView matrix stack
}
void display()
{
glLoadIdentity();
gluLookAt( /* your Lookat parameters */ );
glRotate/Scale/Translate(...); // your local transformations
// ...
}
Note that all of that stuff is completely deprecated and has been removed from the core profile of modern OpenGL versions. When learing OpenGL nowadays, you should consider not learning that old cruft from 20 years ago.
how can i draw in 2D coordinates instead of vertex coordinate system, as this =>
drawPoint(50 , 100 , 0.01f);
this is my code , a background texture and a point
static void Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho( -1 * w/2, 1 * w/2, -1 * h/2, 1 * h/2, w/2, -h/2);
glBegin(GL_POLYGON);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-w/2.f, -h/2.f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( w/2.f, -h/2.f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( w/2.f, h/2.f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-w/2.f, h/2.f, 0.0f);
glEnd();
drawPoint(50 , 100 , 0.01f);
glutSwapBuffers();
}
the function DrawPoint => draws circles
void drawPoint(GLfloat x, GLfloat y, GLfloat radius){
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
int i;
int triangleAmount = 20; //# of triangles used to draw circle
//GLfloat radius = 0.8f; //radius
GLfloat twicePi = 2.0f * 3.1415;
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(x, y); // center of circle
for(i = 0; i <= triangleAmount;i++) {
glVertex2f(
x + (radius * cos(i * twicePi / triangleAmount)),
y + (radius * sin(i * twicePi / triangleAmount))
);
}
glEnd();
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
}
So I don't know if I have to change the DrawPoint function.
UPDATE : this is my main source
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInit(&argc, argv);
glutInitWindowSize(widthX, heightY);
glutCreateWindow("prg");
glutReshapeFunc(resize);
glutDisplayFunc(Draw);
glutKeyboardFunc(keyPressed);
glutKeyboardUpFunc(keyUp);
texture[0] = SOIL_load_OGL_texture
(
"img.jpg",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnable(GL_TEXTURE_2D);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glutMainLoop();
UPDATE 2 :
if in this way is impossible, is there a method that transform an x and y into a vector ?, so for example :
DrawPoint(VectConvert(50),VectConvert(100),0.01f);
I am not sure if this is right answer. I edited your code, try this:
static void Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// You divided your window width and height by 300 which seems to be wrong
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Create ortho 2d
// The last two parameters are near and far planes
// Since you are using only 2D you should keep them at 0.0 and 1.0
glOrtho( -1 * w/2.0, 1 * w/2.0, -1 * h/2.0, 1 * h/2.0, 0.0f, 1.0f);
// Mirror Y axis
glScalef(1, -1, 1);
// Now your coordinate system starts at center of your window
// You need to move it to the left top corner
glTranslatef(-(w/2.0f), -(h/2.0f), 0.0f);
texture[0] = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
(
"img.jpg",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_POLYGON);
// You need also to mirror your Y coordinates for texture
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f , 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(w , 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(w , h , 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f , h , 0.0f);
glEnd();
drawPoint(50 , 100 , 0.01f);
glutSwapBuffers();
}
Also, do not load your texture from file every frame. It is overkill for your GPU.
Just set an ortogonal projection as you need it:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, w, h, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Please note a few things here:
This assumes that w and h are actually the width and height of your viewport.
I put this into the GL_PROJECTION matrix. That is where this stuff belongs. (Although it might not be critical in your use case).
I set the near and far planes to -1 and 1 respectively. I don't know what you actually will need, but your values didn't make any sense.
That will set up a coordinate system where the pixel centers are actually exactly between two integer values, and integer values denote the middle between two adjacent pixels, so (0,0) will be the top left corner of the top left pixel, and (w,h) the bottom right corner of the bottom left pixel.
You also could set up a mapping that maps the integers to the pixel centers, like glOrtho(-0.5, w-0.5, h-0.5, -0.5, -1, 1). Now (0,0) is the center of the top left pixel, and (w,h) is outside the screen, (w-1,h-1) is the center of the bottom right pixel.
Had some trouble with animation in my OpenGL project (window was non-responsive after a few seconds or when clicked, and animations were getting stuck and looping at seemingly random points), so I was advised to add an idle callback and then make my Display function only render the "current" frame each time it's called.
Although I don't know how to make my Display function only render the "current" frame.
Here's my Display function:
// GLUT display callback function
void Display(void)
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity(); // transformations are represented by matrices
// for placing camera
gluLookAt(0,1,50,0,0,0,0,1,0);
// for mouse movement
glTranslatef(g_fTransX,g_fTransY,g_fZoom);
glRotatef (g_fSpinX,1.0f,0.0f,0.0f);
glRotatef (g_fSpinY,0.0f,1.0f,0.0f);
glLightfv(GL_LIGHT0,GL_POSITION,lpos);
// xyz axes
glDisable(GL_LIGHTING);
glLineWidth(2.0);
glBegin(GL_LINES);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(20.0, 0.0, 0.0);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 20.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 20.0);
glEnd();
glEnable(GL_LIGHTING);
float Ambient_m[] = {0.0f,1.0f,0.0f,0.0f};
glMaterialfv(GL_FRONT,GL_AMBIENT,Ambient_m);
float Ambient_l[] = {0.2f,0.2f,0.2f,0.0f};
glLightfv(GL_LIGHT0,GL_AMBIENT,Ambient_l);
// implementing our custom cylinder function
//draw_cylinder(g_translate_x, g_translate_y, g_dof3_angle);
// our csg object with 4 DOF
GLUquadricObj * qobj = gluNewQuadric();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//draw_lamp(g_dof3_angle);
//glutSwapBuffers();
/*animate(time_from, time_to, dof1_from, dof1_to,
dof2_from, dof2_to, dof3_from, dof3_to,
dof4_from, dof4_to, dof5_from, dof5_to,
dof6_from, dof6_to, dof7_from, dof7_to)*/
animate_lamp(0.0f, 5.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 45.0f, 0.0f, -45.0f,
0.0f, 0.0f, 0.0f, 0.0f);
animate_lamp(5.0f, 7.0f, 0.0f, 5.0f,
0.0f, 5.0f, 0.0f, 0.0f,
45.0f, -45.0f, -45.0f, 45.0f,
0.0f, 0.0f, 0.0f, 0.0f);
animate_lamp(7.0f, 10.0f, 5.0f, 10.0f,
5.0f, 0.0f, 0.0f, 0.0f,
45.0f, -45.0f, -45.0f, 45.0f,
0.0f, 0.0f, 0.0f, 0.0f);
//glutSwapBuffers(); // swap back buffer to front buffer (which is drawn on screen)
}
It's simple - store the current state of the animation somewhere (since you're using C++, you can create an object for it), and then, in your render function, query the state from that object and render it.
Here's a simplified example:
class AnimationData
{
float pos;
public:
void step() { pos += 0.1f; }
void render() const
{
glBegin(GL_TRIANGLES);
glVertex3f(pos, 1.f, 1.f);
glVertex3f(pos, -1.f, 1.f);
glVertex3f(pos + 1.f, 0.f, 1.f);
glEnd(GL_TRIANGLES);
}
};
AnimationData myAnimation;
void Display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity(); // transformations are represented by matrices
// for placing camera
gluLookAt(0,1,50,0,0,0,0,1,0);
// for mouse movement
glTranslatef(g_fTransX,g_fTransY,g_fZoom);
glRotatef (g_fSpinX,1.0f,0.0f,0.0f);
glRotatef (g_fSpinY,0.0f,1.0f,0.0f);
glLightfv(GL_LIGHT0,GL_POSITION,lpos);
// And any other setup
myAnimation.render();
glutSwapBuffers();
}
void timerCallbackFunction()
{
myAnimation.step();
glutPostRedisplay();
}
This will animate a triangle by moving it to the right a bit each time timerCallbackFunction() is called. The display function simply renders the triangle on its current position.
I am trying to draw a large polygon behind the cube to appear like the floor. How ever when ever the background floor is behind the cube it disappears completely. Here is the display function including the background I want to add and one of the cubes sides.
void display(){
// Clear screen and Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
//background floor
glBegin(GL_POLYGON);
glColor3f( 0.5, 0.5, 0.5);
glVertex3f( 1, -0.9, 1 ); // x-y-z right bottom
glVertex3f( 0.6, 0.5, 1 ); //right top
glVertex3f( -0.6, 0.5, 1 ); //left top
glVertex3f( -1, -0.9, 1 ); //left bottom
glEnd();
// Rotate when user changes rotate_x and rotate_y
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );
// FRONT side of cube
glBegin(GL_POLYGON);
glColor3f( 1.0, 0.5, 0.0 );
glVertex3f( 0.05, -0.05, -0.05 );
glVertex3f( 0.05, 0.05, -0.05 );
glVertex3f( -0.05, 0.05, -0.05 );
glVertex3f( -0.05, -0.05, -0.05 );
//I have omitted the other 5 sides
glEnd();
glFlush();
glutSwapBuffers();
}
I suspect your poligon is facing outwards.
Try disabling backface culling with glDisable(GL_CULL_FACE). If this works swap the order of the vertices (should be CCW or trigonometric, on the side that the polygon should be visible from).
Don't leave the face culling disabled, unless you don't care about performance.
I am rendering a scene with some map image in OpenGL and using lat, lon of the map as coordinates directly. So my scene does not start at 0,0 and goes up to width, height. Although I can see my polygon (very small), I can't zoom by changing the z-value of the eye in the gluLookAt().
/*
* My boundary for map quad with texture
*/
#define TOP 41.9061
#define BOTTOM 41.8546
#define LEFT -87.7012
#define RIGHT -87.6054
/*
* window size
*/
const unsigned int window_width = 1024;
const unsigned int window_height = 739;
/*
* drawing a polygon with texture
*/
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mainMapTextureId);
glBegin( GL_POLYGON );
//bottom left
glTexCoord2f( 0.0f, 1.0f );
glVertex3f(LEFT, BOTTOM, 0.0);
//bottom right
glTexCoord2f( 1.0f, 1.0f );
glVertex3f(RIGHT, BOTTOM, 0.0);
//top right
glTexCoord2f( 1.0f, 0.0f );
glVertex3f(RIGHT, TOP, 0.0);
//top left
glTexCoord2f( 0.0f, 0.0f );
glVertex3f(LEFT, TOP, 0.0);
glEnd();
/*
* Setting up the camera
*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)window_width/(GLfloat)window_height, 0.0, 10.0);
gluLookAt( (float)(LEFT+RIGHT)/2.0, (float)(TOP+BOTTOM)/2.0, 1.0,
(float)(LEFT+RIGHT)/2.0, (float)(TOP+BOTTOM)/2.0, 0.0,
0.0f, 1.0f, 0.0f);
It is not legal to have a value of 0.0 for the near plane of gluPerspective. Try replacing it with a nominal small value (0.1f).
Also always put a glGetError call in your code at the end, it will alert you to problems.