6. Creating the cNodeTree Class(创建cNodeTree类)

 

6. Creating the cNodeTree Class(创建cNodeTree类)

是时候设计下了。你得先创建一些结构用来描绘顶点(vertices)、多边形(polygons)、节点(nodes)、纹理组(texture Groups:

// 这个sVertex结构体是一个常用的顶点结构体,

 // 它只包含3D坐标. 这里他被用于从网格顶点缓冲中返回坐标信息

typedef struct sVertex { float x, y, z; } sVertex;

// 这个多边形结构体包含一个纹理组(通过数量)

// time 是他最后被画的时间(所以在每个框架你不会重绘多次)

// 这三个顶点被用于渲染多边形(待会你将看到)

typedef struct sPolygon {

unsigned long Group; // Texture group(纹理组)

unsigned long Time; // Time last drawn(最后绘出时间)

unsigned short Vertex[3]; // Vertex index #s

sPolygon() { Group = Time = 0; } // 清空数据

} sPolygon;

 

// 节点结构体知道在他的3D空间中多边形的数量

// 一组sPolygonList结构体,

// 节点的3D坐标 (还有大小, 它是中心到边的距离,使得节点是一个完全的立方体),

// 还有一个指向子节点的指针

typedef struct sNode {

unsigned long NumPolygons; // 节点中多边形的数量

sPolygon **PolygonList; // 多边形数据列表

float XPos, YPos, ZPos; // 节点中心坐标

float Size; // 节点大小

sNode *Nodes[8]; // 子节点 4=quad, 8=oct

// 使用构造函数,清理数据

sNode()

{

NumPolygons = 0; // 设置为在节点内没有多边形

PolygonList = NULL; // 清空多边形列表

XPos = YPos = ZPos = Size = 0.0f; // 位置和大小

for(short i=0;i<8;i++) // Quadtrees 只使用前四个

Nodes[i] = NULL; // 清空子节点指针

}

// 析构函数清理子节点和变量

~sNode()

{

delete [] PolygonList; // 删除多边形列表

for(short i=0;i<8;i++)

delete Nodes[i]; // 删除子节点

}

} sNode;

 

// 纹理组结构使用一个CorecVertexBuffer类来保存在一个框架中(frame)

// 需要被渲染的多边形

// 还有在一个纹理组中多边形的数量

// 和在每个框架中要画出的多边形的数量.

typedef struct sGroup {

cVertexBuffer VertexBuffer; // 要画出的顶点数据

char *VertexPtr; // 指向顶点数据的指针

unsigned long NumPolygons; // 在纹理组中多边形的数量

unsigned long NumPolygonsToDraw; // 要画出的多边形的数量

sGroup() { NumPolygons = 0; } // 清空多边形的数量

~sGroup() { VertexBuffer.Free(); } // 释放顶点缓冲

} sGroup;

 

每个结构体保存了网格或NodeTree结构各种不同的信息。sVertex是基础的顶点结构;他直接映射到其他所有顶点结构体。如果你从硬盘装在一个网格,你就能使用sVertex结构体去获得顶点的坐标。

 

sPolygon结构体可以保存场景中每个多边形的信息。它保存了纹理组的数量(纹理数量从0到纹理数量-1),最后一次绘出时间(用来停止重绘),还有三个用来绘出多边形的顶点。

 

没错,你直接使用每个顶点的索引值绘出每个多边形来调查网格对象。存取网格顶点将不得不等待直到在下一单元中我们建立起NodeTree类。现在,将你的注意力放到sNode结构体上。

 

sNode保存在节点3D空间中多边形的数量。每个节点有一个描述节点中心的坐标,还有节点的大小,他告诉我们中心点到一条边的距离(使得每一个节点是一个完全的立方体)。对于节点中的每个多边形,一个用于指向保存各自多变性数据的sPolygon结构体的指针。最后,八个子节点指针组成数结构。注意quadtree模式只使用前四个子节点指针。

 

最后就是cGroup结构体,它包含纹理组。每个纹理组使用一个cVertexBuffer对象去包含场景中使用的多边形的精确数量。当节点被扫描,所有可见得多边形被加入到他们各自的纹理组的顶点缓冲中。一次所有节点的扫描,每个纹理组就被使用组的顶点缓冲绘出函数(render function)绘出。

 

对数据结构介绍了一番,现在继续代码。看一下下面的类,他将一个网格读入,并转换为一个你选择的树结构(quadtree octree:

// 两种树结构类型的枚举

enum TreeTypes { QUADTREE = 0, OCTREE };

class cNodeTreeMesh

{

private:

// .. 在这里插入先前的 sVertex, sPolygon, sNode, and sGroup 结构体

int m_TreeType; // 节点树的类型

// QUADTREE or OCTREE

cGraphics *m_Graphics; // cGraphics 父对象

cFrustum *m_Frustum; // Viewing frustum

unsigned long m_Time; // 当前绘出(render)时间

float m_Size; // 世界立方体的大小

float m_MaxSize; // 节点大小的最大值

sNode *m_ParentNode; // 链接父节点

unsigned long m_NumGroups; // 纹理组数量

sGroup *m_Groups; // 纹理组

unsigned long m_NumPolygons; // 网格中多边形数量

unsigned long m_MaxPolygons; // 节点中多边形的数量最大值

sPolygon *m_PolygonList; // 多边形数据列表

sMesh *m_Mesh; // 父网格

char *m_VertexPtr; // 指向网格顶点

unsigned long m_VertexFVF; // 网格顶点的FVF

unsigned long m_VertexSize; // 网格顶点的大小

// SortNode 对多边形进行分组 into nodes

// 并分裂节点 as needed.

void SortNode(sNode *Node, /

float XPos, float YPos, float ZPos, /

float Size);

// AddNode 在要被绘出的节点列表中增加一个节点.

void AddNode(sNode *Node);

// 如果一个多边形的盒子

//与指定的立方体空间交叉IsPolygonContained 返回 TRUE

BOOL IsPolygonContained(sPolygon *Polygon, /

float XPos, float YPos, float ZPos, /

float Size);

// CountPolygons 返回在3D空间中多边形的数量

unsigned long CountPolygons( /

float XPos, float YPos, float ZPos, /

float Size);

 

public:

cNodeTreeMesh(); // 构造函数

~cNodeTreeMesh(); // 析构函数

// Functions to 从一个cMesh对象中创建或释放一个节点/树网格

// 制定一个空间中多边形的最大数量,她是比指定的size要大(强制顶点分裂).

BOOL Create(cGraphics *Graphics, cMesh *Mesh, /

int TreeType = OCTREE, /

float MaxSize = 256.0f, long MaxPolygons = 32);

BOOL Free();

// 使用当前视图矩阵渲染当前视图,并重载视角距离

// 也可以使用一个先前的定义的Frustum或自己定义一个Frustum

BOOL Render(cFrustum *Frustum = NULL, float ZDistance = 0.0f);

};

 

代码的注释已经很好的揭示了每一个变量和函数的作用。在接下来的章节,我将覆盖每个函数去做更多的处理。首先,看下表,他描述了cNodeTree所有变量

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值