游戏开发论坛

 找回密码
 立即注册
搜索
查看: 12949|回复: 10

BSP树

[复制链接]

23

主题

63

帖子

68

积分

注册会员

Rank: 2

积分
68
发表于 2007-7-10 21:16:00 | 显示全部楼层 |阅读模式
                           二叉空间分割(BSP)
1.什么是BSP树
BSP树就是用来对N维空间中的元素进行排序和查找的二叉树。BSP树表示整个空间,BSP树中的任意一个接点表示一个凸的子空间。每个接点包含一个“超平面”,将这个接点表示的空间分割成两个子空间。每个接点除了保存其两个子接点的引用以外,还可以保存一个或多个元素。

对于N维空间,超平面为N-1维的对象。通常,用BSP树来表示二维或者三维空间,这时,空间中的元素分别指的是线段和多边型。

因其强大的排序和分类功能,BSP树有着非常广泛的应用。从隐藏面剔除、光线追踪到实体建模和机器人动作规划,都能看到BSP树的身影。

2.举例
认识BSP树,可以从二维空间的简单例子开始。为了简化问题,我们假定空间中的线段都是与X或者Y轴平行的,并且每次我们把空间分割成相等的两部分。比如,一个处于XY平面的正方形,第一次分割,在X方向将其分割成相等的两部分,以后的分割,按X->Y->X…的顺序进行。除非进行人为的干预,此过程将递归地进行下去。下图描述了次过程和与之对应的BSP树。



待续。。。

23

主题

63

帖子

68

积分

注册会员

Rank: 2

积分
68
 楼主| 发表于 2007-7-10 22:21:00 | 显示全部楼层

Re: BSP树

如何建立BSP树
介绍
给定三维空间中的一组多边形,我们要建立的BSP树应该包含它们当中的每一个。建立BSP树的算法是非常简单的:
1.选择分割平面
如何建立BSP树
介绍
        给定三维空间中的一组多边形,我们要建立的BSP树应该包含它们当中的每一个。建立BSP树的算法是非常简单的:
1.        选择分割平面
分割平面的选择依赖于BSP树将如何被使用,以及空间中多边形的排序条件。某些情况下,使用空间中某个多边形所在的平面进行分割(叫做自动分割)。在另外一些情况下,与坐标轴垂直的平面常被用做分割平面。
在任何一种情况下,对选择分割平面的策略进行评估都是很重要的。一个很普遍的想法是让BSP树的结构尽量趋近于平衡二叉树,但是这样做是有代价的。要实现一个完全平衡的BSP树,当一个多边形与分割平面相交时,它必须被分割成两部分。一个糟糕的分割平面选择策略会产生很多这样的分割。
2.        分割多边形集合
需要根据步骤1中选择的分割平面将多边形集合分解成两个子集。如果一个多边形完全处于分割平面的一侧,只需要把它添加对应的子集中。如果与分割平面相交,先将其分成两部分,再分别添加到两个子集中。
3.        何时停止分割
判断建立BSP树的递归过程在什么条件下停止,也是与具体的应用有关的。可以在接点包含的多边形数目小于某个界限时停止,也可以当BSP树的深度超过某个界限时停止。

伪代码
struct BSP_tree
{
        plane     partition;
        list      polygons;
        BSP_tree  *front, *back;
};

这个结构体定义在下面的讨论中将被一直使用。它表示BSP树的一个接点,包含有一个分割平面,处于分割平面的多边形列表,以及指向子接点的指针。

void Buld_BSP_Tree( BSP_tree *tree, list polygons )
{
    polygon *root = polygons.Get_From_List();
    tree->partition = root->Get_Plane();
    tree->polygons.Add_To_List( root );
    list                front_list, back_list;
    polygon  *poly;

    while( ( poly = polygons.Get_From_List() ) != 0 )
    {
        int result = tree->partition.Classify_polygon(poly);

        switch( result )
        {
        case COINCIDENT:                // 共面
             tree->polygons.Add_To_List(poly);
             break;
        case IN_BACK_OF:
             back_list.Add_To_List(poly);
             break;
        case IN_FRONT_OF
             front_list.Add_To_List(poly);
             break;
        case SPANNING:
             polygon        *front_piece, *back_piece;
           split_Polygon( poly, tree->partition, front_piece, back_piece );
             back_list.Add_To_List( back_piece );
             front_list.Add_To_List( front_piece );
             break;
         }
       }

       if( !front_list.Is->Empty_List() )
       {
        tree->front = new BSP_tree;
        Build_BSP_Tree( tree->front, front_list );
       }
       if( !back_list->Is_Empty_List() )
       {
        tree->back = new BSP_tree;
        Build_BSP_Tree( tree->back, back_list );
       }
}

