Adapt existing code for OpenGL stereoscopic rendering? - opengl

I'm trying to implement stereoscopic 3d in OpenGL using a side-by-side technique.
I've read this article which in great detail explains how to set up the camera for left and right views. It uses a camera model and set up the left and right views using gluLookAt.
However in my case I want to adapt existing code that already set up the projection.
See the following example where "existingcode" represents the code that I cannot make changes to.
//Render left view
// setUpCamera set the gl projection and model matrix
existingcode.setUpCamera()
..
here I want to somehow modify the current gl projection matrix for the left view
..
existingcode.renderScene()
//.. then render right view
Can it be done, perhaps by calling glGetMatrix and modify it somehow?

What you've to do is employ some lens shiftig.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
stereo_offset = eye * near * parallax_factor / convergence_distance;
glFrustum(stereo_offset + left, stereo_offset + right, bottom, top, near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(eye * parallax_factor * convergence_distance, 0, 0);
/* now use gluLookAt here as this were a normal 2D rendering */
parallax_factor should be no larger than the ratio of half_eye_distance / screen_width, so the larger the screen gets the smaller the parallax_factor is. A good value for parallax_factor for computer display use is 0.05, for large screens (think cinema) it's something like 0.01
This projection shifting technique is exactly what I used for re-rendering Elephants Dream in stereoscopic 3D, although, since Blenders offline renderer doesn't use OpenGL the code looks a little bit different http://www.youtube.com/watch?v=L-tmaMR1p3w

Related

Render a 3D model with the same size regardless of camera position

I've got a particular model that acts as controls in the viewer. The user can click on different parts of it to perform transformations on another model in the viewer (like controls/handles in applications like Unity or Blender).
We'd like the controls to remain the same size regardless how zoomed in/out the camera is. I've tried scaling the size of it based on the distance between the object and the camera but it isn't quite right. Is there a standard way of accomplishing something like this?
The controls are rendered using the fixed pipeline, but we've got other components using the programmable pipeline.
The easy answer is "use the programmable pipeline" because it's not that difficult to write
if(normalObject) {
gl_Position = projection * view * model * vertex;
} else {
gl_Position = specialMVPMatrix * vertex;
}
Whereas you'll spend a lot more code trying to get this to work in the Fixed-Function-Pipeline and plenty more CPU cycles rendering it.
With the fixed pipeline, the easiest way to do this is to simply not apply any transformations when you render the controls:
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// draw controls
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
The glPushMatrix()/glPopMatrix() calls will make sure that the previous matrices are restored at the end of this code fragment.
With no transformation at all, the range of coordinates mapped to the window will be [-1.0 .. 1.0] in both coordinate directions. If you need anything else, you can apply the necessary transformations before you start drawing the controls.

Zoom OpenGL scene using mouse selection

I'm trying to implement zoom of opengl scene according to selected area on screen with a mouse.
My goal is to make so that user is able to zoom whichever part of a 2D opengl world using a mouse.
Also he should ne able to zoom several times.
Having hard time trying to achieve this.
Drawing is perfromed with:
glViewport(fullscreen)
gluOrtho2D()
...drawing...
Tried to change world coords in gluOrtho2D, but it seems to be impossible to zoom several times then...
So I'm trying to figure numbers for glScalef and glTranslatef...
Maybe any1 has tried to do something like this and could help with some advice?
How about you use glLoadIdentity to reset the matrix to a sane value. Everytime you call one of OpenGL's matrix manipulation functions it does an in-place multiplication onto the top of the currently active matrix stack.
Your typical display function should look like this (pseudocode)
display:
glClear(…)
# just to illustrate that you can mix multiple projection
# setups throughout rendering a single frame
foreach l in layers:
glViewport(l→viewport)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
l→setup_projection() # for example glOrtho
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
l→setup_view() # for example gluLookAt
foreach m in models:
glMatrixMode(GL_MODELVIEW)
# make a copy of the current modelview so that we can
# restore it after the model has been drawn, by pushing onto the stack
glPushMatrix()
setup_model_transformation()
draw_model()
glMatrixMode(GL_MODELVIEW)
# restore to the previous matrix by poping it from the stack
glPopMatrix()
Note that this uses the deprecated (i.e. old and removed from modern OpenGL) matrix stack. Modern OpenGL programs do their own matrix math and just load the relevant, effective matrices into so called shader uniforms for each model drawn.
Made some progress...
displayedMapCoords[0] = mapCenterPoint[0] - sceneSize * aspectRatio;
displayedMapCoords[1] = mapCenterPoint[0] + sceneSize * aspectRatio;
displayedMapCoords[2] = mapCenterPoint[1] - sceneSize;
displayedMapCoords[3] = mapCenterPoint[1] + sceneSize;
...
gluOrtho2D( displayedMapCoords[0], displayedMapCoords[1],
displayedMapCoords[2], displayedMapCoords[3] );
glScalef(mapScale, mapScale, 0);
...
When selected a rect with mouse, I calculate scale factor and new center point:
mapScale = (float) CfgManager::Instance()->getScreenHeight() / selectedAreaSize;
mapCenterPoint[0] = -(float) mapScale * (CfgManager::Instance()->getScreenWidth()/2 - zoomArea[0] - selectedAreaSize / 2) * sceneSize / CfgManager::Instance()->getScreenHeight();
mapCenterPoint[1] = (float) mapScale * (CfgManager::Instance()->getScreenHeight()/2 - zoomArea[1] - selectedAreaSize / 2) * sceneSize / CfgManager::Instance()->getScreenHeight();
This code works just fine... but only once. I'd like to be able to select another area after I've zoomed already.
Calculating scale factor is not an issue here, but calculate new center point position is not so easy :/

Black Screen Effect - OpenGL

I'm new to OpenGL and I've been experiencing the "Black Screen Effect". I've spent ages trying to work out why I'm not seeing anything and I haven't had much success. I'm using LWJGL and here is the piece of code I'm trying to run:
glViewport(0,0,DISPLAY_WIDTH,DISPLAY_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 6200000.0f, 6300000.0f, 350000.0f, 380000.0f, -10000000.0f, 100000000.0f);
gluLookAt(368000.0f, 6250000.0f, -10000.0f, 368000.0f, 6250000.0f, 10000.0f, 0.0f,1.0f,0.0f);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
if(ready)
{
glColor3f(1.0f,0.5f,1.0f);
glPointSize(100);
glBegin(GL_POINTS);
for(int i = 0; i < data.length; i += 100)
{
glColor3f(1.0f,1.0f,1.0f);
glVertex3f((float) data[i][1], (float) data[i][2],0.0f);
System.out.println((float) data[i][1] + ", " + (float) data[i][2]);
}
glEnd();
System.out.println("\n\nfinished drawing\n\n");
glFlush();
I am drawing in a different colour that i used to clear the screen.
My data set is quite large (over 100 000 points) so I tried plotting every hundredth point, but that's not working.
I am also trying to plot points at positions such as (400 000, 6 800 000) would this be presenting me with problems? I'm pretty sure that 32bit floating point numbers should be able to handle these values.
I am pretty certain that a pixel with size=1 will try to plot as 1 pixel on the screen, regardless of how small it is compared with the bounds of the orthographic projection.
Maybe I'm dealing with the projection matrix incorrectly.
First, like said in my comment don't use gluLookAt on the projection matrix. It defines the camera (view) and therefore belongs to the model view matrix. This isn't the cause for your problem and it should also work this way, but it is conceptually wrong.
Next, if you call this code every frame, you push a new matrix onto the stack every frame, without calling glPopMatrix. glPushMatrix is generally there to save the current matrix and restore it later with a call to glPopMatrix, because every other command (like glLoadIdentity, but also gluLookAt and glOrtho) modifies the current matrix (the one selected by glMatrixMode).
Otherwise, you should always keep the size of your scene in relation to the viewing volume (the glOrtho parameters in your case) in mind. At the moment you're looking from point (368000, 6250000, -10000) to point (368000, 6250000, 10000). Together with the glOrtho parameters this should define your viewing volume to be the [368000-6300000 , 368000-6200000] x [6250000+350000 , 6250000+380000] x [-10000000-10000, 100000000-10000] box. If you don't transform your points further by any local transformations, their coordinates should ly in these intervals to be visible. Keep an eye on the minus in the x-interval. This is due to the fact that you actually rotated the view volume 180 degrees around the y-axis, because you defined the view to look from -z to z, whereas GL's default eye-space defines the viewer to look from z to -z (which usually is not that much of a problem with an origin-symmetric viewing volume, but yours is highly asymmetric).
Although your numbers are extremely strange they should be handlable by 32bit floats. But are you really sure you want your points to have a size of 100 pixels (if this is even supported)?
And if you only draw 2D points in an orthographic view, I'm also not sure if you need such a HUGE depth range.

Setting up a camera in OpenGL

I've been working on a game engine for awhile. I've started out with 2D Graphics with just SDL but I've slowly been moving towards 3D capabilities by using OpenGL. Most of the documentation I've seen about "how to get things done," use GLUT, which I am not using.
The question is how do I create a "camera" in OpenGL that I could move around a 3D environment and properly display 3D models as well as sprites (for example, a sprite that has a fixed position and rotation). What functions should I be concerned with in order to setup a camera in OpenGL camera and in what order should they be called in?
Here is some background information leading up to why I want an actual camera.
To draw a simple sprite, I create a GL texture from an SDL surface and I draw it onto the screen at the coordinates of (SpriteX-CameraX) and (SpriteY-CameraY). This works fine but when moving towards actual 3D models it doesn't work quite right. The cameras location is a custom vector class (i.e. not using the standard libraries for it) with X, Y, Z integer components.
I have a 3D cube made up of triangles and by itself, I can draw it and rotate it and I can actually move the cube around (although in an awkward way) by passing in the camera location when I draw the model and using that components of the location vector to calculate the models position. Problems become evident with this approach when I go to rotate the model though. The origin of the model isn't the model itself but seems to be the origin of the screen. Some googling tells me I need to save the location of the model, rotate it about the origin, then restore the model to its origal location.
Instead of passing in the location of my camera and calculating where things should be being drawn in the Viewport by calculating new vertices, I figured I would create an OpenGL "camera" to do this for me so all I would need to do is pass in the coordinates of my Camera object into the OpenGL camera and it would translate the view automatically. This tasks seems to be extremely easy if you use GLUT but I'm not sure how to set up a camera using just OpenGL.
EDIT #1 (after some comments):
Following some suggestion, here is the update method that gets called throughout my program. Its been updated to create perspective and view matrices. All drawing happens before this is called. And a similar set of methods is executed when OpenGL executes (minus the buffer swap). The x,y,z coordinates are straight an instance of Camera and its location vector. If the camera was at (256, 32, 0) then 256, 32 and 0 would be passed into the Update method. Currently, z is set to 0 as there is no way to change that value at the moment. The 3D model being drawn is a set of vertices/triangles + normals at location X=320, Y=240, Z=-128. When the program is run, this is what is drawn in FILL mode and then in LINE mode and another one in FILL after movement, when I move the camera a little bit to the right. It likes like may Normals may be the cause, but I think it has moreso to do with me missing something extremely important or not completely understanding what the NEAR and FAR parameters for glFrustum actually do.
Before I implemented these changes, I was using glOrtho and the cube rendered correctly. Now if I switch back to glOrtho, one face renders (Green) and the rotation is quite weird - probably due to the translation. The cube has 6 different colors, one for each side. Red, Blue, Green, Cyan, White and Purple.
int VideoWindow::Update(double x, double y, double z)
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum(0.0f, GetWidth(), GetHeight(), 0.0f, 32.0f, 192.0f);
glMatrixMode( GL_MODELVIEW );
SDL_GL_SwapBuffers();
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(0, 1.0f, 0.0f, 0.0f);
glRotatef(0, 0.0f, 1.0f, 0.0f);
glRotatef(0, 0.0f, 0.0f, 1.0f);
glTranslated(-x, -y, 0);
return 0;
}
EDIT FINAL:
The problem turned out to be an issue with the Near and Far arguments of glFrustum and the Z value of glTranslated. While change the values has fixed it, I'll probably have to learn more about the relationship between the two functions.
You need a view matrix, and a projection matrix. You can do it one of two ways:
Load the matrix yourself, using glMatrixMode() and glLoadMatrixf(), after you use your own library to calculate the matrices.
Use combinations of glMatrixMode(GL_MODELVIEW) and glTranslate() / glRotate() to create your view matrix, and glMatrixMode(GL_PROJECTION) with glFrustum() to create your projection matrix. Remember - your view matrix is the negative translation of your camera's position (As it's where you should move the world to relative to the camera origin), as well as any rotations applied (pitch/yaw).
Hope this helps, if I had more time I'd write you a proper example!
You have to do it using the matrix stack as for object hierarchy,
but the camera is inside the hierarchy so you have to put the inverse transform on the stack before drawing the objects as openGL only uses the matrix from 3D to camera.
If you have not checked then may be looking at following project would explain in detail what "tsalter" wrote in his post.
Camera from OGL SDK (CodeColony)
Also look at Red book for explanation on viewing and how does model-view and projection matrix will help you create camera. It starts with good comparison between actual camera and what corresponds to OpenGL API. Chapter 3 - Viewing

