查看: 2047|回复: 4

OSG拾取求交

[复制链接]

该用户从未签到

发表于 2010-10-13 10:20:40 | 显示全部楼层 |阅读模式
问题是自己建立一个节点,比如由点构成的球,采用求交计算,得不到交点,为什么,以下是代码片段(用OSG的球或其他形状的可以):
(1)初始化节点片段
std::vector<std::vector<estreetPoint>>vvGlobePts;
createOriginalGlobePts(vvGlobePts);
osg::ref_ptr<osg::Group>gr=createGlobeNode(vvGlobePts);
  m_Root->addChild(gr.get());
(2)
//求球的点,以构成网格
//点按照从-90,到90的纬度线,每隔1度构成
void   COsgScene::createOriginalGlobePts(std::vector<std::vector<estreetPoint>>&vvGlobePts)
{
double x,y,z;
double a=6378245,e=1/298.3,n;
double cosB,sinB,e2=e*e,b,l;
for(double B=90;B>=-90;B-=1.0)
{
  b=B*estreetPi/180.0;
  n=a/sqrt(1-e2*sin(b)*sin(b));
  cosB=cos(b);
  sinB=sin(b);
  //保存纬度线上的点,经线按照1度增加
  std::vector<estreetPoint>vBpts;
  for(double L=0;L<=360;L+=1.0)
  {
   l=L*estreetPi/180.0;
   x=n*cosB*cos(l);
   y=n*cosB*sin(l);
   z=n*(1-e2)*sinB;
   vBpts.push_back(estreetPoint(x,y,z));
  }
  vvGlobePts.push_back(vBpts);
}
return ;
}
(3)
osg::Group*   COsgScene::createGlobeNode(std::vector<std::vector<estreetPoint>>&vvGlobePts)
{
osg::ref_ptr<osg::Geometry> pointGeom = new osg::Geometry();
pointGeom->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
pointGeom->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::ON);

int numPts=0;
osg::ref_ptr<osg::Vec3dArray> vertices = new osg::Vec3dArray();
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
//注意索引
for(int i=0;i<(int)vvGlobePts.size()-1;i++)
  for(int j=0;j<(int)vvGlobePts[i].size()-1;j++)
  {
   numPts+=4;;
   vertices->push_back(osg::Vec3d(vvGlobePts[i][j].x,vvGlobePts[i][j].y,vvGlobePts[i][j].z));
   vertices->push_back(osg::Vec3d(vvGlobePts[i+1][j].x,vvGlobePts[i+1][j].y,vvGlobePts[i+1][j].z));
   vertices->push_back(osg::Vec3d(vvGlobePts[i+1][j+1].x,vvGlobePts[i+1][j+1].y,vvGlobePts[i+1][j+1].z));
   vertices->push_back(osg::Vec3d(vvGlobePts[i][j+1].x,vvGlobePts[i][j+1].y,vvGlobePts[i][j+1].z));
   
   osg::Vec3d n1(vvGlobePts[i][j].x,vvGlobePts[i][j].y,vvGlobePts[i][j].z);
   osg::Vec3d n2(vvGlobePts[i+1][j].x,vvGlobePts[i+1][j].y,vvGlobePts[i+1][j].z);
   osg::Vec3d n3(vvGlobePts[i+1][j+1].x,vvGlobePts[i+1][j+1].y,vvGlobePts[i+1][j+1].z);
   osg::Vec3d n4(vvGlobePts[i][j+1].x,vvGlobePts[i][j+1].y,vvGlobePts[i][j+1].z);
   n1.normalize();
   n2.normalize();
   n3.normalize();
   n4.normalize();
   normals->push_back(n1);
   normals->push_back(n2);
   normals->push_back(n3);
   normals->push_back(n4);
  }
pointGeom->setVertexArray(vertices.get());
pointGeom->setNormalArray(normals.get());
pointGeom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);

pointGeom->addPrimitiveSet(new osg:rawArrays(osg:rimitiveSet:UADS,0,numPts));
osg::ref_ptr<osg::Geode>ge=new osg::Geode();
ge->addDrawable(pointGeom.get());
osg::ref_ptr<osg::Group>gr=new osg::Group();
gr->addChild(ge.get());
return gr.release();
}

