1.11M Members

C++ OpenGL: Relocating Vanishing Point

 
0
 

Hello,

I am using OpenGL in C++ to create graphics in a program of mine. In the window, there is the main section and a sidebar.

My problem is that I do not know how to relocate the vanishing point in my window. Currently, it is at (0, 0), which is the default. I want to make it shift to (-0.25, 0) so as to give the illusion that the sidebar is not part of the main section.

 
0
 

umm, haven't done opengl for a while, but I think you are looking for gluPerspective(..). Its areguments are the following

void gluPerspective(	GLdouble  	fovy,
 	GLdouble  	aspect,
 	GLdouble  	zNear,
 	GLdouble  	zFar);

So just specifiz zNear to be some negative number and zFar to be an adequate high number and you should be fine.

 
1
 

That's very easy actually. In order of simplicity:

1. You can use the function glFrustum() which takes left, right, bottom, top, near and far coordinates for the projection, all centered about the vanishing point. So if top and bottom are not equal in magnitude (like 1 and -1) then the vanishing point won't be in the middle. Essentially, the typical gluPerspective function is just a specific case for which top = -bottom and left = -right, in which case only the aspect ratio and FOV matters.

2. You can follow the following explanation of projection matrices to manually set the projection matrix yourself. The format of all matrices in OpenGL is a 4x4 matrix (column-major, meaning that columns are saved one after the other in a linear array of length 16). You would pass the matrix that you have computed as follows:

GLfloat myProjectionMatrix[16];
  //calculate myProjectionMatrix based on the link above.
  glMatrixMode(GL_PROJECTION);
  glLoadMatrixf(myProjectionMatrix);

3. If you want a slightly different effect, you can also apply are translation (in x-y) after the perspective calculation, as follows:

glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glPerspective(/*.. your fov, width / height, near and far data here ..*/);
  glTranslatef(0.0, -0.25, 0.0);

Happy Coding! ;)

 
0
 

Detailed. Unfortunately, it didn't really help me much.

