现在的位置: 首页 > 综合 > 正文

自己写游戏引擎(06)-渲染Quake 场景

2013年06月10日 ⁄ 综合 ⁄ 共 4946字 ⁄ 字号 评论关闭
 

游戏引擎中最终要的部分——世界场景,直接影响了引擎的结构。通过学习Quake3Quake4(原理和Doom3几乎相同)的场景渲染方式,我们也来为自己的引擎添加这一模块。

         Quake3Quake4在这一方面有不同之处。可能是由于卡马克感觉到BSP的局限性,在Quake4中,没有直接采用编译好了的BSP文件,而是直接用了.map文件,把BSP树(在Quake4中也许还是这中场景管理树)的创建放在了游戏引擎运行时,这种方法的具体细节还无法得知,在Quake4SDK中也只能找到.map文件的信息,所以,我们的重点放在Quake3的场景管理中。

         这篇文章的目的,是简单的介绍BSPQuake中的实现,以及更重要的,我们怎样实现。这篇文章是我原创的,但是用到了几篇英文的文章,你可以在结尾查看,所以,我将不使用“原创”来标识这篇文章,我想用“整理”,毕竟这是我现在正在做的工作。可惜没有“整理”这个选项,所以,如果我引用了英文的文章,我就用“翻译”,用了中文的文章,我就用“转载”(我并不关心其他的问题,我的文章,主要目的是总结,还有分享)。

        

         先来说明一下Quake中的地图格式,.map文件是用ASCII码记录的,你可以通过文本编辑器查看所有的信息,还有就是.bsp文件,是用bsp编译器对.map编译生成,你可以查看相应的命令行参数,这个里面有很多的讲究。有一点需要注意,在Quake3的游戏资源中,我们看不到.map文件,只有.bsp文件;而Quake4的游戏资源中,只有.map文件。所以,这里的重点在与讲解Quake3中的.bsp文件及其渲染方式,而对于.map文件,注意了,用的是Quake4的格式。

 

先来看一下Quake4中的.map格式,因为这种格式比较直观(简单):

brushside 记录的是一个平面和对应的纹理(包括纹理坐标信息);

brush          由多个brushsdie组成,brushquake中比较“出名”的一个名词,你可以在很多的地图编辑器中看到这个名词;brush不仅可以表示几何信息(可以渲染出来)而且,还是天然的包围体,在游戏引擎中,会大量的应用这一性质。

patch          这是quake中的曲面,也包含了对应的纹理和纹理坐标,在渲染之前,需要采样获得一个多边形列表。

entity          实体,也就是地图中的“东东”,由多个brushpatch组成。

就这么简单几个东西,因为.map的唯一用途就是记载世界的几何信息。

下面是引擎中Q4File.h文件。

 

// file: Q4File.h

#ifndef __INCLUDE_Q4FILE_H__

#define __INCLUDE_Q4FILE_H__

 

#include <PlutoMain/PEPreCompiled.h>

#include <EngineLib/EngineLib.h>

 

using namespace EL;

namespace PE

{

     class _PE_Export Q4MapBrushSide

     {

     public:

                                 Q4MapBrushSide();

         virtual                ~Q4MapBrushSide();

 

         void               SetPlane( const Plane &plane );

         const Plane &      GetPlane( void ) const;

        

         void               SetSkinStr( const std::string &skin );

         const std::string & GetSkinStr( void ) const;

        

         void               SetTexMatrix( const Vector3 mat[2] );

         void               GetTexMatrix( const Vector3 &mat1, const Vector3 &mat2 ) const;

     protected:

         std::string            m_skin;

         Plane                  m_plane;

         Vector3                m_texMat[2];

     };

 

     class _PE_Export Q4MapPrimitive

     {

     public:

         enum { TYPE_NONE = -1, TYPE_BRUSH, TYPE_PATCH };

 

                                 Q4MapPrimitive() { m_type = TYPE_NONE; }

         virtual                ~Q4MapPrimitive() { }

     protected:

         int                    m_type;

     };

 

     class _PE_Export Q4MapBrush : public Q4MapPrimitive

     {

     public:

                                 Q4MapBrush();

         virtual                ~Q4MapBrush();

        

         int                    GetNumSides( void );

         void               AddSide( Q4MapBrushSide *pSide );

         Q4MapBrushSide *   GetSideAt( const int index );

 

     protected:

         std::list<Q4MapBrushSide*>  m_sides;

     };

 

 

     typedef struct _Q4Vertex

     {

         float x, y, z;

         float u, v;

     } Q4Vertex;

 

     class _PE_Export Q4MapPatch : public Q4MapPrimitive

     {

     public:

                                 Q4MapPatch();

         virtual                ~Q4MapPatch();

        

         void               SetSkinStr( const std::string &skin );

         const std::string & GetSkinStr( void ) const;

        

         void               SetControl( const Q4Vertex &v, const int index );

         const Q4Vertex &    GetControlAt( const int index ) const;

     protected:

         Q4Vertex           m_controls[9];

         std::string            m_skin;

     };

 

     class _PE_Export Q4MapEntity

     {

         typedef  std::list<Q4MapPrimitive*>       PrimitiveList;

     public:

                                 Q4MapEntity();

         virtual                ~Q4MapEntity();

 

         size_t                 GetNumPrimitives( void );

         void               AddPrimitive( Q4Primitive *pPrim );

         Q4MapPrimitive *   GetPrimitiveAt( const int index );

 

         void               SetName( const std::string &name );

         const std::string & GetName( void ) const;

 

         void               SetClass( const std::string &name );

         const std::string & GetClass( void ) const;

 

     protected:

         PrimitiveList      m_primitives;

         std::string            m_strName;

         std::string            m_strClass;

     };

 

     class _PE_Export Q4MapFile

     {

         typedef std::list<Q4MapEntity*>      EntityList;

     public:

                                 Q4MapFile();

         virtual                ~Q4MapFile();

        

         bool               ParseFile( const char *fileName );

         bool               WriteFile( const char *fileName );

 

         void               AddEntity( Q4MapEntity *pEntity );

         Q4MapEntity *      GetEntityAt( const int index );

         Q4MapEntity *      GetEntityByName( const std::string &name );

        

         void               DeleteEntity( Q4MapEntity *pEntity );

         void               DeleteEntity( const int index );

         void               DeleteEntity( const std::string &name );

         void               DeleteEntityClass( const std::string &name );

         void               DeleteAllEntities( void );

        

         bool               HasPrimitiveData( void );

 

         bool               ParseEntity( Q4MapEntity *pEntity );

         bool               ParseBrushSide( Q4MapBrushSide *pBrushSide );

         bool               ParseBrush( Q4MapBrush *pBrush );

         bool               ParsePatch( Q4MapPatch *pPatch );        

抱歉!评论已关闭.