Refactored Keystone setup as a step toward integrating Keystone correction with stereo

This commit is contained in:
Robert Osfield 2013-04-18 17:02:57 +00:00
parent adea6c9329
commit a2615388db

View File

@ -391,7 +391,6 @@ struct KeystoneUpdateCallback : public osg::Drawable::UpdateCallback
}; };
osg::Geode* createKeystoneDistortionMesh(Keystone* keystone) osg::Geode* createKeystoneDistortionMesh(Keystone* keystone)
{ {
osg::ref_ptr<osg::Geode> geode = new osg::Geode; osg::ref_ptr<osg::Geode> geode = new osg::Geode;
@ -564,6 +563,94 @@ osg::Node* createGrid(Keystone* keystone, const osg::Vec4& colour)
return geode.release(); return geode.release();
} }
osg::Texture* createKestoneDistortionTexture(int width, int height)
{
osg::ref_ptr<osg::TextureRectangle> texture = new osg::TextureRectangle;
texture->setTextureSize(width, height);
texture->setInternalFormat(GL_RGB);
texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
return texture.release();
}
osg::Camera* assignKeystoneRenderToTextureCamera(osgViewer::View* view, osg::GraphicsContext* gc, int width, int height, osg::Texture* texture)
{
osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
GLenum buffer = GL_FRONT;
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setName("Render to texture camera");
camera->setGraphicsContext(gc);
camera->setViewport(new osg::Viewport(0,0,width, height));
camera->setDrawBuffer(buffer);
camera->setReadBuffer(buffer);
camera->setAllowEventFocus(false);
// tell the camera to use OpenGL frame buffer object where supported.
camera->setRenderTargetImplementation(renderTargetImplementation);
// attach the texture and use it as the color buffer.
camera->attach(osg::Camera::COLOR_BUFFER, texture);
view->addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
return camera.release();
}
osg::Camera* assignKeystoneDistortionCamera(osgViewer::View* view, osg::DisplaySettings* ds, osg::GraphicsContext* gc, int x, int y, int width, int height, GLenum buffer, osg::Texture* texture, Keystone* keystone)
{
double screenDistance = ds->getScreenDistance();
double screenWidth = ds->getScreenWidth();
double screenHeight = ds->getScreenHeight();
double fovy = osg::RadiansToDegrees(2.0*atan2(screenHeight/2.0,screenDistance));
double aspectRatio = screenWidth/screenHeight;
osg::Geode* geode = createKeystoneDistortionMesh(keystone);
// new we need to add the texture to the mesh, we do so by creating a
// StateSet to contain the Texture StateAttribute.
osg::StateSet* stateset = geode->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
osg::TexMat* texmat = new osg::TexMat;
texmat->setScaleByTextureRectangleSize(true);
stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
camera->setViewport(new osg::Viewport(x, y, width, height));
camera->setDrawBuffer(buffer);
camera->setReadBuffer(buffer);
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setAllowEventFocus(false);
camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
//camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
camera->setViewMatrix(osg::Matrix::identity());
camera->setProjectionMatrixAsPerspective(fovy, aspectRatio, 0.1, 1000.0);
// add subgraph to render
camera->addChild(geode);
camera->addChild(createGrid(keystone, osg::Vec4(1.0,1.0,1.0,1.0)));
camera->setName("DistortionCorrectionCamera");
// camera->addEventCallback(new KeystoneHandler(keystone));
view->addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
return camera.release();
}
struct StereoSlaveCallback : public osg::View::Slave::UpdateSlaveCallback struct StereoSlaveCallback : public osg::View::Slave::UpdateSlaveCallback
{ {
StereoSlaveCallback(osg::DisplaySettings* ds, double eyeScale):_ds(ds), _eyeScale(eyeScale) {} StereoSlaveCallback(osg::DisplaySettings* ds, double eyeScale):_ds(ds), _eyeScale(eyeScale) {}
@ -797,19 +884,27 @@ void setUpViewForStereo(osgViewer::View* view, osg::DisplaySettings* ds)
{ {
case(osg::DisplaySettings::QUAD_BUFFER): case(osg::DisplaySettings::QUAD_BUFFER):
{ {
// left Camera red // left Camera left buffer
{ {
osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_LEFT : GL_FRONT_LEFT, -1.0); osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_LEFT : GL_FRONT_LEFT, -1.0);
camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0);
} }
// right Camera cyan // right Camera right buffer
{ {
osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_RIGHT : GL_FRONT_RIGHT, 1.0); osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK_RIGHT : GL_FRONT_RIGHT, 1.0);
camera->setClearMask(GL_DEPTH_BUFFER_BIT); camera->setClearMask(GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1);
} }
// for keystone:
// left camera to render to left texture
// right camera to render to right texture
// left keystone camera to render to left buffer
// left keystone camera to render to right buffer
// one keystone and editing for the one window
break; break;
} }
case(osg::DisplaySettings::ANAGLYPHIC): case(osg::DisplaySettings::ANAGLYPHIC):
@ -830,6 +925,12 @@ void setUpViewForStereo(osgViewer::View* view, osg::DisplaySettings* ds)
camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1); camera->setRenderOrder(osg::Camera::NESTED_RENDER, 1);
} }
// for keystone:
// left camera to render to texture using red colour mask
// right camera to render to same texture using cyan colour mask
// keystone camera to render to whole screen without colour masks
// one keystone and editing for the one window
break; break;
} }
case(osg::DisplaySettings::HORIZONTAL_SPLIT): case(osg::DisplaySettings::HORIZONTAL_SPLIT):
@ -844,6 +945,13 @@ void setUpViewForStereo(osgViewer::View* view, osg::DisplaySettings* ds)
traits->width/2,0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, traits->width/2,0, traits->width/2, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT,
(ds->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_RIGHT_VIEWPORT) ? -1.0 : 1.0); (ds->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_RIGHT_VIEWPORT) ? -1.0 : 1.0);
// for keystone:
// left camera to render to left texture using whole viewport of left texture
// right camera to render to right texture using whole viewport of right texture
// left keystone camera to render to left viewport/window
// right keystone camera to render to right viewport/window
// two keystone, one for each of the left and right viewports/windows
break; break;
} }
case(osg::DisplaySettings::VERTICAL_SPLIT): case(osg::DisplaySettings::VERTICAL_SPLIT):
@ -858,18 +966,39 @@ void setUpViewForStereo(osgViewer::View* view, osg::DisplaySettings* ds)
0,traits->height/2, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT, 0,traits->height/2, traits->width, traits->height/2, traits->doubleBuffer ? GL_BACK : GL_FRONT,
(ds->getSplitStereoVerticalEyeMapping()==osg::DisplaySettings::LEFT_EYE_TOP_VIEWPORT) ? -1.0 : 1.0); (ds->getSplitStereoVerticalEyeMapping()==osg::DisplaySettings::LEFT_EYE_TOP_VIEWPORT) ? -1.0 : 1.0);
// for keystone:
// left camera to render to left texture using whole viewport of left texture
// right camera to render to right texture using whole viewport of right texture
// left keystone camera to render to left viewport/window
// right keystone camera to render to right viewport/window
// two keystone, one for each of the left and right viewports/windows
break; break;
} }
case(osg::DisplaySettings::LEFT_EYE): case(osg::DisplaySettings::LEFT_EYE):
{ {
// single window, whole window, just left eye offsets // single window, whole window, just left eye offsets
osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0); osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, -1.0);
// for keystone:
// treat as standard keystone correction.
// left eye camera to render to texture
// keystone camera then render to window
// one keystone and editing for window
break; break;
} }
case(osg::DisplaySettings::RIGHT_EYE): case(osg::DisplaySettings::RIGHT_EYE):
{ {
// single window, whole window, just right eye offsets // single window, whole window, just right eye offsets
osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0); osg::ref_ptr<osg::Camera> camera = assignStereoCamera(view, ds, gc, 0, 0, traits->width, traits->height, traits->doubleBuffer ? GL_BACK : GL_FRONT, 1.0);
// for keystone:
// treat as standard keystone correction.
// left eye camera to render to texture
// keystone camera then render to window
// one keystone and editing for window
break; break;
} }
case(osg::DisplaySettings::HORIZONTAL_INTERLACE): case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
@ -999,95 +1128,23 @@ void setUpViewForKeystone(osgViewer::View* view, Keystone* keystone)
return; return;
} }
int tex_width = width; osg::DisplaySettings* ds = osg::DisplaySettings::instance();
int tex_height = height;
int camera_width = tex_width;
int camera_height = tex_height;
osg::TextureRectangle* texture = new osg::TextureRectangle; // create distortion texture
osg::ref_ptr<osg::Texture> texture = createKestoneDistortionTexture(width, height);
texture->setTextureSize(tex_width, tex_height); // create RTT Camera
texture->setInternalFormat(GL_RGB); assignKeystoneRenderToTextureCamera(view, gc.get(), width, height, texture);
texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
#if 0 // create Keystone distortion camera
osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW; osg::ref_ptr<osg::Camera> camera = assignKeystoneDistortionCamera(view, ds, gc.get(),
GLenum buffer = GL_FRONT; 0, 0, width, height,
#else traits->doubleBuffer ? GL_BACK : GL_FRONT,
osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT; texture, keystone);
GLenum buffer = GL_FRONT; // attach Keystone editing event handler.
#endif camera->addEventCallback(new KeystoneHandler(keystone));
// front face
{
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setName("Render to texture camera");
camera->setGraphicsContext(gc.get());
camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
camera->setDrawBuffer(buffer);
camera->setReadBuffer(buffer);
camera->setAllowEventFocus(false);
// tell the camera to use OpenGL frame buffer object where supported.
camera->setRenderTargetImplementation(renderTargetImplementation);
// attach the texture and use it as the color buffer.
camera->attach(osg::Camera::COLOR_BUFFER, texture);
view->addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
}
// distortion correction set up.
{
double screenDistance = osg::DisplaySettings::instance()->getScreenDistance();
double screenWidth = osg::DisplaySettings::instance()->getScreenWidth();
double screenHeight = osg::DisplaySettings::instance()->getScreenHeight();
double fovy = osg::RadiansToDegrees(2.0*atan2(screenHeight/2.0,screenDistance));
double aspectRatio = screenWidth/screenHeight;
osg::Geode* geode = createKeystoneDistortionMesh(keystone);
// new we need to add the texture to the mesh, we do so by creating a
// StateSet to contain the Texture StateAttribute.
osg::StateSet* stateset = geode->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
osg::TexMat* texmat = new osg::TexMat;
texmat->setScaleByTextureRectangleSize(true);
stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc.get());
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
camera->setViewport(new osg::Viewport(0, 0, width, height));
GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
camera->setDrawBuffer(buffer);
camera->setReadBuffer(buffer);
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setAllowEventFocus(false);
camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
//camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
camera->setViewMatrix(osg::Matrix::identity());
camera->setProjectionMatrixAsPerspective(fovy, aspectRatio, 0.1, 1000.0);
// add subgraph to render
camera->addChild(geode);
camera->addChild(createGrid(keystone, osg::Vec4(1.0,1.0,1.0,1.0)));
camera->setName("DistortionCorrectionCamera");
camera->addEventCallback(new KeystoneHandler(keystone));
view->addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
}
} }
int main( int argc, char **argv ) int main( int argc, char **argv )