Re: [osg-users] Visibility of lines
Hi, I think there might be a small bug in osg::OcclusionQueryNode, that I've yet to find. Here is a small example with a line triangle, that shows the problem. I added no face geometry so the lines should basically always be visible when in view. Each line is under an OcclusionQueryNode, but under some camera poses using the trackball manipulator, line 3 isn't visible, although it should be. When I put all the lines in a osg::Group, they are visible. Does anybody have an idea where the problem might be? Code: #include #include #include #include #include #include int main( int argc, char** argv ) { int width = 640; int height = 480; osgViewer::Viewer viewer; osg::ref_ptr camera = new osg::Camera; camera->setClearColor(osg::Vec4(1.0, 1.0, 1.0, 0.0)); camera->setViewport( new osg::Viewport(0, 0, width, height) ); camera->setProjectionMatrixAsPerspective(30.0f, static_cast(width)/static_cast(height), 1.0f, 1.0f ); viewer.setCamera(camera); osg::Group* rootnode = new osg::Group; viewer.setSceneData(rootnode); viewer.addEventHandler(new osgViewer::StatsHandler); viewer.setUpViewInWindow(200, 200, width, height); viewer.setCameraManipulator( new osgGA::TrackballManipulator ); std::vector lines; //Line 1 lines.push_back(osg::Vec3(-1,0,0)); lines.push_back(osg::Vec3(0,1,0)); //Line 2 lines.push_back(osg::Vec3(0,1,0)); lines.push_back(osg::Vec3(1,0,0)); //Line 3 lines.push_back(osg::Vec3(1,0,0)); lines.push_back( osg::Vec3(-1,0,0)); for(int i = 0; i < 3; i++){ //osg::ref_ptr parent = new osg::Group; osg::ref_ptr parent = new osg::OcclusionQueryNode; parent->setVisibilityThreshold(1); parent->setQueriesEnabled(true); osg::Geometry* linesGeom = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array; vertices->push_back(lines.at(i+i)); vertices->push_back(lines.at(i+i+1)); osg::Vec4Array* color = new osg::Vec4Array; color->push_back(osg::Vec4(1,0,0,1)); linesGeom->setColorArray(color); linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL); linesGeom->setVertexArray(vertices); linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); osg::Geode* geode = new osg::Geode(); geode->addDrawable(linesGeom); parent->addChild(geode); rootnode->addChild(parent); } return viewer.run(); } Cheers, Dakota -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=51621#51621 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Visibility of lines
Hi Jen, I haven't personally used the OcclusionQueryNode for work myself, perhaps Paul Martz the author of this feature might be able to chip in. Robert. On 12 December 2012 12:39, Jen Hunter wrote: > Hi Robert, > > thank you for your reply. I appreciate your help :) > > I'm sorry if I didn't express myself correctly. I also have to admit I'm > not quite the expert on computer graphics. > > Let's try to make it clearer. I want to know which of the lines on my > model are visible in a rendered image. That would be the case if a line > results in at least one drawn pixel. > > I need to have this information for an AR application which performs edge > tracking. Such approaches work with 2D-3D correspondences for each frame to > estimate the camera parameters. > The recorded webcam image of an object shows of course only the edges of > the object which are visible from the cameras point of view. To get the > correspondences I need excactly the same lines on the model (from the last > frame). > > I programmed a working OPENGL example for finding out the visible lines > using occlusion query glGetOcclusionQueryuivNV. > > At the moment I fail to understand how to make that work for OSG. I had a > look at osgocclusionquery and the used OcclusionQueryNode and understand > that it uses ARB_occlusion_query to check the pixel count. > > I tried the following but the output of the visible lines is still > incorrect: > > > Code: > > osg::Node* scene = osgDB::readNodeFile("file.dae"); > if (!scene) return 1; > > osg::Group* rootnode = new osg::Group; > rootnode->addChild(scene); > viewer.setSceneData(rootnode); > > GetLinesVisitor lineFinder; > scene->accept(lineFinder); > lines = lineFinder.getLineVector(); > > for(int i = 0; i < lines.size(); i++){ > > osg::ref_ptr parent = new > osg::OcclusionQueryNode; > parent->setVisibilityThreshold( 0 ); > > osg::Geometry* linesGeom = new osg::Geometry(); > osg::Vec3Array* vertices = new osg::Vec3Array; > vertices->push_back(lines.at(i).start); > vertices->push_back(lines.at(i).end); > linesGeom->setVertexArray(vertices); > linesGeom->addPrimitiveSet(new > osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); > > osg::Geode* geode = new osg::Geode(); > geode->addDrawable(linesGeom); > parent->addChild(geode); > > > //A std::vector for all OcclusionQueryNodes. I later ask in a loop > for each element oqNodes.at(i).get()->getPassed() and count the trues > oqNodes.push_back(parent); > rootnode->addChild(parent); > } > > > > > > > So here are my questions: > > (1) How do I set up an OcclusionQueryNode for each line? > > (2) Why does the approach from my previous post not work? Is the > calculation of screen coordinates (using MVPW matrix) for a given vertex > really so imprecise that I cannot count on this being the correct > coordinates to look up in the depth buffer? > > > Cheers, > Dakota > > -- > Read this topic online here: > http://forum.openscenegraph.org/viewtopic.php?p=51538#51538 > > > > > > ___ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Visibility of lines
Hi Robert, thank you for your reply. I appreciate your help :) I'm sorry if I didn't express myself correctly. I also have to admit I'm not quite the expert on computer graphics. Let's try to make it clearer. I want to know which of the lines on my model are visible in a rendered image. That would be the case if a line results in at least one drawn pixel. I need to have this information for an AR application which performs edge tracking. Such approaches work with 2D-3D correspondences for each frame to estimate the camera parameters. The recorded webcam image of an object shows of course only the edges of the object which are visible from the cameras point of view. To get the correspondences I need excactly the same lines on the model (from the last frame). I programmed a working OPENGL example for finding out the visible lines using occlusion query glGetOcclusionQueryuivNV. At the moment I fail to understand how to make that work for OSG. I had a look at osgocclusionquery and the used OcclusionQueryNode and understand that it uses ARB_occlusion_query to check the pixel count. I tried the following but the output of the visible lines is still incorrect: Code: osg::Node* scene = osgDB::readNodeFile("file.dae"); if (!scene) return 1; osg::Group* rootnode = new osg::Group; rootnode->addChild(scene); viewer.setSceneData(rootnode); GetLinesVisitor lineFinder; scene->accept(lineFinder); lines = lineFinder.getLineVector(); for(int i = 0; i < lines.size(); i++){ osg::ref_ptr parent = new osg::OcclusionQueryNode; parent->setVisibilityThreshold( 0 ); osg::Geometry* linesGeom = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array; vertices->push_back(lines.at(i).start); vertices->push_back(lines.at(i).end); linesGeom->setVertexArray(vertices); linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2)); osg::Geode* geode = new osg::Geode(); geode->addDrawable(linesGeom); parent->addChild(geode); //A std::vector for all OcclusionQueryNodes. I later ask in a loop for each element oqNodes.at(i).get()->getPassed() and count the trues oqNodes.push_back(parent); rootnode->addChild(parent); } So here are my questions: (1) How do I set up an OcclusionQueryNode for each line? (2) Why does the approach from my previous post not work? Is the calculation of screen coordinates (using MVPW matrix) for a given vertex really so imprecise that I cannot count on this being the correct coordinates to look up in the depth buffer? Cheers, Dakota -- Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=51538#51538 ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Visibility of lines
On 5 December 2012 16:31, Robert Osfield wrote: > Are you away of the OpenGL occlusion querry feature? > Opps typo, "away" should be "aware". Have a look at the osgocclusionquery example for more details. Robert. ___ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Re: [osg-users] Visibility of lines
Hi Jen, I'll not dive into the details of how you are going about things as I suspect it might be best to tackle things in a different way. So.. could you explain from a higher level what you need to do and for what purpose. Please explain what exactly you mean by visible - just in the view frustum or do you mean just contributes pixels to the final on screen? Are you away of the OpenGL occlusion querry feature? Robert. On 5 December 2012 11:28, Jen Hunter wrote: > Dear osg community, > > currently I need to find out which lines were visible in last drawn frame. > > My current approach is the following: > > (1) I use a NodeVisitor to check the loaded model for lines. I store the > vertices of each line in a class LineData. Every LineData object is stored > in a vector. > > (2) Knowing the lines I want to determine which of them were visible in > the last view. I calculate the screen coordinates for each vertex of a line > (vec = V * modelViewMatrix * projectionMatrix * windowMatrix). > > (3) Then I convert the z values of the screen coordinates to depth values > using Znear*Zfar / (Zfar - vec.z()*(Zfar-Znear)). > > (4) After that I check the depth buffer of the last frame at the position > of the screen coordinates and also extract the depth value using the > formula from (3). > > (5) Then I substract both depth values and for the start and the end point > of the line and if both results are under a specified threshold i count the > line as visible. > > However, I think in theory it should be working this way, but the > calculated number of visible lines is almost always wrong. I found out that > for some calculated screen coordinates one dimension is one pixel off, so > that I do not access the correct pixel in the depth buffer which is why the > returned value of these is the zfar value and not the wanted depth. > > > I attached some code and a model to show my problem. When you click at a > point on the model the visible lines are calculated. While the camera is in > home position the output of the visible lines on the command line is 4 > which is correct. When you move the camera and try different poses the > number of calculated visible lines changes but almost never to the desired > number which can be counted on the rendered image. > > > Code: > > #include > > #include > #include > #include > #include > #include > #include > #include > #include > > #include > #include > #include > #include > > osg::Matrix lastViewMatrix; > > struct CaptureCB : public osg::Camera::DrawCallback{ > > CaptureCB(osg::ref_ptrimg1){ > image3D = img1; > } > virtual void operator()( osg::RenderInfo& ri ) const{ > > image3D->readPixels( 0, 0, > ri.getCurrentCamera()->getViewport()->width(), > ri.getCurrentCamera()->getViewport()->height(), GL_DEPTH_COMPONENT, > GL_FLOAT ); > osg::ref_ptr osgCam = ri.getCurrentCamera(); > osgCam->attach(osg::Camera::DEPTH_BUFFER,image3D.get()); > lastViewMatrix = ri.getCurrentCamera()->getViewMatrix(); > } > protected: > osg::ref_ptrimage3D; > > }; > > class LineData{ > > public: > LineData(){}; > ~LineData(){}; > > osg::Vec3 start; > osg::Vec3 end; > > void setLine(osg::Vec3 s, osg::Vec3 e){ > start = s; > end = e; > > for(int i = 1; i < samplePointNr; i++){ > double t = (double)i/samplePointNr; > osg::Vec3 p(start.x() * (1-t) + end.x() * t, start.y() * > (1-t) + end.y() * t, start.z() * (1-t) + end.z() * t); > samplePoints.push_back(p); > } > } > > bool operator == (const LineData& line2) const{ > > if > ((!start.valid())||(!end.valid())||(!line2.start.valid())||(!line2.end.valid())) > return false; > > return ((start.x() == line2.start.x()) && > (start.y() == line2.start.y()) && > (start.z() == line2.start.z()) && > (end.x() == line2.end.x()) && > (end.y() == line2.end.y()) && > (end.z() == line2.end.z())); > } > > void printValues(){ > std::cout<<"start: "< "< > } > > double getEuclideanDistance(osg::Vec3 s,osg::Vec3 e){ > double dist = sqrt( pow(s.x() - e.x(), 2) + pow(s.y() - e.y(), 2) > + pow(s.z() - e.z(), 2) ); > return dist; > } > > private: > int samplePointNr; > std::vectorsamplePoints; > > > }; > > std::vectorlines; > osg::ref_ptr image = new osg::Image; > > //Determine lines in the model > class GetLinesVisitor : public osg::NodeVisitor{ > > public: > > GetLinesVisitor(): > osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){ > numberOfLines = 0; > numberOfLinesDeleted = 0; > } > > std::vector getLi