Paranoia2/cl_dll/render/gl_studio.h
2020-08-31 19:50:41 +03:00

744 lines
25 KiB
C++

/*
gl_studio.h - studio model rendering
this code written for Paranoia 2: Savior modification
Copyright (C) 2014 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef GL_STUDIO_H
#define GL_STUDIO_H
#include "pmtrace.h"
#include "studio.h"
#include <utllinkedlist.h>
#include <utlarray.h>
#include <stringlib.h>
#include "gl_decals.h"
#include "gl_studiodecal.h"
#include "trace.h"
#include "bs_defs.h"
#include "ikcontext.h"
#include "jigglebones.h"
#include "tbnfile.h"
#define EVENT_CLIENT 5000 // less than this value it's a server-side studio events
#define MAX_MODEL_MESHES (MAXSTUDIOBODYPARTS * MAXSTUDIOMODELS)
#define SHADE_LAMBERT 1.495f
#define MAXARRAYVERTS 65536 // max vertices per studio submodel
#define MAX_SEQBLENDS 8 // must be power of two
#define MASK_SEQBLENDS (MAX_SEQBLENDS - 1)
#define MF_STATIC_BOUNDS BIT( 0 ) // this model is a env_static. don't recalc bounds every frame
#define MF_CUSTOM_LIGHTGRID BIT( 1 ) // model has special attahaments that was accepted as light probe start points
#define MF_VERTEX_LIGHTING BIT( 2 ) // model has the custom vertex lighting (loading from level)
#define MF_SURFACE_LIGHTING BIT( 3 ) // model has the custom surface lighting (loading from level)
#define MF_VL_BAD_CACHE BIT( 4 ) // for some reasons this model can't be instanced with a vertex lighting (bad crc, mismatch vertexcount etc)
#define MF_INIT_SMOOTHSTAIRS BIT( 5 )
#define MF_ATTACHMENTS_DONE BIT( 6 )
#define MF_POSITION_CHANGED BIT( 7 )
// studiorenderer modes
#define DRAWSTUDIO_NORMAL 0 // as default
#define DRAWSTUDIO_VIEWMODEL 1 // rendeging viewmodel
#define DRAWSTUDIO_HEADSHIELD 2 // headshield or gasmask
#define DRAWSTUDIO_RUNEVENTS 3 // run events of studiomodel
#define LIGHTSTATIC_NONE 0
#define LIGHTSTATIC_VERTEX 1
#define LIGHTSTATIC_SURFACE 2
#define TBNSTATE_INACTIVE 0
#define TBNSTATE_LOADING 1
#define TBNSTATE_GENERATE 2
// holds temporary data
typedef struct
{
int firstvertex;
int numvertices;
int firstindex;
int numindices;
int lightmapnum;
} StudioMesh_t;
// new blending sequence system
typedef struct
{
float blendtime; // time to blend between current and previous sequence
int sequence; // previous sequence number
float cycle; // cycle where sequence was changed
float fadeout;
bool gaitseq;
} mstudioblendseq_t;
typedef struct
{
float frame;
int sequence;
float gaitframe;
int gaitsequence;
// for smooth stair climbing
float stairtime;
float stairoldz;
} mstudiolerp_t;
// source vertex data (106 bytes here)
typedef struct xvert_s
{
Vector vertex; // position
Vector normal; // normal
Vector tangent; // tangent
Vector binormal; // binormal
float stcoord[4]; // ST texture coords
float lmcoord0[4]; // LM texture coords
float lmcoord1[4]; // LM texture coords
char boneid[4]; // control bones
byte weight[4]; // boneweights
float light[MAXLIGHTMAPS]; // packed color
float deluxe[MAXLIGHTMAPS]; // packed lightdir
byte styles[MAXLIGHTMAPS]; // lightstyles
word m_MeshVertexIndex; // index into the mesh's vertex list (decals only)
} svert_t;
typedef void (*pfnCreateStudioBuffer)( vbomesh_t *pOut, svert_t *arrayxvert );
typedef void (*pfnBindStudioBuffer)( vbomesh_t *pOut, int attrFlags );
typedef struct
{
pfnCreateStudioBuffer CreateBuffer;
pfnBindStudioBuffer BindBuffer;
const char* BufferName; // debug
} mesh_loader_t;
class CBaseBoneSetup : public CStudioBoneSetup
{
public:
virtual void debugMsg( char *szFmt, ... );
virtual mstudioanim_t *GetAnimSourceData( mstudioseqdesc_t *pseqdesc );
virtual void debugLine( const Vector& origin, const Vector& dest, int r, int g, int b, bool noDepthTest = false, float duration = 0.0f );
};
/*
====================
CStudioModelRenderer
====================
*/
class CStudioModelRenderer
{
public:
// Construction/Destruction
CStudioModelRenderer( void );
virtual ~CStudioModelRenderer( void );
// Initialization
void Init( void );
void VidInit( void );
// Look up animation data for sequence
mstudioanim_t *StudioGetAnim ( model_t *pModel, mstudioseqdesc_t *pseqdesc );
// precache vertexlit mesh
void CreateStudioCacheVL( const char *modelname, int cacheID );
// precache lightmapped mesh
void CreateStudioCacheFL( const char *modelname, int cacheID );
// throw all the meshes when the engine is shutting down
void FreeStudioCacheVL( void );
void FreeStudioCacheFL( void );
private:
// Local interfaces
// Extract bbox from current sequence
int StudioExtractBbox ( studiohdr_t *phdr, int sequence, Vector &mins, Vector &maxs );
// Compute a full bounding box for current sequence
int StudioComputeBBox ( void );
float CalcStairSmoothValue( float oldz, float newz, float smoothtime, float smoothvalue );
const Vector StudioGetOrigin( void );
// Interpolate model position and angles and set up matrices
void StudioSetUpTransform( void );
// Set up model bone positions
void StudioSetupBones( void );
// Find final attachment points
void StudioCalcAttachments( matrix3x4 bones[] );
void AddBlendSequence( int oldseq, int newseq, float prevframe, bool gaitseq = false );
void BlendSequence( Vector pos[], Vector4D q[], mstudioblendseq_t *pseqblend );
void UpdateIKLocks( CIKContext *pIK );
void CalculateIKLocks( CIKContext *pIK );
// Merge cached bones with current bones for model
void StudioMergeBones( matrix3x4 &transform, matrix3x4 bones[], matrix3x4 cached_bones[], model_t *pModel, model_t *pParentModel );
// Determine interpolation fraction
float StudioEstimateInterpolant( void );
// Determine current gaitframe for rendering
float StudioEstimateGaitFrame ( mstudioseqdesc_t *pseqdesc );
// Determine current frame for rendering
float StudioEstimateFrame ( mstudioseqdesc_t *pseqdesc );
void StudioInterpolateControllers( cl_entity_t *e, float dadt );
void StudioInterpolatePoseParams( cl_entity_t *e, float dadt );
// Apply special effects to transform matrix
void StudioFxTransform( cl_entity_t *ent, matrix3x4 &transform );
void ComputeSkinMatrix( mstudioboneweight_t *boneweights, const matrix3x4 worldtransform[], matrix3x4 &result );
void ComputeSkinMatrix( svert_t *vertex, const matrix3x4 worldtransform[], matrix3x4 &result );
int StudioCheckLOD( void );
//calc bodies and get pointers to him
int StudioSetupModel ( int bodypart, mstudiomodel_t **ppsubmodel, msubmodel_t **ppvbomodel );
void DrawMeshFromBuffer( const vbomesh_t *mesh );
void DeleteVBOMesh( vbomesh_t *mesh );
// Process studio client events
void StudioClientEvents( void );
void StudioLighting( float *lv, int bone, int flags, const Vector &normal );
void StudioStaticLight( cl_entity_t *ent, mstudiolight_t *light );
void CacheVertexLight( cl_entity_t *ent );
void CacheSurfaceLight( cl_entity_t *ent );
void StudioFormatAttachment( Vector &point );
word ChooseStudioProgram( studiohdr_t *phdr, mstudiomaterial_t *mat, bool lightpass );
void AddMeshToDrawList( studiohdr_t *phdr, vbomesh_t *mesh, bool lightpass );
void AddBodyPartToDrawList( studiohdr_t *phdr, mbodypart_t *bodyparts, int bodypart, bool lightpass );
bool CheckBoneCache( float f );
word ShaderSceneForward( mstudiomaterial_t *mat, int lightmode, bool bone_weighting, int numbones );
word ShaderLightForward( CDynLight *dl, mstudiomaterial_t *mat, bool bone_weighting, int numbones );
word ShaderSceneDeferred( mstudiomaterial_t *mat, bool bone_weighting, int numbones );
word ShaderLightDeferred( mstudiomaterial_t *mat, bool bone_weighting, int numbones );
word ShaderSceneDepth( mstudiomaterial_t *mat, bool bone_weighting, int numbones );
word ShaderDecalForward( studiodecal_t *pDecal, bool has_vertexlight );
// Debug drawing
void StudioDrawDebug( cl_entity_t *e );
void StudioDrawHulls( int iHitbox = -1 );
void StudioDrawAbsBBox( void );
void StudioDrawBones( void );
void StudioDrawAttachments( bool bCustomFov );
int HeadShieldThink( void );
// intermediate structure. Used only for build unique submodels
struct TmpModel_t
{
char name[64];
mstudiomodel_t *pmodel;
msubmodel_t *pout;
};
struct BoneCache_t
{
float frame; // product of StudioEstimateFrame, not a curstate.frame!
short sequence;
byte blending[2];
byte controller[4];
byte mouthopen;
matrix3x4 transform; // cached transform because ent->angles\ent->origin doesn't contains interpolation info
float poseparam[MAXSTUDIOPOSEPARAM];
// special fields for player
short gaitsequence;
float gaitframe;
};
struct StudioAttachment_t
{
char name[MAXSTUDIONAME];
matrix3x4 local; // local position
Vector origin; // attachment pos
Vector angles; // VectorAngles
Vector dir; // old method
};
typedef struct
{
int m_VertCount; // Number of used vertices
int m_Indices[2][7]; // Indices into the clip verts array of the used vertices
bool m_Pass; // Helps us avoid copying the m_Indices array by using double-buffering
int m_ClipVertCount; // Add vertices we've started with and had to generate due to clipping
svert_t m_ClipVerts[16];
int m_ClipFlags[16]; // Union of the decal triangle clip flags above for each vert
} DecalClipState_t;
typedef CUtlArray<studiodecal_t> StudioDecalList_t;
typedef CUtlArray<int> CIntVector;
enum
{
MESHLOADER_BASE = 0,
MESHLOADER_BASEBUMP,
MESHLOADER_VLIGHT,
MESHLOADER_VLIGHTBUMP,
MESHLOADER_WEIGHT,
MESHLOADER_WEIGHTBUMP,
MESHLOADER_LIGHTMAP,
MESHLOADER_LIGHTMAPBUMP,
MESHLOADER_GENERIC,
MESHLOADER_COUNT,
};
struct ModelInstance_t
{
cl_entity_t *m_pEntity;
// Need to store off the model. When it changes, we lose all instance data..
model_t *m_pModel;
StudioDecalList_t m_DecalList; // new decal list for each instance
int m_DecalCount; // just used as timestamp for calculate decal depth
int info_flags;
// NOTE: each decal applied while model has some pose
// keep it in this array for each model and dump into
// savefile to properly restored decal positions
CUtlArray<modelstate_t> pose_stamps;
mstudiocache_t *m_VlCache; // valid only for env_statics that have vertexlight data
mstudiocache_t *m_FlCache; // valid only for env_statics that have surfacelight data
byte styles[MAXLIGHTMAPS];// actual only if MF_VERTEX_LIGHTING|MF_SURFACE_LIGHTING bit is set
// bounds info
Vector absmin;
Vector absmax;
float radius;
Vector origin; // transformed origin
BoneCache_t bonecache; // just compare to avoid recalc bones every frame
// attachments
StudioAttachment_t attachment[MAXSTUDIOATTACHMENTS];
int numattachments;
byte m_controller[MAXSTUDIOCONTROLLERS];
float m_poseparameter[MAXSTUDIOPOSEPARAM]; // blends for traditional studio models
float m_oldposeparams[MAXSTUDIOPOSEPARAM]; // latched values
mstudioblendseq_t m_seqblend[MAX_SEQBLENDS];
int m_current_seqblend;
// sequence blends stuff
mstudiolerp_t lerp;
CJiggleBones *m_pJiggleBones;
CIKContext m_ik;
// attached cubemaps
mcubemap_t *cubemap[2];
float lerpFactor;
mstudiomaterial_t *materials; // shaders cache
// light interpolation
mstudiolight_t oldlight;
mstudiolight_t newlight;
mstudiolight_t light; // cached light values
float lighttimecheck;
bool light_update;
byte lights[MAXDYNLIGHTS]; // dynamic lights cache
matrix3x4 m_protationmatrix;
matrix3x4 m_pbones[MAXSTUDIOBONES]; // bone to pose
matrix3x4 m_pwpnbones[MAXSTUDIOBONES];
Vector4D m_glstudiobones[MAXSTUDIOBONES*3]; // GLSL-friendly compacted matrix4x3
Vector4D m_glweaponbones[MAXSTUDIOBONES*3]; // GLSL-friendly compacted matrix4x3
// GLSL cached arrays
Vector4D m_studioquat[MAXSTUDIOBONES];
Vector m_studiopos[MAXSTUDIOBONES];
Vector4D m_weaponquat[MAXSTUDIOBONES];
Vector m_weaponpos[MAXSTUDIOBONES];
GLfloat m_glmatrix[16];
unsigned int cached_frame; // to avoid compute bones more than once per frame
unsigned int visframe; // model is visible this frame
};
struct DecalBuildInfo_t
{
// this part is constant all time while decal is build
const DecalGroupEntry* m_pTexInfo;
modelstate_t* modelState;
dmodelvertlight_t* modelLight;
Vector vecLocalNormal;
Vector vecLocalEnd;
Vector2D vecDecalScale;
bool m_UseClipVert;
int decalDepth;
byte decalFlags;
int poseState;
studiodecal_t *current;
float m_Radius;
// this part is changed for each mesh
vbomesh_t* m_pModelMesh;
StudioMesh_t* m_pDecalMesh;
dvertlight_t* m_pVertexLight;
DecalVertexInfo_t* m_pVertexInfo;
CUtlArray<svert_t> m_Vertices;
CUtlArray<unsigned int> m_Indices;
};
// keep model instances for each entity
CUtlLinkedList< ModelInstance_t, word > m_ModelInstances;
// decal stuff
bool ComputePoseToDecal( const Vector &vecStart, const Vector &vecEnd );
void AddDecalToModel( DecalBuildInfo_t& buildInfo );
void AddDecalToMesh( DecalBuildInfo_t& buildInfo );
void AllocDecalForMesh( DecalBuildInfo_t& build );
void ProjectDecalOntoMesh( DecalBuildInfo_t& build );
bool IsFrontFacing( const svert_t *vert );
void DecalCreateBuffer( DecalBuildInfo_t& build, studiodecal_t *pDecal );
bool TransformToDecalSpace( DecalBuildInfo_t& build, const svert_t *vert, Vector2D& uv );
matrix3x3 GetDecalRotateTransform( byte vertexBone );
void AddTriangleToDecal( DecalBuildInfo_t& build, int i1, int i2, int i3 );
int ComputeClipFlags( Vector2D const& uv );
bool ClipDecal( DecalBuildInfo_t& build, int i1, int i2, int i3, int *pClipFlags );
void ConvertMeshVertexToDecalVertex( DecalBuildInfo_t& build, int vertIndex, svert_t *out );
void ClipTriangleAgainstPlane( DecalClipState_t& state, int normalInd, int flag, float val );
int IntersectPlane( DecalClipState_t& state, int start, int end, int normalInd, float val );
word AddVertexToDecal( DecalBuildInfo_t& build, int vertIndex );
word AddVertexToDecal( DecalBuildInfo_t& build, svert_t *vert );
void AddClippedDecalToTriangle( DecalBuildInfo_t& build, DecalClipState_t& clipState );
void ComputeDecalTBN( DecalBuildInfo_t& build );
void PurgeDecals( ModelInstance_t *inst );
void PurgeDecals( cl_entity_t *pEnt );
bool StudioSetEntity( cl_entity_t *pEnt );
bool StudioSetEntity( CSolidEntry *entry );
bool IsModelInstanceValid( ModelInstance_t *inst );
bool StudioSetupInstance( void );
void DestroyInstance( word handle );
void SetDecalUniforms( studiodecal_t *pDecal );
void DrawDecal( CSolidEntry *entry, GLenum cull = GL_FRONT );
mstudiocache_t *CreateStudioCache( void *dml = NULL, int lightmode = LIGHTSTATIC_NONE );
void DeleteStudioCache( mstudiocache_t **ppcache );
void DestroyMeshCache( void );
void CreateStudioCacheVL( dmodelvertlight_t *dml, int cacheID );
void CreateStudioCacheFL( dmodelfacelight_t *dml, int cacheID );
void PrecacheStudioShaders( void );
void LoadStudioMaterials( void );
void FreeStudioMaterials( void );
void UpdateInstanceMaterials( void );
void ClearInstanceData( bool create );
// set uniforms data for specified shader
void DrawSingleMesh( CSolidEntry *mesh, bool force );
void SetupSubmodelVerts( const mstudiomodel_t *pSubModel, const matrix3x4 bones[], void *dml, int lightmode );
void MeshCreateBuffer( vbomesh_t *pDst, const mstudiomesh_t *pSrc, const StudioMesh_t *pMeshInfo, int lightmode );
void AllocLightmapsForMesh( StudioMesh_t *pCurMesh, const dmodelfacelight_t *dfl );
bool CalcLightmapAxis( mstudiosurface_t *surf, const dfacelight_t *fl, const dmodelfacelight_t *dfl );
static void CreateBufferBaseGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferBaseGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferBaseBumpGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferBaseBumpGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferVLightGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferVLightGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferVLightBumpGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferVLightBumpGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferWeightGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferWeightGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferWeightBumpGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferWeightBumpGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferLightMapGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferLightMapGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferLightMapBumpGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferLightMapBumpGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferGenericGL21( vbomesh_t *pOut, svert_t *arrayxvert );
static void CreateBufferGenericGL30( vbomesh_t *pOut, svert_t *arrayxvert );
static void BindBufferBaseGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferBaseGL30( vbomesh_t *pOut, int attrFlags );
static void BindBufferBaseBumpGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferBaseBumpGL30( vbomesh_t *pOut, int attrFlags );
static void BindBufferVLightGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferVLightGL30( vbomesh_t *pOut, int attrFlags );
static void BindBufferVLightBumpGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferVLightBumpGL30( vbomesh_t *pOut, int attrFlags );
static void BindBufferWeightGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferWeightGL30( vbomesh_t *pOut, int attrFlags );
static void BindBufferWeightBumpGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferWeightBumpGL30( vbomesh_t *pOut, int attrFlags );
static void BindBufferLightMapGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferLightMapGL30( vbomesh_t *pOut, int attrFlags );
static void BindBufferLightMapBumpGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferLightMapBumpGL30( vbomesh_t *pOut, int attrFlags );
static void BindBufferGenericGL21( vbomesh_t *pOut, int attrFlags );
static void BindBufferGenericGL30( vbomesh_t *pOut, int attrFlags );
static void CreateIndexBuffer( vbomesh_t *pOut, unsigned int *arrayelems );
static void BindIndexBuffer( vbomesh_t *pOut );
static int SortSolidMeshes( const CSolidEntry *a, const CSolidEntry *b );
unsigned int ComputeAttribFlags( int numbones, bool has_bumpmap, bool has_boneweights, bool has_vertexlight, bool has_lightmap );
unsigned int SelectMeshLoader( int numbones, bool has_bumpmap, bool has_boneweights, bool has_vertexlight, bool has_lightmap );
static mesh_loader_t m_pfnMeshLoaderGL21[MESHLOADER_COUNT];
static mesh_loader_t m_pfnMeshLoaderGL30[MESHLOADER_COUNT];
bool m_fShootDecal; // disable all interpolations and bonecache
float m_flViewmodelFov; // custom fov for viewmodel
int m_iDrawModelType; // various modes of rendering
// Cvars that studio model code needs to reference
cvar_t *m_pCvarHiModels; // Use high quality models?
cvar_t *m_pCvarDrawViewModel;
cvar_t *m_pCvarHand; // handness
cvar_t *m_pCvarViewmodelFov;
cvar_t *m_pCvarHeadShieldFov;
cvar_t *m_pCvarLegsOffset;
cvar_t *m_pCvarDrawLegs;
cvar_t *m_pCvarCompatible;
cvar_t *m_pCvarLodScale;
cvar_t *m_pCvarLodBias;
CBaseBoneSetup m_boneSetup;
// current mesh material
mstudiomaterial_t *m_pCurrentMaterial;
ModelInstance_t *m_pModelInstance;
// Pointer to header block for studio model data
studiohdr_t *m_pStudioHeader;
mstudiocache_t *m_pStudioCache; // only valid while mesh is build
msubmodel_t *m_pVboModel;
mstudiomodel_t *m_pSubModel;
StudioMesh_t m_pTempMesh[MAXSTUDIOSKINS]; // temp structure
// used by PushEntity\PopEntity
entity_state_t m_savestate;
Vector m_saveorigin;
Vector m_saveangles;
Vector m_bonelightvecs[MAXSTUDIOBONES]; // debug used this
Vector m_arrayverts[MAXARRAYVERTS];
svert_t m_arrayxvert[MAXARRAYVERTS];
dmodeltbn_t *m_tbnverts; // variable sized
unsigned int m_arrayelems[MAXARRAYVERTS*3];
unsigned int m_nNumArrayVerts;
unsigned int m_nNumArrayElems;
unsigned int m_nNumLightVerts;
unsigned int m_nNumLightFaces;
unsigned int m_nNumTBNVerts;
unsigned int m_nNumTempVerts; // used to conversion to fan sequence
// decal building stuff
matrix3x4 m_pdecaltransform[MAXSTUDIOBONES]; // decal->world
matrix3x4 m_pworldtransform[MAXSTUDIOBONES]; // world->decal
// firstperson legs stuff
model_t *m_pPlayerLegsModel;
int m_iTBNState;
public:
void DestroyAllModelInstances( void );
int StudioGetBounds( cl_entity_t *e, Vector bounds[2] );
int StudioGetBounds( CSolidEntry *entry, Vector bounds[2] );
bool StudioLoadTBN( void );
bool StudioSaveTBN( void );
void PushEntityState( cl_entity_t *ent );
void PopEntityState( cl_entity_t *ent );
void EntityToModelState( modelstate_t *state, const cl_entity_t *ent );
void ModelStateToEntity( cl_entity_t *ent, const modelstate_t *state );
void StudioDecalShoot( const Vector &vecNorm, const Vector &vecEnd, const char *name, cl_entity_t *ent, int flags, modelstate_t *state );
void StudioDecalShoot( struct pmtrace_s *tr, const char *name, bool visent = false );
int StudioDecalList( decallist_t *pList, int count );
void StudioClearDecals( void );
void RemoveAllDecals( int entityIndex );
void UpdateLatchedVars( cl_entity_t *e, qboolean reset );
void ProcessUserData( model_t *mod, qboolean create, const byte *buffer );
void LoadLocalMatrix( int bone, mstudioboneinfo_t *boneinfo );
void AddStudioModelToDrawList( cl_entity_t *e, bool update = false );
void StudioGetAttachment( const cl_entity_t *ent, int iAttachment, Vector *pos, Vector *ang, Vector *dir );
// Process viewmodel events (at start the frame so muzzleflashes will be correct added)
void RunViewModelEvents( void );
bool ComputeCustomFov( matrix4x4 &projMatrix, matrix4x4 &worldViewProjMatrix );
void RestoreNormalFov( matrix4x4 &projMatrix, matrix4x4 &worldViewProjMatrix );
// Draw view model (at end the frame)
void DrawViewModel( void );
// draw head shield (after viewmodel)
void DrawHeadShield( void );
void RenderDeferredStudioList( void );
void RenderSolidStudioList( void );
void RenderShadowStudioList( void );
void RenderDebugStudioList( bool bViewModel );
void RenderDynLightList( bool solid );
void RenderTransMesh( CTransEntry *entry );
void BuildMeshListForLight( CDynLight *pl, bool solid );
void DrawLightForMeshList( CDynLight *pl );
int CacheCount( void ) { return m_ModelInstances.Count(); }
void ClearLightCache( void );
};
extern CStudioModelRenderer g_StudioRenderer;
// implementation of drawing funcs
inline void R_RunViewmodelEvents( void ) { g_StudioRenderer.RunViewModelEvents(); }
inline void R_DrawViewModel( void ) { g_StudioRenderer.DrawViewModel(); }
inline void R_DrawHeadShield( void ) { g_StudioRenderer.DrawHeadShield(); }
inline void R_ProcessStudioData( model_t *mod, qboolean create, const byte *buffer )
{
if( mod->type == mod_studio )
g_StudioRenderer.ProcessUserData( mod, create, buffer );
}
inline int R_CreateStudioDecalList( decallist_t *pList, int count )
{
return g_StudioRenderer.StudioDecalList( pList, count );
}
inline void R_ClearStudioDecals( void )
{
g_StudioRenderer.StudioClearDecals();
}
inline int R_StudioGetBounds( cl_entity_t *e, Vector bounds[2] )
{
return g_StudioRenderer.StudioGetBounds( e, bounds );
}
inline int R_StudioGetBounds( CSolidEntry *entry, Vector bounds[2] )
{
return g_StudioRenderer.StudioGetBounds( entry, bounds );
}
inline void R_RenderDeferredStudioList( void )
{
g_StudioRenderer.RenderDeferredStudioList();
}
inline void R_RenderSolidStudioList( void )
{
g_StudioRenderer.RenderSolidStudioList();
}
inline void R_RenderTransMesh( CTransEntry *entry )
{
g_StudioRenderer.RenderTransMesh( entry );
}
inline void R_RenderLightForTransMeshes( void )
{
g_StudioRenderer.RenderDynLightList( false );
}
inline void R_RenderShadowStudioList( void )
{
g_StudioRenderer.RenderShadowStudioList();
}
inline void R_RenderDebugStudioList( bool bViewModel )
{
g_StudioRenderer.RenderDebugStudioList( bViewModel );
}
inline void R_AddStudioToDrawList( cl_entity_t *e, bool update = false )
{
g_StudioRenderer.AddStudioModelToDrawList( e, update );
}
inline void R_StudioClearLightCache( void )
{
g_StudioRenderer.ClearLightCache();
}
inline void R_StudioAttachmentPosAng( const cl_entity_t *ent, int num, Vector *pos, Vector *ang )
{
g_StudioRenderer.StudioGetAttachment( ent, num, pos, ang, NULL );
}
inline void R_StudioAttachmentPosDir( const cl_entity_t *ent, int num, Vector *pos, Vector *dir )
{
g_StudioRenderer.StudioGetAttachment( ent, num, pos, NULL, dir );
}
inline Vector R_StudioAttachmentPos( const cl_entity_t *ent, int num )
{
Vector pos = g_vecZero;
g_StudioRenderer.StudioGetAttachment( ent, num, &pos, NULL, NULL );
return pos;
}
inline Vector R_StudioAttachmentAng( const cl_entity_t *ent, int num )
{
Vector ang = g_vecZero;
g_StudioRenderer.StudioGetAttachment( ent, num, NULL, &ang, NULL );
return ang;
}
inline void R_UpdateLatchedVars( cl_entity_t *e, qboolean reset )
{
g_StudioRenderer.UpdateLatchedVars( e, reset );
}
#endif// GL_STUDIO_H