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.

1377 lines
31 KiB

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