Team Fortress 2 Source Code as on 22/4/2020
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.
 
 
 
 
 
 

796 lines
22 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef GL_MODEL_PRIVATE_H
#define GL_MODEL_PRIVATE_H
#ifdef _WIN32
#pragma once
#endif
#include "mathlib/vector4d.h"
#include "tier0/dbg.h"
#include "tier1/utlsymbol.h"
#include "idispinfo.h"
#include "shadowmgr.h"
#include "vcollide.h"
#include "studio.h"
#include "qlimits.h"
#include "host.h"
#include "gl_model.h"
#include "cmodel.h"
#include "bspfile.h"
#include "Overlay.h"
//#include "datamap.h"
#include "surfacehandle.h"
#include "mathlib/compressed_light_cube.h"
#include "datacache/imdlcache.h"
#include "bitmap/cubemap.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
struct studiomeshdata_t;
struct decal_t;
struct msurface1_t;
struct msurfacelighting_t;
struct msurfacenormal_t;
class ITexture;
class CEngineSprite;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
struct mvertex_t
{
Vector position;
};
// !!! if this is changed, it must be changed in asm_draw.h too !!!
struct medge_t
{
unsigned short v[2];
// unsigned int cachededgeoffset;
};
class IMaterial;
class IMaterialVar;
// This is here for b/w compatibility with world surfaces that use
// WorldVertexTransition. We can get rid of it when we rev the engine.
#define TEXINFO_USING_BASETEXTURE2 0x0001
struct mtexinfo_t
{
Vector4D textureVecsTexelsPerWorldUnits[2]; // [s/t] unit vectors in world space.
// [i][3] is the s/t offset relative to the origin.
Vector4D lightmapVecsLuxelsPerWorldUnits[2];
float luxelsPerWorldUnit;
float worldUnitsPerLuxel;
unsigned short flags; // SURF_ flags.
unsigned short texinfoFlags;// TEXINFO_ flags.
IMaterial *material;
mtexinfo_t( mtexinfo_t const& src )
{
// copy constructor needed since Vector4D has no copy constructor
memcpy( this, &src, sizeof(mtexinfo_t) );
}
};
struct mnode_t
{
// common with leaf
int contents; // <0 to differentiate from leafs
// -1 means check the node for visibility
// -2 means don't check the node for visibility
int visframe; // node needs to be traversed if current
mnode_t *parent;
short area; // If all leaves below this node are in the same area, then
// this is the area index. If not, this is -1.
short flags;
VectorAligned m_vecCenter;
VectorAligned m_vecHalfDiagonal;
// node specific
cplane_t *plane;
mnode_t *children[2];
unsigned short firstsurface;
unsigned short numsurfaces;
};
struct mleaf_t
{
public:
// common with node
int contents; // contents mask
int visframe; // node needs to be traversed if current
mnode_t *parent;
short area;
short flags;
VectorAligned m_vecCenter;
VectorAligned m_vecHalfDiagonal;
// leaf specific
short cluster;
short leafWaterDataID;
unsigned short firstmarksurface;
unsigned short nummarksurfaces;
short nummarknodesurfaces;
short unused;
unsigned short dispListStart; // index into displist of first displacement
unsigned short dispCount; // number of displacements in the list for this leaf
};
struct mleafwaterdata_t
{
float surfaceZ;
float minZ;
short surfaceTexInfoID;
short firstLeafIndex;
};
struct mcubemapsample_t
{
Vector origin;
ITexture *pTexture;
unsigned char size; // default (mat_envmaptgasize) if 0, 1<<(size-1) otherwise.
};
typedef struct mportal_s
{
unsigned short *vertList;
int numportalverts;
cplane_t *plane;
unsigned short cluster[2];
// int visframe;
} mportal_t;
typedef struct mcluster_s
{
unsigned short *portalList;
int numportals;
} mcluster_t;
struct mmodel_t
{
Vector mins, maxs;
Vector origin; // for sounds or lights
float radius;
int headnode;
int firstface, numfaces;
};
struct mprimitive_t
{
int type;
unsigned short firstIndex;
unsigned short indexCount;
unsigned short firstVert;
unsigned short vertCount;
};
struct mprimvert_t
{
Vector pos;
float texCoord[2];
float lightCoord[2];
};
typedef dleafambientindex_t mleafambientindex_t;
typedef dleafambientlighting_t mleafambientlighting_t;
struct LightShadowZBufferSample_t
{
float m_flTraceDistance; // how far we traced. 0 = invalid
float m_flHitDistance; // where we hit
};
#define SHADOW_ZBUF_RES 8 // 6 * 64 * 2 * 4 = 3k bytes per light
typedef CCubeMap< LightShadowZBufferSample_t, SHADOW_ZBUF_RES> lightzbuffer_t;
#include "model_types.h"
#define MODELFLAG_MATERIALPROXY 0x0001 // we've got a material proxy
#define MODELFLAG_TRANSLUCENT 0x0002 // we've got a translucent model
#define MODELFLAG_VERTEXLIT 0x0004 // we've got a vertex-lit model
#define MODELFLAG_TRANSLUCENT_TWOPASS 0x0008 // render opaque part in opaque pass
#define MODELFLAG_FRAMEBUFFER_TEXTURE 0x0010 // we need the framebuffer as a texture
#define MODELFLAG_HAS_DLIGHT 0x0020 // need to check dlights
#define MODELFLAG_STUDIOHDR_USES_FB_TEXTURE 0x0100 // persisted from studiohdr
#define MODELFLAG_STUDIOHDR_USES_BUMPMAPPING 0x0200 // persisted from studiohdr
#define MODELFLAG_STUDIOHDR_USES_ENV_CUBEMAP 0x0400 // persisted from studiohdr
#define MODELFLAG_STUDIOHDR_AMBIENT_BOOST 0x0800 // persisted from studiohdr
#define MODELFLAG_STUDIOHDR_DO_NOT_CAST_SHADOWS 0x1000 // persisted from studiohdr
struct worldbrushdata_t
{
int numsubmodels;
int numplanes;
cplane_t *planes;
int numleafs; // number of visible leafs, not counting 0
mleaf_t *leafs;
int numleafwaterdata;
mleafwaterdata_t *leafwaterdata;
int numvertexes;
mvertex_t *vertexes;
int numoccluders;
doccluderdata_t *occluders;
int numoccluderpolys;
doccluderpolydata_t *occluderpolys;
int numoccludervertindices;
int *occludervertindices;
int numvertnormalindices; // These index vertnormals.
unsigned short *vertnormalindices;
int numvertnormals;
Vector *vertnormals;
int numnodes;
mnode_t *nodes;
unsigned short *m_LeafMinDistToWater;
int numtexinfo;
mtexinfo_t *texinfo;
int numtexdata;
csurface_t *texdata;
int numDispInfos;
HDISPINFOARRAY hDispInfos; // Use DispInfo_Index to get IDispInfos..
/*
int numOrigSurfaces;
msurface_t *pOrigSurfaces;
*/
int numsurfaces;
msurface1_t *surfaces1;
msurface2_t *surfaces2;
msurfacelighting_t *surfacelighting;
msurfacenormal_t *surfacenormals;
bool unloadedlightmaps;
int numvertindices;
unsigned short *vertindices;
int nummarksurfaces;
SurfaceHandle_t *marksurfaces;
ColorRGBExp32 *lightdata;
int numworldlights;
dworldlight_t *worldlights;
lightzbuffer_t *shadowzbuffers;
// non-polygon primitives (strips and lists)
int numprimitives;
mprimitive_t *primitives;
int numprimverts;
mprimvert_t *primverts;
int numprimindices;
unsigned short *primindices;
int m_nAreas;
darea_t *m_pAreas;
int m_nAreaPortals;
dareaportal_t *m_pAreaPortals;
int m_nClipPortalVerts;
Vector *m_pClipPortalVerts;
mcubemapsample_t *m_pCubemapSamples;
int m_nCubemapSamples;
int m_nDispInfoReferences;
unsigned short *m_pDispInfoReferences;
mleafambientindex_t *m_pLeafAmbient;
mleafambientlighting_t *m_pAmbientSamples;
#if 0
int numportals;
mportal_t *portals;
int numclusters;
mcluster_t *clusters;
int numportalverts;
unsigned short *portalverts;
int numclusterportals;
unsigned short *clusterportals;
#endif
};
// only models with type "mod_brush" have this data
struct brushdata_t
{
worldbrushdata_t *pShared;
int firstmodelsurface, nummodelsurfaces;
unsigned short renderHandle;
unsigned short firstnode;
};
// only models with type "mod_sprite" have this data
struct spritedata_t
{
int numframes;
int width;
int height;
CEngineSprite *sprite;
};
struct model_t
{
FileNameHandle_t fnHandle;
CUtlString strName;
int nLoadFlags; // mark loaded/not loaded
int nServerCount; // marked at load
IMaterial **ppMaterials; // null-terminated runtime material cache; ((intptr_t*)(ppMaterials))[-1] == nMaterials
modtype_t type;
int flags; // MODELFLAG_???
// volume occupied by the model graphics
Vector mins, maxs;
float radius;
union
{
brushdata_t brush;
MDLHandle_t studio;
spritedata_t sprite;
};
};
//-----------------------------------------------------------------------------
// Decals
//-----------------------------------------------------------------------------
struct decallist_t
{
DECLARE_SIMPLE_DATADESC();
Vector position;
char name[ 128 ];
short entityIndex;
byte depth;
byte flags;
// This is the surface plane that we hit so that we can move certain decals across
// transitions if they hit similar geometry
Vector impactPlaneNormal;
};
inline class IDispInfo *MLeaf_Disaplcement( mleaf_t *pLeaf, int index, worldbrushdata_t *pData = host_state.worldbrush )
{
Assert(index<pLeaf->dispCount);
int dispIndex = pData->m_pDispInfoReferences[pLeaf->dispListStart+index];
return DispInfo_IndexArray( pData->hDispInfos, dispIndex );
}
#define MAXLIGHTMAPS 4
// drawing surface flags
#define SURFDRAW_NOLIGHT 0x00000001 // no lightmap
#define SURFDRAW_NODE 0x00000002 // This surface is on a node
#define SURFDRAW_SKY 0x00000004 // portal to sky
#define SURFDRAW_BUMPLIGHT 0x00000008 // Has multiple lightmaps for bump-mapping
#define SURFDRAW_NODRAW 0x00000010 // don't draw this surface, not really visible
#define SURFDRAW_TRANS 0x00000020 // sort this surface from back to front
#define SURFDRAW_PLANEBACK 0x00000040 // faces away from plane of the node that stores this face
#define SURFDRAW_DYNAMIC 0x00000080 // Don't use a static buffer for this face
#define SURFDRAW_TANGENTSPACE 0x00000100 // This surface needs a tangent space
#define SURFDRAW_NOCULL 0x00000200 // Don't bother backface culling these
#define SURFDRAW_HASLIGHTSYTLES 0x00000400 // has a lightstyle other than 0
#define SURFDRAW_HAS_DISP 0x00000800 // has a dispinfo
#define SURFDRAW_ALPHATEST 0x00001000 // Is alphstested
#define SURFDRAW_NOSHADOWS 0x00002000 // No shadows baby
#define SURFDRAW_NODECALS 0x00004000 // No decals baby
#define SURFDRAW_HAS_PRIMS 0x00008000 // has a list of prims
#define SURFDRAW_WATERSURFACE 0x00010000 // This is a water surface
#define SURFDRAW_UNDERWATER 0x00020000
#define SURFDRAW_ABOVEWATER 0x00040000
#define SURFDRAW_HASDLIGHT 0x00080000 // Has some kind of dynamic light that must be checked
#define SURFDRAW_DLIGHTPASS 0x00100000 // Must be drawn in the dlight pass
#define SURFDRAW_UNUSED2 0x00200000 // unused
#define SURFDRAW_VERTCOUNT_MASK 0xFF000000 // 8 bits of vertex count
#define SURFDRAW_SORTGROUP_MASK 0x00C00000 // 2 bits of sortgroup
#define SURFDRAW_VERTCOUNT_SHIFT 24
#define SURFDRAW_SORTGROUP_SHIFT 22
// NOTE: 16-bytes, preserve size/alignment - we index this alot
struct msurface1_t
{
// garymct - are these needed? - used by decal projection code
int textureMins[2]; // smallest unnormalized s/t position on the surface.
short textureExtents[2]; // ?? s/t texture size, 1..512 for all non-sky surfaces
struct
{
unsigned short numPrims;
unsigned short firstPrimID; // index into primitive list if numPrims > 0
} prims;
};
#pragma pack(1)
struct msurfacenormal_t
{
unsigned int firstvertnormal;
// unsigned short firstvertnormal;
// FIXME: Should I just point to the leaf here since it has this data?????????????
// short fogVolumeID; // -1 if not in fog
};
#pragma pack()
// This is a single cache line (32 bytes)
struct msurfacelighting_t
{
// You read that minus sign right. See the comment below.
ColorRGBExp32 *AvgLightColor( int nLightStyleIndex ) { return m_pSamples - (nLightStyleIndex + 1); }
// Lightmap info
short m_LightmapMins[2];
short m_LightmapExtents[2];
short m_OffsetIntoLightmapPage[2];
int m_nLastComputedFrame; // last frame the surface's lightmap was recomputed
int m_fDLightBits; // Indicates which dlights illuminates this surface.
int m_nDLightFrame; // Indicates the last frame in which dlights illuminated this surface
unsigned char m_nStyles[MAXLIGHTMAPS]; // index into d_lightstylevalue[] for animated lights
// no one surface can be effected by more than 4
// animated lights.
// NOTE: This is tricky. To get this to fit in a single cache line,
// and to save the extra memory of not having to store average light colors for
// lightstyles that are not used, I store between 0 and 4 average light colors +before+
// the samples, depending on how many lightstyles there are. Naturally, accessing
// an average color for an undefined lightstyle on the surface results in undefined results.
// 0->4 avg light colors, *in reverse order from m_nStyles* + [numstyles*surfsize]
ColorRGBExp32 *m_pSamples;
};
const int WORLD_DECAL_HANDLE_INVALID = 0xFFFF;
typedef unsigned short WorldDecalHandle_t;
#pragma pack(1)
// NOTE: 32-bytes. Aligned/indexed often
struct msurface2_t
{
unsigned int flags; // see SURFDRAW_ #defines (only 22-bits right now)
// These are packed in to flags now
//unsigned char vertCount; // number of verts for this surface
//unsigned char sortGroup; // only uses 2 bits, subdivide?
cplane_t *plane; // pointer to shared plane
int firstvertindex; // look up in model->vertindices[] (only uses 17-18 bits?)
WorldDecalHandle_t decals;
ShadowDecalHandle_t m_ShadowDecals; // unsigned short
OverlayFragmentHandle_t m_nFirstOverlayFragment; // First overlay fragment on the surface (short)
short materialSortID;
unsigned short vertBufferIndex;
unsigned short m_bDynamicShadowsEnabled : 1; // Can this surface receive dynamic shadows?
unsigned short texinfo : 15;
IDispInfo *pDispInfo; // displacement map information
int visframe; // should be drawn when node is crossed
};
#pragma pack()
inline unsigned short MSurf_AreDynamicShadowsEnabled( SurfaceHandle_t surfID )
{
return surfID->m_bDynamicShadowsEnabled;
}
inline int MSurf_Index( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = surfID - pData->surfaces2;
Assert(surfaceIndex >= 0 && surfaceIndex < pData->numsurfaces);
return surfaceIndex;
}
inline const SurfaceHandle_t SurfaceHandleFromIndex( int surfaceIndex, const worldbrushdata_t *pData )
{
return &pData->surfaces2[surfaceIndex];
}
inline SurfaceHandle_t SurfaceHandleFromIndex( int surfaceIndex, worldbrushdata_t *pData = host_state.worldbrush )
{
return &pData->surfaces2[surfaceIndex];
}
#if _DEBUG
#define ASSERT_SURF_VALID(surfID) MSurf_Index(surfID)
#else
#define ASSERT_SURF_VALID(surfID)
#endif
inline unsigned int& MSurf_Flags( SurfaceHandle_t surfID )
{
return surfID->flags;
}
inline bool SurfaceHasDispInfo( SurfaceHandle_t surfID )
{
return ( MSurf_Flags( surfID ) & SURFDRAW_HAS_DISP ) ? true : false;
}
inline bool SurfaceHasPrims( SurfaceHandle_t surfID )
{
return ( MSurf_Flags( surfID ) & SURFDRAW_HAS_PRIMS ) ? true : false;
}
inline int& MSurf_VisFrame( SurfaceHandle_t surfID )
{
return surfID->visframe;
}
inline int MSurf_SortGroup( SurfaceHandle_t surfID )
{
return (surfID->flags & SURFDRAW_SORTGROUP_MASK) >> SURFDRAW_SORTGROUP_SHIFT;
}
inline void MSurf_SetSortGroup( SurfaceHandle_t surfID, int sortGroup )
{
unsigned int flags = (sortGroup << SURFDRAW_SORTGROUP_SHIFT) & SURFDRAW_SORTGROUP_MASK;
surfID->flags |= flags;
}
/*
inline int& MSurf_DLightFrame( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfID].dlightframe;
}
*/
inline int& MSurf_DLightBits( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfaceIndex].m_fDLightBits;
}
inline cplane_t& MSurf_Plane( SurfaceHandle_t surfID )
{
return *surfID->plane;
}
inline int& MSurf_FirstVertIndex( SurfaceHandle_t surfID )
{
return surfID->firstvertindex;
}
inline int MSurf_VertCount( SurfaceHandle_t surfID )
{
return (surfID->flags >> SURFDRAW_VERTCOUNT_SHIFT) & 0xFF;
}
inline void MSurf_SetVertCount( SurfaceHandle_t surfID, int vertCount )
{
int flags = (vertCount << SURFDRAW_VERTCOUNT_SHIFT) & SURFDRAW_VERTCOUNT_MASK;
surfID->flags |= flags;
}
inline int *MSurf_TextureMins( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfaces1[surfaceIndex].textureMins;
}
inline short *MSurf_TextureExtents( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfaces1[surfaceIndex].textureExtents;
}
inline short *MSurf_LightmapMins( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfaceIndex].m_LightmapMins;
}
inline short *MSurf_LightmapExtents( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfaceIndex].m_LightmapExtents;
}
inline short MSurf_MaxLightmapSizeWithBorder( SurfaceHandle_t surfID )
{
// ASSERT_SURF_VALID( surfID );
return SurfaceHasDispInfo( surfID ) ? MAX_DISP_LIGHTMAP_DIM_INCLUDING_BORDER : MAX_BRUSH_LIGHTMAP_DIM_INCLUDING_BORDER;
}
inline short MSurf_MaxLightmapSizeWithoutBorder( SurfaceHandle_t surfID )
{
// ASSERT_SURF_VALID( surfID );
return SurfaceHasDispInfo( surfID ) ? MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER : MAX_BRUSH_LIGHTMAP_DIM_WITHOUT_BORDER;
}
inline mtexinfo_t *MSurf_TexInfo( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
return &pData->texinfo[surfID->texinfo];
}
inline WorldDecalHandle_t& MSurf_Decals( SurfaceHandle_t surfID )
{
return surfID->decals;
}
inline bool SurfaceHasDecals( SurfaceHandle_t surfID )
{
return ( MSurf_Decals( surfID ) != WORLD_DECAL_HANDLE_INVALID ) ? true : false;
}
inline ShadowDecalHandle_t& MSurf_ShadowDecals( SurfaceHandle_t surfID )
{
return surfID->m_ShadowDecals;
}
inline ColorRGBExp32 *MSurf_AvgLightColor( SurfaceHandle_t surfID, int nIndex, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfaceIndex].AvgLightColor(nIndex);
}
inline byte *MSurf_Styles( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfaceIndex].m_nStyles;
}
/*
inline int *MSurf_CachedLight( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfID].cached_light;
}
inline short& MSurf_CachedDLight( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfID].cached_dlight;
}
*/
inline unsigned short MSurf_NumPrims( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
if ( SurfaceHasDispInfo( surfID ) || !SurfaceHasPrims( surfID ))
return 0;
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfaces1[surfaceIndex].prims.numPrims;
}
inline unsigned short MSurf_FirstPrimID( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
if ( SurfaceHasDispInfo( surfID ) )
return 0;
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfaces1[surfaceIndex].prims.firstPrimID;
}
inline ColorRGBExp32 *MSurf_Samples( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfaceIndex].m_pSamples;
}
inline IDispInfo *MSurf_DispInfo( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
return surfID->pDispInfo;
}
//inline unsigned short &MSurf_FirstVertNormal( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
inline unsigned int &MSurf_FirstVertNormal( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
Assert( pData->surfacenormals[surfaceIndex].firstvertnormal < MAX_MAP_VERTNORMALINDICES );
return pData->surfacenormals[surfaceIndex].firstvertnormal;
}
inline unsigned short &MSurf_VertBufferIndex( SurfaceHandle_t surfID )
{
return surfID->vertBufferIndex;
}
inline short& MSurf_MaterialSortID( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
return surfID->materialSortID;
}
inline short *MSurf_OffsetIntoLightmapPage( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return pData->surfacelighting[surfaceIndex].m_OffsetIntoLightmapPage;
}
inline VPlane MSurf_GetForwardFacingPlane( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
// ASSERT_SURF_VALID( surfID );
Assert( pData );
return VPlane( MSurf_Plane( surfID).normal, MSurf_Plane( surfID ).dist );
}
inline OverlayFragmentHandle_t &MSurf_OverlayFragmentList( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
return surfID->m_nFirstOverlayFragment;
}
inline msurfacelighting_t *SurfaceLighting( SurfaceHandle_t surfID, worldbrushdata_t *pData = host_state.worldbrush )
{
int surfaceIndex = MSurf_Index(surfID,pData);
Assert( pData );
return &pData->surfacelighting[surfaceIndex];
}
#endif // GL_MODEL_PRIVATE_H