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
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* OPCODE - Optimized Collision Detection
* Copyright (C) 2001 Pierre Terdiman
* Homepage: http://www.codercorner.com/Opcode.htm
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains base collider class.
* \file OPC_Collider.h
* \author Pierre Terdiman
* \date June, 2, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __OPC_COLLIDER_H__
#define __OPC_COLLIDER_H__
enum CollisionFlag
{
OPC_FIRST_CONTACT = (1<<0), //!< Report all contacts (false) or only first one (true)
OPC_TEMPORAL_COHERENCE = (1<<1), //!< Use temporal coherence or not
OPC_CONTACT = (1<<2), //!< Final contact status after a collision query
OPC_TEMPORAL_HIT = (1<<3), //!< There has been an early exit due to temporal coherence
OPC_NO_PRIMITIVE_TESTS = (1<<4), //!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries)
OPC_CONTACT_FOUND = OPC_FIRST_CONTACT | OPC_CONTACT,
OPC_TEMPORAL_CONTACT = OPC_TEMPORAL_HIT | OPC_CONTACT,
OPC_FORCE_DWORD = 0x7fffffff
};
class OPCODE_API Collider
{
public:
// Constructor / Destructor
Collider();
virtual ~Collider();
// Collision report
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the last collision status after a collision query.
* \return true if a collision occured
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL GetContactStatus() const { return mFlags & OPC_CONTACT; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the "first contact" mode.
* \return true if "first contact" mode is on
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL FirstContactEnabled() const { return mFlags & OPC_FIRST_CONTACT; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the temporal coherence mode.
* \return true if temporal coherence is on
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL TemporalCoherenceEnabled() const { return mFlags & OPC_TEMPORAL_COHERENCE; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks a first contact has already been found.
* \return true if a first contact has been found and we can stop a query
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL ContactFound() const { return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks there's been an early exit due to temporal coherence;
* \return true if a temporal hit has occured
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL TemporalHit() const { return mFlags & OPC_TEMPORAL_HIT; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Checks primitive tests are enabled;
* \return true if primitive tests must be skipped
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL SkipPrimitiveTests() const { return mFlags & OPC_NO_PRIMITIVE_TESTS; }
// Settings
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Reports all contacts (false) or first contact only (true)
* \param flag [in] true for first contact, false for all contacts
* \see SetTemporalCoherence(bool flag)
* \see ValidateSettings()
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void SetFirstContact(bool flag)
{
if(flag) mFlags |= OPC_FIRST_CONTACT;
else mFlags &= ~OPC_FIRST_CONTACT;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Enable/disable temporal coherence.
* \param flag [in] true to enable temporal coherence, false to discard it
* \see SetFirstContact(bool flag)
* \see ValidateSettings()
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void SetTemporalCoherence(bool flag)
{
if(flag) mFlags |= OPC_TEMPORAL_COHERENCE;
else mFlags &= ~OPC_TEMPORAL_COHERENCE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Enable/disable primitive tests.
* \param flag [in] true to enable primitive tests, false to discard them
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ void SetPrimitiveTests(bool flag)
{
if(!flag) mFlags |= OPC_NO_PRIMITIVE_TESTS;
else mFlags &= ~OPC_NO_PRIMITIVE_TESTS;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider.
* \return null if everything is ok, else a string describing the problem
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual const char* ValidateSettings() = 0;
protected:
udword mFlags; //!< Bit flags
const BaseModel* mCurrentModel; //!< Current model for collision query (owner of touched faces)
// User mesh interface
const MeshInterface* mIMesh; //!< User-defined mesh interface
// Internal methods
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Setups current collision model
* \param model [in] current collision model
* \return TRUE if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline_ BOOL Setup(const BaseModel* model)
{
// Keep track of current model
mCurrentModel = model;
if(!mCurrentModel) return FALSE;
mIMesh = model->GetMeshInterface();
return mIMesh!=null;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Initializes a query
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual inline_ void InitQuery() { mFlags &= ~OPC_TEMPORAL_CONTACT; }
};
#endif // __OPC_COLLIDER_H__
|