I am currently looking at the feasibility of adding support for SVI
autostereoscopic display in OSG.
Does anyone know anything about this?
So far, I have been looking at an SDK that provides an OpenGL based API and
examples for driving the display.
I have also been looking at the different ways OSG implements stereo modes
with a view to seeing where might be the best place to perform the interlace
function required to support the SVI display.
I noticed that the WOWVX support is done by creating two slave cameras that
render to textures, then combining the textures and wowvx headers using a
pixel shader. So, at first, that seemed a good pattern to try and follow,
but on reflection it's difficult for me to see how to use the SVI API in
this way (even though internally I suspect something similar is going on).
I seem to be floundering a bit., so I wondered if I can trouble anyone on
the list to take a quick look at the attached OpenGL example code from the
SVILaceOGL SDK and make any suggestions about how and where the best place
to try and use the API from within OSG (or from an OSG application).
Of course, if I'm successful with the integration, I'll be happy to share
the result with the OSG community. ;-)
Cheers.
Chris.
/**
\file
SVILaceOgl Example 1
Initialize an interlacer.
Set an arbitary stereo mode and
provide anaglyph red cyan stereo
\author klaus.kesseler<at>spatialview.com
\author dietrich.john<at>spatialview.com
\author (c) http://www.spatialview.com
*/
#include "SVILaceOgl.h"
#include "OglCameras.h"
#include <vector>
#include <string>
#include <iostream>
#include <GL/glut.h>
using namespace SVI;
using namespace SVI::OglCameras;
//==============================================================================
namespace{
int g_rotation = 0;
int g_rotation_increment = 1;
struct IlaceData{
IlaceOgl::IlaceHandle interlacer;
std::vector<GLuint> textures;
unsigned int texWidth;
unsigned int texHeight;
};
IlaceData g_data;
} // anonymous Namespace
//==============================================================================
void cbDisplay();
void cbResize(int w, int h);
void cbIdle(void);
void cbTimer(int );
void cbKey(unsigned char k, int , int );
//==============================================================================
// init Glut window
void initGlut(int *argc, char *argv[])
{
//Init window position and size:
int windowX = 100;
int windowY = 100;
int windowWidth = 680;
int windowHeight = 480;
glutInit(argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition(windowX, windowY);
glutCreateWindow(argv[0]);
//call backs
glutDisplayFunc(cbDisplay);
glutReshapeFunc(cbResize);
glutIdleFunc(cbIdle);
glutTimerFunc(10000/360, cbTimer, 0);
glutKeyboardFunc(cbKey);
}
//==============================================================================
// create the interlacer
bool ilaceInit(){
// Check for OpenGL extensions, we need
if (!IlaceOgl::checkHardware())
{
std::cout << "Interlacing support is not available. Missing OpenGL
extensions:" << std::endl;
std::cout << IlaceOgl::getMissingExt();
return false;
}
// Create an interlacer
g_data.interlacer=IlaceOgl::createInstance();
// Test for failure:
if (!g_data.interlacer)
{
std::cout << "Failure, can not create interlacer" << std::endl;
return false;
}
// Set an arbitrary Stereo Mode:
IlaceOgl::setCurrentStereoMode(g_data.interlacer,"AnaglyphRedCyan");
// Query the number of camera views, we need for the stereo mode:
int camCount = IlaceOgl::getCameraCount(g_data.interlacer);
int windowWidth = glutGet(GLUT_WINDOW_WIDTH );
int windowHeight = glutGet(GLUT_WINDOW_HEIGHT);
//initialize input textures
g_data.textures.resize(camCount);
g_data.texWidth = windowWidth;
g_data.texHeight = windowHeight;
// use a helper function from IlaceOgl to request texture id's and
initialize the texture:
IlaceOgl::provideTextures(&g_data.textures[0],camCount,g_data.texWidth,g_data.texHeight);
IlaceOgl::setTextures(g_data.interlacer, &g_data.textures[0], camCount);
int screenX = 0; // Here we use 0,0 for x,y for the first display, but we should know
int screenY = 0; // the position of the display, if we use a second one.
int screenWidth = glutGet(GLUT_SCREEN_WIDTH);
int screenHeight = glutGet(GLUT_SCREEN_HEIGHT);
IlaceOgl::setScreen(g_data.interlacer, screenX, screenY, screenWidth,
screenHeight);
return true;
}
//------------------------------------------------------------------------------
void ilaceClear()
{
//free the interlacer handle
IlaceOgl::destroy(g_data.interlacer);
//free the textures
for(std::size_t i = 0; i < g_data.textures.size(); i++)
{
glDeleteTextures(1, &g_data.textures[i]);
}
g_data.textures.clear();
}
//------------------------------------------------------------------------------
// some initialization for OpenGL to make it look nice
void initOpenGL(void)
{
glClearColor(0.2, 0.2, 0.2, 1.0);
GLfloat matAmb [4] = {1.0, 1.0, 1.0, 1.0};
GLfloat matDiff[4] = {1.0, 0.1, 0.2, 1.0};
GLfloat matSpec[4] = {1.0, 1.0, 1.0, 1.0};
GLfloat lightPos [] = {10.0, 10.0, 10.0, 0.0};
GLfloat lightAmb [4] = { 0.0, 0.0, 0.0, 1.0};
GLfloat lightDiff[4] = { 1.0, 1.0, 1.0, 1.0};
GLfloat lightSpec[4] = { 1.0, 1.0, 1.0, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60.0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpec);
//cmd4 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT,
GL_SEPARATE_SPECULAR_COLOR_EXT);
GLfloat black[] = {0.0, 0.0, 0.0, 1.0};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
//------------------------------------------------------------------------------
void cbIdle(void)
{
glutPostRedisplay();
}
//------------------------------------------------------------------------------
//change the window size and position
void cbResize(int w, int h)
{
if (h == 0) h = 1;
// init or reset window positions and dimensions of the interlacer.
int windowX = glutGet(GLUT_WINDOW_X);
int windowY = glutGet(GLUT_WINDOW_Y);
int windowWidth = w; // glutGet(GLUT_WINDOW_WIDTH );
int windowHeight = h; // glutGet(GLUT_WINDOW_HEIGHT);
glViewport(0, 0, windowWidth, windowHeight);
IlaceOgl::move(g_data.interlacer, windowX, windowY);
IlaceOgl::resize(g_data.interlacer, windowWidth, windowHeight );
// also adapt the input texture size
g_data.texWidth = windowWidth;
g_data.texHeight = windowHeight;
glutPostRedisplay();
}
//------------------------------------------------------------------------------
void initCamera(std::vector<Matrix>& tgtCams, std::vector<Matrix>&
tgtProjections)
{
// init the MODEL_VIEW and PROJECTION matrices
int windowWidth = glutGet(GLUT_WINDOW_WIDTH );
int windowHeight = glutGet(GLUT_WINDOW_HEIGHT);
GLdouble aspectRatio = (GLdouble)windowWidth / (GLdouble)windowHeight;
double separation=0.3; // eye base width
double zeroPlaneDistance=4.0; // distance to the plane of no disparity
getOffAxisPerspective(&tgtProjections[0], tgtProjections.size(),
separation, zeroPlaneDistance,
45.0, aspectRatio, 0.5, 150.);
GLdouble srcCamera[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,-4.0, 1.0};
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(srcCamera);
glRotated(g_rotation, 0, 1, 0);
Matrix sourceCamera;
glGetDoublev(GL_MODELVIEW_MATRIX, sourceCamera.mat);
getViewMatrixBySeparation(sourceCamera, &tgtCams[0], tgtCams.size(),
AlignOffAxis, separation, zeroPlaneDistance);
}
//------------------------------------------------------------------------------
// draw the model
void cbDisplay()
{
int camCount = IlaceOgl::getCameraCount(g_data.interlacer);
std::vector<Matrix> tgtCams(camCount);
std::vector<Matrix> tgtProjections(camCount);
initCamera(tgtCams, tgtProjections);
// draw each view
for(int i = 0; i < camCount; i ++)
{
glClearColor(0.2, 0.2, 0.2, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// apply the MODEL_VIEW and PROJECTION matrices for the
specific target camera
glMatrixMode(GL_PROJECTION);
glLoadMatrixd(tgtProjections[i].mat);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd( tgtCams[i].mat );
// draw the model
glBindTexture(GL_TEXTURE_2D, 0);
glutSolidTeapot(1.f);
// copy to the frame buffer,
// if your hardware support it, you can also draw direct to the texture, instead copying each view
glBindTexture(GL_TEXTURE_2D, g_data.textures[i]);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0,
g_data.texWidth, g_data.texHeight, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
// interlace the views and draw to screen
IlaceOgl::render(g_data.interlacer);
GLenum errorNo = glGetError();
if (errorNo!=GL_NO_ERROR)
{
int j = 10;
}
glutSwapBuffers();
}
//------------------------------------------------------------------------------
void cbTimer(int )
{
g_rotation = (g_rotation + g_rotation_increment) %360;
glutTimerFunc(10000/360, cbTimer, 0);
}
//------------------------------------------------------------------------------
void cbKey(unsigned char k, int , int )
{
switch(k)
{
case 27: // quit
case 'Q':
case 'q':
ilaceClear();
exit(0);
break;
case 'R': // start/stop rotation
case 'r':
if (g_rotation_increment == 0) {g_rotation_increment =
1; }
else
{g_rotation_increment = 0; }
break;
}
}
//==============================================================================
int main(int argc, char* argv[])
{
//init Glut - or any other way to open an OpenGL context
initGlut(&argc, argv);
//initialize the material and lights for the geometry to render
initOpenGL();
// initialize the interlacer
if (!ilaceInit()) {return 1; }
// call the main loop
glutMainLoop();
// clean up:
ilaceClear();
return 0;
}_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org