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.

3223 lines
95 KiB

  1. //========= Copyright � 1996-2005, 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. matrix3x4a_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. #define PHYSICS_HULL_ARC_SEGS 32
  54. //-----------------------------------------------------------------------------
  55. // Purpose:
  56. //-----------------------------------------------------------------------------
  57. mstudioseqdesc_t &StudioModel::GetSeqDesc( int seq )
  58. {
  59. CStudioHdr *pStudioHdr = GetStudioHdr();
  60. return pStudioHdr->pSeqdesc( seq );
  61. }
  62. mstudioanimdesc_t &StudioModel::GetAnimDesc( int anim )
  63. {
  64. CStudioHdr *pStudioHdr = GetStudioHdr();
  65. return pStudioHdr->pAnimdesc( anim );
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose: Keeps a global clock to autoplay sequences to run from
  69. // Also deals with speedScale changes
  70. //-----------------------------------------------------------------------------
  71. float GetAutoPlayTime( void )
  72. {
  73. static int g_prevTicks;
  74. static float g_time;
  75. int ticks = GetTickCount();
  76. // limit delta so that float time doesn't overflow
  77. if (g_prevTicks == 0)
  78. g_prevTicks = ticks;
  79. g_time += ( (ticks - g_prevTicks) / 1000.0f ) * g_viewerSettings.speedScale;
  80. g_prevTicks = ticks;
  81. return g_time;
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose: Keeps a global clock for "realtime" overlays to run from
  85. //-----------------------------------------------------------------------------
  86. float GetRealtimeTime( void )
  87. {
  88. // renamed static's so debugger doesn't get confused and show the wrong one
  89. static int g_prevTicksRT;
  90. static float g_timeRT;
  91. int ticks = GetTickCount();
  92. // limit delta so that float time doesn't overflow
  93. if (g_prevTicksRT == 0)
  94. g_prevTicksRT = ticks;
  95. g_timeRT += ( (ticks - g_prevTicksRT) / 1000.0f );
  96. g_prevTicksRT = ticks;
  97. return g_timeRT;
  98. }
  99. void StudioModel::AdvanceFrame( float dt )
  100. {
  101. if (dt > 0.1)
  102. dt = 0.1f;
  103. m_dt = dt;
  104. float t = GetDuration( );
  105. if (t > 0)
  106. {
  107. if (dt > 0)
  108. {
  109. m_cycle += dt / t;
  110. m_sequencetime += dt;
  111. // wrap
  112. m_cycle -= (int)(m_cycle);
  113. }
  114. }
  115. else
  116. {
  117. m_cycle = 0;
  118. }
  119. for (int i = 0; i < MAXSTUDIOANIMLAYERS; i++)
  120. {
  121. t = GetDuration( m_Layer[i].m_sequence );
  122. if (t > 0)
  123. {
  124. if (dt > 0)
  125. {
  126. m_Layer[i].m_cycle += (dt / t) * m_Layer[i].m_playbackrate;
  127. m_Layer[i].m_cycle -= (int)(m_Layer[i].m_cycle);
  128. }
  129. }
  130. else
  131. {
  132. m_Layer[i].m_cycle = 0;
  133. }
  134. }
  135. }
  136. float StudioModel::GetInterval( void )
  137. {
  138. return m_dt;
  139. }
  140. float StudioModel::GetCycle( void )
  141. {
  142. return m_cycle;
  143. }
  144. float StudioModel::GetFrame( void )
  145. {
  146. return GetCycle() * GetMaxFrame();
  147. }
  148. int StudioModel::GetMaxFrame( void )
  149. {
  150. CStudioHdr *pStudioHdr = GetStudioHdr();
  151. return Studio_MaxFrame( pStudioHdr, m_sequence, m_poseparameter );
  152. }
  153. int StudioModel::SetFrame( int frame )
  154. {
  155. CStudioHdr *pStudioHdr = GetStudioHdr();
  156. if ( !pStudioHdr )
  157. return 0;
  158. if ( frame <= 0 )
  159. frame = 0;
  160. int maxFrame = GetMaxFrame();
  161. if ( frame >= maxFrame )
  162. {
  163. frame = maxFrame;
  164. m_cycle = 0.99999;
  165. return frame;
  166. }
  167. m_cycle = frame / (float)maxFrame;
  168. return frame;
  169. }
  170. float StudioModel::GetCycle( int iLayer )
  171. {
  172. if (iLayer == 0)
  173. {
  174. return m_cycle;
  175. }
  176. else if (iLayer <= MAXSTUDIOANIMLAYERS)
  177. {
  178. int index = iLayer - 1;
  179. return m_Layer[index].m_cycle;
  180. }
  181. return 0;
  182. }
  183. float StudioModel::GetFrame( int iLayer )
  184. {
  185. return GetCycle( iLayer ) * GetMaxFrame( iLayer );
  186. }
  187. int StudioModel::GetMaxFrame( int iLayer )
  188. {
  189. CStudioHdr *pStudioHdr = GetStudioHdr();
  190. if ( pStudioHdr )
  191. {
  192. if (iLayer == 0)
  193. return Studio_MaxFrame( pStudioHdr, m_sequence, m_poseparameter );
  194. if (iLayer <= MAXSTUDIOANIMLAYERS)
  195. {
  196. int index = iLayer - 1;
  197. return Studio_MaxFrame( pStudioHdr, m_Layer[index].m_sequence, m_poseparameter );
  198. }
  199. }
  200. return 0;
  201. }
  202. int StudioModel::SetFrame( int iLayer, int frame )
  203. {
  204. CStudioHdr *pStudioHdr = GetStudioHdr();
  205. if ( !pStudioHdr )
  206. return 0;
  207. if ( frame <= 0 )
  208. frame = 0;
  209. int maxFrame = GetMaxFrame( iLayer );
  210. float cycle = 0;
  211. if (maxFrame)
  212. {
  213. if ( frame >= maxFrame )
  214. {
  215. frame = maxFrame;
  216. cycle = 0.99999;
  217. }
  218. cycle = frame / (float)maxFrame;
  219. }
  220. if (iLayer == 0)
  221. {
  222. m_cycle = cycle;
  223. }
  224. else if (iLayer <= MAXSTUDIOANIMLAYERS)
  225. {
  226. int index = iLayer - 1;
  227. m_Layer[index].m_cycle = cycle;
  228. }
  229. return frame;
  230. }
  231. //-----------------------------------------------------------------------------
  232. // Purpose: Maps from local axis (X,Y,Z) to Half-Life (PITCH,YAW,ROLL) axis/rotation mappings
  233. //-----------------------------------------------------------------------------
  234. static int RemapAxis( int axis )
  235. {
  236. switch( axis )
  237. {
  238. case 0:
  239. return 2;
  240. case 1:
  241. return 0;
  242. case 2:
  243. return 1;
  244. }
  245. return 0;
  246. }
  247. void StudioModel::Physics_SetPreview( int previewBone, int axis, float t )
  248. {
  249. m_physPreviewBone = previewBone;
  250. m_physPreviewAxis = axis;
  251. m_physPreviewParam = t;
  252. }
  253. void StudioModel::OverrideBones( bool *override )
  254. {
  255. matrix3x4_t basematrix;
  256. matrix3x4_t bonematrix;
  257. QAngle tmp;
  258. // offset for the base pose to world transform of 90 degrees around up axis
  259. tmp[0] = 0; tmp[1] = 90; tmp[2] = 90;
  260. AngleMatrix( tmp, bonematrix );
  261. ConcatTransforms( g_viewtransform, bonematrix, basematrix );
  262. for ( int i = 0; i < m_pPhysics->Count(); i++ )
  263. {
  264. CPhysmesh *pmesh = m_pPhysics->GetMesh( i );
  265. // BUGBUG: Cache this if you care about performance!
  266. int boneIndex = FindBone(pmesh->m_boneName);
  267. // bone is not constrained, don't override rotations
  268. if ( pmesh->m_constraint.parentIndex == 0 && pmesh->m_constraint.childIndex == 0 )
  269. {
  270. boneIndex = -1;
  271. }
  272. if ( boneIndex >= 0 )
  273. {
  274. matrix3x4_t *parentMatrix = &basematrix;
  275. override[boneIndex] = true;
  276. int parentBone = -1;
  277. if ( pmesh->m_constraint.parentIndex >= 0 )
  278. {
  279. parentBone = FindBone( m_pPhysics->GetMesh(pmesh->m_constraint.parentIndex)->m_boneName );
  280. }
  281. if ( parentBone >= 0 )
  282. {
  283. parentMatrix = &m_pBoneToWorld[ parentBone ];
  284. }
  285. if ( m_physPreviewBone == i )
  286. {
  287. matrix3x4_t tmpmatrix;
  288. QAngle rot;
  289. constraint_axislimit_t *axis = pmesh->m_constraint.axes + m_physPreviewAxis;
  290. int hlAxis = RemapAxis( m_physPreviewAxis );
  291. rot.Init();
  292. rot[hlAxis] = axis->minRotation + (axis->maxRotation - axis->minRotation) * m_physPreviewParam;
  293. AngleMatrix( rot, tmpmatrix );
  294. ConcatTransforms( pmesh->m_matrix, tmpmatrix, bonematrix );
  295. }
  296. else
  297. {
  298. MatrixCopy( pmesh->m_matrix, bonematrix );
  299. }
  300. ConcatTransforms( *parentMatrix, bonematrix, m_pBoneToWorld[ boneIndex ] );
  301. }
  302. }
  303. }
  304. int StudioModel::BoneMask( void )
  305. {
  306. int lod = g_viewerSettings.autoLOD ? 0 : g_viewerSettings.lod;
  307. int mask = BONE_USED_BY_VERTEX_AT_LOD(lod);
  308. if (g_viewerSettings.showAttachments || g_viewerSettings.m_iEditAttachment != -1 || m_nSolveHeadTurn != 0 || LookupAttachment( "eyes" ) != -1)
  309. {
  310. mask |= BONE_USED_BY_ATTACHMENT;
  311. }
  312. if (g_viewerSettings.showBones || g_viewerSettings.highlightBone >= 0)
  313. {
  314. mask |= BONE_USED_BY_ANYTHING;
  315. }
  316. if (g_viewerSettings.showHitBoxes)
  317. {
  318. mask |= BONE_USED_BY_HITBOX;
  319. }
  320. mask |= BONE_USED_BY_BONE_MERGE;
  321. return mask;
  322. // return BONE_USED_BY_ANYTHING_AT_LOD( lod );
  323. // return BONE_USED_BY_ANYTHING;
  324. }
  325. void StudioModel::SetUpBones( bool mergeBones )
  326. {
  327. int i, j;
  328. const mstudiobone_t *pbones;
  329. static Vector pos[MAXSTUDIOBONES];
  330. ALIGN16 matrix3x4_t bonematrix;
  331. static QuaternionAligned q[MAXSTUDIOBONES];
  332. bool override[MAXSTUDIOBONES];
  333. static ALIGN16 matrix3x4_t boneCache[MAXSTUDIOBONES];
  334. // For blended transitions
  335. static Vector pos2[MAXSTUDIOBONES];
  336. static Quaternion q2[MAXSTUDIOBONES];
  337. CStudioHdr *pStudioHdr = GetStudioHdr();
  338. mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_sequence );
  339. QAngle a1;
  340. Vector p1;
  341. MatrixAngles( g_viewtransform, a1, p1 );
  342. CIKContext *pIK = NULL;
  343. m_ik.Init( pStudioHdr, a1, p1, GetRealtimeTime(), m_iFramecounter, BoneMask( ) );
  344. if ( g_viewerSettings.enableIK )
  345. {
  346. pIK = &m_ik;
  347. }
  348. IBoneSetup boneSetup( pStudioHdr, BoneMask(), m_poseparameter );
  349. boneSetup.InitPose( pos, q );
  350. boneSetup.AccumulatePose( pos, q, m_sequence, m_cycle, 1.0, GetRealtimeTime(), pIK );
  351. if ( g_viewerSettings.blendSequenceChanges &&
  352. m_sequencetime < m_blendtime &&
  353. m_prevsequence != m_sequence &&
  354. m_prevsequence < pStudioHdr->GetNumSeq() &&
  355. !(seqdesc.flags & STUDIO_SNAP) )
  356. {
  357. // Make sure frame is valid
  358. if ( m_prevcycle >= 1.0 )
  359. {
  360. m_prevcycle = 0.0f;
  361. }
  362. float s = 1.0 - ( m_sequencetime / m_blendtime );
  363. s = 3 * s * s - 2 * s * s * s;
  364. boneSetup.AccumulatePose( pos, q, m_prevsequence, m_prevcycle, s, GetRealtimeTime(), NULL );
  365. // Con_DPrintf("%d %f : %d %f : %f\n", pev->sequence, f, pev->prevsequence, pev->prevframe, s );
  366. }
  367. else
  368. {
  369. m_prevcycle = m_cycle;
  370. }
  371. int iMaxPriority = 0;
  372. for (i = 0; i < MAXSTUDIOANIMLAYERS; i++)
  373. {
  374. if (m_Layer[i].m_weight > 0)
  375. {
  376. iMaxPriority = max( m_Layer[i].m_priority, iMaxPriority );
  377. }
  378. }
  379. for (j = 0; j <= iMaxPriority; j++)
  380. {
  381. for (i = 0; i < MAXSTUDIOANIMLAYERS; i++)
  382. {
  383. if (m_Layer[i].m_priority == j && m_Layer[i].m_weight > 0)
  384. {
  385. boneSetup.AccumulatePose( pos, q, m_Layer[i].m_sequence, m_Layer[i].m_cycle, m_Layer[i].m_weight, GetRealtimeTime(), pIK );
  386. }
  387. }
  388. }
  389. if (m_nSolveHeadTurn != 0)
  390. {
  391. GetBodyPoseParametersFromFlex( );
  392. }
  393. CalcHeadRotation( pos, q );
  394. CIKContext auto_ik;
  395. auto_ik.Init( pStudioHdr, a1, p1, 0.0, 0, BoneMask( ) );
  396. boneSetup.CalcAutoplaySequences( pos, q, GetAutoPlayTime(), &auto_ik );
  397. boneSetup.CalcBoneAdj( pos, q, m_controller );
  398. CBoneBitList boneComputed;
  399. if (pIK)
  400. {
  401. Vector deltaPos;
  402. QAngle deltaAngles;
  403. GetMovement( m_prevIKCycles, deltaPos, deltaAngles );
  404. Vector tmp;
  405. VectorRotate( deltaPos, g_viewtransform, tmp );
  406. deltaPos = tmp;
  407. pIK->UpdateTargets( pos, q, m_pBoneToWorld, boneComputed );
  408. // FIXME: check number of slots?
  409. for (int i = 0; i < pIK->m_target.Count(); i++)
  410. {
  411. trace_t tr;
  412. CIKTarget *pTarget = &pIK->m_target[i];
  413. switch( pTarget->type )
  414. {
  415. case IK_GROUND:
  416. {
  417. // drawLine( pTarget->est.pos, pTarget->est.pos + pTarget->offset.pos, 0, 255, 0 );
  418. // hack in movement
  419. pTarget->est.pos -= deltaPos;
  420. matrix3x4_t invViewTransform;
  421. MatrixInvert( g_viewtransform, invViewTransform );
  422. Vector tmp;
  423. VectorTransform( pTarget->est.pos, invViewTransform, tmp );
  424. tmp.z = pTarget->est.floor;
  425. VectorTransform( tmp, g_viewtransform, pTarget->est.pos );
  426. Vector p1;
  427. Quaternion q1;
  428. MatrixAngles( g_viewtransform, q1, p1 );
  429. pTarget->est.q = q1;
  430. float color[4] = { 0, 0, 0, 0 };
  431. float wirecolor[4] = { 1, 1, 0, 1 };
  432. if (pTarget->est.latched > 0.0)
  433. {
  434. wirecolor[1] = 1.0 - pTarget->est.flWeight;
  435. }
  436. else
  437. {
  438. wirecolor[0] = 1.0 - pTarget->est.flWeight;
  439. }
  440. float r = max(pTarget->est.radius,1);
  441. Vector p0 = tmp + Vector( -r, -r, 0 );
  442. Vector p2 = tmp + Vector( r, r, 0 );
  443. drawTransparentBox( p0, p2, g_viewtransform, color, wirecolor );
  444. if (!g_viewerSettings.enableTargetIK)
  445. {
  446. pTarget->est.flWeight = 0.0;
  447. }
  448. }
  449. break;
  450. case IK_ATTACHMENT:
  451. {
  452. matrix3x4_t m;
  453. QuaternionMatrix( pTarget->est.q, pTarget->est.pos, m );
  454. drawTransform( m, g_viewerSettings.originAxisLength * 0.4f );
  455. }
  456. break;
  457. }
  458. // drawLine( pTarget->est.pos, pTarget->latched.pos, 255, 0, 0 );
  459. }
  460. pIK->SolveDependencies( pos, q, m_pBoneToWorld, boneComputed );
  461. }
  462. pbones = pStudioHdr->pBone( 0 );
  463. memset( override, 0, sizeof(bool)*pStudioHdr->numbones() );
  464. if ( g_viewerSettings.showPhysicsPreview )
  465. {
  466. OverrideBones( override );
  467. }
  468. int nMergedModelIndex = -1;
  469. for ( int n=0; n<HLMV_MAX_MERGED_MODELS; n++ )
  470. {
  471. if ( g_pStudioExtraModel[n] && g_pStudioExtraModel[n]->GetStudioHdr() == pStudioHdr )
  472. {
  473. if ( g_MergeModelBonePairs[n].szLocalBone[0] && g_MergeModelBonePairs[n].szTargetBone[0] )
  474. {
  475. nMergedModelIndex = n;
  476. }
  477. break;
  478. }
  479. }
  480. for (i = 0; i < pStudioHdr->numbones(); i++)
  481. {
  482. if ( !(pStudioHdr->pBone( i )->flags & BoneMask()))
  483. {
  484. int j, k;
  485. for (j = 0; j < 3; j++)
  486. {
  487. for (k = 0; k < 4; k++)
  488. {
  489. m_pBoneToWorld[i][j][k] = VEC_T_NAN;
  490. }
  491. }
  492. continue;
  493. }
  494. if ( override[i] )
  495. {
  496. continue;
  497. }
  498. else if (boneComputed.IsBoneMarked(i))
  499. {
  500. // already calculated
  501. }
  502. else if (CalcProceduralBone( pStudioHdr, i, CBoneAccessor( m_pBoneToWorld ) ))
  503. {
  504. continue;
  505. }
  506. else
  507. {
  508. QuaternionMatrix( q[i], bonematrix );
  509. bonematrix[0][3] = pos[i][0];
  510. bonematrix[1][3] = pos[i][1];
  511. bonematrix[2][3] = pos[i][2];
  512. if ( (pStudioHdr->pBone( 0 )[i].flags & BONE_ALWAYS_PROCEDURAL) &&
  513. (pStudioHdr->pBone( 0 )[i].proctype == STUDIO_PROC_JIGGLE) )
  514. {
  515. //
  516. // Physics-based "jiggle" bone
  517. // Bone is assumed to be along the Z axis
  518. // Pitch around X, yaw around Y
  519. //
  520. // compute desired bone orientation
  521. matrix3x4_t goalMX;
  522. if (pbones[i].parent == -1)
  523. {
  524. ConcatTransforms( g_viewtransform, bonematrix, goalMX );
  525. }
  526. else
  527. {
  528. ConcatTransforms( m_pBoneToWorld[ pbones[i].parent ], bonematrix, goalMX );
  529. }
  530. // get jiggle properties from QC data
  531. mstudiojigglebone_t *jiggleInfo = (mstudiojigglebone_t *)pStudioHdr->pBone( 0 )[i].pProcedure( );
  532. if (!m_pJiggleBones)
  533. {
  534. m_pJiggleBones = new CJiggleBones;
  535. }
  536. // do jiggle physics
  537. m_pJiggleBones->BuildJiggleTransformations( i, GetRealtimeTime(), jiggleInfo, goalMX, m_pBoneToWorld[ i ], false );
  538. }
  539. else if (pbones[i].parent == -1)
  540. {
  541. ConcatTransforms( g_viewtransform, bonematrix, m_pBoneToWorld[ i ] );
  542. // MatrixCopy(bonematrix, g_bonetoworld[i]);
  543. }
  544. else
  545. {
  546. ConcatTransforms( m_pBoneToWorld[ pbones[i].parent ], bonematrix, m_pBoneToWorld[ i ] );
  547. }
  548. if (pStudioHdr->pBone( 0 )[i].flags & BONE_WORLD_ALIGN)
  549. {
  550. Vector vecOrigin = m_pBoneToWorld[ i ].GetOrigin();
  551. m_pBoneToWorld[ i ].Init( Vector(1,0,0), Vector(0,1,0), Vector(0,0,1), vecOrigin );
  552. }
  553. }
  554. if (!mergeBones)
  555. {
  556. g_pCacheHdr = pStudioHdr;
  557. MatrixCopy( m_pBoneToWorld[ i ], boneCache[i] );
  558. }
  559. else if (g_pCacheHdr)
  560. {
  561. // attempt to attach merge models with force bone-to-bone setting
  562. if ( nMergedModelIndex != -1 )
  563. {
  564. const char* szDesiredMergeModelLocalBoneName = g_MergeModelBonePairs[nMergedModelIndex].szLocalBone;
  565. const char* szDesiredTargetBoneName = g_MergeModelBonePairs[nMergedModelIndex].szTargetBone;
  566. const char* szCurrentMergeModelBoneName = pStudioHdr->pBone( i )->pszName();
  567. int nMergeModelLocalBone = -1;
  568. int nMergeModelAttachment = -1;
  569. matrix3x4_t matMergeModelAttachmentLocal;
  570. SetIdentityMatrix( matMergeModelAttachmentLocal );
  571. int nTargetBone = -1;
  572. int nTargetAttachment = -1;
  573. matrix3x4_t matTargetBoneToWorld;
  574. SetIdentityMatrix( matTargetBoneToWorld );
  575. matrix3x4_t matTargetAttachmentLocal;
  576. SetIdentityMatrix( matTargetAttachmentLocal );
  577. //check the attachments
  578. for ( int n=0; n<pStudioHdr->GetNumAttachments(); n++ )
  579. {
  580. mstudioattachment_t &pModelAttachment = (mstudioattachment_t &)pStudioHdr->pAttachment( n );
  581. if ( Q_stricmp( pModelAttachment.pszName(), szDesiredMergeModelLocalBoneName ) == 0 )
  582. {
  583. pStudioHdr->setBoneFlags( pModelAttachment.localbone, BONE_USED_BY_BONE_MERGE );
  584. if ( pModelAttachment.localbone == i )
  585. {
  586. matrix3x4_t matAttachmentToWorld;
  587. ConcatTransforms( m_pBoneToWorld[ pModelAttachment.localbone ], pModelAttachment.local, matAttachmentToWorld );
  588. matrix3x4_t matAttachmentToWorldInv;
  589. MatrixInvert( matAttachmentToWorld, matAttachmentToWorldInv );
  590. ConcatTransforms( matAttachmentToWorldInv, m_pBoneToWorld[0], matMergeModelAttachmentLocal );
  591. nMergeModelLocalBone = i;
  592. nMergeModelAttachment = n;
  593. }
  594. }
  595. }
  596. // otherwise check if we're already on the merge model local bone
  597. if ( nMergeModelLocalBone == -1 && Q_stricmp( szCurrentMergeModelBoneName, szDesiredMergeModelLocalBoneName ) == 0 )
  598. {
  599. nMergeModelLocalBone = i;
  600. }
  601. // if the local bone is valid, let's look for the target bone
  602. if ( nMergeModelLocalBone != -1 )
  603. {
  604. //search master mdl for target bone name
  605. for ( int n=0; n<g_pCacheHdr->numbones(); n++ )
  606. {
  607. const char* szCurrentTargetModelBoneName = g_pCacheHdr->pBone( n )->pszName();
  608. if ( Q_stricmp( szCurrentTargetModelBoneName, szDesiredTargetBoneName ) == 0 )
  609. {
  610. nTargetBone = n;
  611. MatrixCopy( *g_pStudioModel->BoneToWorld( nTargetBone ), matTargetBoneToWorld );
  612. break;
  613. }
  614. }
  615. //if we didn't find it, look at the attachments
  616. if ( nTargetBone == -1 )
  617. {
  618. for ( int a = 0; a < g_pCacheHdr->GetNumAttachments(); a++)
  619. {
  620. mstudioattachment_t &pModelAttachment = (mstudioattachment_t &)g_pCacheHdr->pAttachment( a );
  621. const char* szCurrentTargetModelBoneName = pModelAttachment.pszName();
  622. if ( Q_stricmp( szCurrentTargetModelBoneName, szDesiredTargetBoneName ) == 0 )
  623. {
  624. nTargetBone = pModelAttachment.localbone;
  625. MatrixCopy( *g_pStudioModel->BoneToWorld( nTargetBone ), matTargetBoneToWorld );
  626. nTargetAttachment = a;
  627. MatrixCopy( pModelAttachment.local, matTargetAttachmentLocal );
  628. break;
  629. }
  630. }
  631. }
  632. // both local and target are valid. Let's connect the two
  633. if ( nTargetBone != -1 )
  634. {
  635. pStudioHdr->setBoneFlags( 0, BONE_USED_BY_BONE_MERGE );
  636. pStudioHdr->setBoneFlags( nMergeModelLocalBone, BONE_USED_BY_BONE_MERGE );
  637. g_pCacheHdr->setBoneFlags( nTargetBone, BONE_USED_BY_BONE_MERGE );
  638. matrix3x4_t matTargetBoneToWorldFinal;
  639. ConcatTransforms( matTargetBoneToWorld, matTargetAttachmentLocal, matTargetBoneToWorldFinal );
  640. ConcatTransforms( matTargetBoneToWorldFinal, matMergeModelAttachmentLocal, matTargetBoneToWorldFinal );
  641. MatrixCopy( matTargetBoneToWorldFinal, m_pBoneToWorld[ 0 ] );
  642. }
  643. }
  644. }
  645. else
  646. {
  647. for (j = 0; j < g_pCacheHdr->numbones(); j++)
  648. {
  649. if ( Q_stricmp( pStudioHdr->pBone( i )->pszName(), g_pCacheHdr->pBone( j )->pszName() ) == 0 )
  650. break;
  651. }
  652. if (j < g_pCacheHdr->numbones())
  653. {
  654. pStudioHdr->setBoneFlags( i, BONE_USED_BY_BONE_MERGE );
  655. g_pCacheHdr->setBoneFlags( j, BONE_USED_BY_BONE_MERGE );
  656. MatrixCopy( boneCache[j], m_pBoneToWorld[ i ] );
  657. }
  658. }
  659. }
  660. }
  661. if ( mergeBones )
  662. {
  663. Studio_RunBoneFlexDrivers( m_flexweight, pStudioHdr, pos, m_pBoneToWorld, g_mCachedViewTransform );
  664. }
  665. else
  666. {
  667. MatrixCopy( g_viewtransform, g_mCachedViewTransform );
  668. Studio_RunBoneFlexDrivers( m_flexweight, pStudioHdr, pos, m_pBoneToWorld, g_viewtransform );
  669. }
  670. if ( g_viewerSettings.simulateSoftbodies )
  671. {
  672. if ( CSoftbody *pSoftbody = pStudioHdr->GetSoftbody() )
  673. {
  674. pSoftbody->GoWakeup();
  675. pSoftbody->SetAnimatedTransforms( m_pBoneToWorld );
  676. pSoftbody->FilterTransforms( m_pBoneToWorld );
  677. }
  678. }
  679. if (g_viewerSettings.showAttachments)
  680. {
  681. // drawTransform( m_pBoneToWorld[ 0 ] );
  682. }
  683. }
  684. /*
  685. ================
  686. StudioModel::SetupLighting
  687. set some global variables based on entity position
  688. inputs:
  689. outputs:
  690. ================
  691. */
  692. void StudioModel::SetupLighting ( )
  693. {
  694. // DEBUG: Spin the light around the head for debugging
  695. // g_viewerSettings.lightrot = QAngle( 0, 0, 0 );
  696. // g_viewerSettings.lightrot.y = fmod( (90 * GetTickCount( ) / 1000.0), 360.0);
  697. if (g_viewerSettings.secondaryLights)
  698. {
  699. LightDesc_t light[3];
  700. for ( int i=0; i < 3; i++ )
  701. {
  702. light[i].m_Type = MATERIAL_LIGHT_DIRECTIONAL;
  703. light[i].m_Attenuation0 = 1.0f;
  704. light[i].m_Attenuation1 = 0.0;
  705. light[i].m_Attenuation2 = 0.0;
  706. light[i].m_Color[0] = g_viewerSettings.lColor[0];
  707. light[i].m_Color[1] = g_viewerSettings.lColor[1];
  708. light[i].m_Color[2] = g_viewerSettings.lColor[2];
  709. light[i].m_Range = 2000;
  710. AngleVectors(g_viewerSettings.lightrot, &light[i].m_Direction, NULL, NULL);
  711. }
  712. light[1].m_Color[0] = 0.3f;
  713. light[1].m_Color[1] = 0.4f;
  714. light[1].m_Color[2] = 0.5f;
  715. AngleVectors(g_viewerSettings.lightrot + QAngle(180, 0, 0), &light[1].m_Direction, NULL, NULL);
  716. light[2].m_Color[0] = 0.5f;
  717. light[2].m_Color[1] = 0.4f;
  718. light[2].m_Color[2] = 0.3f;
  719. AngleVectors(g_viewerSettings.lightrot + QAngle(0, 90, 0), &light[2].m_Direction, NULL, NULL);
  720. g_pStudioRender->SetLocalLights(3, light);
  721. }
  722. else
  723. {
  724. LightDesc_t light[1];
  725. light[0].m_Type = MATERIAL_LIGHT_DIRECTIONAL;
  726. light[0].m_Attenuation0 = 1.0f;
  727. light[0].m_Attenuation1 = 0.0;
  728. light[0].m_Attenuation2 = 0.0;
  729. light[0].m_Color[0] = g_viewerSettings.lColor[0];
  730. light[0].m_Color[1] = g_viewerSettings.lColor[1];
  731. light[0].m_Color[2] = g_viewerSettings.lColor[2];
  732. light[0].m_Range = 2000;
  733. light[0].m_Position = Vector( 0, 0, 0 );
  734. AngleVectors(g_viewerSettings.lightrot, &light[0].m_Direction, NULL, NULL);
  735. g_pStudioRender->SetLocalLights(1, light);
  736. }
  737. for (int i = 0; i < g_pStudioRender->GetNumAmbientLightSamples(); i++)
  738. {
  739. m_AmbientLightColors[i][0] = g_viewerSettings.aColor[0];
  740. m_AmbientLightColors[i][1] = g_viewerSettings.aColor[1];
  741. m_AmbientLightColors[i][2] = g_viewerSettings.aColor[2];
  742. }
  743. g_pStudioRender->SetAmbientLightColors(m_AmbientLightColors);
  744. }
  745. int FindBoneIndex( CStudioHdr *pstudiohdr, const char *pName )
  746. {
  747. const mstudiobone_t *pbones = pstudiohdr->pBone( 0 );
  748. for (int i = 0; i < pstudiohdr->numbones(); i++)
  749. {
  750. if ( !strcmpi( pName, pbones[i].pszName() ) )
  751. return i;
  752. }
  753. return -1;
  754. }
  755. //-----------------------------------------------------------------------------
  756. // Purpose: Find the named bone index, -1 if not found
  757. // Input : *pName - bone name
  758. //-----------------------------------------------------------------------------
  759. int StudioModel::FindBone( const char *pName )
  760. {
  761. CStudioHdr *pStudioHdr = GetStudioHdr();
  762. return FindBoneIndex( pStudioHdr, pName );
  763. }
  764. int StudioModel::Physics_GetBoneIndex( const char *pName )
  765. {
  766. for (int i = 0; i < m_pPhysics->Count(); i++)
  767. {
  768. CPhysmesh *pmesh = m_pPhysics->GetMesh(i);
  769. if ( !strcmpi( pName, pmesh[i].m_boneName ) )
  770. return i;
  771. }
  772. return -1;
  773. }
  774. /*
  775. =================
  776. StudioModel::SetupModel
  777. based on the body part, figure out which mesh it should be using.
  778. inputs:
  779. currententity
  780. outputs:
  781. pstudiomesh
  782. pmdl
  783. =================
  784. */
  785. void StudioModel::SetupModel ( int bodypart )
  786. {
  787. int index;
  788. CStudioHdr *pStudioHdr = GetStudioHdr();
  789. if (bodypart > pStudioHdr->numbodyparts())
  790. {
  791. // Con_DPrintf ("StudioModel::SetupModel: no such bodypart %d\n", bodypart);
  792. bodypart = 0;
  793. }
  794. mstudiobodyparts_t *pbodypart = pStudioHdr->pBodypart( bodypart );
  795. index = m_bodynum / pbodypart->base;
  796. index = index % pbodypart->nummodels;
  797. m_pmodel = pbodypart->pModel( index );
  798. if(first){
  799. maxNumVertices = m_pmodel->numvertices;
  800. first = 0;
  801. }
  802. }
  803. static IMaterial *g_pAlpha;
  804. //-----------------------------------------------------------------------------
  805. // Draws a box, not wireframed
  806. //-----------------------------------------------------------------------------
  807. void StudioModel::drawBox (Vector const *v, float const * color )
  808. {
  809. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  810. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  811. CMeshBuilder meshBuilder;
  812. // The four sides
  813. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 * 4 );
  814. for (int i = 0; i < 10; i++)
  815. {
  816. meshBuilder.Position3fv (v[i & 7].Base() );
  817. meshBuilder.Color4fv( color );
  818. meshBuilder.AdvanceVertex();
  819. }
  820. meshBuilder.End();
  821. pMesh->Draw();
  822. // top and bottom
  823. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 );
  824. meshBuilder.Position3fv (v[6].Base());
  825. meshBuilder.Color4fv( color );
  826. meshBuilder.AdvanceVertex();
  827. meshBuilder.Position3fv (v[0].Base());
  828. meshBuilder.Color4fv( color );
  829. meshBuilder.AdvanceVertex();
  830. meshBuilder.Position3fv (v[4].Base());
  831. meshBuilder.Color4fv( color );
  832. meshBuilder.AdvanceVertex();
  833. meshBuilder.Position3fv (v[2].Base());
  834. meshBuilder.Color4fv( color );
  835. meshBuilder.AdvanceVertex();
  836. meshBuilder.End();
  837. pMesh->Draw();
  838. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 );
  839. meshBuilder.Position3fv (v[1].Base());
  840. meshBuilder.Color4fv( color );
  841. meshBuilder.AdvanceVertex();
  842. meshBuilder.Position3fv (v[7].Base());
  843. meshBuilder.Color4fv( color );
  844. meshBuilder.AdvanceVertex();
  845. meshBuilder.Position3fv (v[3].Base());
  846. meshBuilder.Color4fv( color );
  847. meshBuilder.AdvanceVertex();
  848. meshBuilder.Position3fv (v[5].Base());
  849. meshBuilder.Color4fv( color );
  850. meshBuilder.AdvanceVertex();
  851. meshBuilder.End();
  852. pMesh->Draw();
  853. }
  854. //-----------------------------------------------------------------------------
  855. // Draws a wireframed box
  856. //-----------------------------------------------------------------------------
  857. void StudioModel::drawWireframeBox (Vector const *v, float const* color )
  858. {
  859. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  860. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  861. CMeshBuilder meshBuilder;
  862. // The four sides
  863. meshBuilder.Begin( pMesh, MATERIAL_LINES, 4 );
  864. for (int i = 0; i < 10; i++)
  865. {
  866. meshBuilder.Position3fv (v[i & 7].Base());
  867. meshBuilder.Color4fv( color );
  868. meshBuilder.AdvanceVertex();
  869. }
  870. meshBuilder.End();
  871. pMesh->Draw();
  872. // top and bottom
  873. meshBuilder.Begin( pMesh, MATERIAL_LINE_STRIP, 4 );
  874. meshBuilder.Position3fv (v[6].Base());
  875. meshBuilder.Color4fv( color );
  876. meshBuilder.AdvanceVertex();
  877. meshBuilder.Position3fv (v[0].Base());
  878. meshBuilder.Color4fv( color );
  879. meshBuilder.AdvanceVertex();
  880. meshBuilder.Position3fv (v[2].Base());
  881. meshBuilder.Color4fv( color );
  882. meshBuilder.AdvanceVertex();
  883. meshBuilder.Position3fv (v[4].Base());
  884. meshBuilder.Color4fv( color );
  885. meshBuilder.AdvanceVertex();
  886. meshBuilder.Position3fv (v[6].Base());
  887. meshBuilder.Color4fv( color );
  888. meshBuilder.AdvanceVertex();
  889. meshBuilder.End();
  890. pMesh->Draw();
  891. meshBuilder.Begin( pMesh, MATERIAL_LINE_STRIP, 4 );
  892. meshBuilder.Position3fv (v[1].Base());
  893. meshBuilder.Color4fv( color );
  894. meshBuilder.AdvanceVertex();
  895. meshBuilder.Position3fv (v[7].Base());
  896. meshBuilder.Color4fv( color );
  897. meshBuilder.AdvanceVertex();
  898. meshBuilder.Position3fv (v[5].Base());
  899. meshBuilder.Color4fv( color );
  900. meshBuilder.AdvanceVertex();
  901. meshBuilder.Position3fv (v[3].Base());
  902. meshBuilder.Color4fv( color );
  903. meshBuilder.AdvanceVertex();
  904. meshBuilder.Position3fv (v[1].Base());
  905. meshBuilder.Color4fv( color );
  906. meshBuilder.AdvanceVertex();
  907. meshBuilder.End();
  908. pMesh->Draw();
  909. }
  910. //-----------------------------------------------------------------------------
  911. // Draws the position and axies of a transformation matrix, x=red,y=green,z=blue
  912. //-----------------------------------------------------------------------------
  913. void StudioModel::drawTransform( matrix3x4_t& m, float flLength )
  914. {
  915. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  916. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  917. CMeshBuilder meshBuilder;
  918. for (int k = 0; k < 3; k++)
  919. {
  920. static unsigned char color[3][3] =
  921. {
  922. { 255, 0, 0 },
  923. { 0, 255, 0 },
  924. { 0, 0, 255 }
  925. };
  926. meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
  927. meshBuilder.Color3ubv( color[k] );
  928. meshBuilder.Position3f( m[0][3], m[1][3], m[2][3]);
  929. meshBuilder.AdvanceVertex();
  930. meshBuilder.Color3ubv( color[k] );
  931. meshBuilder.Position3f( m[0][3] + m[0][k] * flLength, m[1][3] + m[1][k] * flLength, m[2][3] + m[2][k] * flLength);
  932. meshBuilder.AdvanceVertex();
  933. meshBuilder.End();
  934. pMesh->Draw();
  935. }
  936. }
  937. void drawLine( Vector const &p1, Vector const &p2, int r, int g, int b, bool noDepthTest, float duration )
  938. {
  939. g_pStudioModel->drawLine( p1, p2, r, g, b );
  940. }
  941. void StudioModel::drawLine( Vector const &p1, Vector const &p2, int r, int g, int b )
  942. {
  943. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  944. pRenderContext->Bind( g_materialVertexColor );
  945. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  946. CMeshBuilder meshBuilder;
  947. meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
  948. meshBuilder.Color3ub( r, g, b );
  949. meshBuilder.Position3f( p1.x, p1.y, p1.z );
  950. meshBuilder.AdvanceVertex();
  951. meshBuilder.Color3ub( r, g, b );
  952. meshBuilder.Position3f( p2.x, p2.y, p2.z );
  953. meshBuilder.AdvanceVertex();
  954. meshBuilder.End();
  955. pMesh->Draw();
  956. }
  957. #define CHAR_WIDTH 0.0625f // 1/16
  958. #define CHAR_HEIGHT 0.0625f // 1/16
  959. float buildTextCharQuad( CMeshBuilder* pMeshBuilder, const char* szLetter, Vector const &pos, float flScale )
  960. {
  961. Vector vecPos;
  962. VectorCopy( pos, vecPos );
  963. float flPolyWidth = flScale;
  964. float flPolyHeight = flScale;
  965. vecPos.z -= flPolyHeight * 0.5f;
  966. int nCharIdx = (int)((char)*szLetter) - 32;
  967. int nRow = nCharIdx / 16;
  968. int nCol = nCharIdx % 16;
  969. float flU = (nCol * CHAR_WIDTH);
  970. float flV = (nRow * CHAR_HEIGHT);
  971. flV += CHAR_HEIGHT;
  972. pMeshBuilder->Position3fv( vecPos.Base() );
  973. pMeshBuilder->TexCoord2f( 0, flU, flV );
  974. pMeshBuilder->Color4ub( 255, 255, 255, 255 );
  975. pMeshBuilder->AdvanceVertex();
  976. vecPos.z += flPolyHeight;
  977. flV -= CHAR_HEIGHT;
  978. pMeshBuilder->Position3fv( vecPos.Base() );
  979. pMeshBuilder->TexCoord2f( 0, flU, flV );
  980. pMeshBuilder->Color4ub( 255, 255, 255, 255 );
  981. pMeshBuilder->AdvanceVertex();
  982. vecPos.y += flPolyWidth;
  983. flU += CHAR_WIDTH;
  984. pMeshBuilder->Position3fv( vecPos.Base() );
  985. pMeshBuilder->TexCoord2f( 0, flU, flV );
  986. pMeshBuilder->Color4ub( 255, 255, 255, 255 );
  987. pMeshBuilder->AdvanceVertex();
  988. vecPos.z -= flPolyHeight;
  989. flV += CHAR_HEIGHT;
  990. pMeshBuilder->Position3fv( vecPos.Base() );
  991. pMeshBuilder->TexCoord2f( 0, flU, flV );
  992. pMeshBuilder->Color4ub( 255, 255, 255, 255 );
  993. pMeshBuilder->AdvanceVertex();
  994. return flPolyWidth * 0.6f;
  995. }
  996. void StudioModel::drawText( Vector const &pos, const char* szText )
  997. {
  998. int nNumChars = strlen( szText );
  999. if ( !nNumChars )
  1000. return;
  1001. Vector vecStartPos;
  1002. VectorCopy( pos, vecStartPos );
  1003. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1004. pRenderContext->Bind( g_materialDebugText );
  1005. float screenSize = 50.0f / MAX( pRenderContext->ComputePixelWidthOfSphere( vecStartPos, 1.0f ), 0.001f );
  1006. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  1007. CMeshBuilder meshBuilder;
  1008. meshBuilder.Begin( pMesh, MATERIAL_QUADS, nNumChars );
  1009. for ( int i=0; i<nNumChars; i++ )
  1010. {
  1011. vecStartPos.y += buildTextCharQuad( &meshBuilder, szText, vecStartPos, screenSize );
  1012. szText++;
  1013. }
  1014. meshBuilder.End();
  1015. pMesh->Draw();
  1016. }
  1017. // todo: draw a capsule procedurally instead of using these baked-in unit capsule verts
  1018. #define CAPSULE_VERTS 290
  1019. #define CAPSULE_TRIS 576
  1020. #define CAPSULE_LINES 148
  1021. static float g_capsuleVertPositions[CAPSULE_VERTS][3]={
  1022. {-0.02,1.0,0.0},{-0.27,0.96,0.0},{-0.52,0.86,0.0},{-0.72,0.7,0.0},{-0.88,0.5,0.0},{-0.98,0.25,0.0},{-1.02,0.0,0.0},{-0.98,-0.26,0.0},
  1023. {-0.88,-0.51,0.0},{-0.72,-0.71,0.0},{-0.52,-0.87,0.0},{-0.27,-0.97,0.0},{-0.02,-1.01,0.0},{0.24,-0.97,0.0},{0.48,-0.87,0.0},{0.69,-0.71,0.0},
  1024. {0.85,-0.51,0.0},{0.95,-0.26,0.0},{0.98,-0.01,0.0},{0.95,0.25,0.0},{0.85,0.5,0.0},{0.69,0.7,0.0},{0.48,0.86,0.0},{0.24,0.96,0.0},{-0.02,0.96,-0.26},
  1025. {-0.27,0.93,-0.26},{-0.5,0.83,-0.26},{-0.7,0.68,-0.26},{-0.85,0.48,-0.26},{-0.95,0.25,-0.26},{-0.98,0.0,-0.26},{-0.95,-0.26,-0.26},{-0.85,-0.49,-0.26},
  1026. {-0.7,-0.69,-0.26},{-0.5,-0.84,-0.26},{-0.27,-0.94,-0.26},{-0.02,-0.97,-0.26},{0.23,-0.94,-0.26},{0.47,-0.84,-0.26},{0.67,-0.69,-0.26},{0.82,-0.49,-0.26},
  1027. {0.92,-0.26,-0.26},{0.95,-0.01,-0.26},{0.92,0.25,-0.26},{0.82,0.48,-0.26},{0.67,0.68,-0.26},{0.47,0.83,-0.26},{0.23,0.93,-0.26},{-0.02,0.86,-0.51},
  1028. {-0.24,0.83,-0.51},{-0.45,0.75,-0.51},{-0.63,0.61,-0.51},{-0.77,0.43,-0.51},{-0.85,0.22,-0.51},{-0.88,0.0,-0.51},{-0.85,-0.23,-0.51},{-0.77,-0.44,-0.51},
  1029. {-0.63,-0.62,-0.51},{-0.45,-0.76,-0.51},{-0.24,-0.84,-0.51},{-0.02,-0.87,-0.51},{0.21,-0.84,-0.51},{0.42,-0.76,-0.51},{0.6,-0.62,-0.51},{0.73,-0.44,-0.51},
  1030. {0.82,-0.23,-0.51},{0.85,-0.01,-0.51},{0.82,0.22,-0.51},{0.73,0.43,-0.51},{0.6,0.61,-0.51},{0.42,0.75,-0.51},{0.21,0.83,-0.51},{-0.02,0.7,-0.71},
  1031. {-0.2,0.68,-0.71},{-0.37,0.61,-0.71},{-0.52,0.5,-0.71},{-0.63,0.35,-0.71},{-0.7,0.18,-0.71},{-0.72,0.0,-0.71},{-0.7,-0.19,-0.71},{-0.63,-0.36,-0.71},
  1032. {-0.52,-0.51,-0.71},{-0.37,-0.62,-0.71},{-0.2,-0.69,-0.71},{-0.02,-0.71,-0.71},{0.17,-0.69,-0.71},{0.34,-0.62,-0.71},{0.48,-0.51,-0.71},{0.6,-0.36,-0.71},
  1033. {0.67,-0.19,-0.71},{0.69,-0.01,-0.71},{0.67,0.18,-0.71},{0.6,0.35,-0.71},{0.48,0.5,-0.71},{0.34,0.61,-0.71},{0.17,0.68,-0.71},{-0.02,0.5,-0.87},
  1034. {-0.14,0.48,-0.87},{-0.27,0.43,-0.87},{-0.37,0.35,-0.87},{-0.45,0.25,-0.87},{-0.5,0.12,-0.87},{-0.52,0.0,-0.87},{-0.5,-0.13,-0.87},{-0.45,-0.26,-0.87},
  1035. {-0.37,-0.36,-0.87},{-0.27,-0.44,-0.87},{-0.14,-0.49,-0.87},{-0.02,-0.51,-0.87},{0.11,-0.49,-0.87},{0.23,-0.44,-0.87},{0.34,-0.36,-0.87},{0.42,-0.26,-0.87},
  1036. {0.47,-0.13,-0.87},{0.48,-0.01,-0.87},{0.47,0.12,-0.87},{0.42,0.25,-0.87},{0.34,0.35,-0.87},{0.23,0.43,-0.87},{0.11,0.48,-0.87},{-0.02,0.25,-0.97},
  1037. {-0.08,0.25,-0.97},{-0.14,0.22,-0.97},{-0.2,0.18,-0.97},{-0.24,0.12,-0.97},{-0.27,0.06,-0.97},{-0.27,0.0,-0.97},{-0.27,-0.07,-0.97},{-0.24,-0.13,-0.97},
  1038. {-0.2,-0.19,-0.97},{-0.14,-0.23,-0.97},{-0.08,-0.26,-0.97},{-0.02,-0.26,-0.97},{0.05,-0.26,-0.97},{0.11,-0.23,-0.97},{0.17,-0.19,-0.97},{0.21,-0.13,-0.97},
  1039. {0.23,-0.07,-0.97},{0.24,-0.01,-0.97},{0.23,0.06,-0.97},{0.21,0.12,-0.97},{0.17,0.18,-0.97},{0.11,0.22,-0.97},{0.05,0.25,-0.97},{-0.02,0.0,-1.01},
  1040. {-0.27,-0.97,0.0},{-0.02,-1.01,0.0},{0.24,-0.97,0.0},{0.48,-0.87,0.0},{0.69,-0.71,0.0},{0.85,-0.51,0.0},{0.95,-0.26,0.0},{0.98,-0.01,0.0},{0.95,0.25,0.0},
  1041. {0.85,0.5,0.0},{-0.02,1.0,0.0},{0.24,0.96,0.0},{0.48,0.86,0.0},{0.69,0.7,0.0},{-0.52,-0.87,0.0},{-0.72,-0.71,0.0},{-0.88,-0.51,0.0},{-0.98,-0.26,0.0},
  1042. {-1.02,-0.01,0.0},{-0.98,0.25,0.0},{-0.88,0.5,0.0},{-0.72,0.7,0.0},{-0.52,0.86,0.0},{-0.27,0.96,0.0},{-0.02,0.96,0.25},{0.23,0.93,0.25},{0.47,0.83,0.25},
  1043. {0.67,0.68,0.25},{0.82,0.48,0.25},{0.92,0.25,0.25},{0.95,-0.01,0.25},{0.92,-0.26,0.25},{0.82,-0.49,0.25},{0.67,-0.69,0.25},{0.47,-0.84,0.25},
  1044. {0.23,-0.94,0.25},{-0.02,-0.97,0.25},{-0.27,-0.94,0.25},{-0.5,-0.84,0.25},{-0.7,-0.69,0.25},{-0.85,-0.49,0.25},{-0.95,-0.26,0.25},{-0.98,-0.01,0.25},
  1045. {-0.95,0.25,0.25},{-0.85,0.48,0.25},{-0.7,0.68,0.25},{-0.5,0.83,0.25},{-0.27,0.93,0.25},{-0.02,0.86,0.5},{0.21,0.83,0.5},{0.42,0.75,0.5},{0.6,0.61,0.5},
  1046. {0.73,0.43,0.5},{0.82,0.22,0.5},{0.85,-0.01,0.5},{0.82,-0.23,0.5},{0.73,-0.44,0.5},{0.6,-0.62,0.5},{0.42,-0.76,0.5},{0.21,-0.84,0.5},{-0.02,-0.87,0.5},
  1047. {-0.24,-0.84,0.5},{-0.45,-0.76,0.5},{-0.63,-0.62,0.5},{-0.77,-0.44,0.5},{-0.85,-0.23,0.5},{-0.88,-0.01,0.5},{-0.85,0.22,0.5},{-0.77,0.43,0.5},
  1048. {-0.63,0.61,0.5},{-0.45,0.75,0.5},{-0.24,0.83,0.5},{-0.02,0.7,0.7},{0.17,0.68,0.7},{0.34,0.61,0.7},{0.48,0.5,0.7},{0.6,0.35,0.7},{0.67,0.18,0.7},
  1049. {0.69,-0.01,0.7},{0.67,-0.19,0.7},{0.6,-0.36,0.7},{0.48,-0.51,0.7},{0.34,-0.62,0.7},{0.17,-0.69,0.7},{-0.02,-0.71,0.7},{-0.2,-0.69,0.7},{-0.37,-0.62,0.7},
  1050. {-0.52,-0.51,0.7},{-0.63,-0.36,0.7},{-0.7,-0.19,0.7},{-0.72,-0.01,0.7},{-0.7,0.18,0.7},{-0.63,0.35,0.7},{-0.52,0.5,0.7},{-0.37,0.61,0.7},{-0.2,0.68,0.7},
  1051. {-0.02,0.5,0.86},{0.11,0.48,0.86},{0.23,0.43,0.86},{0.34,0.35,0.86},{0.42,0.25,0.86},{0.47,0.12,0.86},{0.48,-0.01,0.86},{0.47,-0.13,0.86},{0.42,-0.26,0.86},
  1052. {0.34,-0.36,0.86},{0.23,-0.44,0.86},{0.11,-0.49,0.86},{-0.02,-0.51,0.86},{-0.14,-0.49,0.86},{-0.27,-0.44,0.86},{-0.37,-0.36,0.86},{-0.45,-0.26,0.86},
  1053. {-0.5,-0.13,0.86},{-0.52,-0.01,0.86},{-0.5,0.12,0.86},{-0.45,0.25,0.86},{-0.37,0.35,0.86},{-0.27,0.43,0.86},{-0.14,0.48,0.86},{-0.02,0.25,0.96},
  1054. {0.05,0.25,0.96},{0.11,0.22,0.96},{0.17,0.18,0.96},{0.21,0.12,0.96},{0.23,0.06,0.96},{0.24,-0.01,0.96},{0.23,-0.07,0.96},{0.21,-0.13,0.96},
  1055. {0.17,-0.19,0.96},{0.11,-0.23,0.96},{0.05,-0.26,0.96},{-0.02,-0.26,0.96},{-0.08,-0.26,0.96},{-0.14,-0.23,0.96},{-0.2,-0.19,0.96},{-0.24,-0.13,0.96},
  1056. {-0.27,-0.07,0.96},{-0.27,-0.01,0.96},{-0.27,0.06,0.96},{-0.24,0.12,0.96},{-0.2,0.18,0.96},{-0.14,0.22,0.96},{-0.08,0.25,0.96},{-0.02,-0.01,1.0},
  1057. };
  1058. static int g_capsuleTriIndices[ CAPSULE_TRIS ][ 3 ] = {
  1059. {25,1,0},{0,24,25},{26,2,1},{1,25,26},{27,3,2},{2,26,27},{28,4,3},{3,27,28},{29,5,4},{4,28,29},{30,6,5},{5,29,30},{31,7,6},{6,30,31},{32,8,7},{7,31,32},
  1060. {33,9,8},{8,32,33},{34,10,9},{9,33,34},{35,11,10},{10,34,35},{36,12,11},{11,35,36},{37,13,12},{12,36,37},{38,14,13},{13,37,38},{39,15,14},{14,38,39},
  1061. {40,16,15},{15,39,40},{41,17,16},{16,40,41},{42,18,17},{17,41,42},{43,19,18},{18,42,43},{44,20,19},{19,43,44},{45,21,20},{20,44,45},{46,22,21},{21,45,46},
  1062. {47,23,22},{22,46,47},{24,0,23},{23,47,24},{49,25,24},{24,48,49},{50,26,25},{25,49,50},{51,27,26},{26,50,51},{52,28,27},{27,51,52},{53,29,28},{28,52,53},
  1063. {54,30,29},{29,53,54},{55,31,30},{30,54,55},{56,32,31},{31,55,56},{57,33,32},{32,56,57},{58,34,33},{33,57,58},{59,35,34},{34,58,59},{60,36,35},{35,59,60},
  1064. {61,37,36},{36,60,61},{62,38,37},{37,61,62},{63,39,38},{38,62,63},{64,40,39},{39,63,64},{65,41,40},{40,64,65},{66,42,41},{41,65,66},{67,43,42},{42,66,67},
  1065. {68,44,43},{43,67,68},{69,45,44},{44,68,69},{70,46,45},{45,69,70},{71,47,46},{46,70,71},{48,24,47},{47,71,48},{73,49,48},{48,72,73},{74,50,49},{49,73,74},
  1066. {75,51,50},{50,74,75},{76,52,51},{51,75,76},{77,53,52},{52,76,77},{78,54,53},{53,77,78},{79,55,54},{54,78,79},{80,56,55},{55,79,80},{81,57,56},{56,80,81},
  1067. {82,58,57},{57,81,82},{83,59,58},{58,82,83},{84,60,59},{59,83,84},{85,61,60},{60,84,85},{86,62,61},{61,85,86},{87,63,62},{62,86,87},{88,64,63},{63,87,88},
  1068. {89,65,64},{64,88,89},{90,66,65},{65,89,90},{91,67,66},{66,90,91},{92,68,67},{67,91,92},{93,69,68},{68,92,93},{94,70,69},{69,93,94},{95,71,70},{70,94,95},
  1069. {72,48,71},{71,95,72},{97,73,72},{72,96,97},{98,74,73},{73,97,98},{99,75,74},{74,98,99},{100,76,75},{75,99,100},{101,77,76},{76,100,101},{102,78,77},
  1070. {77,101,102},{103,79,78},{78,102,103},{104,80,79},{79,103,104},{105,81,80},{80,104,105},{106,82,81},{81,105,106},{107,83,82},{82,106,107},{108,84,83},
  1071. {83,107,108},{109,85,84},{84,108,109},{110,86,85},{85,109,110},{111,87,86},{86,110,111},{112,88,87},{87,111,112},{113,89,88},{88,112,113},{114,90,89},
  1072. {89,113,114},{115,91,90},{90,114,115},{116,92,91},{91,115,116},{117,93,92},{92,116,117},{118,94,93},{93,117,118},{119,95,94},{94,118,119},{96,72,95},
  1073. {95,119,96},{121,97,96},{96,120,121},{122,98,97},{97,121,122},{123,99,98},{98,122,123},{124,100,99},{99,123,124},{125,101,100},{100,124,125},{126,102,101},
  1074. {101,125,126},{127,103,102},{102,126,127},{128,104,103},{103,127,128},{129,105,104},{104,128,129},{130,106,105},{105,129,130},{131,107,106},{106,130,131},
  1075. {132,108,107},{107,131,132},{133,109,108},{108,132,133},{134,110,109},{109,133,134},{135,111,110},{110,134,135},{136,112,111},{111,135,136},{137,113,112},
  1076. {112,136,137},{138,114,113},{113,137,138},{139,115,114},{114,138,139},{140,116,115},{115,139,140},{141,117,116},{116,140,141},{142,118,117},{117,141,142},
  1077. {143,119,118},{118,142,143},{120,96,119},{119,143,120},{144,121,120},{144,122,121},{144,123,122},{144,124,123},{144,125,124},{144,126,125},{144,127,126},
  1078. {144,128,127},{144,129,128},{144,130,129},{144,131,130},{144,132,131},{144,133,132},{144,134,133},{144,135,134},{144,136,135},{144,137,136},{144,138,137},
  1079. {144,139,138},{144,140,139},{144,141,140},{144,142,141},{144,143,142},{144,120,143},{0,1,168},{168,155,0},{1,2,167},{167,168,1},{2,3,166},{166,167,2},
  1080. {3,4,165},{165,166,3},{4,5,164},{164,165,4},{5,6,163},{163,164,5},{6,7,162},{162,163,6},{7,8,161},{161,162,7},{8,9,160},{160,161,8},{9,10,159},{159,160,9},
  1081. {10,11,145},{145,159,10},{11,12,146},{146,145,11},{12,13,147},{147,146,12},{13,14,148},{148,147,13},{14,15,149},{149,148,14},{15,16,150},{150,149,15},
  1082. {16,17,151},{151,150,16},{17,18,152},{152,151,17},{18,19,153},{153,152,18},{19,20,154},{154,153,19},{20,21,158},{158,154,20},{21,22,157},{157,158,21},
  1083. {22,23,156},{156,157,22},{23,0,155},{155,156,23},{170,156,155},{155,169,170},{171,157,156},{156,170,171},{172,158,157},{157,171,172},{173,154,158},
  1084. {158,172,173},{174,153,154},{154,173,174},{175,152,153},{153,174,175},{176,151,152},{152,175,176},{177,150,151},{151,176,177},{178,149,150},{150,177,178},
  1085. {179,148,149},{149,178,179},{180,147,148},{148,179,180},{181,146,147},{147,180,181},{182,145,146},{146,181,182},{183,159,145},{145,182,183},{184,160,159},
  1086. {159,183,184},{185,161,160},{160,184,185},{186,162,161},{161,185,186},{187,163,162},{162,186,187},{188,164,163},{163,187,188},{189,165,164},{164,188,189},
  1087. {190,166,165},{165,189,190},{191,167,166},{166,190,191},{192,168,167},{167,191,192},{169,155,168},{168,192,169},{194,170,169},{169,193,194},{195,171,170},
  1088. {170,194,195},{196,172,171},{171,195,196},{197,173,172},{172,196,197},{198,174,173},{173,197,198},{199,175,174},{174,198,199},{200,176,175},{175,199,200},
  1089. {201,177,176},{176,200,201},{202,178,177},{177,201,202},{203,179,178},{178,202,203},{204,180,179},{179,203,204},{205,181,180},{180,204,205},{206,182,181},
  1090. {181,205,206},{207,183,182},{182,206,207},{208,184,183},{183,207,208},{209,185,184},{184,208,209},{210,186,185},{185,209,210},{211,187,186},{186,210,211},
  1091. {212,188,187},{187,211,212},{213,189,188},{188,212,213},{214,190,189},{189,213,214},{215,191,190},{190,214,215},{216,192,191},{191,215,216},{193,169,192},
  1092. {192,216,193},{218,194,193},{193,217,218},{219,195,194},{194,218,219},{220,196,195},{195,219,220},{221,197,196},{196,220,221},{222,198,197},{197,221,222},
  1093. {223,199,198},{198,222,223},{224,200,199},{199,223,224},{225,201,200},{200,224,225},{226,202,201},{201,225,226},{227,203,202},{202,226,227},{228,204,203},
  1094. {203,227,228},{229,205,204},{204,228,229},{230,206,205},{205,229,230},{231,207,206},{206,230,231},{232,208,207},{207,231,232},{233,209,208},{208,232,233},
  1095. {234,210,209},{209,233,234},{235,211,210},{210,234,235},{236,212,211},{211,235,236},{237,213,212},{212,236,237},{238,214,213},{213,237,238},{239,215,214},
  1096. {214,238,239},{240,216,215},{215,239,240},{217,193,216},{216,240,217},{242,218,217},{217,241,242},{243,219,218},{218,242,243},{244,220,219},{219,243,244},
  1097. {245,221,220},{220,244,245},{246,222,221},{221,245,246},{247,223,222},{222,246,247},{248,224,223},{223,247,248},{249,225,224},{224,248,249},{250,226,225},
  1098. {225,249,250},{251,227,226},{226,250,251},{252,228,227},{227,251,252},{253,229,228},{228,252,253},{254,230,229},{229,253,254},{255,231,230},{230,254,255},
  1099. {256,232,231},{231,255,256},{257,233,232},{232,256,257},{258,234,233},{233,257,258},{259,235,234},{234,258,259},{260,236,235},{235,259,260},{261,237,236},
  1100. {236,260,261},{262,238,237},{237,261,262},{263,239,238},{238,262,263},{264,240,239},{239,263,264},{241,217,240},{240,264,241},{266,242,241},{241,265,266},
  1101. {267,243,242},{242,266,267},{268,244,243},{243,267,268},{269,245,244},{244,268,269},{270,246,245},{245,269,270},{271,247,246},{246,270,271},{272,248,247},
  1102. {247,271,272},{273,249,248},{248,272,273},{274,250,249},{249,273,274},{275,251,250},{250,274,275},{276,252,251},{251,275,276},{277,253,252},{252,276,277},
  1103. {278,254,253},{253,277,278},{279,255,254},{254,278,279},{280,256,255},{255,279,280},{281,257,256},{256,280,281},{282,258,257},{257,281,282},{283,259,258},
  1104. {258,282,283},{284,260,259},{259,283,284},{285,261,260},{260,284,285},{286,262,261},{261,285,286},{287,263,262},{262,286,287},{288,264,263},{263,287,288},
  1105. {265,241,264},{264,288,265},{289,266,265},{289,267,266},{289,268,267},{289,269,268},{289,270,269},{289,271,270},{289,272,271},{289,273,272},{289,274,273},
  1106. {289,275,274},{289,276,275},{289,277,276},{289,278,277},{289,279,278},{289,280,279},{289,281,280},{289,282,281},{289,283,282},{289,284,283},{289,285,284},
  1107. {289,286,285},{289,287,286},{289,288,287},{289,265,288},
  1108. };
  1109. static int g_capsuleLineIndices[CAPSULE_LINES][2] = {
  1110. { 0, 1 }, { 0, 24 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 6, 30 }, { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 9 }, { 9, 10 }, { 10, 11 }, { 12, 36 },
  1111. { 11, 12 }, { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 16 }, { 16, 17 }, { 18, 42 }, { 17, 18 }, { 18, 19 }, { 19, 20 }, { 20, 21 }, { 21, 22 }, { 22, 23 }, { 0, 23 },
  1112. { 24, 48 }, { 48, 49 }, { 49, 50 }, { 50, 51 }, { 51, 52 }, { 52, 53 }, { 30, 54 }, { 53, 54 }, { 54, 55 }, { 55, 56 }, { 56, 57 }, { 57, 58 }, { 58, 59 }, { 36, 60 },
  1113. { 59, 60 }, { 60, 61 }, { 61, 62 }, { 62, 63 }, { 63, 64 }, { 64, 65 }, { 42, 66 }, { 65, 66 }, { 66, 67 }, { 67, 68 }, { 68, 69 }, { 69, 70 }, { 70, 71 }, { 48, 71 },
  1114. { 48, 72 }, { 54, 78 }, { 60, 84 }, { 66, 90 }, { 72, 96 }, { 78, 102 }, { 84, 108 }, { 90, 114 }, { 96, 120 }, { 102, 126 }, { 108, 132 }, { 114, 138 }, { 120, 144 }, { 126, 144 },
  1115. { 132, 144 }, { 138, 144 }, { 155, 168 }, { 0, 155 }, { 167, 168 }, { 166, 167 }, { 165, 166 }, { 164, 165 }, { 6, 163 }, { 163, 164 }, { 162, 163 }, { 161, 162 }, { 160, 161 }, { 159, 160 },
  1116. { 145, 159 }, { 12, 146 }, { 145, 146 }, { 146, 147 }, { 147, 148 }, { 148, 149 }, { 149, 150 }, { 150, 151 }, { 18, 152 }, { 151, 152 }, { 152, 153 }, { 153, 154 }, { 154, 158 }, { 157, 158 },
  1117. { 156, 157 }, { 155, 156 }, { 155, 169 }, { 152, 175 }, { 146, 181 }, { 163, 187 }, { 169, 193 }, { 193, 194 }, { 194, 195 }, { 195, 196 }, { 196, 197 }, { 197, 198 }, { 175, 199 }, { 198, 199 },
  1118. { 199, 200 }, { 200, 201 }, { 201, 202 }, { 202, 203 }, { 203, 204 }, { 181, 205 }, { 204, 205 }, { 205, 206 }, { 206, 207 }, { 207, 208 }, { 208, 209 }, { 209, 210 }, { 187, 211 }, { 210, 211 },
  1119. { 211, 212 }, { 212, 213 }, { 213, 214 }, { 214, 215 }, { 215, 216 }, { 193, 216 }, { 193, 217 }, { 199, 223 }, { 205, 229 }, { 211, 235 }, { 217, 241 }, { 223, 247 }, { 229, 253 }, { 235, 259 },
  1120. { 241, 265 }, { 247, 271 }, { 253, 277 }, { 259, 283 }, { 265, 289 }, { 271, 289 }, { 277, 289 }, { 283, 289 },
  1121. };
  1122. void StudioModel::drawCapsule( Vector const &bbmin, Vector const &bbmax, float flRadius, const matrix3x4_t& m, float const *interiorcolor, float const *wirecolor )
  1123. {
  1124. Vector vecCapsuleCoreNormal = ( bbmin - bbmax ).Normalized();
  1125. matrix3x4_t matCapsuleRotationSpace;
  1126. VectorMatrix( Vector(0,0,1), matCapsuleRotationSpace );
  1127. matrix3x4_t matCapsuleSpace;
  1128. VectorMatrix( vecCapsuleCoreNormal, matCapsuleSpace );
  1129. Vector v[CAPSULE_VERTS];
  1130. for ( int i=0; i<CAPSULE_VERTS; i++ )
  1131. {
  1132. Vector vecCapsuleVert = Vector( g_capsuleVertPositions[i][0], g_capsuleVertPositions[i][1], g_capsuleVertPositions[i][2] );
  1133. VectorRotate( vecCapsuleVert, matCapsuleRotationSpace, vecCapsuleVert );
  1134. VectorRotate( vecCapsuleVert, matCapsuleSpace, vecCapsuleVert );
  1135. vecCapsuleVert *= flRadius;
  1136. if ( i < CAPSULE_VERTS/2 )
  1137. {
  1138. vecCapsuleVert += bbmin;
  1139. }
  1140. else
  1141. {
  1142. vecCapsuleVert += bbmax;
  1143. }
  1144. VectorTransform( vecCapsuleVert, m, v[i] );
  1145. }
  1146. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1147. pRenderContext->Bind( g_materialBones );
  1148. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  1149. CMeshBuilder meshBuilder;
  1150. for ( int i=0; i<CAPSULE_LINES; i++ )
  1151. {
  1152. meshBuilder.Begin( pMesh, MATERIAL_LINES, 2 );
  1153. meshBuilder.Position3fv (v[g_capsuleLineIndices[i][0]].Base());
  1154. meshBuilder.Color4fv( wirecolor );
  1155. meshBuilder.AdvanceVertex();
  1156. meshBuilder.Position3fv (v[g_capsuleLineIndices[i][1]].Base());
  1157. meshBuilder.Color4fv( wirecolor );
  1158. meshBuilder.AdvanceVertex();
  1159. meshBuilder.End();
  1160. }
  1161. pMesh->Draw();
  1162. pRenderContext->Bind( g_pAlpha );
  1163. meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, CAPSULE_TRIS );
  1164. for ( int i=0; i<CAPSULE_TRIS; i++ )
  1165. {
  1166. meshBuilder.Position3fv (v[g_capsuleTriIndices[i][2]].Base());
  1167. meshBuilder.Color4fv( interiorcolor );
  1168. meshBuilder.AdvanceVertex();
  1169. meshBuilder.Position3fv (v[g_capsuleTriIndices[i][1]].Base());
  1170. meshBuilder.Color4fv( interiorcolor );
  1171. meshBuilder.AdvanceVertex();
  1172. meshBuilder.Position3fv (v[g_capsuleTriIndices[i][0]].Base());
  1173. meshBuilder.Color4fv( interiorcolor );
  1174. meshBuilder.AdvanceVertex();
  1175. }
  1176. meshBuilder.End();
  1177. pMesh->Draw();
  1178. }
  1179. //-----------------------------------------------------------------------------
  1180. // Draws a transparent box with a wireframe outline
  1181. //-----------------------------------------------------------------------------
  1182. void StudioModel::drawTransparentBox( Vector const &bbmin, Vector const &bbmax,
  1183. const matrix3x4_t& m, float const *color, float const *wirecolor )
  1184. {
  1185. Vector v[8], v2[8];
  1186. v[0][0] = bbmin[0];
  1187. v[0][1] = bbmax[1];
  1188. v[0][2] = bbmin[2];
  1189. v[1][0] = bbmin[0];
  1190. v[1][1] = bbmin[1];
  1191. v[1][2] = bbmin[2];
  1192. v[2][0] = bbmax[0];
  1193. v[2][1] = bbmax[1];
  1194. v[2][2] = bbmin[2];
  1195. v[3][0] = bbmax[0];
  1196. v[3][1] = bbmin[1];
  1197. v[3][2] = bbmin[2];
  1198. v[4][0] = bbmax[0];
  1199. v[4][1] = bbmax[1];
  1200. v[4][2] = bbmax[2];
  1201. v[5][0] = bbmax[0];
  1202. v[5][1] = bbmin[1];
  1203. v[5][2] = bbmax[2];
  1204. v[6][0] = bbmin[0];
  1205. v[6][1] = bbmax[1];
  1206. v[6][2] = bbmax[2];
  1207. v[7][0] = bbmin[0];
  1208. v[7][1] = bbmin[1];
  1209. v[7][2] = bbmax[2];
  1210. VectorTransform (v[0], m, v2[0]);
  1211. VectorTransform (v[1], m, v2[1]);
  1212. VectorTransform (v[2], m, v2[2]);
  1213. VectorTransform (v[3], m, v2[3]);
  1214. VectorTransform (v[4], m, v2[4]);
  1215. VectorTransform (v[5], m, v2[5]);
  1216. VectorTransform (v[6], m, v2[6]);
  1217. VectorTransform (v[7], m, v2[7]);
  1218. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1219. pRenderContext->Bind( g_pAlpha );
  1220. drawBox( v2, color );
  1221. pRenderContext->Bind( g_materialBones );
  1222. drawWireframeBox( v2, wirecolor );
  1223. }
  1224. void StudioModel::UpdateStudioRenderConfig( bool bWireframe, bool bZBufferWireframe, bool bNormals, bool bTangentFrame )
  1225. {
  1226. StudioRenderConfig_t config;
  1227. memset( &config, 0, sizeof( config ) );
  1228. config.fEyeShiftX = 0.0f;
  1229. config.fEyeShiftY = 0.0f;
  1230. config.fEyeShiftZ = 0.0f;
  1231. config.fEyeSize = 0;
  1232. config.drawEntities = 1;
  1233. config.skin = 0;
  1234. config.fullbright = 0;
  1235. config.bEyeMove = true;
  1236. config.bWireframe = bWireframe;
  1237. if ( g_viewerSettings.renderMode == RM_WIREFRAME || g_viewerSettings.softwareSkin || config.bWireframe || bNormals || bTangentFrame )
  1238. {
  1239. config.bSoftwareSkin = true;
  1240. }
  1241. else
  1242. {
  1243. config.bSoftwareSkin = false;
  1244. }
  1245. config.bSoftwareLighting = false;
  1246. config.bNoHardware = false;
  1247. config.bNoSoftware = false;
  1248. config.bTeeth = true;
  1249. config.bEyes = true;
  1250. config.bFlex = true;
  1251. config.bDrawNormals = bNormals;
  1252. config.bDrawTangentFrame = bTangentFrame;
  1253. config.bDrawZBufferedWireframe = bZBufferWireframe;
  1254. config.bShowEnvCubemapOnly = false;
  1255. g_pStudioRender->UpdateConfig( config );
  1256. MaterialSystem_Config_t matSysConfig = g_pMaterialSystem->GetCurrentConfigForVideoCard();
  1257. extern void InitMaterialSystemConfig(MaterialSystem_Config_t *pConfig);
  1258. InitMaterialSystemConfig( &matSysConfig );
  1259. matSysConfig.nFullbright = 0;
  1260. if( g_viewerSettings.renderMode == RM_SMOOTHSHADED )
  1261. {
  1262. matSysConfig.nFullbright = 2;
  1263. }
  1264. if ( g_dxlevel != 0 )
  1265. {
  1266. matSysConfig.dxSupportLevel = g_dxlevel;
  1267. }
  1268. g_pMaterialSystem->OverrideConfig( matSysConfig, false );
  1269. }
  1270. //-----------------------------------------------------------------------------
  1271. // Draws the skeleton
  1272. //-----------------------------------------------------------------------------
  1273. void StudioModel::DrawBones( )
  1274. {
  1275. // draw bones
  1276. if (!g_viewerSettings.showBones && (g_viewerSettings.highlightBone < 0))
  1277. return;
  1278. CStudioHdr *pStudioHdr = GetStudioHdr();
  1279. const mstudiobone_t *pbones = pStudioHdr->pBone( 0 );
  1280. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1281. pRenderContext->Bind( g_materialBones );
  1282. IMesh* pMesh = pRenderContext->GetDynamicMesh( );
  1283. CMeshBuilder meshBuilder;
  1284. bool drawRed = (g_viewerSettings.highlightBone >= 0);
  1285. for (int i = 0; i < pStudioHdr->numbones(); i++)
  1286. {
  1287. if ( !(pStudioHdr->pBone( i )->flags & BoneMask()))
  1288. continue;
  1289. if ( pbones[i].parent >= 0 )
  1290. {
  1291. int j = pbones[i].parent;
  1292. if ( (g_viewerSettings.highlightBone < 0 ) || (j == g_viewerSettings.highlightBone) )
  1293. {
  1294. drawTransform( m_pBoneToWorld[i], g_viewerSettings.originAxisLength * 0.1f );
  1295. meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
  1296. if (drawRed)
  1297. meshBuilder.Color3ub( 255, 255, 0 );
  1298. else
  1299. meshBuilder.Color3ub( 0, 255, 255 );
  1300. meshBuilder.Position3f( m_pBoneToWorld[j][0][3], m_pBoneToWorld[j][1][3], m_pBoneToWorld[j][2][3]);
  1301. meshBuilder.AdvanceVertex();
  1302. if (drawRed)
  1303. meshBuilder.Color3ub( 255, 255, 0 );
  1304. else
  1305. meshBuilder.Color3ub( 0, 255, 255 );
  1306. meshBuilder.Position3f( m_pBoneToWorld[i][0][3], m_pBoneToWorld[i][1][3], m_pBoneToWorld[i][2][3]);
  1307. meshBuilder.AdvanceVertex();
  1308. meshBuilder.End();
  1309. pMesh->Draw();
  1310. }
  1311. }
  1312. if (g_viewerSettings.highlightBone >= 0)
  1313. {
  1314. if (i != g_viewerSettings.highlightBone)
  1315. continue;
  1316. }
  1317. drawTransform( m_pBoneToWorld[i], g_viewerSettings.originAxisLength * 0.4f );
  1318. }
  1319. if ( g_viewerSettings.showBoneNames )
  1320. {
  1321. for (int i = 0; i < pStudioHdr->numbones(); i++)
  1322. {
  1323. if ( g_viewerSettings.highlightBone >= 0 && i != g_viewerSettings.highlightBone )
  1324. continue;
  1325. char szBoneName[128] = "~"; // a silly bone icon
  1326. V_strcat_safe( szBoneName, pbones[i].pszName() );
  1327. drawText( m_pBoneToWorld[i].GetOrigin(), szBoneName );
  1328. }
  1329. }
  1330. // manadatory to access correct verts
  1331. SetCurrentModel();
  1332. // highlight used vertices with point
  1333. /*
  1334. if (g_viewerSettings.highlightBone >= 0)
  1335. {
  1336. int k, j, n;
  1337. for (i = 0; i < pStudioHdr->numbodyparts; i++)
  1338. {
  1339. for (j = 0; j < pStudioHdr->pBodypart( i )->nummodels; j++)
  1340. {
  1341. mstudiomodel_t *pModel = pStudioHdr->pBodypart( i )->pModel( j );
  1342. const mstudio_modelvertexdata_t *vertData = pModel->GetVertexData();
  1343. Assert( vertData ); // This can only return NULL on X360 for now
  1344. meshBuilder.Begin( pMesh, MATERIAL_POINTS, 1 );
  1345. for (k = 0; k < pModel->numvertices; k++)
  1346. {
  1347. for (n = 0; n < vertData->BoneWeights( k )->numbones; n++)
  1348. {
  1349. if (vertData->BoneWeights( k )->bone[n] == g_viewerSettings.highlightBone)
  1350. {
  1351. Vector tmp;
  1352. Transform( *vertData->Position( k ), vertData->BoneWeights( k ), tmp );
  1353. meshBuilder.Color3ub( 0, 255, 255 );
  1354. meshBuilder.Position3f( tmp.x, tmp.y, tmp.z );
  1355. meshBuilder.AdvanceVertex();
  1356. break;
  1357. }
  1358. }
  1359. }
  1360. meshBuilder.End();
  1361. pMesh->Draw();
  1362. }
  1363. }
  1364. }
  1365. */
  1366. }
  1367. //-----------------------------------------------------------------------------
  1368. // Draws attachments
  1369. //-----------------------------------------------------------------------------
  1370. void StudioModel::DrawAttachments( )
  1371. {
  1372. if ( !g_viewerSettings.showAttachments )
  1373. return;
  1374. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1375. pRenderContext->Bind( g_materialBones );
  1376. CStudioHdr *pStudioHdr = GetStudioHdr();
  1377. for (int i = 0; i < pStudioHdr->GetNumAttachments(); i++)
  1378. {
  1379. mstudioattachment_t &pattachments = (mstudioattachment_t &)pStudioHdr->pAttachment( i );
  1380. matrix3x4_t world;
  1381. ConcatTransforms( m_pBoneToWorld[ pStudioHdr->GetAttachmentBone( i ) ], pattachments.local, world );
  1382. drawTransform( world, g_viewerSettings.originAxisLength * 0.4f );
  1383. }
  1384. }
  1385. //-----------------------------------------------------------------------------
  1386. // Draws Axis
  1387. //-----------------------------------------------------------------------------
  1388. void StudioModel::DrawOriginAxis( )
  1389. {
  1390. if ( !g_viewerSettings.showOriginAxis )
  1391. return;
  1392. const float fAxisLength = g_viewerSettings.originAxisLength;
  1393. if ( fAxisLength <= 0.0f )
  1394. return;
  1395. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1396. pRenderContext->Bind( g_materialBones );
  1397. pRenderContext->MatrixMode(MATERIAL_MODEL);
  1398. pRenderContext->PushMatrix();;
  1399. pRenderContext->LoadIdentity();
  1400. pRenderContext->MatrixMode(MATERIAL_VIEW);
  1401. pRenderContext->PushMatrix();;
  1402. pRenderContext->LoadIdentity();
  1403. pRenderContext->MatrixMode( MATERIAL_VIEW );
  1404. pRenderContext->LoadIdentity( );
  1405. pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
  1406. pRenderContext->Rotate( -90, 0, 0, 1 );
  1407. pRenderContext->Translate( -g_pStudioModel->m_origin[0], -g_pStudioModel->m_origin[1], -g_pStudioModel->m_origin[2] );
  1408. pRenderContext->Rotate( g_pStudioModel->m_angles[1], 0, 0, 1 );
  1409. pRenderContext->Rotate( g_pStudioModel->m_angles[0], 0, 1, 0 );
  1410. pRenderContext->Rotate( g_pStudioModel->m_angles[2], 1, 0, 0 );
  1411. IMesh *pMesh = pRenderContext->GetDynamicMesh( );
  1412. CMeshBuilder meshBuilder;
  1413. meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
  1414. meshBuilder.Position3f( 0.0f, 0.0f, 0.0f );
  1415. meshBuilder.Color4ub( 255, 0, 0, 255 );
  1416. meshBuilder.AdvanceVertex();
  1417. meshBuilder.Position3f( fAxisLength, 0.0f, 0.0f );
  1418. meshBuilder.Color4ub( 255, 0, 0, 255 );
  1419. meshBuilder.AdvanceVertex();
  1420. meshBuilder.Position3f( 0.0f, 0.0f, 0.0f );
  1421. meshBuilder.Color4ub( 0, 255, 0, 255 );
  1422. meshBuilder.AdvanceVertex();
  1423. meshBuilder.Position3f( 0.0f, fAxisLength, 0.0f );
  1424. meshBuilder.Color4ub( 0, 255, 0, 255 );
  1425. meshBuilder.AdvanceVertex();
  1426. meshBuilder.Position3f( 0.0f, 0.0f, 0.0f );
  1427. meshBuilder.Color4ub( 0, 0, 255, 255 );
  1428. meshBuilder.AdvanceVertex();
  1429. meshBuilder.Position3f( 0.0f, 0.0f, fAxisLength );
  1430. meshBuilder.Color4ub( 0, 0, 255, 255 );
  1431. meshBuilder.AdvanceVertex();
  1432. meshBuilder.End();
  1433. pMesh->Draw();
  1434. pRenderContext->MatrixMode(MATERIAL_MODEL);
  1435. pRenderContext->PopMatrix();
  1436. pRenderContext->MatrixMode(MATERIAL_VIEW);
  1437. pRenderContext->PopMatrix();
  1438. }
  1439. void StudioModel::DrawEditAttachment()
  1440. {
  1441. CStudioHdr *pStudioHdr = GetStudioHdr();
  1442. int iEditAttachment = g_viewerSettings.m_iEditAttachment;
  1443. if ( iEditAttachment >= 0 && iEditAttachment < pStudioHdr->GetNumAttachments() )
  1444. {
  1445. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1446. pRenderContext->Bind( g_materialBones );
  1447. mstudioattachment_t &pAttachment = (mstudioattachment_t &)pStudioHdr->pAttachment( iEditAttachment );
  1448. matrix3x4_t world;
  1449. ConcatTransforms( m_pBoneToWorld[ pStudioHdr->GetAttachmentBone( iEditAttachment ) ], pAttachment.local, world );
  1450. drawTransform( world, g_viewerSettings.originAxisLength * 0.4f );
  1451. }
  1452. }
  1453. //-----------------------------------------------------------------------------
  1454. // Draws hitboxes
  1455. //-----------------------------------------------------------------------------
  1456. static float hullcolor[8][4] =
  1457. {
  1458. { 1.0, 1.0, 1.0, 1.0 },
  1459. { 1.0, 0.5, 0.5, 1.0 },
  1460. { 0.5, 1.0, 0.5, 1.0 },
  1461. { 1.0, 1.0, 0.5, 1.0 },
  1462. { 0.5, 0.5, 1.0, 1.0 },
  1463. { 1.0, 0.5, 1.0, 1.0 },
  1464. { 0.5, 1.0, 1.0, 1.0 },
  1465. { 1.0, 1.0, 1.0, 1.0 }
  1466. };
  1467. void StudioModel::DrawHitboxes( )
  1468. {
  1469. CStudioHdr *pStudioHdr = GetStudioHdr();
  1470. if (!g_pAlpha)
  1471. {
  1472. g_pAlpha = g_pMaterialSystem->FindMaterial("debug/debughitbox", TEXTURE_GROUP_OTHER, false);
  1473. }
  1474. if (g_viewerSettings.showHitBoxes || (g_viewerSettings.highlightHitbox >= 0))
  1475. {
  1476. int hitboxset = g_MDLViewer->GetCurrentHitboxSet();
  1477. bool bDrawWidget = false;
  1478. matrix3x4_t matWidgetSaved;
  1479. Vector vecWidgetPosSaved;
  1480. HitboxList_t &list = g_pStudioModel->m_HitboxSets[ hitboxset ].m_Hitboxes;
  1481. for (unsigned short j = list.Head(); j != list.InvalidIndex(); j = list.Next(j) )
  1482. {
  1483. mstudiobbox_t *pBBox = &list[j].m_BBox;
  1484. float interiorcolor[4];
  1485. int c = pBBox->group % 8;
  1486. interiorcolor[0] = hullcolor[c][0] * 0.7;
  1487. interiorcolor[1] = hullcolor[c][1] * 0.7;
  1488. interiorcolor[2] = hullcolor[c][2] * 0.7;
  1489. interiorcolor[3] = hullcolor[c][3] * 0.4;
  1490. matrix3x4_t hitboxMatrix;
  1491. AngleMatrix( pBBox->angOffsetOrientation, hitboxMatrix);
  1492. MatrixMultiply( m_pBoneToWorld[ pBBox->bone ], hitboxMatrix, hitboxMatrix );
  1493. matrix3x4_t hitboxMatrixPlusWidgetRotation;
  1494. hitboxMatrixPlusWidgetRotation = hitboxMatrix;
  1495. Vector bbMinPreview = pBBox->bbmin;
  1496. Vector bbMaxPreview = pBBox->bbmax;
  1497. float flWidgetDelta = g_pWidgetControl->m_vecWidgetDeltaCoord.x * 0.1f;
  1498. if ( g_pWidgetControl->m_WidgetState != WIDGET_STATE_NONE )
  1499. {
  1500. Vector vecDelta;
  1501. vecDelta.Init();
  1502. if ( g_pWidgetControl->m_WidgetState == WIDGET_CHANGE_X )
  1503. vecDelta.x = flWidgetDelta;
  1504. else if ( g_pWidgetControl->m_WidgetState == WIDGET_CHANGE_Z )
  1505. vecDelta.y = flWidgetDelta;
  1506. else if ( g_pWidgetControl->m_WidgetState == WIDGET_CHANGE_Y )
  1507. vecDelta.z = flWidgetDelta;
  1508. g_pWidgetControl->m_vecValue = vecDelta;
  1509. }
  1510. //show unselected hitboxes faintly
  1511. if ( (g_viewerSettings.highlightHitbox >= 0) && (g_viewerSettings.highlightHitbox != j) )
  1512. {
  1513. float interiorcolorDim[4];
  1514. float wirecolorDim[4];
  1515. for ( int i=0; i<4; i++ )
  1516. {
  1517. interiorcolorDim[i] = interiorcolor[i] * 0.6;
  1518. wirecolorDim[i] = hullcolor[ c ][i] * 0.6;
  1519. }
  1520. if ( pBBox->flCapsuleRadius > 0 )
  1521. {
  1522. drawCapsule( pBBox->bbmin, pBBox->bbmax, pBBox->flCapsuleRadius, hitboxMatrix, interiorcolorDim, wirecolorDim );
  1523. }
  1524. else
  1525. {
  1526. drawTransparentBox( pBBox->bbmin, pBBox->bbmax, hitboxMatrix, interiorcolorDim, wirecolorDim );
  1527. }
  1528. }
  1529. else if ( (g_viewerSettings.highlightHitbox >= 0) && (g_viewerSettings.highlightHitbox == j) )
  1530. {
  1531. //selected hitbox
  1532. if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_ROTATION )
  1533. {
  1534. g_pWidgetControl->m_WidgetType = WIDGET_ROTATE;
  1535. QAngle storedValue = QAngle( g_pWidgetControl->m_vecValue.x, g_pWidgetControl->m_vecValue.y, g_pWidgetControl->m_vecValue.z );
  1536. if ( g_pWidgetControl->m_WidgetState == WIDGET_STATE_NONE && g_pWidgetControl->HasStoredValue() )
  1537. {
  1538. pBBox->angOffsetOrientation += storedValue;
  1539. g_pWidgetControl->m_vecValue.Init();
  1540. }
  1541. AngleMatrix( pBBox->angOffsetOrientation + storedValue, hitboxMatrixPlusWidgetRotation);
  1542. MatrixMultiply( m_pBoneToWorld[ pBBox->bone ], hitboxMatrixPlusWidgetRotation, hitboxMatrixPlusWidgetRotation );
  1543. }
  1544. else if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMIN || g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMAX )
  1545. {
  1546. g_pWidgetControl->m_WidgetType = WIDGET_TRANSLATE;
  1547. Vector vecValueSwizzleZXY = Vector( g_pWidgetControl->m_vecValue.z, g_pWidgetControl->m_vecValue.x, g_pWidgetControl->m_vecValue.y );
  1548. if ( g_pWidgetControl->m_WidgetState == WIDGET_STATE_NONE && g_pWidgetControl->HasStoredValue() )
  1549. {
  1550. if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMIN )
  1551. pBBox->bbmin += vecValueSwizzleZXY;
  1552. if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMAX )
  1553. pBBox->bbmax += vecValueSwizzleZXY;
  1554. g_pWidgetControl->m_vecValue.Init();
  1555. }
  1556. if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMIN )
  1557. bbMinPreview += vecValueSwizzleZXY;
  1558. if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMAX )
  1559. bbMaxPreview += vecValueSwizzleZXY;
  1560. }
  1561. if ( pBBox->flCapsuleRadius > 0 )
  1562. {
  1563. drawCapsule( bbMinPreview, bbMaxPreview, pBBox->flCapsuleRadius, hitboxMatrixPlusWidgetRotation, interiorcolor, hullcolor[c] );
  1564. }
  1565. else
  1566. {
  1567. drawTransparentBox( bbMinPreview, bbMaxPreview, hitboxMatrixPlusWidgetRotation, interiorcolor, hullcolor[ c ] );
  1568. }
  1569. bDrawWidget = true;
  1570. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1571. pRenderContext->GetMatrix( MATERIAL_VIEW, &matWidgetSaved );
  1572. MatrixMultiply( matWidgetSaved, hitboxMatrixPlusWidgetRotation, matWidgetSaved );
  1573. if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMIN )
  1574. {
  1575. vecWidgetPosSaved = bbMinPreview;
  1576. }
  1577. else if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMAX )
  1578. {
  1579. vecWidgetPosSaved = bbMaxPreview;
  1580. }
  1581. }
  1582. else
  1583. {
  1584. if ( pBBox->flCapsuleRadius > 0 )
  1585. {
  1586. drawCapsule( pBBox->bbmin, pBBox->bbmax, pBBox->flCapsuleRadius, hitboxMatrix, interiorcolor, hullcolor[ c ] );
  1587. }
  1588. else
  1589. {
  1590. drawTransparentBox( pBBox->bbmin, pBBox->bbmax, hitboxMatrix, interiorcolor, hullcolor[ c ] );
  1591. }
  1592. }
  1593. }
  1594. if ( bDrawWidget && g_pWidgetControl->GetWidgetModel() )
  1595. {
  1596. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1597. pRenderContext->MatrixMode(MATERIAL_VIEW);
  1598. pRenderContext->PushMatrix();
  1599. pRenderContext->LoadMatrix( matWidgetSaved );
  1600. if ( g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMIN || g_viewerSettings.hitboxEditMode == HITBOX_EDIT_BBMAX )
  1601. {
  1602. pRenderContext->Translate( vecWidgetPosSaved.x, vecWidgetPosSaved.y, vecWidgetPosSaved.z );
  1603. }
  1604. g_pWidgetControl->GetWidgetModel()->DrawWidgetModel( );
  1605. pRenderContext->MatrixMode(MATERIAL_VIEW);
  1606. pRenderContext->PopMatrix();
  1607. }
  1608. }
  1609. /*
  1610. float color2[] = { 0, 0.7, 1, 0.6 };
  1611. float wirecolor2[] = { 0, 1, 1, 1.0 };
  1612. drawTransparentBox( pStudioHdr->min, pStudioHdr->max, g_viewtransform, color2, wirecolor2 );
  1613. */
  1614. if (g_viewerSettings.showSequenceBoxes)
  1615. {
  1616. float color[] = { 0.7, 1, 0, 0.6 };
  1617. float wirecolor[] = { 1, 1, 0, 1.0 };
  1618. drawTransparentBox( pStudioHdr->pSeqdesc( m_sequence ).bbmin, pStudioHdr->pSeqdesc( m_sequence ).bbmax, g_viewtransform, color, wirecolor );
  1619. }
  1620. }
  1621. void StudioModel::DrawIllumPosition( )
  1622. {
  1623. if( !g_viewerSettings.showIllumPosition )
  1624. return;
  1625. CStudioHdr *pStudioHdr = GetStudioHdr();
  1626. Vector modelPt0;
  1627. Vector modelPt1;
  1628. Vector worldPt0;
  1629. Vector worldPt1;
  1630. // draw axis through illum position
  1631. VectorCopy(pStudioHdr->illumposition(), modelPt0);
  1632. VectorCopy(pStudioHdr->illumposition(), modelPt1);
  1633. modelPt0.x -= 4;
  1634. modelPt1.x += 4;
  1635. VectorTransform (modelPt0, g_viewtransform, worldPt0);
  1636. VectorTransform (modelPt1, g_viewtransform, worldPt1);
  1637. drawLine( worldPt0, worldPt1, 255, 0, 0 );
  1638. VectorCopy(pStudioHdr->illumposition(), modelPt0);
  1639. VectorCopy(pStudioHdr->illumposition(), modelPt1);
  1640. modelPt0.y -= 4;
  1641. modelPt1.y += 4;
  1642. VectorTransform (modelPt0, g_viewtransform, worldPt0);
  1643. VectorTransform (modelPt1, g_viewtransform, worldPt1);
  1644. drawLine( worldPt0, worldPt1, 0, 255, 0 );
  1645. VectorCopy(pStudioHdr->illumposition(), modelPt0);
  1646. VectorCopy(pStudioHdr->illumposition(), modelPt1);
  1647. modelPt0.z -= 4;
  1648. modelPt1.z += 4;
  1649. VectorTransform (modelPt0, g_viewtransform, worldPt0);
  1650. VectorTransform (modelPt1, g_viewtransform, worldPt1);
  1651. drawLine( worldPt0, worldPt1, 0, 0, 255 );
  1652. }
  1653. //-----------------------------------------------------------------------------
  1654. // Draws the physics model
  1655. //-----------------------------------------------------------------------------
  1656. void StudioModel::DrawPhysicsModel( )
  1657. {
  1658. if (!g_viewerSettings.showPhysicsModel)
  1659. return;
  1660. if ( g_viewerSettings.renderMode == RM_WIREFRAME )
  1661. {
  1662. for (int i = 0; i < m_pPhysics->Count(); i++)
  1663. {
  1664. CPhysmesh *pmesh = m_pPhysics->GetMesh(i);
  1665. int boneIndex = FindBone(pmesh->m_boneName);
  1666. // show the convex pieces in solid
  1667. DrawPhysConvex( pmesh, boneIndex, g_materialFlatshaded );
  1668. }
  1669. }
  1670. else
  1671. {
  1672. for (int i = 0; i < m_pPhysics->Count(); i++)
  1673. {
  1674. float red[] = { 1.0, 0, 0, 0.25 };
  1675. float yellow[] = { 1.0, 1.0, 0, 0.5 };
  1676. CPhysmesh *pmesh = m_pPhysics->GetMesh(i);
  1677. int boneIndex = FindBone(pmesh->m_boneName);
  1678. if ( boneIndex >= 0 )
  1679. {
  1680. constraint_ragdollparams_t *pConstraintInfo = &pmesh->m_constraint;
  1681. if ( (i+1) == g_viewerSettings.highlightPhysicsBone )
  1682. {
  1683. DrawPhysmesh( pmesh, boneIndex, g_materialBones, red );
  1684. if ( pConstraintInfo )
  1685. {
  1686. DrawRangeOfMotionArcs( pmesh, boneIndex, g_materialArcActive );
  1687. }
  1688. }
  1689. else
  1690. {
  1691. if ( g_viewerSettings.highlightPhysicsBone < 1 )
  1692. {
  1693. // yellow for most
  1694. DrawPhysmesh( pmesh, boneIndex, g_materialBones, yellow );
  1695. if ( pConstraintInfo )
  1696. {
  1697. DrawRangeOfMotionArcs( pmesh, boneIndex, g_materialArcInActive );
  1698. }
  1699. }
  1700. }
  1701. }
  1702. else
  1703. {
  1704. DrawPhysmesh( pmesh, -1, g_materialBones, red );
  1705. }
  1706. }
  1707. }
  1708. }
  1709. void StudioModel::DrawSoftbody()
  1710. {
  1711. if ( CSoftbody *pSoftbody = GetSoftbody() )
  1712. {
  1713. {
  1714. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1715. pRenderContext->Bind( g_materialFlatshaded );
  1716. IMesh* pMatMesh = pRenderContext->GetDynamicMesh();
  1717. pSoftbody->Draw( g_viewerSettings.softbodyDrawOptions, pMatMesh );
  1718. pMatMesh->Draw();
  1719. }
  1720. /*
  1721. if ( g_viewerSettings.softbodyDrawOptions.m_nLayers & RN_SOFTBODY_DRAW_INDICES )
  1722. {
  1723. const VectorAligned *pPos = pSoftbody->GetNodePositions();
  1724. for ( uint i = 0; i < pSoftbody->GetNodeCount(); ++i )
  1725. {
  1726. }
  1727. }
  1728. */
  1729. }
  1730. }
  1731. void StudioModel::SetViewTarget( void )
  1732. {
  1733. // only valid if the attachment bones are used
  1734. if ((BoneMask() & BONE_USED_BY_ATTACHMENT) == 0)
  1735. {
  1736. return;
  1737. }
  1738. int iEyeAttachment = LookupAttachment( "eyes" );
  1739. if (iEyeAttachment == -1)
  1740. return;
  1741. Vector local;
  1742. Vector tmp;
  1743. // look forward
  1744. CStudioHdr *pStudioHdr = GetStudioHdr();
  1745. mstudioattachment_t &patt = (mstudioattachment_t &)pStudioHdr->pAttachment( iEyeAttachment );
  1746. matrix3x4_t attToWorld;
  1747. ConcatTransforms( m_pBoneToWorld[ pStudioHdr->GetAttachmentBone( iEyeAttachment ) ], patt.local, attToWorld );
  1748. local = Vector( 32, 0, 0 );
  1749. Vector vEyes;
  1750. MatrixPosition( attToWorld, vEyes );
  1751. // aim the eyes if there's a target
  1752. if (m_vecHeadTargets.Count() > 0 && !m_vecHeadTargets.Tail().m_bSelf)
  1753. {
  1754. VectorITransform( m_vecHeadTargets.Tail().m_vecPosition - vEyes, attToWorld, local );
  1755. }
  1756. float flDist = local.Length();
  1757. VectorNormalize( local );
  1758. // calculate animated eye deflection
  1759. Vector eyeDeflect;
  1760. QAngle eyeAng( GetFlexController("eyes_updown"), GetFlexController("eyes_rightleft"), 0 );
  1761. // debugoverlay->AddTextOverlay( m_vecOrigin + Vector( 0, 0, 64 ), 0, 0, "%.2f %.2f", eyeAng.x, eyeAng.y );
  1762. AngleVectors( eyeAng, &eyeDeflect );
  1763. eyeDeflect.x = 0;
  1764. // reduce deflection the more the eye is off center
  1765. // FIXME: this angles make no damn sense
  1766. eyeDeflect = eyeDeflect * (local.x * local.x);
  1767. local = local + eyeDeflect;
  1768. VectorNormalize( local );
  1769. // check to see if the eye is aiming outside the max eye deflection
  1770. float flMaxEyeDeflection = pStudioHdr->MaxEyeDeflection();
  1771. if ( local.x < flMaxEyeDeflection )
  1772. {
  1773. // if so, clamp it to 30 degrees offset
  1774. // debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), 1, 0, "%5.3f %5.3f %5.3f", local.x, local.y, local.z );
  1775. local.x = 0;
  1776. float d = local.LengthSqr();
  1777. if ( d > 0.0f )
  1778. {
  1779. d = sqrtf( ( 1.0f - flMaxEyeDeflection * flMaxEyeDeflection ) / ( local.y*local.y + local.z*local.z ) );
  1780. local.x = flMaxEyeDeflection;
  1781. local.y = local.y * d;
  1782. local.z = local.z * d;
  1783. }
  1784. else
  1785. {
  1786. local.x = 1.0;
  1787. }
  1788. }
  1789. local = local * flDist;
  1790. VectorTransform( local, attToWorld, tmp );
  1791. g_pStudioRender->SetEyeViewTarget( pStudioHdr->GetRenderHdr(), m_bodynum, tmp );
  1792. }
  1793. float UTIL_VecToYaw( const matrix3x4_t& matrix, const Vector &vec )
  1794. {
  1795. Vector tmp = vec;
  1796. VectorNormalize( tmp );
  1797. float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
  1798. float y = matrix[0][1] * tmp.x + matrix[1][1] * tmp.y + matrix[2][1] * tmp.z;
  1799. if (x == 0.0f && y == 0.0f)
  1800. return 0.0f;
  1801. float yaw = atan2( -y, x );
  1802. yaw = RAD2DEG(yaw);
  1803. if (yaw < 0)
  1804. yaw += 360;
  1805. return yaw;
  1806. }
  1807. float UTIL_VecToPitch( const matrix3x4_t& matrix, const Vector &vec )
  1808. {
  1809. float pitch = 0;
  1810. Vector tmp = vec;
  1811. if ( VectorNormalize( tmp ) > 0 )
  1812. {
  1813. float z = matrix[0][2] * tmp.x + matrix[1][2] * tmp.y + matrix[2][2] * tmp.z;
  1814. pitch = RAD2DEG( asin( -z ) );
  1815. if (pitch < 0)
  1816. pitch += 360;
  1817. }
  1818. return pitch;
  1819. }
  1820. float UTIL_AngleDiff( float destAngle, float srcAngle )
  1821. {
  1822. float delta;
  1823. delta = destAngle - srcAngle;
  1824. if ( destAngle > srcAngle )
  1825. {
  1826. while ( delta >= 180 )
  1827. delta -= 360;
  1828. }
  1829. else
  1830. {
  1831. while ( delta <= -180 )
  1832. delta += 360;
  1833. }
  1834. return delta;
  1835. }
  1836. void StudioModel::UpdateBoneChain(
  1837. Vector pos[],
  1838. Quaternion q[],
  1839. int iBone,
  1840. matrix3x4_t *pBoneToWorld )
  1841. {
  1842. matrix3x4_t bonematrix;
  1843. QuaternionMatrix( q[iBone], pos[iBone], bonematrix );
  1844. CStudioHdr *pStudioHdr = GetStudioHdr();
  1845. int parent = pStudioHdr->pBone( iBone )->parent;
  1846. if (parent == -1)
  1847. {
  1848. ConcatTransforms( g_viewtransform, bonematrix, pBoneToWorld[iBone] );
  1849. }
  1850. else
  1851. {
  1852. // evil recursive!!!
  1853. UpdateBoneChain( pos, q, parent, pBoneToWorld );
  1854. ConcatTransforms( pBoneToWorld[parent], bonematrix, pBoneToWorld[iBone] );
  1855. }
  1856. }
  1857. void StudioModel::GetBodyPoseParametersFromFlex( )
  1858. {
  1859. float flGoal;
  1860. flGoal = GetFlexController( "move_rightleft" );
  1861. SetPoseParameter( "body_trans_Y", flGoal );
  1862. flGoal = GetFlexController( "move_forwardback" );
  1863. SetPoseParameter( "body_trans_X", flGoal );
  1864. flGoal = GetFlexController( "move_updown" );
  1865. SetPoseParameter( "body_lift", flGoal );
  1866. flGoal = GetFlexController( "body_rightleft" ) + GetBodyYaw();
  1867. SetPoseParameter( "body_yaw", flGoal );
  1868. flGoal = GetFlexController( "body_updown" );
  1869. SetPoseParameter( "body_pitch", flGoal );
  1870. flGoal = GetFlexController( "body_tilt" );
  1871. SetPoseParameter( "body_roll", flGoal );
  1872. flGoal = GetFlexController( "chest_rightleft" ) + GetSpineYaw();
  1873. SetPoseParameter( "spine_yaw", flGoal );
  1874. flGoal = GetFlexController( "chest_updown" );
  1875. SetPoseParameter( "spine_pitch", flGoal );
  1876. flGoal = GetFlexController( "chest_tilt" );
  1877. SetPoseParameter( "spine_roll", flGoal );
  1878. flGoal = GetFlexController( "head_forwardback" );
  1879. SetPoseParameter( "neck_trans", flGoal );
  1880. flGoal = GetFlexController( "gesture_updown" );
  1881. SetPoseParameter( "gesture_height", flGoal );
  1882. flGoal = GetFlexController( "gesture_rightleft" );
  1883. SetPoseParameter( "gesture_width", flGoal );
  1884. }
  1885. void StudioModel::CalcHeadRotation( Vector pos[], Quaternion q[] )
  1886. {
  1887. static Vector pos2[MAXSTUDIOBONES];
  1888. static Quaternion q2[MAXSTUDIOBONES];
  1889. if (m_nSolveHeadTurn == 0)
  1890. return;
  1891. if (m_dt == 0.0f)
  1892. {
  1893. m_dt = 0.1;
  1894. }
  1895. // GetAttachment( "eyes", vEyePosition, vEyeAngles );
  1896. int iForwardAttachment = LookupAttachment( "forward" );
  1897. if (iForwardAttachment == -1)
  1898. return;
  1899. CStudioHdr *pStudioHdr = GetStudioHdr();
  1900. mstudioattachment_t &patt = (mstudioattachment_t &)pStudioHdr->pAttachment( iForwardAttachment );
  1901. matrix3x4_t attToWorld;
  1902. int iBone = pStudioHdr->GetAttachmentBone( iForwardAttachment );
  1903. BuildBoneChain( pStudioHdr, g_viewtransform, pos, q, iBone, m_pBoneToWorld );
  1904. ConcatTransforms( m_pBoneToWorld[ iBone ], patt.local, attToWorld );
  1905. Vector vForward;
  1906. VectorRotate( Vector( 1, 0, 0 ), attToWorld, vForward );
  1907. float dt = m_dt;
  1908. if (m_nSolveHeadTurn == 2)
  1909. {
  1910. dt = 0.1;
  1911. }
  1912. Vector vEyes;
  1913. MatrixPosition( attToWorld, vEyes );
  1914. Vector vHead = vForward;
  1915. float flHeadInfluence = 0.0;
  1916. int i;
  1917. for (i = 0; i < m_vecHeadTargets.Count(); i++)
  1918. {
  1919. Vector dir;
  1920. if (m_vecHeadTargets[i].m_bSelf)
  1921. {
  1922. dir = vForward;
  1923. }
  1924. else
  1925. {
  1926. dir = m_vecHeadTargets[i].m_vecPosition - vEyes;
  1927. }
  1928. VectorNormalize( dir );
  1929. float flInterest = m_vecHeadTargets[i].m_flWeight;
  1930. if (flInterest > 0.0)
  1931. {
  1932. if (flHeadInfluence == 0.0)
  1933. {
  1934. vHead = dir;
  1935. flHeadInfluence = flInterest;
  1936. }
  1937. else
  1938. {
  1939. flHeadInfluence = flHeadInfluence * (1 - flInterest) + flInterest;
  1940. float w = flInterest / flHeadInfluence;
  1941. vHead = vHead * (1 - w) + dir * w;
  1942. }
  1943. }
  1944. }
  1945. Vector vTargetDir = Vector( 0, 0, 0 );
  1946. vTargetDir = vForward * (1.0 - flHeadInfluence) + vHead * flHeadInfluence;
  1947. VectorNormalize( vTargetDir );
  1948. SetPoseParameter( "head_pitch", 0.0 );
  1949. SetPoseParameter( "head_yaw", 0.0 );
  1950. SetPoseParameter( "head_roll", 0.0 );
  1951. SetHeadPosition( attToWorld, vTargetDir, dt );
  1952. // Msg( "yaw %f pitch %f\n", vEyeAngles.y, vEyeAngles.x );
  1953. }
  1954. float StudioModel::SetHeadPosition( matrix3x4_t& attToWorld, Vector const &vTargetPos, float dt )
  1955. {
  1956. float flDiff;
  1957. int iPose;
  1958. QAngle vEyeAngles;
  1959. float flMoved = 0.0f;
  1960. matrix3x4a_t targetXform, invAttToWorld;
  1961. matrix3x4_t headXform;
  1962. // align current "forward direction" to target direction
  1963. targetXform = attToWorld;
  1964. Studio_AlignIKMatrix( targetXform, vTargetPos );
  1965. // calc head movement needed
  1966. MatrixInvert( attToWorld, invAttToWorld );
  1967. ConcatTransforms( invAttToWorld, targetXform, headXform );
  1968. MatrixAngles( headXform, vEyeAngles );
  1969. // FIXME: add chest compression
  1970. // Msg( "yaw %f pitch %f\n", vEyeAngles.y, vEyeAngles.x );
  1971. float flMin, flMax;
  1972. #if 1
  1973. //--------------------------------------
  1974. // Set head yaw
  1975. //--------------------------------------
  1976. // flDiff = vEyeAngles.y + GetFlexController( "head_rightleft" );
  1977. iPose = LookupPoseParameter( "head_yaw" );
  1978. GetPoseParameterRange( iPose, &flMin, &flMax );
  1979. flDiff = RangeCompressor( vEyeAngles.y + GetFlexController( "head_rightleft" ), flMin, flMax, 0.0 );
  1980. SetPoseParameter( iPose, flDiff );
  1981. #endif
  1982. #if 1
  1983. //--------------------------------------
  1984. // Set head pitch
  1985. //--------------------------------------
  1986. iPose = LookupPoseParameter( "head_pitch" );
  1987. GetPoseParameterRange( iPose, &flMin, &flMax );
  1988. flDiff = RangeCompressor( vEyeAngles.x + GetFlexController( "head_updown" ), flMin, flMax, 0.0 );
  1989. SetPoseParameter( iPose, flDiff );
  1990. #endif
  1991. #if 1
  1992. //--------------------------------------
  1993. // Set head roll
  1994. //--------------------------------------
  1995. iPose = LookupPoseParameter( "head_roll" );
  1996. GetPoseParameterRange( iPose, &flMin, &flMax );
  1997. flDiff = RangeCompressor( vEyeAngles.z + GetFlexController( "head_tilt" ), flMin, flMax, 0.0 );
  1998. SetPoseParameter( iPose, flDiff );
  1999. #endif
  2000. return flMoved;
  2001. }
  2002. DrawModelInfo_t g_DrawModelInfo;
  2003. DrawModelResults_t g_DrawModelResults;
  2004. bool g_bDrawModelInfoValid = false;
  2005. void StudioModel::GetModelTransform( matrix3x4_t &mat )
  2006. {
  2007. AngleMatrix( m_angles, mat );
  2008. Vector vecModelOrigin;
  2009. VectorMultiply( m_origin, -1.0f, vecModelOrigin );
  2010. MatrixSetColumn( vecModelOrigin, 3, mat );
  2011. }
  2012. void StudioModel::SetModelTransform( const matrix3x4_t &mat )
  2013. {
  2014. m_origin.x = -mat.m_flMatVal[0][3];
  2015. m_origin.y = -mat.m_flMatVal[1][3];
  2016. m_origin.z = -mat.m_flMatVal[2][3];
  2017. MatrixAngles( mat, m_angles );
  2018. }
  2019. /*
  2020. ================
  2021. StudioModel::DrawModel
  2022. inputs:
  2023. currententity
  2024. r_entorigin
  2025. ================
  2026. */
  2027. int StudioModel::DrawModel( bool mergeBones, int nRenderPassMode )
  2028. {
  2029. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  2030. if ( !HasModel())
  2031. return 0;
  2032. CStudioHdr *pStudioHdr = GetStudioHdr();
  2033. g_smodels_total++; // render data cache cookie
  2034. // JasonM & garymcthack - should really only do this once a frame and at init time.
  2035. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  2036. g_viewerSettings.showNormals,
  2037. g_viewerSettings.showTangentFrame );
  2038. // NOTE: UpdateStudioRenderConfig can delete the studio hdr
  2039. // Construct a transform to apply to the model. The camera is stuck in a fixed position
  2040. GetModelTransform( g_viewtransform );
  2041. Vector vecModelOrigin;
  2042. VectorMultiply( m_origin, -1.0f, vecModelOrigin );
  2043. MatrixSetColumn( vecModelOrigin, 3, g_viewtransform );
  2044. // These values HAVE to be sent down for LOD to work correctly.
  2045. Vector viewOrigin, viewRight, viewUp, viewPlaneNormal;
  2046. g_pStudioRender->SetViewState( vec3_origin, Vector(0, 1, 0), Vector(0, 0, 1), Vector( 1, 0, 0 ) );
  2047. // g_pStudioRender->SetEyeViewTarget( viewOrigin );
  2048. SetUpBones( mergeBones );
  2049. SetupLighting( );
  2050. SetViewTarget( );
  2051. extern float g_flexdescweight[MAXSTUDIOFLEXDESC]; // garymcthack
  2052. extern float g_flexdescweight2[MAXSTUDIOFLEXDESC]; // garymcthack
  2053. int i;
  2054. for (i = 0; i < pStudioHdr->numflexdesc(); i++)
  2055. {
  2056. g_flexdescweight[i] = 0.0;
  2057. }
  2058. RunFlexRules( );
  2059. float d = 0.8;
  2060. if (m_dt != 0)
  2061. {
  2062. d = ExponentialDecay( 0.8, 0.033, m_dt );
  2063. }
  2064. float *pFlexWeights = NULL, *pFlexDelayedWeights = NULL;
  2065. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  2066. CMatRenderData< float > rdFlexWeights( pRenderContext );
  2067. CMatRenderData< float > rdDelayedFlexWeights( pRenderContext );
  2068. int nFlexCount = pStudioHdr->numflexdesc();
  2069. if ( nFlexCount )
  2070. {
  2071. pFlexWeights = rdFlexWeights.Lock( nFlexCount );
  2072. pFlexDelayedWeights = rdDelayedFlexWeights.Lock( nFlexCount );
  2073. for ( i = 0; i < nFlexCount; i++ )
  2074. {
  2075. g_flexdescweight2[i] = g_flexdescweight2[i] * d + g_flexdescweight[i] * (1 - d);
  2076. pFlexWeights[i] = g_flexdescweight[i];
  2077. pFlexDelayedWeights[i] = g_flexdescweight2[i];
  2078. }
  2079. }
  2080. // draw
  2081. g_pStudioRender->SetAlphaModulation( 1.0f );
  2082. g_bDrawModelInfoValid = true;
  2083. memset( &g_DrawModelInfo, 0, sizeof( g_DrawModelInfo ) );
  2084. g_DrawModelInfo.m_pStudioHdr = (studiohdr_t *)pStudioHdr->GetRenderHdr();
  2085. g_DrawModelInfo.m_pHardwareData = GetHardwareData();
  2086. if ( !g_DrawModelInfo.m_pHardwareData )
  2087. return 0;
  2088. g_DrawModelInfo.m_Decals = STUDIORENDER_DECAL_INVALID;
  2089. g_DrawModelInfo.m_Skin = m_skinnum;
  2090. g_DrawModelInfo.m_Body = m_bodynum;
  2091. g_DrawModelInfo.m_HitboxSet = g_MDLViewer->GetCurrentHitboxSet();
  2092. g_DrawModelInfo.m_pClientEntity = NULL;
  2093. g_DrawModelInfo.m_Lod = g_viewerSettings.autoLOD ? -1 : g_viewerSettings.lod;
  2094. g_DrawModelInfo.m_pColorMeshes = NULL;
  2095. if( nRenderPassMode == PASS_DEFAULT || nRenderPassMode == PASS_MODELONLY )
  2096. {
  2097. if( g_viewerSettings.renderMode == RM_SHOWBADVERTEXDATA )
  2098. {
  2099. DebugDrawModelBadVerts( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin );
  2100. DebugDrawModelWireframe( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin, Vector( 0.2f, 0.2f, 0.2f ) );
  2101. g_DrawModelInfo.m_Lod = m_LodUsed;
  2102. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  2103. #if 0
  2104. // overlay wireframe
  2105. // Set the state to trigger wireframe rendering
  2106. UpdateStudioRenderConfig( true, true, false, false );
  2107. // Draw wireframe
  2108. count = g_pStudioRender->DrawModel( &g_DrawModelResults, g_DrawModelInfo, m_pBoneToWorld,
  2109. pFlexWeights, pFlexDelayedWeights, vecModelOrigin, STUDIORENDER_DRAW_ENTIRE_MODEL );
  2110. m_LodUsed = g_DrawModelResults.m_nLODUsed;
  2111. m_LodMetric = g_DrawModelResults.m_flLodMetric;
  2112. g_DrawModelInfo.m_Lod = m_LodUsed;
  2113. // Restore the studio render config
  2114. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  2115. g_viewerSettings.showNormals,
  2116. g_viewerSettings.showTangentFrame );
  2117. #endif
  2118. }
  2119. else if( g_viewerSettings.renderMode == RM_BONEWEIGHTS )
  2120. {
  2121. DebugDrawModelBoneWeights( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin );
  2122. DebugDrawModelWireframe( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin, Vector( 0.2f, 0.2f, 0.2f ) );
  2123. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  2124. m_LodUsed = g_DrawModelInfo.m_Lod;
  2125. }
  2126. else if( g_viewerSettings.renderMode == RM_TEXCOORDS )
  2127. {
  2128. const char *pMatName = "";
  2129. if ( g_DrawModelInfo.m_pHardwareData->m_pLODs && g_viewerSettings.materialIndex < g_DrawModelInfo.m_pHardwareData->m_pLODs[0].numMaterials )
  2130. {
  2131. pMatName = g_DrawModelInfo.m_pHardwareData->m_pLODs[0].ppMaterials[g_viewerSettings.materialIndex]->GetName();
  2132. }
  2133. DebugDrawModelTexCoord( g_pStudioRender, pMatName, g_DrawModelInfo, m_pBoneToWorld, g_viewerSettings.width, g_viewerSettings.height );
  2134. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  2135. m_LodUsed = g_DrawModelInfo.m_Lod;
  2136. }
  2137. else if ( g_viewerSettings.renderMode == RM_SHOWCOLOCATED )
  2138. {
  2139. DebugDrawModelVertColocation( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin );
  2140. DebugDrawModelWireframe( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecModelOrigin, Vector( 0.2f, 0.2f, 0.2f ) );
  2141. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  2142. m_LodUsed = g_DrawModelInfo.m_Lod;
  2143. }
  2144. else
  2145. {
  2146. // Draw the model normally (may include normal and/or tangent line segments)
  2147. g_pStudioRender->DrawModel( &g_DrawModelResults, g_DrawModelInfo, m_pBoneToWorld,
  2148. pFlexWeights, pFlexDelayedWeights, vecModelOrigin );
  2149. m_LodUsed = g_DrawModelResults.m_nLODUsed;
  2150. m_LodMetric = g_DrawModelResults.m_flLODMetric;
  2151. g_pStudioRender->GetPerfStats( &g_DrawModelResults, g_DrawModelInfo, NULL );
  2152. // Optionally overlay wireframe...
  2153. if ( g_viewerSettings.overlayWireframe && !(g_viewerSettings.renderMode == RM_WIREFRAME) )
  2154. {
  2155. // Set the state to trigger wireframe rendering
  2156. UpdateStudioRenderConfig( true, true, false, false );
  2157. // Draw the wireframe over top of the model
  2158. g_pStudioRender->DrawModel( NULL, g_DrawModelInfo, m_pBoneToWorld,
  2159. pFlexWeights, pFlexDelayedWeights, vecModelOrigin );
  2160. // Restore the studio render config
  2161. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  2162. g_viewerSettings.showNormals,
  2163. g_viewerSettings.showTangentFrame );
  2164. }
  2165. }
  2166. }
  2167. int nCount = g_DrawModelResults.m_ActualTriCount;
  2168. if ( !mergeBones && (nRenderPassMode == PASS_DEFAULT || nRenderPassMode == PASS_EXTRASONLY) )
  2169. {
  2170. DrawBones();
  2171. DrawAttachments();
  2172. DrawOriginAxis();
  2173. DrawEditAttachment();
  2174. DrawHitboxes();
  2175. DrawPhysicsModel();
  2176. DrawSoftbody();
  2177. DrawIllumPosition();
  2178. }
  2179. // Only draw the shadow if the ground is also drawn
  2180. if ( g_viewerSettings.showShadow && g_viewerSettings.showGround )
  2181. {
  2182. matrix3x4_t invViewTransform;
  2183. MatrixInvert( g_viewtransform, invViewTransform );
  2184. for (int i = 0; i < pStudioHdr->numbones(); i++)
  2185. {
  2186. matrix3x4_t *pMatrix = &m_pBoneToWorld[ i ];
  2187. matrix3x4_t tmp1;
  2188. ConcatTransforms( invViewTransform, *pMatrix, tmp1 );
  2189. tmp1[2][0] = 0.0;
  2190. tmp1[2][1] = 0.0;
  2191. tmp1[2][2] = 0.0;
  2192. tmp1[2][3] = 0.05;
  2193. ConcatTransforms( g_viewtransform, tmp1, *pMatrix );
  2194. }
  2195. g_DrawModelInfo.m_Lod = GetHardwareData()->m_NumLODs - 1;
  2196. float zero[4] = { 0, 0, 0, 0 };
  2197. g_pStudioRender->SetColorModulation( zero );
  2198. g_pStudioRender->ForcedMaterialOverride( g_materialShadow );
  2199. // Turn off any wireframe, normals or tangent frame display for the drop shadow
  2200. UpdateStudioRenderConfig( false, false, false, false );
  2201. g_pStudioRender->DrawModel( NULL, g_DrawModelInfo, m_pBoneToWorld,
  2202. pFlexWeights, pFlexDelayedWeights, vecModelOrigin );
  2203. // Restore the studio render config
  2204. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  2205. g_viewerSettings.showNormals,
  2206. g_viewerSettings.showTangentFrame );
  2207. g_pStudioRender->ForcedMaterialOverride( NULL );
  2208. float one[4] = { 1, 1, 1, 1 };
  2209. g_pStudioRender->SetColorModulation( one );
  2210. }
  2211. return nCount;
  2212. }
  2213. void StudioModel::DrawWidgetModel( )
  2214. {
  2215. MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
  2216. if ( !HasModel())
  2217. return;
  2218. CStudioHdr *pStudioHdr = GetStudioHdr();
  2219. g_smodels_total++; // render data cache cookie
  2220. // JasonM & garymcthack - should really only do this once a frame and at init time.
  2221. UpdateStudioRenderConfig( g_viewerSettings.renderMode == RM_WIREFRAME, false,
  2222. g_viewerSettings.showNormals,
  2223. g_viewerSettings.showTangentFrame );
  2224. // NOTE: UpdateStudioRenderConfig can delete the studio hdr
  2225. if ( !GetStudioHdr() )
  2226. return;
  2227. // Construct a transform to apply to the model. The camera is stuck in a fixed position
  2228. GetModelTransform( g_viewtransform );
  2229. Vector vecModelOrigin;
  2230. VectorMultiply( m_origin, -1.0f, vecModelOrigin );
  2231. MatrixSetColumn( vecModelOrigin, 3, g_viewtransform );
  2232. // These values HAVE to be sent down for LOD to work correctly.
  2233. Vector viewOrigin, viewRight, viewUp, viewPlaneNormal;
  2234. g_pStudioRender->SetViewState( vec3_origin, Vector(0, 1, 0), Vector(0, 0, 1), Vector( 1, 0, 0 ) );
  2235. // g_pStudioRender->SetEyeViewTarget( viewOrigin );
  2236. SetUpBones( false );
  2237. SetupLighting( );
  2238. SetViewTarget( );
  2239. // draw
  2240. g_pStudioRender->SetAlphaModulation( 1.0f );
  2241. g_bDrawModelInfoValid = true;
  2242. memset( &g_DrawModelInfo, 0, sizeof( g_DrawModelInfo ) );
  2243. g_DrawModelInfo.m_pStudioHdr = (studiohdr_t *)pStudioHdr->GetRenderHdr();
  2244. g_DrawModelInfo.m_pHardwareData = GetHardwareData();
  2245. if ( !g_DrawModelInfo.m_pHardwareData )
  2246. return;
  2247. g_DrawModelInfo.m_Decals = STUDIORENDER_DECAL_INVALID;
  2248. g_DrawModelInfo.m_Skin = m_skinnum;
  2249. g_DrawModelInfo.m_Body = m_bodynum;
  2250. g_DrawModelInfo.m_HitboxSet = g_MDLViewer->GetCurrentHitboxSet();
  2251. g_DrawModelInfo.m_pClientEntity = NULL;
  2252. g_DrawModelInfo.m_Lod = -1;
  2253. g_DrawModelInfo.m_pColorMeshes = NULL;
  2254. g_pStudioRender->DrawModel( &g_DrawModelResults, g_DrawModelInfo, m_pBoneToWorld, NULL, NULL, vecModelOrigin );
  2255. }
  2256. void StudioModel::DrawRangeOfMotionArcs( CPhysmesh *pMesh, int boneIndex, IMaterial* pMaterial )
  2257. {
  2258. matrix3x4_t *pMatrix;
  2259. if ( boneIndex >= 0 )
  2260. {
  2261. pMatrix = &m_pBoneToWorld[ boneIndex ];
  2262. }
  2263. else
  2264. {
  2265. pMatrix = &g_viewtransform;
  2266. }
  2267. for( int iAxis=0; iAxis<3; iAxis++ )
  2268. {
  2269. constraint_ragdollparams_t *pConstraintInfo = &pMesh->m_constraint;
  2270. if ( !pConstraintInfo )
  2271. continue;
  2272. constraint_axislimit_t *axis = &pConstraintInfo->axes[iAxis];
  2273. Vector vecAxis;
  2274. vecAxis.Init();
  2275. vecAxis[iAxis] = 1;
  2276. int iVisAxis = RemapAxis( iAxis );
  2277. Vector arcVerts[30];
  2278. for ( int i=0; i<30; i++ )
  2279. {
  2280. float flArc = float(i)/29.0f;
  2281. arcVerts[i].Init();
  2282. arcVerts[i][iVisAxis] = 1;
  2283. VMatrix matRot;
  2284. matRot.Identity();
  2285. MatrixRotate( matRot, vecAxis, axis->minRotation + (axis->maxRotation - axis->minRotation) * flArc );
  2286. VectorTransform( arcVerts[i], matRot.As3x4(), arcVerts[i] );
  2287. arcVerts[i] = arcVerts[i].Normalized() * 4.0f;
  2288. }
  2289. float flColor[] = {0,0,0,0.5};
  2290. flColor[iAxis] = 1;
  2291. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  2292. pRenderContext->Bind( pMaterial );
  2293. IMesh* pMatMesh = pRenderContext->GetDynamicMesh( );
  2294. CMeshBuilder meshBuilder;
  2295. meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, 29 );
  2296. int vertIndex = 0;
  2297. for ( int i = 0; i < 32; i+=1 )
  2298. {
  2299. Vector v;
  2300. VectorTransform (arcVerts[vertIndex], *pMatrix, v);
  2301. meshBuilder.Position3fv( v.Base() );
  2302. meshBuilder.Color4fv( flColor );
  2303. meshBuilder.AdvanceVertex();
  2304. vertIndex ++;
  2305. VectorTransform (arcVerts[vertIndex], *pMatrix, v);
  2306. meshBuilder.Position3fv( v.Base() );
  2307. meshBuilder.Color4fv( flColor );
  2308. meshBuilder.AdvanceVertex();
  2309. VectorTransform (Vector(0,0,0), *pMatrix, v);
  2310. meshBuilder.Position3fv( v.Base() );
  2311. meshBuilder.Color4fv( flColor );
  2312. meshBuilder.AdvanceVertex();
  2313. }
  2314. meshBuilder.End();
  2315. pMatMesh->Draw();
  2316. //draw center line
  2317. {
  2318. Vector vecStart;
  2319. vecStart.Init();
  2320. Vector vecEnd;
  2321. vecEnd.Init();
  2322. vecEnd[iVisAxis] = 4.2f;
  2323. if ( iAxis == m_physPreviewAxis && ( axis->maxRotation != axis->minRotation ) )
  2324. {
  2325. VMatrix matRot;
  2326. matRot.Identity();
  2327. MatrixRotate( matRot, vecAxis, axis->minRotation + (axis->maxRotation - axis->minRotation) * (1.0f-m_physPreviewParam) );
  2328. VectorTransform( vecEnd, matRot.As3x4(), vecEnd );
  2329. }
  2330. VectorTransform (vecStart, *pMatrix, vecStart);
  2331. VectorTransform (vecEnd, *pMatrix, vecEnd);
  2332. drawLine( vecStart, vecEnd, flColor[0]*255, flColor[1]*255, flColor[2]*255 );
  2333. }
  2334. }
  2335. }
  2336. void StudioModel::DrawPhysmesh( CPhysmesh *pMesh, int boneIndex, IMaterial* pMaterial, float* color )
  2337. {
  2338. matrix3x4_t *pMatrix;
  2339. if ( boneIndex >= 0 )
  2340. {
  2341. pMatrix = &m_pBoneToWorld[ boneIndex ];
  2342. }
  2343. else
  2344. {
  2345. pMatrix = &g_viewtransform;
  2346. }
  2347. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  2348. pRenderContext->Bind( pMaterial );
  2349. IMesh* pMatMesh = pRenderContext->GetDynamicMesh( );
  2350. CMeshBuilder meshBuilder;
  2351. meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, pMesh->m_vertCount/3 );
  2352. int vertIndex = 0;
  2353. for ( int i = 0; i < pMesh->m_vertCount; i+=3 )
  2354. {
  2355. Vector v;
  2356. VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
  2357. meshBuilder.Position3fv( v.Base() );
  2358. meshBuilder.Color4fv( color );
  2359. meshBuilder.AdvanceVertex();
  2360. vertIndex ++;
  2361. VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
  2362. meshBuilder.Position3fv( v.Base() );
  2363. meshBuilder.Color4fv( color );
  2364. meshBuilder.AdvanceVertex();
  2365. vertIndex ++;
  2366. VectorTransform (pMesh->m_pVerts[vertIndex], *pMatrix, v);
  2367. meshBuilder.Position3fv( v.Base() );
  2368. meshBuilder.Color4fv( color );
  2369. meshBuilder.AdvanceVertex();
  2370. vertIndex ++;
  2371. }
  2372. meshBuilder.End();
  2373. pMatMesh->Draw();
  2374. }
  2375. void RandomColor( float *color, int key )
  2376. {
  2377. static bool first = true;
  2378. static colorVec colors[256];
  2379. if ( first )
  2380. {
  2381. int r, g, b;
  2382. first = false;
  2383. for ( int i = 0; i < 256; i++ )
  2384. {
  2385. do
  2386. {
  2387. r = rand()&255;
  2388. g = rand()&255;
  2389. b = rand()&255;
  2390. } while ( (r+g+b)<256 );
  2391. colors[i].r = r;
  2392. colors[i].g = g;
  2393. colors[i].b = b;
  2394. colors[i].a = 255;
  2395. }
  2396. }
  2397. int index = key & 255;
  2398. color[0] = colors[index].r * (1.f / 255.f);
  2399. color[1] = colors[index].g * (1.f / 255.f);
  2400. color[2] = colors[index].b * (1.f / 255.f);
  2401. color[3] = colors[index].a * (1.f / 255.f);
  2402. }
  2403. void StudioModel::DrawPhysConvex( CPhysmesh *pMesh, int boneIndex, IMaterial* pMaterial )
  2404. {
  2405. matrix3x4_t &matrix = m_pBoneToWorld[ boneIndex ];
  2406. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  2407. pRenderContext->Bind( pMaterial );
  2408. for ( int i = 0; i < pMesh->m_pCollisionModel->ConvexCount(); i++ )
  2409. {
  2410. float color[4];
  2411. RandomColor( color, (i+1) * (boneIndex+1) );
  2412. IMesh* pMatMesh = pRenderContext->GetDynamicMesh( );
  2413. CMeshBuilder meshBuilder;
  2414. int triCount = pMesh->m_pCollisionModel->TriangleCount( i );
  2415. meshBuilder.Begin( pMatMesh, MATERIAL_TRIANGLES, triCount );
  2416. for ( int j = 0; j < triCount; j++ )
  2417. {
  2418. Vector objectSpaceVerts[3];
  2419. pMesh->m_pCollisionModel->GetTriangleVerts( i, j, objectSpaceVerts );
  2420. for ( int k = 0; k < 3; k++ )
  2421. {
  2422. Vector v;
  2423. VectorTransform (objectSpaceVerts[k], matrix, v);
  2424. meshBuilder.Position3fv( v.Base() );
  2425. meshBuilder.Color4fv( color );
  2426. meshBuilder.AdvanceVertex();
  2427. }
  2428. }
  2429. meshBuilder.End();
  2430. pMatMesh->Draw();
  2431. }
  2432. }
  2433. void StudioModel::ExtractVertExtents( Vector &vecMin, Vector &vecMax )
  2434. {
  2435. studiohdr_t *pStudioHdr = GetStudioRenderHdr();
  2436. if ( !pStudioHdr )
  2437. return;
  2438. SetUpBones( false );
  2439. DebugModelVertExtents( g_pStudioRender, g_DrawModelInfo, m_pBoneToWorld, vecMin, vecMax );
  2440. }
  2441. /*
  2442. ================
  2443. ================
  2444. */
  2445. int StudioModel::GetLodUsed( void )
  2446. {
  2447. return m_LodUsed;
  2448. }
  2449. float StudioModel::GetLodMetric( void )
  2450. {
  2451. return m_LodMetric;
  2452. }
  2453. const char *StudioModel::GetKeyValueText( int iSequence )
  2454. {
  2455. CStudioHdr *pStudioHdr = GetStudioHdr();
  2456. return Studio_GetKeyValueText( pStudioHdr, iSequence );
  2457. }
  2458. //-----------------------------------------------------------------------------
  2459. // Purpose:
  2460. // Input : solve -
  2461. //-----------------------------------------------------------------------------
  2462. void StudioModel::SetSolveHeadTurn( int solve )
  2463. {
  2464. m_nSolveHeadTurn = solve;
  2465. }
  2466. //-----------------------------------------------------------------------------
  2467. // Purpose:
  2468. // Output : int
  2469. //-----------------------------------------------------------------------------
  2470. int StudioModel::GetSolveHeadTurn() const
  2471. {
  2472. return m_nSolveHeadTurn;
  2473. }
  2474. //-----------------------------------------------------------------------------
  2475. // Purpose:
  2476. // Input : target -
  2477. //-----------------------------------------------------------------------------
  2478. void StudioModel::ClearLookTargets( void )
  2479. {
  2480. m_vecHeadTargets.RemoveAll();
  2481. }
  2482. //-----------------------------------------------------------------------------
  2483. // Purpose:
  2484. // Input : target -
  2485. //-----------------------------------------------------------------------------
  2486. void StudioModel::AddLookTarget( const Vector& vecPosition, float flWeight )
  2487. {
  2488. if (m_vecHeadTargets.Count() > 8)
  2489. return;
  2490. StudioLookTarget tmp;
  2491. tmp.m_flWeight = flWeight;
  2492. tmp.m_vecPosition = vecPosition;
  2493. tmp.m_bSelf = false;
  2494. m_vecHeadTargets.AddToTail( tmp );
  2495. }
  2496. void StudioModel::AddLookTargetSelf( float flWeight )
  2497. {
  2498. if (m_vecHeadTargets.Count() > 8)
  2499. return;
  2500. StudioLookTarget tmp;
  2501. tmp.m_flWeight = flWeight;
  2502. tmp.m_vecPosition = Vector(0,0,0);
  2503. tmp.m_bSelf = true;
  2504. m_vecHeadTargets.AddToTail( tmp );
  2505. }
  2506. //-----------------------------------------------------------------------------
  2507. // Purpose:
  2508. // Output :
  2509. //-----------------------------------------------------------------------------
  2510. void StudioModel::SetModelYaw( float flYaw )
  2511. {
  2512. m_flModelYaw = flYaw;
  2513. }
  2514. float StudioModel::GetModelYaw( void ) const
  2515. {
  2516. return m_flModelYaw;
  2517. }
  2518. void StudioModel::SetBodyYaw( float flYaw )
  2519. {
  2520. m_flBodyYaw = flYaw;
  2521. }
  2522. float StudioModel::GetBodyYaw( void ) const
  2523. {
  2524. return m_flBodyYaw;
  2525. }
  2526. void StudioModel::SetSpineYaw( float flYaw )
  2527. {
  2528. m_flSpineYaw = flYaw;
  2529. }
  2530. float StudioModel::GetSpineYaw( void ) const
  2531. {
  2532. return m_flSpineYaw;
  2533. }
  2534. int StudioModel::GetNumIncludeModels() const
  2535. {
  2536. CStudioHdr *pStudioHdr = GetStudioHdr();
  2537. if ( !pStudioHdr )
  2538. return 0;
  2539. const studiohdr_t *pRenderHdr = pStudioHdr->GetRenderHdr();
  2540. if ( !pRenderHdr )
  2541. return 0;
  2542. return pRenderHdr->numincludemodels;
  2543. }
  2544. const char *StudioModel::GetIncludeModelName( int index ) const
  2545. {
  2546. CStudioHdr *pStudioHdr = GetStudioHdr();
  2547. if ( !pStudioHdr )
  2548. return "";
  2549. const studiohdr_t *pRenderHdr = pStudioHdr->GetRenderHdr();
  2550. if ( !pRenderHdr )
  2551. return "";
  2552. if ( index < 0 || index > pRenderHdr->numincludemodels )
  2553. return "";
  2554. mstudiomodelgroup_t *pIncludeModel = pRenderHdr->pModelGroup( index );
  2555. if ( !pIncludeModel )
  2556. return "";
  2557. return pIncludeModel->pszName();
  2558. }