游戏引擎中物体的组织

1.一切都以空间为根本

     对于3D渲染来说,能够剔除的东西都应该剔除,所以我们需要知道当前空间是否可见,如果不可见,对不起,这个空间中的物体就都不应该作为可见物体来看待,因此,物体之所以存在,就是因为有空间这个概念,一个空间就应该代表一个独有的本地坐标系,同时它又在世界中占据一个一定大小的位置,而这个大小,则应该根据这个空间容纳物体物体的多少来定.

 

2.抽象出空间与物体

    我认为,如果认为"世界"是最顶层的,没有任何物体可以包含它,那么可以把空间抽象为:

    class Spatial{

        (1)以世界坐标为准的仿射变换 TransWORLD

        (2)以本地坐标为准的仿射变换 TransLOCAL

        (3)用来表示自身占据的包围体 BoundingVolume

        (4)包含自己的空间引用          Spatial*

    }

    以上的类就是对空间的抽象,它在"世界"中占据一个位置,而具体方位以本地变换为基础来求出,具体大小由包围体指定,并且它知道自己属于哪个空间

 

3.层次组织

    以一个车子为例子,车中的人实际上可以以车作为自己的上层空间,因为人的移动可以通过车在世界中的位置来求出如下:

    W车 = L车

    W人 = W车 * L人

    而最终求出的W人就是人的最终在世界中的位置,用这个变换可以把人正确的在世界中定位.

    为了体现这种层次性,我们需要将空间区分为两种类型,一种是纯粹的空间抽象,它只是提供一个坐标系,来包含子物体,并将它们组织在自己的子空间中,我称它为Node,我们可以认为"世界"就是一个最高层的Node,因为所有的其他空间都是它的子孙.

还有一种类型是物体,它表现为可渲染,可表现的实体,不能作为其他物体的父亲,我称它为Geometry,也就是我们常说的网格.

    具体类如下:

    class Node : public Spatial{

 

        //包含的空间 list of Spatial

 

    }

    class Geomety : public Spatial{

 

        //网格数据 data for Render

 

    }

    我们可以发现,所有的物体,可以通过以世界Node为根节点的树型结构来组织起来.

 

4.更新操作

    更新分成两个部分,一个是如果移动,一个是添加,移动对层次的影响是需要重新计算世界的位置,而添加的影响是需要重新计算空间的包围体.

   通过分析可以简单的发现,事实上世界位置的影响是自顶向下传播的,因此如果你移动了某个节点,只需要将该节点下所有子节点的世界位置递归的传递下去就可以了:

   W子 = W父 * L子

   而对于添加的操作,如果你在某一节点下添加了一个新物体,你需要做的是向上重新计算父空间的包围体大小,一直到树根,计算包围体大小的方法是将空间中所有子物体的包围体合并成一个最终的包围体.

   从上可以看出,通过树型组织的物体场景图确实有着不小的威力

   另外,在进行剔除操作时,如果一个空间是不可见的,那么该空间的子集都可以被减枝从而可以不再测试可见性了,这也是其他组织方法所不能提供的便利.

 

5.最后还想提醒一下,Node应该看作一个空间的进一步抽象,而不能认为它也是一个物体,它与高层抽象Spatial一样都是一个有大小的坐标系,只不过Node可以包含更多的Node,而在Spatial的抽象层次没有这一功能

   

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值