| 31 | | public: |
| 32 | | |
| 33 | | DistortionNode(); |
| 34 | | |
| 35 | | DistortionNode(const DistortionNode& rhs,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): |
| 36 | | osg::Group(rhs,copyop) {} |
| 37 | | |
| 38 | | META_Node(osgDistortion, DistortionNode); |
| 39 | | |
| 40 | | virtual void traverse(osg::NodeVisitor& nv); |
| 41 | | |
| 42 | | protected: |
| 43 | | |
| 44 | | void createHUDSubgraph(); |
| 45 | | |
| 46 | | void preRender(osgUtil::CullVisitor& nv); |
| 47 | | |
| 48 | | osg::ref_ptr<osg::Node> _hudSubgraph; |
| 49 | | osg::ref_ptr<osg::Texture2D> _texture; |
| 50 | | osg::ref_ptr<osg::StateSet> _localStateSet; |
| 51 | | |
| 52 | | }; |
| 53 | | |
| 54 | | |
| 55 | | DistortionNode::DistortionNode() |
| 56 | | { |
| 57 | | setCullingActive(false); |
| 58 | | createHUDSubgraph(); |
| 59 | | } |
| 60 | | |
| 61 | | void DistortionNode::createHUDSubgraph() |
| 62 | | { |
| 63 | | // create the quad to visualize. |
| 64 | | osg::Geometry* polyGeom = new osg::Geometry(); |
| 65 | | |
| 66 | | polyGeom->setSupportsDisplayList(false); |
| 67 | | |
| 68 | | osg::Vec3 origin(0.0f,0.0f,0.0f); |
| 69 | | osg::Vec3 xAxis(1.0f,0.0f,0.0f); |
| 70 | | osg::Vec3 yAxis(0.0f,1.0f,0.0f); |
| 71 | | osg::Vec3 zAxis(0.0f,0.0f,1.0f); |
| 72 | | float height = 1024.0f; |
| 73 | | float width = 1280.0f; |
| 74 | | int noSteps = 50; |
| 75 | | |
| 76 | | osg::Vec3Array* vertices = new osg::Vec3Array; |
| 77 | | osg::Vec2Array* texcoords = new osg::Vec2Array; |
| 78 | | osg::Vec4Array* colors = new osg::Vec4Array; |
| 79 | | |
| 80 | | osg::Vec3 bottom = origin; |
| 81 | | osg::Vec3 dx = xAxis*(width/((float)(noSteps-1))); |
| 82 | | osg::Vec3 dy = yAxis*(height/((float)(noSteps-1))); |
| 83 | | |
| 84 | | osg::Vec2 bottom_texcoord(0.0f,0.0f); |
| 85 | | osg::Vec2 dx_texcoord(1.0f/(float)(noSteps-1),0.0f); |
| 86 | | osg::Vec2 dy_texcoord(0.0f,1.0f/(float)(noSteps-1)); |
| 87 | | |
| 88 | | osg::Vec3 cursor = bottom; |
| 89 | | osg::Vec2 texcoord = bottom_texcoord; |
| 90 | | int i,j; |
| 91 | | for(i=0;i<noSteps;++i) |
| 92 | | { |
| 93 | | osg::Vec3 cursor = bottom+dy*(float)i; |
| 94 | | osg::Vec2 texcoord = bottom_texcoord+dy_texcoord*(float)i; |
| 95 | | for(j=0;j<noSteps;++j) |
| 96 | | { |
| 97 | | vertices->push_back(cursor); |
| 98 | | texcoords->push_back(osg::Vec2((sin(texcoord.x()*osg::PI-osg::PI*0.5)+1.0f)*0.5f,(sin(texcoord.y()*osg::PI-osg::PI*0.5)+1.0f)*0.5f)); |
| 99 | | colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); |
| 100 | | |
| 101 | | cursor += dx; |
| 102 | | texcoord += dx_texcoord; |
| 103 | | } |
| 104 | | } |
| 105 | | |
| 106 | | // pass the created vertex array to the points geometry object. |
| 107 | | polyGeom->setVertexArray(vertices); |
| 108 | | |
| 109 | | polyGeom->setColorArray(colors); |
| 110 | | polyGeom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); |
| 111 | | |
| 112 | | polyGeom->setTexCoordArray(0,texcoords); |
| 113 | | |
| 114 | | |
| 115 | | for(i=0;i<noSteps-1;++i) |
| 116 | | { |
| 117 | | osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP); |
| 118 | | for(j=0;j<noSteps;++j) |
| 119 | | { |
| 120 | | elements->push_back(j+(i+1)*noSteps); |
| 121 | | elements->push_back(j+(i)*noSteps); |
| 122 | | } |
| 123 | | polyGeom->addPrimitiveSet(elements); |
| 124 | | } |
| 125 | | |
| 126 | | |
| 127 | | // new we need to add the texture to the Drawable, we do so by creating a |
| 128 | | // StateSet to contain the Texture StateAttribute. |
| 129 | | osg::StateSet* stateset = new osg::StateSet; |
| 130 | | |
| | 30 | osg::Group* distortionNode = new osg::Group; |
| | 31 | |
| | 32 | unsigned int tex_width = 1024; |
| | 33 | unsigned int tex_height = 1024; |
| | 34 | |
| 136 | | stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); |
| 137 | | stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); |
| 138 | | polyGeom->setStateSet(stateset); |
| 139 | | |
| 140 | | _texture = texture; |
| 141 | | |
| 142 | | osg::Geode* geode = new osg::Geode(); |
| 143 | | geode->addDrawable(polyGeom); |
| 144 | | |
| 145 | | // create the hud. |
| 146 | | osg::MatrixTransform* modelview_abs = new osg::MatrixTransform; |
| 147 | | modelview_abs->setReferenceFrame(osg::Transform::ABSOLUTE_RF); |
| 148 | | modelview_abs->setMatrix(osg::Matrix::identity()); |
| 149 | | modelview_abs->addChild(geode); |
| 150 | | |
| 151 | | osg::Projection* projection = new osg::Projection; |
| 152 | | projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); |
| 153 | | projection->addChild(modelview_abs); |
| 154 | | |
| 155 | | _hudSubgraph = projection; |
| 156 | | |
| 157 | | _localStateSet = new osg::StateSet; |
| 158 | | |
| 159 | | |
| 160 | | } |
| 161 | | |
| 162 | | |
| 163 | | void DistortionNode::traverse(osg::NodeVisitor& nv) |
| 164 | | { |
| 165 | | if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) |
| 166 | | { |
| 167 | | osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(&nv); |
| 168 | | if (cullVisitor && _texture.valid() && _hudSubgraph.valid()) |
| | 40 | |
| | 41 | // set up the render to texture camera. |
| | 42 | { |
| | 43 | osg::CameraNode* camera = new osg::CameraNode; |
| | 44 | |
| | 45 | // just inherit the main cameras view |
| | 46 | camera->setReferenceFrame(osg::Transform::RELATIVE_RF); |
| | 47 | camera->setProjectionMatrix(osg::Matrixd::identity()); |
| | 48 | camera->setViewMatrix(osg::Matrixd::identity()); |
| | 49 | |
| | 50 | // set viewport |
| | 51 | camera->setViewport(0,0,tex_width,tex_height); |
| | 52 | camera->getOrCreateStateSet()->setAttribute(camera->getViewport()); |
| | 53 | |
| | 54 | // set the camera to render before the main camera. |
| | 55 | camera->setRenderOrder(osg::CameraNode::PRE_RENDER); |
| | 56 | |
| | 57 | // tell the camera to use OpenGL frame buffer object where supported. |
| | 58 | camera->setRenderTargetImplmentation(osg::CameraNode::FRAME_BUFFER_OBJECT); |
| | 59 | |
| | 60 | // attach the texture and use it as the color buffer. |
| | 61 | camera->attach(osg::CameraNode::COLOR_BUFFER, texture); |
| | 62 | |
| | 63 | // add subgraph to render |
| | 64 | camera->addChild(subgraph); |
| | 65 | |
| | 66 | distortionNode->addChild(camera); |
| | 67 | } |
| | 68 | |
| | 69 | // set up the render to texture camera. |
| | 70 | { |
| | 71 | |
| | 72 | // create the quad to visualize. |
| | 73 | osg::Geometry* polyGeom = new osg::Geometry(); |
| | 74 | |
| | 75 | polyGeom->setSupportsDisplayList(false); |
| | 76 | |
| | 77 | osg::Vec3 origin(0.0f,0.0f,0.0f); |
| | 78 | osg::Vec3 xAxis(1.0f,0.0f,0.0f); |
| | 79 | osg::Vec3 yAxis(0.0f,1.0f,0.0f); |
| | 80 | osg::Vec3 zAxis(0.0f,0.0f,1.0f); |
| | 81 | float height = 1024.0f; |
| | 82 | float width = 1280.0f; |
| | 83 | int noSteps = 50; |
| | 84 | |
| | 85 | osg::Vec3Array* vertices = new osg::Vec3Array; |
| | 86 | osg::Vec2Array* texcoords = new osg::Vec2Array; |
| | 87 | osg::Vec4Array* colors = new osg::Vec4Array; |
| | 88 | |
| | 89 | osg::Vec3 bottom = origin; |
| | 90 | osg::Vec3 dx = xAxis*(width/((float)(noSteps-1))); |
| | 91 | osg::Vec3 dy = yAxis*(height/((float)(noSteps-1))); |
| | 92 | |
| | 93 | osg::Vec2 bottom_texcoord(0.0f,0.0f); |
| | 94 | osg::Vec2 dx_texcoord(1.0f/(float)(noSteps-1),0.0f); |
| | 95 | osg::Vec2 dy_texcoord(0.0f,1.0f/(float)(noSteps-1)); |
| | 96 | |
| | 97 | osg::Vec3 cursor = bottom; |
| | 98 | osg::Vec2 texcoord = bottom_texcoord; |
| | 99 | int i,j; |
| | 100 | for(i=0;i<noSteps;++i) |
| 176 | | } |
| 177 | | |
| 178 | | Group::traverse(nv); |
| 179 | | } |
| 180 | | |
| 181 | | void DistortionNode::preRender(osgUtil::CullVisitor& cv) |
| 182 | | { |
| 183 | | // create the render to texture stage. |
| 184 | | osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage; |
| 185 | | |
| 186 | | // set up lighting. |
| 187 | | // currently ignore lights in the scene graph itself.. |
| 188 | | // will do later. |
| 189 | | osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->getStage(); |
| 190 | | |
| 191 | | // set up the background color and clear mask. |
| 192 | | rtts->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f)); |
| 193 | | rtts->setClearMask(previous_stage->getClearMask()); |
| 194 | | |
| 195 | | // set up to charge the same RenderStageLighting is the parent previous stage. |
| 196 | | rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); |
| 197 | | |
| 198 | | |
| 199 | | // record the render bin, to be restored after creation |
| 200 | | // of the render to text |
| 201 | | osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin(); |
| 202 | | |
| 203 | | // set the current renderbin to be the newly created stage. |
| 204 | | cv.setCurrentRenderBin(rtts.get()); |
| 205 | | |
| 206 | | cv.pushStateSet(_localStateSet.get()); |
| 207 | | |
| 208 | | { |
| 209 | | |
| 210 | | // traverse the subgraph |
| 211 | | Group::traverse(cv); |
| 212 | | |
| 213 | | } |
| 214 | | |
| 215 | | cv.popStateSet(); |
| 216 | | |
| 217 | | // restore the previous renderbin. |
| 218 | | cv.setCurrentRenderBin(previousRenderBin); |
| 219 | | |
| 220 | | if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0) |
| 221 | | { |
| 222 | | // getting to this point means that all the subgraph has been |
| 223 | | // culled by small feature culling or is beyond LOD ranges. |
| 224 | | return; |
| 225 | | } |
| 226 | | |
| 227 | | int height = 1024; |
| 228 | | int width = 1024; |
| 229 | | |
| 230 | | |
| 231 | | const osg::Viewport& viewport = *cv.getViewport(); |
| 232 | | |
| 233 | | // offset the impostor viewport from the center of the main window |
| 234 | | // viewport as often the edges of the viewport might be obscured by |
| 235 | | // other windows, which can cause image/reading writing problems. |
| 236 | | int center_x = viewport.x()+viewport.width()/2; |
| 237 | | int center_y = viewport.y()+viewport.height()/2; |
| 238 | | |
| 239 | | osg::Viewport* new_viewport = new osg::Viewport; |
| 240 | | new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height); |
| 241 | | rtts->setViewport(new_viewport); |
| 242 | | |
| 243 | | _localStateSet->setAttribute(new_viewport); |
| 244 | | |
| 245 | | // and the render to texture stage to the current stages |
| 246 | | // dependancy list. |
| 247 | | cv.getCurrentRenderBin()->getStage()->addToDependencyList(rtts.get()); |
| 248 | | |
| 249 | | // if one exist attach texture to the RenderToTextureStage. |
| 250 | | if (_texture.valid()) rtts->setTexture(_texture.get()); |
| | 114 | |
| | 115 | // pass the created vertex array to the points geometry object. |
| | 116 | polyGeom->setVertexArray(vertices); |
| | 117 | |
| | 118 | polyGeom->setColorArray(colors); |
| | 119 | polyGeom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); |
| | 120 | |
| | 121 | polyGeom->setTexCoordArray(0,texcoords); |
| | 122 | |
| | 123 | |
| | 124 | for(i=0;i<noSteps-1;++i) |
| | 125 | { |
| | 126 | osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP); |
| | 127 | for(j=0;j<noSteps;++j) |
| | 128 | { |
| | 129 | elements->push_back(j+(i+1)*noSteps); |
| | 130 | elements->push_back(j+(i)*noSteps); |
| | 131 | } |
| | 132 | polyGeom->addPrimitiveSet(elements); |
| | 133 | } |
| | 134 | |
| | 135 | |
| | 136 | // new we need to add the texture to the Drawable, we do so by creating a |
| | 137 | // StateSet to contain the Texture StateAttribute. |
| | 138 | osg::StateSet* stateset = polyGeom->getOrCreateStateSet(); |
| | 139 | stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); |
| | 140 | stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); |
| | 141 | |
| | 142 | osg::Geode* geode = new osg::Geode(); |
| | 143 | geode->addDrawable(polyGeom); |
| | 144 | |
| | 145 | // set up the camera to render the textured quad |
| | 146 | osg::CameraNode* camera = new osg::CameraNode; |
| | 147 | |
| | 148 | // just inherit the main cameras view |
| | 149 | camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); |
| | 150 | camera->setViewMatrix(osg::Matrix::identity()); |
| | 151 | camera->setProjectionMatrixAsOrtho2D(0,1280,0,1024); |
| | 152 | |
| | 153 | // set the camera to render before the main camera. |
| | 154 | camera->setRenderOrder(osg::CameraNode::NESTED_RENDER); |
| | 155 | |
| | 156 | // tell the camera to use OpenGL frame buffer object where supported. |
| | 157 | camera->setRenderTargetImplmentation(osg::CameraNode::FRAME_BUFFER_OBJECT); |
| | 158 | |
| | 159 | // attach the texture and use it as the color buffer. |
| | 160 | camera->attach(osg::CameraNode::COLOR_BUFFER, texture); |
| | 161 | |
| | 162 | // add subgraph to render |
| | 163 | camera->addChild(geode); |
| | 164 | |
| | 165 | distortionNode->addChild(camera); |
| | 166 | } |
| | 167 | return distortionNode; |