I have a 3D labyrinth with a 3d model that the user controls to exit the labyrinth. I want to draw a rectangle on top of the models head, in which the idea is to show his "energy". The rectangle is to be above his head at all times.
I have this code so far:
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glColor3f(1, 0, 0);
glTranslatef(modelo.objecto.pos.x, modelo.objecto.pos.y+1, modelo.objecto.pos.z);
glBegin(GL_QUADS); //Begin quadrilateral coordinates
//Trapezoid
glVertex2f(0, 0);
glVertex2f(2, 0);
glVertex2f(2, .5);
glVertex2f(0, .5);
glEnd(); //End quadrilateral coordinates
This is the result: Result
It doensn't appear neither red, nor at the right position..
Project the world-space coordinate of the top of the model's head into window space using gluProject() or similar.
Swap your projection matrix over to an ortho one
Draw quad centered on window space coords acquired in #1.
All together:
#include <GL/glut.h>
float angle = 0;
void timer( int extra )
{
angle += 0.5;
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}
void display(void)
{
const double w = glutGet( GLUT_WINDOW_WIDTH );
const double h = glutGet( GLUT_WINDOW_HEIGHT );
const double ar = w / h;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 60.0, ar, 0.1, 100.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef( 0, 0, -4 );
glRotatef( angle, 0.1, 0.5, 0.3 );
glColor3ub( 255, 255, 255 );
glutWireCube( 2.0 );
GLdouble modelview[16];
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
GLdouble projection[16];
glGetDoublev( GL_PROJECTION_MATRIX, projection );
GLint viewport[4];
glGetIntegerv( GL_VIEWPORT, viewport );
double x, y, z;
gluProject( 1, 1, 1, modelview, projection, viewport, &x, &y, &z );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, w, 0, h, -1, 1 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef( x, y, 0 );
glScalef( 10, 10, 1 );
glBegin( GL_QUADS );
glColor3ub( 255, 0, 0 );
glVertex2i( -1, -1 );
glVertex2i( 1, -1 );
glVertex2i( 1, 1 );
glVertex2i( -1, 1 );
glEnd();
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 800, 600 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
The easiest way to accomplish that would probably be to a have a plane and place it right over the model, then turn the rotation to the camera. The only problem with that might be that the energy bar is affected by perspective in that case and to get rid of that you would need to render in ortho. But if you are fine with the perspective changing the look of it, that should be a good enough solution.
Related
I use
glm::mat4 transform(1.0f);
transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
to get rotation around the axis over time. But why does the rotation happen evenly and not increase with the timer (first 1 s, then 43, and therefore 43 degrees?) After all, the timer does not reset, but grows, but image rotation goes as if at the same "speed"
But why does the rotation happen evenly and not increase with the timer
Because you're starting the the transform from "zero" (identity) each time through.
If you want to rotate faster & faster with time you need to accumulate the angle:
float angle = 0.0f;
while( shouldDraw() )
{
...
angle += static_cast< float >( glfwGetTime() );
glm::mat4 transform(1.0f);
transform = glm::rotate(transform, angle, glm::vec3(0.0f, 0.0f, 1.0f));
...
}
All together, comparing both approaches:
// g++ main.cpp `pkg-config --cflags --libs glfw3 gl`
#include <GLFW/glfw3.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
void DrawTriangle()
{
glBegin( GL_TRIANGLES );
glColor3ub( 255, 0, 0 );
glVertex2f( 0, 1 );
glColor3ub( 0, 255, 0 );
glVertex2f( -1, -1 );
glColor3ub( 0, 0, 255 );
glVertex2f( 1, -1 );
glEnd();
}
int main( int, char** )
{
glfwInit();
GLFWwindow* window = glfwCreateWindow( 600, 600, "GLFW", NULL, NULL );
glfwMakeContextCurrent( window );
float angle2 = 0.0f;
while( !glfwWindowShouldClose( window ) )
{
glfwPollEvents();
int w, h;
glfwGetFramebufferSize( window, &w, &h );
glViewport( 0, 0, w, h );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( -5, 5, -5, 5, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
const float time = static_cast< float >( glfwGetTime() );
float angle1 = time;
angle2 += time;
glPushMatrix();
{
glTranslatef( 2.5f, 2.5f, 0.0f );
glm::mat4 transform(1.0f);
transform = glm::rotate(transform, angle1, glm::vec3(0.0f, 0.0f, 1.0f));
glMultMatrixf( glm::value_ptr( transform ) );
DrawTriangle();
}
glPopMatrix();
glPushMatrix();
{
glTranslatef( -2.5f, -2.5f, 0.0f );
glm::mat4 transform(1.0f);
transform = glm::rotate(transform, angle2, glm::vec3(0.0f, 0.0f, 1.0f));
glMultMatrixf( glm::value_ptr( transform ) );
DrawTriangle();
}
glPopMatrix();
glfwSwapBuffers( window );
}
glfwTerminate();
}
Welcome to Stack Overflow! :)
I assume that you apply your transformation matrix just like one would apply a model matrix. In that case, your rotation is applied to your object during rendering only once. This results in an even or linear rotation, since time increases linearly.
So the result is just rotations_per_second * static_cast<float>(glfwGetTime()).
If you want to increase the rotation of your object by said amount, you have to multiply both rotation matrices together.
Or you could reduce overhead and define an angular acceleration angular_velocity_per_second and multiply it by your time twice to get the angle of rotation.
here is code
#include <gl/Gl.h>
#include <gl/Glu.h>
#include <gl/glut.h>
#include <windows.h>
using namespace std;
struct GLintPoint {
GLint x, y;
};
void drawDot(GLint x, GLint y)
{
glBegin (GL_POINTS);
glVertex2i(x,y);
glEnd();
}
int screenWidth = 640, screenHeight = 480;
void myDisplay() {
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColor3f( 1.0f, 1.0f, 1.0f );
}
/*
if( selected ) {
glBegin( GL_QUADS );
glVertex2i( corner[0].x, corner[0].y );
glVertex2i( corner[0].x, corner[1].y );
glVertex2i( corner[1].x, corner[1].y );
glVertex2i( corner[1].x, corner[0].y );
glEnd();
}
glutSwapBuffers();
*/
void myKeyboard(unsigned char theKey, int mouseX, int mouseY)
{
GLint x = mouseX;
GLint y = screenHeight - mouseY; // flip the y value as always
switch(theKey)
{
case 'p':
drawDot(x, y); // draw a dot at the mouse position
break;
case 'E':
exit(-1); //terminate the program
default:
break; // do nothing
}
glutPostRedisplay();
}
void myMouse(int button, int state, int x, int y) {}
int main( int argc, char ** argv ) {
glutInit( &argc, argv );
// initialize window
glutInitWindowSize( screenWidth, screenHeight );
glutInitWindowPosition( 0, 0 );
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
// create window
glutCreateWindow( "Rubber Rect Demo" );
// set the projection matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( 0, screenWidth, 0, screenHeight );
glMatrixMode( GL_MODELVIEW );
// clear rendering surface
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // background is black
glViewport(0, 0, screenWidth, screenHeight);
glutMouseFunc( myMouse );
glutDisplayFunc( myDisplay );
glutKeyboardFunc(myKeyboard);
// glutPassiveMotionFunc( myPassiveMotion );
glutMainLoop();
return( 0 );
}
After i compile and run it,I press 'P',it can not plot a point in cursor's position,I don't know why it can not work.
here is link where the sourcecode comefrom http://www.4twk.com/shill/3rd-edition.html
in chapter 2,Chapter 2 - Getting Started Drawing Figures - zip file
Keep drawing operations to the display function. Do not call OpenGL drawing calls from the event handler. In the event handler set a variable that will make the point draw in the display function, then issue a redraw using glutPostRedisplay.
Give this a shot:
#include <GL/glut.h>
#include <vector>
using namespace std;
struct GLintPoint
{
GLint x, y;
};
vector< GLintPoint > points;
void myDisplay()
{
int w = glutGet( GLUT_WINDOW_WIDTH );
int h = glutGet( GLUT_WINDOW_HEIGHT );
glViewport(0, 0, w, h);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // background is black
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, w, 0, h, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColor3f( 1.0f, 1.0f, 1.0f );
glBegin (GL_POINTS);
for( size_t i = 0; i < points.size(); ++i )
{
glVertex2i( points[i].x, points[i].y );
}
glEnd();
glutSwapBuffers();
}
void myKeyboard(unsigned char theKey, int mouseX, int mouseY)
{
int h = glutGet( GLUT_WINDOW_HEIGHT );
GLint x = mouseX;
GLint y = h - mouseY; // flip the y value as always
switch(theKey)
{
case 'p':
{
GLintPoint temp;
temp.x = x;
temp.y = y;
points.push_back( temp );
glutPostRedisplay();
}
break;
case 'E':
exit(-1); //terminate the program
default:
break; // do nothing
}
}
int main( int argc, char ** argv )
{
glutInit( &argc, argv );
// initialize window
glutInitWindowSize( 640, 480 );
glutInitWindowPosition( 0, 0 );
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
// create window
glutCreateWindow( "Rubber Rect Demo" );
glutDisplayFunc( myDisplay );
glutKeyboardFunc(myKeyboard);
glutMainLoop();
return( 0 );
}
I can draw text by specifying the glRasterPos2i(WindowX, WindowY); and it draws the text at the specified position within my window just fine.
For example: glPrint(150, 150, "dgdg"); Where my viewport is 0, 0, 800, 500.
However, doing the same for a square doesn't work. So I tried setting up my view again:
const int W = 800, H = 500;
glViewport(0, 0, W, H);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, W, H, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(100, 100);
glVertex2f(150, 100);
glVertex2f(150, 150);
glVertex2f(100, 150);
glEnd();
But my square never shows up :l
I disabled DepthTesting and GL_RECTANGLE_2D. Still no go.
What am I doing wrong? How can I get it to draw at window coords instead of specifying 1.0f, etc?
Workin' fine here:
#include <GL/glut.h>
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, h, 0, -1, 1);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColor3f(1.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(100, 100);
glVertex2f(150, 100);
glVertex2f(150, 150);
glVertex2f(100, 150);
glEnd();
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
You can add glFlush() after your OpenGL code to require the drawings in the buffer to flush to the window.
For some reference to glFlush(), checkout this link.
I'm trying to highlight ("color #00FFFF") specific individual pixels in an image (already displayed in the background) using OpenGL/C++. The pixel coordinates and the image exist in exact 2D space, but all the OpenGL code I'm seeing in the project so far - glTranslatef(), glScalef() - is 3D and float-based, and the positioning of the object appears to happen separately from the time it's drawn.
I'm used to Java's Graphics2D package, where I can call something to the effect of
width = 1; height = 1;
buffer.drawRect(width, height, xPosition, yPosition);
and it'll fill in a pixel at the specified location. Is there anything similar to that syntax - where I can set size, set position, and draw all in one line - in OpenGL? If not, how would I go about adapting my 2D+pixel input to OpenGL's float and 3D structure?
I currently have this:
glPushMatrix();
glTranslatef(0.0f, 0.0f, -5.0f);
glColor3f(0, 1, 1);
glPointSize(5.0f);
glBegin(GL_POINTS);
glVertex3f(1.0f, 1.0f, 1.0f);
glPopMatrix();
which I pieced together from some Google searches and other parts of my code, but I don't see anything being draw. I have no idea as to the units for the translate, vertex, or pointsize commands. It'd be awesome if I could replace all of that with something like the Java command up above. If not, is there some way I can guarantee whatever I draw here will be "on top" of everything else, but still not behind the camera.
Is there anything similar to that syntax - where I can set size, set position, and draw all in one line - in OpenGL?
glRect():
#include <GL/glut.h>
void display()
{
glEnable( GL_CULL_FACE );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glDepthMask( GL_TRUE );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// draw teapot
glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60, w / h, 1, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -5 );
glColor4ub( 255, 0, 0, 255 );
glPushMatrix();
float angle = 60.0f * ( glutGet(GLUT_ELAPSED_TIME) / 1000.0f );
glRotatef( angle, 0.1, 0.95, 0.05 );
glutSolidTeapot( 1.0 );
glPopMatrix();
// draw rectangle
glDisable( GL_DEPTH_TEST );
glDepthMask( GL_FALSE );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, w, 0, h, -1, 1);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColor4ub( 0, 255, 0, 128 );
glRecti( 0 + 50, 0 + 50, w - 50, h - 50 );
glutSwapBuffers();
}
void timer( int extra )
{
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "Rect" );
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
#include <iostream>
#include <X11/Xlib.h>
#include <GL/glut.h>
#include <GL/glui.h>
using namespace std;
GLsizei wh = 500;
GLsizei ww = 500;
void MyInit();
void DisplayLine(void);
void DisplaySquare(void );
void MyInit()
{
glClearColor( 1, 1, 1, 0 );
glColor3f( 1, 0, 0 );
glPointSize( 10 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glOrtho( 0.0, ww, 0.0, wh, -1.0, 1.0 );
}
void DisplayLine()
{
glClear( GL_COLOR_BUFFER_BIT );
glBegin( GL_LINES );
glVertex2i( 100, 100 );
glVertex2i( 170, 170 );
glVertex2i( 30, 370 );
glVertex2i( 160, 50 );
glEnd( );
glFlush( );
}
void DisplaySquare()
{
glClear( GL_COLOR_BUFFER_BIT );
glBegin( GL_LINE_STRIP );
glBegin( GL_POLYGON );
glVertex2f( 150, 150 );
glVertex2f( 350, 150 );
glVertex2f( 350, 350 );
glVertex2f( 150, 350 );
glVertex2f( 150, 150 );
glEnd( );
glFlush( );
}
void DisplayRSquare()
{
glClear( GL_COLOR_BUFFER_BIT );
#if 0
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glBegin( GL_LINE_LOOP );
glVertex2f( 50, 50 );
glVertex2f( 250, 250 );
glVertex2f( 50, 250 );
glEnd( );
#endif
glBegin( GL_LINE_LOOP );
glVertex2f( 0, 0 );
glVertex2f( 500, 0 );
glVertex2f( 500, 500 );
glVertex2f( 0, 500 );
glEnd( );
glTranslatef( 100, 0, 0 );
#if 0
glRotatef( 20, 0, 0, 1 );
glTranslatef( -50, -50, 0 );
glColor3f( 0, 1, 0 );
glBegin( GL_LINE_LOOP );
glVertex2f( 0, 0 );
glVertex2f( 500, 0 );
glVertex2f( 500, 500 );
glVertex2f( 0, 500 );
glEnd( );
glBegin( GL_LINE_LOOP );
glVertex2f( 50, 50 );
glVertex2f( 250, 50 );
glVertex2f( 250, 250 );
glVertex2f( 50, 250 );
glEnd( );
glRotatef( 12, 0, 0, 1 );
glBegin( GL_LINE_LOOP );
glVertex2f( 75, 75 );
glVertex2f( 75, 550 );
glVertex2f( 550, 550 );
glVertex2f( 550, 75 );
glEnd( );
glFlush( );
glBegin( GL_LINES );
glVertex2f( 0, 0 );
glVertex2f( 150, 150 );
glEnd()
#endif
glFlush( );
}
void DisplayCube()
{
glClear( GL_COLOR_BUFFER_BIT );
glBegin( GL_LINE_STRIP );
glBegin( GL_POLYGON );
glVertex2i( 150, 150 );
glVertex2i( 350, 150 );
glVertex2i( 350, 350 );
glVertex2i( 150, 350 );
glVertex2i( 150, 150 );
glEnd( );
glBegin( GL_LINE_STRIP );
glBegin( GL_POLYGON );
glVertex2i( 250, 250 );
glVertex2i( 450, 250 );
glVertex2i( 450, 450 );
glVertex2i( 250, 450 );
glVertex2i( 250, 250 );
glEnd( );
glBegin( GL_LINE_STRIP );
glBegin( GL_LINES );
glVertex2i( 150, 150 );
glVertex2i( 250, 250 );
glVertex2i( 350, 150 );
glVertex2i( 450, 250 );
glVertex2i( 350, 350 );
glVertex2i( 450, 450 );
glVertex2i( 150, 350 );
glVertex2i( 250, 450 );
glEnd( );
glFlush( );
}
void DisplayRotate()
{
glClear( GL_COLOR_BUFFER_BIT );
glColor3f( 0.0, 1.0, 0.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
for( int angle = 0; angle < 18; angle += 3 )
{
glRotatef( angle, 1, 0, 0 );
if( angle > 8 )
{
glRotatef( angle * 2, 1, 0.0, 0 );
glColor3f( 1.0, 0.0, 0.0 );
}
glBegin( GL_LINE_LOOP );
glVertex2f( 150, 150 );
glVertex2f( 350, 150 );
glVertex2f( 350, 350 );
glVertex2f( 150, 350 );
glEnd( );
}
glFlush( );
}
void pressMouse(int button, int state, int x, int y )
{
if( state == GLUT_DOWN )
{
glBegin( GL_POINTS );
glPointSize( 50 );
glVertex2i( x, wh - y );
glEnd( );
glFlush( );
}
}
void holdMouse(int x, int y )
{
glBegin( GL_POINTS );
glPointSize( 50 );
glVertex2i( x, wh - y );
glEnd( );
glFlush( );
}
void mouse(int btn, int state, int x, int y )
{
if( state == GLUT_DOWN )
{
mouseState = state;
mouseButton = btn;
mouseX = x;
mouseY = y;
}
else
{
mouseState = 0;
}
}
void motion(int x, int y )
{
if( mouseState == GLUT_DOWN )
{
if( MouseButton == GLUT_LEFT_BUTTON )
{
yrotation -= ( mouseX - x );
xrotation -= ( mouseY - y );
}
}
mouseX = x;
mouseY = y;
glutPostRedisplay( );
}
void DisplayFSquare()
{
glClear( GL_COLOR_BUFFER_BIT );
glColor3f( 0, 0, 1 );
glBegin( GL_LINE_LOOP );
glVertex2f( ( GLdouble ) 0.25, ( GLdouble ) 0.25 );
glVertex2f( ( GLdouble ) 0.75, ( GLdouble ) 0.25 );
glVertex2f( ( GLdouble ) 0.75, ( GLdouble ) .75 );
glVertex2f( ( GLdouble ) 0.25, ( GLdouble ) 0.75 );
glEnd( );
glFlush( );
}
int main(int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize( ww, wh );
glutInitWindowPosition( 150, 150 );
glutCreateWindow( "Line" );
MyInit( );
glutDisplayFunc( DisplayRSquare );
glutMouseFunc( pressMouse );
glutMotionFunc( holdMouse );
glutMainLoop( );
}
I have just created several trivial models to test the basic transformation. I have two questions:
DisplayRSquare : in this function I draw a square with the window size and want to move it to (100, 0), but it translated to (200, 0). And if I move it to (50, 0) it will move to (100, 0).
What more weird is, the program sometimes works and sometimes not.
For function glVertex2f(0.3,0.7), we should find a point in the position 0.3*widthofthewindow, 0.7* height of the window, right? But I cannot find it. I have to compute the coordinates and run glVertex2f(0.3*width,0.7*height).
My compiling command is g++ -o line Line.cpp -lGL -lGLU -lglut -lglui
and just run ./line(File name is Line.cpp)
Please speak with me: "OpenGL is not a scene graph! – It doesn't maintain a scene, and all it does is executing drawing commands, drawing single points, lines and triangles, one at a time."
Your code lacks certain basic steps. First you need to setup a proper projection and modelview matrix. You put a projective matrix (ortho) in the modelview matrix at the beginning of your program. And then you just multiply, and multiply and multiply and multiply on the modelview matrix, without ever resetting it to a known (identity) state.
The coarse outline of every fixed function OpenGL display process is about the following:
set clear color and depth, then clear
set viewport and projection matrix
matrix mode projection
load identity
multiply projection (ortho or perspective)
set initial view matrix
matrix mode modelview
load identity
setup view (lookat or whatever)
draw geometry
for each object
matrix mode modelview
push matrix
apply local transformation
draw object
pop matrix
Update 1
First a rewriting of your program, that works in a predictible way and does what you originally indended.
Find answers to your questions after it
#include <GL/glut.h>
void DrawRSquare(
float sz,
float tx,
float ty )
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
/*
Order of operations matters.
Drawing commands use the current state
of OpenGL, which includes the transformation
matrix state. So this must be set before
drawing.
*/
glTranslatef(tx, ty, 0);
glColor3f(1, 0, 0);
glBegin( GL_LINE_LOOP );
glVertex2f( 0, 0 );
glVertex2f( sz, 0 );
glVertex2f( sz, sz );
glVertex2f( 0, sz );
glEnd();
glPopMatrix();
}
void Display(void)
{
glClearColor( 1, 1, 1, 0 );
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
const int windim[2] = {
glutGet(GLUT_WINDOW_WIDTH),
glutGet(GLUT_WINDOW_HEIGHT)
};
glViewport(0, 0, windim[0], windim[1]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, windim[0], 0.0, windim[1], -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
DrawRSquare(50, 100, 0);
DrawRSquare(50, 200, 100);
glutSwapBuffers();
}
int main(
int argc,
char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
glutCreateWindow( "" );
glutDisplayFunc( Display );
glutMainLoop( );
}
Actually the program is running DisplayRSquare, in this function I draw a square same size with the window we created and want to more it with the vector (100,0) in the 2-D space but actually it translated (200,0). And if you change the vector into (50,0), it will move (100,0).
The reason for this is, that your Display function is probably called thrice and then no more. In the first call of DisplayRSquare a translation of (100,0,0) is applied after drawing some lines when the window is created but not yet exposed. Then the window gets exposed and the next redraw applies another (100,0,0) to the already set transformation. But still the window gets exposed another time and now the square will be drawn once again, now with the (100,0,0) + (100,0,0) applied. If you resize your window, the square would futher translate away until out of view with each redraw.
That's why you must reset your OpenGL state into a well known state before beginning any drawing.
What is more wired, the program sometimes works well. Sometimes not. My code is glTranslatef(100,0,0). For the same program ,sometimes it translate 100, sometime 200......Kind of wired...
What happens is, that the amount of redraw events your programm receives varies. This is by moving other windows over it, iconizing and revertig it, etc.
For function glVertex2f(0.3,0.7), we should find a point in the position 0.3*widthofthewindow, 0.7* height of the window, right?
This entirely depends on the set projection and modelview matrices. Without knowing how those are set, and your program never sets them into a well defined state, we don't know.
But I cannot find it.
Quite likely, because your transformation matrices will be way off, of what you indended.
I have to compute the coordinates and run glVertex2f(0.3*width,0.7*height)?
No. Well, at least not in the way you think.
A suggestion: You're using the fixed function pipeline and immediate mode. Both are severely outdated and deprecated. In fact they have been stripped out of recent versions of OpenGL, so I'd not even bother learning them.
If you want to learn modern OpenGL, I stronly suggest you read and work through the tutorial of Nicol Bolas, which is IMHO one of the best you can find at the moment:
http://arcsynthesis.org/gltut