Panda3D
lodNode.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 lodNode.I
10  * @author drose
11  * @date 2002-03-06
12  */
13 
14 /**
15  *
16  */
17 INLINE LODNode::
18 LODNode(const std::string &name) :
19  PandaNode(name)
20 {
21  set_cull_callback();
22 }
23 
24 /**
25  *
26  */
27 INLINE LODNode::
28 LODNode(const LODNode &copy) :
29  PandaNode(copy),
30  _cycler(copy._cycler)
31 {
32 }
33 
34 /**
35  * Adds a switch range to the LODNode. This implies that the corresponding
36  * child node has been parented to the node.
37  *
38  * The sense of in vs. out distances is as if the object were coming towards
39  * you from far away: it switches "in" at the far distance, and switches "out"
40  * at the close distance. Thus, "in" should be larger than "out".
41  */
42 INLINE void LODNode::
43 add_switch(PN_stdfloat in, PN_stdfloat out) {
44  nassertv(in >= out);
45 
46  CDWriter cdata(_cycler);
47  cdata->_switch_vector.push_back(Switch(in, out));
48  cdata->check_limits();
49 
50  if (cdata->_num_shown != 0) {
51  mark_internal_bounds_stale();
52  }
53 }
54 
55 /**
56  * Changes the switching range of a particular child of the LODNode. See
57  * add_switch().
58  */
59 INLINE bool LODNode::
60 set_switch(int index, PN_stdfloat in, PN_stdfloat out) {
61  nassertr(in >= out, false);
62 
63  CDWriter cdata(_cycler);
64  nassertr(index >= 0 && index < (int)cdata->_switch_vector.size(), false);
65  cdata->_switch_vector[index].set_range(in, out);
66  cdata->check_limits();
67 
68  if (cdata->_num_shown != 0) {
69  mark_internal_bounds_stale();
70  }
71 
72  return true;
73 }
74 
75 /**
76  * Removes the set of switching ranges for the LODNode, presumably in
77  * conjunction with removing all of its children. See add_switch().
78  */
79 INLINE void LODNode::
81  CDWriter cdata(_cycler);
82  cdata->_switch_vector.clear();
83  cdata->_lowest = 0;
84  cdata->_highest = 0;
85 
86  if (cdata->_num_shown != 0) {
87  mark_internal_bounds_stale();
88  }
89 }
90 
91 /**
92  * Returns the number of switch ranges added to the LODNode. This should
93  * correspond to the number of children of the node in order for the LODNode
94  * to function correctly.
95  */
96 INLINE int LODNode::
97 get_num_switches() const {
98  CDReader cdata(_cycler);
99  return cdata->_switch_vector.size();
100 }
101 
102 /**
103  * Returns the multiplier for lod distances
104  */
105 INLINE PN_stdfloat LODNode::
106 get_lod_scale() const {
107  CDReader cdata(_cycler);
108  return cdata->_lod_scale;
109 }
110 
111 /**
112  * Sets the multiplier for lod distances. A higher value means you'll see
113  * farther switchs than normal
114  */
115 INLINE void LODNode::
116 set_lod_scale(PN_stdfloat value) {
117  CDWriter cdata(_cycler);
118  cdata->_lod_scale = value;
119 }
120 
121 
122 /**
123  * Returns the "in" distance of the indicated switch range. This should be
124  * larger than the "out" distance of the same range.
125  */
126 INLINE PN_stdfloat LODNode::
127 get_in(int index) const {
128  CDReader cdata(_cycler);
129  nassertr(index >= 0 && index < (int)cdata->_switch_vector.size(), 0.0);
130  return cdata->_switch_vector[index].get_in();
131 }
132 
133 /**
134  * Returns the "out" distance of the indicated switch range. This should be
135  * smaller than the "in" distance of the same range.
136  */
137 INLINE PN_stdfloat LODNode::
138 get_out(int index) const {
139  CDReader cdata(_cycler);
140  nassertr(index >= 0 && index < (int)cdata->_switch_vector.size(), 0.0);
141  return cdata->_switch_vector[index].get_out();
142 }
143 
144 /**
145  * Returns the index number of the child with the lowest level of detail; that
146  * is, the one that is designed to be seen from the farthest away. This is
147  * usually the first child, but it is not necessarily so.
148  */
149 INLINE int LODNode::
150 get_lowest_switch() const {
151  CDReader cdata(_cycler);
152  return cdata->_lowest;
153 }
154 
155 /**
156  * Returns the index number of the child with the highest level of detail;
157  * that is, the one that is designed to be seen from the closest to the
158  * camera. This is usually the last child, but it is not necessarily so.
159  */
160 INLINE int LODNode::
161 get_highest_switch() const {
162  CDReader cdata(_cycler);
163  return cdata->_highest;
164 }
165 
166 /**
167  * Forces the LODNode to show the indicated level instead of the level that
168  * would normally be shown based on the distance from the camera.
169  */
170 INLINE void LODNode::
171 force_switch(int index) {
172  CDWriter cdata(_cycler);
173  cdata->_force_switch = index;
174  cdata->_got_force_switch = true;
175 }
176 
177 /**
178  * Undoes the effect of a previous call to force_switch() and releases the
179  * LODNode to once again display the normal level.
180  */
181 INLINE void LODNode::
183  CDWriter cdata(_cycler);
184  cdata->_got_force_switch = false;
185 }
186 
187 /**
188  * Specifies the center of the LOD. This is the point that is compared to the
189  * camera (in camera space) to determine the particular LOD that should be
190  * chosen.
191  */
192 INLINE void LODNode::
193 set_center(const LPoint3 &center) {
194  CDWriter cdata(_cycler);
195  cdata->_center = center;
196 
197  if (cdata->_num_shown != 0) {
198  mark_internal_bounds_stale();
199  }
200 }
201 
202 /**
203  * Returns the center of the LOD. This is the point that is compared to the
204  * camera (in camera space) to determine the particular LOD that should be
205  * chosen.
206  */
207 INLINE const LPoint3 &LODNode::
208 get_center() const {
209  CDReader cdata(_cycler);
210  return cdata->_center;
211 }
212 
213 /**
214  * Returns true if any switch has been shown with show_switch(), indicating
215  * the LODNode is in debug show mode; or false if it is in the normal mode.
216  */
217 INLINE bool LODNode::
218 is_any_shown() const {
219  CDReader cdata(_cycler);
220  return (cdata->_num_shown != 0);
221 }
222 
223 /**
224  * To be called internally when the node is rendered, this will raise an
225  * assertion if verify-lods is configured true, and verify_child_bounds()
226  * returns false.
227  */
228 INLINE void LODNode::
229 consider_verify_lods(CullTraverser *trav, CullTraverserData &data) {
230 #ifndef NDEBUG
231  if (verify_lods) {
232  do_auto_verify_lods(trav, data);
233  }
234 #endif // NDEBUG
235 }
236 
237 /**
238  *
239  */
240 INLINE LODNode::CData::
241 CData() :
242  _center(0.0f, 0.0f, 0.0f),
243  _lowest(0),
244  _highest(0),
245  _got_force_switch(false),
246  _force_switch(0),
247  _num_shown(0),
248  _lod_scale(1)
249 {
250 }
251 
252 /**
253  *
254  */
255 INLINE LODNode::CData::
256 CData(const LODNode::CData &copy) :
257  _center(copy._center),
258  _switch_vector(copy._switch_vector),
259  _lowest(copy._lowest),
260  _highest(copy._highest),
261  _bounds_seq(UpdateSeq::old()),
262  _got_force_switch(copy._got_force_switch),
263  _force_switch(copy._force_switch),
264  _num_shown(copy._num_shown),
265  _lod_scale(copy._lod_scale)
266 {
267 }
268 
269 /**
270  *
271  */
272 INLINE LODNode::Switch::
273 Switch(PN_stdfloat in, PN_stdfloat out) :
274  _shown(false),
275  _bounds_seq(UpdateSeq::old()),
276  _verify_ok(false)
277 {
278  set_range(in, out);
279 }
280 
281 /**
282  *
283  */
284 INLINE PN_stdfloat LODNode::Switch::
285 get_in() const {
286  return _in;
287 }
288 
289 /**
290  *
291  */
292 INLINE PN_stdfloat LODNode::Switch::
293 get_out() const {
294  return _out;
295 }
296 
297 /**
298  *
299  */
300 INLINE void LODNode::Switch::
301 set_range(PN_stdfloat in, PN_stdfloat out) {
302  _in = in;
303  _out = out;
304  clear_ring_viz();
305 }
306 
307 /**
308  * Returns true if the indicated distance is within the range for the LOD.
309  */
310 INLINE bool LODNode::Switch::
311 in_range(PN_stdfloat dist) const {
312  return (dist >= _out && dist < _in);
313 }
314 
315 /**
316  * Returns true if the indicated distance squared is within the range for the
317  * LOD. (The distance value is understood to be the square of the distance
318  * from the camera to the object.)
319  */
320 INLINE bool LODNode::Switch::
321 in_range_2(PN_stdfloat dist2) const {
322  return (dist2 >= _out * _out && dist2 < _in * _in);
323 }
324 
325 /**
326  * Scales the switching distances by the indicated factor.
327  */
328 INLINE void LODNode::Switch::
329 rescale(PN_stdfloat factor) {
330  _in *= factor;
331  _out *= factor;
332  clear_ring_viz();
333 }
334 
335 /**
336  * Returns true if show() has been called.
337  */
338 INLINE bool LODNode::Switch::
339 is_shown() const {
340  return _shown;
341 }
342 
343 /**
344  * Shows this ring in debug mode using the indicated color.
345  */
346 INLINE void LODNode::Switch::
347 show(const LColor &color) {
348  _shown = true;
349  _show_color = color;
350 }
351 
352 /**
353  * Undoes a previous call to show().
354  */
355 INLINE void LODNode::Switch::
356 hide() {
357  _shown = false;
358 }
359 
360 /**
361  * Returns a PandaNode suitable for rendering the ring associated with this
362  * switch.
363  */
364 INLINE PandaNode *LODNode::Switch::
365 get_ring_viz() const {
366  if (_ring_viz.is_null()) {
367  ((Switch *)this)->compute_ring_viz();
368  }
369 
370  return _ring_viz;
371 }
372 
373 /**
374  * Returns a PandaNode suitable for rendering the center spindle of the
375  * LODNode, in the color of this switch.
376  */
377 INLINE PandaNode *LODNode::Switch::
378 get_spindle_viz() const {
379  if (_spindle_viz.is_null()) {
380  ((Switch *)this)->compute_spindle_viz();
381  }
382 
383  return _spindle_viz;
384 }
385 
386 /**
387  * Returns a RenderState suitable for drawing the visible children of this
388  * switch level when the show_switch() debugging mode is enabled.
389  */
390 INLINE const RenderState *LODNode::Switch::
391 get_viz_model_state() const {
392  if (_viz_model_state.is_null()) {
393  ((Switch *)this)->compute_viz_model_state();
394  }
395 
396  return _viz_model_state;
397 }
398 
399 /**
400  * Writes the contents of the Switch out to the datagram, presumably in
401  * preparation to writing to a Bam file.
402  */
403 INLINE void LODNode::Switch::
404 write_datagram(Datagram &destination) const {
405  destination.add_stdfloat(_in);
406  destination.add_stdfloat(_out);
407 }
408 
409 /**
410  * Reads the contents of the Switch from the datagram, presumably in response
411  * to reading a Bam file.
412  */
413 INLINE void LODNode::Switch::
414 read_datagram(DatagramIterator &source) {
415  _in = source.get_stdfloat();
416  _out = source.get_stdfloat();
417 }
418 
419 /**
420  * Resets the internal cache values for the ring and spindle viz, and related
421  * pointers, for the set_switch() debugging mode.
422  */
423 INLINE void LODNode::Switch::
424 clear_ring_viz() {
425  _ring_viz.clear();
426  _spindle_viz.clear();
427  _viz_model_state.clear();
428  _bounds_seq = UpdateSeq::old();
429 }
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
void clear_switches()
Removes the set of switching ranges for the LODNode, presumably in conjunction with removing all of i...
Definition: lodNode.I:80
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
Definition: datagram.I:133
void force_switch(int index)
Forces the LODNode to show the indicated level instead of the level that would normally be shown base...
Definition: lodNode.I:171
void add_switch(PN_stdfloat in, PN_stdfloat out)
Adds a switch range to the LODNode.
Definition: lodNode.I:43
set_lod_scale
Sets the multiplier for lod distances.
Definition: lodNode.h:82
A Level-of-Detail node.
Definition: lodNode.h:28
bool set_switch(int index, PN_stdfloat in, PN_stdfloat out)
Changes the switching range of a particular child of the LODNode.
Definition: lodNode.I:60
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
get_in
Returns the "in" distance of the indicated switch range.
Definition: lodNode.h:59
bool is_any_shown() const
Returns true if any switch has been shown with show_switch(), indicating the LODNode is in debug show...
Definition: lodNode.I:218
A class to retrieve the individual data elements previously stored in a Datagram.
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
void clear_force_switch()
Undoes the effect of a previous call to force_switch() and releases the LODNode to once again display...
Definition: lodNode.I:182
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
set_center
Specifies the center of the LOD.
Definition: lodNode.h:83
get_out
Returns the "out" distance of the indicated switch range.
Definition: lodNode.h:61