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.

354 lines
7.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "MAX.H"
  9. #include "DECOMP.H"
  10. #include "STDMAT.H"
  11. #include "ANIMTBL.H"
  12. #include "istdplug.h"
  13. #include "phyexp.h"
  14. #include "BonesPro.h"
  15. #include "vweightexprc.h"
  16. #include "vweightexp.h"
  17. #include "vweightimp.h"
  18. //===================================================================
  19. // Global variable definitions
  20. //
  21. // For OutputDebugString and misc sprintf's
  22. static char st_szDBG[8193];
  23. //=====================================================================
  24. // Methods for VWeightImportClass
  25. //
  26. CONSTRUCTOR VWeightImportClass::VWeightImportClass(void)
  27. {
  28. m_cSrcMaxNodes = 0;
  29. m_cSrcMaxVertex = 0;
  30. m_cMaxNodes = 0;
  31. }
  32. DESTRUCTOR VWeightImportClass::~VWeightImportClass(void)
  33. {
  34. for (int i = 0; i < m_cSrcMaxVertex; i++)
  35. {
  36. delete[] m_SrcMaxVertex[i];
  37. }
  38. }
  39. int VWeightImportClass::DoImport(const TCHAR *name, ImpInterface *ii, Interface *pi, BOOL suppressPrompts)
  40. {
  41. ImpInterface *pimpiface = ii;
  42. Interface *piface = pi;
  43. // Break up filename, re-assemble longer versions
  44. TSTR strPath, strFile, strExt;
  45. TCHAR szFile[MAX_PATH];
  46. SplitFilename(TSTR(name), &strPath, &strFile, &strExt);
  47. sprintf(szFile, "%s\\%s.%s", (char*)strPath, (char*)strFile, DEFAULT_EXT);
  48. // Get animation metrics
  49. m_intervalOfAnimation = piface->GetAnimRange();
  50. m_tvStart = m_intervalOfAnimation.Start();
  51. m_tvEnd = m_intervalOfAnimation.End();
  52. m_tpf = ::GetTicksPerFrame();
  53. Interface *ip = GetCOREInterface();
  54. ResetINodeMap( );
  55. m_cMaxNodes = BuildINodeMap( ip->GetRootNode() );
  56. CollectNodes( ip->GetRootNode() );
  57. // read src data
  58. FILE *pFile;
  59. if ((pFile = fopen(szFile, "rb")) == NULL)
  60. return FALSE/*failure*/;
  61. int version = 1;
  62. fread( &version, 1, sizeof( int ), pFile );
  63. int i, j;
  64. fread( &m_cSrcMaxNodes, 1, sizeof( int ), pFile );
  65. fread( &m_cSrcMaxVertex, 1, sizeof( int ), pFile );
  66. for (i = 0; i < m_cSrcMaxNodes; i++)
  67. {
  68. fread( &m_SrcMaxNode[i], 1, sizeof(m_SrcMaxNode[i]), pFile );
  69. }
  70. int cNodes = (m_cSrcMaxNodes > m_cMaxNodes) ? m_cSrcMaxNodes : m_cMaxNodes;
  71. for (j = 0; j < m_cSrcMaxVertex; j++)
  72. {
  73. m_SrcMaxVertex[j] = new MaxVertWeight [cNodes];
  74. fread( m_SrcMaxVertex[j], m_cSrcMaxNodes, sizeof(MaxVertWeight), pFile );
  75. }
  76. fclose( pFile );
  77. RemapSrcWeights( );
  78. NodeEnum( ip->GetSelNode( 0 ) );
  79. // Tell user that exporting is finished (it can take a while with no feedback)
  80. char szExportComplete[300];
  81. sprintf(szExportComplete, "Imported %s.", szFile);
  82. MessageBox(GetActiveWindow(), szExportComplete, "Status", MB_OK);
  83. return 1/*success*/;
  84. }
  85. void VWeightImportClass::CollectNodes( INode *pnode )
  86. {
  87. // Get pre-stored "index"
  88. int index = ::GetIndexOfINode(pnode);
  89. if (index >= 0)
  90. {
  91. // Get name, store name in array
  92. TSTR strNodeName(pnode->GetName());
  93. strcpy(m_MaxNode[index].szNodeName, (char*)strNodeName);
  94. // Get Node's time-zero Transformation Matrices
  95. m_MaxNode[index].mat3NodeTM = pnode->GetNodeTM(0);
  96. m_MaxNode[index].mat3ObjectTM = pnode->GetObjectTM(0);
  97. }
  98. for (int c = 0; c < pnode->NumberOfChildren(); c++)
  99. {
  100. CollectNodes(pnode->GetChildNode(c));
  101. }
  102. return;
  103. }
  104. void VWeightImportClass::NodeEnum( INode *node )
  105. {
  106. #if 0
  107. // For each child of this node, we recurse into ourselves
  108. // until no more children are found.
  109. for (int c = 0; c < node->NumberOfChildren(); c++)
  110. {
  111. NodeEnum(node->GetChildNode(c));
  112. }
  113. #endif
  114. UpdateModel( node );
  115. }
  116. void VWeightImportClass::RemapSrcWeights( )
  117. {
  118. int index;
  119. for (index = 0; index < m_cMaxNodes; index++)
  120. {
  121. m_iToSrc[index] = -1;
  122. }
  123. for (int iSrc = 0; iSrc < m_cSrcMaxNodes; iSrc++)
  124. {
  125. index = GetIndexOfNodeName( (char*) m_SrcMaxNode[iSrc].szNodeName );
  126. if (index >= 0)
  127. {
  128. m_iToSrc[index] = iSrc;
  129. }
  130. else
  131. {
  132. iSrc = iSrc;
  133. }
  134. }
  135. MaxVertWeight flTmp[512];
  136. for (index = 0; index < m_cMaxNodes; index++)
  137. {
  138. flTmp[index].flDist = 0.0;
  139. flTmp[index].flWeight = 0.0;
  140. }
  141. for (int iVert = 0; iVert < m_cSrcMaxVertex; iVert++)
  142. {
  143. for (index = 0; index < m_cMaxNodes; index++)
  144. {
  145. if (m_iToSrc[index] >= 0)
  146. {
  147. flTmp[index] = m_SrcMaxVertex[iVert][m_iToSrc[index]];
  148. }
  149. }
  150. for (index = 0; index < m_cMaxNodes; index++)
  151. {
  152. m_SrcMaxVertex[iVert][index] = flTmp[index];
  153. }
  154. }
  155. }
  156. int VWeightImportClass::UpdateModel(INode *pnode)
  157. {
  158. if (::FNodeMarkedToSkip(pnode))
  159. return TREE_CONTINUE;
  160. if ( !pnode->Selected())
  161. return TREE_CONTINUE;
  162. // clear physique export parameters
  163. m_mcExport = NULL;
  164. m_phyExport = NULL;
  165. m_phyMod = NULL;
  166. m_bonesProMod = NULL;
  167. ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!");
  168. int iNode = ::GetIndexOfINode(pnode);
  169. TSTR strNodeName(pnode->GetName());
  170. // The Footsteps node apparently MUST have a dummy mesh attached! Ignore it explicitly.
  171. if (FStrEq((char*)strNodeName, "Bip01 Footsteps"))
  172. return TREE_CONTINUE;
  173. // Helper nodes don't have meshes
  174. Object *pobj = pnode->GetObjectRef();
  175. if (pobj->SuperClassID() == HELPER_CLASS_ID)
  176. return TREE_CONTINUE;
  177. // Get Node's object, convert to a triangle-mesh object, so I can access the Faces
  178. ObjectState os = pnode->EvalWorldState(m_tvStart);
  179. pobj = os.obj;
  180. // Shouldn't have gotten this far if it's a helper object
  181. if (pobj->SuperClassID() == HELPER_CLASS_ID)
  182. {
  183. return TREE_CONTINUE;
  184. }
  185. // convert mesh to triobject
  186. if (!pobj->CanConvertToType(triObjectClassID))
  187. return TREE_CONTINUE;
  188. TriObject *ptriobj = (TriObject*)pobj->ConvertToType(m_tvStart, triObjectClassID);
  189. if (ptriobj == NULL)
  190. return TREE_CONTINUE;
  191. Mesh *pmesh = &ptriobj->mesh;
  192. // We want the vertex coordinates in World-space, not object-space
  193. Matrix3 mat3ObjectTM = pnode->GetObjectTM(m_tvStart);
  194. // initialize physique export parameters
  195. m_phyMod = FindPhysiqueModifier(pnode);
  196. if (m_phyMod)
  197. {
  198. // Physique Modifier exists for given Node
  199. m_phyExport = (IPhysiqueExport *)m_phyMod->GetInterface(I_PHYINTERFACE);
  200. if (m_phyExport)
  201. {
  202. // create a ModContext Export Interface for the specific node of the Physique Modifier
  203. m_mcExport = (IPhyContextExport *)m_phyExport->GetContextInterface(pnode);
  204. if (m_mcExport)
  205. {
  206. // convert all vertices to Rigid
  207. m_mcExport->ConvertToRigid(TRUE);
  208. }
  209. }
  210. }
  211. // initialize bones pro export parameters
  212. m_wa = NULL;
  213. m_bonesProMod = FindBonesProModifier(pnode);
  214. if (m_bonesProMod)
  215. {
  216. m_bonesProMod->SetProperty( BP_PROPID_GET_WEIGHTS, &m_wa );
  217. }
  218. int cVerts = pmesh->getNumVerts();
  219. // Dump the triangle face info
  220. int cFaces = pmesh->getNumFaces();
  221. MaxVertWeight mvTmp[512];
  222. for (int iVert = 0; iVert < cVerts; iVert++)
  223. {
  224. Point3 pt3Vertex1 = pmesh->getVert(iVert);
  225. Point3 v1 = pt3Vertex1 * mat3ObjectTM;
  226. if (v1.x < -24.0)
  227. {
  228. v1 = v1;
  229. }
  230. GetUnifiedCoord( v1, mvTmp, m_MaxNode, m_cMaxNodes );
  231. GetBoneWeights( m_bonesProMod, iVert, mvTmp );
  232. int iClosest = -1;
  233. float flMinDist = 1E30f;
  234. for (int iVert2 = 0; iVert2 < m_cSrcMaxVertex; iVert2++)
  235. {
  236. float flDist = 0;
  237. for (int index = 0; index < m_cMaxNodes && flDist < flMinDist; index++)
  238. {
  239. if (m_iToSrc[index]>=0)
  240. {
  241. float tmp = mvTmp[index].flDist - m_SrcMaxVertex[iVert2][index].flDist;
  242. flDist += (tmp * tmp);
  243. }
  244. }
  245. if (flDist < flMinDist)
  246. {
  247. iClosest = iVert2;
  248. flMinDist = flDist;
  249. }
  250. }
  251. if (iClosest != -1)
  252. {
  253. SetBoneWeights( m_bonesProMod, iVert, m_SrcMaxVertex[iClosest] );
  254. }
  255. }
  256. if (m_bonesProMod)
  257. {
  258. m_bonesProMod->SetProperty ( BP_PROPID_REFRESH, NULL );
  259. }
  260. // fflush( m_pfile );
  261. return TREE_CONTINUE;
  262. }
  263. void UpdateModelTEP::cleanup(void)
  264. {
  265. if (m_phyMod && m_phyExport)
  266. {
  267. if (m_mcExport)
  268. {
  269. m_phyExport->ReleaseContextInterface(m_mcExport);
  270. m_mcExport = NULL;
  271. }
  272. m_phyMod->ReleaseInterface(I_PHYINTERFACE, m_phyExport);
  273. m_phyExport = NULL;
  274. m_phyMod = NULL;
  275. }
  276. }