void PickHandler::pick(osgViewer::View*
view, const osgGA::GUIEventAdapter&
ea)
{
osgUtil::LineSegmentIntersector::Intersections intersections;//求集交互器
float x = ea.getX();
float y = ea.getY();//传入事件的x,y坐标
if (view->computeIntersections(x,y,intersections))//进入computeIntersections()求交集
{
for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr =
intersections.begin();
hitr != intersections.end();
++hitr)
{
}
}
}
先传入x,y坐标,然后进入computeIntersections(x,y,intersections))求交集,在此函数加断点后进入,分析以下函数
bool View::computeIntersections(float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections,
osg::Node::NodeMask traversalMask)
{
if (!_camera.valid()) return false;
float local_x, local_y = 0.0;
const osg::Camera* camera
= getCameraContainingPosition(x, y, local_x, local_y);
if (!camera) camera = _camera.get();
osgUtil::LineSegmentIntersector::CoordinateFrame cf
= camera->getViewport()
? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
osg::ref_ptr<
osgUtil::LineSegmentIntersector
> picker = new
osgUtil::LineSegmentIntersector(cf, local_x, local_y);
osgUtil::IntersectionVisitor
iv(picker.get());//用访问者设计模式对各个节点进行访问,函数内部不断的调用各个节点相应的accepte()函数,对节点进行访问,并把节点压入_NodePath,最终对Geode用accept()访问。
iv.setTraversalMask(traversalMask);
const_cast<osg::Camera*>(camera)->accept(iv);//
if (picker->containsIntersections())
{
intersections = picker->getIntersections();
return true;
}
else
{
intersections.clear();
return false;
}
}
void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor&
iv, osg::Drawable* drawable)
{
osg::Vec3d s(_start), e(_end); //最终对某个geode的Drawable循环调用此函数
if ( !intersectAndClip(
s, e, drawable->getBound()
) ) return;
if (iv.getDoDummyTraversal()) return;
osg::KdTree* kdTree = iv.getUseKdTreeWhenAvailable() ? dynamic_cast<osg::KdTree*>(drawable->getShape()) : 0;
if (kdTree)
{
osg::KdTree::LineSegmentIntersections intersections;
intersections.reserve(4);
if (kdTree->intersect(s,e,intersections))
{
// osg::notify(osg::NOTICE)<<"Got KdTree
intersections"<<std::endl;
for(osg::KdTree::LineSegmentIntersections::iterator itr = intersections.begin();
itr != intersections.end();
++itr)
{
osg::KdTree::LineSegmentIntersection& lsi = *(itr);
// get ratio in s,e range
double ratio = lsi.ratio;
// remap ratio into _start, _end range
double remap_ratio
= ((s-_start).length() + ratio
* (e-s).length() )/(_end-_start).length();
Intersection hit;
hit.ratio = remap_ratio;
hit.matrix = iv.getModelMatrix();
hit.nodePath = iv.getNodePath();
hit.drawable = drawable;
hit.primitiveIndex
= lsi.primitiveIndex;
hit.localIntersectionPoint
= _start*(1.0-remap_ratio)
+ _end*remap_ratio;
// osg::notify(osg::NOTICE)<<"KdTree:
ratio="<<hit.ratio<<"
("<<hit.localIntersectionPoint<<")"<<std::endl;
hit.localIntersectionNormal
= lsi.intersectionNormal;
hit.indexList.reserve(3);
hit.ratioList.reserve(3);
if (lsi.r0!=0.0f)
{
hit.indexList.push_back(lsi.p0);
hit.ratioList.push_back(lsi.r0);
}
if (lsi.r1!=0.0f)
{
hit.indexList.push_back(lsi.p1);
hit.ratioList.push_back(lsi.r1);
}
if (lsi.r2!=0.0f)
{
hit.indexList.push_back(lsi.p2);
hit.ratioList.push_back(lsi.r2);
}
insertIntersection(hit);
}
}
return;
}
osg::TriangleFunctor<LineSegmentIntersectorUtils::TriangleIntersector> ti;//定义一个三角形求交器
ti.set(s,e);
drawable->accept(ti);//用三角形求交器对drawable进行访问
if (ti._hit)//如果和drawable有交点
{
osg::Geometry* geometry = drawable->asGeometry();
for(LineSegmentIntersectorUtils::TriangleIntersections::iterator
thitr = ti._intersections.begin();
thitr != ti._intersections.end();
++thitr)
{
// get ratio in s,e range
double ratio = thitr->first;
// remap ratio into _start, _end range
double remap_ratio
= ((s-_start).length() + ratio
* (e-s).length() )/(_end-_start).length();
LineSegmentIntersectorUtils::TriangleIntersection& triHit
= thitr->second;
Intersection hit;
hit.ratio = remap_ratio;
hit.matrix = iv.getModelMatrix();
hit.nodePath = iv.getNodePath();
hit.drawable = drawable;
hit.primitiveIndex
= triHit._index;
hit.localIntersectionPoint
= _start*(1.0-remap_ratio)
+ _end*remap_ratio;
// osg::notify(osg::NOTICE)<<"Conventional:
ratio="<<hit.ratio<<"
("<<hit.localIntersectionPoint<<")"<<std::endl;
hit.localIntersectionNormal
= triHit._normal;
if (geometry)
{
osg::Vec3Array*
vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
if (vertices)
{
osg::Vec3*
first = &(vertices->front());
if (triHit._v1)
{
hit.indexList.push_back(triHit._v1-first);
hit.ratioList.push_back(triHit._r1);
}
if (triHit._v2)
{
hit.indexList.push_back(triHit._v2-first);
hit.ratioList.push_back(triHit._r2);
}
if (triHit._v3)
{
hit.indexList.push_back(triHit._v3-first);
hit.ratioList.push_back(triHit._r3);
}
}
}
insertIntersection(hit);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~