diff --git a/include/osgViewer/View b/include/osgViewer/View index 884e751ed..5e17cd88b 100644 --- a/include/osgViewer/View +++ b/include/osgViewer/View @@ -166,6 +166,9 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter /** Convenience method for spherical display by rendering main scene to as panoramic 2:1 texture and then doing distortion correction to present onto a spherical display.*/ void setUpViewForPanoramicSphericalDisplay(double radius=1.0, double collar=0.45, unsigned int screenNum=0, osg::Image* intensityMap=0, const osg::Matrixd& projectorMatrix = osg::Matrixd()); + /** Convenience method for autostereoscopic Philips WoWvx display.*/ + void setUpViewForWoWVxDisplay(unsigned int screenNum, unsigned char wow_content, unsigned char wow_factor, unsigned char wow_offset, float wow_disparity_Zd, float wow_disparity_vz, float wow_disparity_M, float wow_disparity_C); + /** Return true if this view contains a specified camera.*/ bool containsCamera(const osg::Camera* camera) const; diff --git a/src/osgViewer/View.cpp b/src/osgViewer/View.cpp index 05ec6421f..687c60383 100644 --- a/src/osgViewer/View.cpp +++ b/src/osgViewer/View.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -1364,6 +1365,255 @@ void View::setUpViewForPanoramicSphericalDisplay(double radius, double collar, u } } +void View::setUpViewForWoWVxDisplay(unsigned int screenNum, unsigned char wow_content, unsigned char wow_factor, unsigned char wow_offset, float wow_disparity_Zd, float wow_disparity_vz, float wow_disparity_M, float wow_disparity_C) +{ + osg::notify(osg::INFO)<<"View::setUpViewForWoWVxDisplay(...)"<getScreenResolution(si, width, height); + + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->hostName = si.hostName; + traits->displayNum = si.displayNum; + traits->screenNum = si.screenNum; + traits->x = 0; + traits->y = 0; + traits->width = width; + traits->height = height; + traits->windowDecoration = false; + traits->doubleBuffer = true; + traits->sharedContext = 0; + + + osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + if (!gc) + { + osg::notify(osg::NOTICE)<<"GraphicsWindow has not been created successfully."<setTextureSize(tex_width, tex_height); + texture->setInternalFormat(GL_RGB); + texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + + osg::Texture2D* textureD = new osg::Texture2D; + textureD->setTextureSize(tex_width, tex_height); + textureD->setInternalFormat(GL_DEPTH_COMPONENT); + textureD->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + textureD->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + +#if 0 + osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW; + GLenum buffer = GL_FRONT; +#else + osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT; + GLenum buffer = GL_FRONT; +#endif + + // front face + { + osg::ref_ptr camera = new osg::Camera; + camera->setName("Front face 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); + camera->attach(osg::Camera::DEPTH_BUFFER, textureD); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd()); + } + + // WoW display set up. + { + osg::Texture1D *textureHeader = new osg::Texture1D(); + // Set up the header + { + unsigned char header[]= {0xF1,wow_content,wow_factor,wow_offset,0x00,0x00,0x00,0x00,0x00,0x00}; + // Calc the CRC32 + { + unsigned long _register = 0; + for(int i = 0; i < 10; ++i) { + unsigned char mask = 0x80; + unsigned char byte = header[i]; + for (int j = 0; j < 8; ++j) + { + bool topBit = (_register & 0x80000000) != 0; + _register <<= 1; + _register ^= ((byte & mask) != 0? 0x1: 0x0); + if (topBit) + { + _register ^= 0x04c11db7; + } + mask >>= 1; + } + } + unsigned char *p = (unsigned char*) &_register; + for(size_t i = 0; i < 4; ++i) + { + header[i+6] = p[3-i]; + } + } + + osg::ref_ptr imageheader = new osg::Image(); + imageheader->allocateImage(256,1,1,GL_LUMINANCE,GL_UNSIGNED_BYTE); + { + unsigned char *cheader = imageheader->data(); + for (int x=0; x<256; ++x){ + cheader[x] = 0; + } + for (int x=0; x<=9; ++x){ + for (int y=7; y>=0; --y){ + int i = 2*(7-y)+16*x; + cheader[i] = (((1<<(y))&(header[x])) << (7-(y))); + } + } + } + textureHeader->setImage(imageheader.get()); + } + + // Create the Screen Aligned Quad + osg::Geode* geode = new osg::Geode(); + { + osg::Geometry* geom = new osg::Geometry; + + osg::Vec3Array* vertices = new osg::Vec3Array; + vertices->push_back(osg::Vec3(0,height,0)); + vertices->push_back(osg::Vec3(0,0,0)); + vertices->push_back(osg::Vec3(width,0,0)); + vertices->push_back(osg::Vec3(width,height,0)); + geom->setVertexArray(vertices); + + osg::Vec2Array* tex = new osg::Vec2Array; + tex->push_back(osg::Vec2(0,1)); + tex->push_back(osg::Vec2(0,0)); + tex->push_back(osg::Vec2(1,0)); + tex->push_back(osg::Vec2(1,1)); + geom->setTexCoordArray(0,tex); + + geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4)); + geode->addDrawable(geom); + + // new we need to add the textures to the quad, and setting up the shader. + osg::StateSet* stateset = geode->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(0, textureHeader,osg::StateAttribute::ON); + stateset->setTextureAttributeAndModes(1, texture,osg::StateAttribute::ON); + stateset->setTextureAttributeAndModes(2, textureD,osg::StateAttribute::ON); + stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + + osg::ref_ptr programShader = new osg::Program(); + stateset->setAttribute(programShader.get(), osg::StateAttribute::ON); + stateset->addUniform( new osg::Uniform("wow_width", (int)width)); + stateset->addUniform( new osg::Uniform("wow_height", (int)height)); + stateset->addUniform( new osg::Uniform("wow_disparity_M", wow_disparity_M)); + stateset->addUniform( new osg::Uniform("wow_disparity_Zd", wow_disparity_Zd)); + stateset->addUniform( new osg::Uniform("wow_disparity_vz", wow_disparity_vz)); + stateset->addUniform( new osg::Uniform("wow_disparity_C", wow_disparity_C)); + + stateset->addUniform(new osg::Uniform("wow_header", 0)); + stateset->addUniform(new osg::Uniform("wow_tcolor", 1)); + stateset->addUniform(new osg::Uniform("wow_tdepth", 2)); + + osg::Shader *frag = new osg::Shader(osg::Shader::FRAGMENT); + frag->setShaderSource(" "\ + " uniform sampler1D wow_header; " \ + " uniform sampler2D wow_tcolor; " \ + " uniform sampler2D wow_tdepth; " \ + " " \ + " uniform int wow_width; " \ + " uniform int wow_height; " \ + " uniform float wow_disparity_M; " \ + " uniform float wow_disparity_Zd; " \ + " uniform float wow_disparity_vz; " \ + " uniform float wow_disparity_C; " \ + " " \ + " float disparity(float Z) " \ + " { " \ + " return (wow_disparity_M*(1.0-(wow_disparity_vz/(Z-wow_disparity_Zd+wow_disparity_vz))) " \ + " + wow_disparity_C) / 255.0; " \ + " } " \ + " " \ + " void main() " \ + " { " \ + " vec2 pos = (gl_FragCoord.xy / vec2(wow_width/2,wow_height) ); " \ + " if (gl_FragCoord.x > float(wow_width/2)) " \ + " { " \ + " gl_FragColor = vec4(disparity(( texture2D(wow_tdepth, pos - vec2(1,0))).z)); " \ + " } " \ + " else{ " \ + " gl_FragColor = texture2D(wow_tcolor, pos); " \ + " } " \ + " if ( (gl_FragCoord.y >= float(wow_height-1)) && (gl_FragCoord.x < 256.0) ) " \ + " { " \ + " float pos = gl_FragCoord.x/256.0; " \ + " float blue = texture1D(wow_header, pos).b; " \ + " if ( blue < 0.5) " \ + " gl_FragColor.b -=0.5; " \ + " else " \ + " gl_FragColor.b += 0.5; " \ + " } " \ + " } " ); + + programShader->addShader(frag); + } + + // Create the Camera + { + osg::ref_ptr 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->setProjectionMatrixAsOrtho2D(0,width,0,height); + camera->setViewMatrix(osg::Matrix::identity()); + + // add subgraph to render + camera->addChild(geode); + + camera->setName("WoWCamera"); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false); + } + } +} + + void View::assignSceneDataToCameras() { diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index e10b2e9e9..f54d96ad0 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -76,7 +76,38 @@ Viewer::Viewer(osg::ArgumentParser& arguments) while (arguments.read("--window",x,y,width,height)) {} bool ss3d = false; - if ((ss3d=arguments.read("--3d-sd")) || arguments.read("--panoramic-sd")) + bool wowvx20 = false; + bool wowvx42 = false; + if ((wowvx20=arguments.read("--wowvx-20")) || (wowvx42=arguments.read("--wowvx-42")) || arguments.read("--wowvx")) + { + int wow_content=0x02, wow_factor=0x40, wow_offset=0x80; + float wow_Zd, wow_vz, wow_M, wow_C; + if (wowvx20){ + wow_Zd = 0.459813f; + wow_vz = 6.180772f; + wow_M = -1586.34f; + wow_C = 127.5f; + } + else if (wowvx42){ + wow_Zd = 0.467481f; + wow_vz = 7.655192f; + wow_M = -1960.37f; + wow_C = 127.5f; + } + + while (arguments.read("--wow-content",wow_content)) {} + while (arguments.read("--wow-factor",wow_factor)) {} + while (arguments.read("--wow-offset",wow_offset)) {} + while (arguments.read("--wow-zd",wow_Zd)) {} + while (arguments.read("--wow-vz",wow_vz)) {} + while (arguments.read("--wow-M",wow_M)) {} + while (arguments.read("--wow-C",wow_C)) {} + + if (screenNum<0) screenNum = 0; + + setUpViewForWoWVxDisplay( screenNum, wow_content, wow_factor, wow_offset, wow_Zd, wow_vz, wow_M, wow_C ); + } + else if ((ss3d=arguments.read("--3d-sd")) || arguments.read("--panoramic-sd")) { double radius = 1.0; while (arguments.read("--radius",radius)) {}