diff --git a/src/hmdcamera.cpp b/src/hmdcamera.cpp index c3aed0c..fb83193 100644 --- a/src/hmdcamera.cpp +++ b/src/hmdcamera.cpp @@ -22,9 +22,9 @@ HMDCamera::HMDCamera(osgViewer::View* view, osg::ref_ptr dev) : osg::Group(), m_configured(false), - m_chromaticAberrationCorrection(false), + m_useChromaticAberrationCorrection(false), m_view(view), - m_dev(dev) + m_device(dev) { } @@ -40,54 +40,58 @@ void HMDCamera::traverse(osg::NodeVisitor& nv) } // Get orientation from oculus sensor - osg::Quat orient = m_dev->getOrientation(); + osg::Quat orient = m_device->getOrientation(); // Nasty hack to update the view offset for each of the slave cameras // There doesn't seem to be an accessor for this, fortunately the offsets are public - m_view->findSlaveForCamera(m_l_rtt.get())->_viewOffset.setRotate(orient); - m_view->findSlaveForCamera(m_r_rtt.get())->_viewOffset.setRotate(orient); + m_view->findSlaveForCamera(m_cameraRTTLeft.get())->_viewOffset.setRotate(orient); + m_view->findSlaveForCamera(m_cameraRTTRight.get())->_viewOffset.setRotate(orient); osg::Group::traverse(nv); } -osg::Camera* HMDCamera::createRTTCamera(osg::Camera::BufferComponent buffer, osg::Texture* tex) +osg::Camera* HMDCamera::createRTTCamera(osg::Texture* texture, osg::GraphicsContext* gc) const { osg::ref_ptr camera = new osg::Camera; camera->setClearColor(osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f)); camera->setClearMask( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); + camera->setDrawBuffer(GL_FRONT); + camera->setReadBuffer(GL_FRONT); camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT ); - camera->setRenderOrder( osg::Camera::PRE_RENDER ); - camera->setGraphicsContext(m_view->getCamera()->getGraphicsContext()); + camera->setRenderOrder(osg::Camera::PRE_RENDER); + camera->setAllowEventFocus(false); + camera->setGraphicsContext(gc); camera->setReferenceFrame(osg::Camera::RELATIVE_RF); - if ( tex ) { - tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR ); - tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR ); - camera->setViewport( 0, 0, tex->getTextureWidth(), tex->getTextureHeight() ); - camera->attach( buffer, tex, 0, 0, false, 4, 4); + if ( texture ) { + texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); + texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR); + camera->setViewport(0, 0, texture->getTextureWidth(), texture->getTextureHeight()); + camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, 0, false, 4, 4); } return camera.release(); } -osg::Camera* HMDCamera::createHUDCamera(double left, double right, double bottom, double top) +osg::Camera* HMDCamera::createHUDCamera(double left, double right, double bottom, double top, osg::GraphicsContext* gc) const { osg::ref_ptr camera = new osg::Camera; - camera->setGraphicsContext(m_view->getCamera()->getGraphicsContext()); camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF ); camera->setClearColor(osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f)); camera->setClearMask( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - camera->setRenderOrder( osg::Camera::POST_RENDER ); - camera->setAllowEventFocus( false ); - camera->setProjectionMatrix( osg::Matrix::ortho2D(left, right, bottom, top) ); + camera->setRenderOrder(osg::Camera::POST_RENDER); + camera->setAllowEventFocus(false); + camera->setGraphicsContext(gc); + camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); + camera->setProjectionMatrix(osg::Matrix::ortho2D(left, right, bottom, top)); camera->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); return camera.release(); } -osg::Geode* HMDCamera::createHUDQuad( float width, float height, float scale ) +osg::Geode* HMDCamera::createHUDQuad( float width, float height, float scale ) const { osg::Geometry* geom = osg::createTexturedQuadGeometry(osg::Vec3(), - osg::Vec3(width, 0.0f, 0.0f), - osg::Vec3(0.0f, height, 0.0f), - 0.0f, 0.0f, width*scale, height*scale ); + osg::Vec3(width, 0.0f, 0.0f), + osg::Vec3(0.0f, height, 0.0f), + 0.0f, 0.0f, width*scale, height*scale ); osg::ref_ptr quad = new osg::Geode; quad->addDrawable( geom ); int values = osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED; @@ -96,33 +100,63 @@ osg::Geode* HMDCamera::createHUDQuad( float width, float height, float scale ) return quad.release(); } +void HMDCamera::applyShaderParameters(osg::StateSet* stateSet, osg::Program* program, + osg::Texture2D* texture, OculusDevice::EyeSide eye) const { + stateSet->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); + stateSet->setAttributeAndModes( program, osg::StateAttribute::ON ); + stateSet->addUniform( new osg::Uniform("WarpTexture", 0) ); + stateSet->addUniform( new osg::Uniform("LensCenter", m_device->lensCenter(eye))); + stateSet->addUniform( new osg::Uniform("ScreenCenter", m_device->screenCenter())); + stateSet->addUniform( new osg::Uniform("Scale", m_device->scale())); + stateSet->addUniform( new osg::Uniform("ScaleIn", m_device->scaleIn())); + stateSet->addUniform( new osg::Uniform("HmdWarpParam", m_device->warpParameters())); + stateSet->addUniform( new osg::Uniform("ChromAbParam", m_device->chromAbParameters())); +} + void HMDCamera::configure() { - const int textureWidth = m_dev->scaleFactor() * m_dev->hScreenResolution()/2; - const int textureHeight = m_dev->scaleFactor() * m_dev->vScreenResolution(); + const int textureWidth = m_device->scaleFactor() * m_device->hScreenResolution()/2; + const int textureHeight = m_device->scaleFactor() * m_device->vScreenResolution(); + // master projection matrix - m_view->getCamera()->setProjectionMatrix(m_dev->projectionCenterMatrix()); - osg::ref_ptr l_tex = new osg::Texture2D; - l_tex->setTextureSize( textureWidth, textureHeight ); - l_tex->setInternalFormat( GL_RGBA ); - osg::ref_ptr r_tex = new osg::Texture2D; - r_tex->setTextureSize( textureWidth, textureHeight ); - r_tex->setInternalFormat( GL_RGBA ); - osg::ref_ptr l_rtt = createRTTCamera(osg::Camera::COLOR_BUFFER, l_tex); - m_l_rtt = l_rtt; - osg::ref_ptr r_rtt = createRTTCamera(osg::Camera::COLOR_BUFFER, r_tex); - m_r_rtt = r_rtt; + m_view->getCamera()->setProjectionMatrix(m_device->projectionCenterMatrix()); + m_view->setName("Oculus"); + osg::ref_ptr mainCamera = m_view->getCamera(); + mainCamera->setName("Main"); + // Disable scene rendering for main camera + mainCamera->setCullMask(~m_sceneNodeMask); + + osg::ref_ptr textureLeft = new osg::Texture2D; + textureLeft->setTextureSize( textureWidth, textureHeight ); + textureLeft->setInternalFormat( GL_RGBA ); + osg::ref_ptr textureRight = new osg::Texture2D; + textureRight->setTextureSize( textureWidth, textureHeight ); + textureRight->setInternalFormat( GL_RGBA ); + + osg::ref_ptr gc = mainCamera->getGraphicsContext(); + // Create render to texture cameras + m_cameraRTTLeft = createRTTCamera(textureLeft, gc.get()); + m_cameraRTTRight = createRTTCamera(textureRight, gc.get()); + m_cameraRTTLeft->setName("LeftRTT"); + m_cameraRTTRight->setName("RightRTT"); + m_cameraRTTLeft->setCullMask(m_sceneNodeMask); + m_cameraRTTRight->setCullMask(m_sceneNodeMask); + + // Create HUD cameras for each eye - osg::ref_ptr l_hud = createHUDCamera(0.0, 1.0, 0.0, 1.0); - l_hud->setViewport(new osg::Viewport(0, 0, m_dev->hScreenResolution() / 2.0f, m_dev->vScreenResolution())); - osg::ref_ptr r_hud = createHUDCamera(0.0, 1.0, 0.0, 1.0); - r_hud->setViewport(new osg::Viewport(m_dev->hScreenResolution() / 2.0f, 0, - m_dev->hScreenResolution() / 2.0f, m_dev->vScreenResolution())); + osg::ref_ptr cameraHUDLeft = createHUDCamera(0.0, 1.0, 0.0, 1.0, gc.get()); + cameraHUDLeft->setName("LeftHUD"); + cameraHUDLeft->setViewport(new osg::Viewport(0, 0, m_device->hScreenResolution() / 2.0f, m_device->vScreenResolution())); + osg::ref_ptr cameraHUDRight = createHUDCamera(0.0, 1.0, 0.0, 1.0, gc.get()); + cameraHUDRight->setName("RightHUD"); + cameraHUDRight->setViewport(new osg::Viewport(m_device->hScreenResolution() / 2.0f, 0, + m_device->hScreenResolution() / 2.0f, m_device->vScreenResolution())); // Create quads on each camera osg::ref_ptr leftQuad = createHUDQuad(1.0f, 1.0f); - l_hud->addChild(leftQuad); + cameraHUDLeft->addChild(leftQuad); osg::ref_ptr rightQuad = createHUDQuad(1.0f, 1.0f); - r_hud->addChild(rightQuad); + cameraHUDRight->addChild(rightQuad); + // Set up shaders from the Oculus SDK documentation osg::ref_ptr program = new osg::Program; osg::ref_ptr vertexShader = new osg::Shader(osg::Shader::VERTEX); @@ -130,7 +164,7 @@ void HMDCamera::configure() osg::ref_ptr fragmentShader = new osg::Shader(osg::Shader::FRAGMENT); // Fragment shader with or without correction for chromatic aberration - if (m_chromaticAberrationCorrection) { + if (m_useChromaticAberrationCorrection) { fragmentShader->loadShaderSourceFromFile(osgDB::findDataFile("warpWithChromeAb.frag")); } else { fragmentShader->loadShaderSourceFromFile(osgDB::findDataFile("warpWithoutChromeAb.frag")); @@ -138,32 +172,21 @@ void HMDCamera::configure() program->addShader(vertexShader); program->addShader(fragmentShader); - // Configure state sets for both eyes + + // Attach shaders to each HUD osg::StateSet* leftEyeStateSet = leftQuad->getOrCreateStateSet(); - leftEyeStateSet->setTextureAttributeAndModes(0, l_tex, osg::StateAttribute::ON); - leftEyeStateSet->setAttributeAndModes( program, osg::StateAttribute::ON ); - leftEyeStateSet->addUniform( new osg::Uniform("WarpTexture", 0) ); - leftEyeStateSet->addUniform( new osg::Uniform("LensCenter", m_dev->lensCenter(OculusDevice::LEFT_EYE))); - leftEyeStateSet->addUniform( new osg::Uniform("ScreenCenter", m_dev->screenCenter())); - leftEyeStateSet->addUniform( new osg::Uniform("Scale", m_dev->scale())); - leftEyeStateSet->addUniform( new osg::Uniform("ScaleIn", m_dev->scaleIn())); - leftEyeStateSet->addUniform( new osg::Uniform("HmdWarpParam", m_dev->warpParameters())); - leftEyeStateSet->addUniform( new osg::Uniform("ChromAbParam", m_dev->chromAbParameters())); osg::StateSet* rightEyeStateSet = rightQuad->getOrCreateStateSet(); - rightEyeStateSet->setTextureAttributeAndModes(0, r_tex, osg::StateAttribute::ON); - rightEyeStateSet->setAttributeAndModes( program, osg::StateAttribute::ON ); - rightEyeStateSet->addUniform( new osg::Uniform("WarpTexture", 0) ); - rightEyeStateSet->addUniform( new osg::Uniform("LensCenter", m_dev->lensCenter(OculusDevice::RIGHT_EYE))); - rightEyeStateSet->addUniform( new osg::Uniform("ScreenCenter", m_dev->screenCenter())); - rightEyeStateSet->addUniform( new osg::Uniform("Scale", m_dev->scale())); - rightEyeStateSet->addUniform( new osg::Uniform("ScaleIn", m_dev->scaleIn())); - rightEyeStateSet->addUniform( new osg::Uniform("HmdWarpParam", m_dev->warpParameters())); - rightEyeStateSet->addUniform( new osg::Uniform("ChromAbParam", m_dev->chromAbParameters())); + applyShaderParameters(leftEyeStateSet, program.get(), textureLeft.get(), OculusDevice::LEFT_EYE); + applyShaderParameters(rightEyeStateSet, program.get(), textureRight.get(), OculusDevice::RIGHT_EYE); + // Add cameras as slaves, specifying offsets for the projection - // View takes ownership of our cameras, that's why we keep only weak pointers to them - m_view->addSlave(l_rtt, m_dev->projectionOffsetMatrix(OculusDevice::LEFT_EYE), m_dev->viewMatrix(OculusDevice::LEFT_EYE), true); - m_view->addSlave(r_rtt, m_dev->projectionOffsetMatrix(OculusDevice::RIGHT_EYE), m_dev->viewMatrix(OculusDevice::RIGHT_EYE), true); - m_view->addSlave(l_hud, false); - m_view->addSlave(r_hud, false); + m_view->addSlave(m_cameraRTTLeft.get(), m_device->projectionOffsetMatrix(OculusDevice::LEFT_EYE), + m_device->viewMatrix(OculusDevice::LEFT_EYE), + true); + m_view->addSlave(m_cameraRTTRight.get(), m_device->projectionOffsetMatrix(OculusDevice::RIGHT_EYE), + m_device->viewMatrix(OculusDevice::RIGHT_EYE), + true); + m_view->addSlave(cameraHUDLeft, false); + m_view->addSlave(cameraHUDRight, false); m_configured = true; } diff --git a/src/hmdcamera.h b/src/hmdcamera.h index 0cd24b0..a0773c8 100644 --- a/src/hmdcamera.h +++ b/src/hmdcamera.h @@ -10,8 +10,8 @@ #include -// Forward declarations -class OculusDevice; +#include "oculusdevice.h" + namespace osgViewer { class View; class NodeVisitor; @@ -21,20 +21,23 @@ class HMDCamera: public osg::Group { public: HMDCamera(osgViewer::View* view, osg::ref_ptr dev); virtual void traverse(osg::NodeVisitor& nv); - void setChromaticAberrationCorrection(bool correctionEnabled) { m_chromaticAberrationCorrection = correctionEnabled; } + void setChromaticAberrationCorrection(bool correctionEnabled) { m_useChromaticAberrationCorrection = correctionEnabled; } + void setSceneNodeMask(osg::Node::NodeMask nodeMask) { m_sceneNodeMask = nodeMask; } protected: ~HMDCamera(); virtual void configure(); - osg::Camera* createRTTCamera(osg::Camera::BufferComponent buffer, osg::Texture* tex); - osg::Camera* createHUDCamera(double left, double right, double bottom, double top); - osg::Geode* createHUDQuad( float width, float height, float scale = 1.0f ); - + osg::Camera* createRTTCamera(osg::Texture* tex, osg::GraphicsContext* gc) const; + osg::Camera* createHUDCamera(double left, double right, double bottom, double top, osg::GraphicsContext* gc) const; + osg::Geode* createHUDQuad(float width, float height, float scale = 1.0f) const; + void applyShaderParameters(osg::StateSet* stateSet, osg::Program* program, + osg::Texture2D* texture, OculusDevice::EyeSide eye) const; bool m_configured; - bool m_chromaticAberrationCorrection; + bool m_useChromaticAberrationCorrection; osg::observer_ptr m_view; - osg::observer_ptr m_l_rtt, m_r_rtt; - osg::observer_ptr m_dev; + osg::observer_ptr m_cameraRTTLeft, m_cameraRTTRight; + osg::observer_ptr m_device; + osg::Node::NodeMask m_sceneNodeMask; }; #endif /* _OSG_HMDCAMERA_H_ */ diff --git a/src/osgoculusviewer_deprecated.cpp b/src/osgoculusviewer_deprecated.cpp index 966bafb..b0d38f5 100644 --- a/src/osgoculusviewer_deprecated.cpp +++ b/src/osgoculusviewer_deprecated.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "oculusdevice.h" #include "hmdcamera.h" @@ -49,6 +50,8 @@ int main( int argc, char** argv ) // Open the HMD osg::ref_ptr oculusDevice = new OculusDevice(); oculusDevice->setCustomScaleFactor(1.25f); + + // Create screen with match the Oculus Rift resolution osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { @@ -56,9 +59,23 @@ int main( int argc, char** argv ) return 1; } + // Get the screen identifiers set in environment variable DISPLAY + osg::GraphicsContext::ScreenIdentifier si; + si.readDISPLAY(); + + // If displayNum has not been set, reset it to 0. + if (si.displayNum < 0) si.displayNum = 0; + + // If screenNum has not been set, reset it to 0. + if (si.screenNum < 0) si.screenNum = 0; + unsigned int width, height; - wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height); + wsi->getScreenResolution(si, width, height); + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->hostName = si.hostName; + traits->screenNum = si.screenNum; + traits->displayNum = si.displayNum; traits->windowDecoration = false; traits->x = 0; traits->y = 0; @@ -66,10 +83,14 @@ int main( int argc, char** argv ) traits->height = oculusDevice->vScreenResolution(); traits->doubleBuffer = true; traits->sharedContext = 0; - traits->sampleBuffers = true; - traits->samples = 4; - traits->vsync = true; + traits->vsync = true; // VSync should always be enabled for Oculus Rift applications + + // Create a graphic context based on our desired traits osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits); + if (!gc) { + osg::notify(osg::NOTICE) << "Error, GraphicsWindow has not been created successfully" << std::endl; + return 1; + } if (gc.valid()) { gc->setClearColor(osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f)); @@ -79,17 +100,23 @@ int main( int argc, char** argv ) osgViewer::Viewer viewer(arguments); viewer.getCamera()->setGraphicsContext(gc); viewer.getCamera()->setViewport(0, 0, traits->width, traits->height); + // Disable automatic computation of near and far plane viewer.getCamera()->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); viewer.setCameraManipulator(cameraManipulator); viewer.realize(); + + // Subtract at least one bit of the node mask to disable rendering for main camera + osg::Node::NodeMask sceneNodeMask = loadedModel->getNodeMask() & ~0x1; + loadedModel->setNodeMask(sceneNodeMask); + osg::ref_ptr hmd_camera = new HMDCamera(&viewer, oculusDevice); hmd_camera->setChromaticAberrationCorrection(true); + hmd_camera->setSceneNodeMask(sceneNodeMask); hmd_camera->addChild(loadedModel); viewer.setSceneData(hmd_camera); - // Create matrix for camera position and orientation (from HMD) - osg::Matrix cameraManipulatorViewMatrix; - osg::Matrix orientationMatrix; + // Add statistics handler + viewer.addEventHandler(new osgViewer::StatsHandler); // Start Viewer viewer.run(); return 0;