Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

424 lines
20 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. //
  3. // Class & functions to parse and represent a VMF file.
  4. //
  5. //===============================================================================
  6. #ifndef SIMPLEMAPFILE_H
  7. #define SIMPLEMAPFILE_H
  8. #if defined( COMPILER_MSVC )
  9. #pragma once
  10. #endif
  11. #include "chunkfile.h"
  12. #include "stringpool.h"
  13. #include "vbspmathutil.h"
  14. class CSimpleMapFile;
  15. class GameData;
  16. DECLARE_LOGGING_CHANNEL( LOG_VBSP2 );
  17. //-----------------------------------------------------------------------------
  18. // Flags that modify a brush volume or brush side surface
  19. //-----------------------------------------------------------------------------
  20. typedef int MapBrushContentsFlags_t;
  21. //-----------------------------------------------------------------------------
  22. // Flags that modify a brush side surface
  23. //-----------------------------------------------------------------------------
  24. typedef short MapBrushSideSurfaceFlags_t;
  25. //-----------------------------------------------------------------------------
  26. // A single entity from a VMF file.
  27. //-----------------------------------------------------------------------------
  28. struct MapEntity_t
  29. {
  30. // World-space location of the object.
  31. Vector m_vOrigin;
  32. // Index & count of brushes contained within this entity. These are stored in the map's brush array.
  33. // Brushes in an entity have contiguous indices in the range: [m_nFirstBrushIndex, m_nFirstBrushIndex + m_nNumBrushes).
  34. int m_nFirstBrushIndex;
  35. int m_nNumBrushes;
  36. // Index & count of key-value pairs (entity properties) contained within this entity. These are stored in the map's key-value pair array.
  37. // Key-value pairs in an entity have contiguous indices in the range: [m_nFirstKVPairIndex, m_nFirstKVPairIndex + m_nNumKVPairs).
  38. int m_nFirstKVPairIndex;
  39. int m_nNumKVPairs;
  40. };
  41. //-----------------------------------------------------------------------------
  42. // A property of an entity from a VMF file.
  43. //-----------------------------------------------------------------------------
  44. struct MapEntityKeyValuePair_t
  45. {
  46. // These point into the string pool owned by the map object, so no memory management is necessary.
  47. const char *m_pKey;
  48. const char *m_pValue;
  49. // True if this key value pair came from the "connections" section of an entity,
  50. // false if it came from an ordinary entity key.
  51. bool m_bIsConnection;
  52. };
  53. //-----------------------------------------------------------------------------
  54. // A CSG brush (convex solid) from a VMF file.
  55. //-----------------------------------------------------------------------------
  56. struct MapBrush_t
  57. {
  58. // Contents of the brush, based on the properties of its sides.
  59. MapBrushContentsFlags_t m_ContentsFlags;
  60. // Index & count of brush sides. These are stored in the map's brush sides array.
  61. // Brush sides have contiguous indices in the range: [m_nFirstSideIndex, m_nFirstSideIndex + m_nNumSides).
  62. int m_nFirstSideIndex;
  63. int m_nNumSides;
  64. // AABB of the brush
  65. Vector m_vMinBounds, m_vMaxBounds;
  66. };
  67. static const int INVALID_DISPLACEMENT_INDEX = -1;
  68. //-----------------------------------------------------------------------------
  69. // A single side of a CSG brush from a VMF file.
  70. //-----------------------------------------------------------------------------
  71. struct MapBrushSide_t
  72. {
  73. // Contents of the brush side, based on the material properties.
  74. MapBrushContentsFlags_t m_ContentsFlags;
  75. // Surface flags of the brush side, based on the material properties.
  76. MapBrushSideSurfaceFlags_t m_SurfaceFlags;
  77. // The index of the plane coincident with this brush side. The index is in the map's plane hash.
  78. int m_nPlaneIndex;
  79. // The index of the texture info struct for this brush side, describing the material applied to this side.
  80. // The index is into the map's texture info array.
  81. int m_nTextureInfoIndex;
  82. // The polygonal face of this brush side.
  83. Polygon_t m_Polygon;
  84. // The index of the displacement associated with this side, or INVALID_DISPLACEMENT_INDEX if
  85. // this side is not a displacement surface.
  86. int m_nDisplacementIndex;
  87. };
  88. //-----------------------------------------------------------------------------
  89. // A displacement surface, specified on a particular CSG brush side.
  90. //-----------------------------------------------------------------------------
  91. class CMapDisplacement
  92. {
  93. public:
  94. CMapDisplacement();
  95. bool AreVerticesAllocated() const { return m_Vertices.Count() > 0 && m_nPower > 0; }
  96. // NOTE: If new fields are added to this class, you must update MoveFrom()!
  97. // Power-of-2 number of subdivisions.
  98. // MIN_MAP_DISP_POWER <= m_nPower <= MAX_MAP_DISP_POWER
  99. int m_nPower;
  100. // Map brush side corresponding to this displacement surface. The brush side is "orphaned"
  101. // in that no brushes will point to it (since the original brush is removed from the world).
  102. int m_nOriginalBrushSide;
  103. // SURF_* flags, defined in builddisp.h
  104. int m_nFlags;
  105. // Contents flags taken from the original brush.
  106. // The value is stored here, since the original brush gets removed from the world.
  107. MapBrushContentsFlags_t m_ContentsFlags;
  108. Vector m_vStartPosition;
  109. struct Vertex_t
  110. {
  111. float m_flAlpha;
  112. float m_flDistance;
  113. Vector m_vNormal;
  114. Vector m_vOffset;
  115. Vector4D m_vMultiBlend;
  116. Vector m_vMultiBlendColors[MAX_MULTIBLEND_CHANNELS];
  117. };
  118. CUtlVector< Vertex_t > m_Vertices;
  119. // DISPTRI_* flags, defined in bspfile.h (one per triangle).
  120. CUtlVector< unsigned short > m_TriangleTags;
  121. // Copies values and takes ownership of owned data from the other displacement object
  122. // (this is a destructive, but efficient, operation used to migrate a displacement
  123. // from one map object to another).
  124. // NOTE: If you add new fields to CMapDisplacement, you must update this function!
  125. void MoveFrom( CMapDisplacement *pOther );
  126. private:
  127. // Disallow value semantics
  128. CMapDisplacement( const CMapDisplacement &other );
  129. CMapDisplacement &operator=( const CMapDisplacement &other );
  130. };
  131. static const int MAX_TEXTURE_NAME_LENGTH = 128;
  132. //-----------------------------------------------------------------------------
  133. // Texture properties for a brush side, as loaded from a VMF file.
  134. //-----------------------------------------------------------------------------
  135. struct MapBrushTexture_t
  136. {
  137. Vector m_vUAxis, m_vVAxis;
  138. float m_flShift[2];
  139. float m_flTextureWorldUnitsPerTexel[2];
  140. float m_flLightmapWorldUnitsPerLuxel;
  141. char m_MaterialName[MAX_TEXTURE_NAME_LENGTH];
  142. MapBrushSideSurfaceFlags_t m_SurfaceFlags;
  143. };
  144. //-----------------------------------------------------------------------------
  145. // Sentinel texture info index for a side of a solid BSP node.
  146. //-----------------------------------------------------------------------------
  147. static const int NODE_TEXTURE_INFO_INDEX = -1;
  148. //-----------------------------------------------------------------------------
  149. // Planar mapping of texture data to a particular surface.
  150. //-----------------------------------------------------------------------------
  151. struct MapTextureInfo_t
  152. {
  153. // The U and V vectors (w-component contains the offset) that define
  154. // a homogeneous planar mapping from 3D (world) space to 2D (texture) space.
  155. float m_flTextureVectors[2][4];
  156. float m_flLightmapVectors[2][4];
  157. // Index into the map's texture data array of the structure which describes
  158. // the material being mapped to this surface.
  159. int m_nTextureDataIndex;
  160. MapBrushSideSurfaceFlags_t m_SurfaceFlags;
  161. };
  162. //-----------------------------------------------------------------------------
  163. // Basic material information for a surface.
  164. //-----------------------------------------------------------------------------
  165. struct MapTextureData_t
  166. {
  167. Vector m_vReflectivity;
  168. // Width and height of the base texture referenced by the material
  169. int m_nWidth, m_nHeight;
  170. // Name of the material (e.g. DEV/GRAYGRID) being mapped
  171. char m_MaterialName[MAX_TEXTURE_NAME_LENGTH];
  172. };
  173. //-----------------------------------------------------------------------------
  174. // Finds a key-value pair with the specified key in a given array of
  175. // key-value pairs, or NULL if none is found
  176. //-----------------------------------------------------------------------------
  177. const MapEntityKeyValuePair_t *FindPair( const char *pKeyName, const MapEntityKeyValuePair_t *pPairs, int nNumPairs );
  178. MapEntityKeyValuePair_t *FindPair( const char *pKeyName, MapEntityKeyValuePair_t *pPairs, int nNumPairs );
  179. //-----------------------------------------------------------------------------
  180. // Gets the value associated with the given pair or "" if the pair
  181. // or value string is NULL (safe to chain with FindPair)
  182. //-----------------------------------------------------------------------------
  183. const char *GetPairValue( const MapEntityKeyValuePair_t *pPair );
  184. //-----------------------------------------------------------------------------
  185. // A class which represents a VMF (map) file in memory
  186. // or value string is NULL (safe to chain with FindPair)
  187. //-----------------------------------------------------------------------------
  188. class CSimpleMapFile
  189. {
  190. public:
  191. //-----------------------------------------------------------------------------
  192. // Gets the minimum and maximum bound of all world brushes in this map file
  193. //-----------------------------------------------------------------------------
  194. Vector GetMinBounds() const { return m_vMinBounds; }
  195. Vector GetMaxBounds() const { return m_vMaxBounds; }
  196. int GetMapRevision() const { return m_nMapRevision; }
  197. const MapEntity_t *GetEntities() const { return &m_Entities[0]; }
  198. MapEntity_t *GetEntities() { return &m_Entities[0]; }
  199. int GetEntityCount() const { return m_Entities.Count(); }
  200. //-----------------------------------------------------------------------------
  201. // Gets the world entity, which is the 0th entity in the file
  202. //-----------------------------------------------------------------------------
  203. const MapEntity_t *GetWorldEntity() const { return GetEntities(); }
  204. MapEntity_t *GetWorldEntity() { return GetEntities(); }
  205. const MapBrush_t *GetBrushes() const { return &m_Brushes[0]; }
  206. MapBrush_t *GetBrushes() { return &m_Brushes[0]; }
  207. int GetBrushCount() const { return m_Brushes.Count(); }
  208. const MapBrushSide_t *GetBrushSides() const { return &m_BrushSides[0]; }
  209. MapBrushSide_t *GetBrushSides() { return &m_BrushSides[0]; }
  210. int GetBrushSideCount() const { return m_BrushSides.Count(); }
  211. const CMapDisplacement *GetDisplacements() const { return &m_Displacements[0]; }
  212. CMapDisplacement *GetDisplacements() { return &m_Displacements[0]; }
  213. int GetDisplacementCount() const { return m_Displacements.Count(); }
  214. const MapTextureInfo_t *GetTextureInfos() const { return &m_TextureInfos[0]; }
  215. MapTextureInfo_t *GetTextureInfos() { return &m_TextureInfos[0]; }
  216. int GetTextureInfoCount() const { return m_TextureInfos.Count(); }
  217. const MapTextureData_t *GetTextureData() const { return &m_TextureData[0]; }
  218. MapTextureData_t *GetTextureData() { return &m_TextureData[0]; }
  219. int GetTextureDataCount() const { return m_TextureData.Count(); }
  220. const MapEntityKeyValuePair_t *GetKeyValuePairs() const { return &m_KeyValuePairs[0]; }
  221. MapEntityKeyValuePair_t *GetKeyValuePairs() { return &m_KeyValuePairs[0]; }
  222. int GetKeyValuePairCount() const { return m_KeyValuePairs.Count(); }
  223. const CPlaneHash *GetPlaneHash() const { return &m_PlaneHash; }
  224. const char *GetFilename() const { return m_pFilename; }
  225. //-----------------------------------------------------------------------------
  226. // Adds a func_instance entity to the map file.
  227. //-----------------------------------------------------------------------------
  228. void AddFuncInstance( const char *pFilename, QAngle angles, Vector vOrigin, MapEntityKeyValuePair_t *pExtraKeyValues = NULL, int nExtraKeyValues = 0 );
  229. int FindEntity( const char *pClassName, const char *pKeyName, const char *pValue, int nStartingIndex = 0 );
  230. void RemoveEntity( int nEntityIndex );
  231. //-----------------------------------------------------------------------------
  232. // Flags passed to ResolveInstances() to control behavior.
  233. //-----------------------------------------------------------------------------
  234. enum ResolveInstanceFlags_t
  235. {
  236. NO_FLAGS = 0x0,
  237. CONVERT_STRUCTURAL_TO_DETAIL = 0x1, // convert all solids in world entities to func_detail
  238. };
  239. //-----------------------------------------------------------------------------
  240. // Callback invoked after loading each instance.
  241. // The callback is given the originally provided context value, the loaded
  242. // instance map, and the key-value pairs from the parent map's
  243. // func_instance entity chunk.
  244. //-----------------------------------------------------------------------------
  245. typedef void ( *PostLoadInstanceHandler_t )( void *pContext, CSimpleMapFile *pInstanceMapFile, MapEntityKeyValuePair_t *pFuncInstanceKeyValuePairs, int nNumKeyValuePairs );
  246. //-----------------------------------------------------------------------------
  247. // Recursively loads all contained func_instance entities and merges
  248. // them with the current map in breadth-first recursive order.
  249. //-----------------------------------------------------------------------------
  250. bool ResolveInstances( ResolveInstanceFlags_t instanceFlags = NO_FLAGS, PostLoadInstanceHandler_t pPostLoadInstanceHandler = NULL, void *pHandlerContext = NULL );
  251. //-----------------------------------------------------------------------------
  252. // Loads a VMF (map) file from disk and constructs a new CSimpleMapFile object.
  253. // The caller must delete the object when done.
  254. //-----------------------------------------------------------------------------
  255. static void LoadFromFile( IFileSystem *pFileSystem, const char *pVMFFilename, CSimpleMapFile **ppNewMapFile, ResolveInstanceFlags_t instanceFlags = NO_FLAGS );
  256. private:
  257. CSimpleMapFile( IFileSystem *pFileSystem, const char *pVMFFilename );
  258. MapEntity_t *AllocateNewEntity();
  259. MapBrush_t *AllocateNewBrush();
  260. MapBrushSide_t *AllocateNewBrushSide();
  261. CMapDisplacement *AllocateNewDisplacement();
  262. MapBrushTexture_t *AllocateNewBrushTexture();
  263. MapTextureData_t *AllocateNewTextureData();
  264. MapEntityKeyValuePair_t *AllocateNewKeyValuePair();
  265. // Some entity types are simply ignored
  266. void DeallocateLastEntity() { m_Entities.RemoveMultipleFromTail( 1 ); }
  267. // Some brushes are loaded and then discarded (e.g. brushes with displacement)
  268. void DeallocateLastBrush() { m_Brushes.RemoveMultipleFromTail( 1 ); }
  269. void ReportParseError( const char *pErrorString );
  270. void MakeBrushPolygons( MapBrush_t *pBrush );
  271. void MoveEntityBrushesToWorld( int nEntityIndex );
  272. int GetTextureInfoForBrushTexture( MapBrushTexture_t *pBrushTexture, const Vector &vRelativeOrigin );
  273. int FindOrCreateTextureData( const char *pTextureName );
  274. int FindOrCreateTextureInfo( const MapTextureInfo_t &textureInfo );
  275. MapBrushContentsFlags_t ComputeBrushContents( MapBrush_t *b );
  276. // Functions used to merge instance data (recursively) with the primary map
  277. void MergeInstance( int nEntityIndex, CSimpleMapFile *pInstanceMap, GameData *pGameData );
  278. void PreLoadInstances( GameData *pGD );
  279. void MergeBrushes( int nEntityIndex, const CSimpleMapFile *pInstanceMap, const Vector &vOrigin, const QAngle &orientation, const matrix3x4_t &transform );
  280. void MergeBrushSides( int nEntityIndex, CSimpleMapFile *pInstanceMap, const Vector &vOrigin, const QAngle &orientation, const matrix3x4_t &transform );
  281. void MergeEntities( int nEntityIndex, const CSimpleMapFile *pInstanceMap, const Vector &vOrigin, const QAngle &orientation, const matrix3x4_t &transform, GameData *pGameData );
  282. void FixupInstanceKeyValuePair( MapEntityKeyValuePair_t *pNewKeyValuePair, const char *pOriginalValue, const MapEntityKeyValuePair_t *pInstancePairs, int nNumPairs );
  283. // The following static functions are passed as callbacks to the chunk file reader
  284. // when certain chunks and key blocks are encountered in the VMF file.
  285. static ChunkFileResult_t EntityChunkHandler( CChunkFile *pFile, void *pData );
  286. static ChunkFileResult_t SolidChunkHandler( CChunkFile *pFile, void *pData );
  287. static ChunkFileResult_t SideChunkHandler( CChunkFile *pFile, void *pData );
  288. static ChunkFileResult_t DispInfoChunkHandler( CChunkFile *pFile, void *pData );
  289. static ChunkFileResult_t ConnectionsChunkHandler( CChunkFile *pFile, void *pData );
  290. static ChunkFileResult_t EntityKeyHandler( const char *pKey, const char *pValue, void *pData );
  291. static ChunkFileResult_t SolidKeyHandler( const char *pKey, const char *pValue, void *pData );
  292. static ChunkFileResult_t SideKeyHandler( const char *pKey, const char *pValue, void *pData );
  293. static ChunkFileResult_t DisplacementKeyHandler( const char *pKey, const char *pValue, void *pData );
  294. // These are shim functions which simply call into their corresponding displacement key handlers
  295. static ChunkFileResult_t DisplacementNormalsChunkHandler( CChunkFile *pFile, void *pData );
  296. static ChunkFileResult_t DisplacementDistancesChunkHandler( CChunkFile *pFile, void *pData );
  297. static ChunkFileResult_t DisplacementOffsetsChunkHandler( CChunkFile *pFile, void *pData );
  298. static ChunkFileResult_t DisplacementAlphasChunkHandler( CChunkFile *pFile, void *pData );
  299. static ChunkFileResult_t DisplacementTriangleTagsChunkHandler( CChunkFile *pFile, void *pData );
  300. static ChunkFileResult_t DisplacementMultiBlendChunkHandler( CChunkFile *pFile, void *pData );
  301. static ChunkFileResult_t DisplacementMultiBlendColor0( CChunkFile *pFile, void *pData );
  302. static ChunkFileResult_t DisplacementMultiBlendColor1( CChunkFile *pFile, void *pData );
  303. static ChunkFileResult_t DisplacementMultiBlendColor2( CChunkFile *pFile, void *pData );
  304. static ChunkFileResult_t DisplacementMultiBlendColor3( CChunkFile *pFile, void *pData );
  305. // These read the actual key data associated with each displacement attribute
  306. static ChunkFileResult_t DisplacementNormalsKeyHandler( const char *pKey, const char *pValue, void *pData );
  307. static ChunkFileResult_t DisplacementDistancesKeyHandler( const char *pKey, const char *pValue, void *pData );
  308. static ChunkFileResult_t DisplacementOffsetsKeyHandler( const char *pKey, const char *pValue, void *pData );
  309. static ChunkFileResult_t DisplacementAlphasKeyHandler( const char *pKey, const char *pValue, void *pData );
  310. static ChunkFileResult_t DisplacementTriangleTagsKeyHandler( const char *pKey, const char *pValue, void *pData );
  311. static ChunkFileResult_t DisplacementMultiBlendKeyHandler( const char *pKey, const char *pValue, void *pData );
  312. static ChunkFileResult_t DisplacementMultiBlendColorKeyHandler( const char *pKey, const char *pValue, void *pData );
  313. static ChunkFileResult_t ConnectionsKeyHandler( const char *pKey, const char *pValue, void *pData );
  314. struct MaterialInfo_t
  315. {
  316. char m_Name[MAX_TEXTURE_NAME_LENGTH];
  317. MapBrushContentsFlags_t m_ContentsFlags;
  318. MapBrushSideSurfaceFlags_t m_SurfaceFlags;
  319. };
  320. MaterialInfo_t* FindMaterialInfo( const char *pName );
  321. IFileSystem *m_pFileSystem;
  322. // This is needed so instances can be resolved. If we're loading map files from memory buffers
  323. // or other non-file sources, we'll need an "include interface" (like D3DX/HLSL's include resolution system).
  324. const char *m_pFilename;
  325. CPlaneHash m_PlaneHash;
  326. CUtlVector< MapEntity_t > m_Entities;
  327. CUtlVector< MapBrush_t > m_Brushes;
  328. CUtlVector< CMapDisplacement > m_Displacements;
  329. // These two arrays (m_BrushSides & m_BrushTextures) should always be the same size as there is a 1:1 correspondence.
  330. CUtlVector< MapBrushSide_t > m_BrushSides;
  331. CUtlVector< MapBrushTexture_t > m_BrushTextures;
  332. CUtlVector< MapTextureInfo_t > m_TextureInfos;
  333. CUtlVector< MapTextureData_t > m_TextureData;
  334. // Number of instances loaded (recursively).
  335. // This value is only used on the root-level map. It is used to generate unique names for instanced entities.
  336. int m_nInstanceCount;
  337. // This value is only used on instance maps to control loading and processing.
  338. ResolveInstanceFlags_t m_InstanceFlags;
  339. // Used to store entity property data
  340. CUtlVector< MapEntityKeyValuePair_t > m_KeyValuePairs;
  341. CStringPool m_KeyValueStringPool;
  342. Vector m_vMinBounds, m_vMaxBounds;
  343. int m_nMapRevision;
  344. int m_nHighestID;
  345. // Used to cache results of FindMaterialInfo, which gets information about materials applied to brush sides.
  346. CUtlVector< MaterialInfo_t > m_MaterialInfos;
  347. };
  348. #endif // SIMPLEMAPFILE_H