What is a good way of implementing HCI in OpenGL?

I'd like to try and implement some HCI for my existing OpenGL application. If possible, the menus should appear infront of my 3D graphics which would be in the background.
I was thinking of drawing a square directly in front of the "camera", and then drawing either textures or more primatives on top of the "base" square.
While the menus are active the camera can't move, so that the camera doesn't look away from the menus.
Does this sound far feteched to anyone or am I on the right tracks? How would everyone else do it?
I would just glPushMatrix, glLoadIdentity, do your drawing, then glPopMatrix and not worry about where your camera is.
You'll also need to disable and re-enable depth test, lighting and such
There is the GLUI library to do this (no personal experience)
Or if you are using Qt there are ways of rendering Qt widgets transparently on top of the OpenGL model, there is also beta support for rendering all of Qt in opengl.
You could also do all your 3d Rendering, then switch to orthographic projection and draw all your menu objects. This would be much easier than putting it all on a large billboarded quad as you suggested.
Check out this exerpt, specifically the heading "Projection Transformations".
As stated here, you need to apply a translation of 0.375 in x and y to get pixel perfect alignment:
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375, 0.375, 0.0);
/* render all primitives at integer positions */
The algorithm is simple:
Draw your 3D scene, presumably with depth testing enabled.
Disable depth testing so that your GUI elements will draw over the 3D stuff.
Use glPushMatrix to store you current model view and projection matrices (assuming you want to restore them - otherwise, just trump on them)
Set up your model view and projection matrices as described in the above code
Draw your UI stuff
Use glPushMatrix to restore your pushed matrices (assuming you pushed them)
Doing it like this makes the camera position irrelevant - in fact, as the camera moves, the 3D parts will be affected as normal, but the 2D overlay stays in place. I'm expecting that this is the behaviour you want.