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.

419 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "meshbase.h"
  7. #include "shaderapi_global.h"
  8. // memdbgon must be the last include file in a .cpp file!!!
  9. #include "tier0/memdbgon.h"
  10. //-----------------------------------------------------------------------------
  11. // Helpers with VertexDesc_t...
  12. //-----------------------------------------------------------------------------
  13. // FIXME: add compression-agnostic read-accessors (which decompress and return by value, checking desc.m_CompressionType)
  14. inline Vector &Position( VertexDesc_t const &desc, int vert )
  15. {
  16. return *(Vector*)((unsigned char*)desc.m_pPosition + vert * desc.m_VertexSize_Position );
  17. }
  18. inline float Wrinkle( VertexDesc_t const &desc, int vert )
  19. {
  20. return *(float*)((unsigned char*)desc.m_pWrinkle + vert * desc.m_VertexSize_Wrinkle );
  21. }
  22. inline float *BoneWeight( VertexDesc_t const &desc, int vert )
  23. {
  24. Assert( desc.m_CompressionType == VERTEX_COMPRESSION_NONE );
  25. return (float*)((unsigned char*)desc.m_pBoneWeight + vert * desc.m_VertexSize_BoneWeight );
  26. }
  27. inline unsigned char *BoneIndex( VertexDesc_t const &desc, int vert )
  28. {
  29. return desc.m_pBoneMatrixIndex + vert * desc.m_VertexSize_BoneMatrixIndex;
  30. }
  31. inline Vector &Normal( VertexDesc_t const &desc, int vert )
  32. {
  33. Assert( desc.m_CompressionType == VERTEX_COMPRESSION_NONE );
  34. return *(Vector*)((unsigned char*)desc.m_pNormal + vert * desc.m_VertexSize_Normal );
  35. }
  36. inline unsigned char *Color( VertexDesc_t const &desc, int vert )
  37. {
  38. return desc.m_pColor + vert * desc.m_VertexSize_Color;
  39. }
  40. inline Vector2D &TexCoord( VertexDesc_t const &desc, int vert, int stage )
  41. {
  42. return *(Vector2D*)((unsigned char*)desc.m_pTexCoord[stage] + vert * desc.m_VertexSize_TexCoord[stage] );
  43. }
  44. inline Vector &TangentS( VertexDesc_t const &desc, int vert )
  45. {
  46. return *(Vector*)((unsigned char*)desc.m_pTangentS + vert * desc.m_VertexSize_TangentS );
  47. }
  48. inline Vector &TangentT( VertexDesc_t const &desc, int vert )
  49. {
  50. return *(Vector*)((unsigned char*)desc.m_pTangentT + vert * desc.m_VertexSize_TangentT );
  51. }
  52. //-----------------------------------------------------------------------------
  53. //
  54. // Vertex Buffer implementations begin here
  55. //
  56. //-----------------------------------------------------------------------------
  57. //-----------------------------------------------------------------------------
  58. // constructor, destructor
  59. //-----------------------------------------------------------------------------
  60. CVertexBufferBase::CVertexBufferBase( const char *pBudgetGroupName )
  61. {
  62. m_pBudgetGroupName = pBudgetGroupName;
  63. }
  64. CVertexBufferBase::~CVertexBufferBase()
  65. {
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Displays the vertex format
  69. //-----------------------------------------------------------------------------
  70. void CVertexBufferBase::PrintVertexFormat( VertexFormat_t vertexFormat )
  71. {
  72. VertexCompressionType_t compression = CompressionType( vertexFormat );
  73. if( vertexFormat & VERTEX_POSITION )
  74. {
  75. Msg( "VERTEX_POSITION|" );
  76. }
  77. if( vertexFormat & VERTEX_NORMAL )
  78. {
  79. // FIXME: genericise this stuff using VertexElement_t data tables (so funcs like 'just work' if we make compression changes)
  80. if ( compression == VERTEX_COMPRESSION_ON )
  81. Msg( "VERTEX_NORMAL|" );
  82. else
  83. Msg( "VERTEX_NORMAL[COMPRESSED]|" );
  84. }
  85. if( vertexFormat & VERTEX_COLOR )
  86. {
  87. Msg( "VERTEX_COLOR|" );
  88. }
  89. if( vertexFormat & VERTEX_SPECULAR )
  90. {
  91. Msg( "VERTEX_SPECULAR|" );
  92. }
  93. if( vertexFormat & VERTEX_TANGENT_S )
  94. {
  95. Msg( "VERTEX_TANGENT_S|" );
  96. }
  97. if( vertexFormat & VERTEX_TANGENT_T )
  98. {
  99. Msg( "VERTEX_TANGENT_T|" );
  100. }
  101. if( vertexFormat & VERTEX_BONE_INDEX )
  102. {
  103. Msg( "VERTEX_BONE_INDEX|" );
  104. }
  105. if( vertexFormat & VERTEX_FORMAT_VERTEX_SHADER )
  106. {
  107. Msg( "VERTEX_FORMAT_VERTEX_SHADER|" );
  108. }
  109. if( NumBoneWeights( vertexFormat ) > 0 )
  110. {
  111. Msg( "VERTEX_BONEWEIGHT(%d)%s|",
  112. NumBoneWeights( vertexFormat ), ( compression ? "[COMPRESSED]" : "" ) );
  113. }
  114. if( UserDataSize( vertexFormat ) > 0 )
  115. {
  116. Msg( "VERTEX_USERDATA_SIZE(%d)|", UserDataSize( vertexFormat ) );
  117. }
  118. int i;
  119. for( i = 0; i < VERTEX_MAX_TEXTURE_COORDINATES; i++ )
  120. {
  121. int nDim = TexCoordSize( i, vertexFormat );
  122. if ( nDim == 0 )
  123. continue;
  124. Msg( "VERTEX_TEXCOORD_SIZE(%d,%d)", i, nDim );
  125. }
  126. Msg( "\n" );
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Used to construct vertex data
  130. //-----------------------------------------------------------------------------
  131. void CVertexBufferBase::ComputeVertexDescription( unsigned char *pBuffer,
  132. VertexFormat_t vertexFormat, VertexDesc_t &desc )
  133. {
  134. ComputeVertexDesc( pBuffer, vertexFormat, desc );
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Returns the vertex format size
  138. //-----------------------------------------------------------------------------
  139. int CVertexBufferBase::VertexFormatSize( VertexFormat_t vertexFormat )
  140. {
  141. // FIXME: We could make this much faster
  142. MeshDesc_t temp;
  143. ComputeVertexDescription( 0, vertexFormat, temp );
  144. return temp.m_ActualVertexSize;
  145. }
  146. //-----------------------------------------------------------------------------
  147. // Spews the mesh data
  148. //-----------------------------------------------------------------------------
  149. void CVertexBufferBase::Spew( int nVertexCount, const VertexDesc_t &desc )
  150. {
  151. LOCK_SHADERAPI();
  152. char pTempBuf[1024];
  153. Q_snprintf( pTempBuf, sizeof(pTempBuf), "\nVerts %d (First %d, Offset %d) :\n", nVertexCount, desc.m_nFirstVertex, desc.m_nOffset );
  154. Warning( "%s", pTempBuf );
  155. Assert( ( desc.m_NumBoneWeights == 2 ) || ( desc.m_NumBoneWeights == 0 ) );
  156. int nLen = 0;
  157. int nBoneWeightCount = desc.m_NumBoneWeights;
  158. for ( int i = 0; i < nVertexCount; ++i )
  159. {
  160. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "[%4d] ", i + desc.m_nFirstVertex );
  161. if ( desc.m_VertexSize_Position )
  162. {
  163. Vector &pos = Position( desc, i );
  164. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "P %8.2f %8.2f %8.2f ",
  165. pos[0], pos[1], pos[2]);
  166. }
  167. if ( desc.m_VertexSize_Wrinkle )
  168. {
  169. float flWrinkle = Wrinkle( desc, i );
  170. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "Wr %8.2f ",flWrinkle );
  171. }
  172. if ( nBoneWeightCount )
  173. {
  174. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "BW ");
  175. float* pWeight = BoneWeight( desc, i );
  176. for ( int j = 0; j < nBoneWeightCount; ++j )
  177. {
  178. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "%1.2f ", pWeight[j] );
  179. }
  180. }
  181. if ( desc.m_VertexSize_BoneMatrixIndex )
  182. {
  183. unsigned char *pIndex = BoneIndex( desc, i );
  184. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "BI %d %d %d %d ", ( int )pIndex[0], ( int )pIndex[1], ( int )pIndex[2], ( int )pIndex[3] );
  185. Assert( pIndex[0] >= 0 && pIndex[0] < 16 );
  186. Assert( pIndex[1] >= 0 && pIndex[1] < 16 );
  187. Assert( pIndex[2] >= 0 && pIndex[2] < 16 );
  188. Assert( pIndex[3] >= 0 && pIndex[3] < 16 );
  189. }
  190. if ( desc.m_VertexSize_Normal )
  191. {
  192. Vector & normal = Normal( desc, i );
  193. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "N %1.2f %1.2f %1.2f ",
  194. normal[0], normal[1], normal[2]);
  195. }
  196. if ( desc.m_VertexSize_Color )
  197. {
  198. unsigned char* pColor = Color( desc, i );
  199. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "C b %3d g %3d r %3d a %3d ",
  200. pColor[0], pColor[1], pColor[2], pColor[3]);
  201. }
  202. for ( int j = 0; j < VERTEX_MAX_TEXTURE_COORDINATES; ++j )
  203. {
  204. if ( desc.m_VertexSize_TexCoord[j] )
  205. {
  206. Vector2D& texcoord = TexCoord( desc, i, j );
  207. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "T%d %.2f %.2f ", j,texcoord[0], texcoord[1]);
  208. }
  209. }
  210. if ( desc.m_VertexSize_TangentS )
  211. {
  212. Vector& tangentS = TangentS( desc, i );
  213. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "S %1.2f %1.2f %1.2f ",
  214. tangentS[0], tangentS[1], tangentS[2]);
  215. }
  216. if ( desc.m_VertexSize_TangentT )
  217. {
  218. Vector& tangentT = TangentT( desc, i );
  219. nLen += Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "T %1.2f %1.2f %1.2f ",
  220. tangentT[0], tangentT[1], tangentT[2]);
  221. }
  222. Q_snprintf( &pTempBuf[nLen], sizeof(pTempBuf) - nLen, "\n" );
  223. Warning( "%s", pTempBuf );
  224. nLen = 0;
  225. }
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Validates vertex buffer data
  229. //-----------------------------------------------------------------------------
  230. void CVertexBufferBase::ValidateData( int nVertexCount, const VertexDesc_t &spewDesc )
  231. {
  232. LOCK_SHADERAPI();
  233. #ifdef VALIDATE_DEBUG
  234. int i;
  235. // This is needed so buffering can just use this
  236. VertexFormat_t fmt = m_pMaterial->GetVertexUsage();
  237. // Set up the vertex descriptor
  238. VertexDesc_t desc = spewDesc;
  239. int numBoneWeights = NumBoneWeights( fmt );
  240. for ( i = 0; i < nVertexCount; ++i )
  241. {
  242. if( fmt & VERTEX_POSITION )
  243. {
  244. D3DXVECTOR3& pos = Position( desc, i );
  245. Assert( IsFinite( pos[0] ) && IsFinite( pos[1] ) && IsFinite( pos[2] ) );
  246. }
  247. if( fmt & VERTEX_WRINKLE )
  248. {
  249. float flWrinkle = Wrinkle( desc, i );
  250. Assert( IsFinite( flWrinkle ) );
  251. }
  252. if (numBoneWeights > 0)
  253. {
  254. float* pWeight = BoneWeight( desc, i );
  255. for (int j = 0; j < numBoneWeights; ++j)
  256. {
  257. Assert( pWeight[j] >= 0.0f && pWeight[j] <= 1.0f );
  258. }
  259. }
  260. if( fmt & VERTEX_BONE_INDEX )
  261. {
  262. unsigned char *pIndex = BoneIndex( desc, i );
  263. Assert( pIndex[0] >= 0 && pIndex[0] < 16 );
  264. Assert( pIndex[1] >= 0 && pIndex[1] < 16 );
  265. Assert( pIndex[2] >= 0 && pIndex[2] < 16 );
  266. Assert( pIndex[3] >= 0 && pIndex[3] < 16 );
  267. }
  268. if( fmt & VERTEX_NORMAL )
  269. {
  270. D3DXVECTOR3& normal = Normal( desc, i );
  271. Assert( normal[0] >= -1.05f && normal[0] <= 1.05f );
  272. Assert( normal[1] >= -1.05f && normal[1] <= 1.05f );
  273. Assert( normal[2] >= -1.05f && normal[2] <= 1.05f );
  274. }
  275. if (fmt & VERTEX_COLOR)
  276. {
  277. int* pColor = (int*)Color( desc, i );
  278. Assert( *pColor != FLOAT32_NAN_BITS );
  279. }
  280. for (int j = 0; j < VERTEX_MAX_TEXTURE_COORDINATES; ++j)
  281. {
  282. if( TexCoordSize( j, fmt ) > 0)
  283. {
  284. D3DXVECTOR2& texcoord = TexCoord( desc, i, j );
  285. Assert( IsFinite( texcoord[0] ) && IsFinite( texcoord[1] ) );
  286. }
  287. }
  288. if (fmt & VERTEX_TANGENT_S)
  289. {
  290. D3DXVECTOR3& tangentS = TangentS( desc, i );
  291. Assert( IsFinite( tangentS[0] ) && IsFinite( tangentS[1] ) && IsFinite( tangentS[2] ) );
  292. }
  293. if (fmt & VERTEX_TANGENT_T)
  294. {
  295. D3DXVECTOR3& tangentT = TangentT( desc, i );
  296. Assert( IsFinite( tangentT[0] ) && IsFinite( tangentT[1] ) && IsFinite( tangentT[2] ) );
  297. }
  298. }
  299. #endif // _DEBUG
  300. }
  301. //-----------------------------------------------------------------------------
  302. //
  303. // Index Buffer implementations begin here
  304. //
  305. //-----------------------------------------------------------------------------
  306. //-----------------------------------------------------------------------------
  307. // constructor, destructor
  308. //-----------------------------------------------------------------------------
  309. CIndexBufferBase::CIndexBufferBase( const char *pBudgetGroupName ) : m_pBudgetGroupName( pBudgetGroupName )
  310. {
  311. }
  312. //-----------------------------------------------------------------------------
  313. // Spews the mesh data
  314. //-----------------------------------------------------------------------------
  315. void CIndexBufferBase::Spew( int nIndexCount, const IndexDesc_t &indexDesc )
  316. {
  317. LOCK_SHADERAPI();
  318. char pTempBuf[512];
  319. int nLen = 0;
  320. pTempBuf[0] = '\0';
  321. char *pTemp = pTempBuf;
  322. Q_snprintf( pTempBuf, sizeof(pTempBuf), "\nIndices: %d (First %d, Offset %d)\n", nIndexCount, indexDesc.m_nFirstIndex, indexDesc.m_nOffset );
  323. Warning( "%s", pTempBuf );
  324. for ( int i = 0; i < nIndexCount; ++i )
  325. {
  326. nLen += Q_snprintf( pTemp, sizeof(pTempBuf) - nLen - 1, "%d ", ( int )indexDesc.m_pIndices[i] );
  327. pTemp = pTempBuf + nLen;
  328. if ( (i & 0x0F) == 0x0F )
  329. {
  330. Q_snprintf( pTemp, sizeof(pTempBuf) - nLen - 1, "\n" );
  331. Warning( "%s", pTempBuf );
  332. pTempBuf[0] = '\0';
  333. nLen = 0;
  334. pTemp = pTempBuf;
  335. }
  336. }
  337. Q_snprintf( pTemp, sizeof(pTempBuf) - nLen - 1, "\n" );
  338. Warning( "%s", pTempBuf );
  339. }
  340. //-----------------------------------------------------------------------------
  341. // Call this in debug mode to make sure our data is good.
  342. //-----------------------------------------------------------------------------
  343. void CIndexBufferBase::ValidateData( int nIndexCount, const IndexDesc_t& desc )
  344. {
  345. /* FIXME */
  346. // NOTE: Is there anything reasonable to do here at all?
  347. // Or is this a bogus method altogether?
  348. }
  349. //-----------------------------------------------------------------------------
  350. //
  351. // Base mesh
  352. //
  353. //-----------------------------------------------------------------------------
  354. //-----------------------------------------------------------------------------
  355. // constructor, destructor
  356. //-----------------------------------------------------------------------------
  357. CMeshBase::CMeshBase()
  358. {
  359. }
  360. CMeshBase::~CMeshBase()
  361. {
  362. }