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.

2368 lines
58 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // studio_render.cpp: routines for drawing Half-Life 3DStudio models
  9. // updates:
  10. // 1-4-99 fixed AdvanceFrame wraping bug
  11. #include <string.h>
  12. #include <assert.h>
  13. #include <stdio.h>
  14. #include <stdarg.h>
  15. #include <windows.h> // for OutputDebugString. . has to be a better way!
  16. #include "ViewerSettings.h"
  17. #include "StudioModel.h"
  18. #include "vphysics/constraints.h"
  19. #include "physmesh.h"
  20. #include "materialsystem/imaterialsystem.h"
  21. #include "materialsystem/imaterial.h"
  22. #include "materialsystem/imaterialvar.h"
  23. #include "matsyswin.h"
  24. #include "istudiorender.h"
  25. #include "utldict.h"
  26. #include "filesystem.h"
  27. #include "studio_render.h"
  28. #include "materialsystem/imesh.h"
  29. #include "bone_setup.h"
  30. #include "materialsystem/MaterialSystem_Config.h"
  31. #include "MDLViewer.h"
  32. #include "bone_accessor.h"
  33. #include "jigglebones.h"
  34. #include "debugdrawmodel.h"
  35. // FIXME:
  36. extern ViewerSettings g_viewerSettings;
  37. int g_dxlevel = 0;
  38. #pragma warning( disable : 4244 ) // double to float
  39. ////////////////////////////////////////////////////////////////////////
  40. CStudioHdr *g_pCacheHdr = NULL;
  41. Vector g_flexedverts[MAXSTUDIOVERTS];
  42. Vector g_flexednorms[MAXSTUDIOVERTS];
  43. int g_flexages[MAXSTUDIOVERTS];
  44. Vector *g_pflexedverts;
  45. Vector *g_pflexednorms;
  46. int *g_pflexages;
  47. int g_smodels_total; // cookie
  48. matrix3x4_t g_viewtransform; // view transformation
  49. //matrix3x4_t g_posetoworld[MAXSTUDIOBONES]; // bone transformation matrix
  50. matrix3x4_t g_mCachedViewTransform; // copy of view transform for boneMerge passes
  51. static int maxNumVertices;
  52. static int first = 1;
  53. //-----------------------------------------------------------------------------
  54. // Purpose:
  55. //-----------------------------------------------------------------------------
  56. mstudioseqdesc_t &StudioModel::GetSeqDesc( int seq )
  57. {
  58. CStudioHdr *pStudioHdr = GetStudioHdr();
  59. return pStudioHdr->pSeqdesc( seq );
  60. }
  61. mstudioanimdesc_t &StudioModel::GetAnimDesc( int anim )
  62. {
  63. CStudioHdr *pStudioHdr = GetStudioHdr();
  64. return pStudioHdr->pAnimdesc( anim );
  65. }
  66. //-----------------------------------------------------------------------------
  67. // Purpose: Keeps a global clock to autoplay sequences to run from
  68. // Also deals with speedScale changes
  69. //-----------------------------------------------------------------------------
  70. float GetAutoPlayTime( void )
  71. {
  72. static int g_prevTicks;
  73. static float g_time;
  74. int ticks = GetTickCount();
  75. // limit delta so that float time doesn't overflow
  76. if (g_prevTicks == 0)
  77. g_prevTicks = ticks;
  78. g_time += ( (ticks - g_prevTicks) / 1000.0f ) * g_viewerSettings.speedScale;
  79. g_prevTicks = ticks;
  80. return g_time;
  81. }
  82. //-----------------------------------------------------------------------------
  83. // Purpose: Keeps a global clock for "realtime" overlays to run from
  84. //-----------------------------------------------------------------------------
  85. float GetRealtimeTime( void )
  86. {
  87. // renamed static's so debugger doesn't get confused and show the wrong one
  88. static int g_prevTicksRT;
  89. static float g_timeRT;
  90. int ticks = GetTickCount();
  91. // limit delta so that float time doesn't overflow
  92. if (g_prevTicksRT == 0)
  93. g_prevTicksRT = ticks;
  94. g_timeRT += ( (ticks - g_prevTicksRT) / 1000.0f );
  95. g_prevTicksRT = ticks;
  96. return g_timeRT;
  97. }
  98. void StudioModel::AdvanceFrame( float dt )
  99. {
  100. if (dt > 0.1)
  101. dt = 0.1f;
  102. m_dt = dt;
  103. float t = GetDuration( );
  104. if (t > 0)
  105. {
  106. if (dt > 0)
  107. {
  108. m_cycle += dt / t;
  109. m_sequencetime += dt;
  110. // wrap
  111. m_cycle -= (int)(m_cycle);
  112. }
  113. }
  114. else
  115. {
  116. m_cycle = 0;
  117. }
  118. for (int i = 0; i < MAXSTUDIOANIMLAYERS; i++)
  119. {
  120. t = GetDuration( m_Layer[i].m_sequence );
  121. if (t > 0)
  122. {
  123. if (dt > 0)
  124. {
  125. m_Layer[i].m_cycle += (dt / t) * m_Layer[i].m_playbackrate;
  126. m_Layer[i].m_cycle -= (int)(m_Layer[i].m_cycle);
  127. }
  128. }
  129. else
  130. {
  131. m_Layer[i].m_cycle = 0;
  132. }
  133. }
  134. }
  135. float StudioModel::GetInterval( void )
  136. {
  137. return m_dt;
  138. }
  139. float StudioModel::GetCycle( void )
  140. {
  141. return m_cycle;
  142. }
  143. float StudioModel::GetFrame( void )
  144. {
  145. return GetCycle() * GetMaxFrame();
  146. }
  147. int StudioModel::GetMaxFrame( void )
  148. {
  149. CStudioHdr *pStudioHdr = GetStudioHdr();
  150. return Studio_MaxFrame( pStudioHdr, m_sequence, m_poseparameter );
  151. }
  152. int StudioModel::SetFrame( int frame )
  153. {
  154. CStudioHdr *pStudioHdr = GetStudioHdr();
  155. if ( !pStudioHdr )
  156. return 0;
  157. if ( frame <= 0 )
  158. frame = 0;
  159. int maxFrame = GetMaxFrame();
  160. if ( frame >= maxFrame )
  161. {
  162. frame = maxFrame;
  163. m_cycle = 0.99999;
  164. return frame;
  165. }
  166. m_cycle = frame / (float)maxFrame;
  167. return frame;
  168. }
  169. float StudioModel::GetCycle( int iLayer )
  170. {
  171. if (iLayer == 0)
  172. {
  173. return m_cycle;
  174. }
  175. else if (iLayer <= MAXSTUDIOANIMLAYERS)
  176. {
  177. int index = iLayer - 1;
  178. return m_Layer[index].m_cycle;
  179. }
  180. return 0;
  181. }
  182. float StudioModel::GetFrame( int iLayer )
  183. {
  184. return GetCycle( iLayer ) * GetMaxFrame( iLayer );
  185. }
  186. int StudioModel::GetMaxFrame( int iLayer )
  187. {
  188. CStudioHdr *pStudioHdr = GetStudioHdr();
  189. if ( pStudioHdr )
  190. {
  191. if (iLayer == 0)
  192. return Studio_MaxFrame( pStudioHdr, m_sequence, m_poseparameter );
  193. if (iLayer <= MAXSTUDIOANIMLAYERS)
  194. {
  195. int index = iLayer - 1;
  196. return Studio_MaxFrame( pStudioHdr, m_Layer[index].m_sequence, m_poseparameter );
  197. }
  198. }
  199. return 0;
  200. }
  201. int StudioModel::SetFrame( int iLayer, int frame )
  202. {
  203. CStudioHdr *pStudioHdr = GetStudioHdr();
  204. if ( !pStudioHdr )
  205. return 0;
  206. if ( frame <= 0 )
  207. frame = 0;
  208. int maxFrame = GetMaxFrame( iLayer );
  209. float cycle = 0;
  210. if (maxFrame)
  211. {
  212. if ( frame >= maxFrame )
  213. {
  214. frame = maxFrame;
  215. cycle = 0.99999;
  216. }
  217. cycle = frame / (float)maxFrame;
  218. }
  219. if (iLayer == 0)
  220. {
  221. m_cycle = cycle;
  222. }
  223. else if (iLayer <= MAXSTUDIOANIMLAYERS)
  224. {
  225. int index = iLayer - 1;
  226. m_Layer[index].m_cycle = cycle;
  227. }
  228. return frame;
  229. }
  230. //-----------------------------------------------------------------------------
  231. // Purpose: Maps from local axis (X,Y,Z) to Half-Life (PITCH,YAW,ROLL) axis/rotation mappings
  232. //-----------------------------------------------------------------------------
  233. static int RemapAxis( int axis )
  234. {
  235. switch( axis )
  236. {
  237. case 0:
  238. return 2;
  239. case 1:
  240. return 0;
  241. case 2:
  242. return 1;
  243. }
  244. return 0;
  245. }
  246. void StudioModel::Physics_SetPreview( int previewBone, int axis, float t )
  247. {
  248. m_physPreviewBone = previewBone;
  249. m_physPreviewAxis = axis;
  250. m_physPreviewParam = t;
  251. }
  252. void StudioModel::OverrideBones( bool *override )
  253. {
  254. matrix3x4_t basematrix;
  255. matrix3x4_t bonematrix;
  256. QAngle tmp;
  257. // offset for the base pose to world transform of 90 degrees around up axis
  258. tmp[0] = 0; tmp[1] = 90; tmp[2] = 0;
  259. AngleMatrix( tmp, bonematrix );
  260. ConcatTransforms( g_viewtransform, bonematrix, basematrix );
  261. for ( int i = 0; i < m_pPhysics->Count(); i++ )
  262. {
  263. CPhysmesh *pmesh = m_pPhysics->GetMesh( i );
  264. // BUGBUG: Cache this if you care about performance!
  265. int boneIndex = FindBone(pmesh->m_boneName);
  266. // bone is not constrained, don't override rotations
  267. if ( pmesh->m_constraint.parentIndex == 0 && pmesh->m_constraint.childIndex == 0 )
  268. {
  269. boneIndex = -1;
  270. }
  271. if ( boneIndex >= 0 )
  272. {
  273. matrix3x4_t *parentMatrix = &basematrix;
  274. override[boneIndex] = true;
  275. int parentBone = -1;
  276. if ( pmesh->m_constraint.parentIndex >= 0 )
  277. {
  278. parentBone = FindBone( m_pPhysics->GetMesh(pmesh->m_constraint.parentIndex)->m_boneName );
  279. }
  280. if ( parentBone >= 0 )
  281. {
  282. parentMatrix = &m_pBoneToWorld[ parentBone ];
  283. }
  284. if ( m_physPreviewBone == i )
  285. {
  286. matrix3x4_t tmpmatrix;
  287. QAngle rot;
  288. constraint_axislimit_t *axis = pmesh->m_constraint.axes + m_physPreviewAxis;
  289. int hlAxis = RemapAxis( m_physPreviewAxis );
  290. rot.Init();
  291. rot[hlAxis] = axis->minRotation + (axis->maxRotation - axis->minRotation) * m_physPreviewParam;
  292. AngleMatrix( rot, tmpmatrix );
  293. ConcatTransforms( pmesh->m_matrix, tmpmatrix, bonematrix );
  294. }
  295. else
  296. {
  297. MatrixCopy( pmesh->m_matrix, bonematrix );
  298. }
  299. ConcatTransforms( *parentMatrix, bonematrix, m_pBoneToWorld[ boneIndex ] );
  300. }
  301. }
  302. }
  303. int StudioModel::BoneMask( void )
  304. {
  305. int lod = g_viewerSettings.autoLOD ? 0 : g_viewerSettings.lod;
  306. int mask = BONE_USED_BY_VERTEX_AT_LOD(lod);
  307. if (g_viewerSettings.showAttachments || g_viewerSettings.m_iEditAttachment != -1 || m_nSolveHeadTurn != 0 || LookupAttachment( "eyes" ) != -1)
  308. {
  309. mask |= BONE_USED_BY_ATTACHMENT;
  310. }
  311. if (g_viewerSettings.showHitBoxes)
  312. {
  313. mask |= BONE_USED_BY_HITBOX;
  314. }
  315. mask |= BONE_USED_BY_BONE_MERGE;
  316. return mask;
  317. // return BONE_USED_BY_ANYTHING_AT_LOD( lod );
  318. // return BONE_USED_BY_ANYTHING;
  319. }
  320. void StudioModel::SetUpBones( bool mergeBones )
  321. {
  322. int i, j;
  323. mstudiobone_t *pbones;
  324. static Vector pos[MAXSTUDIOBONES];
  325. matrix3x4_t bonematrix;
  326. static Quaternion q[MAXSTUDIOBONES];
  327. bool override[MAXSTUDIOBONES];
  328. static matrix3x4_t boneCache[MAXSTUDIOBONES];
  329. // For blended transitions
  330. static Vector pos2[MAXSTUDIOBONES];
  331. static Quaternion q2[MAXSTUDIOBONES];
  332. CStudioHdr *pStudioHdr = GetStudioHdr();
  333. mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_sequence );
  334. QAngle a1;
  335. Vector p1;
  336. MatrixAngles( g_viewtransform, a1, p1 );
  337. CIKContext *pIK = NULL;
  338. m_ik.Init( pStudioHdr, a1, p1, GetRealtimeTime(), m_iFramecounter, BoneMask( ) );
  339. if ( g_viewerSettings.enableIK )
  340. {
  341. pIK = &m_ik;
  342. }
  343. IBoneSetup boneSetup( pStudioHdr, BoneMask(), m_poseparameter );
  344. boneSetup.InitPose( pos, q );
  345. boneSetup.AccumulatePose( pos, q, m_sequence, m_cycle, 1.0, GetRealtimeTime(), pIK );
  346. if ( g_viewerSettings.blendSequenceChanges &&
  347. m_sequencetime < m_blendtime &&
  348. m_prevsequence != m_sequence &&
  349. m_prevsequence < pStudioHdr->GetNumSeq() &&
  350. !(seqdesc.flags & STUDIO_SNAP) )
  351. {
  352. // Make sure frame is valid
  353. if ( m_prevcycle >= 1.0 )
  354. {
  355. m_prevcycle = 0.0f;
  356. }
  357. float s = 1.0 - ( m_sequencetime / m_blendtime );
  358. s = 3 * s * s - 2 * s * s * s;
  359. boneSetup.AccumulatePose( pos, q, m_prevsequence, m_prevcycle, s, GetRealtimeTime(), NULL );
  360. // Con_DPrintf("%d %f : %d %f : %f\n", pev->sequence, f, pev->prevsequence, pev->prevframe, s );
  361. }
  362. else
  363. {
  364. m_prevcycle = m_cycle;
  365. }
  366. int iMaxPriority = 0;
  367. for (i = 0; i < MAXSTUDIOANIMLAYERS; i++)
  368. {
  369. if (m_Layer[i].m_weight > 0)
  370. {
  371. iMaxPriority = max( m_Layer[i].m_priority, iMaxPriority );
  372. }
  373. }
  374. for (j = 0; j <= iMaxPriority; j++)
  375. {
  376. for (i = 0; i < MAXSTUDIOANIMLAYERS; i++)
  377. {
  378. if (m_Layer[i].m_priority == j && m_Layer[i].m_weight > 0)
  379. {
  380. boneSetup.AccumulatePose( pos, q, m_Layer[i].m_sequence, m_Layer[i].m_cycle, m_Layer[i].m_weight, GetRealtimeTime(), pIK );
  381. }
  382. }
  383. }
  384. if (m_nSolveHeadTurn != 0)
  385. {
  386. GetBodyPoseParametersFromFlex( );
  387. }
  388. CalcHeadRotation( pos, q );
  389. CIKContext auto_ik;
  390. auto_ik.Init( pStudioHdr, a1, p1, 0.0, 0, BoneMask( ) );
  391. boneSetup.CalcAutoplaySequences( pos, q, GetAutoPlayTime(), &auto_ik );
  392. boneSetup.CalcBoneAdj( pos, q, m_controller );
  393. CBoneBitList boneComputed;
  394. if (pIK)
  395. {
  396. Vector deltaPos;
  397. QAngle deltaAngles;
  398. GetMovement( m_prevIKCycles, deltaPos, deltaAngles );
  399. Vector tmp;
  400. VectorRotate( deltaPos, g_viewtransform, tmp );
  401. deltaPos = tmp;
  402. pIK->UpdateTargets( pos, q, m_pBoneToWorld, boneComputed );
  403. // FIXME: check number of slots?
  404. for (int i = 0; i < pIK->m_target.Count(); i++)
  405. {
  406. trace_t tr;
  407. CIKTarget *pTarget = &pIK->m_target[i];
  408. switch( pTarget->type )
  409. {
  410. case IK_GROUND:
  411. {
  412. // drawLine( pTarget->est.pos, pTarget->est.pos + pTarget->offset.pos, 0, 255, 0 );
  413. // hack in movement
  414. pTarget->est.pos -= deltaPos;
  415. matrix3x4_t invViewTransform;
  416. MatrixInvert( g_viewtransform, invViewTransform );
  417. Vector tmp;
  418. VectorTransform( pTarget->est.pos, invViewTransform, tmp );
  419. tmp.z = pTarget->est.floor;
  420. VectorTransform( tmp, g_viewtransform, pTarget->est.pos );
  421. Vector p1;
  422. Quaternion q1;
  423. MatrixAngles( g_viewtransform, q1, p1 );
  424. pTarget->est.q = q1;
  425. float color[4] = { 0, 0, 0, 0 };
  426. float wirecolor[4] = { 1, 1, 0, 1 };
  427. if (pTarget->est.latched > 0.0)
  428. {
  429. wirecolor[1] = 1.0 - pTarget->est.flWeight;
  430. }
  431. else
  432. {
  433. wirecolor[0] = 1.0 - pTarget->est.flWeight;
  434. }
  435. float r = max(pTarget->est.radius,1.f);
  436. Vector p0 = tmp + Vector( -r, -r, 0 );
  437. Vector p2 = tmp + Vector( r, r, 0 );
  438. drawTransparentBox( p0, p2, g_viewtransform, color, wirecolor );
  439. if (!g_viewerSettings.enableTargetIK)
  440. {
  441. pTarget->est.flWeight = 0.0;
  442. }
  443. }
  444. break;
  445. case IK_ATTACHMENT:
  446. {
  447. matrix3x4_t m;
  448. QuaternionMatrix( pTarget->est.q, pTarget->est.pos, m );
  449. drawTransform( m, 4 );
  450. }
  451. break;
  452. }
  453. // drawLine( pTarget->est.pos, pTarget->latched.pos, 255, 0, 0 );
  454. }
  455. pIK->SolveDependencies( pos, q, m_pBoneToWorld, boneComputed );
  456. }
  457. pbones = pStudioHdr->pBone( 0 );
  458. memset( override, 0, sizeof(bool)*pStudioHdr->numbones() );
  459. if ( g_viewerSettings.showPhysicsPreview )
  460. {
  461. OverrideBones( override );
  462. }
  463. for (i = 0; i < pStudioHdr->numbones(); i++)
  464. {
  465. if ( !(pStudioHdr->pBone( i )->flags & BoneMask()))
  466. {
  467. int j, k;
  468. for (j = 0; j < 3; j++)
  469. {
  470. for (k = 0; k < 4; k++)
  471. {
  472. m_pBoneToWorld[i][j][k] = VEC_T_NAN;
  473. }
  474. }
  475. continue;
  476. }
  477. if ( override[i] )
  478. {
  479. continue;
  480. }
  481. else if (boneComputed.IsBoneMarked(i))
  482. {
  483. // already calculated
  484. }
  485. else if (CalcProceduralBone( pStudioHdr, i, CBoneAccessor( m_pBoneToWorld ) ))
  486. {
  487. continue;
  488. }
  489. else
  490. {
  491. QuaternionMatrix( q[i], bonematrix );
  492. bonematrix[0][3] = pos[i][0];
  493. bonematrix[1][3] = pos[i][1];
  494. bonematrix[2][3] = pos[i][2];
  495. if ( (pStudioHdr->pBone( 0 )[i].flags & BONE_ALWAYS_PROCEDURAL) &&
  496. (pStudioHdr->pBone( 0 )[i].proctype & STUDIO_PROC_JIGGLE) )
  497. {
  498. //
  499. // Physics-based "jiggle" bone
  500. // Bone is assumed to be along the Z axis
  501. // Pitch around X, yaw around Y
  502. //
  503. // compute desired bone orientation
  504. matrix3x4_t goalMX;
  505. if (pbones[i].parent == -1)
  506. {
  507. ConcatTransforms( g_viewtransform, bonematrix, goalMX );
  508. }
  509. else
  510. {
  511. ConcatTransforms( m_pBoneToWorld[ pbones[i].parent ], bonematrix, goalMX );
  512. }
  513. // get jiggle properties from QC data
  514. mstudiojigglebone_t *jiggleInfo = (mstudiojigglebone_t *)pStudioHdr->pBone( 0 )[i].pProcedure( );
  515. if (!m_pJiggleBones)
  516. {
  517. m_pJiggleBones = new CJiggleBones;
  518. }
  519. // do jiggle physics
  520. m_pJiggleBones->BuildJiggleTransformations( i, GetRealtimeTime(), jiggleInfo, goalMX, m_pBoneToWorld[ i ] );
  521. }
  522. else if (pbones[i].parent == -1)
  523. {
  524. ConcatTransforms( g_viewtransform, bonematrix, m_pBoneToWorld[ i ] );
  525. // MatrixCopy(bonematrix, g_bonetoworld[i]);
  526. }
  527. else
  528. {
  529. ConcatTransforms( m_pBoneToWorld[ pbones[i].parent ], bonematrix, m_pBoneToWorld[ i ] );
  530. }
  531. }
  532. if (!mergeBones)
  533. {
  534. g_pCacheHdr = pStudioHdr;
  535. MatrixCopy( m_pBoneToWorld[ i ], boneCache[i] );
  536. }
  537. else if (g_pCacheHdr)
  538. {
  539. for (j = 0; j < g_pCacheHdr->numbones(); j++)
  540. {
  541. if ( Q_stricmp( pStudioHdr->pBone( i )->pszName(), g_pCacheHdr->pBone( j )->pszName() ) == 0 )
  542. break;
  543. }
  544. if (j < g_pCacheHdr->numbones())
  545. {
  546. MatrixCopy( boneCache[j], m_pBoneToWorld[ i ] );
  547. }
  548. }
  549. }
  550. if ( mergeBones )
  551. {
  552. Studio_RunBoneFlexDrivers( m_flexweight, pStudioHdr, pos, m_pBoneToWorld, g_mCachedViewTransform );
  553. }
  554. else
  555. {
  556. MatrixCopy( g_viewtransform, g_mCachedViewTransform );
  557. Studio_RunBoneFlexDrivers( m_flexweight, pStudioHdr, pos, m_pBoneToWorld, g_viewtransform );
  558. }
  559. if (g_viewerSettings.showAttachments)
  560. {
  561. // drawTransform( m_pBoneToWorld[ 0 ] );
  562. }
  563. }
  564. /*
  565. ================
  566. StudioModel::SetupLighting
  567. set some global variables based on entity position
  568. inputs:
  569. outputs:
  570. ================
  571. */
  572. void StudioModel::SetupLighting ( )
  573. {
  574. LightDesc_t light[2];
  575. light[0].m_Type = MATERIAL_LIGHT_DIRECTIONAL;
  576. light[0].m_Attenuation0 = 1.0f;
  577. light[0].m_Attenuation1 = 0.0;
  578. light[0].m_Attenuation2 = 0.0;
  579. light[0].m_Color[0] = g_viewerSettings.lColor[0];
  580. light[0].m_Color[1] = g_viewerSettings.lColor[1];
  581. light[0].m_Color[2] = g_viewerSettings.lColor[2];
  582. light[0].m_Range = 2000;
  583. // DEBUG: Spin the light around the head for debugging
  584. // g_viewerSettings.lightrot = QAngle( 0, 0, 0 );
  585. // g_viewerSettings.lightrot.y = fmod( (90 * GetTickCount( ) / 1000.0), 360.0);
  586. AngleVectors( g_viewerSettings.lightrot, &light[0].m_Direction, NULL, NULL );
  587. g_pStudioRender->SetLocalLights( 1, light );
  588. #if 0
  589. light[1].m_Type = MATERIAL_LIGHT_DIRECTIONAL;
  590. light[1].m_Attenuation0 = 1.0f;
  591. light[1].m_Attenuation1 = 0.0;
  592. light[1].m_Attenuation2 = 0.0;
  593. light[1].m_Range = 2000;
  594. light[1].m_Color[0] = g_viewerSettings.lColor[2];
  595. light[1].m_Color[1] = g_viewerSettings.lColor[1];
  596. light[1].m_Color[2] = g_viewerSettings.lColor[0];
  597. light[1].m_Direction.x = -light[0].m_Direction.y;
  598. light[1].m_Direction.y = light[0].m_Direction.x;
  599. light[1].m_Direction.z = light[0].m_Direction.z;
  600. g_pStudioRender->SetLocalLights( 2, light );
  601. #endif
  602. int i;
  603. for( i = 0; i < g_pStudioRender->GetNumAmbientLightSamples(); i++ )
  604. {
  605. m_AmbientLightColors[i][0] = g_viewerSettings.aColor[0];
  606. m_AmbientLightColors[i][1] = g_viewerSettings.aColor[1];
  607. m_AmbientLightColors[i][2] = g_viewerSettings.aColor[2];
  608. }
  609. //m_AmbientLightColors[0][0] = 1.0;
  610. //m_AmbientLightColors[0][1] = 1.0;
  611. //m_AmbientLightColors[0][2] = 1.0;
  612. g_pStudioRender->SetAmbientLightColors( m_AmbientLightColors );
  613. }
  614. int FindBoneIndex( CStudioHdr *pstudiohdr, const char *pName )
  615. {
  616. mstudiobone_t *pbones = pstudiohdr->pBone( 0 );
  617. for (int i = 0; i < pstudiohdr->numbones(); i++)
  618. {
  619. if ( !strcmpi( pName, pbones[i].pszName() ) )
  620. return i;
  621. }
  622. return -1;
  623. }
  624. //-----------------------------------------------------------------------------
  625. // Purpose: Find the named bone index, -1 if not found
  626. // Input : *pName - bone name
  627. //-----------------------------------------------------------------------------
  628. int StudioModel::FindBone( const char *pName )
  629. {
  630. CStudioHdr *pStudioHdr = GetStudioHdr();
  631. return FindBoneIndex( pStudioHdr, pName );
  632. }
  633. int StudioModel::Physics_GetBoneIndex( const char *pName )
  634. {
  635. for (int i = 0; i < m_pPhysics->Count(); i++)
  636. {
  637. CPhysmesh *pmesh = m_pPhysics->GetMesh(i);
  638. if ( !strcmpi( pName, pmesh[i].m_boneName ) )
  639. return i;
  640. }
  641. return -1;
  642. }
  643. /*
  644. =================
  645. StudioModel::SetupModel
  646. based on the body part, figure out which mesh it should be using.
  647. inputs:
  648. currententity
  649. outputs:
  650. pstudiomesh
  651. pmdl
  652. =================
  653. */
  654. void StudioModel::SetupModel ( int bodypart )
  655. {
  656. int index;
  657. CStudioHdr *pStudioHdr = GetStudioHdr();
  658. if (bodypart > pStudioHdr->numbodyparts())
  659. {
  660. // Con_DPrintf ("StudioModel::SetupModel: no such bodypart %d\n", bodypart);
  661. bodypart = 0;
  662. }
  663. mstudiobodyparts_t *pbodypart = pStudioHdr->pBodypart( bodypart );
  664. index = m_bodynum / pbodypart->base;
  665. index = index % pbodypart->nummodels;
  666. m_pmodel = pbodypart->pModel( index );
  667. if(first){
  668. maxNumVertices = m_pmodel->numvertices;
  669. first = 0;
  670. }
  671. }
  672. static IMaterial *g_pAlpha;
  673. //-----------------------------------------------------------------------------
  674. // Draws a box, not wireframed
  675. //-----------------------------------------------------------------------------
  676. void StudioModel::drawBox (Vector const *v, float const * color )
  677. {
  678. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  679. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  680. CMeshBuilder meshBuilder;
  681. // The four sides
  682. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 * 4 );
  683. for (int i = 0; i < 10; i++)
  684. {
  685. meshBuilder.Position3fv (v[i & 7].Base() );
  686. meshBuilder.Color4fv( color );
  687. meshBuilder.AdvanceVertex();
  688. }
  689. meshBuilder.End();
  690. pMesh->Draw();
  691. // top and bottom
  692. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 );
  693. meshBuilder.Position3fv (v[6].Base());
  694. meshBuilder.Color4fv( color );
  695. meshBuilder.AdvanceVertex();
  696. meshBuilder.Position3fv (v[0].Base());
  697. meshBuilder.Color4fv( color );
  698. meshBuilder.AdvanceVertex();
  699. meshBuilder.Position3fv (v[4].Base());
  700. meshBuilder.Color4fv( color );
  701. meshBuilder.AdvanceVertex();
  702. meshBuilder.Position3fv (v[2].Base());
  703. meshBuilder.Color4fv( color );
  704. meshBuilder.AdvanceVertex();
  705. meshBuilder.End();
  706. pMesh->Draw();
  707. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 );
  708. meshBuilder.Position3fv (v[1].Base());
  709. meshBuilder.Color4fv( color );
  710. meshBuilder.AdvanceVertex();
  711. meshBuilder.Position3fv (v[7].Base());
  712. meshBuilder.Color4fv( color );
  713. meshBuilder.AdvanceVertex();
  714. meshBuilder.Position3fv (v[3].Base());
  715. meshBuilder.Color4fv( color );
  716. meshBuilder.AdvanceVertex();
  717. meshBuilder.Position3fv (v[5].Base());
  718. meshBuilder.Color4fv( color );
  719. meshBuilder.AdvanceVertex();
  720. meshBuilder.End();
  721. pMesh->Draw();
  722. }
  723. //-----------------------------------------------------------------------------
  724. // Draws a wireframed box
  725. //-----------------------------------------------------------------------------
  726. void StudioModel::drawWireframeBox (Vector const *v, float const* color )
  727. {
  728. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  729. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  730. CMeshBuilder meshBuilder;
  731. // The four sides
  732. meshBuilder.Begin( pMesh, MATERIAL_LINES, 4 );
  733. for (int i = 0; i < 10; i++)
  734. {
  735. meshBuilder.Position3fv (v[i & 7].Base());
  736. meshBuilder.Color4fv( color );
  737. meshBuilder.AdvanceVertex();
  738. }
  739. meshBuilder.End();
  740. pMesh->Draw();
  741. // top and bottom
  742. meshBuilder.Begin( pMesh, MATERIAL_LINE_STRIP, 4 );
  743. meshBuilder.Position3fv (v[6].Base());
  744. meshBuilder.Color4fv( color );
  745. meshBuilder.AdvanceVertex();
  746. meshBuilder.Position3fv (v[0].Base());
  747. meshBuilder.Color4fv( color );
  748. meshBuilder.AdvanceVertex();
  749. meshBuilder.Position3fv (v[2].Base());
  750. meshBuilder.Color4fv( color );
  751. meshBuilder.AdvanceVertex();
  752. meshBuilder.Position3fv (v[4].Base());
  753. meshBuilder.Color4fv( color );
  754. meshBuilder.AdvanceVertex();
  755. meshBuilder.Position3fv (v[6].Base());
  756. meshBuilder.Color4fv( color );
  757. meshBuilder.AdvanceVertex();
  758. meshBuilder.End();
  759. pMesh->Draw();
  760. meshBuilder.Begin( pMesh, MATERIAL_LINE_STRIP, 4 );
  761. meshBuilder.Position3fv (v[1].Base());
  762. meshBuilder.Color4fv( color );
  763. meshBuilder.AdvanceVertex();
  764. meshBuilder.Position3fv (v[7].Base());
  765. meshBuilder.Color4fv( color );
  766. meshBuilder.AdvanceVertex();
  767. meshBuilder.Position3fv (v[5].Base());
  768. meshBuilder.Color4fv( color );
  769. meshBuilder.AdvanceVertex();
  770. meshBuilder.Position3fv (v[3].Base());
  771. meshBuilder.Color4fv( color );
  772. meshBuilder.AdvanceVertex();
  773. meshBuilder.Position3fv (v[1].Base());
  774. meshBuilder.Color4fv( color );
  775. meshBuilder.AdvanceVertex();
  776. meshBuilder.End();
  777. pMesh->Draw();
  778. }
  779. //-----------------------------------------------------------------------------
  780. // Draws the position and axies of a transformation matrix, x=red,y=green,z=blue
  781. //-----------------------------------------------------------------------------
  782. void StudioModel::drawTransform( matrix3x4_t& m, float flLength )
  783. {
  784. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  785. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  786. CMeshBuilder meshBuilder;
  787. for (int k = 0; k < 3; k++)
  788. {
  789. static unsigned char color[3][3] =
  790. {
  791. { 255, 0, 0 },
  792. { 0, 255, 0 },
  793. { 0, 0, 255 }
  794. };
  795. meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
  796. meshBuilder.Color3ubv( color[k] );
  797. meshBuilder.Position3f( m[0][3], m[1][3], m[2][3]);
  798. meshBuilder.AdvanceVertex();
  799. meshBuilder.Color3ubv( color[k] );
  800. meshBuilder.Position3f( m[0][3] + m[0][k] * flLength, m[1][3] + m[1][k] * flLength, m[2][3] + m[2][k] * flLength);
  801. meshBuilder.AdvanceVertex();
  802. meshBuilder.End();
  803. pMesh->Draw();
  804. }
  805. }
  806. void drawLine( Vector const &p1, Vector const &p2, int r, int g, int b, bool noDepthTest, float duration )
  807. {
  808. g_pStudioModel->drawLine( p1, p2, r, g, b );
  809. }
  810. void StudioModel::drawLine( Vector const &p1, Vector const &p2, int r, int g, int b )
  811. {
  812. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  813. pRenderContext->Bind( g_materialVertexColor );
  814. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  815. CMeshBuilder meshBuilder;
  816. meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
  817. meshBuilder.Color3ub( r, g, b );
  818. meshBuilder.Position3f( p1.x, p1.y, p1.z );
  819. meshBuilder.AdvanceVertex();
  820. meshBuilder.Color3ub( r, g, b );
  821. meshBuilder.Position3f( p2.x, p2.y, p2.z );
  822. meshBuilder.AdvanceVertex();
  823. meshBuilder.End();
  824. pMesh->Draw();
  825. }
  826. //-----------------------------------------------------------------------------
  827. // Draws a transparent box with a wireframe outline
  828. //-----------------------------------------------------------------------------
  829. void StudioModel::drawTransparentBox( Vector const &bbmin, Vector const &bbmax,
  830. const matrix3x4_t& m, float const *color, float const *wirecolor )
  831. {
  832. Vector v[8], v2[8];
  833. v[0][0] = bbmin[0];
  834. v[0][1] = bbmax[1];
  835. v[0][2] = bbmin[2];
  836. v[1][0] = bbmin[0];
  837. v[1][1] = bbmin[1];
  838. v[1][2] = bbmin[2];
  839. v[2][0] = bbmax[0];
  840. v[2][1] = bbmax[1];
  841. v[2][2] = bbmin[2];
  842. v[3][0] = bbmax[0];
  843. v[3][1] = bbmin[1];
  844. v[3][2] = bbmin[2];
  845. v[4][0] = bbmax[0];
  846. v[4][1] = bbmax[1];
  847. v[4][2] = bbmax[2];
  848. v[5][0] = bbmax[0];
  849. v[5][1] = bbmin[1];
  850. v[5][2] = bbmax[2];
  851. v[6][0] = bbmin[0];
  852. v[6][1] = bbmax[1];
  853. v[6][2] = bbmax[2];
  854. v[7][0] = bbmin[0];
  855. v[7][1] = bbmin[1];
  856. v[7][2] = bbmax[2];
  857. VectorTransform (v[0], m, v2[0]);
  858. VectorTransform (v[1], m, v2[1]);
  859. VectorTransform (v[2], m, v2[2]);
  860. VectorTransform (v[3], m, v2[3]);
  861. VectorTransform (v[4], m, v2[4]);
  862. VectorTransform (v[5], m, v2[5]);
  863. VectorTransform (v[6], m, v2[6]);
  864. VectorTransform (v[7], m, v2[7]);
  865. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  866. pRenderContext->Bind( g_pAlpha );
  867. drawBox( v2, color );
  868. pRenderContext->Bind( g_materialBones );
  869. drawWireframeBox( v2, wirecolor );
  870. }
  871. void StudioModel::UpdateStudioRenderConfig( bool bWireframe, bool bZBufferWireframe, bool bNormals, bool bTangentFrame )
  872. {
  873. StudioRenderConfig_t config;
  874. memset( &config, 0, sizeof( config ) );
  875. config.fEyeShiftX = 0.0f;
  876. config.fEyeShiftY = 0.0f;
  877. config.fEyeShiftZ = 0.0f;
  878. config.fEyeSize = 0;
  879. config.drawEntities = 1;
  880. config.skin = 0;
  881. config.fullbright = 0;
  882. config.bEyeMove = true;
  883. config.bWireframe = bWireframe;
  884. if ( g_viewerSettings.renderMode == RM_WIREFRAME || g_viewerSettings.softwareSkin || config.bWireframe || bNormals || bTangentFrame )
  885. {
  886. config.bSoftwareSkin = true;
  887. }
  888. else
  889. {
  890. config.bSoftwareSkin = false;
  891. }
  892. config.bSoftwareLighting = false;
  893. config.bNoHardware = false;
  894. config.bNoSoftware = false;
  895. config.bTeeth = true;
  896. config.bEyes = true;
  897. config.bFlex = true;
  898. config.bDrawNormals = bNormals;
  899. config.bDrawTangentFrame = bTangentFrame;
  900. config.bDrawZBufferedWireframe = bZBufferWireframe;
  901. config.bShowEnvCubemapOnly = false;
  902. g_pStudioRender->UpdateConfig( config );
  903. MaterialSystem_Config_t matSysConfig = g_pMaterialSystem->GetCurrentConfigForVideoCard();
  904. extern void InitMaterialSystemConfig(MaterialSystem_Config_t *pConfig);
  905. InitMaterialSystemConfig( &matSysConfig );
  906. matSysConfig.nFullbright = 0;
  907. if( g_viewerSettings.renderMode == RM_SMOOTHSHADED )
  908. {
  909. matSysConfig.nFullbright = 2;
  910. }
  911. if ( g_dxlevel != 0 )
  912. {
  913. matSysConfig.dxSupportLevel = g_dxlevel;
  914. }
  915. g_pMaterialSystem->OverrideConfig( matSysConfig, false );
  916. }
  917. //-----------------------------------------------------------------------------
  918. // Draws the skeleton
  919. //-----------------------------------------------------------------------------
  920. void StudioModel::DrawBones( )
  921. {
  922. // draw bones
  923. if (!g_viewerSettings.showBones && (g_viewerSettings.highlightBone < 0))
  924. return;
  925. CStudioHdr *pStudioHdr = GetStudioHdr();
  926. mstudiobone_t *pbones = pStudioHdr->pBone( 0 );
  927. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  928. pRenderContext->Bind( g_materialBones );
  929. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  930. CMeshBuilder meshBuilder;
  931. bool drawRed = (g_viewerSettings.highlightBone >= 0);
  932. for (int i = 0; i < pStudioHdr->numbones(); i++)
  933. {
  934. if ( !(pStudioHdr->pBone( i )->flags & BoneMask()))
  935. continue;
  936. if ( pbones[i].parent >= 0 )
  937. {
  938. int j = pbones[i].parent;
  939. if ( (g_viewerSettings.highlightBone < 0 ) || (j == g_viewerSettings.highlightBone) )
  940. {
  941. meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
  942. if (drawRed)
  943. meshBuilder.Color3ub( 255, 255, 0 );
  944. else
  945. meshBuilder.Color3ub( 0, 255, 255 );
  946. meshBuilder.Position3f( m_pBoneToWorld[j][0][3], m_pBoneToWorld[j][1][3], m_pBoneToWorld[j][2][3]);
  947. meshBuilder.AdvanceVertex();
  948. if (drawRed)
  949. meshBuilder.Color3ub( 255, 255, 0 );
  950. else
  951. meshBuilder.Color3ub( 0, 255, 255 );
  952. meshBuilder.Position3f( m_pBoneToWorld[i][0][3], m_pBoneToWorld[i][1][3], m_pBoneToWorld[i][2][3]);
  953. meshBuilder.AdvanceVertex();
  954. meshBuilder.End();
  955. pMesh->Draw();
  956. }
  957. }
  958. if (g_viewerSettings.highlightBone >= 0)
  959. {
  960. if (i != g_viewerSettings.highlightBone)
  961. continue;
  962. }
  963. drawTransform( m_pBoneToWorld[i] );
  964. }
  965. // manadatory to access correct verts
  966. SetCurrentModel();
  967. // highlight used vertices with point
  968. /*
  969. if (g_viewerSettings.highlightBone >= 0)
  970. {
  971. int k, j, n;
  972. for (i = 0; i < pStudioHdr->numbodyparts; i++)
  973. {
  974. for (j = 0; j < pStudioHdr->pBodypart( i )->nummodels; j++)
  975. {
  976. mstudiomodel_t *pModel = pStudioHdr->pBodypart( i )->pModel( j );
  977. const mstudio_modelvertexdata_t *vertData = pModel->GetVertexData();
  978. Assert( vertData ); // This can only return NULL on X360 for now
  979. meshBuilder.Begin( pMesh, MATERIAL_POINTS, 1 );
  980. for (k = 0; k < pModel->numvertices; k++)
  981. {
  982. for (n = 0; n < vertData->BoneWeights( k )->numbones; n++)
  983. {
  984. if (vertData->BoneWeights( k )->bone[n] == g_viewerSettings.highlightBone)
  985. {
  986. Vector tmp;
  987. Transform( *vertData->Position( k ), vertData->BoneWeights( k ), tmp );
  988. meshBuilder.Color3ub( 0, 255, 255 );
  989. meshBuilder.Position3f( tmp.x, tmp.y, tmp.z );
  990. meshBuilder.AdvanceVertex();
  991. break;
  992. }
  993. }
  994. }
  995. meshBuilder.End();
  996. pMesh->Draw();
  997. }
  998. }
  999. }
  1000. */
  1001. }
  1002. //-----------------------------------------------------------------------------
  1003. // Draws attachments
  1004. //-----------------------------------------------------------------------------
  1005. void StudioModel::DrawAttachments( )
  1006. {
  1007. if ( !g_viewerSettings.showAttachments )
  1008. return;
  1009. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1010. pRenderContext->Bind( g_materialBones );
  1011. CStudioHdr *pStudioHdr = GetStudioHdr();
  1012. for (int i = 0; i < pStudioHdr->GetNumAttachments(); i++)
  1013. {
  1014. mstudioattachment_t &pattachments = (mstudioattachment_t &)pStudioHdr->pAttachment( i );
  1015. matrix3x4_t world;
  1016. ConcatTransforms( m_pBoneToWorld[ pStudioHdr->GetAttachmentBone( i ) ], pattachments.local, world );
  1017. drawTransform( world );
  1018. }
  1019. }
  1020. //-----------------------------------------------------------------------------
  1021. // Draws Axis
  1022. //-----------------------------------------------------------------------------
  1023. void StudioModel::DrawOriginAxis( )
  1024. {
  1025. if ( !g_viewerSettings.showOriginAxis )
  1026. return;
  1027. const float fAxisLength = g_viewerSettings.originAxisLength;
  1028. if ( fAxisLength <= 0.0f )
  1029. return;
  1030. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1031. pRenderContext->Bind( g_materialBones );
  1032. pRenderContext->MatrixMode(MATERIAL_MODEL);
  1033. pRenderContext->PushMatrix();;
  1034. pRenderContext->LoadIdentity();
  1035. pRenderContext->MatrixMode(MATERIAL_VIEW);
  1036. pRenderContext->PushMatrix();;
  1037. pRenderContext->LoadIdentity();
  1038. pRenderContext->MatrixMode( MATERIAL_VIEW );
  1039. pRenderContext->LoadIdentity( );
  1040. pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
  1041. pRenderContext->Rotate( -90, 0, 0, 1 );
  1042. pRenderContext->Translate( -g_pStudioModel->m_origin[0], -g_pStudioModel->m_origin[1], -g_pStudioModel->m_origin[2] );
  1043. pRenderContext->Rotate( g_pStudioModel->m_angles[1], 0, 0, 1 );
  1044. pRenderContext->Rotate( g_pStudioModel->m_angles[0], 0, 1, 0 );
  1045. pRenderContext->Rotate( g_pStudioModel->m_angles[2], 1, 0, 0 );
  1046. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  1047. CMeshBuilder meshBuilder;
  1048. meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
  1049. meshBuilder.Position3f( 0.0f, 0.0f, 0.0f );
  1050. meshBuilder.Color4ub( 255, 0, 0, 255 );
  1051. meshBuilder.AdvanceVertex();
  1052. meshBuilder.Position3f( fAxisLength, 0.0f, 0.0f );
  1053. meshBuilder.Color4ub( 255, 0, 0, 255 );
  1054. meshBuilder.AdvanceVertex();
  1055. meshBuilder.Position3f( 0.0f, 0.0f, 0.0f );
  1056. meshBuilder.Color4ub( 0, 255, 0, 255 );
  1057. meshBuilder.AdvanceVertex();
  1058. meshBuilder.Position3f( 0.0f, fAxisLength, 0.0f );
  1059. meshBuilder.Color4ub( 0, 255, 0, 255 );
  1060. meshBuilder.AdvanceVertex();
  1061. meshBuilder.Position3f( 0.0f, 0.0f, 0.0f );
  1062. meshBuilder.Color4ub( 0, 0, 255, 255 );
  1063. meshBuilder.AdvanceVertex();
  1064. meshBuilder.Position3f( 0.0f, 0.0f, fAxisLength );
  1065. meshBuilder.Color4ub( 0, 0, 255, 255 );
  1066. meshBuilder.AdvanceVertex();
  1067. meshBuilder.End();
  1068. pMesh->Draw();
  1069. pRenderContext->MatrixMode(MATERIAL_MODEL);
  1070. pRenderContext->PopMatrix();
  1071. pRenderContext->MatrixMode(MATERIAL_VIEW);
  1072. pRenderContext->PopMatrix();
  1073. }
  1074. void StudioModel::DrawEditAttachment()
  1075. {
  1076. CStudioHdr *pStudioHdr = GetStudioHdr();
  1077. int iEditAttachment = g_viewerSettings.m_iEditAttachment;
  1078. if ( iEditAttachment >= 0 && iEditAttachment < pStudioHdr->GetNumAttachments() )
  1079. {
  1080. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1081. pRenderContext->Bind( g_materialBones );
  1082. mstudioattachment_t &pAttachment = (mstudioattachment_t &)pStudioHdr->pAttachment( iEditAttachment );
  1083. matrix3x4_t world;
  1084. ConcatTransforms( m_pBoneToWorld[ pStudioHdr->GetAttachmentBone( iEditAttachment ) ], pAttachment.local, world );
  1085. drawTransform( world );
  1086. }
  1087. }
  1088. //-----------------------------------------------------------------------------
  1089. // Draws hitboxes
  1090. //-----------------------------------------------------------------------------
  1091. static float hullcolor[8][4] =
  1092. {
  1093. { 1.0, 1.0, 1.0, 1.0 },
  1094. { 1.0, 0.5, 0.5, 1.0 },
  1095. { 0.5, 1.0, 0.5, 1.0 },
  1096. { 1.0, 1.0, 0.5, 1.0 },
  1097. { 0.5, 0.5, 1.0, 1.0 },
  1098. { 1.0, 0.5, 1.0, 1.0 },
  1099. { 0.5, 1.0, 1.0, 1.0 },
  1100. { 1.0, 1.0, 1.0, 1.0 }
  1101. };
  1102. void StudioModel::DrawHitboxes( )
  1103. {
  1104. CStudioHdr *pStudioHdr = GetStudioHdr();
  1105. if (!g_pAlpha)
  1106. {
  1107. g_pAlpha = g_pMaterialSystem->FindMaterial("debug/debughitbox", TEXTURE_GROUP_OTHER, false);
  1108. if ( g_pAlpha )
  1109. {
  1110. g_pAlpha->AddRef();
  1111. }
  1112. }
  1113. if (g_viewerSettings.showHitBoxes || (g_viewerSettings.highlightHitbox >= 0))
  1114. {
  1115. int hitboxset = g_MDLViewer->GetCurrentHitboxSet();
  1116. HitboxList_t &list = g_pStudioModel->m_HitboxSets[ hitboxset ].m_Hitboxes;
  1117. for (unsigned short j = list.Head(); j != list.InvalidIndex(); j = list.Next(j) )
  1118. {
  1119. // Only draw one hitbox if we've selected it.
  1120. if ((g_viewerSettings.highlightHitbox >= 0) &&
  1121. (g_viewerSettings.highlightHitbox != j))
  1122. continue;
  1123. mstudiobbox_t *pBBox = &list[j].m_BBox;
  1124. float interiorcolor[4];
  1125. int c = pBBox->group % 8;
  1126. interiorcolor[0] = hullcolor[c][0] * 0.7;
  1127. interiorcolor[1] = hullcolor[c][1] * 0.7;
  1128. interiorcolor[2] = hullcolor[c][2] * 0.7;
  1129. interiorcolor[3] = hullcolor[c][3] * 0.4;
  1130. drawTransparentBox( pBBox->bbmin, pBBox->bbmax, m_pBoneToWorld[ pBBox->bone ], interiorcolor, hullcolor[ c ] );
  1131. }
  1132. }
  1133. /*
  1134. float color2[] = { 0, 0.7, 1, 0.6 };
  1135. float wirecolor2[] = { 0, 1, 1, 1.0 };
  1136. drawTransparentBox( pStudioHdr->min, pStudioHdr->max, g_viewtransform, color2, wirecolor2 );
  1137. */
  1138. if (g_viewerSettings.showSequenceBoxes)
  1139. {
  1140. float color[] = { 0.7, 1, 0, 0.6 };
  1141. float wirecolor[] = { 1, 1, 0, 1.0 };
  1142. drawTransparentBox( pStudioHdr->pSeqdesc( m_sequence ).bbmin, pStudioHdr->pSeqdesc( m_sequence ).bbmax, g_viewtransform, color, wirecolor );
  1143. }
  1144. }
  1145. void StudioModel::DrawIllumPosition( )
  1146. {
  1147. if( !g_viewerSettings.showIllumPosition )
  1148. return;
  1149. CStudioHdr *pStudioHdr = GetStudioHdr();
  1150. Vector modelPt0;
  1151. Vector modelPt1;
  1152. Vector worldPt0;
  1153. Vector worldPt1;
  1154. // draw axis through illum position
  1155. VectorCopy(pStudioHdr->illumposition(), modelPt0);
  1156. VectorCopy(pStudioHdr->illumposition(), modelPt1);
  1157. modelPt0.x -= 4;
  1158. modelPt1.x += 4;
  1159. VectorTransform (modelPt0, g_viewtransform, worldPt0);
  1160. VectorTransform (modelPt1, g_viewtransform, worldPt1);
  1161. drawLine( worldPt0, worldPt1, 255, 0, 0 );
  1162. VectorCopy(pStudioHdr->illumposition(), modelPt0);
  1163. VectorCopy(pStudioHdr->illumposition(), modelPt1);
  1164. modelPt0.y -= 4;
  1165. modelPt1.y += 4;
  1166. VectorTransform (modelPt0, g_viewtransform, worldPt0);
  1167. VectorTransform (modelPt1, g_viewtransform, worldPt1);
  1168. drawLine( worldPt0, worldPt1, 0, 255, 0 );
  1169. VectorCopy(pStudioHdr->illumposition(), modelPt0);
  1170. VectorCopy(pStudioHdr->illumposition(), modelPt1);
  1171. modelPt0.z -= 4;
  1172. modelPt1.z += 4;
  1173. VectorTransform (modelPt0, g_viewtransform, worldPt0);
  1174. VectorTransform (modelPt1, g_viewtransform, worldPt1);
  1175. drawLine( worldPt0, worldPt1, 0, 0, 255 );
  1176. }
  1177. //-----------------------------------------------------------------------------
  1178. // Draws the physics model
  1179. //-----------------------------------------------------------------------------
  1180. void StudioModel::DrawPhysicsModel( )
  1181. {
  1182. if (!g_viewerSettings.showPhysicsModel)
  1183. return;
  1184. if ( g_viewerSettings.renderMode == RM_WIREFRAME && m_pPhysics->Count() == 1 )
  1185. {
  1186. // show the convex pieces in solid
  1187. DrawPhysConvex( m_pPhysics->GetMesh(0), g_materialFlatshaded );
  1188. }
  1189. else
  1190. {
  1191. for (int i = 0; i < m_pPhysics->Count(); i++)
  1192. {
  1193. float red[] = { 1.0, 0, 0, 0.25 };
  1194. float yellow[] = { 1.0, 1.0, 0, 0.5 };
  1195. CPhysmesh *pmesh = m_pPhysics->GetMesh(i);
  1196. int boneIndex = FindBone(pmesh->m_boneName);
  1197. if ( boneIndex >= 0 )
  1198. {
  1199. if ( (i+1) == g_viewerSettings.highlightPhysicsBone )
  1200. {
  1201. DrawPhysmesh( pmesh, boneIndex, g_materialBones, red );
  1202. }
  1203. else
  1204. {
  1205. if ( g_viewerSettings.highlightPhysicsBone < 1 )
  1206. {
  1207. // yellow for most
  1208. DrawPhysmesh( pmesh, boneIndex, g_materialBones, yellow );
  1209. }
  1210. }
  1211. }
  1212. else
  1213. {
  1214. DrawPhysmesh( pmesh, -1, g_materialBones, red );
  1215. }
  1216. }
  1217. }
  1218. }
  1219. void StudioModel::SetViewTarget( void )
  1220. {
  1221. // only valid if the attachment bones are used
  1222. if ((BoneMask() & BONE_USED_BY_ATTACHMENT) == 0)
  1223. {
  1224. return;
  1225. }
  1226. int iEyeAttachment = LookupAttachment( "eyes" );
  1227. if (iEyeAttachment == -1)
  1228. return;
  1229. Vector local;
  1230. Vector tmp;
  1231. // look forward
  1232. CStudioHdr *pStudioHdr = GetStudioHdr();
  1233. mstudioattachment_t &patt = (mstudioattachment_t &)pStudioHdr->pAttachment( iEyeAttachment );
  1234. matrix3x4_t attToWorld;
  1235. ConcatTransforms( m_pBoneToWorld[ pStudioHdr->GetAttachmentBone( iEyeAttachment ) ], patt.local, attToWorld );
  1236. local = Vector( 32, 0, 0 );
  1237. Vector vEyes;
  1238. MatrixPosition( attToWorld, vEyes );
  1239. // aim the eyes if there's a target
  1240. if (m_vecHeadTargets.Count() > 0 && !m_vecHeadTargets.Tail().m_bSelf)
  1241. {
  1242. VectorITransform( m_vecHeadTargets.Tail().m_vecPosition - vEyes, attToWorld, local );
  1243. }
  1244. float flDist = local.Length();
  1245. VectorNormalize( local );
  1246. // calculate animated eye deflection
  1247. Vector eyeDeflect;
  1248. QAngle eyeAng( GetFlexController("eyes_updown"), GetFlexController("eyes_rightleft"), 0 );
  1249. // debugoverlay->AddTextOverlay( m_vecOrigin + Vector( 0, 0, 64 ), 0, 0, "%.2f %.2f", eyeAng.x, eyeAng.y );
  1250. AngleVectors( eyeAng, &eyeDeflect );
  1251. eyeDeflect.x = 0;
  1252. // reduce deflection the more the eye is off center
  1253. // FIXME: this angles make no damn sense
  1254. eyeDeflect = eyeDeflect * (local.x * local.x);
  1255. local = local + eyeDeflect;
  1256. VectorNormalize( local );
  1257. // check to see if the eye is aiming outside the max eye deflection
  1258. float flMaxEyeDeflection = pStudioHdr->MaxEyeDeflection();
  1259. if ( local.x < flMaxEyeDeflection )
  1260. {
  1261. // if so, clamp it to 30 degrees offset
  1262. // debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), 1, 0, "%5.3f %5.3f %5.3f", local.x, local.y, local.z );
  1263. local.x = 0;
  1264. float d = local.LengthSqr();
  1265. if ( d > 0.0f )
  1266. {
  1267. d = sqrtf( ( 1.0f - flMaxEyeDeflection * flMaxEyeDeflection ) / ( local.y*local.y + local.z*local.z ) );
  1268. local.x = flMaxEyeDeflection;
  1269. local.y = local.y * d;
  1270. local.z = local.z * d;
  1271. }
  1272. else
  1273. {
  1274. local.x = 1.0;
  1275. }
  1276. }
  1277. local = local * flDist;
  1278. VectorTransform( local, attToWorld, tmp );
  1279. g_pStudioRender->SetEyeViewTarget( pStudioHdr->GetRenderHdr(), m_bodynum, tmp );
  1280. }
  1281. float UTIL_VecToYaw( const matrix3x4_t& matrix, const Vector &vec )
  1282. {
  1283. Vector tmp = vec;
  1284. VectorNormalize( tmp );
  1285. float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
  1286. float y = matrix[0][1] * tmp.x + matrix[1][1] * tmp.y + matrix[2][1] * tmp.z;
  1287. if (x == 0.0f && y == 0.0f)
  1288. return 0.0f;
  1289. float yaw = atan2( -y, x );
  1290. yaw = RAD2DEG(yaw);
  1291. if (yaw < 0)
  1292. yaw += 360;
  1293. return yaw;
  1294. }
  1295. float UTIL_VecToPitch( const matrix3x4_t& matrix, const Vector &vec )
  1296. {
  1297. Vector tmp = vec;
  1298. VectorNormalize( tmp );
  1299. float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
  1300. float z = matrix[0][2] * tmp.x + matrix[1][2] * tmp.y + matrix[2][2] * tmp.z;
  1301. if (x == 0.0f && z == 0.0f)
  1302. return 0.0f;
  1303. float pitch = atan2( z, x );
  1304. pitch = RAD2DEG(pitch);
  1305. if (pitch < 0)
  1306. pitch += 360;
  1307. return pitch;
  1308. }
  1309. float UTIL_AngleDiff( float destAngle, float srcAngle )
  1310. {
  1311. float delta;
  1312. delta = destAngle - srcAngle;
  1313. if ( destAngle > srcAngle )
  1314. {
  1315. while ( delta >= 180 )
  1316. delta -= 360;
  1317. }
  1318. else
  1319. {
  1320. while ( delta <= -180 )
  1321. delta += 360;
  1322. }
  1323. return delta;
  1324. }
  1325. void StudioModel::UpdateBoneChain(
  1326. Vector pos[],
  1327. Quaternion q[],
  1328. int iBone,
  1329. matrix3x4_t *pBoneToWorld )
  1330. {
  1331. matrix3x4_t bonematrix;
  1332. QuaternionMatrix( q[iBone], pos[iBone], bonematrix );
  1333. CStudioHdr *pStudioHdr = GetStudioHdr();
  1334. int parent = pStudioHdr->pBone( iBone )->parent;
  1335. if (parent == -1)
  1336. {
  1337. ConcatTransforms( g_viewtransform, bonematrix, pBoneToWorld[iBone] );
  1338. }
  1339. else
  1340. {
  1341. // evil recursive!!!
  1342. UpdateBoneChain( pos, q, parent, pBoneToWorld );
  1343. ConcatTransforms( pBoneToWorld[parent], bonematrix, pBoneToWorld[iBone] );
  1344. }
  1345. }
  1346. void StudioModel::GetBodyPoseParametersFromFlex( )
  1347. {
  1348. float flGoal;
  1349. flGoal = GetFlexController( "move_rightleft" );
  1350. SetPoseParameter( "body_trans_Y", flGoal );
  1351. flGoal = GetFlexController( "move_forwardback" );
  1352. SetPoseParameter( "body_trans_X", flGoal );
  1353. flGoal = GetFlexController( "move_updown" );
  1354. SetPoseParameter( "body_lift", flGoal );
  1355. flGoal = GetFlexController( "body_rightleft" ) + GetBodyYaw();
  1356. SetPoseParameter( "body_yaw", flGoal );
  1357. flGoal = GetFlexController( "body_updown" );
  1358. SetPoseParameter( "body_pitch", flGoal );
  1359. flGoal = GetFlexController( "body_tilt" );
  1360. SetPoseParameter( "body_roll", flGoal );
  1361. flGoal = GetFlexController( "chest_rightleft" ) + GetSpineYaw();
  1362. SetPoseParameter( "spine_yaw", flGoal );
  1363. flGoal = GetFlexController( "chest_updown" );
  1364. SetPoseParameter( "spine_pitch", flGoal );
  1365. flGoal = GetFlexController( "chest_tilt" );
  1366. SetPoseParameter( "spine_roll", flGoal );
  1367. flGoal = GetFlexController( "head_forwardback" );
  1368. SetPoseParameter( "neck_trans", flGoal );
  1369. flGoal = GetFlexController( "gesture_updown" );
  1370. SetPoseParameter( "gesture_height", flGoal );
  1371. flGoal = GetFlexController( "gesture_rightleft" );
  1372. SetPoseParameter( "gesture_width", flGoal );
  1373. }
  1374. void StudioModel::CalcHeadRotation( Vector pos[], Quaternion q[] )
  1375. {
  1376. static Vector pos2[MAXSTUDIOBONES];
  1377. static Quaternion q2[MAXSTUDIOBONES];
  1378. if (m_nSolveHeadTurn == 0)
  1379. return;
  1380. if (m_dt == 0.0f)
  1381. {
  1382. m_dt = 0.1;
  1383. }
  1384. // GetAttachment( "eyes", vEyePosition, vEyeAngles );
  1385. int iForwardAttachment = LookupAttachment( "forward" );
  1386. if (iForwardAttachment == -1)
  1387. return;
  1388. CStudioHdr *pStudioHdr = GetStudioHdr();
  1389. mstudioattachment_t &patt = (mstudioattachment_t &)pStudioHdr->pAttachment( iForwardAttachment );
  1390. matrix3x4_t attToWorld;
  1391. int iBone = pStudioHdr->GetAttachmentBone( iForwardAttachment );
  1392. BuildBoneChain( pStudioHdr, g_viewtransform, pos, q, iBone, m_pBoneToWorld );
  1393. ConcatTransforms( m_pBoneToWorld[ iBone ], patt.local, attToWorld );
  1394. Vector vForward;
  1395. VectorRotate( Vector( 1, 0, 0 ), attToWorld, vForward );
  1396. float dt = m_dt;
  1397. if (m_nSolveHeadTurn == 2)
  1398. {
  1399. dt = 0.1;
  1400. }
  1401. Vector vEyes;
  1402. MatrixPosition( attToWorld, vEyes );
  1403. Vector vHead = vForward;
  1404. float flHeadInfluence = 0.0;
  1405. int i;
  1406. for (i = 0; i < m_vecHeadTargets.Count(); i++)
  1407. {
  1408. Vector dir;
  1409. if (m_vecHeadTargets[i].m_bSelf)
  1410. {
  1411. dir = vForward;
  1412. }
  1413. else
  1414. {
  1415. dir = m_vecHeadTargets[i].m_vecPosition - vEyes;
  1416. }
  1417. VectorNormalize( dir );
  1418. float flInterest = m_vecHeadTargets[i].m_flWeight;
  1419. if (flInterest > 0.0)
  1420. {
  1421. if (flHeadInfluence == 0.0)
  1422. {
  1423. vHead = dir;
  1424. flHeadInfluence = flInterest;
  1425. }
  1426. else
  1427. {
  1428. flHeadInfluence = flHeadInfluence * (1 - flInterest) + flInterest;
  1429. float w = flInterest / flHeadInfluence;
  1430. vHead = vHead * (1 - w) + dir * w;
  1431. }
  1432. }
  1433. }
  1434. Vector vTargetDir = Vector( 0, 0, 0 );
  1435. vTargetDir = vForward * (1.0 - flHeadInfluence) + vHead * flHeadInfluence;
  1436. VectorNormalize( vTargetDir );
  1437. SetPoseParameter( "head_pitch", 0.0 );
  1438. SetPoseParameter( "head_yaw", 0.0 );
  1439. SetPoseParameter( "head_roll", 0.0 );
  1440. SetHeadPosition( attToWorld, vTargetDir, dt );
  1441. // Msg( "yaw %f pitch %f\n", vEyeAngles.y, vEyeAngles.x );
  1442. }
  1443. float StudioModel::SetHeadPosition( matrix3x4_t& attToWorld, Vector const &vTargetPos, float dt )
  1444. {
  1445. float flDiff;
  1446. int iPose;
  1447. QAngle vEyeAngles;
  1448. float flMoved = 0.0f;
  1449. matrix3x4_t targetXform, invAttToWorld;
  1450. matrix3x4_t headXform;
  1451. // align current "forward direction" to target direction
  1452. targetXform = attToWorld;
  1453. Studio_AlignIKMatrix( targetXform, vTargetPos );
  1454. // calc head movement needed
  1455. MatrixInvert( attToWorld, invAttToWorld );
  1456. ConcatTransforms( invAttToWorld, targetXform, headXform );
  1457. MatrixAngles( headXform, vEyeAngles );
  1458. // FIXME: add chest compression
  1459. // Msg( "yaw %f pitch %f\n", vEyeAngles.y, vEyeAngles.x );
  1460. float flMin, flMax;
  1461. #if 1
  1462. //--------------------------------------
  1463. // Set head yaw
  1464. //--------------------------------------
  1465. // flDiff = vEyeAngles.y + GetFlexController( "head_rightleft" );
  1466. iPose = LookupPoseParameter( "head_yaw" );
  1467. GetPoseParameterRange( iPose, &flMin, &flMax );
  1468. flDiff = RangeCompressor( vEyeAngles.y + GetFlexController( "head_rightleft" ), flMin, flMax, 0.0 );
  1469. SetPoseParameter( iPose, flDiff );
  1470. #endif
  1471. #if 1
  1472. //--------------------------------------
  1473. // Set head pitch
  1474. //--------------------------------------
  1475. iPose = LookupPoseParameter( "head_pitch" );
  1476. GetPoseParameterRange( iPose, &flMin, &flMax );
  1477. flDiff = RangeCompressor( vEyeAngles.x + GetFlexController( "head_updown" ), flMin, flMax, 0.0 );
  1478. SetPoseParameter( iPose, flDiff );
  1479. #endif
  1480. #if 1
  1481. //--------------------------------------
  1482. // Set head roll
  1483. //--------------------------------------
  1484. iPose = LookupPoseParameter( "head_roll" );
  1485. GetPoseParameterRange( iPose, &flMin, &flMax );
  1486. flDiff = RangeCompressor( vEyeAngles.z + GetFlexController( "head_tilt" ), flMin, flMax, 0.0 );
  1487. SetPoseParameter( iPose, flDiff );
  1488. #endif
  1489. return flMoved;
  1490. }
  1491. DrawModelInfo_t g_DrawModelInfo;
  1492. DrawModelResults_t g_DrawModelResults;
  1493. bool g_bDrawModelInfoValid = false;
  1494. void StudioModel::GetModelTransform( matrix3x4_t &mat )
  1495. {
  1496. AngleMatrix( m_angles, mat );
  1497. Vector vecModelOrigin;
  1498. VectorMultiply( m_origin, -1.0f, vecModelOrigin );
  1499. MatrixSetColumn( vecModelOrigin, 3, mat );
  1500. }
  1501. void StudioModel::SetModelTransform( const matrix3x4_t &mat )
  1502. {
  1503. m_origin.x = -mat.m_flMatVal[0][3];
  1504. m_origin.y = -mat.m_flMatVal[1][3];
  1505. m_origin.z = -mat.m_flMatVal[2][3];
  1506. MatrixAngles( mat, m_angles );
  1507. }
  1508. /*
  1509. ================
  1510. StudioModel::DrawModel
  1511. inputs:
  1512. currententity
  1513. r_entorigin
  1514. ================
  1515. */
  1516. int StudioModel::DrawModel( bool mergeBones )
  1517. {
  1518. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  1519. CStudioHdr *pStudioHdr = GetStudioHdr();
  1520. if (!pStudioHdr)
  1521. return 0;
  1522. g_smodels_total++; // render data cache cookie
  1523. // JasonM & garymcthack - should really only do this once a frame and at init time.
  1524. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  1525. g_viewerSettings.showNormals,
  1526. g_viewerSettings.showTangentFrame );
  1527. // NOTE: UpdateStudioRenderConfig can delete the studio hdr
  1528. pStudioHdr = GetStudioHdr();
  1529. if ( !pStudioHdr || pStudioHdr->numbodyparts() == 0)
  1530. return 0;
  1531. // Construct a transform to apply to the model. The camera is stuck in a fixed position
  1532. static Vector vecModelOrigin;
  1533. if ( !mergeBones )
  1534. {
  1535. AngleMatrix( m_angles, g_viewtransform );
  1536. VectorMultiply( m_origin, -1.0f, vecModelOrigin );
  1537. MatrixSetColumn( vecModelOrigin, 3, g_viewtransform );
  1538. }
  1539. // These values HAVE to be sent down for LOD to work correctly.
  1540. Vector viewOrigin, viewRight, viewUp, viewPlaneNormal;
  1541. g_pStudioRender->SetViewState( vec3_origin, Vector(0, 1, 0), Vector(0, 0, 1), Vector( 1, 0, 0 ) );
  1542. // g_pStudioRender->SetEyeViewTarget( viewOrigin );
  1543. SetUpBones( mergeBones );
  1544. SetupLighting( );
  1545. SetViewTarget( );
  1546. extern float g_flexdescweight[MAXSTUDIOFLEXDESC]; // garymcthack
  1547. extern float g_flexdescweight2[MAXSTUDIOFLEXDESC]; // garymcthack
  1548. int i;
  1549. for (i = 0; i < pStudioHdr->numflexdesc(); i++)
  1550. {
  1551. g_flexdescweight[i] = 0.0;
  1552. }
  1553. RunFlexRules( );
  1554. float d = 0.8;
  1555. if (m_dt != 0)
  1556. {
  1557. d = ExponentialDecay( 0.8, 0.033, m_dt );
  1558. }
  1559. float *pFlexWeights, *pFlexDelayedWeights;
  1560. g_pStudioRender->LockFlexWeights( pStudioHdr->numflexdesc(), &pFlexWeights, &pFlexDelayedWeights );
  1561. for (i = 0; i < pStudioHdr->numflexdesc(); i++)
  1562. {
  1563. g_flexdescweight2[i] = g_flexdescweight2[i] * d + g_flexdescweight[i] * (1 - d);
  1564. pFlexWeights[i] = g_flexdescweight[i];
  1565. pFlexDelayedWeights[i] = g_flexdescweight2[i];
  1566. }
  1567. g_pStudioRender->UnlockFlexWeights( );
  1568. // draw
  1569. g_pStudioRender->SetAlphaModulation( 1.0f );
  1570. g_bDrawModelInfoValid = true;
  1571. memset( &g_DrawModelInfo, 0, sizeof( g_DrawModelInfo ) );
  1572. g_DrawModelInfo.m_pStudioHdr = (studiohdr_t *)pStudioHdr->GetRenderHdr();
  1573. g_DrawModelInfo.m_pHardwareData = GetHardwareData();
  1574. if ( !g_DrawModelInfo.m_pHardwareData )
  1575. return 0;
  1576. g_DrawModelInfo.m_Decals = STUDIORENDER_DECAL_INVALID;
  1577. g_DrawModelInfo.m_Skin = m_skinnum;
  1578. g_DrawModelInfo.m_Body = m_bodynum;
  1579. g_DrawModelInfo.m_HitboxSet = g_MDLViewer->GetCurrentHitboxSet();
  1580. g_DrawModelInfo.m_pClientEntity = NULL;
  1581. g_DrawModelInfo.m_Lod = g_viewerSettings.autoLOD ? -1 : g_viewerSettings.lod;
  1582. g_DrawModelInfo.m_pColorMeshes = NULL;
  1583. if( g_viewerSettings.renderMode == RM_SHOWBADVERTEXDATA )
  1584. {
  1585. DebugDrawModelBadVerts( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin );
  1586. DebugDrawModelWireframe( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin, Vector( 0.2f, 0.2f, 0.2f ) );
  1587. g_DrawModelInfo.m_Lod = m_LodUsed;
  1588. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  1589. #if 0
  1590. // overlay wireframe
  1591. // Set the state to trigger wireframe rendering
  1592. UpdateStudioRenderConfig( true, true, false, false );
  1593. // Draw wireframe
  1594. count = g_pStudioRender->DrawModel( &g_DrawModelResults, g_DrawModelInfo, m_pBoneToWorld,
  1595. pFlexWeights, pFlexDelayedWeights, vecModelOrigin, STUDIORENDER_DRAW_ENTIRE_MODEL );
  1596. m_LodUsed = g_DrawModelResults.m_nLODUsed;
  1597. m_LodMetric = g_DrawModelResults.m_flLodMetric;
  1598. g_DrawModelInfo.m_Lod = m_LodUsed;
  1599. // Restore the studio render config
  1600. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  1601. g_viewerSettings.showNormals,
  1602. g_viewerSettings.showTangentFrame );
  1603. #endif
  1604. }
  1605. else if( g_viewerSettings.renderMode == RM_BONEWEIGHTS )
  1606. {
  1607. g_DrawModelInfo.m_Lod = 0;
  1608. DebugDrawModelBoneWeights( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin );
  1609. g_DrawModelInfo.m_Lod = m_LodUsed;
  1610. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  1611. }
  1612. else if( g_viewerSettings.renderMode == RM_TEXCOORDS )
  1613. {
  1614. const char *pMatName = "";
  1615. if ( g_DrawModelInfo.m_pHardwareData->m_pLODs && g_viewerSettings.materialIndex < g_DrawModelInfo.m_pHardwareData->m_pLODs[0].numMaterials )
  1616. {
  1617. pMatName = g_DrawModelInfo.m_pHardwareData->m_pLODs[0].ppMaterials[g_viewerSettings.materialIndex]->GetName();
  1618. }
  1619. DebugDrawModelTexCoord( g_pStudioRender, pMatName, g_DrawModelInfo, m_pBoneToWorld, g_viewerSettings.width, g_viewerSettings.height );
  1620. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  1621. m_LodUsed = g_DrawModelInfo.m_Lod;
  1622. }
  1623. else
  1624. {
  1625. // Draw the model normally (may include normal and/or tangent line segments)
  1626. g_pStudioRender->DrawModel( &g_DrawModelResults, g_DrawModelInfo, m_pBoneToWorld,
  1627. pFlexWeights, pFlexDelayedWeights, vecModelOrigin );
  1628. m_LodUsed = g_DrawModelResults.m_nLODUsed;
  1629. m_LodMetric = g_DrawModelResults.m_flLODMetric;
  1630. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  1631. // Optionally overlay wireframe...
  1632. if ( g_viewerSettings.overlayWireframe && !(g_viewerSettings.renderMode == RM_WIREFRAME) )
  1633. {
  1634. // Set the state to trigger wireframe rendering
  1635. UpdateStudioRenderConfig( true, true, false, false );
  1636. // Draw the wireframe over top of the model
  1637. g_pStudioRender->DrawModel( NULL, g_DrawModelInfo, m_pBoneToWorld,
  1638. pFlexWeights, pFlexDelayedWeights, vecModelOrigin );
  1639. // Restore the studio render config
  1640. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  1641. g_viewerSettings.showNormals,
  1642. g_viewerSettings.showTangentFrame );
  1643. }
  1644. }
  1645. int nCount = g_DrawModelResults.m_ActualTriCount;
  1646. DrawBones();
  1647. DrawAttachments();
  1648. DrawOriginAxis();
  1649. DrawEditAttachment();
  1650. DrawHitboxes();
  1651. DrawPhysicsModel();
  1652. DrawIllumPosition();
  1653. // Only draw the shadow if the ground is also drawn
  1654. if ( g_viewerSettings.showShadow && g_viewerSettings.showGround )
  1655. {
  1656. matrix3x4_t invViewTransform;
  1657. MatrixInvert( g_viewtransform, invViewTransform );
  1658. for (int i = 0; i < pStudioHdr->numbones(); i++)
  1659. {
  1660. matrix3x4_t *pMatrix = &m_pBoneToWorld[ i ];
  1661. matrix3x4_t tmp1;
  1662. ConcatTransforms( invViewTransform, *pMatrix, tmp1 );
  1663. tmp1[2][0] = 0.0;
  1664. tmp1[2][1] = 0.0;
  1665. tmp1[2][2] = 0.0;
  1666. tmp1[2][3] = 0.05;
  1667. ConcatTransforms( g_viewtransform, tmp1, *pMatrix );
  1668. }
  1669. g_DrawModelInfo.m_Lod = GetHardwareData()->m_NumLODs - 1;
  1670. float zero[4] = { 0, 0, 0, 0 };
  1671. g_pStudioRender->SetColorModulation( zero );
  1672. g_pStudioRender->ForcedMaterialOverride( g_materialShadow );
  1673. // Turn off any wireframe, normals or tangent frame display for the drop shadow
  1674. UpdateStudioRenderConfig( false, false, false, false );
  1675. g_pStudioRender->DrawModel( NULL, g_DrawModelInfo, m_pBoneToWorld,
  1676. pFlexWeights, pFlexDelayedWeights, vecModelOrigin );
  1677. // Restore the studio render config
  1678. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  1679. g_viewerSettings.showNormals,
  1680. g_viewerSettings.showTangentFrame );
  1681. g_pStudioRender->ForcedMaterialOverride( NULL );
  1682. float one[4] = { 1, 1, 1, 1 };
  1683. g_pStudioRender->SetColorModulation( one );
  1684. }
  1685. return nCount;
  1686. }
  1687. void StudioModel::DrawPhysmesh( CPhysmesh *pMesh, int boneIndex, IMaterial* pMaterial, float* color )
  1688. {
  1689. matrix3x4_t *pMatrix;
  1690. if ( boneIndex >= 0 )
  1691. {
  1692. pMatrix = &m_pBoneToWorld[ boneIndex ];
  1693. }
  1694. else
  1695. {
  1696. pMatrix = &g_viewtransform;
  1697. }
  1698. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1699. pRenderContext->Bind( pMaterial );
  1700. IMesh* pMatMesh = pRenderContext->GetDynamicMesh( );
  1701. CMeshBuilder meshBuilder;
  1702. meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, pMesh->m_vertCount/3 );
  1703. int vertIndex = 0;
  1704. for ( int i = 0; i < pMesh->m_vertCount; i+=3 )
  1705. {
  1706. Vector v;
  1707. VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
  1708. meshBuilder.Position3fv( v.Base() );
  1709. meshBuilder.Color4fv( color );
  1710. meshBuilder.AdvanceVertex();
  1711. vertIndex ++;
  1712. VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
  1713. meshBuilder.Position3fv( v.Base() );
  1714. meshBuilder.Color4fv( color );
  1715. meshBuilder.AdvanceVertex();
  1716. vertIndex ++;
  1717. VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
  1718. meshBuilder.Position3fv( v.Base() );
  1719. meshBuilder.Color4fv( color );
  1720. meshBuilder.AdvanceVertex();
  1721. vertIndex ++;
  1722. }
  1723. meshBuilder.End();
  1724. pMatMesh->Draw();
  1725. }
  1726. void RandomColor( float *color, int key )
  1727. {
  1728. static bool first = true;
  1729. static colorVec colors[256];
  1730. if ( first )
  1731. {
  1732. int r, g, b;
  1733. first = false;
  1734. for ( int i = 0; i < 256; i++ )
  1735. {
  1736. do
  1737. {
  1738. r = rand()&255;
  1739. g = rand()&255;
  1740. b = rand()&255;
  1741. } while ( (r+g+b)<256 );
  1742. colors[i].r = r;
  1743. colors[i].g = g;
  1744. colors[i].b = b;
  1745. colors[i].a = 255;
  1746. }
  1747. }
  1748. int index = key & 255;
  1749. color[0] = colors[index].r * (1.f / 255.f);
  1750. color[1] = colors[index].g * (1.f / 255.f);
  1751. color[2] = colors[index].b * (1.f / 255.f);
  1752. color[3] = colors[index].a * (1.f / 255.f);
  1753. }
  1754. void StudioModel::DrawPhysConvex( CPhysmesh *pMesh, IMaterial* pMaterial )
  1755. {
  1756. matrix3x4_t &matrix = g_viewtransform;
  1757. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1758. pRenderContext->Bind( pMaterial );
  1759. for ( int i = 0; i < pMesh->m_pCollisionModel->ConvexCount(); i++ )
  1760. {
  1761. float color[4];
  1762. RandomColor( color, i );
  1763. IMesh* pMatMesh = pRenderContext->GetDynamicMesh( );
  1764. CMeshBuilder meshBuilder;
  1765. int triCount = pMesh->m_pCollisionModel->TriangleCount( i );
  1766. meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, triCount );
  1767. for ( int j = 0; j < triCount; j++ )
  1768. {
  1769. Vector objectSpaceVerts[3];
  1770. pMesh->m_pCollisionModel->GetTriangleVerts( i, j, objectSpaceVerts );
  1771. for ( int k = 0; k < 3; k++ )
  1772. {
  1773. Vector v;
  1774. VectorTransform (objectSpaceVerts[k], matrix, v);
  1775. meshBuilder.Position3fv( v.Base() );
  1776. meshBuilder.Color4fv( color );
  1777. meshBuilder.AdvanceVertex();
  1778. }
  1779. }
  1780. meshBuilder.End();
  1781. pMatMesh->Draw();
  1782. }
  1783. }
  1784. /*
  1785. ================
  1786. ================
  1787. */
  1788. int StudioModel::GetLodUsed( void )
  1789. {
  1790. return m_LodUsed;
  1791. }
  1792. float StudioModel::GetLodMetric( void )
  1793. {
  1794. return m_LodMetric;
  1795. }
  1796. const char *StudioModel::GetKeyValueText( int iSequence )
  1797. {
  1798. CStudioHdr *pStudioHdr = GetStudioHdr();
  1799. return Studio_GetKeyValueText( pStudioHdr, iSequence );
  1800. }
  1801. //-----------------------------------------------------------------------------
  1802. // Purpose:
  1803. // Input : solve -
  1804. //-----------------------------------------------------------------------------
  1805. void StudioModel::SetSolveHeadTurn( int solve )
  1806. {
  1807. m_nSolveHeadTurn = solve;
  1808. }
  1809. //-----------------------------------------------------------------------------
  1810. // Purpose:
  1811. // Output : int
  1812. //-----------------------------------------------------------------------------
  1813. int StudioModel::GetSolveHeadTurn() const
  1814. {
  1815. return m_nSolveHeadTurn;
  1816. }
  1817. //-----------------------------------------------------------------------------
  1818. // Purpose:
  1819. // Input : target -
  1820. //-----------------------------------------------------------------------------
  1821. void StudioModel::ClearLookTargets( void )
  1822. {
  1823. m_vecHeadTargets.RemoveAll();
  1824. }
  1825. //-----------------------------------------------------------------------------
  1826. // Purpose:
  1827. // Input : target -
  1828. //-----------------------------------------------------------------------------
  1829. void StudioModel::AddLookTarget( const Vector& vecPosition, float flWeight )
  1830. {
  1831. if (m_vecHeadTargets.Count() > 8)
  1832. return;
  1833. StudioLookTarget tmp;
  1834. tmp.m_flWeight = flWeight;
  1835. tmp.m_vecPosition = vecPosition;
  1836. tmp.m_bSelf = false;
  1837. m_vecHeadTargets.AddToTail( tmp );
  1838. }
  1839. void StudioModel::AddLookTargetSelf( float flWeight )
  1840. {
  1841. if (m_vecHeadTargets.Count() > 8)
  1842. return;
  1843. StudioLookTarget tmp;
  1844. tmp.m_flWeight = flWeight;
  1845. tmp.m_vecPosition = Vector(0,0,0);
  1846. tmp.m_bSelf = true;
  1847. m_vecHeadTargets.AddToTail( tmp );
  1848. }
  1849. //-----------------------------------------------------------------------------
  1850. // Purpose:
  1851. // Output :
  1852. //-----------------------------------------------------------------------------
  1853. void StudioModel::SetModelYaw( float flYaw )
  1854. {
  1855. m_flModelYaw = flYaw;
  1856. }
  1857. float StudioModel::GetModelYaw( void ) const
  1858. {
  1859. return m_flModelYaw;
  1860. }
  1861. void StudioModel::SetBodyYaw( float flYaw )
  1862. {
  1863. m_flBodyYaw = flYaw;
  1864. }
  1865. float StudioModel::GetBodyYaw( void ) const
  1866. {
  1867. return m_flBodyYaw;
  1868. }
  1869. void StudioModel::SetSpineYaw( float flYaw )
  1870. {
  1871. m_flSpineYaw = flYaw;
  1872. }
  1873. float StudioModel::GetSpineYaw( void ) const
  1874. {
  1875. return m_flSpineYaw;
  1876. }