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.

931 lines
31 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #ifndef CSTUDIORENDER_H
  7. #define CSTUDIORENDER_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "istudiorender.h"
  12. #include "studio.h"
  13. #include "materialsystem/imaterialsystem.h" // for LightDesc_t
  14. // wouldn't have to include these if it weren't for inlines.
  15. #include "materialsystem/imaterial.h"
  16. #include "mathlib/mathlib.h"
  17. #include "utllinkedlist.h"
  18. #include "utlvector.h"
  19. #include "tier1/utllinkedlist.h"
  20. #include "flexrenderdata.h"
  21. #include "mathlib/compressed_vector.h"
  22. #include "r_studiolight.h"
  23. #if defined( _WIN32 ) && !defined( _X360 )
  24. #include <xmmintrin.h>
  25. #endif
  26. #include "tier0/dbg.h"
  27. //-----------------------------------------------------------------------------
  28. // Forward declarations
  29. //-----------------------------------------------------------------------------
  30. class ITexture;
  31. class CPixelWriter;
  32. class CMeshBuilder;
  33. class IMaterialVar;
  34. struct mstudioeyeball_t;
  35. struct eyeballstate_t;
  36. struct lightpos_t;
  37. struct dworldlight_t;
  38. struct DecalClipState_t;
  39. class CStudioRender;
  40. struct StudioRenderContext_t;
  41. struct FlexWeights_t;
  42. namespace OptimizedModel
  43. {
  44. struct FileHeader_t;
  45. struct MeshHeader_t;
  46. struct StripGroupHeader_t;
  47. struct Vertex_t;
  48. struct ModelLODHeader_t;
  49. }
  50. //-----------------------------------------------------------------------------
  51. // FIXME: Remove
  52. //-----------------------------------------------------------------------------
  53. class IStudioDataCache;
  54. extern IStudioDataCache *g_pStudioDataCache;
  55. //-----------------------------------------------------------------------------
  56. // Singleton
  57. //-----------------------------------------------------------------------------
  58. extern CStudioRender g_StudioRender;
  59. //-----------------------------------------------------------------------------
  60. // Defines + structs
  61. //-----------------------------------------------------------------------------
  62. #define MAXLOCALLIGHTS 4
  63. #define MAXLIGHTCOMPUTE 16
  64. enum StudioModelLighting_t
  65. {
  66. LIGHTING_HARDWARE = 0,
  67. LIGHTING_SOFTWARE,
  68. LIGHTING_MOUTH
  69. };
  70. struct lightpos_t
  71. {
  72. Vector delta; // unit vector from vertex to light
  73. float falloff; // light distance falloff
  74. float dot; // light direction * delta;
  75. lightpos_t() {}
  76. private:
  77. // Copy constructors are not allowed
  78. lightpos_t( const lightpos_t& src );
  79. };
  80. struct eyeballstate_t
  81. {
  82. const mstudioeyeball_t *peyeball;
  83. matrix3x4_t mat;
  84. Vector org; // world center of eyeball
  85. Vector forward;
  86. Vector right;
  87. Vector up;
  88. Vector cornea; // world center of cornea
  89. eyeballstate_t() {}
  90. private:
  91. // Copy constructors are not allowed
  92. eyeballstate_t( const eyeballstate_t& src );
  93. };
  94. //-----------------------------------------------------------------------------
  95. // Store decal vertex data here
  96. //-----------------------------------------------------------------------------
  97. #pragma pack(1)
  98. struct DecalVertex_t
  99. {
  100. mstudiomesh_t *GetMesh( studiohdr_t *pHdr )
  101. {
  102. if ((m_Body == 0xFFFF) || (m_Model == 0xFFFF) || (m_Mesh == 0xFFFF))
  103. return NULL;
  104. mstudiobodyparts_t *pBody = pHdr->pBodypart( m_Body );
  105. mstudiomodel_t *pModel = pBody->pModel( m_Model );
  106. return pModel->pMesh( m_Mesh );
  107. }
  108. IMorph *GetMorph( studiohdr_t *pHdr, studiomeshdata_t *pStudioMeshes )
  109. {
  110. if ( (m_Body == 0xFFFF) || (m_Model == 0xFFFF) || (m_Mesh == 0xFFFF) || (m_Group == 0xFFFF) )
  111. return NULL;
  112. mstudiobodyparts_t *pBody = pHdr->pBodypart( m_Body );
  113. mstudiomodel_t *pModel = pBody->pModel( m_Model );
  114. mstudiomesh_t *pMesh = pModel->pMesh( m_Mesh );
  115. studiomeshdata_t* pMeshData = &pStudioMeshes[pMesh->meshid];
  116. studiomeshgroup_t* pGroup = &pMeshData->m_pMeshGroup[m_Group];
  117. return pGroup->m_pMorph;
  118. }
  119. // NOTE: m_Group + m_GroupIndex is necessary only for decals on
  120. // hardware morphs. If COMPACT_DECAL_VERT is for console, we
  121. // could remove group index + group
  122. #ifdef COMPACT_DECAL_VERT
  123. Vector m_Position; // 12
  124. Vector2d32 m_TexCoord; // 16
  125. Vector48 m_Normal; // 22 (packed to m_Body)
  126. byte m_Body; // 24
  127. byte m_Model;
  128. unsigned short m_MeshVertexIndex; // index into the mesh's vertex list
  129. unsigned short m_Mesh;
  130. unsigned short m_GroupIndex; // index into the mesh's vertex list
  131. unsigned short m_Group;
  132. #else
  133. Vector m_Position;
  134. Vector m_Normal;
  135. Vector2D m_TexCoord;
  136. unsigned short m_MeshVertexIndex; // index into the mesh's vertex list
  137. unsigned short m_Body;
  138. unsigned short m_Model;
  139. unsigned short m_Mesh;
  140. unsigned short m_GroupIndex; // index into the group's index list
  141. unsigned short m_Group;
  142. #endif
  143. DecalVertex_t() {}
  144. DecalVertex_t( const DecalVertex_t& src )
  145. {
  146. m_Position = src.m_Position;
  147. m_Normal = src.m_Normal;
  148. m_TexCoord = src.m_TexCoord;
  149. m_MeshVertexIndex = src.m_MeshVertexIndex;
  150. m_Body = src.m_Body;
  151. m_Model = src.m_Model;
  152. m_Mesh = src.m_Mesh;
  153. m_GroupIndex = src.m_GroupIndex;
  154. m_Group = src.m_Group;
  155. }
  156. };
  157. #pragma pack()
  158. //-----------------------------------------------------------------------------
  159. // Temporary meshes
  160. //-----------------------------------------------------------------------------
  161. struct MeshVertexInfo_t
  162. {
  163. mstudiomesh_t *m_pMesh;
  164. int m_nIndex;
  165. };
  166. //-----------------------------------------------------------------------------
  167. // Vertex prefetch count for software skinning
  168. //-----------------------------------------------------------------------------
  169. enum
  170. {
  171. PREFETCH_VERT_COUNT = 4
  172. };
  173. //-----------------------------------------------------------------------------
  174. // Class that actually renders stuff
  175. //-----------------------------------------------------------------------------
  176. class CStudioRender
  177. {
  178. public:
  179. CStudioRender();
  180. ~CStudioRender();
  181. // Init, shutdown
  182. InitReturnVal_t Init();
  183. void Shutdown( void );
  184. void EnableScissor( FlashlightState_t *state );
  185. void DisableScissor();
  186. void DrawModel( const DrawModelInfo_t& info, const StudioRenderContext_t& rc, matrix3x4_t *pBoneToWorld, const FlexWeights_t& flex, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL );
  187. void DrawModelArray( const DrawModelInfo_t &drawInfo, const StudioRenderContext_t &rc, int arrayCount, model_array_instance_t *pInstanceData, int instanceStride, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL );
  188. // Static-prop related draw methods
  189. void DrawModelStaticProp( const DrawModelInfo_t& info, const StudioRenderContext_t &rc, const matrix3x4_t &modelToWorld, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL );
  190. void DrawStaticPropShadows( const DrawModelInfo_t &drawInfo, const StudioRenderContext_t &rc, const matrix3x4_t &modelToWorld, int flags );
  191. void DrawStaticPropDecals( const DrawModelInfo_t &drawInfo, const StudioRenderContext_t &rc, const matrix3x4_t &modelToWorld );
  192. void ModelStats( const DrawModelInfo_t& info, const StudioRenderContext_t &rc, matrix3x4_t *pBoneToWorld, const FlexWeights_t &flex, int flags );
  193. // Create, destroy list of decals for a particular model
  194. StudioDecalHandle_t CreateDecalList( studiohwdata_t *pHardwareData );
  195. void DestroyDecalList( StudioDecalHandle_t handle );
  196. // Add decals to a decal list by doing a planar projection along the ray
  197. void AddDecal( StudioDecalHandle_t handle, const StudioRenderContext_t& rc, matrix3x4_t *pBoneToWorld, studiohdr_t *pStudioHdr,
  198. const Ray_t & ray, const Vector& decalUp, IMaterial* pDecalMaterial,
  199. float radius, int body, bool noPokethru, int maxLODToDecal = ADDDECAL_TO_ALL_LODS );
  200. // Shadow state (affects the models as they are rendered)
  201. void AddShadow( IMaterial* pMaterial, void* pProxyData, FlashlightState_t *pFlashlightState, VMatrix *pWorldToTexture, ITexture *pFlashlightDepthTexture );
  202. void ClearAllShadows();
  203. // Release/restore material system objects
  204. void PrecacheGlint();
  205. void UncacheGlint();
  206. // Get the config
  207. void R_MouthComputeLightingValues( float& fIllum, Vector& forward );
  208. void R_MouthLighting( float fIllum, const Vector& normal, const Vector& forward, Vector& light );
  209. // Performs the lighting computation
  210. inline void R_ComputeLightAtPoint3( const Vector &pos, const Vector &norm, Vector &color );
  211. #if defined( _WIN32 ) && !defined( _X360 )
  212. // sse-ized lighting pipeline. lights 4 vertices at once
  213. inline void R_ComputeLightAtPoints3( const FourVectors &pos, const FourVectors &norm, FourVectors &color );
  214. void R_MouthLighting( __m128 fIllum, const FourVectors& normal, const FourVectors& forward, FourVectors& light );
  215. #endif
  216. private:
  217. enum
  218. {
  219. DECAL_DYNAMIC = 0x1,
  220. DECAL_SECONDPASS = 0x2,
  221. };
  222. typedef unsigned short DecalId_t;
  223. struct Decal_t
  224. {
  225. int m_IndexCount;
  226. int m_VertexCount;
  227. float m_FadeStartTime;
  228. float m_FadeDuration;
  229. int m_Flags;
  230. };
  231. struct DecalHistory_t
  232. {
  233. unsigned short m_Material;
  234. unsigned short m_Decal;
  235. DecalId_t m_nId;
  236. unsigned short m_nPad;
  237. };
  238. typedef CUtlLinkedList<DecalVertex_t, unsigned short> DecalVertexList_t;
  239. typedef CUtlVector<unsigned short> DecalIndexList_t;
  240. typedef CUtlLinkedList<Decal_t, unsigned short> DecalList_t;
  241. typedef CUtlLinkedList<DecalHistory_t, unsigned short> DecalHistoryList_t;
  242. struct DecalMaterial_t
  243. {
  244. IMaterial* m_pMaterial;
  245. DecalIndexList_t m_Indices;
  246. DecalVertexList_t m_Vertices;
  247. DecalList_t m_Decals;
  248. };
  249. struct DecalLod_t
  250. {
  251. unsigned short m_FirstMaterial;
  252. DecalHistoryList_t m_DecalHistory;
  253. };
  254. struct DecalModelList_t
  255. {
  256. studiohwdata_t* m_pHardwareData;
  257. DecalLod_t* m_pLod;
  258. int m_nLods; // need to retain because hardware data could be flushed
  259. };
  260. // A temporary structure used to figure out new decal verts
  261. struct DecalBuildVertexInfo_t
  262. {
  263. enum
  264. {
  265. FRONT_FACING = 0x1,
  266. VALID_AREA = 0x2, // If you change this, change ProjectDecalOntoMesh
  267. };
  268. Vector2D m_UV;
  269. unsigned short m_VertexIndex; // index into the DecalVertex_t list
  270. unsigned char m_UniqueID;
  271. unsigned char m_Flags;
  272. private:
  273. // No copy constructors
  274. DecalBuildVertexInfo_t( const DecalBuildVertexInfo_t &src );
  275. };
  276. struct DecalBuildInfo_t
  277. {
  278. IMaterial **m_ppMaterials;
  279. studiohdr_t *m_pStudioHdr;
  280. mstudiomesh_t *m_pMesh;
  281. studiomeshdata_t *m_pMeshData;
  282. DecalMaterial_t *m_pDecalMaterial;
  283. MeshVertexInfo_t *m_pMeshVertices;
  284. const mstudio_meshvertexdata_t *m_pMeshVertexData;
  285. const thinModelVertices_t *m_pMeshThinVertexData;
  286. int m_nGlobalMeshIndex;
  287. DecalBuildVertexInfo_t *m_pVertexBuffer;
  288. float m_Radius;
  289. DecalBuildVertexInfo_t *m_pVertexInfo;
  290. int m_Body;
  291. int m_Model;
  292. int m_Mesh;
  293. int m_Group;
  294. DecalVertexList_t::IndexType_t m_FirstVertex;
  295. unsigned short m_VertexCount;
  296. bool m_UseClipVert;
  297. bool m_NoPokeThru;
  298. };
  299. struct ShadowState_t
  300. {
  301. IMaterial* m_pMaterial;
  302. void* m_pProxyData;
  303. FlashlightState_t * m_pFlashlightState;
  304. VMatrix * m_pWorldToTexture;
  305. ITexture * m_pFlashlightDepthTexture;
  306. };
  307. struct BodyPartInfo_t
  308. {
  309. int m_nSubModelIndex;
  310. mstudiomodel_t *m_pSubModel;
  311. };
  312. struct GlintRenderData_t
  313. {
  314. Vector2D m_vecPosition;
  315. Vector m_vecIntensity;
  316. };
  317. // Global LRU for model decals
  318. struct DecalLRU_t
  319. {
  320. StudioDecalHandle_t m_hDecalHandle;
  321. DecalId_t m_nDecalId;
  322. };
  323. typedef CUtlFixedLinkedList< DecalLRU_t >::IndexType_t DecalLRUListIndex_t;
  324. private:
  325. void SetLightingRenderState();
  326. int R_StudioRenderModel( IMatRenderContext *pRenderContext, int skin, int body, int hitboxset, void /*IClientEntity*/ *pEntity,
  327. IMaterial **ppMaterials, int *pMaterialFlags, int flags, int boneMask, int lod, ColorMeshInfo_t *pColorMeshes = NULL );
  328. IMaterial* R_StudioSetupSkinAndLighting( IMatRenderContext *pRenderContext, int index, IMaterial **ppMaterials, int materialFlags,
  329. void /*IClientEntity*/ *pClientEntity, ColorMeshInfo_t *pColorMeshes, StudioModelLighting_t &lighting );
  330. int R_StudioDrawEyeball( IMatRenderContext *pRenderContext, mstudiomesh_t* pmesh, studiomeshdata_t* pMeshData,
  331. StudioModelLighting_t lighting, IMaterial *pMaterial, int lod );
  332. int R_StudioDrawPoints( IMatRenderContext *pRenderContext, int skin, void /*IClientEntity*/ *pClientEntity,
  333. IMaterial **ppMaterials, int *pMaterialFlags, int boneMask, int lod, ColorMeshInfo_t *pColorMeshes );
  334. int R_StudioDrawMesh( IMatRenderContext *pRenderContext, mstudiomesh_t* pmesh, studiomeshdata_t* pMeshData,
  335. StudioModelLighting_t lighting, IMaterial *pMaterial, ColorMeshInfo_t *pColorMeshes, int lod );
  336. int R_StudioRenderFinal( IMatRenderContext *pRenderContext,
  337. int skin, int nBodyPartCount, BodyPartInfo_t *pBodyPartInfo, void /*IClientEntity*/ *pClientEntity,
  338. IMaterial **ppMaterials, int *pMaterialFlags, int boneMask, int lod, ColorMeshInfo_t *pColorMeshes = NULL );
  339. int R_StudioDrawStaticMesh( IMatRenderContext *pRenderContext, mstudiomesh_t* pmesh,
  340. studiomeshgroup_t* pGroup, StudioModelLighting_t lighting, float r_blend, IMaterial* pMaterial,
  341. int lod, ColorMeshInfo_t *pColorMeshes );
  342. int R_StudioDrawDynamicMesh( IMatRenderContext *pRenderContext, mstudiomesh_t* pmesh,
  343. studiomeshgroup_t* pGroup, StudioModelLighting_t lighting,
  344. float r_blend, IMaterial* pMaterial, int lod );
  345. int R_StudioDrawGroupHWSkin( IMatRenderContext *pRenderContext, studiomeshgroup_t* pGroup, IMesh* pMesh, ColorMeshInfo_t *pColorMeshInfo = NULL );
  346. int R_StudioDrawGroupSWSkin( studiomeshgroup_t* pGroup, IMesh* pMesh );
  347. void R_StudioDrawHulls( int hitboxset, bool translucent );
  348. void R_StudioDrawBones (void);
  349. void R_StudioVertBuffer( void );
  350. void DrawNormal( const Vector& pos, float scale, const Vector& normal, const Vector& color );
  351. void BoneMatToMaterialMat( matrix3x4_t& boneMat, float materialMat[4][4] );
  352. // Various inner-loop methods
  353. void R_StudioSoftwareProcessMesh( mstudiomesh_t* pmesh, CMeshBuilder& meshBuilder,
  354. int numVertices, unsigned short* pGroupToMesh, StudioModelLighting_t lighting, bool doFlex, float r_blend,
  355. bool bNeedsTangentSpace, bool bDX8Vertex, IMaterial *pMaterial );
  356. void R_StudioSoftwareProcessMesh_Normals( mstudiomesh_t* pmesh, CMeshBuilder& meshBuilder,
  357. int numVertices, unsigned short* pGroupToMesh, StudioModelLighting_t lighting, bool doFlex, float r_blend,
  358. bool bShowNormals, bool bShowTangentFrame );
  359. template< class T >
  360. void ComputeFlexedVertex_StreamOffset( mstudioflex_t *pflex, T *pvanim, int vertCount, float w1, float w2, float w3, float w4 );
  361. void R_StudioProcessFlexedMesh_StreamOffset( mstudiomesh_t* pmesh, int lod );
  362. template <VertexCompressionType_t T> void FillFlexMeshGroupVB( CMeshBuilder & meshBuilder, studiomeshgroup_t *pGroup );
  363. void R_StudioFlexMeshGroup( studiomeshgroup_t *pGroup );
  364. template<VertexCompressionType_t T> void R_StudioRestoreMesh( mstudiomesh_t* pmesh, studiomeshgroup_t* pMeshData );
  365. void R_StudioProcessFlexedMesh( mstudiomesh_t* pmesh, CMeshBuilder& meshBuilder,
  366. int numVertices, unsigned short* pGroupToMesh );
  367. // Eye rendering using vertex shaders
  368. void SetEyeMaterialVars( IMaterial* pMaterial, mstudioeyeball_t* peyeball,
  369. const Vector& eyeOrigin, const matrix3x4_t& irisTransform, const matrix3x4_t& glintTransform );
  370. void ComputeEyelidStateFACS( mstudiomodel_t *pSubModel );
  371. void R_StudioEyelidFACS( const mstudioeyeball_t *peyeball, const eyeballstate_t *pstate );
  372. void R_StudioEyeballPosition( const mstudioeyeball_t *peyeball, eyeballstate_t *pstate );
  373. // Computes the texture projection matrix for the glint texture
  374. void ComputeGlintTextureProjection( eyeballstate_t const* pState,
  375. const Vector& vright, const Vector& vup, matrix3x4_t& mat );
  376. void R_StudioEyeballGlint( const eyeballstate_t *pstate, IMaterialVar *pGlintTextureVar,
  377. const Vector& vright, const Vector& vup, const Vector& r_origin );
  378. ITexture* RenderGlintTexture( const eyeballstate_t *pstate,
  379. const Vector& vright, const Vector& vup, const Vector& r_origin );
  380. int BuildGlintRenderData( GlintRenderData_t *pData, int nMaxGlints,
  381. const eyeballstate_t *pstate, const Vector& vright, const Vector& vup, const Vector& r_origin );
  382. void R_MouthSetupVertexShader( IMaterial* pMaterial );
  383. // Computes a vertex format to use
  384. VertexFormat_t ComputeSWSkinVertexFormat( IMaterial *pMaterial ) const;
  385. inline bool R_TeethAreVisible( void )
  386. {
  387. return true;
  388. /*
  389. // FIXME: commented out until Gary can change them to just draw black
  390. mstudiomouth_t *pMouth = m_pStudioHdr->pMouth( 0 );
  391. float fIllum = m_FlexWeights[pMouth->flexdesc];
  392. return fIllum > 0.0f;
  393. */
  394. }
  395. inline StudioModelLighting_t R_StudioComputeLighting( IMaterial *pMaterial, int materialFlags, ColorMeshInfo_t *pColorMeshes );
  396. inline void R_StudioTransform( Vector& in1, mstudioboneweight_t *pboneweight, Vector& out1 );
  397. inline void R_StudioRotate( Vector& in1, mstudioboneweight_t *pboneweight, Vector& out1 );
  398. inline void R_StudioRotate( Vector4D& in1, mstudioboneweight_t *pboneweight, Vector4D& out1 );
  399. inline void R_StudioEyeballNormal( mstudioeyeball_t const* peyeball, Vector& org,
  400. Vector& pos, Vector& normal );
  401. void MaterialPlanerProjection( const matrix3x4_t& mat, int count, const Vector *psrcverts, Vector2D *pdesttexcoords );
  402. void AddGlint( CPixelWriter &pixelWriter, float x, float y, const Vector& color );
  403. // Methods associated with lighting
  404. int R_LightGlintPosition( int index, const Vector& org, Vector& delta, Vector& intensity );
  405. void R_LightEffectsWorld( const lightpos_t *light, const Vector& normal, const Vector &src, Vector &dest );
  406. void R_GatherStats( studiomeshgroup_t *pGroup, CMeshBuilder &MeshBuilder, IMesh *pMesh, IMaterial *pMaterial );
  407. public:
  408. // NJS: Messy, but needed for an externally optimized routine to set up the lighting.
  409. void R_InitLightEffectsWorld3();
  410. void (FASTCALL *R_LightEffectsWorld3)( const LightDesc_t *pLightDesc, const lightpos_t *light, const Vector& normal, Vector &dest );
  411. private:
  412. inline float R_WorldLightAngle( const LightDesc_t *wl, const Vector& lnormal, const Vector& snormal, const Vector& delta );
  413. void InitDebugMaterials( void );
  414. void ShutdownDebugMaterials( void );
  415. int SortMeshes( int* pIndices, IMaterial **ppMaterials, short* pskinref, const Vector& vforward, const Vector& r_origin );
  416. // Computes pose to decal space transforms for decal creation
  417. // returns false if it can't for some reason.
  418. bool ComputePoseToDecal( Ray_t const& ray, const Vector& up );
  419. bool AddDecalToModel( DecalBuildInfo_t& buildInfo );
  420. // Helper methods for decal projection, projects pose space vertex data
  421. bool TransformToDecalSpace( DecalBuildInfo_t& build, const Vector& pos, mstudioboneweight_t *pboneweight, Vector2D& uv );
  422. bool ProjectDecalOntoMesh( DecalBuildInfo_t& build, DecalBuildVertexInfo_t* pVertexInfo, mstudiomesh_t *pMesh );
  423. bool IsFrontFacing( const Vector * norm, const mstudioboneweight_t *pboneweight );
  424. int ComputeClipFlags( DecalBuildVertexInfo_t* pVertexInfo, int i );
  425. void ConvertMeshVertexToDecalVertex( DecalBuildInfo_t& build, int meshIndex, DecalVertex_t& decalVertex, int nGroupIndex = 0xFFFF );
  426. unsigned short AddVertexToDecal( DecalBuildInfo_t& build, int meshIndex, int nGroupIndex = 0xFFFF );
  427. unsigned short AddVertexToDecal( DecalBuildInfo_t& build, DecalVertex_t& vert );
  428. void AddClippedDecalToTriangle( DecalBuildInfo_t& build, DecalClipState_t& clipState );
  429. bool ClipDecal( DecalBuildInfo_t& build, int i1, int i2, int i3, int *pClipFlags );
  430. void AddTriangleToDecal( DecalBuildInfo_t& build, int i1, int i2, int i3, int gi1, int gi2, int gi3 );
  431. void AddDecalToMesh( DecalBuildInfo_t& build );
  432. int GetDecalMaterial( DecalLod_t& decalLod, IMaterial* pDecalMaterial );
  433. int AddDecalToMaterialList( DecalMaterial_t* pMaterial );
  434. // Total number of meshes we have to deal with
  435. int ComputeTotalMeshCount( int iRootLOD, int iMaxLOD, int body ) const;
  436. // Project decals onto all meshes
  437. void ProjectDecalsOntoMeshes( DecalBuildInfo_t& build, int nMeshCount );
  438. // Set up the locations for vertices to use
  439. int ComputeVertexAllocation( int iMaxLOD, int body, studiohwdata_t *pHardwareData, MeshVertexInfo_t *pVertexInfo );
  440. // Removes a decal and associated vertices + indices from the history list
  441. void RetireDecal( DecalModelList_t &list, DecalId_t nDecalID, int iLOD, int iMaxLOD );
  442. // Helper methods related to drawing decals
  443. void DrawSingleBoneDecals( CMeshBuilder& meshBuilder, DecalMaterial_t& decalMaterial );
  444. bool DrawMultiBoneDecals( CMeshBuilder& meshBuilder, DecalMaterial_t& decalMaterial, studiohdr_t *pStudioHdr );
  445. void DrawSingleBoneFlexedDecals( IMatRenderContext *pRenderContext, CMeshBuilder& meshBuilder, DecalMaterial_t& decalMaterial );
  446. bool DrawMultiBoneFlexedDecals( IMatRenderContext *pRenderContext, CMeshBuilder& meshBuilder, DecalMaterial_t& decalMaterial, studiohdr_t *pStudioHdr, studioloddata_t *pStudioLOD );
  447. void DrawDecalMaterial( IMatRenderContext *pRenderContext, DecalMaterial_t& decalMaterial, studiohdr_t *pStudioHdr, studioloddata_t *pStudioLOD );
  448. void DrawDecal( const DrawModelInfo_t &drawInfo, int lod, int body );
  449. bool PreDrawDecal( IMatRenderContext *pRenderContext, const DrawModelInfo_t &drawInfo );
  450. // Draw shadows
  451. void DrawShadows( const DrawModelInfo_t& info, int flags, int boneMask );
  452. // Draw flashlight lighting on decals.
  453. void DrawFlashlightDecals( const DrawModelInfo_t& info, int lod );
  454. // Helper methods related to extracting and balancing
  455. float RampFlexWeight( mstudioflex_t &flex, float w );
  456. // Remove decal from LRU
  457. void RemoveDecalListFromLRU( StudioDecalHandle_t h );
  458. // Helper methods related to flexing vertices
  459. void R_StudioFlexVerts( mstudiomesh_t *pmesh, int lod );
  460. // Flex stats
  461. void GetFlexStats( );
  462. // Sets up the hw flex mesh
  463. void ComputeFlexWeights( int nFlexCount, mstudioflex_t *pFlex, MorphWeight_t *pWeights );
  464. // Generate morph accumulator
  465. void GenerateMorphAccumulator( mstudiomodel_t *pSubModel );
  466. // Computes eyeball state
  467. void ComputeEyeballState( mstudiomodel_t *pSubModel );
  468. // Avoid some warnings...
  469. CStudioRender( CStudioRender const& );
  470. public:
  471. // Render context (comes from queue)
  472. StudioRenderContext_t *m_pRC;
  473. private:
  474. // Stores all decals for a particular material and lod
  475. CUtlLinkedList< DecalMaterial_t, unsigned short, true > m_DecalMaterial;
  476. // Stores all decal lists that have been made
  477. CUtlFixedLinkedList< DecalModelList_t > m_DecalList;
  478. CThreadFastMutex m_DecalMutex;
  479. // Stores all shadows to be cast on the current object
  480. CUtlVector<ShadowState_t> m_ShadowState;
  481. matrix3x4_t m_StaticPropRootToWorld;
  482. matrix3x4_t *m_pBoneToWorld; // bone transformation matrix( comes from queue )
  483. matrix3x4_t *m_PoseToWorld; // bone transformation matrix
  484. matrix3x4_t *m_PoseToDecal; // bone transformation matrix
  485. // Flex state, comes from queue
  486. float *m_pFlexWeights;
  487. float *m_pFlexDelayedWeights;
  488. studiohdr_t *m_pStudioHdr;
  489. mstudiomodel_t *m_pSubModel;
  490. studiomeshdata_t *m_pStudioMeshes;
  491. eyeballstate_t m_pEyeballState[16]; // MAXSTUDIOEYEBALLS
  492. // debug materials
  493. IMaterial *m_pMaterialMRMWireframe;
  494. IMaterial *m_pMaterialMRMWireframeZBuffer;
  495. IMaterial *m_pMaterialMRMNormals;
  496. IMaterial *m_pMaterialTangentFrame;
  497. IMaterial *m_pMaterialTranslucentModelHulls;
  498. IMaterial *m_pMaterialSolidModelHulls;
  499. IMaterial *m_pMaterialAdditiveVertexColorVertexAlpha;
  500. IMaterial *m_pMaterialModelBones;
  501. IMaterial *m_pMaterialWorldWireframe;
  502. IMaterial *m_pMaterialModelEnvCubemap;
  503. // Depth override material
  504. IMaterial *m_pDepthWrite[2][2];
  505. IMaterial *m_pSSAODepthWrite[2][2];
  506. // GLINT data
  507. ITexture* m_pGlintTexture;
  508. ITexture* m_pGlintLODTexture;
  509. IMaterial *m_pGlintBuildMaterial;
  510. short m_GlintWidth;
  511. short m_GlintHeight;
  512. // Flex data
  513. CCachedRenderData m_VertexCache;
  514. // Cached variables:
  515. bool m_bSkippedMeshes : 1;
  516. bool m_bDrawTranslucentSubModels : 1;
  517. DecalId_t m_nDecalId;
  518. CUtlFixedLinkedList< DecalLRU_t > m_DecalLRU;
  519. friend class CGlintTextureRegenerator;
  520. friend struct mstudiomodel_t;
  521. friend class CStudioRenderContext;
  522. };
  523. //-----------------------------------------------------------------------------
  524. // Converts matrices to a format material system wants
  525. //-----------------------------------------------------------------------------
  526. /*
  527. ================
  528. R_StudioTransform
  529. ================
  530. */
  531. inline void CStudioRender::R_StudioTransform( Vector& in1, mstudioboneweight_t *pboneweight, Vector& out1 )
  532. {
  533. // MEASURECODE( "R_StudioTransform" );
  534. Vector out2;
  535. switch( pboneweight->numbones )
  536. {
  537. case 1:
  538. VectorTransform( in1, m_PoseToWorld[(unsigned)pboneweight->bone[0]], out1 );
  539. break;
  540. /*
  541. case 2:
  542. VectorTransform( in1, m_PoseToWorld[pboneweight->bone[0]], out1 );
  543. out1 *= pboneweight->weight[0];
  544. VectorTransform( in1, m_PoseToWorld[pboneweight->bone[1]], out2 );
  545. VectorMA( out1, pboneweight->weight[1], out2, out1 );
  546. break;
  547. case 3:
  548. VectorTransform( in1, m_PoseToWorld[pboneweight->bone[0]], out1 );
  549. out1 *= pboneweight->weight[0];
  550. VectorTransform( in1, m_PoseToWorld[pboneweight->bone[1]], out2 );
  551. VectorMA( out1, pboneweight->weight[1], out2, out1 );
  552. VectorTransform( in1, m_PoseToWorld[pboneweight->bone[2]], out2 );
  553. VectorMA( out1, pboneweight->weight[2], out2, out1 );
  554. break;
  555. */
  556. default:
  557. VectorFill( out1, 0 );
  558. for (int i = 0; i < pboneweight->numbones; i++)
  559. {
  560. VectorTransform( in1, m_PoseToWorld[(unsigned)pboneweight->bone[i]], out2 );
  561. VectorMA( out1, pboneweight->weight[i], out2, out1 );
  562. }
  563. break;
  564. }
  565. }
  566. /*
  567. ================
  568. R_StudioRotate
  569. ================
  570. */
  571. inline void CStudioRender::R_StudioRotate( Vector& in1, mstudioboneweight_t *pboneweight, Vector& out1 )
  572. {
  573. // NOTE: This only works to rotate normals if there's no scale in the
  574. // pose to world transforms. If we ever add scale, we'll need to
  575. // multiply by the inverse transpose of the pose to world
  576. if (pboneweight->numbones == 1)
  577. {
  578. VectorRotate( in1, m_PoseToWorld[(unsigned)pboneweight->bone[0]], out1 );
  579. }
  580. else
  581. {
  582. Vector out2;
  583. VectorFill( out1, 0 );
  584. for (int i = 0; i < pboneweight->numbones; i++)
  585. {
  586. VectorRotate( in1, m_PoseToWorld[(unsigned)pboneweight->bone[i]], out2 );
  587. VectorMA( out1, pboneweight->weight[i], out2, out1 );
  588. }
  589. VectorNormalize( out1 );
  590. }
  591. }
  592. inline void CStudioRender::R_StudioRotate( Vector4D& realIn1, mstudioboneweight_t *pboneweight, Vector4D& realOut1 )
  593. {
  594. // garymcthack - god this sucks.
  595. Vector in1( realIn1[0], realIn1[1], realIn1[2] );
  596. Vector out1;
  597. if (pboneweight->numbones == 1)
  598. {
  599. VectorRotate( in1, m_PoseToWorld[(unsigned)pboneweight->bone[0]], out1 );
  600. }
  601. else
  602. {
  603. Vector out2;
  604. VectorFill( out1, 0 );
  605. for (int i = 0; i < pboneweight->numbones; i++)
  606. {
  607. VectorRotate( in1, m_PoseToWorld[(unsigned)pboneweight->bone[i]], out2 );
  608. VectorMA( out1, pboneweight->weight[i], out2, out1 );
  609. }
  610. VectorNormalize( out1 );
  611. }
  612. realOut1.Init( out1[0], out1[1], out1[2], realIn1[3] );
  613. }
  614. //-----------------------------------------------------------------------------
  615. // Compute the contribution of a light depending on it's angle
  616. //-----------------------------------------------------------------------------
  617. /*
  618. light_normal (lights normal translated to same space as other normals)
  619. surface_normal
  620. light_direction_normal | (light_pos - vertex_pos) |
  621. */
  622. template< int nLightType >
  623. class CWorldLightAngleWrapper
  624. {
  625. public:
  626. FORCEINLINE static float WorldLightAngle( const LightDesc_t *wl, const Vector& lnormal, const Vector& snormal, const Vector& delta )
  627. {
  628. float dot, dot2, ratio;
  629. switch (nLightType)
  630. {
  631. case MATERIAL_LIGHT_POINT:
  632. #if 1
  633. // half-lambert
  634. dot = DotProduct( snormal, delta );
  635. if (dot < 0.f)
  636. return 0.f;
  637. #else
  638. dot = DotProduct( snormal, delta ) * 0.5 + 0.5;
  639. dot = dot * dot;
  640. #endif
  641. return dot;
  642. case MATERIAL_LIGHT_SPOT:
  643. #if 1
  644. // half-lambert
  645. dot = DotProduct( snormal, delta );
  646. if (dot < 0.)
  647. return 0.f;
  648. #else
  649. dot = DotProduct( snormal, delta ) * 0.5 + 0.5;
  650. dot = dot * dot;
  651. #endif
  652. dot2 = -DotProduct (delta, lnormal);
  653. if (dot2 <= wl->m_PhiDot)
  654. return 0.f; // outside light cone
  655. ratio = dot;
  656. if (dot2 >= wl->m_ThetaDot)
  657. return ratio; // inside inner cone
  658. if ((wl->m_Falloff == 1.f) || (wl->m_Falloff == 0.f))
  659. {
  660. ratio *= (dot2 - wl->m_PhiDot) / (wl->m_ThetaDot - wl->m_PhiDot);
  661. }
  662. else
  663. {
  664. ratio *= pow((dot2 - wl->m_PhiDot) / (wl->m_ThetaDot - wl->m_PhiDot), wl->m_Falloff );
  665. }
  666. return ratio;
  667. case MATERIAL_LIGHT_DIRECTIONAL:
  668. #if 1
  669. // half-lambert
  670. dot2 = -DotProduct( snormal, lnormal );
  671. if (dot2 < 0.f)
  672. return 0.f;
  673. #else
  674. dot2 = -DotProduct( snormal, lnormal ) * 0.5 + 0.5;
  675. dot2 = dot2 * dot2;
  676. #endif
  677. return dot2;
  678. case MATERIAL_LIGHT_DISABLE:
  679. return 0.f;
  680. NO_DEFAULT;
  681. }
  682. }
  683. };
  684. template< int nLightType >
  685. class CWorldLightAngleWrapperConstDirectional
  686. {
  687. public:
  688. FORCEINLINE static float WorldLightAngle( const LightDesc_t *wl, const Vector& lnormal, const Vector& snormal, const Vector& delta, float directionalamount )
  689. {
  690. float dot, dot2, ratio;
  691. // directional amount is constant
  692. dot = directionalamount;
  693. if (dot < 0.f)
  694. return 0.f;
  695. switch (nLightType)
  696. {
  697. case MATERIAL_LIGHT_POINT:
  698. case MATERIAL_LIGHT_DIRECTIONAL:
  699. return dot;
  700. case MATERIAL_LIGHT_SPOT:
  701. dot2 = -DotProduct (delta, lnormal);
  702. if (dot2 <= wl->m_PhiDot)
  703. return 0.f; // outside light cone
  704. ratio = dot;
  705. if (dot2 >= wl->m_ThetaDot)
  706. return ratio; // inside inner cone
  707. if ((wl->m_Falloff == 1.f) || (wl->m_Falloff == 0.f))
  708. {
  709. ratio *= (dot2 - wl->m_PhiDot) / (wl->m_ThetaDot - wl->m_PhiDot);
  710. }
  711. else
  712. {
  713. ratio *= pow((dot2 - wl->m_PhiDot) / (wl->m_ThetaDot - wl->m_PhiDot), wl->m_Falloff );
  714. }
  715. return ratio;
  716. case MATERIAL_LIGHT_DISABLE:
  717. return 0.f;
  718. NO_DEFAULT;
  719. }
  720. }
  721. };
  722. inline float CStudioRender::R_WorldLightAngle( const LightDesc_t *wl, const Vector& lnormal, const Vector& snormal, const Vector& delta )
  723. {
  724. switch (wl->m_Type)
  725. {
  726. case MATERIAL_LIGHT_DISABLE: return CWorldLightAngleWrapper<MATERIAL_LIGHT_DISABLE>::WorldLightAngle( wl, lnormal, snormal, delta );
  727. case MATERIAL_LIGHT_POINT: return CWorldLightAngleWrapper<MATERIAL_LIGHT_POINT>::WorldLightAngle( wl, lnormal, snormal, delta );
  728. case MATERIAL_LIGHT_DIRECTIONAL: return CWorldLightAngleWrapper<MATERIAL_LIGHT_DIRECTIONAL>::WorldLightAngle( wl, lnormal, snormal, delta );
  729. case MATERIAL_LIGHT_SPOT: return CWorldLightAngleWrapper<MATERIAL_LIGHT_SPOT>::WorldLightAngle( wl, lnormal, snormal, delta );
  730. NO_DEFAULT;
  731. }
  732. }
  733. //-----------------------------------------------------------------------------
  734. // Draws eyeballs
  735. //-----------------------------------------------------------------------------
  736. inline void CStudioRender::R_StudioEyeballNormal( mstudioeyeball_t const* peyeball, Vector& org,
  737. Vector& pos, Vector& normal )
  738. {
  739. // inside of a flattened torus
  740. VectorSubtract( pos, org, normal );
  741. float flUpAmount = DotProduct( normal, peyeball->up );
  742. VectorMA( normal, -0.5 * flUpAmount, peyeball->up, normal );
  743. VectorNormalize( normal );
  744. }
  745. //-----------------------------------------------------------------------------
  746. //
  747. // Stateless utility methods
  748. //
  749. //-----------------------------------------------------------------------------
  750. // Computes the submodel for a specified body + bodypart
  751. int R_StudioSetupModel( int nBodyPart, int nBody, mstudiomodel_t **pSubModel, const studiohdr_t *pStudioHdr );
  752. // Computes PoseToWorld from BoneToWorld
  753. void ComputePoseToWorld( matrix3x4_t *pPoseToWorld, studiohdr_t *pStudioHdr, int boneMask, const Vector& vecViewOrigin, const matrix3x4_t *pBoneToWorld );
  754. // Computes the model LOD
  755. inline int ComputeModelLODAndMetric( studiohwdata_t *pHardwareData, float flUnitSphereSize, float *pMetric )
  756. {
  757. // NOTE: This function was split off since CStudioRender needs it also.
  758. float flMetric = pHardwareData->LODMetric( flUnitSphereSize );
  759. if ( pMetric )
  760. {
  761. *pMetric = flMetric;
  762. }
  763. return pHardwareData->GetLODForMetric( flMetric );
  764. }
  765. #endif // CSTUDIORENDER_H