initial
This commit is contained in:
74
public/vbsp2lib/lightmaptransfer.h
Normal file
74
public/vbsp2lib/lightmaptransfer.h
Normal file
@@ -0,0 +1,74 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// Classes to aid in transferring lightmap data (luxels) between BSPs.
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef LIGHTMAPTRANSFER_H
|
||||
#define LIGHTMAPTRANSFER_H
|
||||
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/intvector3d.h"
|
||||
#include "bspfile.h"
|
||||
|
||||
class CMemoryBSPFile;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A class which acts as a spatial hash for lightmap values.
|
||||
// Multiple source files can be processed into the hash such that every single
|
||||
// lightmap sample has its own entry in the hash.
|
||||
// This data can then be copied into the lightmap lump of a given BSP file.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CLuxelHash
|
||||
{
|
||||
public:
|
||||
CLuxelHash( int nHashBucketCount );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Adds all of the luxels in the source BSP file to a spatial hash.
|
||||
// vOffset is the world-space translation to add to all coordinates in the
|
||||
// source BSP file.
|
||||
//-----------------------------------------------------------------------------
|
||||
void AddSourceBSPFile( const CMemoryBSPFile *pSourceBSPFile, const Vector &vOffset );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copies lighting from the luxel hash into the target BSP file.
|
||||
// Values which are not found are initialized to black.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CopyLighting( CMemoryBSPFile *pTargetBSPFile ) const;
|
||||
|
||||
private:
|
||||
// nDataLength is the number of ColorRGBExp32 (4 bytes each) per luxel.
|
||||
// This is typically 1 for lightmaps without bump light information, or 4 for those with.
|
||||
void AddLuxel( const Vector &vPosition, const Vector &vNormal, const ColorRGBExp32 *pLuxelData, int nDataLength );
|
||||
bool FindLuxel( const Vector &vPosition, const Vector &vNormal, const ColorRGBExp32 **ppLuxelData, int *pDataLength ) const;
|
||||
|
||||
void CopyFaceLighting( CMemoryBSPFile *pTargetBSPFile, int nFace ) const;
|
||||
void CopyWorldLights( CMemoryBSPFile *pTargetBSPFile ) const;
|
||||
|
||||
// Hashes the position and returns a hash bucket index in the range [ 0, m_HashEntries.Count() )
|
||||
int GetGridEntry( const IntVector3D &vIntegerPosition ) const;
|
||||
|
||||
struct LuxelHashEntry_t
|
||||
{
|
||||
Vector m_vPosition;
|
||||
Vector m_vNormal;
|
||||
int m_nDataStart;
|
||||
int m_nDataLength;
|
||||
int m_nNextEntryIndex;
|
||||
};
|
||||
|
||||
CUtlVector< ColorRGBExp32 > m_LuxelData; // Contiguous luxel data
|
||||
CUtlVector< LuxelHashEntry_t > m_HashEntries; // Pool of hash entry linked list nodes, one per luxel
|
||||
CUtlVector< dworldlight_t > m_WorldLightsLDR;
|
||||
CUtlVector< dworldlight_t > m_WorldLightsHDR;
|
||||
|
||||
CUtlVector< int > m_UniformGrid; // 3D grid of indices into a linked list of LuxelHashEntry_t (-1 means no entry)
|
||||
};
|
||||
|
||||
#endif // LIGHTMAPTRANSFER_H
|
||||
236
public/vbsp2lib/serializesimplebspfile.h
Normal file
236
public/vbsp2lib/serializesimplebspfile.h
Normal file
@@ -0,0 +1,236 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// Class to represent and read/write a BSP file.
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef SERIALIZESIMPLEBSPFILE_H
|
||||
#define SERIALIZESIMPLEBSPFILE_H
|
||||
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "bspfile.h"
|
||||
#include "gamebspfile.h"
|
||||
#include "builddisp.h"
|
||||
#include "vbspmathutil.h"
|
||||
#include "simplemapfile.h"
|
||||
|
||||
class CSimpleBSPFile;
|
||||
class CBSPNode;
|
||||
class CBSPFace;
|
||||
|
||||
class CPhysCollisionEntry;
|
||||
class IPhysicsCollision;
|
||||
class IPhysicsSurfaceProps;
|
||||
|
||||
class CUtlBuffer;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Serializes a BSP file to a provided buffer.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SaveToFile( CUtlBuffer *pOutputBuffer, const CSimpleBSPFile *pBSPFile );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class to build and manipulate a BSP file in its on-disk representation.
|
||||
//
|
||||
// This is a lower-level representation of a BSP than CSimpleBSPFile.
|
||||
//
|
||||
// Can be used in one of several modes:
|
||||
//
|
||||
// 1) Serializing a .bsp file -
|
||||
//
|
||||
// a) Given the expanded, in-memory representation
|
||||
// of a compiled map (CSimpleBSPFile), this class will build
|
||||
// intermediate representations of various structures where needed and
|
||||
// serialize the data to a .bsp file. It can be operated in a "memory
|
||||
// efficient" mode where lumps are written out and freed as soon as
|
||||
// possible.
|
||||
//
|
||||
// b) This class can also serialize a BSP file that was constructed
|
||||
// in memory or previously deserialized.
|
||||
//
|
||||
// 2) Deserializing a .bsp file - the recognized lump types will be loaded
|
||||
// and stored in memory, at which point they can be manipulated
|
||||
// as needed.
|
||||
// WARNING: only recognized lumps will be deserialized; this file
|
||||
// has incomplete support for many lump types.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CMemoryBSPFile
|
||||
{
|
||||
public:
|
||||
CMemoryBSPFile();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Grabs data from the BSP class and serializes it to the output buffer.
|
||||
// The output buffer must be at the start of an empty output stream.
|
||||
//-----------------------------------------------------------------------------
|
||||
void ProcessAndSerialize( CUtlBuffer *pOutputBuffer, const CSimpleBSPFile *pSimpleBSPFile );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Writes data to a .bsp file buffer.
|
||||
//-----------------------------------------------------------------------------
|
||||
void Serialize( CUtlBuffer *pOutputBuffer );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Reads .bsp data from a buffer into lump-specific arrays.
|
||||
// Class can then be modified and re-saved to disk with Serialize().
|
||||
//-----------------------------------------------------------------------------
|
||||
void Deserialize( CUtlBuffer *pInputBuffer );
|
||||
|
||||
bool TryGetFaceVertex( int nFace, int nVertexIndex, Vector *pPosition ) const;
|
||||
int GetLeafIndexFromPoint( int nNodeIndex, const Vector &vPosition ) const;
|
||||
|
||||
|
||||
private:
|
||||
bool IsHeaderValid() { return m_FileHeader.ident == IDBSPHEADER; }
|
||||
|
||||
// Begin & End are used when you want to manually Put() data into the buffer
|
||||
void BeginWriteLump( int nLump, int nByteLength, int nVersion = 0 );
|
||||
void EndWriteLump();
|
||||
|
||||
// Writes a whole lump (do not call Begin/EndWriteLump)
|
||||
void WriteLump( int nLump, const void *pData, int nByteLength, int nVersion = 0 );
|
||||
|
||||
template< typename T >
|
||||
void WriteLump( int nLump, const CUtlVector< T > &data, int nVersion = 0 );
|
||||
|
||||
// Begin & End are used when you want to manually Get() data from the buffer
|
||||
int BeginReadLump( int nLump ); // returns size of the lump
|
||||
void EndReadLump();
|
||||
|
||||
// Read a lump into an array (do not call Begin/EndReadLump)
|
||||
template< typename T >
|
||||
void ReadLump( int nLump, CUtlVector< T > *pVector );
|
||||
|
||||
void BuildTexInfo();
|
||||
void WriteTexInfo( bool bPurgeWhenComplete );
|
||||
void BuildTexData();
|
||||
int FindOrAddString( const char *pString );
|
||||
void WriteTexData( bool bPurgeWhenComplete );
|
||||
|
||||
void BuildModelData();
|
||||
void WriteModelData( bool bPurgeWhenComplete );
|
||||
|
||||
void WritePortalFaces( const CBSPNode *pNode );
|
||||
|
||||
// There are 3 types of faces that can be emitted:
|
||||
// 1) Portal faces, emitted all at once when a model is written
|
||||
// 2) Detail faces, emitted after portal faces (also all at once when a model is written)
|
||||
// 3) Displacement faces, emitted only for the world model (model #0), written all at once with the world model
|
||||
void EmitFace( const CBSPFace *pBSPFace, bool bOnNode );
|
||||
|
||||
void BuildBSPTreeData();
|
||||
void WriteBSPTreeData( bool bPurgeWhenComplete );
|
||||
|
||||
int32 EmitLeaf( const CBSPNode *pNode );
|
||||
int32 EmitNode( const CBSPNode *pNode );
|
||||
|
||||
void BuildBrushes();
|
||||
void WriteBrushes( bool bPurgeWhenComplete );
|
||||
|
||||
void BuildPlanes();
|
||||
void WritePlanes( bool bPurgeWhenComplete );
|
||||
|
||||
void WriteModels( bool bPurgeWhenComplete );
|
||||
|
||||
void WriteDummyAreasAndAreaPortals();
|
||||
|
||||
void BuildGameLumpData();
|
||||
void EmitStaticProp( const MapEntity_t *pEntity, CUtlVector< StaticPropLump_t > *pStaticPropLump, CUtlVector< StaticPropLeafLump_t > *pStaticPropLeafLump, CUtlVector< StaticPropDictLump_t > *pStaticPropDictionaryLump );
|
||||
int AddStaticPropDictionaryEntry( const char *pModelName, CUtlVector< StaticPropDictLump_t > *pStaticPropDictionaryLump );
|
||||
int AddStaticPropLeaves( const Vector &vOrigin, int nNodeIndex, CUtlVector< StaticPropLeafLump_t > *pStaticPropLeafLump );
|
||||
void WriteGameLumpData( bool bPurgeWhenComplete );
|
||||
|
||||
void BuildEntityData();
|
||||
void StripTrailingJunkCharacters( char *pString );
|
||||
void WriteEntityData( bool bPurgeWhenComplete );
|
||||
|
||||
void BuildVisibilityData();
|
||||
void WriteVisibilityData( bool bPurgeWhenComplete );
|
||||
|
||||
void BuildDisplacements();
|
||||
void WriteDisplacements( bool bPurgeWhenComplete );
|
||||
|
||||
void BuildPhysicsCollisionData();
|
||||
CPhysCollisionEntry * CreateWorldPhysicsModels(
|
||||
IPhysicsCollision *pPhysicsCollision,
|
||||
CUtlVector< int > *pWorldPropertyRemapList,
|
||||
const int *pSurfacePropertyList,
|
||||
const dmodel_t *pModel,
|
||||
MapBrushContentsFlags_t contentsMask );
|
||||
CPhysCollisionEntry * CreatePhysicsModel(
|
||||
IPhysicsCollision *pPhysicsCollision,
|
||||
IPhysicsSurfaceProps *pPhysicsProperties,
|
||||
const int *pSurfacePropertyList,
|
||||
const dmodel_t *pModel );
|
||||
void BuildDisplacementVirtualMesh( IPhysicsCollision *pPhysicsCollision );
|
||||
const MapBrushSide_t *FindClosestBrushSide( int nBrushIndex, const Vector &vNormal );
|
||||
int RemapWorldMaterial( CUtlVector< int > *pWorldPropertyRemapList, int nSurfacePropertyIndex );
|
||||
|
||||
void WritePhysicsCollisionData( bool bPurgeWhenComplete );
|
||||
|
||||
void WriteLightingData( bool bPurgeWhenComplete );
|
||||
|
||||
CUtlBuffer *m_pSerialBuffer;
|
||||
|
||||
const CSimpleBSPFile *m_pSimpleBSPFile;
|
||||
const CSimpleMapFile *m_pMapFile;
|
||||
|
||||
CPlaneHash m_PlaneHash;
|
||||
|
||||
BSPHeader_t m_FileHeader;
|
||||
|
||||
public:
|
||||
// The following arrays map 1:1 with on-disk BSP data.
|
||||
CUtlVector< texinfo_t > m_TexInfoList;
|
||||
CUtlVector< dtexdata_t > m_TexDataList;
|
||||
|
||||
CUtlVector< char > m_TexStringData;
|
||||
CUtlVector< int32 > m_TexStringIndices;
|
||||
|
||||
CUtlVector< dmodel_t > m_ModelList;
|
||||
CVertexHash m_VertexHash;
|
||||
CUtlVector< dedge_t > m_EdgeList;
|
||||
CUtlVector< int32 > m_SurfEdgeList;
|
||||
CUtlVector< dface_t > m_FaceList;
|
||||
CUtlVector< Vector > m_VertexNormalList;
|
||||
CUtlVector< uint16 > m_VertexNormalIndexList;
|
||||
|
||||
CUtlVector< dnode_t > m_NodeList;
|
||||
CUtlVector< dleaf_t > m_LeafList;
|
||||
CUtlVector< uint16 > m_LeafBrushList;
|
||||
CUtlVector< uint16 > m_LeafFaceList;
|
||||
|
||||
CUtlVector< dbrush_t > m_BrushList;
|
||||
CUtlVector< dbrushside_t > m_BrushSideList;
|
||||
|
||||
CUtlVector< dplane_t > m_Planes;
|
||||
|
||||
CUtlVector< byte > m_GameLumpData;
|
||||
|
||||
CUtlVector< byte > m_EntityData;
|
||||
|
||||
CUtlVector< byte > m_VisibilityData;
|
||||
|
||||
CUtlVector< CCoreDispInfo * > m_DisplacementHelperList;
|
||||
CUtlVector< ddispinfo_t > m_DisplacementList;
|
||||
CUtlVector< CDispVert > m_DisplacementVertexList;
|
||||
CUtlVector< CDispTri > m_DisplacementTriangleList;
|
||||
CUtlVector< CDispMultiBlend > m_DisplacementMultiBlendList;
|
||||
|
||||
CUtlVector< byte > m_PhysicsDisplacementData;
|
||||
CUtlVector< byte > m_PhysicsCollideData;
|
||||
|
||||
CUtlVector< byte > m_LightingData;
|
||||
CUtlVector< dworldlight_t > m_WorldLightsLDR;
|
||||
CUtlVector< dworldlight_t > m_WorldLightsHDR;
|
||||
|
||||
// If entityExclusionFlags[N] is set to true, then do not write entity data for entity NF
|
||||
CBitVec< MAX_MAP_ENTITIES > m_EntityExclusionFlags;
|
||||
};
|
||||
|
||||
#endif // SERIALIZESIMPLEBSPFILE_H
|
||||
401
public/vbsp2lib/simplebspfile.h
Normal file
401
public/vbsp2lib/simplebspfile.h
Normal file
@@ -0,0 +1,401 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// Class to represent and write out a BSP file.
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef SIMPLEBSPFILE_H
|
||||
#define SIMPLEBSPFILE_H
|
||||
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "bitvec.h"
|
||||
|
||||
#include "simplemapfile.h"
|
||||
#include "vbspmathutil.h"
|
||||
|
||||
class CSimpleMapFile;
|
||||
struct MapEntity_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Indicates that the BSP node is a leaf (m_pChildren will be all NULL)
|
||||
//-----------------------------------------------------------------------------
|
||||
static const int LEAF_PLANE_INDEX = -1;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A sentinel cluster index used to indicate that a node does not
|
||||
// belong to any cluster.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const int INVALID_CLUSTER_INDEX = -1;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Default maximum visibility radius used to compute cluster-to-cluster
|
||||
// visibility.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const float DEFAULT_VISIBILITY_RADIUS = 2500.0f;
|
||||
|
||||
class CBSPBrush;
|
||||
class CBSPFace;
|
||||
class CBSPPortal;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A node in a BSP tree.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBSPNode
|
||||
{
|
||||
public:
|
||||
CBSPNode();
|
||||
~CBSPNode();
|
||||
|
||||
bool IsLeaf() const { return m_nSplitPlaneIndex == LEAF_PLANE_INDEX; }
|
||||
|
||||
CBSPNode *m_pParent;
|
||||
CBSPNode *m_pChildren[2];
|
||||
// If this node is a leaf, the value is LEAF_PLANE_INDEX.
|
||||
// Otherwise, the split plane is always the "positive" plane of a pair (that is, even numbered).
|
||||
int m_nSplitPlaneIndex;
|
||||
// Flags indicating the contents of the BSP node.
|
||||
MapBrushContentsFlags_t m_ContentsFlags;
|
||||
// This field owns the contents' memory
|
||||
CUtlVector< CBSPBrush * > m_ClippedBrushes;
|
||||
// A list of portal faces or detail faces on this node.
|
||||
// Leaf nodes may contain only detail faces, non-leaf nodes may contain only portal faces.
|
||||
// This field does NOT own the contents' memory; the faces are owned by the containing model or the portal
|
||||
// (depending on what kind of face it is).
|
||||
CUtlVector< CBSPFace * > m_Faces;
|
||||
// This field does NOT own the contents' memory; the portals are owned by the containing model.
|
||||
CUtlVector< CBSPPortal * > m_Portals;
|
||||
// AABB around the node
|
||||
Vector m_vMinBounds, m_vMaxBounds;
|
||||
// True if an entity can reach this node via portals, False if unreachable
|
||||
bool m_bEntityCanReach;
|
||||
// The BSP cluster to which this leaf node belongs (only applies to the world BSP tree).
|
||||
// A cluster is simply a group of leaves which share visibility information.
|
||||
// In practice, there is 1 cluster per non-solid world leaf.
|
||||
// This value is ignored for non-leaf nodes.
|
||||
int m_nClusterIndex;
|
||||
|
||||
private:
|
||||
// Disallow value semantics
|
||||
CBSPNode( const CBSPNode &other );
|
||||
CBSPNode &operator=( const CBSPNode &other );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A binary space partition tree.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBSPTree
|
||||
{
|
||||
public:
|
||||
CBSPTree();
|
||||
~CBSPTree();
|
||||
|
||||
CBSPNode *m_pRoot;
|
||||
CBSPNode m_OutsideNode; // a sentinel node which exists in the space outside of the BSP tree
|
||||
// AABB around the tree
|
||||
Vector m_vMinBounds, m_vMaxBounds;
|
||||
|
||||
private:
|
||||
// Disallow value semantics
|
||||
CBSPTree( const CBSPTree &other );
|
||||
CBSPTree &operator=( const CBSPTree &other );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A portal between two nodes of a BSP tree.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBSPPortal
|
||||
{
|
||||
public:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a default, null portal.
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPPortal();
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a new portal along the same plane as the given portal,
|
||||
// except with a different shape.
|
||||
// This is used when a single portal is cut by a node's splitting plane
|
||||
// into two new portals along the same plane.
|
||||
//
|
||||
// This constructor swaps its polygon's points with the given polygon's
|
||||
// for efficiency!
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPPortal( const CBSPPortal &other, Polygon_t *pPortalShape );
|
||||
~CBSPPortal();
|
||||
|
||||
CBSPNode *GetOtherNode( const CBSPNode *pNode ) const;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns either 0 or 1 to indicate which node attached to this portal
|
||||
// is responsible for drawing the face.
|
||||
// This call is only valid if m_PortalFaces.Count() > 0.
|
||||
//-----------------------------------------------------------------------------
|
||||
int GetNodeIndexForFace() const;
|
||||
|
||||
// The nodes on either side of the portal.
|
||||
// The convention is that the plane of the portal faces in the direction from node 1 towards node 0.
|
||||
// (That is, node 0 is in the positive half-space of the plane while node 1 is in the the negative half-space).
|
||||
// In a properly built tree, these nodes are always leaves (during construction they may
|
||||
// point to interior nodes).
|
||||
CBSPNode *m_pNodes[2];
|
||||
|
||||
// Not NULL if this portal lives on a node's split plane (which is usually the case, except for
|
||||
// portals at the edge of the world). This node is never a leaf.
|
||||
CBSPNode *m_pOnNode;
|
||||
|
||||
// Shape of the portal.
|
||||
Polygon_t m_Polygon;
|
||||
|
||||
// Plane along which the portal lives.
|
||||
Plane_t m_Plane;
|
||||
|
||||
// These are the faces generated when the portal is in-between solid and non-solid contents.
|
||||
// Logically, there is only 1 convex face, but some constraints (e.g. max lightmap size per face)
|
||||
// can require subdivision of faces.
|
||||
// This class owns the faces and frees them on destruction.
|
||||
CUtlVector< CBSPFace * > m_PortalFaces;
|
||||
|
||||
private:
|
||||
// Disallow value semantics
|
||||
CBSPPortal( const CBSPPortal &other );
|
||||
CBSPPortal &operator=( const CBSPPortal &other );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The side of a BSP brush (convex solid).
|
||||
// This class is copyable.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBSPBrushSide
|
||||
{
|
||||
public:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a default, invalid brush side.
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPBrushSide();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a new brush side initialized from map data.
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPBrushSide( const MapBrushSide_t *pMapBrushSide );
|
||||
|
||||
// Index into BSP creation context's plane list
|
||||
int m_nPlaneIndex;
|
||||
// Index into map's texture infos array
|
||||
int m_nTextureInfoIndex;
|
||||
MapBrushSideSurfaceFlags_t m_SurfaceFlags;
|
||||
Polygon_t m_Polygon;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A convex solid in a BSP file, produced from CSG operations on brushes
|
||||
// found in the original map.
|
||||
// This class is copyable.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBSPBrush
|
||||
{
|
||||
public:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a default brush solid with no sides.
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPBrush();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a new default brush solid initialized from map data.
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPBrush( const MapBrush_t *pMapBrush, const MapBrushSide_t *pMapBrushSides );
|
||||
|
||||
Vector m_vMinBounds, m_vMaxBounds;
|
||||
|
||||
CCopyableUtlVector< CBSPBrushSide > m_Sides;
|
||||
MapBrushContentsFlags_t m_ContentsFlags;
|
||||
const MapBrush_t *m_pOriginalBrush;
|
||||
|
||||
// Which side of the node splitting plane this brush is on.
|
||||
// (both values only used during BSP construction in order to split nodes).
|
||||
PlaneSide_t m_nTempSplitSide;
|
||||
PlaneSide_t m_nSplitSide;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A renderable face associated with the side of a detail brush or a portal.
|
||||
// This class is copyable.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBSPFace
|
||||
{
|
||||
public:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a default, empty face.
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPFace();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a face from the side of a BSP brush solid.
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPFace( const CBSPBrush *pBrush, const CBSPBrushSide *pSide );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructs a face from another face, except with a different shape.
|
||||
// Useful when cutting a face into parts.
|
||||
//
|
||||
// This constructor swaps its polygon's points with the given polygon's
|
||||
// for efficiency.
|
||||
//-----------------------------------------------------------------------------
|
||||
CBSPFace( const CBSPFace &other, Polygon_t *pPolygon );
|
||||
|
||||
// Index into map's texture infos array
|
||||
int m_nTextureInfoIndex;
|
||||
// Index into BSP creation context's plane list
|
||||
int m_nPlaneIndex;
|
||||
Polygon_t m_Polygon;
|
||||
// Index into the map's displacement array, if this face comes from a displacement surface.
|
||||
int m_nDisplacementIndex;
|
||||
// The index of this face in the final output.
|
||||
// All faces in a BSP file appear sequentially by model.
|
||||
// Within a model's contiguous list of faces, portal faces are serialized first
|
||||
// via depth-first traversal of the BSP tree, followed by detail faces.
|
||||
int m_nSerializedFaceIndex;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// An entity in a map with associated CSG brush data.
|
||||
// The 0th model in a BSP file corresponds to the world entity of the map
|
||||
// and includes all detail brushes from detail entities in the original map.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBSPModel
|
||||
{
|
||||
public:
|
||||
CBSPModel();
|
||||
~CBSPModel();
|
||||
|
||||
CBSPTree *m_pTree;
|
||||
// Detail faces are owned by the model and are freed on destruction.
|
||||
CUtlVector< CBSPFace * > m_DetailFaces;
|
||||
// Portals are owned by the model and are freed on destruction.
|
||||
CUtlVector< CBSPPortal * > m_Portals;
|
||||
|
||||
Vector m_vMinBounds, m_vMaxBounds;
|
||||
|
||||
private:
|
||||
// Disallow value semantics
|
||||
CBSPModel( const CBSPModel &other );
|
||||
CBSPModel &operator=( const CBSPModel &other );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// In theory, a cluster is a set of BSP leaf nodes.
|
||||
// In practice, it is simply a pointer to a single, existing BSP leaf node.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct BSPCluster_t
|
||||
{
|
||||
const CBSPNode *m_pLeafNode;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// An in-memory representation of a BSP file, built from a map file.
|
||||
// This class requires that the map file remain valid for its lifetime,
|
||||
// though the map file is accessed in a read-only manner.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CSimpleBSPFile
|
||||
{
|
||||
public:
|
||||
CSimpleBSPFile();
|
||||
~CSimpleBSPFile();
|
||||
|
||||
const CSimpleMapFile *GetOriginalMap() const { return m_pMapFile; }
|
||||
|
||||
const CPlaneHash *GetPlaneHash() const { return &m_PlaneHash; }
|
||||
|
||||
const CBSPModel * const *GetModels() const { return m_Models.Base(); }
|
||||
int GetModelCount() const { return m_Models.Count(); }
|
||||
|
||||
const CBSPFace * GetDisplacementFaces() const { return m_DisplacementFaces.Base(); }
|
||||
int GetDisplacementFaceCount() const { return m_DisplacementFaces.Count(); }
|
||||
|
||||
void SetVisibilityRadius( float flRadius ) { m_flVisibilityRadius = flRadius; }
|
||||
int GetClusterCount() const { return m_Clusters.Count(); }
|
||||
const byte * GetVisibilityData() const { return m_VisibilityData.Base(); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Populates this in-memory BSP file object from the given in-memory map file.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CreateFromMapFile( const CSimpleMapFile *pMapFile );
|
||||
|
||||
private:
|
||||
// Source map file; must remain valid for the lifetime of this object.
|
||||
const CSimpleMapFile *m_pMapFile;
|
||||
|
||||
// Array of planes with acceleration structure for fast lookup.
|
||||
// Starts off copied from the map (so all map plane indices are valid) but is expanded
|
||||
// during the BSP process via CSG operations.
|
||||
CPlaneHash m_PlaneHash;
|
||||
CUtlVector< CBSPModel * > m_Models;
|
||||
CUtlVector< CBSPFace > m_DisplacementFaces;
|
||||
CUtlVector< BSPCluster_t > m_Clusters;
|
||||
CUtlVector< byte > m_VisibilityData;
|
||||
|
||||
// A monotonically increasing value which increments for every face generated during the BSP construction process.
|
||||
int m_nNextFaceIndex;
|
||||
|
||||
// The radius value beyond which clusters cannot see each other.
|
||||
float m_flVisibilityRadius;
|
||||
|
||||
void ProcessWorldEntity( const MapEntity_t *pMapEntity );
|
||||
void ProcessEntity( const MapEntity_t *pMapEntity );
|
||||
|
||||
CBSPNode *GenerateBSPGrid( int nMinX, int nMinY, int nMaxX, int nMaxY, int nAbsoluteMins[2], int nAbsoluteMaxs[2], CBSPNode **ppNodeList );
|
||||
CBSPNode *CreateGridNode( int nX, int nY );
|
||||
|
||||
void CreateBSPBrushList( const MapBrush_t *pBrushes, int nBrushCount, bool bIncludeDetail, bool bIncludeStructural, const Vector &vClipMin, const Vector &vClipMax, CUtlVector< CBSPBrush * > *pBrushList );
|
||||
CBSPBrush *CreateClippedBrush( const MapBrush_t *pMapBrush, const Vector &vClipMin, const Vector &vClipMax, int nClipMinPlanes[2], int nClipMaxPlanes[2] );
|
||||
|
||||
void SplitBrush( CBSPBrush *pBrush, int nPlaneIndex, CBSPBrush **ppFrontBrush, CBSPBrush **ppBackBrush );
|
||||
PlaneSide_t GetPrimaryPlaneSide( CBSPBrush *pBrush, Plane_t *pPlane );
|
||||
|
||||
CBSPTree *BuildBSPTree( CUtlVector< CBSPBrush * > *pBrushList, const Vector &vMin, const Vector &vMax );
|
||||
void BuildBSPChildren( CBSPNode *pNode, CUtlVector< CBSPBrush * > *pBrushList );
|
||||
int FindBestSplitPlane( CUtlVector< CBSPBrush * > *pBrushList );
|
||||
void MakeBrushPolygons( CBSPBrush *pBrush );
|
||||
void SplitBrushList( CUtlVector< CBSPBrush * > *pBrushList, CBSPNode *pNode, CUtlVector< CBSPBrush * > *pFrontChildList, CUtlVector< CBSPBrush * > *pBackChildList );
|
||||
PlaneSide_t TestBrushAgainstPlaneIndex( CBSPBrush *pBrush, int nPlaneIndex, int *nNumSplits );
|
||||
void PruneNodes( CBSPNode *pNode, CUtlVector< CBSPPortal * > *pPortalList );
|
||||
|
||||
void BuildTreePortals( CBSPTree *pTree, CUtlVector< CBSPPortal * > *pPortalList );
|
||||
void BuildNodePortals( CBSPNode *pNode, CUtlVector< CBSPPortal * > *pPortalList );
|
||||
void FloodEntities( CBSPTree *pTree );
|
||||
void FloodEntity( CBSPNode *pNode, const Vector &vPosition );
|
||||
void FloodFillThroughPortals( CBSPNode *pNode );
|
||||
void MakeUnreachableNodesSolid( CBSPNode *pNode );
|
||||
void MakeFacesFromPortals( CBSPModel *pModel );
|
||||
void NumberPortalFaces( CBSPNode *pNode );
|
||||
|
||||
void BuildRadialVisibilityData( CBSPNode *pRootNode );
|
||||
void AssignClusterIndicesToLeaves( CBSPNode *pNode );
|
||||
|
||||
void CreateDisplacementFaces();
|
||||
|
||||
void PopulateTreeWithDetail( const CBSPTree *pTree, int nFirstBrush, int nNumBrushes, CUtlVector< CBSPFace * > *pDetailFaceList );
|
||||
void FilterFaceIntoTree( CBSPNode *pNode, CBSPFace *pClippedFace, CBSPFace *pOriginalFace );
|
||||
void FilterBrushIntoTree( CBSPNode *pNode, CBSPBrush *pBrush );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Dumps useful information about the BSP to several files beginning
|
||||
// with the path string pPrefixName and suffixed appropriately
|
||||
// (e.g. "_ent.txt", "_bsp.csv", "_tex.csv").
|
||||
//-----------------------------------------------------------------------------
|
||||
void DumpBSPInfo( const char *pPrefixName, byte *pBSPData, int nBSPDataSize );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Writes all faces to a .gl file which can be viewed in GLView.
|
||||
//-----------------------------------------------------------------------------
|
||||
void WriteGLBSPFile( FileHandle_t fileHandle, byte *pBSPData, int nBSPDataSize );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Dumps the contents of the given lump to the specified file.
|
||||
//-----------------------------------------------------------------------------
|
||||
void DumpLump( FileHandle_t fileHandle, byte *pBSPData, int nBSPDataSize, int nLumpIndex );
|
||||
|
||||
|
||||
#endif // SIMPLEBSPFILE_H
|
||||
425
public/vbsp2lib/simplemapfile.h
Normal file
425
public/vbsp2lib/simplemapfile.h
Normal file
@@ -0,0 +1,425 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// Class & functions to parse and represent a VMF file.
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef SIMPLEMAPFILE_H
|
||||
#define SIMPLEMAPFILE_H
|
||||
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "chunkfile.h"
|
||||
#include "stringpool.h"
|
||||
|
||||
#include "vbspmathutil.h"
|
||||
|
||||
class CSimpleMapFile;
|
||||
class GameData;
|
||||
|
||||
DECLARE_LOGGING_CHANNEL( LOG_VBSP2 );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags that modify a brush volume or brush side surface
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef int MapBrushContentsFlags_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags that modify a brush side surface
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef short MapBrushSideSurfaceFlags_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A single entity from a VMF file.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct MapEntity_t
|
||||
{
|
||||
// World-space location of the object.
|
||||
Vector m_vOrigin;
|
||||
|
||||
// Index & count of brushes contained within this entity. These are stored in the map's brush array.
|
||||
// Brushes in an entity have contiguous indices in the range: [m_nFirstBrushIndex, m_nFirstBrushIndex + m_nNumBrushes).
|
||||
int m_nFirstBrushIndex;
|
||||
int m_nNumBrushes;
|
||||
|
||||
// Index & count of key-value pairs (entity properties) contained within this entity. These are stored in the map's key-value pair array.
|
||||
// Key-value pairs in an entity have contiguous indices in the range: [m_nFirstKVPairIndex, m_nFirstKVPairIndex + m_nNumKVPairs).
|
||||
int m_nFirstKVPairIndex;
|
||||
int m_nNumKVPairs;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A property of an entity from a VMF file.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct MapEntityKeyValuePair_t
|
||||
{
|
||||
// These point into the string pool owned by the map object, so no memory management is necessary.
|
||||
const char *m_pKey;
|
||||
const char *m_pValue;
|
||||
|
||||
// True if this key value pair came from the "connections" section of an entity,
|
||||
// false if it came from an ordinary entity key.
|
||||
bool m_bIsConnection;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A CSG brush (convex solid) from a VMF file.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct MapBrush_t
|
||||
{
|
||||
// Contents of the brush, based on the properties of its sides.
|
||||
MapBrushContentsFlags_t m_ContentsFlags;
|
||||
|
||||
// Index & count of brush sides. These are stored in the map's brush sides array.
|
||||
// Brush sides have contiguous indices in the range: [m_nFirstSideIndex, m_nFirstSideIndex + m_nNumSides).
|
||||
int m_nFirstSideIndex;
|
||||
int m_nNumSides;
|
||||
|
||||
// AABB of the brush
|
||||
Vector m_vMinBounds, m_vMaxBounds;
|
||||
};
|
||||
|
||||
static const int INVALID_DISPLACEMENT_INDEX = -1;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A single side of a CSG brush from a VMF file.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct MapBrushSide_t
|
||||
{
|
||||
// Contents of the brush side, based on the material properties.
|
||||
MapBrushContentsFlags_t m_ContentsFlags;
|
||||
// Surface flags of the brush side, based on the material properties.
|
||||
MapBrushSideSurfaceFlags_t m_SurfaceFlags;
|
||||
// The index of the plane coincident with this brush side. The index is in the map's plane hash.
|
||||
int m_nPlaneIndex;
|
||||
// The index of the texture info struct for this brush side, describing the material applied to this side.
|
||||
// The index is into the map's texture info array.
|
||||
int m_nTextureInfoIndex;
|
||||
// The polygonal face of this brush side.
|
||||
Polygon_t m_Polygon;
|
||||
// The index of the displacement associated with this side, or INVALID_DISPLACEMENT_INDEX if
|
||||
// this side is not a displacement surface.
|
||||
int m_nDisplacementIndex;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A displacement surface, specified on a particular CSG brush side.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CMapDisplacement
|
||||
{
|
||||
public:
|
||||
CMapDisplacement();
|
||||
|
||||
bool AreVerticesAllocated() const { return m_Vertices.Count() > 0 && m_nPower > 0; }
|
||||
|
||||
// NOTE: If new fields are added to this class, you must update MoveFrom()!
|
||||
|
||||
// Power-of-2 number of subdivisions.
|
||||
// MIN_MAP_DISP_POWER <= m_nPower <= MAX_MAP_DISP_POWER
|
||||
int m_nPower;
|
||||
// Map brush side corresponding to this displacement surface. The brush side is "orphaned"
|
||||
// in that no brushes will point to it (since the original brush is removed from the world).
|
||||
int m_nOriginalBrushSide;
|
||||
// SURF_* flags, defined in builddisp.h
|
||||
int m_nFlags;
|
||||
// Contents flags taken from the original brush.
|
||||
// The value is stored here, since the original brush gets removed from the world.
|
||||
MapBrushContentsFlags_t m_ContentsFlags;
|
||||
Vector m_vStartPosition;
|
||||
|
||||
struct Vertex_t
|
||||
{
|
||||
float m_flAlpha;
|
||||
float m_flDistance;
|
||||
Vector m_vNormal;
|
||||
Vector m_vOffset;
|
||||
Vector4D m_vMultiBlend;
|
||||
Vector m_vMultiBlendColors[MAX_MULTIBLEND_CHANNELS];
|
||||
};
|
||||
|
||||
CUtlVector< Vertex_t > m_Vertices;
|
||||
|
||||
// DISPTRI_* flags, defined in bspfile.h (one per triangle).
|
||||
CUtlVector< unsigned short > m_TriangleTags;
|
||||
|
||||
// Copies values and takes ownership of owned data from the other displacement object
|
||||
// (this is a destructive, but efficient, operation used to migrate a displacement
|
||||
// from one map object to another).
|
||||
// NOTE: If you add new fields to CMapDisplacement, you must update this function!
|
||||
void MoveFrom( CMapDisplacement *pOther );
|
||||
|
||||
private:
|
||||
// Disallow value semantics
|
||||
CMapDisplacement( const CMapDisplacement &other );
|
||||
CMapDisplacement &operator=( const CMapDisplacement &other );
|
||||
};
|
||||
|
||||
static const int MAX_TEXTURE_NAME_LENGTH = 128;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Texture properties for a brush side, as loaded from a VMF file.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct MapBrushTexture_t
|
||||
{
|
||||
Vector m_vUAxis, m_vVAxis;
|
||||
float m_flShift[2];
|
||||
float m_flTextureWorldUnitsPerTexel[2];
|
||||
float m_flLightmapWorldUnitsPerLuxel;
|
||||
char m_MaterialName[MAX_TEXTURE_NAME_LENGTH];
|
||||
MapBrushSideSurfaceFlags_t m_SurfaceFlags;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sentinel texture info index for a side of a solid BSP node.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const int NODE_TEXTURE_INFO_INDEX = -1;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Planar mapping of texture data to a particular surface.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct MapTextureInfo_t
|
||||
{
|
||||
// The U and V vectors (w-component contains the offset) that define
|
||||
// a homogeneous planar mapping from 3D (world) space to 2D (texture) space.
|
||||
float m_flTextureVectors[2][4];
|
||||
float m_flLightmapVectors[2][4];
|
||||
// Index into the map's texture data array of the structure which describes
|
||||
// the material being mapped to this surface.
|
||||
int m_nTextureDataIndex;
|
||||
MapBrushSideSurfaceFlags_t m_SurfaceFlags;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Basic material information for a surface.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct MapTextureData_t
|
||||
{
|
||||
Vector m_vReflectivity;
|
||||
// Width and height of the base texture referenced by the material
|
||||
int m_nWidth, m_nHeight;
|
||||
// Name of the material (e.g. DEV/GRAYGRID) being mapped
|
||||
char m_MaterialName[MAX_TEXTURE_NAME_LENGTH];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds a key-value pair with the specified key in a given array of
|
||||
// key-value pairs, or NULL if none is found
|
||||
//-----------------------------------------------------------------------------
|
||||
const MapEntityKeyValuePair_t *FindPair( const char *pKeyName, const MapEntityKeyValuePair_t *pPairs, int nNumPairs );
|
||||
MapEntityKeyValuePair_t *FindPair( const char *pKeyName, MapEntityKeyValuePair_t *pPairs, int nNumPairs );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the value associated with the given pair or "" if the pair
|
||||
// or value string is NULL (safe to chain with FindPair)
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *GetPairValue( const MapEntityKeyValuePair_t *pPair );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A class which represents a VMF (map) file in memory
|
||||
// or value string is NULL (safe to chain with FindPair)
|
||||
//-----------------------------------------------------------------------------
|
||||
class CSimpleMapFile
|
||||
{
|
||||
public:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the minimum and maximum bound of all world brushes in this map file
|
||||
//-----------------------------------------------------------------------------
|
||||
Vector GetMinBounds() const { return m_vMinBounds; }
|
||||
Vector GetMaxBounds() const { return m_vMaxBounds; }
|
||||
|
||||
int GetMapRevision() const { return m_nMapRevision; }
|
||||
|
||||
const MapEntity_t *GetEntities() const { return &m_Entities[0]; }
|
||||
MapEntity_t *GetEntities() { return &m_Entities[0]; }
|
||||
int GetEntityCount() const { return m_Entities.Count(); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the world entity, which is the 0th entity in the file
|
||||
//-----------------------------------------------------------------------------
|
||||
const MapEntity_t *GetWorldEntity() const { return GetEntities(); }
|
||||
MapEntity_t *GetWorldEntity() { return GetEntities(); }
|
||||
|
||||
const MapBrush_t *GetBrushes() const { return &m_Brushes[0]; }
|
||||
MapBrush_t *GetBrushes() { return &m_Brushes[0]; }
|
||||
int GetBrushCount() const { return m_Brushes.Count(); }
|
||||
|
||||
const MapBrushSide_t *GetBrushSides() const { return &m_BrushSides[0]; }
|
||||
MapBrushSide_t *GetBrushSides() { return &m_BrushSides[0]; }
|
||||
int GetBrushSideCount() const { return m_BrushSides.Count(); }
|
||||
|
||||
const CMapDisplacement *GetDisplacements() const { return &m_Displacements[0]; }
|
||||
CMapDisplacement *GetDisplacements() { return &m_Displacements[0]; }
|
||||
int GetDisplacementCount() const { return m_Displacements.Count(); }
|
||||
|
||||
const MapTextureInfo_t *GetTextureInfos() const { return &m_TextureInfos[0]; }
|
||||
MapTextureInfo_t *GetTextureInfos() { return &m_TextureInfos[0]; }
|
||||
int GetTextureInfoCount() const { return m_TextureInfos.Count(); }
|
||||
|
||||
const MapTextureData_t *GetTextureData() const { return &m_TextureData[0]; }
|
||||
MapTextureData_t *GetTextureData() { return &m_TextureData[0]; }
|
||||
int GetTextureDataCount() const { return m_TextureData.Count(); }
|
||||
|
||||
const MapEntityKeyValuePair_t *GetKeyValuePairs() const { return &m_KeyValuePairs[0]; }
|
||||
MapEntityKeyValuePair_t *GetKeyValuePairs() { return &m_KeyValuePairs[0]; }
|
||||
int GetKeyValuePairCount() const { return m_KeyValuePairs.Count(); }
|
||||
|
||||
const CPlaneHash *GetPlaneHash() const { return &m_PlaneHash; }
|
||||
|
||||
const char *GetFilename() const { return m_pFilename; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Adds a func_instance entity to the map file.
|
||||
//-----------------------------------------------------------------------------
|
||||
void AddFuncInstance( const char *pFilename, QAngle angles, Vector vOrigin, MapEntityKeyValuePair_t *pExtraKeyValues = NULL, int nExtraKeyValues = 0 );
|
||||
|
||||
int FindEntity( const char *pClassName, const char *pKeyName, const char *pValue, int nStartingIndex = 0 );
|
||||
void RemoveEntity( int nEntityIndex );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags passed to ResolveInstances() to control behavior.
|
||||
//-----------------------------------------------------------------------------
|
||||
enum ResolveInstanceFlags_t
|
||||
{
|
||||
NO_FLAGS = 0x0,
|
||||
CONVERT_STRUCTURAL_TO_DETAIL = 0x1, // convert all solids in world entities to func_detail
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Callback invoked after loading each instance.
|
||||
// The callback is given the originally provided context value, the loaded
|
||||
// instance map, and the key-value pairs from the parent map's
|
||||
// func_instance entity chunk.
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef void ( *PostLoadInstanceHandler_t )( void *pContext, CSimpleMapFile *pInstanceMapFile, MapEntityKeyValuePair_t *pFuncInstanceKeyValuePairs, int nNumKeyValuePairs );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Recursively loads all contained func_instance entities and merges
|
||||
// them with the current map in breadth-first recursive order.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ResolveInstances( ResolveInstanceFlags_t instanceFlags = NO_FLAGS, PostLoadInstanceHandler_t pPostLoadInstanceHandler = NULL, void *pHandlerContext = NULL );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Loads a VMF (map) file from disk and constructs a new CSimpleMapFile object.
|
||||
// The caller must delete the object when done.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void LoadFromFile( IFileSystem *pFileSystem, const char *pVMFFilename, CSimpleMapFile **ppNewMapFile, ResolveInstanceFlags_t instanceFlags = NO_FLAGS );
|
||||
|
||||
private:
|
||||
CSimpleMapFile( IFileSystem *pFileSystem, const char *pVMFFilename );
|
||||
|
||||
MapEntity_t *AllocateNewEntity();
|
||||
MapBrush_t *AllocateNewBrush();
|
||||
MapBrushSide_t *AllocateNewBrushSide();
|
||||
CMapDisplacement *AllocateNewDisplacement();
|
||||
MapBrushTexture_t *AllocateNewBrushTexture();
|
||||
MapTextureData_t *AllocateNewTextureData();
|
||||
MapEntityKeyValuePair_t *AllocateNewKeyValuePair();
|
||||
|
||||
// Some entity types are simply ignored
|
||||
void DeallocateLastEntity() { m_Entities.RemoveMultipleFromTail( 1 ); }
|
||||
|
||||
// Some brushes are loaded and then discarded (e.g. brushes with displacement)
|
||||
void DeallocateLastBrush() { m_Brushes.RemoveMultipleFromTail( 1 ); }
|
||||
|
||||
void ReportParseError( const char *pErrorString );
|
||||
|
||||
void MakeBrushPolygons( MapBrush_t *pBrush );
|
||||
|
||||
void MoveEntityBrushesToWorld( int nEntityIndex );
|
||||
|
||||
int GetTextureInfoForBrushTexture( MapBrushTexture_t *pBrushTexture, const Vector &vRelativeOrigin );
|
||||
int FindOrCreateTextureData( const char *pTextureName );
|
||||
int FindOrCreateTextureInfo( const MapTextureInfo_t &textureInfo );
|
||||
MapBrushContentsFlags_t ComputeBrushContents( MapBrush_t *b );
|
||||
|
||||
// Functions used to merge instance data (recursively) with the primary map
|
||||
void MergeInstance( int nEntityIndex, CSimpleMapFile *pInstanceMap, GameData *pGameData );
|
||||
void PreLoadInstances( GameData *pGD );
|
||||
void MergeBrushes( int nEntityIndex, const CSimpleMapFile *pInstanceMap, const Vector &vOrigin, const QAngle &orientation, const matrix3x4_t &transform );
|
||||
void MergeBrushSides( int nEntityIndex, CSimpleMapFile *pInstanceMap, const Vector &vOrigin, const QAngle &orientation, const matrix3x4_t &transform );
|
||||
void MergeEntities( int nEntityIndex, const CSimpleMapFile *pInstanceMap, const Vector &vOrigin, const QAngle &orientation, const matrix3x4_t &transform, GameData *pGameData );
|
||||
void FixupInstanceKeyValuePair( MapEntityKeyValuePair_t *pNewKeyValuePair, const char *pOriginalValue, const MapEntityKeyValuePair_t *pInstancePairs, int nNumPairs );
|
||||
|
||||
// The following static functions are passed as callbacks to the chunk file reader
|
||||
// when certain chunks and key blocks are encountered in the VMF file.
|
||||
static ChunkFileResult_t EntityChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t SolidChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t SideChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DispInfoChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t ConnectionsChunkHandler( CChunkFile *pFile, void *pData );
|
||||
|
||||
static ChunkFileResult_t EntityKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t SolidKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t SideKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t DisplacementKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
|
||||
// These are shim functions which simply call into their corresponding displacement key handlers
|
||||
static ChunkFileResult_t DisplacementNormalsChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementDistancesChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementOffsetsChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementAlphasChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementTriangleTagsChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementMultiBlendChunkHandler( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementMultiBlendColor0( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementMultiBlendColor1( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementMultiBlendColor2( CChunkFile *pFile, void *pData );
|
||||
static ChunkFileResult_t DisplacementMultiBlendColor3( CChunkFile *pFile, void *pData );
|
||||
|
||||
// These read the actual key data associated with each displacement attribute
|
||||
static ChunkFileResult_t DisplacementNormalsKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t DisplacementDistancesKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t DisplacementOffsetsKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t DisplacementAlphasKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t DisplacementTriangleTagsKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t DisplacementMultiBlendKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
static ChunkFileResult_t DisplacementMultiBlendColorKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
|
||||
static ChunkFileResult_t ConnectionsKeyHandler( const char *pKey, const char *pValue, void *pData );
|
||||
|
||||
struct MaterialInfo_t
|
||||
{
|
||||
char m_Name[MAX_TEXTURE_NAME_LENGTH];
|
||||
MapBrushContentsFlags_t m_ContentsFlags;
|
||||
MapBrushSideSurfaceFlags_t m_SurfaceFlags;
|
||||
};
|
||||
MaterialInfo_t* FindMaterialInfo( const char *pName );
|
||||
|
||||
IFileSystem *m_pFileSystem;
|
||||
|
||||
// This is needed so instances can be resolved. If we're loading map files from memory buffers
|
||||
// or other non-file sources, we'll need an "include interface" (like D3DX/HLSL's include resolution system).
|
||||
const char *m_pFilename;
|
||||
|
||||
CPlaneHash m_PlaneHash;
|
||||
CUtlVector< MapEntity_t > m_Entities;
|
||||
CUtlVector< MapBrush_t > m_Brushes;
|
||||
CUtlVector< CMapDisplacement > m_Displacements;
|
||||
// These two arrays (m_BrushSides & m_BrushTextures) should always be the same size as there is a 1:1 correspondence.
|
||||
CUtlVector< MapBrushSide_t > m_BrushSides;
|
||||
CUtlVector< MapBrushTexture_t > m_BrushTextures;
|
||||
CUtlVector< MapTextureInfo_t > m_TextureInfos;
|
||||
CUtlVector< MapTextureData_t > m_TextureData;
|
||||
|
||||
// Number of instances loaded (recursively).
|
||||
// This value is only used on the root-level map. It is used to generate unique names for instanced entities.
|
||||
int m_nInstanceCount;
|
||||
|
||||
// This value is only used on instance maps to control loading and processing.
|
||||
ResolveInstanceFlags_t m_InstanceFlags;
|
||||
|
||||
// Used to store entity property data
|
||||
CUtlVector< MapEntityKeyValuePair_t > m_KeyValuePairs;
|
||||
CStringPool m_KeyValueStringPool;
|
||||
|
||||
Vector m_vMinBounds, m_vMaxBounds;
|
||||
|
||||
int m_nMapRevision;
|
||||
int m_nHighestID;
|
||||
|
||||
// Used to cache results of FindMaterialInfo, which gets information about materials applied to brush sides.
|
||||
CUtlVector< MaterialInfo_t > m_MaterialInfos;
|
||||
};
|
||||
|
||||
#endif // SIMPLEMAPFILE_H
|
||||
238
public/vbsp2lib/vbspmathutil.h
Normal file
238
public/vbsp2lib/vbspmathutil.h
Normal file
@@ -0,0 +1,238 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// Utility functions for BSP and map file math operations.
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef VBSPMATHUTIL_H
|
||||
#define VBSPMATHUTIL_H
|
||||
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "mathlib/vector.h"
|
||||
#include "worldsize.h"
|
||||
#include "bspfile.h"
|
||||
|
||||
DECLARE_LOGGING_CHANNEL( LOG_VBSP2 );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A threshold used to determine whether coordinates of two normals are equal.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const float c_flNormalEpsilon = 0.00001f;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A threshold used to determine whether the distance value of two planes
|
||||
// are equal. Also used for rounding coordinates to the nearest integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const float c_flDistanceEpsilon = 0.01f;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Threshold used to determine whether something is entirely on one side
|
||||
// of a plane or another.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const float c_flPlaneSideEpsilon = 0.1f;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Threshold used to determine whether points should be snapped to each other.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const float c_flWeldVertexEpsilon = 0.1f;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Threshold used when clipping to determine whether a point is on a plane
|
||||
// or on a particular side.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const float c_flPlaneClipEpsilon = 0.01f;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Polygons with more points than this are not handled properly by
|
||||
// the system.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const int MAX_POINTS_ON_POLYGON = 64;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Represents a plane.
|
||||
// Unlike a standard plane equation, a point P is defined to be on a plane if
|
||||
// P * m_vNormal - m_flDistance == 0.
|
||||
// A point P is defined to be in the positive half-space if
|
||||
// P * m_vNormal - m_flDistance > 0.
|
||||
// (In a standard plane equation that minus sign is a plus sign)
|
||||
//-----------------------------------------------------------------------------
|
||||
struct Plane_t
|
||||
{
|
||||
Vector m_vNormal;
|
||||
float m_flDistance;
|
||||
// A value in the range [0,5] which indicates the axis alignment,
|
||||
// e.g. PLANE_X, PLANE_Y, PLANE_Z, PLANE_ANYX, PLANE_ANYY, PLANE_ANYZ
|
||||
int m_Type;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags indicating on which side of a plane something lies.
|
||||
//-----------------------------------------------------------------------------
|
||||
enum PlaneSide_t
|
||||
{
|
||||
PLANE_SIDE_INVALID = 0,
|
||||
PLANE_SIDE_FRONT = 1,
|
||||
PLANE_SIDE_BACK = 2,
|
||||
PLANE_SIDE_BOTH = PLANE_SIDE_FRONT | PLANE_SIDE_BACK,
|
||||
// "Facing" means that the point or face is directly on the plane;
|
||||
// this may be combined with front or back to take into account
|
||||
// direction.
|
||||
PLANE_SIDE_FACING = 4,
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns which side of a plane a bounding box is on.
|
||||
//-----------------------------------------------------------------------------
|
||||
PlaneSide_t GetPlaneSide( const Vector &vMin, const Vector &vMax, Plane_t *pPlane );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Snaps the plane to be axis-aligned if it is within an epsilon of axial.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SnapVector( Vector &vNormal );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Snaps the plane to be axis-aligned if it is within an epsilon of axial.
|
||||
// Recalculates dist if the vNormal was snapped. Rounds dist to integer
|
||||
// if it is within an epsilon of integer.
|
||||
//
|
||||
// vNormal - Plane vNormal vector (assumed to be unit length).
|
||||
// flDistance - Plane constant.
|
||||
// v0, v1, v2 - Three points on the plane.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SnapPlane( Vector &vNormal, vec_t &flDistance, const Vector &v0, const Vector &v1, const Vector &v2 );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns true if one plane representation is equal to the other,
|
||||
// within an epsilon threshold.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool PlaneEqual( Plane_t *pPlane, const Vector &vNormal, float flDistance );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns a value classifying the plane based on its axis alignment,
|
||||
// e.g. PLANE_X, PLANE_Y, PLANE_Z, PLANE_ANYX, PLANE_ANYY, PLANE_ANYZ
|
||||
//-----------------------------------------------------------------------------
|
||||
int GetPlaneTypeFromNormal( const Vector &vNormal );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compute a normal for a triangle, given three points.
|
||||
// The points are clockwise when looking at the triangle from the normal side.
|
||||
//-----------------------------------------------------------------------------
|
||||
Vector TriangleNormal( const Vector &v0, const Vector &v1, const Vector &v2 );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A polygon used to represent faces on maps, BSPs, etc.
|
||||
// This class is copyable.
|
||||
//-----------------------------------------------------------------------------
|
||||
class Polygon_t
|
||||
{
|
||||
public:
|
||||
CCopyableUtlVector< Vector > m_Points;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Computes whether a given polygon is tiny, relative to an epsilon threshold
|
||||
//-----------------------------------------------------------------------------
|
||||
bool IsPolygonTiny( Polygon_t *pPolygon );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Checks all points in a polygon against the min and max coordinates.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool IsPolygonHuge( Polygon_t *pPolygon );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Computes the area of a polygon
|
||||
//-----------------------------------------------------------------------------
|
||||
float ComputePolygonArea( const Polygon_t &polygon );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates a large polygon with extremal coordinates that lies on the plane
|
||||
//-----------------------------------------------------------------------------
|
||||
void CreatePolygonFromPlane( const Vector &vNormal, float flDistance, Polygon_t *pPolygon );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Clips a polygon against a plane, creating* either:
|
||||
// 1) One new, identical polygon (pOn), if the polygon is coincident
|
||||
// with the plane.
|
||||
// 2) One new, identical polygon (either pFront or pBack) if the polygon
|
||||
// is entirely on one side of the plane.
|
||||
// 3) Two new, different polygons (pFront and pBack) if the polygon is
|
||||
// clipped by the plane
|
||||
//
|
||||
// If pOn is NULL, the "on" case is ignored and treated as either front
|
||||
// or back appropriately.
|
||||
//
|
||||
// *The passed-in polygons (pOn, pFront, pBack) have their point arrays
|
||||
// cleared at the start of the function. They are considered to be
|
||||
// "created" upon exit if their point array has a non-zero point count.
|
||||
//-----------------------------------------------------------------------------
|
||||
void ChopPolygon( const Polygon_t &polygon, const Vector &vNormal, float flDistance, Polygon_t *pOn, Polygon_t *pFront, Polygon_t *pBack );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Clips a polygon against a plane. If the polygon is completely clipped,
|
||||
// pPolygon->m_Points will be empty ( Count() == 0 ).
|
||||
//-----------------------------------------------------------------------------
|
||||
void ChopPolygonInPlace( Polygon_t *pPolygon, const Vector &vNormal, float flDistance );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A plane which can be stored efficiently in a hash table for fast lookup.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct HashedPlane_t : public Plane_t
|
||||
{
|
||||
int m_nNextPlaneIndex;
|
||||
};
|
||||
|
||||
// Make sure this is a power of 2, code depends on it.
|
||||
static const int PLANE_HASH_TABLE_SIZE = 1024;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A class to hash and pool planes.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CPlaneHash
|
||||
{
|
||||
public:
|
||||
CPlaneHash();
|
||||
|
||||
int FindPlaneIndex( const Vector &vNormal, float flDistance );
|
||||
int FindPlaneIndex( Vector vPoints[3] );
|
||||
|
||||
CCopyableUtlVector< HashedPlane_t > m_Planes;
|
||||
|
||||
private:
|
||||
HashedPlane_t *AllocateNewPlane();
|
||||
|
||||
// Hash table consisting of indices into the m_Planes array
|
||||
int m_HashTable[PLANE_HASH_TABLE_SIZE];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A class to hash, weld, and pool vertices.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CVertexHash
|
||||
{
|
||||
public:
|
||||
CVertexHash();
|
||||
|
||||
CUtlVector< Vector > &GetVertices() { return m_Vertices; }
|
||||
const CUtlVector< Vector > &GetVertices() const { return m_Vertices; }
|
||||
void Purge();
|
||||
|
||||
// If bAlwaysAdd is true, this will skip the hash check and always add a new vertex
|
||||
// (useful if vertex indices must be kept consistent and duplicates might exist)
|
||||
int FindVertexIndex( const Vector &vertex, bool bAlwaysAdd = false );
|
||||
|
||||
private:
|
||||
static const int m_nHashBitShift = 8;
|
||||
static const int m_nHashLength = COORD_EXTENT >> m_nHashBitShift;
|
||||
// Hash along the X and Y axes by grouping vertices into hash buckets
|
||||
// which are NxN square columns of space.
|
||||
// ~64 KB
|
||||
int m_nVertexHash[m_nHashLength * m_nHashLength];
|
||||
CUtlVector< int > m_VertexHashChain;
|
||||
CUtlVector< Vector > m_Vertices;
|
||||
};
|
||||
|
||||
#endif // VBSPMATHUTIL_H
|
||||
Reference in New Issue
Block a user