OGRE碰撞检测MOC

 

 

 http://www.ogre3d.org/wiki/index.php/Minimal_Ogre_Collision上找到它。

      我决定把其中最核心的一段代码挑出来,详细解读。
//ray,求交射线;result,与模型面片的交点;target,相交物体;closest_distance,距离最近交点的距离;queryMask,碰撞检测掩码
bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result,Ogre::MovableObject* &target,float &closest_distance, const Ogre::uint32 queryMask)
{
  target = NULL;
      //  测试射线是否有效
      if (mRaySceneQuery != NULL)
      {
              //  创建一个射线查询
    mRaySceneQuery->setRay(ray);
    mRaySceneQuery->setSortByDistance(true);//查询结果按距离排序
    mRaySceneQuery->setQueryMask(queryMask);//设置掩码
              //  执行查询
              if (mRaySceneQuery->execute().size() <= 0)
              {
                      return (false);
              }
      }
      else
      {
              //LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG;
              return (false);
      }
      // 注意哦,到这里我们已经得到一系列按照包围盒检测到的模型了.
      // 我们要找到第一个相交的物体.
      //  这就意味着我们不必去检测后面的物体了,这样大大节省了时间
      //  但是很遗憾,我们不得不遍历每一个物体的三角面,听起来是多么痛苦,必须得忍
      // 
      //初始化最小距离为-1
  closest_distance = -1.0f;
      Ogre::Vector3 closest_result;
      Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults();//取回刚才查询的结果,因为之前并没有保存
      for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++)
      {
              //  如果下一个碰撞物体比这个还远,当然要无视啦               
              if ((closest_distance >= 0.0f) &&
                      (closest_distance < query_result[qr_idx].distance))
              {
                      break;
              }
              //  我们只关心碰撞的东西是个物体
              if ((query_result[qr_idx].movable != NULL)  &&
                      (query_result[qr_idx].movable->getMovableType().compare("Entity") == 0))
              {
                      //  取得被碰撞的物体
                      Ogre::MovableObject *pentity = static_cast<Ogre::MovableObject*>(query_result[qr_idx].movable);
                      //  顶点是顶点,索引是索引,不着急,往下看
                      size_t vertex_count;
                      size_t index_count;
                      Ogre::Vector3 *vertices;
                      Ogre::uint32 *indices;
                      //  下面的函数得到模型的详细信息
      GetMeshInformation(((Ogre::Entity*)pentity)->getMesh(), vertex_count, vertices, index_count, indices,
                                                          pentity->getParentNode()->_getDerivedPosition(),
                                                          pentity->getParentNode()->_getDerivedOrientation(),
                                                          pentity->getParentNode()->_getDerivedScale());
                      //  再次注意了,下面求每一个三角面的交点,同样记录最近点
                      bool new_closest_found = false;
                      for (size_t i = 0; i < index_count; i += 3)
                      {
                              // 下面的函数求一条射线与三角面的交点,返回一个pair,《是否相交,距离交点距离》
                              std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]],
                                      vertices[indices[i+1]], vertices[indices[i+2]], true, false);//知道索引干嘛用的了吧,索引乃顶点之索引也
                              //  如果碰撞,检查是否是当前最小距离
                              if (hit.first)
                              {
                                      if ((closest_distance < 0.0f) ||
                                              (hit.second < closest_distance))
                                      {
                                              //  如果是则更新
                                              closest_distance = hit.second;
                                              new_closest_found = true;
                                      }
                              }
                      }
      //  释放刚才申请的内存,这种东西当然是在写申请的时候就要成对编写的了,正如同时写下{}
                      delete[] vertices;
                      delete[] indices;
                      //如果找到新的点,不要忘了更新相应信息
                      if (new_closest_found)
                      {
                              target = pentity;
                              closest_result = ray.getPoint(closest_distance);//最近点的计算,简单的线性方程
                      }
              }
      }
      //  返回结果
      if (closest_distance >= 0.0f)
      {
              //  成功了
              result = closest_result;
              return (true);
      }
      else
      {
              //失败了
              return (false);
      }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值