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.

1224 lines
27 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // updates:
  9. // 1-4-99 fixed file texture load and file read bug
  10. ////////////////////////////////////////////////////////////////////////
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <malloc.h>
  15. #include "StudioModel.h"
  16. #include "vphysics/constraints.h"
  17. #include "physmesh.h"
  18. #include "materialsystem/imaterialsystem.h"
  19. #include "materialsystem/imaterial.h"
  20. #include "ViewerSettings.h"
  21. #include "bone_setup.h"
  22. #include "UtlMemory.h"
  23. #include "mxtk/mx.h"
  24. #include "filesystem.h"
  25. #include "IStudioRender.h"
  26. #include "materialsystem/IMaterialSystemHardwareConfig.h"
  27. #include "MDLViewer.h"
  28. #include "optimize.h"
  29. extern char g_appTitle[];
  30. Vector *StudioModel::m_AmbientLightColors;
  31. #pragma warning( disable : 4244 ) // double to float
  32. static StudioModel g_studioModel;
  33. static StudioModel *g_pActiveModel;
  34. // Expose it to the rest of the app
  35. StudioModel *g_pStudioModel = &g_studioModel;
  36. StudioModel *g_pStudioExtraModel[HLMV_MAX_MERGED_MODELS];
  37. StudioModel::StudioModel()
  38. {
  39. m_MDLHandle = MDLHANDLE_INVALID;
  40. ClearLookTargets();
  41. }
  42. void StudioModel::Init()
  43. {
  44. m_AmbientLightColors = new Vector[g_pStudioRender->GetNumAmbientLightSamples()];
  45. // JasonM & garymcthack - should really only do this once a frame and at init time.
  46. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  47. g_viewerSettings.showNormals,
  48. g_viewerSettings.showTangentFrame );
  49. }
  50. void StudioModel::Shutdown( void )
  51. {
  52. g_pStudioModel->FreeModel( false );
  53. delete [] m_AmbientLightColors;
  54. }
  55. void StudioModel::SetCurrentModel()
  56. {
  57. // track the correct model
  58. g_pActiveModel = this;
  59. }
  60. void StudioModel::ReleaseStudioModel()
  61. {
  62. SaveViewerSettings( g_pStudioModel->GetFileName(), g_pStudioModel );
  63. g_pStudioModel->FreeModel( true );
  64. }
  65. void StudioModel::RestoreStudioModel()
  66. {
  67. // should view settings be loaded before the model is loaded?
  68. if ( g_pStudioModel->LoadModel( g_pStudioModel->m_pModelName ) )
  69. {
  70. g_pStudioModel->PostLoadModel( g_pStudioModel->m_pModelName );
  71. }
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Purpose: Frees the model data and releases textures from OpenGL.
  75. //-----------------------------------------------------------------------------
  76. void StudioModel::FreeModel( bool bReleasing )
  77. {
  78. if ( m_pStudioHdr )
  79. {
  80. delete m_pStudioHdr;
  81. m_pStudioHdr = NULL;
  82. }
  83. if ( m_MDLHandle != MDLHANDLE_INVALID )
  84. {
  85. g_pMDLCache->Release( m_MDLHandle );
  86. m_MDLHandle = MDLHANDLE_INVALID;
  87. }
  88. if ( !bReleasing )
  89. {
  90. if (m_pModelName)
  91. {
  92. delete[] m_pModelName;
  93. m_pModelName = NULL;
  94. }
  95. }
  96. m_SurfaceProps.Purge();
  97. DestroyPhysics( m_pPhysics );
  98. m_pPhysics = NULL;
  99. }
  100. void *StudioModel::operator new( size_t stAllocateBlock )
  101. {
  102. // call into engine to get memory
  103. Assert( stAllocateBlock != 0 );
  104. return calloc( 1, stAllocateBlock );
  105. }
  106. void StudioModel::operator delete( void *pMem )
  107. {
  108. #ifdef _DEBUG
  109. // set the memory to a known value
  110. int size = _msize( pMem );
  111. memset( pMem, 0xcd, size );
  112. #endif
  113. // get the engine to free the memory
  114. free( pMem );
  115. }
  116. void *StudioModel::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine )
  117. {
  118. // call into engine to get memory
  119. Assert( stAllocateBlock != 0 );
  120. return calloc( 1, stAllocateBlock );
  121. }
  122. void StudioModel::operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine )
  123. {
  124. #ifdef _DEBUG
  125. // set the memory to a known value
  126. int size = _msize( pMem );
  127. memset( pMem, 0xcd, size );
  128. #endif
  129. // get the engine to free the memory
  130. free( pMem );
  131. }
  132. bool StudioModel::LoadModel( const char *pModelName )
  133. {
  134. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  135. if (!pModelName)
  136. return 0;
  137. // In the case of restore, m_pModelName == modelname
  138. if (m_pModelName != pModelName)
  139. {
  140. // Copy over the model name; we'll need it later...
  141. if (m_pModelName)
  142. {
  143. delete[] m_pModelName;
  144. }
  145. m_pModelName = new char[Q_strlen(pModelName) + 1];
  146. strcpy( m_pModelName, pModelName );
  147. }
  148. m_MDLHandle = g_pMDLCache->FindMDL( pModelName );
  149. // allocate a pool for a studiohdr cache
  150. if (m_pStudioHdr != NULL)
  151. {
  152. delete m_pStudioHdr;
  153. }
  154. m_pStudioHdr = new CStudioHdr( g_pMDLCache->GetStudioHdr( m_MDLHandle ), g_pMDLCache );
  155. // manadatory to access correct verts
  156. SetCurrentModel();
  157. m_pPhysics = LoadPhysics( m_MDLHandle );
  158. // Copy over all of the hitboxes; we may add and remove elements
  159. m_HitboxSets.RemoveAll();
  160. CStudioHdr *pStudioHdr = GetStudioHdr();
  161. int i;
  162. for ( int s = 0; s < pStudioHdr->numhitboxsets(); s++ )
  163. {
  164. mstudiohitboxset_t *pSrcSet = pStudioHdr->pHitboxSet( s );
  165. if ( !pSrcSet )
  166. continue;
  167. int j = m_HitboxSets.AddToTail();
  168. HitboxSet_t &set = m_HitboxSets[j];
  169. set.m_Name = pSrcSet->pszName();
  170. for ( i = 0; i < pSrcSet->numhitboxes; ++i )
  171. {
  172. mstudiobbox_t *pHit = pSrcSet->pHitbox(i);
  173. int nIndex = set.m_Hitboxes.AddToTail( );
  174. HitboxInfo_t &hitbox = set.m_Hitboxes[nIndex];
  175. hitbox.m_Name = pHit->pszHitboxName();
  176. hitbox.m_BBox = *pHit;
  177. // Blat out bbox name index so we don't use it by mistake...
  178. hitbox.m_BBox.szhitboxnameindex = 0;
  179. }
  180. }
  181. // Copy over all of the surface props; we may change them...
  182. for ( i = 0; i < pStudioHdr->numbones(); ++i )
  183. {
  184. mstudiobone_t* pBone = pStudioHdr->pBone(i);
  185. CUtlSymbol prop( pBone->pszSurfaceProp() );
  186. m_SurfaceProps.AddToTail( prop );
  187. }
  188. m_physPreviewBone = -1;
  189. bool forceOpaque = (pStudioHdr->flags() & STUDIOHDR_FLAGS_FORCE_OPAQUE) != 0;
  190. bool vertexLit = false;
  191. m_bIsTransparent = false;
  192. m_bHasProxy = false;
  193. studiohwdata_t *pHardwareData = g_pMDLCache->GetHardwareData( m_MDLHandle );
  194. if ( !pHardwareData )
  195. {
  196. Assert( 0 );
  197. return false;
  198. }
  199. for( int lodID = pHardwareData->m_RootLOD; lodID < pHardwareData->m_NumLODs; lodID++ )
  200. {
  201. studioloddata_t *pLODData = &pHardwareData->m_pLODs[lodID];
  202. for ( i = 0; i < pLODData->numMaterials; ++i )
  203. {
  204. if (pLODData->ppMaterials[i]->IsVertexLit())
  205. {
  206. vertexLit = true;
  207. }
  208. if ((!forceOpaque) && pLODData->ppMaterials[i]->IsTranslucent())
  209. {
  210. m_bIsTransparent = true;
  211. //Msg("Translucent material %s for model %s\n", pLODData->ppMaterials[i]->GetName(), pStudioHdr->name );
  212. }
  213. if (pLODData->ppMaterials[i]->HasProxy())
  214. {
  215. m_bHasProxy = true;
  216. }
  217. }
  218. }
  219. return true;
  220. }
  221. bool StudioModel::PostLoadModel( const char *modelname )
  222. {
  223. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  224. CStudioHdr *pStudioHdr = GetStudioHdr();
  225. if (pStudioHdr == NULL)
  226. return false;
  227. SetSequence (0);
  228. SetController (0, 0.0f);
  229. SetController (1, 0.0f);
  230. SetController (2, 0.0f);
  231. SetController (3, 0.0f);
  232. SetBlendTime( DEFAULT_BLEND_TIME );
  233. // SetHeadTurn( 1.0f ); // FIXME:!!!
  234. int n;
  235. for (n = 0; n < pStudioHdr->numbodyparts(); n++)
  236. {
  237. SetBodygroup (n, 0);
  238. }
  239. SetSkin (0);
  240. /*
  241. Vector mins, maxs;
  242. ExtractBbox (mins, maxs);
  243. if (mins[2] < 5.0f)
  244. m_origin[2] = -mins[2];
  245. */
  246. return true;
  247. }
  248. //------------------------------------------------------------------------------
  249. // Returns true if the model has at least one body part with model data, false if not.
  250. //------------------------------------------------------------------------------
  251. bool StudioModel::HasModel()
  252. {
  253. CStudioHdr *pStudioHdr = GetStudioHdr();
  254. if ( !pStudioHdr )
  255. return false;
  256. for ( int i = 0; i < pStudioHdr->numbodyparts(); i++ )
  257. {
  258. if ( pStudioHdr->pBodypart(i)->nummodels )
  259. {
  260. return true;
  261. }
  262. }
  263. return false;
  264. }
  265. ////////////////////////////////////////////////////////////////////////
  266. int StudioModel::GetSequence( )
  267. {
  268. return m_sequence;
  269. }
  270. int StudioModel::SetSequence( int iSequence )
  271. {
  272. CStudioHdr *pStudioHdr = GetStudioHdr();
  273. if ( !pStudioHdr )
  274. return 0;
  275. if (iSequence < 0)
  276. return 0;
  277. if (iSequence > pStudioHdr->GetNumSeq())
  278. return m_sequence;
  279. m_prevsequence = m_sequence;
  280. m_sequence = iSequence;
  281. m_cycle = 0;
  282. m_sequencetime = 0.0;
  283. return m_sequence;
  284. }
  285. const char* StudioModel::GetSequenceName( int iSequence )
  286. {
  287. CStudioHdr *pStudioHdr = GetStudioHdr();
  288. if ( !pStudioHdr )
  289. return NULL;
  290. if (iSequence < 0)
  291. return NULL;
  292. if (iSequence > pStudioHdr->GetNumSeq())
  293. return NULL;
  294. return pStudioHdr->pSeqdesc( iSequence ).pszLabel();
  295. }
  296. void StudioModel::ClearOverlaysSequences( void )
  297. {
  298. ClearAnimationLayers( );
  299. memset( m_Layer, 0, sizeof( m_Layer ) );
  300. }
  301. void StudioModel::ClearAnimationLayers( void )
  302. {
  303. m_iActiveLayers = 0;
  304. }
  305. int StudioModel::GetNewAnimationLayer( int iPriority )
  306. {
  307. CStudioHdr *pStudioHdr = GetStudioHdr();
  308. if ( !pStudioHdr )
  309. return 0;
  310. if ( m_iActiveLayers >= MAXSTUDIOANIMLAYERS )
  311. {
  312. Assert( 0 );
  313. return MAXSTUDIOANIMLAYERS - 1;
  314. }
  315. m_Layer[m_iActiveLayers].m_priority = iPriority;
  316. return m_iActiveLayers++;
  317. }
  318. int StudioModel::SetOverlaySequence( int iLayer, int iSequence, float flWeight )
  319. {
  320. CStudioHdr *pStudioHdr = GetStudioHdr();
  321. if ( !pStudioHdr )
  322. return 0;
  323. if (iSequence < 0)
  324. return 0;
  325. if (iLayer < 0 || iLayer >= MAXSTUDIOANIMLAYERS)
  326. {
  327. Assert(0);
  328. return 0;
  329. }
  330. if (iSequence > pStudioHdr->GetNumSeq())
  331. return m_Layer[iLayer].m_sequence;
  332. m_Layer[iLayer].m_sequence = iSequence;
  333. m_Layer[iLayer].m_weight = flWeight;
  334. m_Layer[iLayer].m_playbackrate = 1.0;
  335. return iSequence;
  336. }
  337. float StudioModel::SetOverlayRate( int iLayer, float flCycle, float flPlaybackRate )
  338. {
  339. if (iLayer >= 0 && iLayer < MAXSTUDIOANIMLAYERS)
  340. {
  341. m_Layer[iLayer].m_cycle = flCycle;
  342. m_Layer[iLayer].m_playbackrate = flPlaybackRate;
  343. }
  344. return flCycle;
  345. }
  346. int StudioModel::GetOverlaySequence( int iLayer )
  347. {
  348. CStudioHdr *pStudioHdr = GetStudioHdr();
  349. if ( !pStudioHdr )
  350. return -1;
  351. if (iLayer < 0 || iLayer >= MAXSTUDIOANIMLAYERS)
  352. {
  353. Assert(0);
  354. return 0;
  355. }
  356. return m_Layer[iLayer].m_sequence;
  357. }
  358. float StudioModel::GetOverlaySequenceWeight( int iLayer )
  359. {
  360. CStudioHdr *pStudioHdr = GetStudioHdr();
  361. if ( !pStudioHdr )
  362. return -1;
  363. if (iLayer < 0 || iLayer >= MAXSTUDIOANIMLAYERS)
  364. {
  365. Assert(0);
  366. return 0;
  367. }
  368. return m_Layer[iLayer].m_weight;
  369. }
  370. int StudioModel::LookupSequence( const char *szSequence )
  371. {
  372. int i;
  373. CStudioHdr *pStudioHdr = GetStudioHdr();
  374. if ( !pStudioHdr )
  375. return -1;
  376. for (i = 0; i < pStudioHdr->GetNumSeq(); i++)
  377. {
  378. if (!stricmp( szSequence, pStudioHdr->pSeqdesc( i ).pszLabel() ))
  379. {
  380. return i;
  381. }
  382. }
  383. return -1;
  384. }
  385. int StudioModel::LookupActivity( const char *szActivity )
  386. {
  387. int i;
  388. CStudioHdr *pStudioHdr = GetStudioHdr();
  389. if ( !pStudioHdr )
  390. return -1;
  391. for (i = 0; i < pStudioHdr->GetNumSeq(); i++)
  392. {
  393. if (!stricmp( szActivity, pStudioHdr->pSeqdesc( i ).pszActivityName() ))
  394. {
  395. return i;
  396. }
  397. }
  398. return -1;
  399. }
  400. int StudioModel::SetSequence( const char *szSequence )
  401. {
  402. return SetSequence( LookupSequence( szSequence ) );
  403. }
  404. void StudioModel::StartBlending( void )
  405. {
  406. // Switch back to old sequence ( this will oscillate between this one and the last one )
  407. SetSequence( m_prevsequence );
  408. }
  409. void StudioModel::SetBlendTime( float blendtime )
  410. {
  411. if ( blendtime > 0.0f )
  412. {
  413. m_blendtime = blendtime;
  414. }
  415. }
  416. float StudioModel::GetTransitionAmount( void )
  417. {
  418. if ( g_viewerSettings.blendSequenceChanges &&
  419. m_sequencetime < m_blendtime && m_prevsequence != m_sequence )
  420. {
  421. float s;
  422. s = ( m_sequencetime / m_blendtime );
  423. return s;
  424. }
  425. return 0.0f;
  426. }
  427. LocalFlexController_t StudioModel::LookupFlexController( char *szName )
  428. {
  429. CStudioHdr *pStudioHdr = GetStudioHdr();
  430. if (!pStudioHdr)
  431. return LocalFlexController_t(0);
  432. for (LocalFlexController_t iFlex = LocalFlexController_t(0); iFlex < pStudioHdr->numflexcontrollers(); iFlex++)
  433. {
  434. if (stricmp( szName, pStudioHdr->pFlexcontroller( iFlex )->pszName() ) == 0)
  435. {
  436. return iFlex;
  437. }
  438. }
  439. return LocalFlexController_t(-1);
  440. }
  441. void StudioModel::SetFlexController( char *szName, float flValue )
  442. {
  443. SetFlexController( LookupFlexController( szName ), flValue );
  444. }
  445. void StudioModel::SetFlexController( LocalFlexController_t iFlex, float flValue )
  446. {
  447. CStudioHdr *pStudioHdr = GetStudioHdr();
  448. if ( !pStudioHdr )
  449. return;
  450. if (iFlex >= 0 && iFlex < pStudioHdr->numflexcontrollers())
  451. {
  452. mstudioflexcontroller_t *pflex = pStudioHdr->pFlexcontroller(iFlex);
  453. if (pflex->min != pflex->max)
  454. {
  455. flValue = (flValue - pflex->min) / (pflex->max - pflex->min);
  456. }
  457. m_flexweight[iFlex] = clamp( flValue, 0.0f, 1.0f );
  458. }
  459. }
  460. void StudioModel::SetFlexControllerRaw( LocalFlexController_t iFlex, float flValue )
  461. {
  462. CStudioHdr *pStudioHdr = GetStudioHdr();
  463. if ( !pStudioHdr )
  464. return;
  465. if (iFlex >= 0 && iFlex < pStudioHdr->numflexcontrollers())
  466. {
  467. // mstudioflexcontroller_t *pflex = pStudioHdr->pFlexcontroller(iFlex);
  468. m_flexweight[iFlex] = clamp( flValue, 0.0f, 1.0f );
  469. }
  470. }
  471. float StudioModel::GetFlexController( char *szName )
  472. {
  473. return GetFlexController( LookupFlexController( szName ) );
  474. }
  475. float StudioModel::GetFlexController( LocalFlexController_t iFlex )
  476. {
  477. CStudioHdr *pStudioHdr = GetStudioHdr();
  478. if ( !pStudioHdr )
  479. return 0.0f;
  480. if (iFlex >= 0 && iFlex < pStudioHdr->numflexcontrollers())
  481. {
  482. mstudioflexcontroller_t *pflex = pStudioHdr->pFlexcontroller(iFlex);
  483. float flValue = m_flexweight[iFlex];
  484. if (pflex->min != pflex->max)
  485. {
  486. flValue = flValue * (pflex->max - pflex->min) + pflex->min;
  487. }
  488. return flValue;
  489. }
  490. return 0.0;
  491. }
  492. float StudioModel::GetFlexControllerRaw( LocalFlexController_t iFlex )
  493. {
  494. CStudioHdr *pStudioHdr = GetStudioHdr();
  495. if ( !pStudioHdr )
  496. return 0.0f;
  497. if (iFlex >= 0 && iFlex < pStudioHdr->numflexcontrollers())
  498. {
  499. // mstudioflexcontroller_t *pflex = pStudioHdr->pFlexcontroller(iFlex);
  500. return m_flexweight[iFlex];
  501. }
  502. return 0.0;
  503. }
  504. int StudioModel::GetNumLODs() const
  505. {
  506. return g_pStudioRender->GetNumLODs( *GetHardwareData() );
  507. }
  508. float StudioModel::GetLODSwitchValue( int lod ) const
  509. {
  510. return g_pStudioRender->GetLODSwitchValue( *GetHardwareData(), lod );
  511. }
  512. void StudioModel::SetLODSwitchValue( int lod, float switchValue )
  513. {
  514. g_pStudioRender->SetLODSwitchValue( *GetHardwareData(), lod, switchValue );
  515. }
  516. void StudioModel::ExtractBbox( Vector &mins, Vector &maxs )
  517. {
  518. studiohdr_t *pStudioHdr = GetStudioRenderHdr();
  519. if ( !pStudioHdr )
  520. return;
  521. // look for hull
  522. if ( ((Vector)pStudioHdr->hull_min).Length() != 0 )
  523. {
  524. mins = pStudioHdr->hull_min;
  525. maxs = pStudioHdr->hull_max;
  526. }
  527. // look for view clip
  528. else if (((Vector)pStudioHdr->view_bbmin).Length() != 0)
  529. {
  530. mins = pStudioHdr->view_bbmin;
  531. maxs = pStudioHdr->view_bbmax;
  532. }
  533. else
  534. {
  535. mstudioseqdesc_t &pseqdesc = pStudioHdr->pSeqdesc( m_sequence );
  536. mins = pseqdesc.bbmin;
  537. maxs = pseqdesc.bbmax;
  538. }
  539. }
  540. void StudioModel::GetSequenceInfo( int iSequence, float *pflFrameRate, float *pflGroundSpeed )
  541. {
  542. float t = GetDuration( iSequence );
  543. if (t > 0)
  544. {
  545. *pflFrameRate = 1.0 / t;
  546. }
  547. else
  548. {
  549. *pflFrameRate = 1.0;
  550. }
  551. *pflGroundSpeed = GetGroundSpeed( iSequence );
  552. }
  553. void StudioModel::GetSequenceInfo( float *pflFrameRate, float *pflGroundSpeed )
  554. {
  555. GetSequenceInfo( m_sequence, pflFrameRate, pflGroundSpeed );
  556. }
  557. float StudioModel::GetFPS( int iSequence )
  558. {
  559. CStudioHdr *pStudioHdr = GetStudioHdr();
  560. if ( !pStudioHdr )
  561. return 0.0f;
  562. return Studio_FPS( pStudioHdr, iSequence, m_poseparameter );
  563. }
  564. float StudioModel::GetFPS( void )
  565. {
  566. return GetFPS( m_sequence );
  567. }
  568. float StudioModel::GetDuration( int iSequence )
  569. {
  570. CStudioHdr *pStudioHdr = GetStudioHdr();
  571. if ( !pStudioHdr )
  572. return 0.0f;
  573. return Studio_Duration( pStudioHdr, iSequence, m_poseparameter );
  574. }
  575. int StudioModel::GetNumFrames( int iSequence )
  576. {
  577. CStudioHdr *pStudioHdr = GetStudioHdr();
  578. if ( !pStudioHdr || iSequence < 0 || iSequence >= pStudioHdr->GetNumSeq() )
  579. {
  580. return 1;
  581. }
  582. return Studio_MaxFrame( pStudioHdr, iSequence, m_poseparameter );
  583. }
  584. static int GetSequenceFlags( CStudioHdr *pstudiohdr, int sequence )
  585. {
  586. if ( !pstudiohdr ||
  587. sequence < 0 ||
  588. sequence >= pstudiohdr->GetNumSeq() )
  589. {
  590. return 0;
  591. }
  592. mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence );
  593. return seqdesc.flags;
  594. }
  595. //-----------------------------------------------------------------------------
  596. // Purpose:
  597. // Input : iSequence -
  598. // Output : Returns true on success, false on failure.
  599. //-----------------------------------------------------------------------------
  600. bool StudioModel::GetSequenceLoops( int iSequence )
  601. {
  602. CStudioHdr *pStudioHdr = GetStudioHdr();
  603. if ( !pStudioHdr )
  604. return false;
  605. int flags = GetSequenceFlags( pStudioHdr, iSequence );
  606. bool looping = flags & STUDIO_LOOPING ? true : false;
  607. return looping;
  608. }
  609. float StudioModel::GetDuration( )
  610. {
  611. return GetDuration( m_sequence );
  612. }
  613. void StudioModel::GetMovement( float prevcycle[5], Vector &vecPos, QAngle &vecAngles )
  614. {
  615. vecPos.Init();
  616. vecAngles.Init();
  617. CStudioHdr *pStudioHdr = GetStudioHdr();
  618. if ( !pStudioHdr )
  619. return;
  620. // assume that changes < -0.5 are loops....
  621. if (m_cycle - prevcycle[0] < -0.5)
  622. {
  623. prevcycle[0] = prevcycle[0] - 1.0;
  624. }
  625. Studio_SeqMovement( pStudioHdr, m_sequence, prevcycle[0], m_cycle, m_poseparameter, vecPos, vecAngles );
  626. prevcycle[0] = m_cycle;
  627. int i;
  628. for (i = 0; i < 4; i++)
  629. {
  630. Vector vecTmp;
  631. QAngle angTmp;
  632. if (m_Layer[i].m_cycle - prevcycle[i+1] < -0.5)
  633. {
  634. prevcycle[i+1] = prevcycle[i+1] - 1.0;
  635. }
  636. if (m_Layer[i].m_weight > 0.0)
  637. {
  638. vecTmp.Init();
  639. angTmp.Init();
  640. if (Studio_SeqMovement( pStudioHdr, m_Layer[i].m_sequence, prevcycle[i+1], m_Layer[i].m_cycle, m_poseparameter, vecTmp, angTmp ))
  641. {
  642. vecPos = vecPos * ( 1.0 - m_Layer[i].m_weight ) + vecTmp * m_Layer[i].m_weight;
  643. }
  644. }
  645. prevcycle[i+1] = m_Layer[i].m_cycle;
  646. }
  647. return;
  648. }
  649. void StudioModel::GetMovement( int iSequence, float prevCycle, float nextCycle, Vector &vecPos, QAngle &vecAngles )
  650. {
  651. CStudioHdr *pStudioHdr = GetStudioHdr();
  652. if ( !pStudioHdr )
  653. {
  654. vecPos.Init();
  655. vecAngles.Init();
  656. return;
  657. }
  658. // FIXME: this doesn't consider layers
  659. Studio_SeqMovement( pStudioHdr, iSequence, prevCycle, nextCycle, m_poseparameter, vecPos, vecAngles );
  660. return;
  661. }
  662. //-----------------------------------------------------------------------------
  663. // Purpose: Returns the ground speed of the specifed sequence.
  664. //-----------------------------------------------------------------------------
  665. float StudioModel::GetGroundSpeed( int iSequence )
  666. {
  667. Vector vecMove;
  668. QAngle vecAngles;
  669. GetMovement( iSequence, 0, 1, vecMove, vecAngles );
  670. float t = GetDuration( iSequence );
  671. float flGroundSpeed = 0;
  672. if (t > 0)
  673. {
  674. flGroundSpeed = vecMove.Length() / t;
  675. }
  676. return flGroundSpeed;
  677. }
  678. //-----------------------------------------------------------------------------
  679. // Purpose: Returns the ground speed of the current sequence.
  680. //-----------------------------------------------------------------------------
  681. float StudioModel::GetGroundSpeed( void )
  682. {
  683. return GetGroundSpeed( m_sequence );
  684. }
  685. //-----------------------------------------------------------------------------
  686. // Purpose: Returns the ground speed of the current sequence.
  687. //-----------------------------------------------------------------------------
  688. float StudioModel::GetCurrentVelocity( void )
  689. {
  690. Vector vecVelocity;
  691. CStudioHdr *pStudioHdr = GetStudioHdr();
  692. if (pStudioHdr && Studio_SeqVelocity( pStudioHdr, m_sequence, m_cycle, m_poseparameter, vecVelocity ))
  693. {
  694. return vecVelocity.Length();
  695. }
  696. return 0;
  697. }
  698. //-----------------------------------------------------------------------------
  699. // Purpose: Returns the the sequence should be hidden or not
  700. //-----------------------------------------------------------------------------
  701. bool StudioModel::IsHidden( int iSequence )
  702. {
  703. CStudioHdr *pStudioHdr = GetStudioHdr();
  704. if (pStudioHdr->pSeqdesc( iSequence ).flags & STUDIO_HIDDEN)
  705. return true;
  706. return false;
  707. }
  708. void StudioModel::GetSeqAnims( int iSequence, mstudioanimdesc_t *panim[4], float *weight )
  709. {
  710. CStudioHdr *pStudioHdr = GetStudioHdr();
  711. if (!pStudioHdr)
  712. return;
  713. mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence );
  714. Studio_SeqAnims( pStudioHdr, seqdesc, iSequence, m_poseparameter, panim, weight );
  715. }
  716. void StudioModel::GetSeqAnims( mstudioanimdesc_t *panim[4], float *weight )
  717. {
  718. GetSeqAnims( m_sequence, panim, weight );
  719. }
  720. float StudioModel::SetController( int iController, float flValue )
  721. {
  722. CStudioHdr *pStudioHdr = GetStudioHdr();
  723. if (!pStudioHdr)
  724. return 0.0f;
  725. return Studio_SetController( pStudioHdr, iController, flValue, m_controller[iController] );
  726. }
  727. int StudioModel::LookupPoseParameter( char const *szName )
  728. {
  729. CStudioHdr *pStudioHdr = GetStudioHdr();
  730. if (!pStudioHdr)
  731. return false;
  732. for (int iParameter = 0; iParameter < pStudioHdr->GetNumPoseParameters(); iParameter++)
  733. {
  734. if (stricmp( szName, pStudioHdr->pPoseParameter( iParameter ).pszName() ) == 0)
  735. {
  736. return iParameter;
  737. }
  738. }
  739. return -1;
  740. }
  741. float StudioModel::SetPoseParameter( char const *szName, float flValue )
  742. {
  743. return SetPoseParameter( LookupPoseParameter( szName ), flValue );
  744. }
  745. float StudioModel::SetPoseParameter( int iParameter, float flValue )
  746. {
  747. CStudioHdr *pStudioHdr = GetStudioHdr();
  748. if (!pStudioHdr)
  749. return 0.0f;
  750. return Studio_SetPoseParameter( pStudioHdr, iParameter, flValue, m_poseparameter[iParameter] );
  751. }
  752. float StudioModel::GetPoseParameter( char const *szName )
  753. {
  754. return GetPoseParameter( LookupPoseParameter( szName ) );
  755. }
  756. float* StudioModel::GetPoseParameters()
  757. {
  758. return m_poseparameter;
  759. }
  760. float StudioModel::GetPoseParameter( int iParameter )
  761. {
  762. CStudioHdr *pStudioHdr = GetStudioHdr();
  763. if (!pStudioHdr)
  764. return 0.0f;
  765. return Studio_GetPoseParameter( pStudioHdr, iParameter, m_poseparameter[iParameter] );
  766. }
  767. bool StudioModel::GetPoseParameterRange( int iParameter, float *pflMin, float *pflMax )
  768. {
  769. *pflMin = 0;
  770. *pflMax = 0;
  771. CStudioHdr *pStudioHdr = GetStudioHdr();
  772. if (!pStudioHdr)
  773. return false;
  774. if (iParameter < 0 || iParameter >= pStudioHdr->GetNumPoseParameters())
  775. return false;
  776. const mstudioposeparamdesc_t &Pose = pStudioHdr->pPoseParameter( iParameter );
  777. *pflMin = Pose.start;
  778. *pflMax = Pose.end;
  779. return true;
  780. }
  781. int StudioModel::LookupAttachment( char const *szName )
  782. {
  783. CStudioHdr *pStudioHdr = GetStudioHdr();
  784. if ( !pStudioHdr )
  785. return -1;
  786. for (int i = 0; i < pStudioHdr->GetNumAttachments(); i++)
  787. {
  788. if (stricmp( pStudioHdr->pAttachment( i ).pszName(), szName ) == 0)
  789. {
  790. return i;
  791. }
  792. }
  793. return -1;
  794. }
  795. int StudioModel::SetBodygroup( int iGroup, int iValue /*= -1*/ )
  796. {
  797. CStudioHdr *pStudioHdr = GetStudioHdr();
  798. if (!pStudioHdr)
  799. return 0;
  800. if (iGroup > pStudioHdr->numbodyparts())
  801. return -1;
  802. mstudiobodyparts_t *pbodypart = pStudioHdr->pBodypart( iGroup );
  803. int iCurrent = (m_bodynum / pbodypart->base) % pbodypart->nummodels;
  804. // if the submodel index is not specified or out of range, just use the current value
  805. if ( iValue < 0 || iValue >= pbodypart->nummodels )
  806. return iCurrent;
  807. m_bodynum = (m_bodynum - (iCurrent * pbodypart->base) + (iValue * pbodypart->base));
  808. return iValue;
  809. }
  810. int StudioModel::SetSkin( int iValue )
  811. {
  812. CStudioHdr *pStudioHdr = GetStudioHdr();
  813. if (!pStudioHdr)
  814. return 0;
  815. if (iValue >= pStudioHdr->numskinfamilies())
  816. {
  817. return m_skinnum;
  818. }
  819. m_skinnum = iValue;
  820. return iValue;
  821. }
  822. void StudioModel::scaleMeshes (float scale)
  823. {
  824. CStudioHdr *pStudioHdr = GetStudioHdr();
  825. if (!pStudioHdr)
  826. return;
  827. int i, j, k;
  828. // manadatory to access correct verts
  829. SetCurrentModel();
  830. // scale verts
  831. int tmp = m_bodynum;
  832. for (i = 0; i < pStudioHdr->numbodyparts(); i++)
  833. {
  834. mstudiobodyparts_t *pbodypart = pStudioHdr->pBodypart( i );
  835. for (j = 0; j < pbodypart->nummodels; j++)
  836. {
  837. SetBodygroup (i, j);
  838. SetupModel (i);
  839. const mstudio_modelvertexdata_t *vertData = m_pmodel->GetVertexData();
  840. Assert( vertData ); // This can only return NULL on X360 for now
  841. for (k = 0; k < m_pmodel->numvertices; k++)
  842. {
  843. *vertData->Position(k) *= scale;
  844. }
  845. }
  846. }
  847. m_bodynum = tmp;
  848. // scale complex hitboxes
  849. int hitboxset = g_MDLViewer->GetCurrentHitboxSet();
  850. mstudiobbox_t *pbboxes = pStudioHdr->pHitbox( 0, hitboxset );
  851. for (i = 0; i < pStudioHdr->iHitboxCount( hitboxset ); i++)
  852. {
  853. VectorScale (pbboxes[i].bbmin, scale, pbboxes[i].bbmin);
  854. VectorScale (pbboxes[i].bbmax, scale, pbboxes[i].bbmax);
  855. }
  856. // scale bounding boxes
  857. for (i = 0; i < pStudioHdr->GetNumSeq(); i++)
  858. {
  859. mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( i );
  860. Vector tmp;
  861. tmp = seqdesc.bbmin;
  862. VectorScale( tmp, scale, tmp );
  863. seqdesc.bbmin = tmp;
  864. tmp = seqdesc.bbmax;
  865. VectorScale( tmp, scale, tmp );
  866. seqdesc.bbmax = tmp;
  867. }
  868. // maybe scale exeposition, pivots, attachments
  869. }
  870. void StudioModel::scaleBones (float scale)
  871. {
  872. CStudioHdr *pStudioHdr = GetStudioHdr();
  873. if (!pStudioHdr)
  874. return;
  875. mstudiobone_t *pbones = pStudioHdr->pBone( 0 );
  876. for (int i = 0; i < pStudioHdr->numbones(); i++)
  877. {
  878. pbones[i].pos *= scale;
  879. pbones[i].posscale *= scale;
  880. }
  881. }
  882. int StudioModel::Physics_GetBoneCount( void )
  883. {
  884. return m_pPhysics->Count();
  885. }
  886. const char *StudioModel::Physics_GetBoneName( int index )
  887. {
  888. CPhysmesh *pmesh = m_pPhysics->GetMesh( index );
  889. if ( !pmesh )
  890. return NULL;
  891. return pmesh->m_boneName;
  892. }
  893. void StudioModel::Physics_GetData( int boneIndex, hlmvsolid_t *psolid, constraint_ragdollparams_t *pConstraint ) const
  894. {
  895. CPhysmesh *pMesh = m_pPhysics->GetMesh( boneIndex );
  896. if ( !pMesh )
  897. return;
  898. if ( psolid )
  899. {
  900. memcpy( psolid, &pMesh->m_solid, sizeof(*psolid) );
  901. }
  902. if ( pConstraint )
  903. {
  904. *pConstraint = pMesh->m_constraint;
  905. }
  906. }
  907. void StudioModel::Physics_SetData( int boneIndex, const hlmvsolid_t *psolid, const constraint_ragdollparams_t *pConstraint )
  908. {
  909. CPhysmesh *pMesh = m_pPhysics->GetMesh( boneIndex );
  910. if ( !pMesh )
  911. return;
  912. if ( psolid )
  913. {
  914. memcpy( &pMesh->m_solid, psolid, sizeof(*psolid) );
  915. }
  916. if ( pConstraint )
  917. {
  918. pMesh->m_constraint = *pConstraint;
  919. }
  920. }
  921. float StudioModel::Physics_GetMass( void )
  922. {
  923. return m_pPhysics->GetMass();
  924. }
  925. void StudioModel::Physics_SetMass( float mass )
  926. {
  927. m_physMass = mass;
  928. }
  929. char *StudioModel::Physics_DumpQC( void )
  930. {
  931. return m_pPhysics->DumpQC();
  932. }
  933. const vertexFileHeader_t * mstudiomodel_t::CacheVertexData( void * pModelData )
  934. {
  935. Assert( pModelData == NULL );
  936. Assert( g_pActiveModel );
  937. return g_pStudioDataCache->CacheVertexData( g_pActiveModel->GetStudioRenderHdr() );
  938. }
  939. //-----------------------------------------------------------------------------
  940. // FIXME: This trashy glue code is really not acceptable. Figure out a way of making it unnecessary.
  941. //-----------------------------------------------------------------------------
  942. const studiohdr_t *studiohdr_t::FindModel( void **cache, char const *pModelName ) const
  943. {
  944. MDLHandle_t handle = g_pMDLCache->FindMDL( pModelName );
  945. *cache = (void*)handle;
  946. return g_pMDLCache->GetStudioHdr( handle );
  947. }
  948. virtualmodel_t *studiohdr_t::GetVirtualModel( void ) const
  949. {
  950. return g_pMDLCache->GetVirtualModel( (MDLHandle_t)virtualModel );
  951. }
  952. byte *studiohdr_t::GetAnimBlock( int i ) const
  953. {
  954. return g_pMDLCache->GetAnimBlock( (MDLHandle_t)virtualModel, i );
  955. }
  956. int studiohdr_t::GetAutoplayList( unsigned short **pOut ) const
  957. {
  958. return g_pMDLCache->GetAutoplayList( (MDLHandle_t)virtualModel, pOut );
  959. }
  960. const studiohdr_t *virtualgroup_t::GetStudioHdr( void ) const
  961. {
  962. return g_pMDLCache->GetStudioHdr( (MDLHandle_t)cache );
  963. }