259 lines
8.1 KiB
C++
259 lines
8.1 KiB
C++
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//===========================================================================//
|
|
|
|
#ifndef C_ROPE_H
|
|
#define C_ROPE_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "c_baseentity.h"
|
|
#include "rope_physics.h"
|
|
#include "materialsystem/imaterial.h"
|
|
#include "rope_shared.h"
|
|
#include "bitvec.h"
|
|
|
|
|
|
class KeyValues;
|
|
class C_BaseAnimating;
|
|
struct RopeSegData_t;
|
|
|
|
#define MAX_ROPE_SUBDIVS 8
|
|
#define MAX_ROPE_SEGMENTS (ROPE_MAX_SEGMENTS+(ROPE_MAX_SEGMENTS-1)*MAX_ROPE_SUBDIVS)
|
|
|
|
//=============================================================================
|
|
class C_RopeKeyframe : public C_BaseEntity
|
|
{
|
|
public:
|
|
|
|
DECLARE_CLASS( C_RopeKeyframe, C_BaseEntity );
|
|
DECLARE_CLIENTCLASS();
|
|
|
|
|
|
private:
|
|
|
|
class CPhysicsDelegate : public CSimplePhysics::IHelper
|
|
{
|
|
public:
|
|
virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel );
|
|
virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes );
|
|
|
|
C_RopeKeyframe *m_pKeyframe;
|
|
};
|
|
|
|
friend class CPhysicsDelegate;
|
|
|
|
|
|
public:
|
|
|
|
C_RopeKeyframe();
|
|
~C_RopeKeyframe();
|
|
|
|
// This can be used for client-only ropes.
|
|
static C_RopeKeyframe* Create(
|
|
C_BaseEntity *pStartEnt,
|
|
C_BaseEntity *pEndEnt,
|
|
int iStartAttachment=0,
|
|
int iEndAttachment=0,
|
|
float ropeWidth = 2,
|
|
const char *pMaterialName = "cable/cable", // Note: whoever creates the rope must
|
|
// use PrecacheModel for whatever material
|
|
// it specifies here.
|
|
int numSegments = 5,
|
|
int ropeFlags = ROPE_SIMULATE
|
|
);
|
|
|
|
// Create a client-only rope and initialize it with the parameters from the KeyValues.
|
|
static C_RopeKeyframe* CreateFromKeyValues( C_BaseAnimating *pEnt, KeyValues *pValues );
|
|
|
|
// Find ropes (with both endpoints connected) that intersect this AABB. This is just an approximation.
|
|
static int GetRopesIntersectingAABB( C_RopeKeyframe **pRopes, int nMaxRopes, const Vector &vAbsMin, const Vector &vAbsMax );
|
|
|
|
// Set the slack.
|
|
void SetSlack( int slack );
|
|
|
|
void SetRopeFlags( int flags );
|
|
int GetRopeFlags() const;
|
|
|
|
void SetupHangDistance( float flHangDist );
|
|
|
|
// Change which entities the rope is connected to.
|
|
void SetStartEntity( C_BaseEntity *pEnt );
|
|
void SetEndEntity( C_BaseEntity *pEnt );
|
|
|
|
C_BaseEntity* GetStartEntity() const;
|
|
C_BaseEntity* GetEndEntity() const;
|
|
|
|
// Hook the physics. Pass in your own implementation of CSimplePhysics::IHelper. The
|
|
// default implementation is returned so you can call through to it if you want.
|
|
CSimplePhysics::IHelper* HookPhysics( CSimplePhysics::IHelper *pHook );
|
|
|
|
// Attach to things (you can also just lock the endpoints down yourself if you hook the physics).
|
|
|
|
// Client-only right now. This could be moved to the server if there was a good reason.
|
|
void SetColorMod( const Vector &vColorMod );
|
|
|
|
// Use this when rope length and slack change to recompute the spring length.
|
|
void RecomputeSprings();
|
|
|
|
void ShakeRope( const Vector &vCenter, float flRadius, float flMagnitude );
|
|
|
|
// Get the attachment position of one of the endpoints.
|
|
bool GetEndPointPos( int iPt, Vector &vPos );
|
|
|
|
// Get the rope material data.
|
|
IMaterial *GetSolidMaterial( void ) { return m_pMaterial; }
|
|
|
|
struct BuildRopeQueuedData_t
|
|
{
|
|
Vector *m_pPredictedPositions;
|
|
Vector *m_pLightValues;
|
|
int m_iNodeCount;
|
|
Vector m_vColorMod;
|
|
float m_RopeLength;
|
|
float m_Slack;
|
|
};
|
|
|
|
void BuildRope( RopeSegData_t *pRopeSegment, const Vector &vCurrentViewForward, const Vector &vCurrentViewOrigin, BuildRopeQueuedData_t *pQueuedData );
|
|
|
|
// C_BaseEntity overrides.
|
|
public:
|
|
|
|
virtual void OnDataChanged( DataUpdateType_t updateType );
|
|
virtual void ClientThink();
|
|
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
|
|
virtual RenderableTranslucencyType_t ComputeTranslucencyType() { return RENDERABLE_IS_OPAQUE; }
|
|
|
|
virtual bool ShouldDraw();
|
|
virtual const Vector& WorldSpaceCenter() const;
|
|
|
|
// Specify ROPE_ATTACHMENT_START_POINT or ROPE_ATTACHMENT_END_POINT for the attachment.
|
|
virtual bool GetAttachment( int number, Vector &origin, QAngle &angles );
|
|
virtual bool GetAttachment( int number, matrix3x4_t &matrix );
|
|
virtual bool GetAttachment( int number, Vector &origin );
|
|
virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel );
|
|
|
|
private:
|
|
|
|
void FinishInit( const char *pMaterialName );
|
|
|
|
void RunRopeSimulation( float flSeconds );
|
|
Vector ConstrainNode( const Vector &vNormal, const Vector &vNodePosition, const Vector &vMidpiont, float fNormalLength );
|
|
void ConstrainNodesBetweenEndpoints( void );
|
|
|
|
bool AnyPointsMoved();
|
|
|
|
bool DidEndPointMove( int iPt );
|
|
bool DetectRestingState( bool &bApplyWind );
|
|
|
|
void UpdateBBox();
|
|
bool InitRopePhysics();
|
|
|
|
bool GetEndPointAttachment( int iPt, Vector &vPos, QAngle &angle );
|
|
|
|
Vector *GetRopeSubdivVectors( int *nSubdivs );
|
|
void CalcLightValues();
|
|
|
|
void ReceiveMessage( int classID, bf_read &msg );
|
|
bool CalculateEndPointAttachment( C_BaseEntity *pEnt, int iAttachment, Vector &vPos, QAngle *pAngles );
|
|
|
|
|
|
private:
|
|
// Track which links touched something last frame. Used to prevent wind from gusting on them.
|
|
CBitVec<ROPE_MAX_SEGMENTS> m_LinksTouchingSomething;
|
|
int m_nLinksTouchingSomething;
|
|
bool m_bApplyWind;
|
|
int m_fPrevLockedPoints; // Which points are locked down.
|
|
int m_iForcePointMoveCounter;
|
|
|
|
// Used to control resting state.
|
|
bool m_bPrevEndPointPos[2];
|
|
Vector m_vPrevEndPointPos[2];
|
|
|
|
float m_flCurScroll; // for scrolling texture.
|
|
float m_flScrollSpeed;
|
|
|
|
int m_RopeFlags; // Combo of ROPE_ flags.
|
|
int m_iRopeMaterialModelIndex; // Index of sprite model with the rope's material.
|
|
|
|
CRopePhysics<ROPE_MAX_SEGMENTS> m_RopePhysics;
|
|
Vector m_LightValues[ROPE_MAX_SEGMENTS]; // light info when the rope is created.
|
|
|
|
int m_nSegments; // Number of segments.
|
|
|
|
EHANDLE m_hStartPoint; // StartPoint/EndPoint are entities
|
|
EHANDLE m_hEndPoint;
|
|
short m_iStartAttachment; // StartAttachment/EndAttachment are attachment points.
|
|
short m_iEndAttachment;
|
|
|
|
int m_Subdiv; // Number of subdivions in between segments.
|
|
|
|
int m_RopeLength; // Length of the rope, used for tension.
|
|
int m_Slack; // Extra length the rope is given.
|
|
float m_TextureScale; // pixels per inch
|
|
|
|
int m_fLockedPoints; // Which points are locked down.
|
|
int m_nChangeCount;
|
|
|
|
float m_Width;
|
|
|
|
CPhysicsDelegate m_PhysicsDelegate;
|
|
|
|
IMaterial *m_pMaterial;
|
|
|
|
int m_TextureHeight; // Texture height, for texture scale calculations.
|
|
|
|
// Instantaneous force
|
|
Vector m_vecImpulse;
|
|
Vector m_vecPreviousImpulse;
|
|
|
|
// Simulated wind gusts.
|
|
float m_flCurrentGustTimer;
|
|
float m_flCurrentGustLifetime; // How long will the current gust last?
|
|
|
|
float m_flTimeToNextGust; // When will the next wind gust be?
|
|
Vector m_vWindDir; // What direction does the current gust go in?
|
|
|
|
Vector m_vColorMod; // Color modulation on all verts?
|
|
|
|
Vector m_vCachedEndPointAttachmentPos[2];
|
|
QAngle m_vCachedEndPointAttachmentAngle[2];
|
|
|
|
// In network table, can't bit-compress
|
|
bool m_bConstrainBetweenEndpoints; // Simulated segment points won't stretch beyond the endpoints
|
|
|
|
bool m_bEndPointAttachmentPositionsDirty : 1;
|
|
bool m_bEndPointAttachmentAnglesDirty : 1;
|
|
bool m_bNewDataThisFrame : 1; // Set to true in OnDataChanged so that we simulate that frame
|
|
bool m_bPhysicsInitted : 1; // It waits until all required entities are
|
|
// present to start simulating and rendering.
|
|
|
|
friend class CRopeManager;
|
|
};
|
|
|
|
|
|
// Profiling info.
|
|
void Rope_ResetCounters();
|
|
//void Rope_ShowRSpeeds();
|
|
|
|
//=============================================================================
|
|
//
|
|
// Rope Manager
|
|
//
|
|
abstract_class IRopeManager
|
|
{
|
|
public:
|
|
virtual ~IRopeManager() {}
|
|
virtual void ResetRenderCache( void ) = 0;
|
|
virtual void AddToRenderCache( C_RopeKeyframe *pRope ) = 0;
|
|
virtual void DrawRenderCache( bool bShadowDepth ) = 0;
|
|
};
|
|
|
|
IRopeManager *RopeManager();
|
|
|
|
#endif // C_ROPE_H
|