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.

688 lines
25 KiB

  1. //========= Copyright � 1996-2007, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "c_surfacerender.h"
  9. #include "view.h"
  10. #include "view_shared.h"
  11. #include "iviewrender.h"
  12. #include "engine/ivdebugoverlay.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. #ifdef USE_BLOBULATOR
  16. ConVar r_surface_draw_isosurface( "r_surface_draw_isosurface", "1", 0, "Draws the surface as an isosurface" );
  17. ConVar r_surface_rotate( "r_surface_rotate", "1", FCVAR_NONE, "Whether to rotate for transparency" );
  18. ConVar r_surface_rotate_by90( "r_surface_rotate_by90", "1", FCVAR_NONE, "Whether to only rotate in 90 degree increments" );
  19. ConVar r_surface_blr_scale( "r_surface_blr_scale", "1.0", FCVAR_NONE, "Scale all surface rendering parameters." );
  20. ConVar r_surface_blr_cubewidth( "r_surface_blr_cubewidth", "0.8", FCVAR_NONE, "Set cubewidth (coarseness of the mesh)" );
  21. ConVar r_surface_blr_render_radius( "r_surface_blr_render_radius", "1.3", FCVAR_NONE, "Set render radius (how far from particle center surface will be)" );
  22. ConVar r_surface_blr_cutoff_radius( "r_surface_blr_cutoff_radius", "3.3", FCVAR_NONE, "Set cutoff radius (how far field extends from each particle)" );
  23. ConVar r_surface_calc_uv_and_tan( "r_surface_calc_uv_and_tan", "1", FCVAR_ARCHIVE, "Calculate UVs and Tangents" );
  24. ConVar r_surface_calc_tan_only( "r_surface_calc_tan_only", "0", FCVAR_ARCHIVE, "Calculate Only Tangents" );
  25. ConVar r_surface_calc_color( "r_surface_calc_color", "0", FCVAR_ARCHIVE, "Just interpolate colors" );
  26. ConVar r_surface_calc_hifreq_color( "r_surface_calc_hifreq_color", "0", FCVAR_ARCHIVE, "Experimental hi-freq colors" );
  27. ConVar r_surface_calc_tile_color( "r_surface_calc_tile_color", "0", FCVAR_ARCHIVE, "Shows color of the tile" );
  28. ConVar r_surface_debug_use_tiler("r_surface_debug_use_tiler", "1", FCVAR_NONE, "Use the tiler");
  29. ConVar r_surface_debug_max_tiles( "r_surface_debug_max_tiles", "-1", FCVAR_NONE, "The maximum number of tiles to draw" );
  30. ConVar r_surface_debug_max_slices( "r_surface_debug_max_slices", "-1", FCVAR_NONE, "The maximum number of slices to draw" );
  31. ConVar r_surface_debug_tile("r_surface_debug_tile", "1", FCVAR_NONE, "If tiler is enabled, whether we draw all tiles or just the central one.");
  32. ConVar r_surface_debug_draw_margin("r_surface_debug_draw_margin", "0", FCVAR_NONE, "If tiler is disabled, whether to draw the margin.");
  33. ConVar r_surface_debug_draw_tile_boundaries("r_surface_debug_draw_tile_boundaries", "0", FCVAR_NONE, "Whether to draw outlines of all tiles.");
  34. ConVar r_surface_wireframe( "r_surface_wireframe", "0", FCVAR_NONE, "Draw wireframe" );
  35. ConVar r_surface_material("r_surface_material", "-1", FCVAR_NONE, "Choose a material from 0 to N");
  36. ConVar r_surface_shader("r_surface_shader", "", FCVAR_NONE, "Choose a shader");
  37. CUtlVector< ImpParticleWithFourInterpolants, CUtlMemoryAligned< ImpParticleWithFourInterpolants, 16 > > g_SurfaceRenderParticles; // This must be aligned due to SSE use
  38. const QAngle g_SurfaceRenderAnglesAngles( 0.0f, 0.0f, 0.0f ); // our local coordinate system is always aligned to world space
  39. //-----------------------------------------------------------------------------
  40. // Purpose: Draw a Sphere
  41. //-----------------------------------------------------------------------------
  42. float g_FastSpherePosData[51][8] = {
  43. { 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 0.0000, 1.0000 },
  44. { -0.0000, 0.5000, 0.8660, 0.2500, 0.1667, -0.0000, 0.5000, 0.8660 },
  45. { 0.5000, 0.0000, 0.8660, 0.0000, 0.1667, 0.5000, 0.0000, 0.8660 },
  46. { 0.0000, 0.0000, 1.0000, 0.5000, 0.0000, 0.0000, 0.0000, 1.0000 },
  47. { -0.5000, -0.0000, 0.8660, 0.5000, 0.1667, -0.5000, -0.0000, 0.8660 },
  48. { 0.0000, 0.0000, -1.0000, 0.0000, 1.0000, 0.0000, 0.0000, -1.0000 },
  49. { 0.5000, 0.0000, -0.8660, 0.0000, 0.8333, 0.5000, 0.0000, -0.8660 },
  50. { -0.0000, 0.5000, -0.8660, 0.2500, 0.8333, -0.0000, 0.5000, -0.8660 },
  51. { 0.0000, 0.0000, -1.0000, 0.5000, 1.0000, 0.0000, 0.0000, -1.0000 },
  52. { -0.5000, -0.0000, -0.8660, 0.5000, 0.8333, -0.5000, -0.0000, -0.8660 },
  53. { 0.0000, -0.5000, 0.8660, 0.7500, 0.1667, 0.0000, -0.5000, 0.8660 },
  54. { 0.0000, 0.0000, 1.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000 },
  55. { 0.5000, 0.0000, 0.8660, 1.0000, 0.1667, 0.5000, 0.0000, 0.8660 },
  56. { 0.0000, -0.5000, -0.8660, 0.7500, 0.8333, 0.0000, -0.5000, -0.8660 },
  57. { 0.0000, 0.0000, -1.0000, 1.0000, 1.0000, 0.0000, 0.0000, -1.0000 },
  58. { 0.5000, 0.0000, -0.8660, 1.0000, 0.8333, 0.5000, 0.0000, -0.8660 },
  59. { 0.6124, 0.6124, 0.5000, 0.1250, 0.3333, 0.6124, 0.6124, 0.5000 },
  60. { 0.8660, 0.0000, 0.5000, 0.0000, 0.3333, 0.8660, 0.0000, 0.5000 },
  61. { -0.0000, 0.8660, 0.5000, 0.2500, 0.3333, -0.0000, 0.8660, 0.5000 },
  62. { 0.8660, 0.0000, -0.5000, 0.0000, 0.6667, 0.8660, 0.0000, -0.5000 },
  63. { 0.6124, 0.6124, -0.5000, 0.1250, 0.6667, 0.6124, 0.6124, -0.5000 },
  64. { -0.0000, 0.8660, -0.5000, 0.2500, 0.6667, -0.0000, 0.8660, -0.5000 },
  65. { -0.6124, 0.6124, 0.5000, 0.3750, 0.3333, -0.6124, 0.6124, 0.5000 },
  66. { -0.8660, -0.0000, 0.5000, 0.5000, 0.3333, -0.8660, -0.0000, 0.5000 },
  67. { -0.6124, 0.6124, -0.5000, 0.3750, 0.6667, -0.6124, 0.6124, -0.5000 },
  68. { -0.8660, -0.0000, -0.5000, 0.5000, 0.6667, -0.8660, -0.0000, -0.5000 },
  69. { -0.6124, -0.6124, 0.5000, 0.6250, 0.3333, -0.6124, -0.6124, 0.5000 },
  70. { 0.0000, -0.8660, 0.5000, 0.7500, 0.3333, 0.0000, -0.8660, 0.5000 },
  71. { -0.6124, -0.6124, -0.5000, 0.6250, 0.6667, -0.6124, -0.6124, -0.5000 },
  72. { 0.0000, -0.8660, -0.5000, 0.7500, 0.6667, 0.0000, -0.8660, -0.5000 },
  73. { 0.6124, -0.6124, 0.5000, 0.8750, 0.3333, 0.6124, -0.6124, 0.5000 },
  74. { 0.8660, 0.0000, 0.5000, 1.0000, 0.3333, 0.8660, 0.0000, 0.5000 },
  75. { 0.6124, -0.6124, -0.5000, 0.8750, 0.6667, 0.6124, -0.6124, -0.5000 },
  76. { 0.8660, 0.0000, -0.5000, 1.0000, 0.6667, 0.8660, 0.0000, -0.5000 },
  77. { 0.9239, 0.3827, 0.0000, 0.0625, 0.5000, 0.9239, 0.3827, 0.0000 },
  78. { 1.0000, 0.0000, 0.0000, 0.0000, 0.5000, 1.0000, 0.0000, 0.0000 },
  79. { 0.7071, 0.7071, 0.0000, 0.1250, 0.5000, 0.7071, 0.7071, 0.0000 },
  80. { 0.3827, 0.9239, 0.0000, 0.1875, 0.5000, 0.3827, 0.9239, 0.0000 },
  81. { -0.0000, 1.0000, 0.0000, 0.2500, 0.5000, -0.0000, 1.0000, 0.0000 },
  82. { -0.3827, 0.9239, 0.0000, 0.3125, 0.5000, -0.3827, 0.9239, 0.0000 },
  83. { -0.7071, 0.7071, 0.0000, 0.3750, 0.5000, -0.7071, 0.7071, 0.0000 },
  84. { -0.9239, 0.3827, 0.0000, 0.4375, 0.5000, -0.9239, 0.3827, 0.0000 },
  85. { -1.0000, -0.0000, 0.0000, 0.5000, 0.5000, -1.0000, -0.0000, 0.0000 },
  86. { -0.9239, -0.3827, 0.0000, 0.5625, 0.5000, -0.9239, -0.3827, 0.0000 },
  87. { -0.7071, -0.7071, 0.0000, 0.6250, 0.5000, -0.7071, -0.7071, 0.0000 },
  88. { -0.3827, -0.9239, 0.0000, 0.6875, 0.5000, -0.3827, -0.9239, 0.0000 },
  89. { 0.0000, -1.0000, 0.0000, 0.7500, 0.5000, 0.0000, -1.0000, 0.0000 },
  90. { 0.3827, -0.9239, 0.0000, 0.8125, 0.5000, 0.3827, -0.9239, 0.0000 },
  91. { 0.7071, -0.7071, 0.0000, 0.8750, 0.5000, 0.7071, -0.7071, 0.0000 },
  92. { 0.9239, -0.3827, 0.0000, 0.9375, 0.5000, 0.9239, -0.3827, 0.0000 },
  93. { 1.0000, 0.0000, 0.0000, 1.0000, 0.5000, 1.0000, 0.0000, 0.0000 }
  94. };
  95. int g_FastSphereTriData[84][3] = {
  96. { 0, 1, 2 },
  97. { 0, 3, 1 },
  98. { 3, 4, 1 },
  99. { 5, 6, 7 },
  100. { 5, 7, 8 },
  101. { 8, 7, 9 },
  102. { 3, 10, 4 },
  103. { 3, 11, 10 },
  104. { 11, 12, 10 },
  105. { 8, 9, 13 },
  106. { 8, 13, 14 },
  107. { 14, 13, 15 },
  108. { 2, 16, 17 },
  109. { 2, 1, 16 },
  110. { 1, 18, 16 },
  111. { 6, 19, 20 },
  112. { 6, 20, 7 },
  113. { 7, 20, 21 },
  114. { 1, 22, 18 },
  115. { 1, 4, 22 },
  116. { 4, 23, 22 },
  117. { 7, 21, 24 },
  118. { 7, 24, 9 },
  119. { 9, 24, 25 },
  120. { 4, 26, 23 },
  121. { 4, 10, 26 },
  122. { 10, 27, 26 },
  123. { 9, 25, 28 },
  124. { 9, 28, 13 },
  125. { 13, 28, 29 },
  126. { 10, 30, 27 },
  127. { 10, 12, 30 },
  128. { 12, 31, 30 },
  129. { 13, 29, 32 },
  130. { 13, 32, 15 },
  131. { 15, 32, 33 },
  132. { 17, 34, 35 },
  133. { 17, 16, 34 },
  134. { 16, 36, 34 },
  135. { 19, 35, 34 },
  136. { 19, 34, 20 },
  137. { 20, 34, 36 },
  138. { 16, 37, 36 },
  139. { 16, 18, 37 },
  140. { 18, 38, 37 },
  141. { 20, 36, 37 },
  142. { 20, 37, 21 },
  143. { 21, 37, 38 },
  144. { 18, 39, 38 },
  145. { 18, 22, 39 },
  146. { 22, 40, 39 },
  147. { 21, 38, 39 },
  148. { 21, 39, 24 },
  149. { 24, 39, 40 },
  150. { 22, 41, 40 },
  151. { 22, 23, 41 },
  152. { 23, 42, 41 },
  153. { 24, 40, 41 },
  154. { 24, 41, 25 },
  155. { 25, 41, 42 },
  156. { 23, 43, 42 },
  157. { 23, 26, 43 },
  158. { 26, 44, 43 },
  159. { 25, 42, 43 },
  160. { 25, 43, 28 },
  161. { 28, 43, 44 },
  162. { 26, 45, 44 },
  163. { 26, 27, 45 },
  164. { 27, 46, 45 },
  165. { 28, 44, 45 },
  166. { 28, 45, 29 },
  167. { 29, 45, 46 },
  168. { 27, 47, 46 },
  169. { 27, 30, 47 },
  170. { 30, 48, 47 },
  171. { 29, 46, 47 },
  172. { 29, 47, 32 },
  173. { 32, 47, 48 },
  174. { 30, 49, 48 },
  175. { 30, 31, 49 },
  176. { 31, 50, 49 },
  177. { 32, 48, 49 },
  178. { 32, 49, 33 },
  179. { 33, 49, 50 }
  180. };
  181. void Surface_DrawFastSphere( CMeshBuilder &meshBuilder, const Vector &center, float radius, float r, float g, float b )
  182. {
  183. int offset = meshBuilder.GetCurrentVertex();
  184. Vector pos;
  185. for (int i = 0; i < 51; i++)
  186. {
  187. pos.x = g_FastSpherePosData[i][0] + center.x + g_FastSpherePosData[i][5] * radius;
  188. pos.y = g_FastSpherePosData[i][1] + center.y + g_FastSpherePosData[i][6] * radius;
  189. pos.z = g_FastSpherePosData[i][2] + center.z + g_FastSpherePosData[i][7] * radius;
  190. meshBuilder.Position3fv( pos.Base() );
  191. meshBuilder.Normal3fv( &g_FastSpherePosData[i][5] );
  192. meshBuilder.TexCoord2fv( 0, &g_FastSpherePosData[i][3] );
  193. meshBuilder.Color3f( r, g, b );
  194. meshBuilder.AdvanceVertex();
  195. }
  196. for (int i = 0; i < 84; i++)
  197. {
  198. meshBuilder.FastIndex( g_FastSphereTriData[i][0] + offset );
  199. meshBuilder.FastIndex( g_FastSphereTriData[i][1] + offset );
  200. meshBuilder.FastIndex( g_FastSphereTriData[i][2] + offset );
  201. }
  202. }
  203. struct Surface_DrawSpheres_sortParticles_t
  204. {
  205. int no;
  206. float dist;
  207. class C
  208. {
  209. public:
  210. static bool gt(Surface_DrawSpheres_sortParticles_t a, Surface_DrawSpheres_sortParticles_t b)
  211. {
  212. return a.dist < b.dist;
  213. }
  214. };
  215. };
  216. void Surface_DrawSpheres( IMaterial *pMaterial, float flRadius )
  217. {
  218. Point3D eye = view->GetViewSetup()->origin;
  219. SmartArray<Surface_DrawSpheres_sortParticles_t> sort_particles;
  220. sort_particles.ensureCapacity(g_SurfaceRenderParticles.Count());
  221. sort_particles.size = g_SurfaceRenderParticles.Count();
  222. for(int i = 0; i < g_SurfaceRenderParticles.Count(); i++)
  223. {
  224. sort_particles[i].no = i;
  225. sort_particles[i].dist = g_SurfaceRenderParticles[i].center.length(eye);
  226. }
  227. sort_particles.sort<Surface_DrawSpheres_sortParticles_t::C>();
  228. CMatRenderContextPtr pRenderContext( materials );
  229. pRenderContext->MatrixMode( MATERIAL_MODEL );
  230. pRenderContext->Bind( pMaterial );
  231. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  232. int vertMax = MIN( 24000 / 51, 32768 / (84 * 3) );
  233. int j = 0;
  234. // Msg( "point %.2f %.2f %.2f\n", m_vecSurfacePos[0].x, m_vecSurfacePos[0].y, m_vecSurfacePos[0].z );
  235. while (j < g_SurfaceRenderParticles.Count())
  236. {
  237. int total = MIN( g_SurfaceRenderParticles.Count() - j, vertMax );
  238. CMeshBuilder meshBuilder;
  239. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, total * 51, total * 84 * 3 );
  240. int i = 0;
  241. while (i < vertMax && j < g_SurfaceRenderParticles.Count())
  242. {
  243. ImpParticleWithOneInterpolant* imp_particle = &(g_SurfaceRenderParticles[sort_particles[j].no]);
  244. if (imp_particle->scale > 0.01)
  245. {
  246. Surface_DrawFastSphere( meshBuilder, imp_particle->center.AsVector(), flRadius * imp_particle->scale, imp_particle->interpolants1[0], imp_particle->interpolants1[1], imp_particle->interpolants1[2] );
  247. i++;
  248. }
  249. j++;
  250. }
  251. meshBuilder.End();
  252. pMesh->Draw();
  253. }
  254. }
  255. void Surface_SafeLightCubeUpdate( const Vector &vecRenderOrigin, Vector4D *cachedCubeColours )
  256. {
  257. // We sometimes get an invalid ambient lightcube for the isosurface sample point, this func smooths over that
  258. // FIXME: this is probably to do with sampling at invalid locations
  259. // FIXME: we need more complex lighting data for isosurfaces anyway
  260. // (per-vertex light sample indices ala skinning, or UVWs into a light sample texture)
  261. Vector boxColors[6];
  262. engine->ComputeLightingCube( vecRenderOrigin, false, boxColors );
  263. // Are we trying to sample outside the world?
  264. bool invalidOrigin = enginetrace->PointOutsideWorld( vecRenderOrigin );
  265. for ( int i = 0; i < 6; i++ )
  266. {
  267. if( !IsFinite( boxColors[i].x ) || !IsFinite( boxColors[i].y ) || !IsFinite( boxColors[i].z ) )
  268. {
  269. DevWarning( "Isosurface lighting cube with infinite values!\n%s",
  270. invalidOrigin ? "(lighting origin is !OUTSIDE! the world)\n" : "" );
  271. return;
  272. }
  273. }
  274. for ( int i = 0; i < 6; i++ )
  275. {
  276. if( boxColors[i].x < -0.1f || boxColors[i].y < -0.1f || boxColors[i].z < -0.1f )
  277. {
  278. DevWarning( "Isosurface lighting cube negative: %f %f %f\n%s", boxColors[i].x, boxColors[i].y, boxColors[i].z,
  279. invalidOrigin ? "(lighting origin is !OUTSIDE! the world)\n" : "" );
  280. }
  281. cachedCubeColours[i].AsVector3D() = Lerp( clamp( 2.0f * gpGlobals->frametime, 0.0f, 1.0f ), cachedCubeColours[i].AsVector3D(), boxColors[i] );
  282. }
  283. bool bBadLightCube = false;
  284. for ( int i = 0; i < 6; i++ )
  285. {
  286. if ( !IsFinite( cachedCubeColours[i].x ) || !IsFinite( cachedCubeColours[i].y ) || !IsFinite( cachedCubeColours[i].z ) ||
  287. ( cachedCubeColours[i].x < -0.01f ) || ( cachedCubeColours[i].y < -0.01f ) || ( cachedCubeColours[i].z < -0.01f ) )
  288. {
  289. DevWarning( "Isosurface lighting cube bad. Resetting.\n%s",
  290. invalidOrigin ? "(lighting origin is !OUTSIDE! the world)\n" : "" );
  291. bBadLightCube = true;
  292. break;
  293. }
  294. }
  295. if ( bBadLightCube )
  296. {
  297. memset( cachedCubeColours, 0, sizeof( cachedCubeColours ) );
  298. }
  299. }
  300. IMaterial* GetDrawMaterial( void )
  301. {
  302. if ( r_surface_wireframe.GetBool() )
  303. {
  304. if( r_surface_material.GetInt() < 0 )
  305. {
  306. return materials->FindMaterial("shadertest/wireframe", TEXTURE_GROUP_OTHER);
  307. }
  308. else
  309. {
  310. return materials->FindMaterial("shadertest/wireframevertexcolornocull", TEXTURE_GROUP_OTHER);
  311. }
  312. }
  313. else if ( strlen( r_surface_shader.GetString() ) > 0 )
  314. {
  315. return materials->FindMaterial( r_surface_shader.GetString(), TEXTURE_GROUP_OTHER, true );
  316. }
  317. else
  318. {
  319. switch ( r_surface_material.GetInt() )
  320. {
  321. case 0:
  322. return materials->FindMaterial( "models/debug/debugwhite", TEXTURE_GROUP_OTHER, true );
  323. case 1:
  324. return materials->FindMaterial( "models/debug/debugwhite2", TEXTURE_GROUP_OTHER, true );
  325. case 2:
  326. return materials->FindMaterial( "models/debug/debugwhite3", TEXTURE_GROUP_OTHER, true );
  327. case 3:
  328. return materials->FindMaterial( "debug/debugvertexcolor", TEXTURE_GROUP_OTHER, true );
  329. case 4:
  330. return materials->FindMaterial( "debug/env_cubemap_model", TEXTURE_GROUP_OTHER, true );
  331. case 5:
  332. return materials->FindMaterial( "models/blob/env_cubemap_model_translucent_fountain", TEXTURE_GROUP_OTHER, true );
  333. case 6:
  334. return materials->FindMaterial( "models/debug/debugmesh", TEXTURE_GROUP_OTHER, true );
  335. case 7:
  336. return materials->FindMaterial( "models/debug/debugmesh_transparent", TEXTURE_GROUP_OTHER, true );
  337. case 8:
  338. return materials->FindMaterial( "models/ihvtest/tongue_bumped", TEXTURE_GROUP_OTHER, true );
  339. case 9:
  340. return materials->FindMaterial( "models/debug/debugbumps", TEXTURE_GROUP_OTHER, true );
  341. case 10:
  342. return materials->FindMaterial( "debug/env_cubemap_model_translucent_no_bumps", TEXTURE_GROUP_OTHER, true );
  343. case 11:
  344. return materials->FindMaterial( "models/shadertest/predator", TEXTURE_GROUP_OTHER, true );
  345. default:
  346. return NULL;
  347. }
  348. }
  349. }
  350. void SetUpImpRendererUserDefinedFuncs( void )
  351. {
  352. RENDERER_CLASS::setCalcSignFunc(calcSign);
  353. RENDERER_CLASS::setCalcSign2Func(calcSign2);
  354. if(r_surface_calc_uv_and_tan.GetBool())
  355. {
  356. RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_COLOR_UV_TAN_CI_SIZE, calcCornerNormalColorUVTan);
  357. //RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNColorUVTan);
  358. RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNTexCoord4); // HACKHACK: This is blob specific!
  359. }
  360. else if(r_surface_calc_tan_only.GetBool())
  361. {
  362. RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_COLOR_UV_TAN_CI_SIZE, calcCornerNormalColorTanNoUV);
  363. RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNColorTanNoUV);
  364. }
  365. else if (r_surface_calc_color.GetBool())
  366. {
  367. RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_COLOR_CI_SIZE, calcCornerNormalColor);
  368. RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNColor);
  369. }
  370. else if (r_surface_calc_hifreq_color.GetBool())
  371. {
  372. RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_COLOR_CI_SIZE, calcCornerNormalHiFreqColor);
  373. RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalNColor);
  374. }
  375. else if (r_surface_calc_tile_color.GetBool())
  376. {
  377. RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_CI_SIZE, calcCornerNormal);
  378. RENDERER_CLASS::setCalcVertexFunc(calcVertexNormalDebugColor);
  379. }
  380. else
  381. {
  382. RENDERER_CLASS::setCalcCornerFunc(CALC_CORNER_NORMAL_CI_SIZE, calcCornerNormal);
  383. RENDERER_CLASS::setCalcVertexFunc(calcVertexNormal);
  384. }
  385. }
  386. void TransformParticles( float angle, const Vector& center, Vector& transformedCenter, Vector& transformedEye, VMatrix& rotationMatrix, VMatrix& invRotationMatrix )
  387. {
  388. for (int i = 0; i < g_SurfaceRenderParticles.Count(); i++)
  389. {
  390. ImpParticleWithFourInterpolants* imp_particle = &(g_SurfaceRenderParticles[i]);
  391. Vector vParticle = imp_particle->center.AsVector();
  392. Vector transformedParticle = vParticle-center;
  393. transformedParticle = rotationMatrix.ApplyRotation(transformedParticle);
  394. Point3D pParticle = transformedParticle;
  395. imp_particle->center = pParticle;
  396. // HACK ALERT!!!
  397. // TODO: This code should not be here as this is very specific to blobs.
  398. // interpolants1[0..2] is the color. interpolants1[3] is the v coordinate
  399. // imp_particle1->interpolants1[3] = MIN(MAX(1.4f - vec.length()/17.0f, 0.0f), 1.0f);
  400. // interpolants2[0..2] is the tangent vector.
  401. // interpolants3[0..2] and interpolants4[0..2] are the normal and
  402. // binormal which are used to generate a u coordinate
  403. Point3D pCenter = transformedCenter;
  404. Point3D vec = (pParticle - pCenter);
  405. imp_particle->interpolants2 = vec.unit();
  406. imp_particle->interpolants4.set(0.0f, 0.0f, -1.0f);
  407. imp_particle->interpolants3 = imp_particle->interpolants2.crossProduct(imp_particle->interpolants4);
  408. imp_particle->interpolants3.normalize();
  409. imp_particle->interpolants4 = imp_particle->interpolants2.crossProduct(imp_particle->interpolants3);
  410. imp_particle->interpolants4.normalize();
  411. }
  412. }
  413. void Surface_DrawIsoSurface( IClientRenderable *pClientRenderable, const Vector &vecRenderOrigin, IMaterial *pMaterial, float flCubeWidth )
  414. {
  415. IMaterial *pSpecialMaterial = GetDrawMaterial();
  416. if( pSpecialMaterial && !IsErrorMaterial( pSpecialMaterial ) )
  417. {
  418. pMaterial = pSpecialMaterial;
  419. }
  420. //////////////////////////////////////////////////
  421. // Set up the render context
  422. /////////////////////////////////////////////////
  423. CMatRenderContextPtr pRenderContext( materials );
  424. pRenderContext->MatrixMode( MATERIAL_MODEL );
  425. pRenderContext->Bind( pMaterial, pClientRenderable );
  426. pRenderContext->PushMatrix();
  427. pRenderContext->LoadIdentity();
  428. ////////////////////////////////////////////////////
  429. // Set up rotations and translations and corresponding matrices.
  430. ////////////////////////////////////////////////////
  431. Vector transformedCenter = vecRenderOrigin;
  432. pRenderContext->Translate(vecRenderOrigin.x, vecRenderOrigin.y, vecRenderOrigin.z);
  433. VMatrix rotationMatrix;
  434. VMatrix invRotationMatrix;
  435. Vector transformedEye;
  436. float angle = 0.0f;
  437. if( r_surface_rotate.GetBool() )
  438. {
  439. angle = view->GetViewSetup()->angles.y+180.0f;
  440. if( r_surface_rotate_by90.GetBool() )
  441. {
  442. // This is a test mode which locks the rotation to a multiple of 90.
  443. angle = float(int((angle + 45.0f) / 90.0f) * 90);
  444. }
  445. pRenderContext->Rotate(angle, 0.0f, 0.0f, 1.0f);
  446. rotationMatrix = SetupMatrixAxisRot(Vector(0.0f, 0.0f, 1.0f), -angle);
  447. invRotationMatrix = SetupMatrixAxisRot(Vector(0.0f, 0.0f, 1.0f), angle);
  448. Vector eye = view->GetViewSetup()->origin;
  449. transformedEye = eye-vecRenderOrigin;
  450. transformedEye = rotationMatrix.ApplyRotation(transformedEye);
  451. }
  452. else
  453. {
  454. rotationMatrix.Identity();
  455. invRotationMatrix.Identity();
  456. transformedEye.Init();
  457. angle = 0.0f;
  458. }
  459. ///////////////////////////////////////////////////////////////
  460. // Begin Rendering by initializing the sweepRenderer or Tiler
  461. // (depending on whether we're using the tiler)
  462. ///////////////////////////////////////////////////////////////
  463. // TODO: These probably shouldn't be static variables (not thread safe)
  464. RENDERER_CLASS::setCubeWidth( flCubeWidth * r_surface_blr_scale.GetFloat() * r_surface_blr_cubewidth.GetFloat());
  465. RENDERER_CLASS::setRenderR( flCubeWidth * r_surface_blr_scale.GetFloat() * r_surface_blr_render_radius.GetFloat());
  466. RENDERER_CLASS::setCutoffR( flCubeWidth * r_surface_blr_scale.GetFloat() * r_surface_blr_cutoff_radius.GetFloat());
  467. SetUpImpRendererUserDefinedFuncs();
  468. TransformParticles( angle, vecRenderOrigin, transformedCenter, transformedEye, rotationMatrix, invRotationMatrix );
  469. ///////////////////////////////////////////////////////////////
  470. // Insert the particles into the tiler/renderer, and do a rendering
  471. // pass. If we are tiling, we can also visualize the tiles and slices.
  472. ///////////////////////////////////////////////////////////////
  473. if( r_surface_debug_use_tiler.GetBool() )
  474. {
  475. ImpTiler* tiler = ImpTilerFactory::factory->getTiler();
  476. RENDERER_CLASS* sweepRenderer = tiler->getRenderer();
  477. tiler->setMaxNoTilesToDraw(r_surface_debug_max_tiles.GetInt());
  478. sweepRenderer->setMaxNoSlicesToDraw(r_surface_debug_max_slices.GetInt());
  479. // TODO: Do we always want to center the tiler on 0,0,0?
  480. // I guess if we are centering the render coordinates, then the answer
  481. // is a yes.
  482. tiler->beginFrame(Point3D(0.0f, 0.0f, 0.0f), (void*)&pRenderContext, !(r_surface_debug_draw_margin.GetBool()));
  483. for (int i = 0; i < g_SurfaceRenderParticles.Count(); i++)
  484. {
  485. tiler->insertParticle(&g_SurfaceRenderParticles[i]);
  486. }
  487. if(r_surface_debug_tile.GetBool())
  488. {
  489. if(r_surface_rotate.GetBool())
  490. {
  491. tiler->drawSurfaceSorted(Point3D(transformedEye));
  492. }
  493. else
  494. {
  495. tiler->drawSurface();
  496. }
  497. // This is code used for visualizing the boundaries of every tile that's drawn
  498. // and maybe in the future, slices within the tiles.
  499. if( r_surface_debug_draw_tile_boundaries.GetBool() == true )
  500. {
  501. for( int i = 0; i < tiler->getNoTiles(); i++ )
  502. {
  503. Vector overlayCenter = invRotationMatrix.ApplyRotation(tiler->getTileOffset(i).AsVector());
  504. Vector mins = tiler->getRenderDim().AsVector() * -0.5f;
  505. Vector maxs = tiler->getRenderDim().AsVector() * 0.5f;
  506. debugoverlay->AddBoxOverlay(overlayCenter + vecRenderOrigin, mins, maxs, QAngle( 0, angle, 0 ), 0, 255, 0, 0, 0 );
  507. }
  508. }
  509. }
  510. else
  511. {
  512. tiler->drawTile(0,0,0);
  513. // This is code used for visualizing the boundaries of the last tile drawn
  514. // slices within that tile
  515. if( r_surface_debug_max_tiles.GetInt() > 0 || r_surface_debug_tile.GetBool() == false )
  516. {
  517. Vector overlayCenter = invRotationMatrix.ApplyRotation(tiler->getLastTilesOffset().AsVector());
  518. Vector mins = tiler->getRenderDim().AsVector() * -0.5f;
  519. Vector maxs = tiler->getRenderDim().AsVector() * 0.5f;
  520. debugoverlay->AddBoxOverlay(overlayCenter + vecRenderOrigin, mins, maxs, QAngle( 0, angle, 0 ), 0, 255, 0, 0, 0 );
  521. if( r_surface_debug_max_slices.GetInt() > 0 )
  522. {
  523. Vector sliceMins = mins;
  524. Vector sliceMaxs = maxs;
  525. sliceMins.x += (sweepRenderer->getLastSliceDrawn() - sweepRenderer->getMarginNCubes()) * sweepRenderer->getCubeWidth();
  526. sliceMaxs.x = sliceMins.x + sweepRenderer->getCubeWidth();
  527. debugoverlay->AddBoxOverlay( overlayCenter + vecRenderOrigin, sliceMins, sliceMaxs, QAngle( 0, angle, 0 ), 255, 0, 0, 0, 0 );
  528. }
  529. }
  530. }
  531. tiler->endFrame();
  532. ImpTilerFactory::factory->returnTiler(tiler);
  533. }
  534. else
  535. {
  536. RENDERER_CLASS* sweepRenderer = ImpRendererFactory::factory->getRenderer();
  537. // This is the no tiler version. We just draw the center tile.
  538. sweepRenderer->beginFrame(!(r_surface_debug_draw_margin.GetBool()), (void*)&pRenderContext);
  539. sweepRenderer->setOffset(Point3D(0.0f, 0.0f, 0.0f));
  540. sweepRenderer->beginTile(NULL);
  541. for (int i = 0; i < g_SurfaceRenderParticles.Count(); i++)
  542. {
  543. sweepRenderer->addParticle(&(g_SurfaceRenderParticles[i]));
  544. }
  545. sweepRenderer->endTile();
  546. sweepRenderer->endFrame();
  547. ImpRendererFactory::factory->returnRenderer(sweepRenderer);
  548. }
  549. //////////////////////////////////////
  550. // Clean up render context
  551. //////////////////////////////////////
  552. pRenderContext->PopMatrix();
  553. }
  554. void Surface_CullOutOfViewParticles( void )
  555. {
  556. int iParticlesRemoved = 0;
  557. for ( int i = 0; i < g_SurfaceRenderParticles.Count() - iParticlesRemoved; ++i )
  558. {
  559. ImpParticleWithOneInterpolant* imp_particle = &(g_SurfaceRenderParticles[ i ]);
  560. Vector vCenter = Vector( imp_particle->center[ 0 ], imp_particle->center[ 1 ], imp_particle->center[ 2 ] );
  561. if ( R_CullSphere( view->GetFrustum(), 5, &vCenter, imp_particle->scale * 24.0f ) )
  562. {
  563. ImpParticleWithOneInterpolant* last_particle = &(g_SurfaceRenderParticles[ g_SurfaceRenderParticles.Count() - iParticlesRemoved - 1 ]);
  564. *imp_particle = *last_particle;
  565. ++iParticlesRemoved;
  566. --i;
  567. }
  568. }
  569. if ( iParticlesRemoved )
  570. {
  571. g_SurfaceRenderParticles.SetCountNonDestructively( g_SurfaceRenderParticles.Count() - iParticlesRemoved );
  572. }
  573. }
  574. void Surface_Draw( IClientRenderable *pClientRenderable, const Vector &vecRenderOrigin, IMaterial *pMaterial, float flCubeWidth, bool bSurfaceNoParticleCull )
  575. {
  576. if ( !bSurfaceNoParticleCull )
  577. {
  578. // Reduce the complexity by first removing particles that won't visibly affect the view
  579. Surface_CullOutOfViewParticles();
  580. }
  581. if ( !r_surface_draw_isosurface.GetBool() )
  582. {
  583. // This draws particles as spheres instead of an isosurface
  584. Surface_DrawSpheres( pMaterial, flCubeWidth );
  585. }
  586. else
  587. {
  588. Surface_DrawIsoSurface( pClientRenderable, vecRenderOrigin, pMaterial, flCubeWidth );
  589. }
  590. }
  591. #endif