该用户从未签到

发表于 2010-10-13 10:56:29 | 显示全部楼层
我没有看到您的求交代码,因此判断不了什么

该用户从未签到

 楼主| 发表于 2010-10-13 11:13:28 | 显示全部楼层
求交代码
(1)
void myManipulator::showMousePosion(int x,int y)
{
        //1、屏幕点坐标
        x=_ga_t0->getX();
        y=_ga_t0->getY();
        osg::Vec3d screenP1(x,y,0);
        //2、得到物体坐标
        osg::Vec3d objectP1;
        screenXyToObjectXYZ(screenP1,objectP1);
        //_vPoints.push_back(estreetPoint(objectP1.x(),objectP1.y(),objectP1.z()));

        std::string str="";
        std:stringstream os;
        os.precision(0);
        //os.width(12);
        os<<std::fixed<<"pt:"<<objectP1.x()<<","<<objectP1.y()<<","<<objectP1.z()
                <<",r="<<sqrt(objectP1.x()*objectP1.x()+objectP1.y()*objectP1.y()+objectP1.z()*objectP1.z())
                <<std::endl ;
        str+=os.str();
        _osgScene->m_hudText->setHudText(str);
        _osgScene->m_hudText->setPos(osg::Vec3(x,y,0));
}
(2)
bool myManipulator::screenXyToObjectXYZ(osg::Vec3d screenPt,osg::Vec3d &ptXYZ)
{       
        ////原则上一次点机只有一个位置合适。可以找到是没有问题的,但是这样找相当于从边开始,效率?
        ////相当于做25次测试
        //osgUtil:ineSegmentIntersector::Intersections intersections;
        //for(float x=screenPt.x()-3,y=screenPt.y()-3;x<screenPt.x()+3,y<screenPt.y()+3;x+=1.0,y+=1.0 )
        //{
        //        osgUtil::LineSegmentIntersector::Intersections intersections;
        //        if (_Viewer->computeIntersections(x,y,intersections))
        //        {
        //                for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
        //                        hitr != intersections.end();
        //                        ++hitr)
        //                {
        //                        ptXYZ=hitr->getWorldIntersectPoint();
        //                        return true;
        //                }
        //        }
        //}
        osg::Vec3d screenPt0(screenPt),screenPt1(screenPt),opt0,opt1;
        screenPt1.set(screenPt.x(),screenPt.y(),1);
        Matrix VPW = _Viewer->getCamera()->getViewMatrix() *
                _Viewer->getCamera()->getProjectionMatrix() *
                _Viewer->getCamera()->getViewport()->computeWindowMatrix();
        Matrix inverseVPW;
        inverseVPW.invert(VPW);
        opt0=screenPt0* inverseVPW;
        opt1=screenPt1* inverseVPW;
        intersect(opt0,opt1,ptXYZ);

        if(ptXYZ.length()>0)return true;
        else return false;
}
(3)
bool myManipulator::intersect(const osg::Vec3d& start, const osg::Vec3d& end, osg::Vec3d& intersection) const
{
    osg::ref_ptr<osgUtil::LineSegmentIntersector> lsi = new osgUtil::LineSegmentIntersector(start,end);

    osgUtil::IntersectionVisitor iv(lsi.get());
    iv.setTraversalMask(_intersectTraversalMask);
   
    _node->accept(iv);
   
    if (lsi->containsIntersections())
    {
        intersection = lsi->getIntersections().begin()->getWorldIntersectPoint();
        return true;
    }
    return false;
}

该用户从未签到

发表于 2010-10-13 13:14:44 | 显示全部楼层
您的程序中似乎不存在特别需要注意的地方,除了:
  1. Matrix VPW = ...
复制代码
这里您没有计算模型矩阵,也就是说您假设_node始终处于MainCamera下,不会有Transform父节点?

除此之外,程序本身看不出什么了,也许您的一些验证方法存在错误,或者您的getX与getY取得的值是否正确

该用户从未签到

 楼主| 发表于 2010-10-13 13:33:38 | 显示全部楼层
是在MainCamera之下。好象与getX与getY也没有啥关系,我改一个自己绘制的正方体就可以拾取到。还有通过DB读入的也可以。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表