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.

432 lines
12 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "matsys_controls/vtfpreviewpanel.h"
  7. #include "matsys_controls/matsyscontrols.h"
  8. #include "VGuiMatSurface/IMatSystemSurface.h"
  9. #include "materialsystem/MaterialSystemUtil.h"
  10. #include "materialsystem/imaterialsystem.h"
  11. #include "materialsystem/itexture.h"
  12. #include "materialsystem/imesh.h"
  13. #include "tier1/keyvalues.h"
  14. // NOTE: This has to be the last file included!
  15. #include "tier0/memdbgon.h"
  16. using namespace vgui;
  17. #define FOV 90.0f
  18. #define ZNEAR 0.1f
  19. #define ZFAR 2000.0f
  20. #define ROTATION_SPEED 120.0f // degrees/sec
  21. //-----------------------------------------------------------------------------
  22. //
  23. // VTF Preview panel
  24. //
  25. //-----------------------------------------------------------------------------
  26. //-----------------------------------------------------------------------------
  27. // constructor
  28. //-----------------------------------------------------------------------------
  29. CVTFPreviewPanel::CVTFPreviewPanel( vgui::Panel *pParent, const char *pName ) :
  30. BaseClass( pParent, pName )
  31. {
  32. SetVTF( "//platform/materials/vgui/vtfnotloaded", true );
  33. m_nTextureID = MatSystemSurface()->CreateNewTextureID( false );
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Sets the current VTF
  37. //-----------------------------------------------------------------------------
  38. void CVTFPreviewPanel::SetVTF( const char *pFullPath, bool bLoadImmediately )
  39. {
  40. m_PreviewTexture.Init( pFullPath, "editor texture" );
  41. m_VTFName = pFullPath;
  42. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  43. if ( m_PreviewTexture->IsCubeMap() )
  44. {
  45. pVMTKeyValues->SetString( "$envmap", pFullPath );
  46. }
  47. else if ( m_PreviewTexture->IsNormalMap() )
  48. {
  49. pVMTKeyValues->SetString( "$bumpmap", pFullPath );
  50. }
  51. else
  52. {
  53. pVMTKeyValues->SetString( "$basetexture", pFullPath );
  54. }
  55. pVMTKeyValues->SetInt( "$nocull", 1 );
  56. pVMTKeyValues->SetInt( "$nodebug", 1 );
  57. m_PreviewMaterial.Init( MaterialSystem()->CreateMaterial( pFullPath, pVMTKeyValues ));
  58. MatSystemSurface()->DrawSetTextureMaterial( m_nTextureID, m_PreviewMaterial );
  59. // Reset the camera direction
  60. m_vecCameraDirection.Init( 1.0f, 0.0f, 0.0f );
  61. m_flLastRotationTime = Plat_FloatTime();
  62. }
  63. void CVTFPreviewPanel::SetTwoVTFs( const char *pFullPath, const char *pSecondFullPath )
  64. {
  65. m_PreviewTexture.Init( pFullPath, "editor texture" );
  66. m_VTFName = pFullPath;
  67. m_SecondPreviewTexture.Init( pSecondFullPath, "editor texture" );
  68. m_SecondVTFName = pSecondFullPath;
  69. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  70. if ( m_PreviewTexture->IsCubeMap() )
  71. {
  72. pVMTKeyValues->SetString( "$envmap", pFullPath );
  73. }
  74. else if ( m_PreviewTexture->IsNormalMap() )
  75. {
  76. pVMTKeyValues->SetString( "$bumpmap", pFullPath );
  77. }
  78. else
  79. {
  80. pVMTKeyValues->SetString( "$basetexture", pFullPath );
  81. }
  82. pVMTKeyValues->SetString( "$detail", pSecondFullPath );
  83. pVMTKeyValues->SetInt( "$detailscale", 1 );
  84. pVMTKeyValues->SetInt( "$detailblendmode", 1 ); // additive
  85. pVMTKeyValues->SetInt( "$nocull", 1 );
  86. pVMTKeyValues->SetInt( "$nodebug", 1 );
  87. m_PreviewMaterial.Init( MaterialSystem()->CreateMaterial( pFullPath, pVMTKeyValues ));
  88. MatSystemSurface()->DrawSetTextureMaterial( m_nTextureID, m_PreviewMaterial );
  89. // Reset the camera direction
  90. m_vecCameraDirection.Init( 1.0f, 0.0f, 0.0f );
  91. m_flLastRotationTime = Plat_FloatTime();
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Gets the current VTF
  95. //-----------------------------------------------------------------------------
  96. const char *CVTFPreviewPanel::GetVTF() const
  97. {
  98. return m_VTFName;
  99. }
  100. const char *CVTFPreviewPanel::GetSecondVTF() const
  101. {
  102. return m_SecondVTFName;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Draw a sphere
  106. //-----------------------------------------------------------------------------
  107. void CVTFPreviewPanel::RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi )
  108. {
  109. CMatRenderContextPtr pRenderContext( MaterialSystem() );
  110. int nVertices = nTheta * nPhi;
  111. int nIndices = 2 * ( nTheta + 1 ) * ( nPhi - 1 );
  112. pRenderContext->FogMode( MATERIAL_FOG_NONE );
  113. pRenderContext->SetNumBoneWeights( 0 );
  114. pRenderContext->Bind( m_PreviewMaterial );
  115. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  116. CMeshBuilder meshBuilder;
  117. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, nVertices, nIndices );
  118. //
  119. // Build the index buffer.
  120. //
  121. int i, j;
  122. for ( i = 0; i < nPhi; ++i )
  123. {
  124. for ( j = 0; j < nTheta; ++j )
  125. {
  126. float u = j / ( float )(nTheta - 1);
  127. float v = i / ( float )(nPhi - 1);
  128. float theta = ( j != nTheta-1 ) ? 2.0f * M_PI * u : 0.0f;
  129. float phi = M_PI * v;
  130. Vector vecPos;
  131. vecPos.x = flRadius * sin(phi) * cos(theta);
  132. vecPos.y = flRadius * cos(phi);
  133. vecPos.z = -flRadius * sin(phi) * sin(theta);
  134. Vector vecNormal = vecPos;
  135. VectorNormalize( vecNormal );
  136. Vector4D vecTangentS;
  137. Vector vecTangentT;
  138. vecTangentS.Init( vecPos.z, -vecPos.x, 0.0f, 1.0f );
  139. if ( VectorNormalize( vecTangentS.AsVector3D() ) == 0.0f )
  140. {
  141. vecTangentS.Init( 1.0f, 0.0f, 0.0f, 1.0f );
  142. }
  143. CrossProduct( vecNormal, vecTangentS.AsVector3D(), vecTangentT );
  144. unsigned char red = (int)( u * 255.0f );
  145. unsigned char green = (int)( v * 255.0f );
  146. unsigned char blue = (int)( v * 255.0f );
  147. unsigned char alpha = (int)( v * 255.0f );
  148. vecPos += vCenter;
  149. float u1, u2, v1, v2;
  150. u1 = u2 = u;
  151. v1 = v2 = v;
  152. meshBuilder.Position3fv( vecPos.Base() );
  153. meshBuilder.Normal3fv( vecNormal.Base() );
  154. meshBuilder.Color4ub( red, green, blue, alpha );
  155. meshBuilder.TexCoord2f( 0, u, v );
  156. meshBuilder.TexCoord2f( 1, u1, v1 );
  157. meshBuilder.TexCoord2f( 2, u2, v2 );
  158. meshBuilder.TangentS3fv( vecTangentS.Base() );
  159. meshBuilder.TangentT3fv( vecTangentT.Base() );
  160. meshBuilder.BoneWeight( 0, 1.0f );
  161. meshBuilder.BoneMatrix( 0, 0 );
  162. meshBuilder.UserData( vecTangentS.Base() );
  163. meshBuilder.AdvanceVertex();
  164. }
  165. }
  166. //
  167. // Emit the triangle strips.
  168. //
  169. int idx = 0;
  170. for ( i = 0; i < nPhi - 1; ++i )
  171. {
  172. for ( j = 0; j < nTheta; ++j )
  173. {
  174. idx = nTheta * i + j;
  175. meshBuilder.FastIndex( idx );
  176. meshBuilder.FastIndex( idx + nTheta );
  177. }
  178. //
  179. // Emit a degenerate triangle to skip to the next row without
  180. // a connecting triangle.
  181. //
  182. if ( i < nPhi - 2 )
  183. {
  184. meshBuilder.FastIndex( idx + 1 );
  185. meshBuilder.FastIndex( idx + 1 + nTheta );
  186. }
  187. }
  188. meshBuilder.End();
  189. pMesh->Draw();
  190. }
  191. //-----------------------------------------------------------------------------
  192. // Paints a regular texture
  193. //-----------------------------------------------------------------------------
  194. void CVTFPreviewPanel::PaintStandardTexture( void )
  195. {
  196. int x, y, w, h;
  197. x = y = 0;
  198. GetSize( w, h );
  199. vgui::surface()->DrawSetTexture( m_nTextureID );
  200. vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
  201. // Get the aspect ratio of the texture
  202. int tw = m_PreviewTexture->GetActualWidth();
  203. int th = m_PreviewTexture->GetActualHeight();
  204. if ( th > 0 && h > 0 )
  205. {
  206. float screenaspect = (float)tw / (float)th;
  207. float aspect = (float)w / (float)h;
  208. float ratio = screenaspect / aspect;
  209. // Screen is wider, need bars at top and bottom
  210. if ( ratio > 1.0f )
  211. {
  212. int usetall = (float)w / screenaspect;
  213. y = ( h - usetall ) / 2;
  214. h = usetall;
  215. }
  216. // Screen is narrower, need bars at left/right
  217. else
  218. {
  219. int usewide = (float)h * screenaspect;
  220. x = ( w - usewide ) / 2;
  221. w = usewide;
  222. }
  223. }
  224. vgui::surface()->DrawTexturedRect( x, y, x+w, y+h );
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Paints a normalmap texture
  228. //-----------------------------------------------------------------------------
  229. void CVTFPreviewPanel::PaintNormalMapTexture( void )
  230. {
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Paints a volume texture
  234. //-----------------------------------------------------------------------------
  235. void CVTFPreviewPanel::PaintVolumeTexture( void )
  236. {
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Paints a cubemap texture
  240. //-----------------------------------------------------------------------------
  241. void CVTFPreviewPanel::PaintCubeTexture( void )
  242. {
  243. float flNewTime = Plat_FloatTime();
  244. // Circle the camera around the origin
  245. VMatrix rot;
  246. MatrixBuildRotateZ( rot, ROTATION_SPEED * (flNewTime - m_flLastRotationTime ) );
  247. Vector vecTemp;
  248. Vector3DMultiply( rot, m_vecCameraDirection, vecTemp );
  249. m_vecCameraDirection = vecTemp;
  250. m_flLastRotationTime = flNewTime;
  251. LookAt( vec3_origin, 12.0f );
  252. // Draw a sphere at the origin
  253. RenderSphere( vec3_origin, 10.0f, 20, 20 );
  254. }
  255. //-----------------------------------------------------------------------------
  256. // Sets the camera to look at the the thing we're spinning around
  257. //-----------------------------------------------------------------------------
  258. void CVTFPreviewPanel::LookAt( const Vector &vecLookAt, float flRadius )
  259. {
  260. // Compute the distance to the camera for the object based on its
  261. // radius and fov.
  262. // since tan( fov/2 ) = f/d
  263. // cos( fov/2 ) = r / r' where r = sphere radius, r' = perp distance from sphere center to max extent of camera
  264. // d/f = r'/d' where d' is distance of camera to sphere
  265. // d' = r' / tan( fov/2 ) * r' = r / ( cos (fov/2) * tan( fov/2 ) ) = r / sin( fov/2 )
  266. float flFOVx = FOV;
  267. // Compute fov/2 in radians
  268. flFOVx *= M_PI / 360.0f;
  269. // Compute an effective fov based on the aspect ratio
  270. // if the height is smaller than the width
  271. int w, h;
  272. GetSize( w, h );
  273. if ( h < w )
  274. {
  275. flFOVx = atan( h * tan( flFOVx ) / w );
  276. }
  277. float flDistance = flRadius / sin( flFOVx );
  278. Vector vecMDLOrigin = vecLookAt;
  279. Vector vecCameraOrigin;
  280. VectorMA( vecMDLOrigin, -flDistance, m_vecCameraDirection, vecCameraOrigin );
  281. CMatRenderContextPtr pRenderContext( MaterialSystem() );
  282. QAngle angles;
  283. VectorAngles( m_vecCameraDirection, angles );
  284. pRenderContext->MatrixMode( MATERIAL_VIEW );
  285. pRenderContext->LoadIdentity();
  286. // convert from a right handed system to a left handed system
  287. // since dx for wants it that way.
  288. // pRenderContext->Scale( 1.0f, 1.0f, -1.0f );
  289. pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
  290. pRenderContext->Rotate( 90, 0, 0, 1 ); // put Z going up
  291. pRenderContext->Rotate( -angles[2], 1, 0, 0 );
  292. pRenderContext->Rotate( -angles[0], 0, 1, 0 );
  293. pRenderContext->Rotate( -angles[1], 0, 0, 1 );
  294. pRenderContext->Translate( -vecCameraOrigin[0], -vecCameraOrigin[1], -vecCameraOrigin[2] );
  295. }
  296. //-----------------------------------------------------------------------------
  297. // Set up a projection matrix for a 90 degree fov
  298. //-----------------------------------------------------------------------------
  299. void CVTFPreviewPanel::SetupProjectionMatrix( int nWidth, int nHeight )
  300. {
  301. CMatRenderContextPtr pRenderContext( MaterialSystem() );
  302. VMatrix proj;
  303. float flFOV = FOV;
  304. float flZNear = ZNEAR;
  305. float flZFar = ZFAR;
  306. float flApsectRatio = (nHeight != 0.0f) ? (float)nWidth / (float)nHeight : 100.0f;
  307. #if 1
  308. float halfWidth = tan( flFOV * M_PI / 360.0 );
  309. float halfHeight = halfWidth / flApsectRatio;
  310. #else
  311. float halfHeight = tan( flFOV * M_PI / 360.0 );
  312. float halfWidth = flApsectRatio * halfHeight;
  313. #endif
  314. memset( proj.Base(), 0, sizeof( proj ) );
  315. proj[0][0] = 1.0f / halfWidth;
  316. proj[1][1] = 1.0f / halfHeight;
  317. proj[2][2] = flZFar / ( flZNear - flZFar );
  318. proj[3][2] = -1.0f;
  319. proj[2][3] = flZNear * flZFar / ( flZNear - flZFar );
  320. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  321. pRenderContext->LoadMatrix( proj );
  322. }
  323. //-----------------------------------------------------------------------------
  324. // Paints the texture
  325. //-----------------------------------------------------------------------------
  326. void CVTFPreviewPanel::Paint( void )
  327. {
  328. if ( !m_PreviewTexture->IsCubeMap() && /*!m_PreviewTexture->IsNormalMap() &&*/ !m_PreviewTexture->IsVolumeTexture() )
  329. {
  330. PaintStandardTexture();
  331. return;
  332. }
  333. CMatRenderContextPtr pRenderContext( MaterialSystem() );
  334. int w, h;
  335. GetSize( w, h );
  336. vgui::MatSystemSurface()->Begin3DPaint( 0, 0, w, h );
  337. pRenderContext->ClearColor4ub( 76, 88, 68, 255 );
  338. pRenderContext->ClearBuffers( true, true );
  339. SetupProjectionMatrix( w, h );
  340. if ( m_PreviewTexture->IsCubeMap() )
  341. {
  342. PaintCubeTexture();
  343. }
  344. else if ( m_PreviewTexture->IsNormalMap() )
  345. {
  346. PaintNormalMapTexture();
  347. }
  348. else if ( m_PreviewTexture->IsVolumeTexture() )
  349. {
  350. PaintVolumeTexture();
  351. }
  352. vgui::MatSystemSurface()->End3DPaint( );
  353. }