source-engine/vphysics/physics_trace.h

245 lines
7.4 KiB
C
Raw Normal View History

2020-04-23 00:56:21 +08:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef PHYSICS_TRACE_H
#define PHYSICS_TRACE_H
#ifdef _WIN32
#pragma once
#endif
class Vector;
class QAngle;
class CGameTrace;
class CTraceRay;
class IVP_Compact_Surface;
typedef CGameTrace trace_t;
struct Ray_t;
class IVP_Compact_Surface;
class IVP_Compact_Mopp;
class IConvexInfo;
enum
{
COLLIDE_POLY = 0,
COLLIDE_MOPP = 1,
COLLIDE_BALL = 2,
COLLIDE_VIRTUAL = 3,
};
class IPhysCollide
{
public:
virtual ~IPhysCollide() {}
//virtual void AddReference() = 0;
//virtual void ReleaseReference() = 0;
// get a surface manager
virtual IVP_SurfaceManager *CreateSurfaceManager( short & ) const = 0;
virtual void GetAllLedges( IVP_U_BigVector<IVP_Compact_Ledge> &ledges ) const = 0;
virtual unsigned int GetSerializationSize() const = 0;
virtual unsigned int SerializeToBuffer( char *pDest, bool bSwap = false ) const = 0;
virtual int GetVCollideIndex() const = 0;
virtual Vector GetMassCenter() const = 0;
virtual void SetMassCenter( const Vector &massCenter ) = 0;
virtual Vector GetOrthographicAreas() const = 0;
virtual void SetOrthographicAreas( const Vector &areas ) = 0;
virtual float GetSphereRadius() const = 0;
virtual void OutputDebugInfo() const = 0;
};
#define LEAFMAP_HAS_CUBEMAP 0x0001
#define LEAFMAP_HAS_SINGLE_VERTEX_SPAN 0x0002
#define LEAFMAP_HAS_MULTIPLE_VERTEX_SPANS 0x0004
struct leafmap_t
{
void *pLeaf;
unsigned short vertCount;
byte flags;
byte spanCount;
unsigned short startVert[8];
void SetHasCubemap()
{
flags = LEAFMAP_HAS_CUBEMAP;
}
void SetSingleVertexSpan( int startVertIndex, int vertCountIn )
{
flags = 0;
flags |= LEAFMAP_HAS_SINGLE_VERTEX_SPAN;
startVert[0] = startVertIndex;
vertCount = vertCountIn;
}
int MaxSpans()
{
return sizeof(startVert) - sizeof(startVert[0]);
}
const byte *GetSpans() const
{
return reinterpret_cast<const byte *>(&startVert[1]);
}
byte *GetSpans()
{
return reinterpret_cast<byte *>(&startVert[1]);
}
void SetRLESpans( int startVertIndex, int spanCountIn, byte *pSpans )
{
flags = 0;
if ( spanCountIn > MaxSpans() )
return;
if ( spanCountIn == 1 )
{
SetSingleVertexSpan( startVertIndex, pSpans[0] );
return;
}
// write out a run length encoded list of verts to include in this model
flags |= LEAFMAP_HAS_MULTIPLE_VERTEX_SPANS;
startVert[0] = startVertIndex;
vertCount = 0;
spanCount = spanCountIn;
byte *pSpanOut = GetSpans();
for ( int i = 0; i < spanCountIn; i++ )
{
pSpanOut[i] = pSpans[i];
if ( !(i & 1) )
{
vertCount += pSpans[i];
}
}
}
inline bool HasSpans() const { return (flags & (LEAFMAP_HAS_SINGLE_VERTEX_SPAN|LEAFMAP_HAS_MULTIPLE_VERTEX_SPANS)) ? true : false; }
inline bool HasCubemap() const { return (flags & LEAFMAP_HAS_CUBEMAP) ? true : false; }
inline bool HasSingleVertexSpan() const { return (flags & LEAFMAP_HAS_SINGLE_VERTEX_SPAN) ? true : false; }
inline bool HasRLESpans() const { return (flags & LEAFMAP_HAS_MULTIPLE_VERTEX_SPANS) ? true : false; }
};
struct collidemap_t
{
int leafCount;
leafmap_t leafmap[1];
};
extern void InitLeafmap( IVP_Compact_Ledge *pLeaf, leafmap_t *pLeafmapOut );
class CPhysCollide : public IPhysCollide
{
public:
static CPhysCollide *UnserializeFromBuffer( const char *pBuffer, unsigned int size, int index, bool swap = false );
virtual const IVP_Compact_Surface *GetCompactSurface() const { return NULL; }
virtual Vector GetOrthographicAreas() const { return Vector(1,1,1); }
virtual float GetSphereRadius() const { return 0; }
virtual void ComputeOrthographicAreas( float epsilon ) {}
virtual void SetOrthographicAreas( const Vector &areas ) {}
virtual const collidemap_t *GetCollideMap() const { return NULL; }
};
class ITraceObject
{
public:
virtual int SupportMap( const Vector &dir, Vector *pOut ) const = 0;
virtual Vector GetVertByIndex( int index ) const = 0;
virtual float Radius( void ) const = 0;
};
// This is the size of the vertex hash
#define CONVEX_HASH_SIZE 512
// The little hashing trick below allows 64K verts per hash entry
#define MAX_CONVEX_VERTS ((CONVEX_HASH_SIZE * (1<<16))-1)
class CPhysicsTrace
{
public:
CPhysicsTrace();
~CPhysicsTrace();
// Calculate the intersection of a swept box (mins/maxs) against an IVP object. All coords are in HL space.
void SweepBoxIVP( const Vector &start, const Vector &end, const Vector &mins, const Vector &maxs, const CPhysCollide *pSurface, const Vector &surfaceOrigin, const QAngle &surfaceAngles, trace_t *ptr );
void SweepBoxIVP( const Ray_t &raySrc, unsigned int contentsMask, IConvexInfo *pConvexInfo, const CPhysCollide *pSurface, const Vector &surfaceOrigin, const QAngle &surfaceAngles, trace_t *ptr );
// Calculate the intersection of a swept compact surface against another compact surface. All coords are in HL space.
// NOTE: BUGBUG: swept surface must be single convex!!!
void SweepIVP( const Vector &start, const Vector &end, const CPhysCollide *pSweptSurface, const QAngle &sweptAngles, const CPhysCollide *pSurface, const Vector &surfaceOrigin, const QAngle &surfaceAngles, trace_t *ptr );
// get an AABB for an oriented collide
void GetAABB( Vector *pMins, Vector *pMaxs, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles );
// get the support map/extent for a collide along the axis given by "direction"
Vector GetExtent( const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, const Vector &direction );
bool IsBoxIntersectingCone( const Vector &boxAbsMins, const Vector &boxAbsMaxs, const truncatedcone_t &cone );
};
class CVisitHash
{
public:
CVisitHash();
inline unsigned short VertIndexToID( int vertIndex );
inline void VisitVert( int vertIndex );
inline bool WasVisited( int vertIndex );
inline void NewVisit( void );
private:
// Store the current increment and the vertex ID (rotating hash) to guarantee no collisions
struct vertmarker_t
{
unsigned short visitID;
unsigned short vertID;
};
vertmarker_t m_vertVisit[CONVEX_HASH_SIZE];
unsigned short m_vertVisitID;
unsigned short m_isInUse;
};
// Calculate the intersection of a swept box (mins/maxs) against an IVP object. All coords are in HL space.
inline unsigned short CVisitHash::VertIndexToID( int vertIndex )
{
// A little hashing trick here:
// rotate the hash key each time you wrap around at 64K
// That way, the index will not collide until you've hit 64K # hash entries times
int high = vertIndex >> 16;
return (unsigned short) ((vertIndex + high) & 0xFFFF);
}
inline void CVisitHash::VisitVert( int vertIndex )
{
int index = vertIndex & (CONVEX_HASH_SIZE-1);
m_vertVisit[index].visitID = m_vertVisitID;
m_vertVisit[index].vertID = VertIndexToID(vertIndex);
}
inline bool CVisitHash::WasVisited( int vertIndex )
{
unsigned short hashIndex = vertIndex & (CONVEX_HASH_SIZE-1);
unsigned short id = VertIndexToID(vertIndex);
if ( m_vertVisit[hashIndex].visitID == m_vertVisitID && m_vertVisit[hashIndex].vertID == id )
return true;
return false;
}
inline void CVisitHash::NewVisit( void )
{
m_vertVisitID++;
if ( m_vertVisitID == 0 )
{
memset( m_vertVisit, 0, sizeof(m_vertVisit) );
}
}
extern IVP_SurfaceManager *CreateSurfaceManager( const CPhysCollide *pCollisionModel, short &collideType );
extern void OutputCollideDebugInfo( const CPhysCollide *pCollisionModel );
#endif // PHYSICS_TRACE_H