Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a stitched scene using glFrustum

I have a program in which I can make a scene render on a screen as per the user's position. As the user changes position, the frustum changes to give off-axis projection. I want to utilize the technique to work on three different displays stitching together a bigger scene, with something of the following sort:

enter image description here Imagine a big real world scene rendered across the three displays. The three displays should be showing the scene as it would look with a changed perspective on each display as per the position of the user. I am able to do this with one display to render a scene as per user's position, but unable to think of the method for this to work on three screens.

The class off-axis projection that I have created basically does the following:

customCam::project(){
pushMatrices();
glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
        glFrustum(leftNear.x, rightNear.x, bottomNear.y, topNear.y, _near, _far);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(uPos.x, uPos.y, 0, uPos.x, uPos.y, -1, 0, 1, 0); //neglect z scaling for now. In the main program, it's there
    glTranslatef(0, 0, uPos.z);
}

How do I stich the three frustum in such a fashion that the scene looks continuous as in real world? Currently, a user of the class draws a scene as follows:

cstCam.project();
    //draw something here
popMatriceS(); //which were pushed before glFrustum projection

EDIT: In my case, to define three frustums for a user (taking into accoutn user and screen corners for all displays in the same frame of reference), I did the following:

custCam1.project();
//draw scene here. eg: two walls at the far left and right screen
drawWalls();
popMatrices();
custCam2.project();
drawWalls();
popMatrices();
custCam3.project();
drawWalls();
popMatrices();

void drawWalls(){
//Left most corner screen wall
glBegin(GL_QUADS);
glVertex3f(-1.5*PHWIDTH, HEIGHT/2, 0); //where PHWIDTH, HEIGHT is the physical width/height of each screen
glVertex3f(-1.5*PHWIDTH, HEIGHT/2, -50);
glVertex3f(-1.5*PHWIDTH, -HEIGHT/2, -50);
glVertex3f(-1.5*PHWIDTH, -HEIGHT/2, 0);
glEnd();

//Right most corner screen wall
glBegin(GL_QUADS);
glVertex3f(1.5*PHWIDTH, HEIGHT/2, 0); //where PHWIDTH, HEIGHT is the physical width/height of each screen
glVertex3f(1.5*PHWIDTH, HEIGHT/2, -50);
glVertex3f(1.5*PHWIDTH, -HEIGHT/2, -50);
glVertex3f(1.5*PHWIDTH, -HEIGHT/2, 0);
glEnd();
}
like image 369
user1240679 Avatar asked Jun 14 '13 18:06

user1240679


1 Answers

This is not that difficult as it might look. Consider the following image (the three screens looked at from above at the znear level)

Screens from above

I assumed that each screen spans 2 units in the x-direction at the znear distance. You may have to scale this value depending on your scene.

The range for the y-coordinate does not change for the three screens, because they are at the same vertical position.

So you need three different projection matrices for the screens. Determining the offset is pretty simple. You just need the differences to the camera point:

left screen   => [-3 - camera.x, -1 - camera.x]
center screen => [-1 - camera.x, 1 - camera.x]
right screen  => [1 - camera.x, 3 - camera.x]

Of course, you need the camera position in the screens' space as in the figure.

The view matrix can be an arbitrary one, but should be the same for all three screens. This time, pass the camera position in scene space to gluLookAt.

like image 177
Nico Schertler Avatar answered Oct 18 '22 22:10

Nico Schertler