Panda3D
Loading...
Searching...
No Matches
collisionLevelState.I
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file collisionLevelState.I
10 * @author drose
11 * @date 2007-04-05
12 */
13
14#ifndef CPPPARSER
15/**
16 *
17 */
18template<class MaskType>
20CollisionLevelState(const NodePath &node_path) :
21 CollisionLevelStateBase(node_path),
22 _current(CurrentMask::all_off())
23{
24}
25#endif // CPPPARSER
26
27#ifndef CPPPARSER
28/**
29 * This constructor goes to the next child node in the traversal.
30 */
31template<class MaskType>
34 CollisionLevelStateBase(parent, child),
35 _current(parent._current)
36{
37}
38#endif // CPPPARSER
39
40#ifndef CPPPARSER
41/**
42 *
43 */
44template<class MaskType>
48 _current(copy._current)
49{
50}
51#endif // CPPPARSER
52
53#ifndef CPPPARSER
54/**
55 *
56 */
57template<class MaskType>
60 CollisionLevelStateBase::operator = (copy);
61 _current = copy._current;
62}
63#endif // CPPPARSER
64
65#ifndef CPPPARSER
66/**
67 *
68 */
69template<class MaskType>
71clear() {
72 CollisionLevelStateBase::clear();
73 _current.clear();
74}
75#endif // CPPPARSER
76
77#ifndef CPPPARSER
78/**
79 * Adds the indicated Collider to the set of Colliders in the current level
80 * state.
81 */
82template<class MaskType>
84prepare_collider(const ColliderDef &def, const NodePath &root) {
85 int index = (int)_colliders.size();
86 nassertv(!CurrentMask::has_max_num_bits() ||
87 index <= CurrentMask::get_max_num_bits());
88
90 _current.set_bit(index);
91}
92#endif // CPPPARSER
93
94#ifndef CPPPARSER
95/**
96 * Checks the bounding volume of the current node against each of our
97 * colliders. Eliminates from the current collider list any that are outside
98 * of the bounding volume. Returns true if any colliders remain, false if all
99 * of them fall outside this node's bounding volume.
100 */
101template<class MaskType>
104#ifndef NDEBUG
105 int indent_level = 0;
106 if (collide_cat.is_spam()) {
107 indent_level = _node_path.get_num_nodes() * 2;
108 collide_cat.spam();
109 indent(collide_cat.spam(false), indent_level)
110 << "Considering " << _node_path.get_node_path() << "\n";
111 }
112#endif // NDEBUG
113
114 PandaNode *pnode = node();
115
116 CPT(BoundingVolume) node_bv = pnode->get_bounds();
117 if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
118 const GeometricBoundingVolume *node_gbv = (const GeometricBoundingVolume *)node_bv.p();
119 CollideMask this_mask = pnode->get_net_collide_mask();
120
121 int num_colliders = get_num_colliders();
122 for (int c = 0; c < num_colliders; c++) {
123 if (has_collider(c)) {
124 CollisionNode *cnode = get_collider_node(c);
125 bool is_in = false;
126
127 // Don't even bother testing the bounding volume if there are no
128 // collide bits in common between our collider and this node.
129 CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask;
130 if (!(from_mask & this_mask).is_zero()) {
131 // Also don't test a node with itself, or with any of its
132 // descendants.
133 if (pnode == cnode) {
134#ifndef NDEBUG
135 if (collide_cat.is_spam()) {
136 indent(collide_cat.spam(false), indent_level)
137 << "Not comparing " << c << " to " << _node_path
138 << " (same node)\n";
139 }
140#endif // NDEBUG
141
142 } else {
143 // There are bits in common, and it's not the same instance, so go
144 // ahead and try the bounding volume.
145 const GeometricBoundingVolume *col_gbv =
146 get_local_bound(c);
147
148 is_in = true; // If there's no bounding volume, we're implicitly in.
149
150 if (col_gbv != nullptr) {
151 is_in = (node_gbv->contains(col_gbv) != 0);
152 _node_volume_pcollector.add_level(1);
153
154#ifndef NDEBUG
155 if (collide_cat.is_spam()) {
156 indent(collide_cat.spam(false), indent_level)
157 << "Comparing " << c << ": " << *col_gbv
158 << " to " << *node_gbv << ", is_in = " << is_in << "\n";
159 }
160#endif // NDEBUG
161 }
162 }
163 }
164
165 if (!is_in) {
166 // This collider cannot intersect with any geometry at this node or
167 // below.
168 omit_collider(c);
169 }
170 }
171 }
172 }
173
174#ifndef NDEBUG
175 if (collide_cat.is_spam()) {
176 int num_active_colliders = 0;
177 int num_colliders = get_num_colliders();
178 for (int c = 0; c < num_colliders; c++) {
179 if (has_collider(c)) {
180 num_active_colliders++;
181 }
182 }
183
184 collide_cat.spam();
185 indent(collide_cat.spam(false), indent_level)
186 << _node_path.get_node_path() << " has " << num_active_colliders
187 << " interested colliders";
188 if (num_colliders != 0) {
189 collide_cat.spam(false)
190 << " (";
191 for (int c = 0; c < num_colliders; c++) {
192 if (has_collider(c)) {
193 CollisionNode *cnode = get_collider_node(c);
194 collide_cat.spam(false)
195 << " " << c << ". " << cnode->get_name();
196 }
197 }
198 collide_cat.spam(false)
199 << " )";
200 }
201 collide_cat.spam(false)
202 << "\n";
203 }
204#endif // NDEBUG
205 return has_any_collider();
206}
207#endif // CPPPARSER
208
209#ifndef CPPPARSER
210/**
211 * Applies the inverse transform from the current node, if any, onto all the
212 * colliders in the level state.
213 *
214 * Returns true if the inverse transform is valid, or false if it is not valid
215 * (e.g. the transform has a scale to zero). If the inverse transform is not
216 * valid, the caller should not visit this node.
217 */
218template<class MaskType>
221 // The "parent" bounds list remembers the bounds list of the previous node.
222 _parent_bounds = _local_bounds;
223
224 if (node()->is_final()) {
225 // If this node has a "final" bounds, we blank out all of the from
226 // bounding volumes, since we've already tested against this node's into
227 // bounds, and there's no need to test any further bounding volumes at
228 // this node level or below.
229 BoundingVolumes new_bounds;
230
231 int num_colliders = get_num_colliders();
232 new_bounds.reserve(num_colliders);
233 for (int c = 0; c < num_colliders; c++) {
234 new_bounds.push_back(nullptr);
235 }
236
237 _local_bounds = new_bounds;
238
239 } else {
240 // Otherwise, in the usual case, the bounds tests will continue.
241 // Recompute the bounds list of this node (if we have a transform).
242 const TransformState *node_transform = node()->get_transform();
243 if (!node_transform->is_identity()) {
244 CPT(TransformState) inv_transform =
245 node_transform->invert_compose(TransformState::make_identity());
246 if (!inv_transform->has_mat()) {
247 // No inverse.
248 return false;
249 }
250
251 const LMatrix4 &mat = inv_transform->get_mat();
252
253 // Now build the new bounding volumes list.
254 BoundingVolumes new_bounds;
255
256 int num_colliders = get_num_colliders();
257 new_bounds.reserve(num_colliders);
258 for (int c = 0; c < num_colliders; c++) {
259 if (!has_collider(c) ||
260 get_local_bound(c) == nullptr) {
261 new_bounds.push_back(nullptr);
262 } else {
263 const GeometricBoundingVolume *old_bound = get_local_bound(c);
264 GeometricBoundingVolume *new_bound =
265 DCAST(GeometricBoundingVolume, old_bound->make_copy());
266 new_bound->xform(mat);
267 new_bounds.push_back(new_bound);
268 }
269 }
270
271 _local_bounds = new_bounds;
272 }
273 }
274
275 return true;
276}
277#endif // CPPPARSER
278
279#ifndef CPPPARSER
280/**
281 * Returns true if there is any the maximum number of colliders that may be
282 * added to the CollisionLevelStateBase at any one time.
283 */
284template<class MaskType>
287 return CurrentMask::has_max_num_bits();
288}
289#endif // CPPPARSER
290
291#ifndef CPPPARSER
292/**
293 * Returns the maximum number of colliders that may be added to the
294 * CollisionLevelStateBase at any one time.
295 */
296template<class MaskType>
299 return CurrentMask::get_max_num_bits();
300}
301#endif // CPPPARSER
302
303#ifndef CPPPARSER
304/**
305 * Returns true if the nth collider in the LevelState is still part of the
306 * level.
307 */
308template<class MaskType>
310has_collider(int n) const {
311 nassertr(n >= 0 && n < (int)_colliders.size(), false);
312 return (_current.get_bit(n));
313}
314#endif // CPPPARSER
315
316#ifndef CPPPARSER
317/**
318 *
319 */
320template<class MaskType>
322has_any_collider() const {
323 return !_current.is_zero();
324}
325#endif // CPPPARSER
326
327#ifndef CPPPARSER
328/**
329 *
330 */
331template<class MaskType>
333omit_collider(int n) {
334 nassertv(n >= 0 && n < (int)_colliders.size());
335 nassertv(has_collider(n));
336
337 _current.clear_bit(n);
338}
339#endif // CPPPARSER
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
This is the state information the CollisionTraverser retains for each level during traversal.
void prepare_collider(const ColliderDef &def, const NodePath &root)
Adds the indicated Collider to the set of Colliders in the current level state.
This is the state information the CollisionTraverser retains for each level during traversal.
bool any_in_bounds()
Checks the bounding volume of the current node against each of our colliders.
bool has_collider(int n) const
Returns true if the nth collider in the LevelState is still part of the level.
void prepare_collider(const ColliderDef &def, const NodePath &root)
Adds the indicated Collider to the set of Colliders in the current level state.
bool apply_transform()
Applies the inverse transform from the current node, if any, onto all the colliders in the level stat...
static bool has_max_colliders()
Returns true if there is any the maximum number of colliders that may be added to the CollisionLevelS...
static int get_max_colliders()
Returns the maximum number of colliders that may be added to the CollisionLevelStateBase at any one t...
A node in the scene graph that can hold any number of CollisionSolids.
get_from_collide_mask
Returns the current "from" CollideMask.
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
int contains(const GeometricBoundingVolume *vol) const
Returns the appropriate set of IntersectionFlags to indicate the amount of intersection with the indi...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
CollideMask get_net_collide_mask(Thread *current_thread=Thread::get_current_thread()) const
Returns the union of all into_collide_mask() values set at CollisionNodes at this level and below.
Indicates a coordinate-system transform on vertices.
bool is_identity() const
Returns true if the transform represents the identity matrix, false otherwise.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20