1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#ifndef STUDIORENDERCONTEXT_H
#define STUDIORENDERCONTEXT_H
#ifdef _WIN32
#pragma once
#endif
#include "istudiorender.h"
#include "tier3/tier3.h"
#include "studio.h"
#include "tier1/delegates.h"
#include "tier1/memstack.h"
#include "studiorender.h"
//-----------------------------------------------------------------------------
// Foward declarations
//-----------------------------------------------------------------------------
class IStudioDataCache;
class CStudioRender;
//-----------------------------------------------------------------------------
// Global interfaces
//-----------------------------------------------------------------------------
extern IStudioDataCache *g_pStudioDataCache;
extern CStudioRender *g_pStudioRenderImp;
IMaterial* GetModelSpecificDecalMaterial( IMaterial* pDecalMaterial );
//-----------------------------------------------------------------------------
// Internal config structure
//-----------------------------------------------------------------------------
struct StudioRenderConfigInternal_t : public StudioRenderConfig_t
{
bool m_bSupportsVertexAndPixelShaders : 1;
bool m_bSupportsOverbright : 1;
bool m_bEnableHWMorph : 1;
bool m_bStatsMode : 1;
};
//-----------------------------------------------------------------------------
// All the data needed to render a studiomodel
//-----------------------------------------------------------------------------
struct FlexWeights_t
{
float *m_pFlexWeights;
float *m_pFlexDelayedWeights;
};
struct StudioRenderContext_t
{
StudioRenderConfigInternal_t m_Config;
Vector m_ViewTarget;
Vector m_ViewOrigin;
Vector m_ViewRight;
Vector m_ViewUp;
Vector m_ViewPlaneNormal;
Vector4D m_LightBoxColors[6];
LightDesc_t m_LocalLights[MAXLOCALLIGHTS];
int m_NumLocalLights;
float m_ColorMod[3];
float m_AlphaMod;
IMaterial* m_pForcedMaterial;
OverrideType_t m_nForcedMaterialType;
};
//-----------------------------------------------------------------------------
// Helper to queue up calls if necessary
//-----------------------------------------------------------------------------
#define QUEUE_STUDIORENDER_CALL( FuncName, ClassName, pObject, ... ) \
CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); \
ICallQueue *pCallQueue = pRenderContext->GetCallQueue(); \
if ( !pCallQueue || studio_queue_mode.GetInt() == 0 ) \
{ \
pObject->FuncName( __VA_ARGS__ ); \
} \
else \
{ \
pCallQueue->QueueCall( pObject, &ClassName::FuncName, ##__VA_ARGS__ ); \
}
#define QUEUE_STUDIORENDER_CALL_RC( FuncName, ClassName, pObject, pRenderContext, ... ) \
ICallQueue *pCallQueue = pRenderContext->GetCallQueue(); \
if ( !pCallQueue || studio_queue_mode.GetInt() == 0 ) \
{ \
pObject->FuncName( __VA_ARGS__ ); \
} \
else \
{ \
pCallQueue->QueueCall( pObject, &ClassName::FuncName, ##__VA_ARGS__ ); \
}
//-----------------------------------------------------------------------------
// Implementation of IStudioRender
//-----------------------------------------------------------------------------
class CStudioRenderContext : public CTier3AppSystem< IStudioRender >
{
typedef CTier3AppSystem< IStudioRender > BaseClass;
// Methods of IAppSystem
public:
virtual bool Connect( CreateInterfaceFn factory );
virtual void Disconnect();
virtual void *QueryInterface( const char *pInterfaceName );
virtual InitReturnVal_t Init();
virtual void Shutdown();
// Methods of IStudioRender
public:
virtual void BeginFrame( void );
virtual void EndFrame( void );
virtual void Mat_Stub( IMaterialSystem *pMatSys );
virtual void UpdateConfig( const StudioRenderConfig_t& config );
virtual void GetCurrentConfig( StudioRenderConfig_t& config );
virtual bool LoadModel(studiohdr_t *pStudioHdr, void *pVtxData, studiohwdata_t *pHardwareData);
virtual void UnloadModel( studiohwdata_t *pHardwareData );
virtual void RefreshStudioHdr( studiohdr_t* pStudioHdr, studiohwdata_t* pHardwareData );
virtual void SetEyeViewTarget( const studiohdr_t *pStudioHdr, int nBodyIndex, const Vector& worldPosition );
virtual void SetAmbientLightColors( const Vector *pAmbientOnlyColors );
virtual void SetAmbientLightColors( const Vector4D *pAmbientOnlyColors );
virtual void SetLocalLights( int numLights, const LightDesc_t *pLights );
virtual int GetNumAmbientLightSamples();
virtual const Vector *GetAmbientLightDirections();
virtual void SetViewState( const Vector& viewOrigin, const Vector& viewRight, const Vector& viewUp, const Vector& viewPlaneNormal );
virtual int GetNumLODs( const studiohwdata_t &hardwareData ) const;
virtual float GetLODSwitchValue( const studiohwdata_t &hardwareData, int lod ) const;
virtual void SetLODSwitchValue( studiohwdata_t &hardwareData, int lod, float switchValue );
virtual void SetColorModulation( const float* pColor );
virtual void SetAlphaModulation( float alpha );
virtual void DrawModel( DrawModelResults_t *pResults, const DrawModelInfo_t& info, matrix3x4_t *pCustomBoneToWorld, float *pFlexWeights, float *pFlexDelayedWeights, const Vector& origin, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL );
virtual void DrawModelArray( const DrawModelInfo_t &drawInfo, int arrayCount, model_array_instance_t *pInstanceData, int instanceStride, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL );
virtual void DrawModelStaticProp( const DrawModelInfo_t& info, const matrix3x4_t &modelToWorld, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL );
virtual void DrawStaticPropDecals( const DrawModelInfo_t &drawInfo, const matrix3x4_t &modelToWorld );
virtual void DrawStaticPropShadows( const DrawModelInfo_t &drawInfo, const matrix3x4_t &modelToWorld, int flags );
virtual void ForcedMaterialOverride( IMaterial *newMaterial, OverrideType_t nOverrideType = OVERRIDE_NORMAL );
DELEGATE_TO_OBJECT_1( StudioDecalHandle_t, CreateDecalList, studiohwdata_t *, g_pStudioRenderImp );
virtual void DestroyDecalList( StudioDecalHandle_t handle );
virtual void AddDecal( StudioDecalHandle_t handle, studiohdr_t *pStudioHdr, matrix3x4_t *pBoneToWorld, const Ray_t & ray, const Vector& decalUp, IMaterial* pDecalMaterial, float radius, int body, bool noPokethru, int maxLODToDecal = ADDDECAL_TO_ALL_LODS );
virtual void ComputeLighting( const Vector* pAmbient, int lightCount, LightDesc_t* pLights, const Vector& pt, const Vector& normal, Vector& lighting );
virtual void ComputeLightingConstDirectional( const Vector* pAmbient, int lightCount, LightDesc_t* pLights, const Vector& pt, const Vector& normal, Vector& lighting, float flDirectionalAmount );
virtual void AddShadow( IMaterial* pMaterial, void* pProxyData, FlashlightState_t *pFlashlightState, VMatrix *pWorldToTexture, ITexture *pFlashlightDepthTexture );
virtual void ClearAllShadows();
virtual int ComputeModelLod( studiohwdata_t* pHardwareData, float flUnitSphereSize, float *pMetric = NULL );
virtual void GetPerfStats( DrawModelResults_t *pResults, const DrawModelInfo_t &info, CUtlBuffer *pSpewBuf = NULL ) const;
virtual void GetTriangles( const DrawModelInfo_t& info, matrix3x4_t *pBoneToWorld, GetTriangles_Output_t &out );
virtual int GetMaterialList( studiohdr_t *pStudioHdr, int count, IMaterial** ppMaterials );
virtual int GetMaterialListFromBodyAndSkin( MDLHandle_t studio, int nSkin, int nBody, int nCountOutputMaterials, IMaterial** ppOutputMaterials );
virtual matrix3x4_t* LockBoneMatrices( int nCount );
virtual void UnlockBoneMatrices();
virtual void LockFlexWeights( int nWeightCount, float **ppFlexWeights, float **ppFlexDelayedWeights = NULL );
virtual void UnlockFlexWeights();
virtual void GetMaterialOverride( IMaterial** ppOutForcedMaterial, OverrideType_t* pOutOverrideType );
// Other public methods
public:
CStudioRenderContext();
virtual ~CStudioRenderContext();
private:
// Load, unload materials
void LoadMaterials( studiohdr_t *phdr, OptimizedModel::FileHeader_t *, studioloddata_t &lodData, int lodID );
// Determines material flags
void ComputeMaterialFlags( studiohdr_t *phdr, studioloddata_t &lodData, IMaterial *pMaterial );
// Creates, destroys static meshes
void R_StudioCreateStaticMeshes( studiohdr_t *pStudioHdr, OptimizedModel::FileHeader_t* pVtxHdr,
studiohwdata_t *pStudioHWData, int lodID, int *pColorMeshID );
void R_StudioCreateSingleMesh( studiohdr_t *pStudioHdr, studioloddata_t *pStudioLodData,
mstudiomesh_t* pMesh, OptimizedModel::MeshHeader_t* pVtxMesh, int numBones,
studiomeshdata_t* pMeshData, int *pColorMeshID );
void R_StudioDestroyStaticMeshes( int numStudioMeshes, studiomeshdata_t **ppStudioMeshes );
// Determine if any strip groups shouldn't be morphed
void DetermineHWMorphing( mstudiomodel_t *pModel, OptimizedModel::ModelLODHeader_t *pVtxLOD );
// Count deltas affecting a particular stripgroup
int CountDeltaFlexedStripGroups( mstudiomodel_t *pModel, OptimizedModel::ModelLODHeader_t *pVtxLOD );
// Count vertices affected by deltas in a particular strip group
int CountFlexedVertices( mstudiomesh_t* pMesh, OptimizedModel::StripGroupHeader_t* pStripGroup );
// Builds morph data
void R_StudioBuildMorph( studiohdr_t *pStudioHdr, studiomeshgroup_t* pMeshGroup, mstudiomesh_t* pMesh,
OptimizedModel::StripGroupHeader_t *pStripGroup );
// Builds the decal bone remap for a particular mesh
void ComputeHWMorphDecalBoneRemap( studiohdr_t *pStudioHdr, OptimizedModel::FileHeader_t *pVtxHdr, studiohwdata_t *pStudioHWData, int nLOD );
void BuildDecalBoneMap( studiohdr_t *pStudioHdr, int *pUsedBones, int *pBoneRemap, int *pMaxBoneCount, mstudiomesh_t* pMesh, OptimizedModel::StripGroupHeader_t* pStripGroup );
// Helper methods used to construct static meshes
int GetNumBoneWeights( const OptimizedModel::StripGroupHeader_t *pGroup );
VertexFormat_t CalculateVertexFormat( const studiohdr_t *pStudioHdr, const studioloddata_t *pStudioLodData,
const mstudiomesh_t* pMesh, OptimizedModel::StripGroupHeader_t *pGroup, bool bIsHwSkinned );
bool MeshNeedsTangentSpace( studiohdr_t *pStudioHdr, studioloddata_t *pStudioLodData, mstudiomesh_t* pMesh );
void R_StudioBuildMeshGroup( const char *pModelName, bool bNeedsTangentSpace, studiomeshgroup_t* pMeshGroup,
OptimizedModel::StripGroupHeader_t *pStripGroup, mstudiomesh_t* pMesh,
studiohdr_t *pStudioHdr, VertexFormat_t vertexFormat );
void R_StudioBuildMeshStrips( studiomeshgroup_t* pMeshGroup,
OptimizedModel::StripGroupHeader_t *pStripGroup );
template <VertexCompressionType_t T> bool R_AddVertexToMesh( const char *pModelName, bool bNeedsTangentSpace, CMeshBuilder& meshBuilder,
OptimizedModel::Vertex_t* pVertex, mstudiomesh_t* pMesh, const mstudio_meshvertexdata_t *vertData, bool hwSkin );
// This will generate random flex data that has a specified # of non-zero values
void GenerateRandomFlexWeights( int nWeightCount, float* pWeights, float *pDelayedWeights );
// Computes LOD
int ComputeRenderLOD( IMatRenderContext *pRenderContext, const DrawModelInfo_t& info, const Vector &origin, float *pMetric );
// This invokes proxies of all materials that are queued to be rendered
void InvokeBindProxies( const DrawModelInfo_t &info );
// Did this matrix come from our allocator?
bool IsInternallyAllocated( const matrix3x4_t *pBoneToWorld );
// Did this flex weights come from our allocator?
bool IsInternallyAllocated( const float *pFlexWeights );
private:
StudioRenderContext_t m_RC;
// Used by the lighting computation methods,
// this is only here to prevent constructors in lightpos_t from being repeatedly run
lightpos_t m_pLightPos[MAXLIGHTCOMPUTE];
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline int CStudioRenderContext::ComputeModelLod( studiohwdata_t *pHardwareData, float flUnitSphereSize, float *pMetric )
{
return ComputeModelLODAndMetric( pHardwareData, flUnitSphereSize, pMetric );
}
#endif // STUDIORENDERCONTEXT_H
|