Panda3D
 All Classes Functions Variables Enumerations
fadeLodNode.cxx
1 // Filename: fadeLodNode.cxx
2 // Created by: sshodhan (14Jun04)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "fadeLodNode.h"
16 #include "fadeLodNodeData.h"
17 #include "cullTraverserData.h"
18 #include "cullTraverser.h"
19 #include "clockObject.h"
20 #include "colorScaleAttrib.h"
21 #include "depthWriteAttrib.h"
22 #include "transparencyAttrib.h"
23 #include "cullBinAttrib.h"
24 #include "depthOffsetAttrib.h"
25 
26 TypeHandle FadeLODNode::_type_handle;
27 
28 ////////////////////////////////////////////////////////////////////
29 // Function: FadeLODNode::Constructor
30 // Access: Published
31 // Description:
32 ////////////////////////////////////////////////////////////////////
33 FadeLODNode::
34 FadeLODNode(const string &name) :
35  LODNode(name)
36 {
37  set_cull_callback();
38 
39  _fade_time = lod_fade_time;
40  _fade_bin_name = lod_fade_bin_name;
41  _fade_bin_draw_order = lod_fade_bin_draw_order;
42  _fade_state_override = lod_fade_state_override;
43 }
44 
45 ////////////////////////////////////////////////////////////////////
46 // Function: FadeLODNode::Copy Constructor
47 // Access: Protected
48 // Description:
49 ////////////////////////////////////////////////////////////////////
50 FadeLODNode::
51 FadeLODNode(const FadeLODNode &copy) :
52  LODNode(copy)
53 {
54  _fade_time = copy._fade_time;
55  _fade_bin_name = copy._fade_bin_name;
56  _fade_bin_draw_order = copy._fade_bin_draw_order;
57  _fade_state_override = copy._fade_state_override;
58 }
59 
60 ////////////////////////////////////////////////////////////////////
61 // Function: FadeLODNode::make_copy
62 // Access: Public, Virtual
63 // Description: Returns a newly-allocated Node that is a shallow copy
64 // of this one. It will be a different Node pointer,
65 // but its internal data may or may not be shared with
66 // that of the original Node.
67 ////////////////////////////////////////////////////////////////////
69 make_copy() const {
70  return new FadeLODNode(*this);
71 }
72 
73 ////////////////////////////////////////////////////////////////////
74 // Function: FadeLODNode::cull_callback
75 // Access: Public, Virtual
76 // Description: This function will be called during the cull
77 // traversal to perform any additional operations that
78 // should be performed at cull time. This may include
79 // additional manipulation of render state or additional
80 // visible/invisible decisions, or any other arbitrary
81 // operation.
82 //
83 // Note that this function will *not* be called unless
84 // set_cull_callback() is called in the constructor of
85 // the derived class. It is necessary to call
86 // set_cull_callback() to indicated that we require
87 // cull_callback() to be called.
88 //
89 // By the time this function is called, the node has
90 // already passed the bounding-volume test for the
91 // viewing frustum, and the node's transform and state
92 // have already been applied to the indicated
93 // CullTraverserData object.
94 //
95 // The return value is true if this node should be
96 // visible, or false if it should be culled.
97 ////////////////////////////////////////////////////////////////////
98 bool FadeLODNode::
100  if (!support_fade_lod) {
101  return LODNode::cull_callback(trav, data);
102  }
103 
104  if (is_any_shown()) {
105  return show_switches_cull_callback(trav, data);
106  }
107 
108  consider_verify_lods(trav, data);
109 
110  Camera *camera = trav->get_scene()->get_camera_node();
111  NodePath this_np = data._node_path.get_node_path();
112  FadeLODNodeData *ldata =
113  DCAST(FadeLODNodeData, camera->get_aux_scene_data(this_np));
114 
116 
117  if (ldata == (AuxSceneData *)NULL || now > ldata->get_expiration_time()) {
118  // This is the first time we have rendered this instance of this
119  // LOD node in a while.
120  ldata = new FadeLODNodeData;
121  ldata->_fade_mode = FadeLODNodeData::FM_solid;
122  ldata->_fade_out = -1;
123  ldata->_fade_in = compute_child(trav, data);
124  camera->set_aux_scene_data(this_np, ldata);
125 
126  } else {
127  // We had rendered this LOD node last frame (or not too long ago,
128  // at least).
129 
130  if (ldata->_fade_mode == FadeLODNodeData::FM_solid) {
131  // We were drawing just one solid child last frame; check whether
132  // it's time to begin a transition.
133  int index = compute_child(trav, data);
134  if (index != ldata->_fade_in) {
135  // Start a transition.
136  if (index >= 0 && ldata->_fade_in >= 0 &&
137  get_out(index) > get_out(ldata->_fade_in)) {
138  // We are fading from a more-detailed model to a
139  // less-detailed model.
140  ldata->_fade_mode = FadeLODNodeData::FM_less_detail;
141  } else {
142  // We are fading from a less-detailed model to a
143  // more-detailed model.
144  ldata->_fade_mode = FadeLODNodeData::FM_more_detail;
145  }
146 
147  // We start the fade as of the last frame we actually rendered;
148  // that way, if the object happened to be offscreen for a large
149  // part of the fade, we'll just view the tail end of it--a
150  // little nicer.
151  ldata->_fade_start = ldata->get_last_render_time();
152  ldata->_fade_out = ldata->_fade_in;
153  ldata->_fade_in = index;
154  }
155  }
156 
157  if (ldata->_fade_mode != FadeLODNodeData::FM_solid) {
158  // Play the transition.
159 
160  PN_stdfloat elapsed = now - ldata->_fade_start;
161 
162  if (elapsed >= _fade_time) {
163  // Transition complete.
164  ldata->_fade_mode = FadeLODNodeData::FM_solid;
165 
166  } else {
167  PN_stdfloat half_fade_time = _fade_time * 0.5f;
168 
169  int in_child = ldata->_fade_in;
170  int out_child = ldata->_fade_out;
171 
172  if (ldata->_fade_mode == FadeLODNodeData::FM_less_detail) {
173  // If we're fading from a more-detailed model to a
174  // less-detailed model, reverse the fade effect for best
175  // visual quality.
176  elapsed = _fade_time - elapsed;
177  int t = in_child;
178  in_child = out_child;
179  out_child = t;
180  }
181 
182  nassertr(elapsed >= 0.0f && elapsed <= _fade_time, false);
183 
184  if (elapsed < half_fade_time) {
185  // FIRST HALF OF FADE
186  // Fade the new LOD in with z writing off
187  // Keep drawing the old LOD opaque with z writing on
188  if (out_child >= 0 && out_child < get_num_children()) {
189  PandaNode *child = get_child(out_child);
190  if (child != (PandaNode *)NULL) {
191  CullTraverserData next_data_out(data, child);
192  next_data_out._state =
193  next_data_out._state->compose(get_fade_1_old_state());
194  trav->traverse(next_data_out);
195  }
196  }
197 
198  if (in_child >= 0 && in_child < get_num_children()) {
199  PandaNode *child = get_child(in_child);
200  if (child != (PandaNode *)NULL) {
201  CullTraverserData next_data_in(data, child);
202 
203  PN_stdfloat in_alpha = elapsed / half_fade_time;
204  next_data_in._state =
205  next_data_in._state->compose(get_fade_1_new_state(in_alpha));
206  trav->traverse(next_data_in);
207  }
208  }
209 
210  } else {
211  // SECOND HALF OF FADE:
212  // Fade out the old LOD with z write off and
213  // draw the opaque new LOD with z write on
214  if (in_child >= 0 && in_child < get_num_children()) {
215  PandaNode *child = get_child(in_child);
216  if (child != (PandaNode *)NULL) {
217  CullTraverserData next_data_in(data, child);
218  next_data_in._state =
219  next_data_in._state->compose(get_fade_2_new_state());
220  trav->traverse(next_data_in);
221  }
222  }
223 
224  if (out_child >= 0 && out_child < get_num_children()) {
225  PandaNode *child = get_child(out_child);
226  if (child != (PandaNode *)NULL) {
227  CullTraverserData next_data_out(data, child);
228 
229  PN_stdfloat out_alpha = 1.0f - (elapsed - half_fade_time) / half_fade_time;
230  next_data_out._state =
231  next_data_out._state->compose(get_fade_2_old_state(out_alpha));
232  trav->traverse(next_data_out);
233  }
234  }
235  }
236  }
237  }
238  }
239 
240  if (ldata->_fade_mode == FadeLODNodeData::FM_solid) {
241  // This is the normal case: we're not in the middle of a
242  // transition; we're just drawing one child of the LOD.
243  int index = ldata->_fade_in;
244  if (index >= 0 && index < get_num_children()) {
245  PandaNode *child = get_child(index);
246  if (child != (PandaNode *)NULL) {
247  CullTraverserData next_data(data, child);
248  trav->traverse(next_data);
249  }
250  }
251  }
252 
253  ldata->set_last_render_time(now);
254  ldata->set_duration(_fade_time);
255 
256  return false;
257 }
258 
259 ////////////////////////////////////////////////////////////////////
260 // Function: FadeLODNode::output
261 // Access: Public, Virtual
262 // Description:
263 ////////////////////////////////////////////////////////////////////
264 void FadeLODNode::
265 output(ostream &out) const {
266  LODNode::output(out);
267  out << " fade time: " << _fade_time;
268 }
269 
270 ////////////////////////////////////////////////////////////////////
271 // Function: FadeLODNode::set_fade_bin
272 // Access: Published
273 // Description: Specifies the cull bin and draw order that is
274 // assigned to the fading part of the geometry during a
275 // transition.
276 ////////////////////////////////////////////////////////////////////
277 void FadeLODNode::
278 set_fade_bin(const string &name, int draw_order) {
279  _fade_bin_name = name;
280  _fade_bin_draw_order = draw_order;
281  _fade_1_new_state.clear();
282  _fade_2_old_state.clear();
283 }
284 
285 ////////////////////////////////////////////////////////////////////
286 // Function: FadeLODNode::set_fade_state_override
287 // Access: Published
288 // Description: Specifies the override value that is applied to the
289 // state changes necessary to apply the fade effect.
290 // This should be larger than any attrib overrides on
291 // the fading geometry.
292 ////////////////////////////////////////////////////////////////////
293 void FadeLODNode::
294 set_fade_state_override(int override) {
295  _fade_state_override = override;
296  _fade_1_old_state.clear();
297  _fade_1_new_state.clear();
298  _fade_2_old_state.clear();
299  _fade_2_new_state.clear();
300 }
301 
302 ////////////////////////////////////////////////////////////////////
303 // Function: FadeLODNode::get_fade_1_old_state
304 // Access: Protected
305 // Description: Returns a RenderState for rendering the old element
306 // during first half of fade.
307 ////////////////////////////////////////////////////////////////////
309 get_fade_1_old_state() {
310  if (_fade_1_old_state == (const RenderState *)NULL) {
311  _fade_1_old_state = RenderState::make_empty();
312  }
313 
314  return _fade_1_old_state;
315 }
316 
317 ////////////////////////////////////////////////////////////////////
318 // Function: FadeLODNode::get_fade_1_new_state
319 // Access: Protected
320 // Description: Returns a RenderState for rendering the new element
321 // during first half of fade.
322 ////////////////////////////////////////////////////////////////////
324 get_fade_1_new_state(PN_stdfloat in_alpha) {
325  if (_fade_1_new_state == (const RenderState *)NULL) {
326  _fade_1_new_state = RenderState::make
327  (TransparencyAttrib::make(TransparencyAttrib::M_alpha),
328  CullBinAttrib::make(_fade_bin_name, _fade_bin_draw_order),
329  DepthOffsetAttrib::make(),
330  _fade_state_override);
331  }
332 
333  LVecBase4 alpha_scale(1.0f, 1.0f, 1.0f, in_alpha);
334  return _fade_1_new_state->compose
335  (RenderState::make(ColorScaleAttrib::make(alpha_scale)));
336 }
337 
338 ////////////////////////////////////////////////////////////////////
339 // Function: FadeLODNode::get_fade_2_old_state
340 // Access: Protected
341 // Description: Returns a RenderState for rendering the old element
342 // during second half of fade.
343 ////////////////////////////////////////////////////////////////////
345 get_fade_2_old_state(PN_stdfloat out_alpha) {
346  if (_fade_2_old_state == (const RenderState *)NULL) {
347  _fade_2_old_state = RenderState::make
348  (TransparencyAttrib::make(TransparencyAttrib::M_alpha),
349  DepthWriteAttrib::make(DepthWriteAttrib::M_off),
350  CullBinAttrib::make(_fade_bin_name, _fade_bin_draw_order),
351  _fade_state_override);
352  }
353 
354  LVecBase4 alpha_scale(1.0f, 1.0f, 1.0f, out_alpha);
355  return _fade_2_old_state->compose
356  (RenderState::make(ColorScaleAttrib::make(alpha_scale)));
357 }
358 
359 ////////////////////////////////////////////////////////////////////
360 // Function: FadeLODNode::get_fade_2_new_state
361 // Access: Protected
362 // Description: Returns a RenderState for rendering the new element
363 // during second half of fade.
364 ////////////////////////////////////////////////////////////////////
366 get_fade_2_new_state() {
367  if (_fade_2_new_state == (const RenderState *)NULL) {
368  _fade_2_new_state = RenderState::make
369  (DepthOffsetAttrib::make(),
370  _fade_state_override);
371  }
372 
373  return _fade_2_new_state;
374 }
375 
376 ////////////////////////////////////////////////////////////////////
377 // Function: FadeLODNode::register_with_read_factory
378 // Access: Public, Static
379 // Description: Tells the BamReader how to create objects of type
380 // LODNode.
381 ////////////////////////////////////////////////////////////////////
382 void FadeLODNode::
384  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
385 }
386 
387 ////////////////////////////////////////////////////////////////////
388 // Function: FadeLODNode::write_datagram
389 // Access: Public, Virtual
390 // Description: Writes the contents of this object to the datagram
391 // for shipping out to a Bam file.
392 ////////////////////////////////////////////////////////////////////
393 void FadeLODNode::
395  LODNode::write_datagram(manager, dg);
396 }
397 
398 ////////////////////////////////////////////////////////////////////
399 // Function: FadeLODNode::make_from_bam
400 // Access: Protected, Static
401 // Description: This function is called by the BamReader's factory
402 // when a new object of type LODNode is encountered
403 // in the Bam file. It should create the LODNode
404 // and extract its information from the file.
405 ////////////////////////////////////////////////////////////////////
406 TypedWritable *FadeLODNode::
407 make_from_bam(const FactoryParams &params) {
408  FadeLODNode *node = new FadeLODNode("");
409  DatagramIterator scan;
410  BamReader *manager;
411 
412  parse_params(params, scan, manager);
413  node->fillin(scan, manager);
414 
415  return node;
416 }
417 
418 ////////////////////////////////////////////////////////////////////
419 // Function: FadeLODNode::fillin
420 // Access: Protected
421 // Description: This internal function is called by make_from_bam to
422 // read in all of the relevant data from the BamFile for
423 // the new FadeLODNode.
424 ////////////////////////////////////////////////////////////////////
425 void FadeLODNode::
426 fillin(DatagramIterator &scan, BamReader *manager) {
427  LODNode::fillin(scan, manager);
428 }
AuxSceneData * get_aux_scene_data(const NodePath &node_path) const
Returns the AuxSceneData associated with the indicated NodePath, or NULL if nothing is associated...
Definition: camera.cxx:214
This is a base class for a generic data structure that can be attached per-instance to the camera...
Definition: auxSceneData.h:35
This is the data that is associated with a particular instance of the FadeLODNode for the scene graph...
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:271
double get_expiration_time() const
Returns the frame_time at which this AuxSceneData object is currently scheduled to be removed from th...
Definition: auxSceneData.I:84
double get_last_render_time() const
Returns the last time this object was used during traversal (according to set_last_render_time()).
Definition: auxSceneData.I:72
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
Definition: fadeLodNode.cxx:99
void set_duration(double duration)
Specifies the minimum length in time, in seconds, to keep this AuxSceneData object around in the scen...
Definition: auxSceneData.I:38
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
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:267
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
void set_aux_scene_data(const NodePath &node_path, AuxSceneData *data)
Associates the indicated AuxSceneData object with the given NodePath, possibly replacing a previous d...
Definition: camera.cxx:180
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
Definition: lodNode.cxx:160
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
SceneSetup * get_scene() const
Returns the SceneSetup object.
Definition: cullTraverser.I:43
Camera * get_camera_node() const
Returns the camera used to render the scene.
Definition: sceneSetup.I:144
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
void set_fade_bin(const string &name, int draw_order)
Specifies the cull bin and draw order that is assigned to the fading part of the geometry during a tr...
PN_stdfloat get_out(int index) const
Returns the &quot;out&quot; distance of the indicated switch range.
Definition: lodNode.I:168
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
Definition: fadeLodNode.cxx:69
A Level-of-Detail node with alpha based switching.
Definition: fadeLodNode.h:26
void set_last_render_time(double render_time)
Should be called with the current frame_time each time the AuxSceneData is used during traversal...
Definition: auxSceneData.I:61
NodePath get_node_path() const
Constructs and returns an actual NodePath that represents the same path we have just traversed...
A Level-of-Detail node.
Definition: lodNode.h:31
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.I:48
int get_num_children(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of child nodes this node has.
Definition: pandaNode.I:68
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:53
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
void set_fade_state_override(int override)
Specifies the override value that is applied to the state changes necessary to apply the fade effect...
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
PandaNode * get_child(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the nth child node of this node.
Definition: pandaNode.I:82
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:37
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: lodNode.cxx:773
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
Definition: cullTraverser.h:48
static void register_with_read_factory()
Tells the BamReader how to create objects of type LODNode.