Counter Strike : Global Offensive Source Code
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.

1048 lines
39 KiB

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