1. glFrustum()
I was confused at this function and went to various websites to learn about it. I ended up with this snippet of code:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 100.0f);
glTranslatef(-0.25f, 0.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

It gave me wonky results though. My 3D Objects were all pointed at the camera instead of being perpendicular to the rendered floor. It would be nice if you could give me an example.

2. Custom Projection Matrix
The explanation, sadly, was incredibly complex...

3. gluPerspective()
The vanishing point did not change, and my sidebar disappeared.

 
0
 

>>It gave me wonky results though. My 3D Objects were all pointed at the camera instead of being perpendicular to the rendered floor.

It seems like you messed up the modelview matrix in the process (the modelview matrix determines the translation and rotation of the displayed objects). Make sure you understand the difference between the projection and modelview matrix, and how the various opengl functions work with those. Make sure that in your code, the transformations in the projection matrix and those on the modelview matrix are well separated.

>>The explanation, sadly, was incredibly complex...

No, the explanation was not at all complex (in fact the simplest I could find). I say this all the time to people: you cannot and should not do 3D graphics programming without a solid background in mathematics (at least geometry and linear algebra, and ideally vector calculus). If you really couldn't understand the explanation I linked to, then you have serious catching up to do in mathematics before you go any further in 3D graphics programming.

>>The vanishing point did not change, and my sidebar disappeared.

If you changed the projection applied to the 3D scene and somehow affected the rendering of the sidebar, then it means you are rendering both the world and the sidebar (GUI) with the same projection (I'm guessing on one viewport too). This is wrong. Any sidebar or GUI-type thingies you want to superimpose to the rendering of the 3D world, you need to render those on a separate, fixed projection and even better, on an orthogonal projection (glOrtho()) such that these items don't get rendered in a 3D perspective projection.

>>It would be nice if you could give me an example.

If you post the code you have, or better, a small extract or example program that has only what you want to fix, I might take a look to see what is wrong. The small amount of code you already posted is not nearly sufficient for anyone to know the mistake. OpenGL is built as a state machine: a few function calls don't mean much in the bigger scheme of things. Try to reproduce you problem on a small piece of code (for example, using a NeHe tutorial as the starting program), and strip it down to only the simplest, but complete, example program that still has the mistake you are looking to fix.

 
0
 

>>No, the explanation was not at all complex
My fault, I'm just not all that familiar with 3D rendering. Up until now, glTranslatef() and glRotatef() were the main functions I used for getting my scene rendered the way I want it.

>>you are rendering both the world and the sidebar (GUI) with the same projection (I'm guessing on one viewport too).

Yes, I am. Now I'm thinking 2 viewports might solve my problem...

>>If you post the code you have
Sure. This is the function in its entirety:

void DrawBackground() {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 100.0f);
        glTranslatef(-0.25f, 0.0f, 0.0f);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        
	glPushMatrix();
	glTranslatef(0.0f, 0.0f, 8.0f);
	glRotatef(-20.0f, 1.0f, 0.0f, 0.0f);
	
	GLfloat yTrans = (Timer*0.125)+1.0f;
	
    glTranslatef(-(BGMapSizeX/2.0f *BGTileSize)-0.25f,
                 -yTrans,
                 -8.0f );
    
    GLfloat BGYSm = yTrans+1.5f;
    GLfloat BGYSM = BGYSm+BGYSize;
    
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    for (int x = 0; x < BGMapSizeX; x++) {for (int y = 0; y < BGMapSizeY; y++) {
        if (Trees[x][y])
        if (Trees[x][y]->Center.X > 0.0f  && Trees[x][y]->Center.X < BGXSize)
        if (Trees[x][y]->Center.Y > BGYSm && Trees[x][y]->Center.Y < BGYSM  )
            DrawTree(*Trees[x][y]);
    }}
    
    glColor3f(White);
    glBindTexture(GL_TEXTURE_2D, BGDirt.texID);
    for (int x = 0; x < BGMapSizeX; x++) {for (int y = 0; y < 1BGMapSizeY; y++) {
        if (Y2[x  ][y] > BGYSm && Y2[x+1][y] < BGYSM) {
            glBegin(GL_TRIANGLE_STRIP);
                glColor3f(Colour[x  ][y  ], Colour[x  ][y  ], Colour[x  ][y  ]);
            	glTexCoord2f( X1a[x][y], Y1a[x][y]); glVertex3f( X2[x  ][y  ], Y2[x  ][y  ], BGPos[x  ][y  ]);
            	glColor3f(Colour[x+1][y  ], Colour[x+1][y  ], Colour[x+1][y  ]);
        		glTexCoord2f( X1b[x][y], Y1a[x][y]); glVertex3f( X2[x+1][y  ], S1Y2[x+1][y  ], BGPos[x+1][y  ]);
        		glColor3f(Colour[x  ][y+1], Colour[x  ][y+1], Colour[x  ][y+1]);
        		glTexCoord2f( X1a[x][y], Y1b[x][y]); glVertex3f( X2[x  ][y+1], Y2[x  ][y+1], BGPos[x  ][y+1]);
        		glColor3f(Colour[x+1][y+1], Colour[x+1][y+1], Colour[x+1][y+1]);
        		glTexCoord2f( X1b[x][y], Y1b[x][y]); glVertex3f( X2[x+1][y+1], Y2[x+1][y+1], BGPos[x+1][y+1]);
    		glEnd();
        }
    }}
    
    glBindTexture(GL_TEXTURE_2D, BGGrass.texID);
    for (int x = 0; x < BGMapSizeX; x++) {for (int y = 0; y < BGMapSizeY; y++) {
        if (Y2[x  ][y] > BGYSm && Y2[x+1][y] < BGYSM) {
            glBegin(GL_TRIANGLE_STRIP);
                glColor4f(Colour[x  ][y  ], Colour[x  ][y  ], Colour[x  ][y  ], BGAlpha[x  ][y  ]);
            	glTexCoord2f( X1a[x][y], Y1a[x][y]); glVertex3f( X2[x  ][y  ], Y2[x  ][y  ], BGPos[x  ][y  ]);
            	glColor4f(Colour[x+1][y  ], Colour[x+1][y  ], Colour[x+1][y  ], BGAlpha[x+1][y  ]);
        		glTexCoord2f( X1b[x][y], Y1a[x][y]); glVertex3f( X2[x+1][y  ], Y2[x+1][y  ], BGPos[x+1][y  ]);
        		glColor4f(Colour[x  ][y+1], Colour[x  ][y+1], Colour[x  ][y+1], BGAlpha[x  ][y+1]);
        		glTexCoord2f( X1a[x][y], Y1b[x][y]); glVertex3f( X2[x  ][y+1], Y2[x  ][y+1], BGPos[x  ][y+1]);
        		glColor4f(Colour[x+1][y+1], Colour[x+1][y+1], Colour[x+1][y+1], BGAlpha[x+1][y+1]);
        		glTexCoord2f( X1b[x][y], Y1b[x][y]); glVertex3f( X2[x+1][y+1], Y2[x+1][y+1], BGPos[x+1][y+1]);
    		glEnd();
        }
    }}
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
    
    glBindTexture(GL_TEXTURE_2D, Blank.texID);
    glPopMatrix();
}

There are some global variables which are used here that I have not included. I don't think those would be relevant to this problem.

*** The function itself may not follow some standards. I've only been programming in C++ and OpenGL for less than a year.

 
0
 

>>No, the explanation was not at all complex
My fault, I'm just not all that familiar with 3D rendering. Up until now, glTranslatef() and glRotatef() were the main functions I used for getting my scene rendered the way I want it.

>>you are rendering both the world and the sidebar (GUI) with the same projection (I'm guessing on one viewport too).

Yes, I am. Now I'm thinking 2 viewports might solve my problem...

>>If you post the code you have
Sure. This is the function in its entirety:

void DrawBackground() {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 100.0f);
        glTranslatef(-0.25f, 0.0f, 0.0f);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        
	glPushMatrix();
	glTranslatef(0.0f, 0.0f, 8.0f);
	glRotatef(-20.0f, 1.0f, 0.0f, 0.0f);
	
	GLfloat yTrans = (Timer*0.125)+1.0f;
	
    glTranslatef(-(BGMapSizeX/2.0f *BGTileSize)-0.25f,
                 -yTrans,
                 -8.0f );
    
    GLfloat BGYSm = yTrans+1.5f;
    GLfloat BGYSM = BGYSm+BGYSize;
    
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    for (int x = 0; x < BGMapSizeX; x++) {for (int y = 0; y < BGMapSizeY; y++) {
        if (Trees[x][y])
        if (Trees[x][y]->Center.X > 0.0f  && Trees[x][y]->Center.X < BGXSize)
        if (Trees[x][y]->Center.Y > BGYSm && Trees[x][y]->Center.Y < BGYSM  )
            DrawTree(*Trees[x][y]);
    }}
    
    glColor3f(White);
    glBindTexture(GL_TEXTURE_2D, BGDirt.texID);
    for (int x = 0; x < BGMapSizeX; x++) {for (int y = 0; y < 1BGMapSizeY; y++) {
        if (Y2[x  ][y] > BGYSm && Y2[x+1][y] < BGYSM) {
            glBegin(GL_TRIANGLE_STRIP);
                glColor3f(Colour[x  ][y  ], Colour[x  ][y  ], Colour[x  ][y  ]);
            	glTexCoord2f( X1a[x][y], Y1a[x][y]); glVertex3f( X2[x  ][y  ], Y2[x  ][y  ], BGPos[x  ][y  ]);
            	glColor3f(Colour[x+1][y  ], Colour[x+1][y  ], Colour[x+1][y  ]);
        		glTexCoord2f( X1b[x][y], Y1a[x][y]); glVertex3f( X2[x+1][y  ], S1Y2[x+1][y  ], BGPos[x+1][y  ]);
        		glColor3f(Colour[x  ][y+1], Colour[x  ][y+1], Colour[x  ][y+1]);
        		glTexCoord2f( X1a[x][y], Y1b[x][y]); glVertex3f( X2[x  ][y+1], Y2[x  ][y+1], BGPos[x  ][y+1]);
        		glColor3f(Colour[x+1][y+1], Colour[x+1][y+1], Colour[x+1][y+1]);
        		glTexCoord2f( X1b[x][y], Y1b[x][y]); glVertex3f( X2[x+1][y+1], Y2[x+1][y+1], BGPos[x+1][y+1]);
    		glEnd();
        }
    }}
    
    glBindTexture(GL_TEXTURE_2D, BGGrass.texID);
    for (int x = 0; x < BGMapSizeX; x++) {for (int y = 0; y < BGMapSizeY; y++) {
        if (Y2[x  ][y] > BGYSm && Y2[x+1][y] < BGYSM) {
            glBegin(GL_TRIANGLE_STRIP);
                glColor4f(Colour[x  ][y  ], Colour[x  ][y  ], Colour[x  ][y  ], BGAlpha[x  ][y  ]);
            	glTexCoord2f( X1a[x][y], Y1a[x][y]); glVertex3f( X2[x  ][y  ], Y2[x  ][y  ], BGPos[x  ][y  ]);
            	glColor4f(Colour[x+1][y  ], Colour[x+1][y  ], Colour[x+1][y  ], BGAlpha[x+1][y  ]);
        		glTexCoord2f( X1b[x][y], Y1a[x][y]); glVertex3f( X2[x+1][y  ], Y2[x+1][y  ], BGPos[x+1][y  ]);
        		glColor4f(Colour[x  ][y+1], Colour[x  ][y+1], Colour[x  ][y+1], BGAlpha[x  ][y+1]);
        		glTexCoord2f( X1a[x][y], Y1b[x][y]); glVertex3f( X2[x  ][y+1], Y2[x  ][y+1], BGPos[x  ][y+1]);
        		glColor4f(Colour[x+1][y+1], Colour[x+1][y+1], Colour[x+1][y+1], BGAlpha[x+1][y+1]);
        		glTexCoord2f( X1b[x][y], Y1b[x][y]); glVertex3f( X2[x+1][y+1], Y2[x+1][y+1], BGPos[x+1][y+1]);
    		glEnd();
        }
    }}
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
    
    glBindTexture(GL_TEXTURE_2D, Blank.texID);
    glPopMatrix();
}

There are some global variables which are used here that I have not included. I don't think those would be relevant to this problem.

*** The function itself may not follow some standards. I've only been programming in C++ and OpenGL for less than a year.

 
0
 

Hey everybody, I found a solution to my problem.
Many thanks to mike_2000_17 for all his hints.

Since I am only rendering a background, this solution works fine for my purposes.
I used a mixture of glViewport() and gluPerspective() to change my vanishing point.

This goes at the beginning:

// Set The Viewport
glViewport(0, 0, (int)(ScreenSizeX*0.75), ScreenSizeY);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set Up Perspective Mode
gluPerspective( 45.0, 1, 0.1f, 500.0f); //1 = 4/3 * 3/4

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-2.0f);

And this goes at the end:

glViewport(0, 0, ScreenSizeX, ScreenSizeY);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set Up Perspective Mode
gluPerspective( 45.0, 4.0/3, 0.1f, 500.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-2.0f);

Note that glTranslatef(0.0f,0.0f,-2.0f) is a 'default' setting within my program.

Question Answered as of 3 Years Ago by mike_2000_17, daviddoria and firstPerson
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
View similar articles that have also been tagged: