zoukankan      html  css  js  c++  java
  • OGRE 八叉树

    void OctreeSceneManager::_addOctreeNode( OctreeNode * n, Octree *octant, int depth )
    {

     // Skip if octree has been destroyed (shutdown conditions)
     if (!mOctree)
      return;

     const AxisAlignedBox& bx = n -> _getWorldAABB();


        //if the octree is twice as big as the scene node,
        //we will add it to a child.
        if ( ( depth < mMaxDepth ) && octant -> _isTwiceSize( bx ) )//深度从0开始递归,octree根结点是n包围盒的两倍
        {
            int x, y, z;
            octant -> _getChildIndexes( bx, &x, &y, &z );//octant有八个空间,或者说是坐标系的八个象限,bx

            if ( octant -> mChildren[ x ][ y ][ z ] == 0 )//如果此空间或者说此象限是空的
            {
                octant -> mChildren[ x ][ y ][ z ] = OGRE_NEW Octree( octant );//生成一个新的子树
                const Vector3& octantMin = octant -> mBox.getMinimum();
                const Vector3& octantMax = octant -> mBox.getMaximum();//当前子树的最大,最小点
                Vector3 min, max;

                if ( x == 0 )
                {
                    min.x = octantMin.x;
                    max.x = ( octantMin.x + octantMax.x ) / 2;
                }

                else
                {
                    min.x = ( octantMin.x + octantMax.x ) / 2;
                    max.x = octantMax.x;
                }

                if ( y == 0 )
                {
                    min.y = octantMin.y;
                    max.y = ( octantMin.y + octantMax.y ) / 2;
                }

                else
                {
                    min.y = ( octantMin.y + octantMax.y ) / 2;
                    max.y = octantMax.y;
                }

                if ( z == 0 )
                {
                    min.z = octantMin.z;
                    max.z = ( octantMin.z + octantMax.z ) / 2;
                }

                else
                {min.z = ( octantMin.z + octantMax.z ) / 2;
                    max.z = octantMax.z;
                }//根据n所在的象限的位置,计算包围盒

                octant -> mChildren[ x ][ y ][ z ] -> mBox.setExtents( min, max );
                octant -> mChildren[ x ][ y ][ z ] -> mHalfSize = ( max - min ) / 2;
            }

               _addOctreeNode( n, octant -> mChildren[ x ][ y ][ z ], ++depth );//如果当前子树的包围盒

               大于包围盒的两倍,则继续遍历查找

        }

        else
        {
            octant -> _addNode( n );//至到父包围的半径小于子包围盒的两倍,则挂在当前结点上
        }
    }

    void _findNodes( const Ray &t, std::list < SceneNode * > &list, SceneNode *exclude, bool full, Octree *octant )
    {

     if ( !full )
     {
      AxisAlignedBox obox;
      octant -> _getCullBounds( &obox );//返回两倍的包围盒,用于剪裁

      Intersection isect = intersect( t, obox );

      if ( isect == OUTSIDE )//如果不想交,则返回
       return ;

      full = ( isect == INSIDE );//如果在扩张后的包围盒内部,但不相交,则full = true,否则full = false
     }

     while ( it != octant -> mNodes.end() )//向下遍历
     {
      OctreeNode * on = ( *it );

      if ( on != exclude )                            //排除exclude节点
      {
       if ( full )                                          //在扩张后的包围盒内部                  
       {
        list.push_back( on );
       }

       else                                               //如果不在扩张后的包围盒内部,则和原始包围盒重新求交
       {
        Intersection nsect = intersect( t, on -> _getWorldAABB() );

      ++it;
     }

     Octree* child;//重新向下遍历

     if ( (child=octant -> mChildren[ 1 ][ 0 ][ 0 ]) != 0 )
      _findNodes( t, list, exclude, full, child );

     if ( (child=octant -> mChildren[ 0 ][ 1 ][ 0 ]) != 0 )
      _findNodes( t, list, exclude, full, child );

     if ( (child=octant -> mChildren[ 1 ][ 1 ][ 0 ]) != 0 )
      _findNodes( t, list, exclude, full, child );

     if ( (child=octant -> mChildren[ 0 ][ 0 ][ 1 ]) != 0 )
      _findNodes( t, list, exclude, full, child );

     if ( (child=octant -> mChildren[ 1 ][ 0 ][ 1 ]) != 0 )
      _findNodes( t, list, exclude, full, child );

     if ( (child=octant -> mChildren[ 0 ][ 1 ][ 1 ]) != 0 )
      _findNodes( t, list, exclude, full, child );

     if ( (child=octant -> mChildren[ 1 ][ 1 ][ 1 ]) != 0 )
      _findNodes( t, list, exclude, full, child );

    }

    注:其他类型求交,只是换了intersector函数

    void OctreeSceneManager::_updateOctreeNode( OctreeNode * onode )
    {
        const AxisAlignedBox& box = onode -> _getWorldAABB();

        if ( box.isNull() )
            return ;

     // Skip if octree has been destroyed (shutdown conditions)
     if (!mOctree)//根结点已经破坏
      return;

        if ( onode -> getOctant() == 0 )//没有挂到节点上
        {
            //if outside the octree, force into the root node.
            if ( ! onode -> _isIn( mOctree -> mBox ) )//onode不在父节点的包围盒内,在直接挂在父节点
                mOctree->_addNode( onode );
            else
                _addOctreeNode( onode, mOctree );   //否则遍历,挂在合适的节点下

     return ;
        }

        if ( ! onode -> _isIn( onode -> getOctant() -> mBox ) )//onode不再父节点的包围盒
        {
            _removeOctreeNode( onode );

            //if outside the octree, force into the root node.
            if ( ! onode -> _isIn( mOctree -> mBox ) )              //不在根节点包围盒内,则直接挂在根结点
                mOctree->_addNode( onode );
            else
                _addOctreeNode( onode, mOctree );
        }
    }

    void OctreeSceneManager::resize( const AxisAlignedBox &box )
    {
        std::list < SceneNode * > nodes;
        std::list < SceneNode * > ::iterator it;

        _findNodes( mOctree->mBox, nodes, 0, true, mOctree );//在包围盒box内部的nodes

        OGRE_DELETE mOctree;

        mOctree = OGRE_NEW Octree( 0 );                                //生成新的根节点
        mOctree->mBox = box;

     const Vector3 min = box.getMinimum();
     const Vector3 max = box.getMaximum();
     mOctree->mHalfSize = ( max - min ) * 0.5f;   

        it = nodes.begin();

        while ( it != nodes.end() )
        {
            OctreeNode * on = static_cast < OctreeNode * > ( *it );    //重新挂在新的根节点下
            on -> setOctant( 0 );
            _updateOctreeNode( on );
            ++it;
        }

    }

  • 相关阅读:
    二叉树的递归遍历框架:
    springmvc 有哪些优点呢?
    springmvc 和 struts2 有哪些区别?
    三层架构 和 MVC 设计模式有哪些区别呢?
    软件测试各个阶段通常完成什么工作?各个阶段的结果文件是什么?包括什么内容?
    软件测试的策略是什么?
    软件产品质量特性是什么?
    软件配置管理的作用?软件配置包括什么?
    什么是软件测试?软件测试的目的与原则
    软件生存周期及其模型是什么?
  • 原文地址:https://www.cnblogs.com/lizhengjin/p/1847298.html
Copyright © 2011-2022 走看看