求交后高亮显示某个Drawable

博客介绍了在3D场景中,如何通过求交算法找到点击位置对应的Drawable,并实现高亮显示。当点击发生时,创建一个Sphere Drawable并设置为绿色,用于标记高亮点。同时,提供了两种方式修改Drawable的颜色,一种是直接更改颜色数组,另一种是通过材质设置散射光。代码示例详细展示了具体操作步骤。

求交后高亮显示某个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

    }

}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值