Buld_BSP_Tree函数根据以上说明的步骤递归地建立BSP树。它使用输入的多边形列表中的第一个多边形所在的平面作为分割平面,假定此列表中的每一个多边形都为凸多边形。
很明显,通过更合理的分割平面选择策略,这个函数可以得到改进,以后将详细为大家阐述。

待续。。。

23

主题

63

帖子

68

积分

注册会员

Rank: 2

积分
68
 楼主| 发表于 2007-7-11 22:12:00 | 显示全部楼层

Re: BSP树

如何用平面对多边形分类

用平面对多边形分类也就是判断平面位于多边形的哪一边。这通常被称为前/后测试,是通过测试多边形的每一个顶点与平面的位置关系来完成的。基本的算法就是遍利多边形的每一条边,找出那些两个顶点分别位于多边形两侧的边,交点将成为分割出的两个多边形的新曾顶点。

关于实现:
用平面对顶点分类,只需要把顶点的XYZ坐标值代入平面方程,AX+BY+CZ +D = 0,结果的绝对值为顶点到平面的距离,结果的符号与平面法线的方向有关。如果顶点位于平面法线所指的半平面,结果为正,否则为负。

下面是分割一个凸多边形的C++伪代码。
#define EPSILON numeric_limits<float>::epsilon( )

void SplitPolygon(polygon *poly, plane *part, polygon **front, polygon **back)
{
        size_t verNum = poly->NumVertices();

        point ptA, ptB;
        float distA, distB;
        std::vector<point> verFront, verBack;

        ptA = poly->Vertex[verNum-1];
        distA = poly->ClassifyPoint( ptA );        //求带符号距离

        for( size_t i = EPSILON; ++i < verNum; )
        {
                ptB = poly->Vertex;
                distB = poly->ClassifyPoint( ptB );

                if( distB > EPSILON && distA < -EPSILON )
                {
                        vector v = ptA - ptB;
                        normalize(v);
                        float sect = -part->ClassifyPoint(ptA) / Dot(poly->normal(), v );
                        verFront.push_back(ptA+(v*sect));
                        verBack.push_back(ptA+(v*sect));
                        verFront.push_back(ptB);
                }
                else if( distB<-EPSILON && distA>EPSILON )
                {
                        vector v = ptB - ptA;
                        normalize(v);
                        float sect = -part->ClassifyPoint(ptB) / Dot(poly->normal(), v );
                        verFront.push_back(ptB+(v*sect));
                        verBack.push_back(ptB+(v*sect));
                        verBack.push_back(ptB);
                }
                else if( distB>EPSILON && distA>EPSILON )
                {
                        verFront.push_back(ptB);
                }
                else if( distB<-EPSILON && distA<-EPSILON )
                {
                        verBack.push_back(ptB);
                }
                else if( distB>-EPSILON && distB<EPSILON )
                {
                        verFront.push_back(ptB);
                        verBack.push_back(ptB);
                }

                ptA = ptB;
                distA = distB;
        }

        if( !verFront.empty() )
                *front = new polygon(verFront);
        if( !verBack.empty() )
                *back = new polygon(verBack);
}

待续。。。

16

主题

65

帖子

75

积分

注册会员

Rank: 2

积分
75
发表于 2007-7-30 19:00:00 | 显示全部楼层

Re:BSP树

学到东西了 就要顶一下 楼下的说是不是?

121

主题

2029

帖子

2034

积分

金牌会员

Rank: 6Rank: 6

积分
2034
QQ
发表于 2007-7-30 21:21:00 | 显示全部楼层

Re:BSP树

又是BSP树。。。不过还是感谢楼主传播知识。。。

3

主题

18

帖子

22

积分

注册会员

Rank: 2

积分
22
发表于 2007-8-8 09:01:00 | 显示全部楼层

Re:BSP树

谢谢LZ,对BSP终于有了点了解

4

主题

10

帖子

14

积分

新手上路

Rank: 1

积分
14
发表于 2007-8-9 09:40:00 | 显示全部楼层

Re:BSP树

先顶了再看

5

主题

72

帖子

74

积分

注册会员

Rank: 2

积分
74
发表于 2009-2-10 13:31:00 | 显示全部楼层

Re:BSP树

支持

5

主题

263

帖子

1113

积分

金牌会员

Rank: 6Rank: 6

积分
1113
发表于 2010-11-9 22:34:00 | 显示全部楼层

Re:BSP树

这是一个很重要的概念啊。我必须掌握!!

2

主题

7

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2010-11-12 16:06:00 | 显示全部楼层

Re:BSP树

楼主,谢谢分享。很庆幸看到了你的帖子。
我现在在做透明物体的折射和焦散效果的研究,其中折射就需要用到光线跟踪算法,不知道你有没有这方面的资料,最好是KD-Tree构建,求交,遍历的源代码,有的话请发到我的邮箱skyzhouth@126.com   谢谢!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-2-27 23:28

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表