I am currently trying to create a 2D side scroller and i currently have my "world" drawing (a large white box for the time being), but i cannot figure out any relationship between the edge of the world map and the edge of the viewport to ensure that the viewport is always fully covered by the map.
My basic world drawing code is:
void drawTiles(void)
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 500; j++)
{
glPushMatrix();
glTranslatef(j, -i, 0);
glBegin (GL_QUADS);
glTexCoord2d(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glTexCoord2d(1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glTexCoord2d(1.0, 1.0);
glVertex3f(1.0, 1.0, 0.0);
glTexCoord2d(0.0, 1.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glPopMatrix();
}
}
}
void display(void)
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(camX, camY, -20); //translate back a bit to view the map correctly (our camera)
drawTiles(); //draw our tiles
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'w':
camY -= 0.25;
break;
case 's':
camY += 0.25;
break;
case 'a':
camX += 0.25;
break;
case 'd':
camX -= 0.25;
break;
}
}
How would i go about ensuring that when I use WASD and on viewport resize, that i do not translate beyond the bounds of the map (currently 500x50 tiles)?
If you have a planar scene (2D only), it should be sufficient to use an orthographic projection transformation. The projection transformation determines the camera's parameters. In the current state (with the perspective projection) you have a usual pin hole camera with a vertical opening angle of 60°.
An orthographic projection is defined by its edges. Let's say you want your camera to "see" two units to the left, 3 units to the right, 1 unit up and 4 units down. This would be possible, although it might not be reasonable in your case.
The current perspective camera "sees" about 11.5 units up and down. The according width can be calculated from the window dimensions (we do not want to stretch the image). So instead of gluPerspective, use the following:
float halfHeight = 11.5f;
float halfWidth = halfHeight * (GLfloat)w / (GLfloat)h; //based on window aspect ratio
glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, -1, 1);
If you want to change the visible area, you just need to adjust the halfHeight. The -1 and 1 are the znear and zfar plane. Everything that is between these planes is visible. Everything else will be cut off. But since you have only 2D content, this should not be relevant.
In your call to glTranslatef(camX, camY, -20);, set the z-coordinate to 0. This is not needed any more, because we have an orthographic view.
Now if you want to check if the map is still visible, do the following. I'll just show the exmple of checking the left/right boundary. The vertical case is similar:
//The camera can see from camX-halfWidth to camX+halfWidth
//You might want to make halfWidth and halfHeight class variables
float leftMapBoundary = 0;
float rightMapBoundary = 500;
//the camera must be
// * at least halfWidth right of the left boundary and
// * at least halfWidth left of the right one:
if(camX < leftMapBoundary + halfWidth)
camX = leftMapBoundary + halfWidth;
if(camX > rightMapBoundary - halfWidth)
camX = rightMapBoundary - halfWidth;
Add the code after the switch in your keyboard function or whenever you move the camera.
Related
So im rendering a curve with openGL. The curve is completely streched for a 1920 x 1080 Pixel Window. With this given relation i now want to analyse the proxy position in world coordinates of my haptic device and draw a 3D/2D Cursor for my window coordinates. How exactly do i have to transform my GL_MODELVIEW_MATRIX, GL_PROJECTION and GL_VIEWPORT to fit my proxy world coordinates (haptic device position) into screen coordinates? Or do i even have to do transformation. Even after researching i dont really understand the transformation of those matrix. So it would be very nice if you could help me here.
display func:
void renderDisplay() {
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 1.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < vertices.size(); i += 3) {
glVertex2f(vertices[i], vertices[i+2]);
}
glEnd();
glFlush();
hlBeginFrame();
hlCheckEvents();
drawCursor();
hlEndFrame();
}
Draw Cursor Func:
void drawCursor()
{
static const double kCursorRadius = 0.5;
static const double kCursorHeight = 1.5;
static const int kCursorTess = 15;
HLdouble proxyxform[16];
GLUquadricObj *qobj = 0;
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT);
glPushMatrix();
if (!gCursorDisplayList)
{
gCursorDisplayList = glGenLists(1);
glNewList(gCursorDisplayList, GL_COMPILE);
qobj = gluNewQuadric();
gluCylinder(qobj, 0.0, kCursorRadius, kCursorHeight,
kCursorTess, kCursorTess);
glTranslated(0.0, 0.0, kCursorHeight);
gluCylinder(qobj, kCursorRadius, 0.0, kCursorHeight / 5.0,
kCursorTess, kCursorTess);
gluDeleteQuadric(qobj);
glEndList();
}
// Get the proxy transform in world coordinates.
hlGetDoublev(HL_PROXY_TRANSFORM, proxyxform);
glMultMatrixd(proxyxform);
// Apply the local cursor scale factor.
glScaled(gCursorScale, gCursorScale, gCursorScale);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glColor3f(0.0, 0.5, 1.0);
glCallList(gCursorDisplayList);
glPopMatrix();
glPopAttrib();
}
setup3DCursor Func:
void setup3DCursor(int width, int height)
{
GLdouble modelview[16];
GLdouble projection[16];
GLint viewport[4];
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
hlMatrixMode(HL_TOUCHWORKSPACE);
hlLoadIdentity();
// Fit haptic workspace to view volume.
hluFitWorkspace(projection);
// Compute cursor scale.
gCursorScale = hluScreenToModelScale(modelview, projection, (HLint*)viewport);
gCursorScale *= CURSOR_SIZE_PIXELS;
}
main func:
findExtrema(); // Find limits for projection
gluOrtho2D(minX, maxX, minY, maxY) // Params: Left, right, bottom, top
glutDisplayFunc(renderDisplay);
glutReshapefunc(setup3DCursor);
So what exactly am i doing wrong here?
I am working on a project for mouse control to look around. I have been successful with rotating the camera using the mouse however I am trying to get the mouse to do 360 turns without the mouse leaving the screen before it can fully rotate. I read around and came across glutWarpPointer(), where most posts said to use it after getting the difference between the centre and the new mouse position in the window.
The issue this causes with my program is that when I move the mouse it will rotate very slightly for that frame the restart the location to the original point. Basically it i have a blue ball in front of me and green behind when i try to rotate towards the green ball the camera will move slightly but stay locked on the blue ball.
Is there a way to around or a fix?
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//rotate and translating the camera
glRotatef(-camVert, 1.0, 0.0, 0.0);
glRotatef(-camHor, 0.0, 1.0, 0.0);
glTranslatef(-posx,-posy,-posz);
//blue and green ball
glPushMatrix();
glColor3f(0.0, 1.0, 0.0);
glTranslatef(1, 0, 25);
glutSolidSphere(5, 20, 20);
glPopMatrix();
glPushMatrix();
glColor3f(0.0,0.0,1.0);
glTranslatef(0, 0, -25);
glutSolidSphere(5, 20, 20);
glPopMatrix();
};
void setAngle(float angy, float angx)
{
camVert = angy*1.5;
if (camVert > 90)
camVert = 90;
else if (camVert < -90)
camVert = -90;
camHor = angx*0.5;
}
void MoveCam(float distance, float direction)
{
float rads = (camHor+direction)*PI / 180;
posx -= sin(rads)*distance;
posz -= cos(rads)*distance;
};
void mouseMove(int x, int y)
{
float diffx = midx - x;
float diffy = midy - y;
setAngle(diffy,diffx);
//glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
}
I am a beginner in OpenGl and I am struggling a bit with setting up the glOrtho camera to match the window size so that I can draw a line using the window's coordinates. For example, if I want to draw a line from coordinates 0,10 (x,y) to 600,10. I managed to draw the line (which will be a "Separator" from the viewport and a toolbar with buttons) in my current set up but it was by "try end error" approach and the coordinates that I needed to put don't make any sense to me. When I tried to draw a line using the above-mentioned coordinates, the line simply did not show up. What I need to change in the glOrtho set up in order to work with these (1000x600) screen size and draw my vertices and not these:
glVertex3f(-2.0, 11.0, 0.0);
glVertex3f(20.0, 11.0, 0.0);
Note, my current window size is 1000x600 (width/height)
This is the line (on the top that crosses the whole screen):
This is my OGWindow class that handles all of the drawing:
void OGWindow::MyReSizeGLScene(int fwidth, int fheight)
{
// Store window size in class variables so it can be accessed in myDrawGLScene() if necessary
wWidth = fwidth;
wHeight = fheight;
// Calculate aspect ration of the OpenGL window
aspect_ratio = (float) fwidth / fheight;
// Set camera so it can see a square area of space running from 0 to 10
// in both X and Y directions, plus a bit of space around it.
Ymin = -1;
Ymax = 12;
Xmin = -1;
// Choose Xmax so that the aspect ration of the projection
// = the aspect ratio of the viewport
Xmax = (aspect_ratio * (Ymax -Ymin)) + Xmin;
glMatrixMode(GL_PROJECTION); // Select The Projection Stack
glLoadIdentity();
glOrtho(Xmin, Xmax, Ymin, Ymax, -1.0, 1.0);
glViewport(0, 0, wWidth, wHeight); // Viewport fills the window
}
void OGWindow::myDrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the drawing area
OGWindow::myDrawModel();
drawToolbar();
glutSwapBuffers(); // Needed if we're running an animation
glFlush();
}
void OGWindow::myDrawModel(GLvoid)
{
switch ( squareColour ) {
case RED:
glColor3f(1.0, 0.0, 0.0);
break;
case BLUE:
glColor3f(0.0, 0.0, 1.0);
break;
}
glBegin( GL_QUADS );
glVertex3f( squareX, squareY, 0.0 ); // Coordinates of bottom-left corner of square
glVertex3f( squareX + squareWidth, squareY, 0.0 );
glVertex3f( squareX + squareWidth, squareY + squareHeight, 0.0 );
glVertex3f( squareX, squareY + squareHeight, 0.0 );
glEnd();
}
// Convert from screen coords returned by mouse
// to world coordinates.
// Return result in worldX, worldY
void OGWindow::screen2World(int screenX, int screenY, double & worldX, double & worldY)
{
// Dimensions of rectangle viewed by camera projection
double projWidth = Xmax -Xmin;
double projHeight = Ymax - Ymin;
// Screen coords with origin at bottom left
int screenLeft = screenX;
int screenUp = wHeight - screenY;
worldX = Xmin + screenLeft * projWidth / wWidth ;
worldY = Ymin + screenUp * projHeight / wHeight ;
}
//Method to draw the toolbar separator line
void OGWindow::drawToolbar(GLvoid) {
//draw toolbar line separator
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(-2.0, 11.0, 0.0);
glVertex3f(20.0, 11.0, 0.0);
glEnd();
//draw create button
glPushMatrix();
glTranslatef(2.0, 10.0, 0.0);
glutSolidCube(2.0);
glPopMatrix();
}
This is my main class where I am ivoking the methods from OGWindow:
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize( 1000, 600 );
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL Demo");
glEnable(GL_DEPTH_TEST); // enable the depth buffer test
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseMotion);
glutPassiveMotionFunc(mousePassiveMotion);
glutIdleFunc(Idle);
theWindow.initGL();
glutMainLoop();
}
Check out the documentation of glOrtho function. As you see, there are 6 parameters: left, right, bottom, top, near, far. You made mistake by setting window width to top instead of bottom parameter. Here's proper use of function:
glOrtho (0, 1000, 600, 0, -1.0, 1.0)
So, first your ortho settings. If you want your camera to match the screen dimensions, glOrtho has to use the same dimensions.
// This will anchor the camera to the center of the screen
// Camera will be centered on (0,0)
glOrtho( -screenWidth/2.f, screenWidth/2.f, -screenHeight/2.f, screenHeight/2.f, -1, 1 );
// This will anchor the camera to the lower left corner of the screen
// Camera will be centered on (screenWidth/2, screenHeight/2)
glOrtho( 0, screenWidth, 0, screenHeight, -1, 1 );
Try both and see the difference. Although if you are making some sort of editor, where your camera doesn't move, you may be looking for the second ortho setup.
Second, you only ever use (apparently) the GL_PROJECTION matrix mode. You must use this mode to set the camera projection and GL_MODELVIEW to apply transforms to the camera or the objects.
So when you call resize and don't change the matrix mode back to GL_MODELVIEW, you'll be applying translations to the projection matrix.
If you did forget to initialize the modelview matrix it may contain garbage values and yield unexpected results.
I am working on an assignment to draw wire frame GLUT standard objects. This seems simple but we are told we cannot use gluAtLook(), glOrtho(), glFrustrum but we must use glTranslate(), glScale() and glRotate. How to you project the object without using these functions in glMatrixMode(GL_PROJECTION)?
This is what I have so far:
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <math.h> // for sqrt()
#include <glut.h>
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glLoadIdentity(); /* clear the matrix */
/* viewing transformation */
glTranslatef(0.0, 0.0, -5.0);
glScalef(1.0, 2.0, 1.0); /* modeling transformation */
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
//glTranslatef(0.0, 0.0, -5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Can someone please help with this?
we are told we cannot use gluAtLook(), glOrtho(), glFrustrum but we must use glTranslate(), glScale() and glRotate
gluLookAt sets up the world to view space transformation, glOrtho does view to orthographic projection space transformation and glFrustum does view to perspective projection space transformation. When you say your tutor hasn't allowed to use it, it clearly means that the intention is to understand how these functions work in the first place.
There're many resources on the internet which teach you that. Here's one by a renowned UC Berkeley professor Dr. Ravi Ramamoorthi. SongHo has good articles which will help you do the same thing.
I can demonstrate a simple case in 2D. Say we've a world defined with objects (for simplicity we take a point P); we want the camera to be at (3, 3) with its X and Y axes pointing in directions opposite to world's X and Y axes. For simplicity we'll assume both frames have the same scaling factor i.e. 1 unit in both X and Y directions measure the same distance (magnitude) for both systems. So the two frames differ only by orientation and origin location (W0 and V0 are the symbols denoting them).
We need to derive Mworld->view i.e. the matrix which maps points in world space to view space. This is what the now-deprecated gluLookAt function calculates and multiplies with GL_MODELVIEW matrix stack. This matrix will be used to get a view of the world from the camera's viewpoint.
We know that Mworld->view = Tview->world. The matrix which maps points of frame A to frame B will also be the matrix which transforms B's frame into A's frame. The derivation goes like this
The point P in world has (1, 2) = Pw as coordinates, we're effectively finding a matrix, which when multiplied with Pw will give Pv i.e. the same point's coordinates in view frame. The point is written as a 3D point since homogeneous extension of a 2D point would be a 3D point; the homogeneous coordinate would be 1 since it's a point; had it been a vector, it'd be 0.
Step one is rotation; rotating view's frame by -180° (right-handed system where +ve rotation is counter-clockwise); now the axes are along the same direction for both frames. We've to tackle the origin difference, this is done by translation, which is step 2. Multiplying both will give the required matrix. Note that each step transforms the view's frame more closer into world's frame by post-multiplying. Also each transformation is based on that current local frame we're in and not based on the starting global (world) frame.
The same idea can be extended to 3D too, with some more effort. In the above derivation all I needed were just rotation matrix, translation matrix and matrix multiplication; no gluLookat.The links I gave you should help in calculating the same for 3D. The projection matrix derivation is a bit more involved. However, you can still achieve the result without using glOrtho; the links I gave above has the formula for the final matrix; you can compose a matrix using that and multiply that to the GL_PROJECTION matrix stack.
Note: The above derivation assumes column vectors and thus transformation matrices (like rotation) and multiplication order are done based on that. If you assume row vector convention then transpose all the matrices and reverse the order of multplication since
(AB)^T = B^T A^T
What you need to do is compute your own projection matrix and model-view matrix. After that you can load them using glLoadMatrix right after you call glLoadIdentity.
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <math.h> // for sqrt()
#include <glut.h>
static GLfloat Xvalue = 0.0f;
static GLfloat Yvalue = 0.0f;
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
static GLfloat zRot = 0.0f;
static GLfloat xScale = 1.0f;
static GLfloat yScale = 1.0f;
static GLfloat zScale = 1.0f;
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glLoadIdentity(); //clear the matrix
glTranslatef(Xvalue, Yvalue, -3.0); // viewing transformation
glScalef(xScale, yScale, zScale); // modeling transformation
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(zRot, 0.0f, 0.0f, 1.0f);
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
GLfloat identity[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };
if (h == 0) // don't want a divide by zero
{
h = 1;
}
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(identity);
GLfloat fovy = 52.0f; // in degrees
GLfloat c = 1.0 / (GLfloat)tan(fovy / 4.0), a = (GLfloat)w / (GLfloat)h, n = 1.0f, f = 1000.0f;
GLfloat projection[16] = { c / a, 0.0, 0.0, 0.0,
0.0, c, 0.0, 0.0,
0.0, 0.0, -(f + n) / (f - n), -1.0,
0.0, 0.0, -2.0*f*n / (f - n), 0.0 };
glMultMatrixf(projection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyInput(unsigned char key, int x, int y)
{ // Keyboard input processing routine.
switch (key)
{
case 'b': // move left
Xvalue -= 0.1;
glutPostRedisplay();
break;
case 'B': // move right
Xvalue += 0.1;
glutPostRedisplay();
break;
case 'c': // move down
Yvalue -= 0.1;
glutPostRedisplay();
break;
case 'C': // move up
Yvalue += 0.1;
glutPostRedisplay();
break;
case 'e': // scale down
zScale -= 0.1;
xScale -= 0.1;
yScale -= 0.1;
glutPostRedisplay();
break;
case 'E': // scale up
zScale += 0.1;
xScale += 0.1;
yScale += 0.1;
glutPostRedisplay();
break;
case 'f': // rotate x axis CW
xRot -= 5.0f;
glutPostRedisplay();
break;
case 'F': // rotate x axis CCW
xRot += 5.0f;
glutPostRedisplay();
break;
case 'g': // rotate y axis CW
yRot -= 5.0f;
glutPostRedisplay();
break;
case 'G': // rotate y axis CCW
yRot += 5.0f;
glutPostRedisplay();
break;
case 'h': // rotate z axis CW
zRot -= 5.0f;
glutPostRedisplay();
break;
case 'H': // rotate z axis CCW
zRot += 5.0f;
glutPostRedisplay();
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyInput);
glutMainLoop();
return 0;
}
I am trying to use glFrustum for a perspective projection and as I understand glFrustum like glOrtho can be used to modify the mapping of our desired coordinate system to real screen coordinates (as read in Blue book). So, if I do glFrustum(-1,1,-1,1,1,1000);, it changes the coordinates to
left = -1, right = 1, bottom = -1, top = 1 in the form of cartesian coordinates.
I tried to draw a simple room (with 2 side walls) in this coordinate system by calling the following function in my draw method and it comes out drawing appropriately on the screen.
void drawRoomWalls(){
//Left wall
glBegin(GL_QUADS);
glVertex3f(-1.0, 1.0, 0.0);
glVertex3f(-1.0, 1.0, -0.4);
glVertex3f(-1.0, -1.0, -0.4);
glVertex3f(-1.0, -1.0, 0.0);
glEnd();
//Right wall
glBegin(GL_QUADS);
glVertex3f(1.0, 1.0, 0.0);
glVertex3f(1.0, 1.0, -0.4);
glVertex3f(1.0, -1.0, -0.4);
glVertex3f(1.0, -1.0, 0.0);
glEnd();
}
The function was called as follows:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(1.0, -1.0, -1.0, 1.0, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -1.0);
drawRoomWalls();
Subsequently, I tried to do an off-axis projection (by taking mouse as input instead of user's head). The code is as follows:
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
double fov, near, far;
double headX, headY, headZ;
float aspectRatio;
near = 0.5f; far = 1000.0f; aspectRatio = ofGetWidth()/ofGetHeight();
fov = tan(DEG_TO_RAD * 30/2); //tan accepts angle in radians. tan of the half of the fov angle
fov = 0.5; //taken constant for now
double msX = (double)ofGetMouseX();
double msY = (double)ofGetMouseY();
double scrWidth = (double)ofGetWidth();
double scrHeight = (double)ofGetHeight();
headX = (msX / scrWidth) - 0.5;
headY = ((scrHeight - msY) / scrHeight) - 0.5;
headZ = -2.0;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum( near * (-fov * aspectRatio + headX),
near * (fov * aspectRatio + headX),
near * (-fov + headY),
near * (fov + headY),
near,
far);
leftValue = near * (-fov * aspectRatio + headX); //for printing out on screen
rightValue = near * (fov * aspectRatio + headX); //for printing out on screen
bottomValue = near * (-fov + headY); //for printing out on screen
topValue = near * (fov + headY); //for printing out on screen
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(headX * headZ, headY * headZ, 0, headX * headZ, headY * headZ, -1, 0, 1, 0);
glTranslatef(0.0, 0.0, headZ);
drawRoomWalls();
I printed the values of leftValue, rightValue, bottomValue, topValue and when the mouse is in the center of the screen (the call to glFrustum looks like glFrustum(-0.25,0.25,-0.25,0.25,1.0,1000.0)
As per the above call, I expected the coordinate system's left=-0.25, right=0.25, bottom=-0.25, top=0.25 and I was expecting the walls to disappear (since they are draw at (1.0,1.0,0.0) for an example). However, the walls keep on appearing on the sides of the screen (with the scene being skewed and at the center being essentially the same as with off-axis projection). Why is it that the walls are still at the place on the sides (even though the coordinates changed to -0.25,0.25) or there's something in glFrustum call that I am missing here about the coordinate system?
I just realized that you also changed headZ to -2. That explains the behaviour.
If the camera is situated at z = 2 and you have a vertical half fov of 0.5, then at z = 0 you already see 1 unit in positive and negative y-direction. That's why you see the walls.