1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
//========= 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
|