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.

343 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // A simple tool for converting SpeedTree .spt files into .smd files
  6. // for use in Source
  7. //
  8. //===========================================================================//
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include "filesystem_tools.h"
  13. #include "cmdlib.h"
  14. #include "mathlib/mathlib.h"
  15. #include "tier0/icommandline.h"
  16. #include "SpeedTreeRT.h"
  17. void OutputMaterialFile( char *filestub, bool bEnableAlphaTest, float alphaTest=0.0f )
  18. {
  19. char filename[MAX_PATH];
  20. _snprintf( filename, MAX_PATH, "%smaterials\\Trees\\%s_VertexLit.vmt", gamedir, filestub );
  21. FILE *file = fopen( filename, "wt" );
  22. if( !file )
  23. return;
  24. fprintf( file, "\"VertexLitGeneric\"\n" );
  25. fprintf( file, "{\n" );
  26. fprintf( file, "\t\"$basetexture\" \"trees/%s\"\n", filestub);
  27. fprintf( file, "\t\"$model\" \"1\"\n" );
  28. fprintf( file, "\t\"$alphatest\" \"%d\"\n", bEnableAlphaTest?1:0 );
  29. fprintf( file, "\t\"$alphatestreference\" \"%f\"\n", alphaTest );
  30. fprintf( file, "}\n\n" );
  31. fclose( file );
  32. }
  33. void OutputLeafMaterialFile( char *filestub, bool bEnableAlphaTest, float alphaTest=0.0f, float *pCenter=NULL )
  34. {
  35. char filename[MAX_PATH];
  36. _snprintf( filename, MAX_PATH, "%smaterials\\Trees\\%s_TreeLeaf.vmt", gamedir, filestub );
  37. FILE *file = fopen( filename, "wt" );
  38. if( !file )
  39. return;
  40. fprintf( file, "\"TreeLeaf\"\n" );
  41. fprintf( file, "{\n" );
  42. fprintf( file, "\t\"$basetexture\" \"trees/%s\"\n", filestub);
  43. fprintf( file, "\t\"$model\" \"1\"\n" );
  44. fprintf( file, "\t\"$alphatest\" \"%d\"\n", bEnableAlphaTest?1:0 );
  45. fprintf( file, "\t\"$alphatestreference\" \"%f\"\n", alphaTest );
  46. fprintf( file, "\t\"$leafcenter\" \"[ %f %f %f ]\"\n", pCenter[0], pCenter[1], pCenter[2] );
  47. fprintf( file, "}\n\n" );
  48. fclose( file );
  49. }
  50. void OutputTreeGeometry( CSpeedTreeRT &speedTree, CSpeedTreeRT::SGeometry &sGeom, char *filename )
  51. {
  52. FILE *file = fopen( filename, "wt" );
  53. if( !file )
  54. return;
  55. fprintf( file, "version 1\n" );
  56. fprintf( file, "nodes\n" );
  57. fprintf( file, "0 \"Tree\" -1\n" );
  58. fprintf( file, "end\n" );
  59. fprintf( file, "skeleton\n" );
  60. fprintf( file, "time 0\n" );
  61. fprintf( file, "0 0.0 0.0 0.0 0.0 0.0 0.0\n" );
  62. fprintf( file, "end\n" );
  63. fprintf( file, "triangles\n" );
  64. CSpeedTreeRT::STextures sTextures;
  65. speedTree.GetTextures( sTextures );
  66. char branchTextureName[ MAX_PATH ];
  67. _splitpath( sTextures.m_pBranchTextureFilename, NULL, NULL, branchTextureName, NULL );
  68. float alphaTest = sGeom.m_fBranchAlphaTestValue/255.0f;
  69. OutputMaterialFile( branchTextureName, false, alphaTest );
  70. for( int nStrip=0;nStrip<sGeom.m_sBranches.m_usNumStrips;nStrip++ )
  71. {
  72. int nStripLength = sGeom.m_sBranches.m_pStripLengths[ nStrip ];
  73. const unsigned short *pStripIndices = sGeom.m_sBranches.m_pStrips[ nStrip ];
  74. for( int i=0;i<nStripLength-2;i++ )
  75. {
  76. int nIndices[3] = { pStripIndices[i], pStripIndices[i+1], pStripIndices[i+2] };
  77. if( i%2 )
  78. {
  79. int tmp = nIndices[2];
  80. nIndices[2] = nIndices[1];
  81. nIndices[1] = tmp;
  82. }
  83. fprintf( file, "%s_VertexLit\n", branchTextureName );
  84. for( int j=0;j<3;j++ )
  85. {
  86. const float *pPos = &sGeom.m_sBranches.m_pCoords[ nIndices[j]*3 ];
  87. const float *pNormal = &sGeom.m_sBranches.m_pNormals[ nIndices[j]*3 ];
  88. const float *pTexCoord = &sGeom.m_sBranches.m_pTexCoords0[ nIndices[j]*2 ];
  89. fprintf( file, "0 %f %f %f %f %f %f %f %f 0\n", pPos[0], pPos[1], pPos[2],
  90. pNormal[0], pNormal[1], pNormal[2],
  91. pTexCoord[0], pTexCoord[1] );
  92. }
  93. }
  94. }
  95. for( unsigned int i=0;i<sTextures.m_uiFrondTextureCount;i++ )
  96. {
  97. char filestub[MAX_PATH];
  98. _splitpath( sTextures.m_pFrondTextureFilenames[i], NULL, NULL, filestub, NULL );
  99. alphaTest = sGeom.m_fFrondAlphaTestValue/255.0f;
  100. OutputMaterialFile( filestub, true, alphaTest );
  101. }
  102. for( int nStrip=0;nStrip<sGeom.m_sFronds.m_usNumStrips;nStrip++ )
  103. {
  104. int nStripLength = sGeom.m_sFronds.m_pStripLengths[ nStrip ];
  105. const unsigned short *pStripIndices = sGeom.m_sFronds.m_pStrips[ nStrip ];
  106. for( int i=0;i<nStripLength-2;i++ )
  107. {
  108. int nIndices[3] = { pStripIndices[i], pStripIndices[i+1], pStripIndices[i+2] };
  109. if( i%2 )
  110. {
  111. int tmp = nIndices[2];
  112. nIndices[2] = nIndices[1];
  113. nIndices[1] = tmp;
  114. }
  115. char frondTextureName[ MAX_PATH ];
  116. _splitpath( sTextures.m_pFrondTextureFilenames[0], NULL, NULL, frondTextureName, NULL );
  117. fprintf( file, "%s_VertexLit\n", frondTextureName );
  118. for( int j=0;j<3;j++ )
  119. {
  120. const float *pPos = &sGeom.m_sFronds.m_pCoords[ nIndices[j]*3 ];
  121. const float *pNormal = &sGeom.m_sFronds.m_pNormals[ nIndices[j]*3 ];
  122. const float *pTexCoord = &sGeom.m_sFronds.m_pTexCoords0[ nIndices[j]*2 ];
  123. fprintf( file, "0 %f %f %f %f %f %f %f %f 0\n", pPos[0], pPos[1], pPos[2],
  124. pNormal[0], pNormal[1], pNormal[2],
  125. pTexCoord[0], pTexCoord[1] );
  126. }
  127. }
  128. }
  129. float *pLeafCentres = new float[ sTextures.m_uiLeafTextureCount*3 ];
  130. int *pLeafCounts = new int[ sTextures.m_uiLeafTextureCount ];
  131. for( unsigned int i=0;i<sTextures.m_uiLeafTextureCount;i++ )
  132. {
  133. pLeafCentres[ i*3 ] = 0.0f;
  134. pLeafCentres[ i*3+1 ] = 0.0f;
  135. pLeafCentres[ i*3+2 ] = 0.0f;
  136. pLeafCounts[ i ] = 0;
  137. }
  138. CSpeedTreeRT::SGeometry::SLeaf &leaves = sGeom.m_sLeaves0;
  139. for( int i=0;i<leaves.m_usLeafCount;i++ )
  140. {
  141. int index = leaves.m_pLeafMapIndices[i] / 2;
  142. char leafTextureName[ MAX_PATH ];
  143. _splitpath( sTextures.m_pLeafTextureFilenames[ index ], NULL, NULL, leafTextureName, NULL );
  144. const float *pPos = &leaves.m_pCenterCoords[ i*3 ];
  145. const float *pCoords = leaves.m_pLeafMapCoords[ i ];
  146. const float *pTex = leaves.m_pLeafMapTexCoords[i];
  147. float d[3] = { pCoords[8] - pCoords[0], pCoords[9] - pCoords[1], pCoords[10] - pCoords[2] };
  148. float size = sqrtf( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] ) * 0.5f;
  149. fprintf( file, "%s_TreeLeaf\n", leafTextureName );
  150. fprintf( file, "0 %f %f %f %f %f 0.0 %f %f\n", pPos[0], pPos[1], pPos[2], pTex[0], pTex[1], -size, -size );
  151. fprintf( file, "0 %f %f %f %f %f 0.0 %f %f\n", pPos[0], pPos[1], pPos[2], pTex[2], pTex[3], size, -size );
  152. fprintf( file, "0 %f %f %f %f %f 0.0 %f %f\n", pPos[0], pPos[1], pPos[2], pTex[4], pTex[5], size, size );
  153. fprintf( file, "%s_TreeLeaf\n", leafTextureName );
  154. fprintf( file, "0 %f %f %f %f %f 0.0 %f %f\n", pPos[0], pPos[1], pPos[2], pTex[0], pTex[1], -size, -size );
  155. fprintf( file, "0 %f %f %f %f %f 0.0 %f %f\n", pPos[0], pPos[1], pPos[2], pTex[4], pTex[5], size, size );
  156. fprintf( file, "0 %f %f %f %f %f 0.0 %f %f\n", pPos[0], pPos[1], pPos[2], pTex[6], pTex[7], -size, size );
  157. pLeafCentres[ index*3 ] += pPos[0];
  158. pLeafCentres[ index*3+1 ] += pPos[1];
  159. pLeafCentres[ index*3+2 ] += pPos[2];
  160. pLeafCounts[ index ]++;
  161. }
  162. for( unsigned int i=0;i<sTextures.m_uiLeafTextureCount;i++ )
  163. {
  164. float oneOnCount = 1.0f / pLeafCounts[i];
  165. pLeafCentres[ i*3 ] *= oneOnCount;
  166. pLeafCentres[ i*3+1 ] *= oneOnCount;
  167. pLeafCentres[ i*3+2 ] *= oneOnCount;
  168. }
  169. for( unsigned int i=0;i<sTextures.m_uiLeafTextureCount;i++ )
  170. {
  171. char filestub[ MAX_PATH ];
  172. _splitpath( sTextures.m_pLeafTextureFilenames[i], NULL, NULL, filestub, NULL );
  173. alphaTest = sGeom.m_sLeaves0.m_fAlphaTestValue/255.0f;
  174. OutputLeafMaterialFile( filestub, true, alphaTest, &pLeafCentres[i*3] );
  175. }
  176. fprintf( file, "end\n\n" );
  177. fclose( file );
  178. }
  179. void OutputTreeTextures( CSpeedTreeRT &speedTree )
  180. {
  181. CSpeedTreeRT::STextures sTextures;
  182. speedTree.GetTextures( sTextures );
  183. CSpeedTreeRT::SGeometry sGeom;
  184. speedTree.GetGeometry( sGeom, SpeedTree_AllGeometry );
  185. char filestub[MAX_PATH];
  186. _splitpath( sTextures.m_pBranchTextureFilename, NULL, NULL, filestub, NULL );
  187. float alphaTest = sGeom.m_fBranchAlphaTestValue/255.0f;
  188. OutputMaterialFile( filestub, false, alphaTest );
  189. for( unsigned int i=0;i<sTextures.m_uiFrondTextureCount;i++ )
  190. {
  191. _splitpath( sTextures.m_pFrondTextureFilenames[i], NULL, NULL, filestub, NULL );
  192. alphaTest = sGeom.m_fFrondAlphaTestValue/255.0f;
  193. OutputMaterialFile( filestub, true, alphaTest );
  194. }
  195. for( unsigned int i=0;i<sTextures.m_uiLeafTextureCount;i++ )
  196. {
  197. _splitpath( sTextures.m_pLeafTextureFilenames[i], NULL, NULL, filestub, NULL );
  198. alphaTest = sGeom.m_sLeaves0.m_fAlphaTestValue/255.0f;
  199. OutputLeafMaterialFile( filestub, true, alphaTest );
  200. }
  201. }
  202. void OutputQCFile( char *treeName )
  203. {
  204. char smdFileName[MAX_PATH];
  205. sprintf( smdFileName, "%s.smd", treeName );
  206. char qcFileName[MAX_PATH];
  207. sprintf( qcFileName, "%s.qc", treeName );
  208. char smdAnimFileName[MAX_PATH];
  209. sprintf( smdAnimFileName, "%s_anim.smd", treeName );
  210. char mdlFileName[MAX_PATH];
  211. sprintf( mdlFileName, "%s.mdl", treeName );
  212. FILE *file = fopen( qcFileName, "wt" );
  213. fprintf( file, "$modelname %s\n", mdlFileName );
  214. fprintf( file, "$cdmaterials trees\n" );
  215. fprintf( file, "$scale 1\n" );
  216. fprintf( file, "$model %s \"%s\"\n", treeName, smdFileName );
  217. fprintf( file, "$sequence idle \"%s_anim\" loop fps 15\n", treeName );
  218. fclose( file );
  219. file = fopen( smdAnimFileName, "wt" );
  220. fprintf( file, "version 1\n" );
  221. fprintf( file, "nodes\n" );
  222. fprintf( file, "0 \"Tree\" -1\n" );
  223. fprintf( file, "end\n" );
  224. fprintf( file, "skeleton\n" );
  225. fprintf( file, "time 0\n" );
  226. fprintf( file, "0 0.0 0.0 0.0 0.0 0.0 0.0\n" );
  227. fprintf( file, "end\n" );
  228. fclose( file );
  229. }
  230. void main( int argc, char **argv )
  231. {
  232. CommandLine()->CreateCmdLine( argc, argv );
  233. if( CommandLine()->ParmCount()!=2 )
  234. {
  235. printf( "usage : sptconvert <SPT file name>\n" );
  236. exit(0);
  237. }
  238. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
  239. CmdLib_InitFileSystem( CommandLine()->GetParm(1) );
  240. CSpeedTreeRT speedTree;
  241. char treeName[MAX_PATH];
  242. _splitpath( argv[1], NULL, NULL, treeName, NULL );
  243. char smdFileName[MAX_PATH];
  244. sprintf( smdFileName, "%s.smd", treeName );
  245. char qcFileName[MAX_PATH];
  246. sprintf( qcFileName, "%s.qc", treeName );
  247. OutputQCFile( treeName );
  248. if( speedTree.LoadTree( argv[1] ) )
  249. {
  250. if( speedTree.Compute( NULL, 1, false ) )
  251. {
  252. CSpeedTreeRT::SGeometry sGeom;
  253. speedTree.GetGeometry( sGeom, SpeedTree_AllGeometry );
  254. OutputTreeGeometry( speedTree, sGeom, smdFileName );
  255. }
  256. else
  257. {
  258. // Trouble with compute
  259. }
  260. }
  261. else
  262. {
  263. // Trouble with load
  264. }
  265. }