void RadialLineOfSightNode::compute_fill(osg::Node* node) { if ( !getMapNode() ) return; GeoPoint centerMap; _center.transform( getMapNode()->getMapSRS(), centerMap ); centerMap.toWorld( _centerWorld, getMapNode()->getTerrain() ); bool isProjected = getMapNode()->getMapSRS()->isProjected(); osg::Vec3d up = isProjected ? osg::Vec3d(0,0,1) : osg::Vec3d(_centerWorld); up.normalize(); //Get the "side" vector osg::Vec3d side = isProjected ? osg::Vec3d(1,0,0) : up ^ osg::Vec3d(0,0,1); //Get the number of spokes double delta = osg::PI * 2.0 / (double)_numSpokes; osg::Geometry* geometry = new osg::Geometry; geometry->setUseVertexBufferObjects(true); osg::Vec3Array* verts = new osg::Vec3Array(); verts->reserve(_numSpokes * 2); geometry->setVertexArray( verts ); osg::Vec4Array* colors = new osg::Vec4Array(); colors->reserve( _numSpokes * 2 ); geometry->setColorArray( colors ); geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); osg::ref_ptr<osgUtil::IntersectorGroup> ivGroup = new osgUtil::IntersectorGroup(); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { double angle = delta * (double)i; osg::Quat quat(angle, up ); osg::Vec3d spoke = quat * (side * _radius); osg::Vec3d end = _centerWorld + spoke; osg::ref_ptr<DPLineSegmentIntersector> dplsi = new DPLineSegmentIntersector( _centerWorld, end ); ivGroup->addIntersector( dplsi.get() ); } osgUtil::IntersectionVisitor iv; iv.setIntersector( ivGroup.get() ); node->accept( iv ); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { //Get the current hit DPLineSegmentIntersector* los = dynamic_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[i].get()); DPLineSegmentIntersector::Intersections& hits = los->getIntersections(); osg::Vec3d currEnd = los->getEnd(); bool currHasLOS = hits.empty(); osg::Vec3d currHit = currHasLOS ? osg::Vec3d() : hits.begin()->getWorldIntersectPoint(); //Get the next hit unsigned int nextIndex = i + 1; if (nextIndex == _numSpokes) nextIndex = 0; DPLineSegmentIntersector* losNext = static_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[nextIndex].get()); DPLineSegmentIntersector::Intersections& hitsNext = losNext->getIntersections(); osg::Vec3d nextEnd = losNext->getEnd(); bool nextHasLOS = hitsNext.empty(); osg::Vec3d nextHit = nextHasLOS ? osg::Vec3d() : hitsNext.begin()->getWorldIntersectPoint(); if (currHasLOS && nextHasLOS) { //Both rays have LOS verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _goodColor ); } else if (!currHasLOS && !nextHasLOS) { //Both rays do NOT have LOS //Draw the "good triangle" verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _goodColor ); //Draw the two bad triangles verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } else if (!currHasLOS && nextHasLOS) { //Current does not have LOS but next does //Draw the good portion verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _goodColor ); //Draw the bad portion verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } else if (currHasLOS && !nextHasLOS) { //Current does not have LOS but next does //Draw the good portion verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _goodColor ); //Draw the bad portion verts->push_back( nextHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } } geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, verts->size())); osg::Geode* geode = new osg::Geode(); geode->addDrawable( geometry ); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); osg::MatrixTransform* mt = new osg::MatrixTransform; mt->setMatrix(osg::Matrixd::translate(_centerWorld)); mt->addChild(geode); //Remove all the children removeChildren(0, getNumChildren()); addChild( mt ); for( LOSChangedCallbackList::iterator i = _changedCallbacks.begin(); i != _changedCallbacks.end(); i++ ) { i->get()->onChanged(); } }
void RadialLineOfSightNode::compute_line(osg::Node* node) { if ( !getMapNode() ) return; GeoPoint centerMap; _center.transform( getMapNode()->getMapSRS(), centerMap ); centerMap.toWorld( _centerWorld, getMapNode()->getTerrain() ); bool isProjected = getMapNode()->getMapSRS()->isProjected(); osg::Vec3d up = isProjected ? osg::Vec3d(0,0,1) : osg::Vec3d(_centerWorld); up.normalize(); //Get the "side" vector osg::Vec3d side = isProjected ? osg::Vec3d(1,0,0) : up ^ osg::Vec3d(0,0,1); //Get the number of spokes double delta = osg::PI * 2.0 / (double)_numSpokes; osg::Geometry* geometry = new osg::Geometry; geometry->setUseVertexBufferObjects(true); osg::Vec3Array* verts = new osg::Vec3Array(); verts->reserve(_numSpokes * 5); geometry->setVertexArray( verts ); osg::Vec4Array* colors = new osg::Vec4Array(); colors->reserve( _numSpokes * 5 ); geometry->setColorArray( colors ); geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); osg::Vec3d previousEnd; osg::Vec3d firstEnd; osg::ref_ptr<osgUtil::IntersectorGroup> ivGroup = new osgUtil::IntersectorGroup(); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { double angle = delta * (double)i; osg::Quat quat(angle, up ); osg::Vec3d spoke = quat * (side * _radius); osg::Vec3d end = _centerWorld + spoke; osg::ref_ptr<DPLineSegmentIntersector> dplsi = new DPLineSegmentIntersector( _centerWorld, end ); ivGroup->addIntersector( dplsi.get() ); } osgUtil::IntersectionVisitor iv; iv.setIntersector( ivGroup.get() ); node->accept( iv ); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { DPLineSegmentIntersector* los = dynamic_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[i].get()); DPLineSegmentIntersector::Intersections& hits = los->getIntersections(); osg::Vec3d start = los->getStart(); osg::Vec3d end = los->getEnd(); osg::Vec3d hit; bool hasLOS = hits.empty(); if (!hasLOS) { hit = hits.begin()->getWorldIntersectPoint(); } if (hasLOS) { verts->push_back( start - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _goodColor ); colors->push_back( _goodColor ); } else { if (_displayMode == LineOfSight::MODE_SPLIT) { verts->push_back( start - _centerWorld ); verts->push_back( hit - _centerWorld ); colors->push_back( _goodColor ); colors->push_back( _goodColor ); verts->push_back( hit - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _badColor ); colors->push_back( _badColor ); } else if (_displayMode == LineOfSight::MODE_SINGLE) { verts->push_back( start - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _badColor ); colors->push_back( _badColor ); } } if (i > 0) { verts->push_back( end - _centerWorld ); verts->push_back( previousEnd - _centerWorld ); colors->push_back( _outlineColor ); colors->push_back( _outlineColor ); } else { firstEnd = end; } previousEnd = end; } //Add the last outside of circle verts->push_back( firstEnd - _centerWorld ); verts->push_back( previousEnd - _centerWorld ); colors->push_back( osg::Vec4(1,1,1,1)); colors->push_back( osg::Vec4(1,1,1,1)); geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, verts->size())); osg::Geode* geode = new osg::Geode(); geode->addDrawable( geometry ); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); osg::MatrixTransform* mt = new osg::MatrixTransform; mt->setMatrix(osg::Matrixd::translate(_centerWorld)); mt->addChild(geode); //Remove all the children removeChildren(0, getNumChildren()); addChild( mt ); for( LOSChangedCallbackList::iterator i = _changedCallbacks.begin(); i != _changedCallbacks.end(); i++ ) { i->get()->onChanged(); } }