/* =========================================================================== Copyright (C) 2008 Daniel Örstadius Copyright (C) 2009 Jared Prince This file is part of bsp-renderer source code. bsp-renderer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. bsp-renderer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with bsp-renderer. If not, see . */ // Q3Map.h -- handles the map data #ifndef _Q3MAP_H #define _Q3MAP_H #define WIN32_LEAN_AND_MEAN #include "windows.h" #include "Q3Map_Bezier.h" #include #include #include "Q3Map_misc.h" //#include "JarDebug.h" //!! just for debugging, remove from final build #define MEMADD 65536 // memory is grown in 66k blocks #define MAX_TOKENSIZE 1024 // make sure tokens in texts aren't ridiculously large #define MINMAXLIMIT 10000000.0 #define BRIGHTNESSTWEAK 0.5f //1.25f // tweak for spotlight brightness #define ADDTEXTUREUNIQUE_FAIL -1 #define ADDTEXLAMP_FAIL -2 #define ADDSPOTLIGHTTEXTURE_FAIL -1 //////////////////////////////////////////////////// #define AXIS_X 0 #define AXIS_Y 1 #define AXIS_Z 2 //////////////////////////////////////////////////// /* #define FACESORT_FACE_LIMIT 16777216 #define FACESORT_FACE_SHIFT 0 #define FACESORT_FACE_MASK 0x0000000000FFFFFF #define FACESORT_TEXTURE_LIMIT 4096 #define FACESORT_TEXTURE_SHIFT 24 #define FACESORT_TEXTURE_MASK 0x0000000FFF000000 #define FACESORT_SUBZONE_LIMIT 4096 // also see MAX_ZONE #define FACESORT_SUBZONE_SHIFT 36 #define FACESORT_SUBZONE_MASK 0x0000FFF000000000 */ #define FACESORT_FACE_LIMIT 16777216 #define FACESORT_FACE_SHIFT 0 #define FACESORT_FACE_MASK 0x0000000000FFFFFF #define FACESORT_GROUP_LIMIT 65536 // also see MAX_TRANS #define FACESORT_GROUP_SHIFT 24 #define FACESORT_GROUP_MASK 0x000000FFFF000000 #define FACESORT_TEXTURE_LIMIT 4096 #define FACESORT_TEXTURE_SHIFT 40 #define FACESORT_TEXTURE_MASK 0x000FFF0000000000 #define FACESORT_SUBZONE_LIMIT 4096 // also see MAX_ZONE #define FACESORT_SUBZONE_SHIFT 52 #define FACESORT_SUBZONE_MASK 0xFFF0000000000000 #define GROUPSORT_FACE_LIMIT 16777216 #define GROUPSORT_FACE_SHIFT 0 #define GROUPSORT_FACE_MASK 0x0000000000FFFFFF #define GROUPSORT_GROUP_LIMIT 16777216 #define GROUPSORT_GROUP_SHIFT 24 #define GROUPSORT_GROUP_MASK 0x0000FFFFFF000000 #define GROUPSORT_SUBZONE_LIMIT 4096 // also see MAX_ZONE #define GROUPSORT_SUBZONE_SHIFT 52 #define GROUPSORT_SUBZONE_MASK 0xFFF0000000000000 //////////////////////////////////////////////////// #define MAX_ZONE 4096 // max subzones and max zones. Also see FACESORT_SUBZONE_LIMIT #define MAX_SUBZONEPERZONE 16 // the most subzones that can make up a zone, further subzones ignored. INDEX_SUBZONECOUNT must be same as this #define INDEX_SUBZONECOUNT 16 // helps subzone counting in m_nZone. See MAX_SUBZONEPERZONE #define MAX_PORTAL 32768 // max subzoneportals in a map. #define MAX_PORTALPERZONE 64 // the most portals that a zone can have, further portals ignored. INDEX_PORTALCOUNT must be same as this #define MAX_ZONEPERPORTAL 8 // the most zones a portal can connect, further zones ignored. INDEX_PORTALZONECOUNT must be the same as this #define MAX_LIGHTPERPORTAL 16 // the most lights that can touch a portal, further lights ignored. INDEX_PORTALLIGHTCOUNT must be the same as this #define INDEX_PORTALCOUNT 64 // helps portal counting in m_nZoneTouchesPortal. See MAX_PORTALSPERZONE #define INDEX_PORTALZONECOUNT 8 // helps portalconnect counting in m_nPortalTouchesZone. See MAX_ZONEPERPORTAL #define INDEX_PORTALLIGHTCOUNT 16 // helps portallight counting in m_PortalConnectsLight. See MAX_LIGHTPERPORTAL #define MAX_ZONEPERZONE 64 // the most zones that a zone can connect to. #define INDEX_ZONEPERZONECOUNT 64 // helps zone per zone counting. #define MAX_LIGHT 32768 // max lights in a map, both from the map and other things (flashlight, missiles, etc) #define MAX_LIGHTPERZONE 64 // the most lights that a zone can have, further lights ignored. INDEX_LIGHTCOUNT must be same as this #define MAX_ZONEPERLIGHT 8 // the most zones a light can touch, further zones ignored. INDEX_LIGHTZONECOUNT must be the same as this #define INDEX_LIGHTCOUNT 64 // helps light counting in m_nZoneContainsLight. see MAX_LIGHTPERZONE #define INDEX_LIGHTZONECOUNT 8 // helps light counting in m_nLightContainedByZone. See MAX_ZONEPERLIGHT #define MAX_SUBLIGHT 262144 // must be MAX_LIGHT * MAX_ZONEPERLIGHT #define MAX_TRANS 65536 // most transparent objects per zone (objects may be defined in various ways). see FACESORT_TRANS_LIMIT //////////////////////////////////////////////////// #define SUBZONE_EPSILON 0.01f // small buffer of extra size around subzones so that we don't accidentally exclude a point due to float accuracy errors. #define FRUSTUM_EPSILON 0.0001f // once frustum is this tiny consider it dead #define VERYSMALL 0.00001 // small number #define PORTAL_UNCHECKED 0 #define PORTAL_VISCHECK 1 #define PORTAL_VISIBLE 2 #define PORTALSTATE_OPENCHECK 0 #define PORTALSTATE_CLOSED 1 #define PORTALSTATE_OPEN 2 #define ZONE_UNCHECKED 0 #define ZONE_VISIBLE 1 #define LIGHT_UNCHECKED 0 #define LIGHT_OUTOFFRUSTUM 1 #define LIGHT_INSIDEFRUSTUM 2 #define LIGHT_NOTVISIBLE 4 #define LIGHT_VISIBLE 8 #define LIGHT_CHECKED 16 /////////////////////////////////////////////////// #define MAX_PROJECTORTEX 16 // most types of projector textures we can have per map. /////////////////////////////////////////////////// // NOERROR is already defined in a windows file, it is 0 #define ERROR_ParseMap 1 #define ERROR_ParseEntities 2 #define ERROR_AllocateVertex 3 #define ERROR_AllocateTriangle 4 #define ERROR_InitializeFaces 5 #define ERROR_ConvertFaces 6 #define ERROR_ConvertPatches 7 #define ERROR_ConvertLamps 8 #define ERROR_ConvertLampGlow 9 #define ERROR_ConvertLightGlow 10 #define ERROR_AssignTriangles 11 #define ERROR_SortTriangles 12 #define ERROR_ConvertTexLamp 13 #define ERROR_SetupTransTextures 14 #define ERROR_SortGroups 15 /////////////////////////////////////////////////// // error values for parsing key/values #define KEY_OK 0 #define KEY_NONE 1 #define KEY_ERROR 2 ////////////////////////////////////////////////// // entity types #define ENTITY_ERROR 0 #define ENTITY_UNKNOWN 1 #define ENTITY_WORLDSPAWN 2 #define ENTITY_LIGHT 3 /////////////////////////////////////////////////// // The lump idexes that make up a bsp file. // Bzn bsp lump data is almost identical to q3a bsp lump data, except that the // Effects, Lightmaps and VisData lumps are removed and there are two new lumps, one // describing the subzones and one describing the portals. The other difference is the lighting // entities (which are stored as normal entities in lump 0) since q3a bsps don't usually // store the light entities at all, and BZN has it's own unique set of lighting keys. const int Textures = 1; const int Planes = 2; const int Nodes = 3; const int Leafs = 4; const int LeafFaces = 5; const int LeafBrushes = 6; const int Brushes = 8; const int BrushSides = 9; const int Vertices = 10; const int MeshVerts = 11; const int Effects = 12; // removed from bzn const int Faces = 13; const int LightMaps = 14; // removed from bzn const int VisData = 16; // removed from bzn const int SubZoneData = 17 ; // added to bzn: overlapping subzones form zones. Zones are like groups of axial boxes. const int PortalData = 18 ; // added to bzn: portals overlapping different zones allow them to see each other. const int MAX_LUMP = 19 ; const int MAX_LUMP_SIZE = 100000000 ; // this value is very large and arbitrary, 100 megabytes. Just make sure MAX_LUMP_SIZE * MAX_LUMP is less than the max size for a size_t or parseMap error checking won't work. enum {POLYGON = 1, PATCH, MESH, BILLBOARD}; typedef struct{ int iOffset; int iLength; } direntry_t; #define Q3NAMESIZE 64 typedef struct { char name[Q3NAMESIZE]; int flags; int contents; } Q3BspTexture; typedef struct{ unsigned char magic[4]; int version; direntry_t Lumps[MAX_LUMP]; } Q3BspHeader_t; typedef struct{ int texture; int effect; int type; int vertex; int n_vertexes; int meshvert; int n_meshverts; int lm_index; int lm_start[2]; int lm_size[2]; float lm_origin[3]; float lm_vecs[2][3]; float normal[3]; int size[2]; } Q3BspFace_t; typedef struct{ float position[3]; float texcoord[2][2]; float normal[3]; unsigned char color[4]; } Q3BspVertex; typedef struct { int cluster; int area; int mins[3]; int maxs[3]; int leafface; int n_leaffaces; int leafbrush; int n_leafbrushes; } Q3BspLeaf; typedef struct { float normal[3]; float dist; } Q3BspPlane; typedef struct { int plane; int children[2]; int mins[3]; int maxs[3]; } Q3BspNode; typedef struct { int brushside; int n_brushsides; int texture; } Q3BspBrush; typedef struct { int plane; int texture; } Q3BspBrushSide; typedef struct { unsigned char lightmap[128][128][3]; } Q3BspLightMap; typedef struct { int n_vecs; int sz_vecs; unsigned char *vecs; } Q3BspVisData; typedef struct { int size; Bezier *bezier; } Q3BspPatch; // this struct must be the same as in BZNq3map2 typedef struct { int Zone ; float Min[3] ; float Max[3] ; } BZN_SubZone_t; // this struct must be the same as in BZNq3map2 typedef struct { float Min[3] ; float Max[3] ; } BZN_Portal_t; typedef struct{ int texture; int type; int vertex; int n_vertexes; int meshvert; int n_meshverts; int n_triangles; int lm_index; float normal[3]; int zone ; // added by Jared Q3BspPatch *patch; } Q3BspFaceRenderer; ////////////////////////////////////// typedef struct { int Zone ; // this gets set to -1 for triangles in no zone, and they don't get added to the manualobjects int Texture ; //int Lightmap ; // bzn doesn't use lightmaps int VIndex[3] ; int Lamp ; // which lamp this triangle came from, -1 for most triangles. int Group ; // triangles from the same face are the same group, triangles from the same patch are the same group. Most stuff is group 0 unless it needs special attention, such as transparent stuff } triangle_t; typedef struct { unsigned int Flags ; float Position[3] ; float Direction[3] ; float Colour[3] ; float Min[3] ; float Max[3] ; float Cutoff ; float Angle ; float Brightness ; int Texture ; // texture index of light unsigned int ZoneCount ; // how many zones this light touches unsigned int CentreZone ; // which zone contains the centre of this light. even if on a boundary, the light will only choose one zone as its centre. short SubLightStart ; // where this light's sublights start in the sublight list. } light_t ; typedef struct { unsigned int Flags ; float Position[3] ; float Colour[3] ; float Min[3] ; float Max[3] ; float Brightness ; int Texture ; // texture index of light int LightNode ; // -1 if not a node, 0 - 3 if a node. LightNodes are used as the data for TexLamps, freeform geometry that gets converted to deferred shading lamp triangles. unsigned short Zone[MAX_ZONEPERLIGHT+1] ; // the zones this lamp touches } lamp_t ; typedef struct { float Min[3] ; float Max[3] ; } minmax_t; // this used for the light culling algo, where each cutup light is treated as a subzone. typedef struct { unsigned short Light ; unsigned short Zone ; float Min[3] ; float Max[3] ; } sublight_t; class Q3Map { public: Q3Map(); ~Q3Map(); int m_nNewCount ; int m_nDebugA ; // CJarDebug Q3Bug ; //!! just for debugging, remove from final build char m_chBug[10240] ; int ParseAndTriangulateMap(const char* pData, size_t Size) ; void FreeParseMem(void) ; int parseMap(const char* pMem, size_t Size); int findVisibleFaces(const QVECTOR *camPos, int *facesToRender); Q3BspFace_t *getFaces(void); Q3BspPatch *handlePatch(int faceIndex); char m_chSpotlightTexture[MAX_PROJECTORTEX][Q3NAMESIZE] ; int m_nMaxSpotlightTexture ; int AddSpolightTexture(char TEXNAME[]) ; private: int findLeaf(const QVECTOR *camPos) const; bool isClusterVisible(int visCluster, int testCluster) const; int *mVisibleFaces; std::vector *patches; public: // map data Q3BspHeader_t m_BspHeader; char *m_pEntities; int m_iNumTexs; Q3BspTexture *m_pTexturesOrig; int m_iNumFaces; Q3BspFace_t *m_pFaces; int m_iNumVertices; Q3BspVertex *m_pVertices; int m_iNumMeshVerts; int *m_pMeshVerts; int m_iNumLeafs; Q3BspLeaf *m_pLeafs; int m_iNumLeafFaces; int *m_pLeafFaces; int m_iNumPlanes; Q3BspPlane *m_pPlanes; int m_iNumNodes; Q3BspNode *m_pNodes; int m_iNumLeafBrushes; int *m_pLeafBrushes; int m_iNumBrushes; Q3BspBrush *m_pBrushes; int m_iNumBrushSides; Q3BspBrushSide *m_pBrushSides; int m_iNumLightMaps; Q3BspLightMap *m_pLightMaps; Q3BspVisData *m_VisData; int m_iNumSubZones ; BZN_SubZone_t *m_pSubZones; int m_iNumPortals ; BZN_Portal_t *m_pPortals; int m_ClusterCount ; void swizzleCoords(void); void swizzleFloat3(float t[3]); void swizzleInt3(int t[3]); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // memory management for the triangles int AllocateTriangleMemory(void) ; void FreeTriangleMemory(void) ; int ExpandTriangleMemory(void) ; int AddTriangle(triangle_t Triangle) ; int m_nTriangleSize ; // starting memory size void* m_pTriangleMem ; // allocate starting memory space triangle_t* m_pTriangle ; // a pointer to the memory cast as a triangle_t int m_nTriangleMax ; int m_nTriangleLimit ; // memory management for the vertices int AllocateVertexMemory(int nVertNum) ; void FreeVertexMemory(void) ; int ExpandVertexMemory(void) ; int AddVertex(Q3BspVertex Vertex) ; int m_nVertexSize ; // starting memory size void* m_pVertexMem ; // allocate starting memory space Q3BspVertex* m_pVertex ; // a pointer to the memory cast as a Q3BspVertex int m_nVertexMax ; int m_nVertexLimit ; // memory management for the lights int AllocateLightMemory(void) ; void FreeLightMemory(void) ; int ExpandLightMemory(void) ; int AddLight(light_t Light) ; int m_nLightSize ; // starting memory size void* m_pLightMem ; // allocate starting memory space light_t* m_pLight ; // a pointer to the memory cast as a light_t int m_nLightMax ; int m_nLightLimit ; // memory management for the lamps (a lamp is a deferred shading non-shadowing point light) int AllocateLampMemory(void) ; void FreeLampMemory(void) ; int ExpandLampMemory(void) ; int AddLamp(lamp_t Lamp) ; int m_nLampSize ; // starting memory size void* m_pLampMem ; // allocate starting memory space lamp_t* m_pLamp ; // a pointer to the memory cast as a lamp_t int m_nLampMax ; int m_nLampLimit ; // memory management for the textures int AllocateTextureMemory(void) ; void FreeTextureMemory(void) ; int ExpandTextureMemory(void) ; int AddTexture(Q3BspTexture Texture) ; int AddTextureUnique(Q3BspTexture Texture) ; // special version of the Add function, will not add if the texture name already exist. returns texture index, or -1 on fail int m_nTextureSize ; // starting memory size void* m_pTextureMem ; // allocate starting memory space Q3BspTexture* m_pTexture ; // a pointer to the memory cast as a Texture_t int m_nTextureMax ; int m_nTextureLimit ; // memory management for the TexLamp Triangles int AllocateTexLampMemory(void) ; void FreeTexLampMemory(void) ; int ExpandTexLampMemory(void) ; int AddTexLamp(int TexLamp) ; int m_nTexLampSize ; // starting memory size void* m_pTexLampMem ; // allocate starting memory space int* m_pTexLamp ; // a pointer to the memory cast as an int int m_nTexLampMax ; int m_nTexLampLimit ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int ParseEntities(void) ; int NextEntity(int* pPos, int nMaxPos) ; int GetEntityType(int nPos, int nMaxPos) ; int GetEntityKeyAndValue(int* pPos, int nMaxPos, char* pKey, char* pValue) ; int GetNumbersFromValue(char* pValue, float *pNumber, int nNumberSize) ; int GetNumbersFromValue(char* pValue, int *pNumber, int nNumberSize) ; int ParseAndAddLight(int* pPos, int nMaxPos) ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Q3BspFaceRenderer *m_BspFaces; int m_NumBspFaces; void DestroyBspFacesMemory(void) ; int initFaces(void) ; // we keep track of common texture indexes to avoid slow calls to AddTextureUnique when we add default light texture indexes int m_nDefaultTextureIndexLamp ; int m_nDefaultTextureIndexLamp2Pass ; int m_nDefaultTextureIndexGlowLamp ; int m_nDefaultTextureIndexGlowLight ; int m_nDefaultTextureIndexSpotlight ; void GetTexLampTextureNumbers() ; int m_nBZN_LightNode0 ; int m_nBZN_LightNode1 ; int m_nBZN_LightNode2 ; int m_nBZN_LightNode3 ; int m_nGroup ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Much easier to keep track of how zones/subzones/portals/lights connect to each other using hardwired arrays // than dynamically allocated memory, even if it does waste a little space and impose some design limits. // It's fast, easy to manage, and the total memory used is reasonably small. // The design limits are generous enough that it's unlikely maps will get anywhere near hitting them. // // Memory Footprints: // // m_nZone: 4096 * (16+1) * sizeof(unsigned short) = 139,264 // m_ZoneBoundary 4096 * sizeof(minmax_t)24 = 98,304 // m_nZoneTouchesPortal 4096 * (64+1) * sizeof(unsigned short) = 532,480 // m_nPortalTouchesZone 32768 * ( 8+1) * sizeof(unsigned short) = 589,824 // // m_nZoneContainsLightCentre 4096 * (64+1) * sizeof(unsigned short) = 532,480 // m_nLightTouchesZone 32768 * ( 8+1) * sizeof(unsigned short) = 589,824 // m_nZoneTouchesSubLight 4096 * (64+1) * sizeof(unsigned short) = 532,480 // // m_nMultiZoneLight 32768 * sizeof(unsigned short) = 65,536 // m_SubLight 32768 * 8 * sizeof(sublight_t)28 = 6,815,744 // m_nZoneTouchesZone 4096 * (64+1) * sizeof(unsigned short) = 532,480 // // TOTAL = 10,428,416 (9.9 meg) unsigned short m_nZone[MAX_ZONE][MAX_SUBZONEPERZONE+1] ; // last index is used as a counter, INDEX_SUBZONECOUNT minmax_t m_ZoneBoundary[MAX_ZONE] ; // min and max of a zone. Since zones might not be square, NEVER use this as the real zone boundary, work it out using the subzones instead. This is just for cutting up lights. unsigned short m_nZoneTouchesPortal[MAX_ZONE][MAX_PORTALPERZONE+1] ; // last index is used as a counter, INDEX_PORTALCOUNT unsigned short m_nPortalTouchesZone[MAX_PORTAL][MAX_ZONEPERPORTAL+1] ; // last index is used as a counter, INDEX_PORTALZONECOUNT // PortalTouchesLight is true if the light AABB touches the portal. unsigned short m_nPortalTouchesLight[MAX_PORTAL][MAX_LIGHTPERPORTAL+1] ; // last index is used as a counter, INDEX_PORTALLIGHTCOUNT unsigned short m_nZoneContainsLightCentre[MAX_ZONE][MAX_LIGHTPERZONE+1] ; // last index is used as a counter, INDEX_LIGHTCOUNT unsigned short m_nLightTouchesZone[MAX_LIGHT][MAX_ZONEPERLIGHT+1] ; // last index is used as a counter, INDEX_LIGHTZONECOUNT unsigned short m_nZoneTouchesSubLight[MAX_ZONE][MAX_LIGHTPERZONE+1] ; // last index is used as a counter, INDEX_LIGHTCOUNT unsigned short m_nZoneTouchesZone[MAX_ZONE][MAX_ZONEPERZONE+1] ; // last index is used as a counter, INDEX_ZONEPERZONECOUNT // list of lights that touche more than one zone. These require more complex visibility checks unsigned short m_nMultiZoneLight[MAX_LIGHT] ; int m_nMaxMultiZoneLight ; sublight_t m_SubLight[MAX_SUBLIGHT] ; int m_nSubLightMax ; // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// int m_nMaxZone ; int ConvertFacesToTriangles(void) ; int ConvertPatchesToTriangles(void) ; int ConvertTexLampsToLampTriangles(void) ; int ConvertLampsToTriangles(void) ; int ConvertLampsToGlowTriangles(void) ; int ConvertLightsToGlowTriangles(void) ; void SetVertex(Q3BspVertex *pVert, float flXPos, float flYPos, float flZPos) ; bool VectorsAreEqual(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ; Q3BspVertex NormalizedCrossProduct(Q3BspVertex VertA, Q3BspVertex VertB, Q3BspVertex VertC) ; float VertexDistance(Q3BspVertex* VertA, Q3BspVertex* VertB) ; void VertexScale(Q3BspVertex* pVert, float flScale) ; Q3BspVertex GetNormalised(Q3BspVertex* pVector) ; Q3BspVertex VectorAdd(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ; Q3BspVertex VectorSubtract(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ; Q3BspVertex VectorMultiply(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ; void SetupZones(void) ; int GetNextSubZone(float *flPoint, int nStart, int nMax) ; bool PointInSubZone(float *flPoint, int nSubZone) ; bool PointInZone(float *flPos, int nZone) ; bool AABBTouchesSubZone(float *flPointMin, float *flPointMax, int nSubZone) ; bool AABBTouchesZone(float *flPosMin, float *flPosMax, int nZone) ; int AssignTrianglesToZones(void) ; int FindTriangleZone(int nTriangle) ; int SetupTriangleZone(int nTriangle) ; int SplitTriangle(int nTriangle, int nAxis, float flCutPos) ; // only does axial cuts. returns false on failure, probably due to lack of memory. void CreateTweenVert(Q3BspVertex* pVertA, Q3BspVertex* pVertB, float flPercent0, Q3BspVertex* pVertAB) ; int SortTrianglesIntoGroups(void) ; static int compareGroups( const void *arg1, const void *arg2 ) ; int SortTrianglesIntoBatches(void) ; static int compareTriangles( const void *arg1, const void *arg2 ) ; int SetupTransTextures(void) ; int* m_pTransTexture ; int AssignPortalsToZones(void) ; int AssignLightsToPortals(void) ; int AssignLightsToZones(void) ; int AssignZonesToZones(void) ; }; #endif /* _Q3MAP_H */