donnaken15

c_hairball.cpp (for Half-Life 2)

Apr 23rd, 2016
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.51 KB | None | 0 0
  1. //========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "simple_physics.h"
  9. #include "mathlib/vmatrix.h"
  10. #include "beamdraw.h"
  11.  
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14.  
  15. class C_Hairball : public C_BaseEntity
  16. {
  17.     DECLARE_CLASS( C_Hairball, C_BaseEntity );
  18. private:
  19.  
  20.     class CHairballDelegate : public CSimplePhysics::IHelper
  21.     {
  22.     public:
  23.         virtual void    GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel );
  24.         virtual void    ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes );
  25.    
  26.         C_Hairball      *m_pParent;
  27.     };
  28.  
  29.  
  30. public:
  31.    
  32.                         C_Hairball();
  33.  
  34.     void                Init();
  35.  
  36.  
  37. // IClientThinkable.
  38. public:
  39.    
  40.     virtual void        ClientThink();
  41.  
  42.  
  43. // IClientRenderable.
  44. public:
  45.  
  46.     virtual int         DrawModel( int flags );
  47.  
  48.  
  49.  
  50. public:
  51.  
  52.     float                               m_flSphereRadius;
  53.  
  54.     int                                 m_nHairs;
  55.     int                                 m_nNodesPerHair;
  56.     float                               m_flSpringDist;             // = hair length / (m_nNodesPerHair-1)
  57.  
  58.     CUtlVector<CSimplePhysics::CNode>   m_Nodes;                    // This is m_nHairs * m_nNodesPerHair large.
  59.     CUtlVector<Vector>                  m_HairPositions;            // Untransformed base hair positions, distributed on the sphere.
  60.     CUtlVector<Vector>                  m_TransformedHairPositions; // Transformed base hair positions, distributed on the sphere.
  61.  
  62.     CHairballDelegate                   m_Delegate;
  63.     CSimplePhysics                      m_Physics;
  64.  
  65.     IMaterial                           *m_pMaterial;
  66.  
  67.  
  68.     // Super sophisticated AI.
  69.     float m_flSitStillTime;
  70.     Vector m_vMoveDir;
  71.  
  72.     float   m_flSpinDuration;
  73.     float   m_flCurSpinTime;
  74.     float   m_flSpinRateX, m_flSpinRateY;
  75.    
  76.     bool    m_bFirstThink;
  77. };
  78.  
  79.  
  80. void C_Hairball::CHairballDelegate::GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel )
  81. {
  82.     pAccel->Init( 0, 0, -1500 );
  83. }
  84.  
  85.  
  86. void C_Hairball::CHairballDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes )
  87. {
  88.     int nSegments = m_pParent->m_nNodesPerHair - 1;
  89.     float flSpringDistSqr = m_pParent->m_flSpringDist * m_pParent->m_flSpringDist;
  90.  
  91.     static int nIterations = 1;
  92.     for( int iIteration=0; iIteration < nIterations; iIteration++ )
  93.     {
  94.         for ( int iHair=0; iHair < m_pParent->m_nHairs; iHair++ )
  95.         {
  96.             CSimplePhysics::CNode *pBase = &pNodes[iHair * m_pParent->m_nNodesPerHair];
  97.  
  98.             for( int i=0; i < nSegments; i++ )
  99.             {
  100.                 Vector &vNode1 = pBase[i].m_vPos;
  101.                 Vector &vNode2 = pBase[i+1].m_vPos;
  102.                 Vector vTo = vNode1 - vNode2;
  103.  
  104.                 float flDistSqr = vTo.LengthSqr();
  105.                 if( flDistSqr > flSpringDistSqr )
  106.                 {
  107.                     float flDist = (float)sqrt( flDistSqr );
  108.                     vTo *= 1 - (m_pParent->m_flSpringDist / flDist);
  109.  
  110.                     vNode1 -= vTo * 0.5f;
  111.                     vNode2 += vTo * 0.5f;
  112.                 }
  113.             }
  114.  
  115.             // Lock the base of each hair to the right spot.
  116.             pBase->m_vPos = m_pParent->m_TransformedHairPositions[iHair];
  117.         }
  118.     }
  119. }
  120.  
  121.  
  122. C_Hairball::C_Hairball()
  123. {
  124.     m_nHairs = 100;
  125.     m_nNodesPerHair = 3;
  126.    
  127.     float flHairLength = 20;
  128.     m_flSpringDist = flHairLength / (m_nNodesPerHair - 1);
  129.    
  130.     m_Nodes.SetSize( m_nHairs * m_nNodesPerHair );
  131.     m_HairPositions.SetSize( m_nHairs );
  132.     m_TransformedHairPositions.SetSize( m_nHairs );
  133.  
  134.     m_flSphereRadius = 20;
  135.     m_vMoveDir.Init();
  136.    
  137.     m_flSpinDuration = 1;
  138.     m_flCurSpinTime = 0;
  139.     m_flSpinRateX = m_flSpinRateY = 0;
  140.  
  141.     // Distribute on the sphere (need a better random distribution for the sphere).
  142.     for ( int i=0; i < m_HairPositions.Count(); i++ )
  143.     {
  144.         float theta = RandomFloat( -M_PI, M_PI );
  145.         float phi   = RandomFloat( -M_PI/2, M_PI/2 );
  146.        
  147.         float cosPhi = cos( phi );
  148.  
  149.         m_HairPositions[i].Init(
  150.             cos(theta) * cosPhi * m_flSphereRadius,
  151.             sin(theta) * cosPhi * m_flSphereRadius,
  152.             sin(phi) * m_flSphereRadius );
  153.     }
  154.  
  155.     m_Delegate.m_pParent = this;
  156.  
  157.     m_Physics.Init( 1.0 / 20 ); // NOTE: PLAY WITH THIS FOR EFFICIENCY
  158.     m_pMaterial = NULL;
  159.  
  160.     m_bFirstThink = true;
  161. }
  162.  
  163.  
  164. void C_Hairball::Init()
  165. {
  166.     ClientEntityList().AddNonNetworkableEntity( this );
  167.     ClientThinkList()->SetNextClientThink( GetClientHandle(), CLIENT_THINK_ALWAYS );
  168.    
  169.     AddToLeafSystem( RENDER_GROUP_OPAQUE_ENTITY );
  170.  
  171.     m_pMaterial = materials->FindMaterial( "cable/cable", TEXTURE_GROUP_OTHER );
  172.     m_flSitStillTime = 5;
  173. }
  174.  
  175.  
  176. void C_Hairball::ClientThink()
  177. {
  178.     // Do some AI-type stuff.. move the entity around.
  179.     //C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  180.     //m_vecAngles = SetAbsAngles( pPlayer->GetAbsAngles() ); // copy player angles.
  181.  
  182.     Assert( !GetMoveParent() );
  183.  
  184.     // Sophisticated AI.
  185.     m_flCurSpinTime += gpGlobals->frametime;
  186.     if ( m_flCurSpinTime < m_flSpinDuration )
  187.     {
  188.         float div = m_flCurSpinTime / m_flSpinDuration;
  189.  
  190.         QAngle angles = GetLocalAngles();
  191.  
  192.         angles.x += m_flSpinRateX * SmoothCurve( div );
  193.         angles.y += m_flSpinRateY * SmoothCurve( div );
  194.  
  195.         SetLocalAngles( angles );
  196.     }
  197.     else
  198.     {
  199.         // Flip between stopped and starting.
  200.         if ( fabs( m_flSpinRateX ) > 0.01f )
  201.         {
  202.             m_flSpinRateX = m_flSpinRateY = 0;
  203.  
  204.             m_flSpinDuration = RandomFloat( 1, 2 );
  205.         }
  206.         else
  207.         {
  208.             static float flXSpeed = 3;
  209.             static float flYSpeed = flXSpeed * 0.1f;
  210.             m_flSpinRateX = RandomFloat( -M_PI*flXSpeed, M_PI*flXSpeed );
  211.             m_flSpinRateY = RandomFloat( -M_PI*flYSpeed, M_PI*flYSpeed );
  212.  
  213.             m_flSpinDuration = RandomFloat( 1, 4 );
  214.         }
  215.  
  216.         m_flCurSpinTime = 0;
  217.     }
  218.  
  219.    
  220.     if ( m_flSitStillTime > 0 )
  221.     {
  222.         m_flSitStillTime -= gpGlobals->frametime;
  223.  
  224.         if ( m_flSitStillTime <= 0 )
  225.         {
  226.             // Shoot out some random lines and find the longest one.
  227.             m_vMoveDir.Init( 1, 0, 0 );
  228.             float flLongestFraction = 0;
  229.             for ( int i=0; i < 15; i++ )
  230.             {
  231.                 Vector vDir( RandomFloat( -1, 1 ), RandomFloat( -1, 1 ), RandomFloat( -1, 1 ) );
  232.                 VectorNormalize( vDir );
  233.  
  234.                 trace_t trace;
  235.                 UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vDir * 10000, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &trace );
  236.  
  237.                 if ( trace.fraction != 1.0 )
  238.                 {
  239.                     if ( trace.fraction > flLongestFraction )
  240.                     {
  241.                         flLongestFraction = trace.fraction;
  242.                         m_vMoveDir = vDir;
  243.                     }
  244.                 }
  245.             }
  246.  
  247.             m_vMoveDir *= 650; // set speed.
  248.             m_flSitStillTime = -1; // Move in this direction..
  249.         }
  250.     }
  251.     else
  252.     {
  253.         // Move in the specified direction.
  254.         Vector vEnd = GetAbsOrigin() + m_vMoveDir * gpGlobals->frametime;
  255.  
  256.         trace_t trace;
  257.         UTIL_TraceLine( GetAbsOrigin(), vEnd, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &trace );
  258.  
  259.         if ( trace.fraction < 1 )
  260.         {
  261.             // Ok, stop moving.
  262.             m_flSitStillTime = RandomFloat( 1, 3 );
  263.         }
  264.         else
  265.         {
  266.             SetLocalOrigin( GetLocalOrigin() + m_vMoveDir * gpGlobals->frametime );
  267.         }
  268.     }
  269.  
  270.    
  271.     // Transform the base hair positions so we can lock them down.
  272.     VMatrix mTransform;
  273.     mTransform.SetupMatrixOrgAngles( GetLocalOrigin(), GetLocalAngles() );
  274.  
  275.     for ( int i=0; i < m_HairPositions.Count(); i++ )
  276.     {
  277.         Vector3DMultiplyPosition( mTransform, m_HairPositions[i], m_TransformedHairPositions[i] );
  278.     }
  279.  
  280.     if ( m_bFirstThink )
  281.     {
  282.         m_bFirstThink = false;
  283.         for ( int i=0; i < m_HairPositions.Count(); i++ )
  284.         {
  285.             for ( int j=0; j < m_nNodesPerHair; j++ )
  286.             {
  287.                 m_Nodes[i*m_nNodesPerHair+j].Init( m_TransformedHairPositions[i] );
  288.             }
  289.         }
  290.     }
  291.  
  292.     // Simulate the physics and apply constraints.
  293.     m_Physics.Simulate( m_Nodes.Base(), m_Nodes.Count(), &m_Delegate, gpGlobals->frametime, 0.98 );
  294. }
  295.  
  296.  
  297. int C_Hairball::DrawModel( int flags )
  298. {
  299.     if ( !m_pMaterial )
  300.         return 0;
  301.  
  302.     CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  303.     for ( int iHair=0; iHair < m_nHairs; iHair++ )
  304.     {
  305.         CSimplePhysics::CNode *pBase = &m_Nodes[iHair * m_nNodesPerHair];
  306.        
  307.         CBeamSegDraw beamDraw;
  308.         beamDraw.Start( pRenderContext, m_nNodesPerHair-1, m_pMaterial );
  309.  
  310.         for ( int i=0; i < m_nNodesPerHair; i++ )
  311.         {
  312.             BeamSeg_t seg;
  313.             seg.m_vPos = pBase[i].m_vPredicted;
  314.             seg.m_vColor.Init( 0, 0, 0 );
  315.             seg.m_flTexCoord = 0;
  316.             static float flHairWidth = 1;
  317.             seg.m_flWidth = flHairWidth;
  318.             seg.m_flAlpha = 0;
  319.  
  320.             beamDraw.NextSeg( &seg );
  321.         }
  322.        
  323.         beamDraw.End();
  324.     }
  325.  
  326.     return 1;
  327. }
  328.  
  329.  
  330. void CreateHairballCallback()
  331. {
  332.     for ( int i=0; i < 20; i++ )
  333.     {
  334.         C_Hairball *pHairball = new C_Hairball;
  335.         pHairball->Init();
  336.        
  337.         // Put it a short distance in front of the player.
  338.         C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  339.        
  340.         if ( !pPlayer )
  341.             return;
  342.  
  343.         Vector vForward;
  344.         AngleVectors( pPlayer->GetAbsAngles(), &vForward );
  345.         pHairball->SetLocalOrigin( pPlayer->GetAbsOrigin() + vForward * 300 + RandomVector( 0, 100 ) );
  346.     }
  347. }
  348.  
  349. ConCommand cc_CreateHairball( "CreateHairball", CreateHairballCallback, 0, FCVAR_CHEAT );
Advertisement
Add Comment
Please, Sign In to add comment