求交后高亮显示某个Drawable:
if (picker->containsIntersections())
{
osg::Vec3 ptWorldIntersectPointFirst= picker->getFirstIntersection().getWorldIntersectPoint();
cout<<"world coords vertex("<< ptWorldIntersectPointFirst.x()<<","
<< ptWorldIntersectPointFirst.y()<< ","<< ptWorldIntersectPointFirst.z()<<")"<< std::endl;
//高亮此点
double dPointRadius= 15.0f;
osg::ShapeDrawable* pShd= new osg::ShapeDrawable(
new osg::Sphere( ptWorldIntersectPointFirst, dPointRadius));
pShd->setColor( osg::Vec4( 0, 1, 0, 1));
geode->addDrawable( pShd);
////将此Drawable高亮显示(更改其材质--散射光)
//osg::ref_ptr< osg::StateSet> pssDra= picker->getFirstIntersection().drawable->getOrCreateStateSet();
////改变颜色
//osg::Material* mat = dynamic_cast< osg::Material*>
// ( pssDra->getAttribute( osg::StateAttribute::MATERIAL));
//if ( mat == NULL)
//{
//mat = new osg::Material;
// mat->setDataVariance( osg::Object::DYNAMIC);
// pssDra->setAttribute( mat);
//}
//mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1, 0, 0, 0));
//直接改变其颜色
osg::ref_ptr< osg::Geometry> pGmt= picker->getFirstIntersection().drawable->asGeometry();
if ( pGmt != NULL)
{
//颜色(先获取原始颜色数组,再调用dirty()更新)
osg::Vec4Array* pv4aColorsOld= dynamic_cast< osg::Vec4Array*> ( pGmt->getColorArray());
if ( pv4aColorsOld != NULL)
{
pv4aColorsOld->clear();
pv4aColorsOld->push_back( osg::Vec4( 1.0f, 0.0f, 0.0f, 1.0f) );//红色
pv4aColorsOld->dirty();//更新颜色数组
pGmt->getOrCreateStateSet()->setMode( GL_LIGHTING,osg::StateAttribute::OFF|
osg::StateAttribute::OVERRIDE);//关闭灯光
}
else
{
pv4aColorsOld= new osg::Vec4Array;
pv4aColorsOld->push_back( osg::Vec4( 1.0f, 0.0f, 0.0f, 1.0f) );//红色
pGmt->setColorArray( pv4aColorsOld);
pGmt->setColorBinding( osg::Geometry::BIND_OVERALL/*BIND_PER_PRIMITIVE_SET:*/);
pGmt->getOrCreateStateSet()->setMode( GL_LIGHTING,osg::StateAttribute::OFF|
osg::StateAttribute::OVERRIDE);//关闭灯光
}
}
}
注:要先获取颜色数组(getColorArray()),再更新(dirty())。如果调用Geometry ->setColorArray(…)来重新设置颜色数组,则会出错。
另一种方法是通过改变材质,但要开启光照,且高亮的颜色可能会随着光照而变化。
―――――――――――――――――――――――――
较完整代码如下:
bool CHUD_viewPoint::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
{
switch(ea.getEventType())
{
case( osgGA::GUIEventAdapter::PUSH):
{
m_vPosWindowMouse.set( ea.getX(), ea.getY());//鼠标单击处的窗口坐标
osgViewer::Viewer* viewer = dynamic_cast< osgViewer::Viewer*>( &aa);
if (viewer)
{
UpdateText( viewer, ea);//更新文字信息
//主相机
osg::ref_ptr<osg::Camera> cameraMaster = viewer->getCamera();
osg::Matrix mvpw = cameraMaster->getViewMatrix() * cameraMaster->getProjectionMatrix();
if ( cameraMaster->getViewport()) mvpw.postMult( cameraMaster->getViewport()->computeWindowMatrix());
osg::Matrix _inverseMVPW;
_inverseMVPW.invert( mvpw);
osg::Vec3d nearPoint = osg::Vec3d( ea.getX(), ea.getY(), 0.0)* _inverseMVPW;//透视投影中Znear平面的交点
osg::Vec3d farPoint = osg::Vec3d( ea.getX(), ea.getY(), 1.0)* _inverseMVPW;//透视投影中Zfar平面的交点
////求交
//osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(
// osgUtil::Intersector::WINDOW, ea.getX(), ea.getY());
//osgUtil::IntersectionVisitor iv( picker.get());
////g_grpMouse->getParent( 0)->getChild( 0)->accept( iv);//模型求交
//cameraMaster->accept( iv);//模型求交(从相机往下遍历)
//求交
osg::ref_ptr< osgUtil::LineSegmentIntersector > picker =new osgUtil::LineSegmentIntersector(
nearPoint, farPoint);//线段(真实的世界坐标)
osgUtil::IntersectionVisitor iv( picker.get());
//g_grpMouse->getParent( 0)->getChild( 0)->accept( iv);//模型求交/**/
g_grpMouse->getParent( 0)->getChild( 0)->/*asGroup()->getChild( 0)->*/accept( iv);//模型求交/**/
// 根节点 cow的MT节点
//cameraMaster->accept( iv);//模型求交(从相机往下遍历)
if (picker->containsIntersections())
{
osg::Vec3 ptWorldIntersectPointFirst= picker->getFirstIntersection().getWorldIntersectPoint();
cout<<"world coords vertex("<< ptWorldIntersectPointFirst.x()<<","
<< ptWorldIntersectPointFirst.y()<< ","<< ptWorldIntersectPointFirst.z()<<")"<< std::endl;
//高亮此点
double dPointRadius= 15.0f;
osg::ShapeDrawable* pShd= new osg::ShapeDrawable(
new osg::Sphere( ptWorldIntersectPointFirst, dPointRadius));
pShd->setColor( osg::Vec4( 0, 1, 0, 1));
geode->addDrawable( pShd);
////将此Drawable高亮显示(更改其材质--散射光)
//osg::ref_ptr< osg::StateSet> pssDra= picker->getFirstIntersection().drawable->getOrCreateStateSet();
////改变颜色
//osg::Material* mat = dynamic_cast< osg::Material*>
// ( pssDra->getAttribute( osg::StateAttribute::MATERIAL));
//if ( mat == NULL)
//{
/// mat = new osg::Material;
// mat->setDataVariance( osg::Object::DYNAMIC);
// pssDra->setAttribute( mat);
//}
//mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1, 0, 0, 0));
//直接改变其颜色
osg::ref_ptr< osg::Geometry> pGmt= picker->getFirstIntersection().drawable->asGeometry();
if ( pGmt != NULL)
{
//颜色(先获取原始颜色数组,再调用dirty()更新)
osg::Vec4Array* pv4aColorsOld= dynamic_cast< osg::Vec4Array*> ( pGmt->getColorArray());
if ( pv4aColorsOld != NULL)
{
pv4aColorsOld->clear();
pv4aColorsOld->push_back( osg::Vec4( 1.0f, 0.0f, 0.0f, 1.0f) );//红色
pv4aColorsOld->dirty();//更新颜色数组
pGmt->getOrCreateStateSet()->setMode( GL_LIGHTING,osg::StateAttribute::OFF|
osg::StateAttribute::OVERRIDE);//关闭灯光
}
else
{
pv4aColorsOld= new osg::Vec4Array;
pv4aColorsOld->push_back( osg::Vec4( 1.0f, 0.0f, 0.0f, 1.0f) );//红色
pGmt->setColorArray( pv4aColorsOld);
pGmt->setColorBinding( osg::Geometry::BIND_OVERALL/*BIND_PER_PRIMITIVE_SET:*/);
pGmt->getOrCreateStateSet()->setMode( GL_LIGHTING,osg::StateAttribute::OFF|
osg::StateAttribute::OVERRIDE);//关闭灯光
}
}
}
}
return true;
}
default:
return false;
}
}
博客介绍了在3D场景中,如何通过求交算法找到点击位置对应的Drawable,并实现高亮显示。当点击发生时,创建一个Sphere Drawable并设置为绿色,用于标记高亮点。同时,提供了两种方式修改Drawable的颜色,一种是直接更改颜色数组,另一种是通过材质设置散射光。代码示例详细展示了具体操作步骤。
862

被折叠的 条评论
为什么被折叠?



