Panda3D
 All Classes Functions Variables Enumerations
fadeLodNode.cxx
00001 // Filename: fadeLodNode.cxx
00002 // Created by:  sshodhan (14Jun04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "fadeLodNode.h"
00016 #include "fadeLodNodeData.h"
00017 #include "cullTraverserData.h"
00018 #include "cullTraverser.h"
00019 #include "clockObject.h"
00020 #include "colorScaleAttrib.h"
00021 #include "depthWriteAttrib.h"
00022 #include "transparencyAttrib.h"
00023 #include "cullBinAttrib.h"
00024 #include "depthOffsetAttrib.h"
00025 
00026 TypeHandle FadeLODNode::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: FadeLODNode::Constructor
00030 //       Access: Published
00031 //  Description:
00032 ////////////////////////////////////////////////////////////////////
00033 FadeLODNode::
00034 FadeLODNode(const string &name) :
00035   LODNode(name) 
00036 {
00037   set_cull_callback();
00038 
00039   _fade_time = lod_fade_time;
00040   _fade_bin_name = lod_fade_bin_name;
00041   _fade_bin_draw_order = lod_fade_bin_draw_order;
00042   _fade_state_override = lod_fade_state_override;
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: FadeLODNode::Copy Constructor
00047 //       Access: Protected
00048 //  Description:
00049 ////////////////////////////////////////////////////////////////////
00050 FadeLODNode::
00051 FadeLODNode(const FadeLODNode &copy) :
00052   LODNode(copy)
00053 {
00054   _fade_time = copy._fade_time;
00055   _fade_bin_name = copy._fade_bin_name;
00056   _fade_bin_draw_order = copy._fade_bin_draw_order;
00057   _fade_state_override = copy._fade_state_override;
00058 }
00059 
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: FadeLODNode::make_copy
00062 //       Access: Public, Virtual
00063 //  Description: Returns a newly-allocated Node that is a shallow copy
00064 //               of this one.  It will be a different Node pointer,
00065 //               but its internal data may or may not be shared with
00066 //               that of the original Node.
00067 ////////////////////////////////////////////////////////////////////
00068 PandaNode *FadeLODNode::
00069 make_copy() const {
00070   return new FadeLODNode(*this);
00071 }
00072 
00073 ////////////////////////////////////////////////////////////////////
00074 //     Function: FadeLODNode::cull_callback
00075 //       Access: Public, Virtual
00076 //  Description: This function will be called during the cull
00077 //               traversal to perform any additional operations that
00078 //               should be performed at cull time.  This may include
00079 //               additional manipulation of render state or additional
00080 //               visible/invisible decisions, or any other arbitrary
00081 //               operation.
00082 //
00083 //               Note that this function will *not* be called unless
00084 //               set_cull_callback() is called in the constructor of
00085 //               the derived class.  It is necessary to call
00086 //               set_cull_callback() to indicated that we require
00087 //               cull_callback() to be called.
00088 //
00089 //               By the time this function is called, the node has
00090 //               already passed the bounding-volume test for the
00091 //               viewing frustum, and the node's transform and state
00092 //               have already been applied to the indicated
00093 //               CullTraverserData object.
00094 //
00095 //               The return value is true if this node should be
00096 //               visible, or false if it should be culled.
00097 ////////////////////////////////////////////////////////////////////
00098 bool FadeLODNode::
00099 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00100   if (!support_fade_lod) {
00101     return LODNode::cull_callback(trav, data);
00102   }
00103 
00104   if (is_any_shown()) {
00105     return show_switches_cull_callback(trav, data);
00106   }
00107 
00108   consider_verify_lods(trav, data);
00109 
00110   Camera *camera = trav->get_scene()->get_camera_node();
00111   NodePath this_np = data._node_path.get_node_path();
00112   FadeLODNodeData *ldata = 
00113     DCAST(FadeLODNodeData, camera->get_aux_scene_data(this_np));
00114 
00115   double now = ClockObject::get_global_clock()->get_frame_time();
00116 
00117   if (ldata == (AuxSceneData *)NULL || now > ldata->get_expiration_time()) {
00118     // This is the first time we have rendered this instance of this
00119     // LOD node in a while.
00120     ldata = new FadeLODNodeData;
00121     ldata->_fade_mode = FadeLODNodeData::FM_solid;
00122     ldata->_fade_out = -1;
00123     ldata->_fade_in = compute_child(trav, data);
00124     camera->set_aux_scene_data(this_np, ldata);
00125 
00126   } else {
00127     // We had rendered this LOD node last frame (or not too long ago,
00128     // at least).
00129 
00130     if (ldata->_fade_mode == FadeLODNodeData::FM_solid) {
00131       // We were drawing just one solid child last frame; check whether
00132       // it's time to begin a transition.
00133       int index = compute_child(trav, data);
00134       if (index != ldata->_fade_in) {
00135         // Start a transition.
00136         if (index >= 0 && ldata->_fade_in >= 0 &&
00137             get_out(index) > get_out(ldata->_fade_in)) {
00138           // We are fading from a more-detailed model to a
00139           // less-detailed model.
00140           ldata->_fade_mode = FadeLODNodeData::FM_less_detail;
00141         } else {
00142           // We are fading from a less-detailed model to a
00143           // more-detailed model.
00144           ldata->_fade_mode = FadeLODNodeData::FM_more_detail;
00145         }
00146         
00147         // We start the fade as of the last frame we actually rendered;
00148         // that way, if the object happened to be offscreen for a large
00149         // part of the fade, we'll just view the tail end of it--a
00150         // little nicer.
00151         ldata->_fade_start = ldata->get_last_render_time();
00152         ldata->_fade_out = ldata->_fade_in; 
00153         ldata->_fade_in = index;
00154       }
00155     }
00156 
00157     if (ldata->_fade_mode != FadeLODNodeData::FM_solid) {
00158       // Play the transition.
00159 
00160       PN_stdfloat elapsed = now - ldata->_fade_start;
00161         
00162       if (elapsed >= _fade_time) {
00163         // Transition complete.
00164         ldata->_fade_mode = FadeLODNodeData::FM_solid;
00165 
00166       } else {
00167         PN_stdfloat half_fade_time = _fade_time * 0.5f;
00168 
00169         int in_child = ldata->_fade_in;
00170         int out_child = ldata->_fade_out;
00171         
00172         if (ldata->_fade_mode == FadeLODNodeData::FM_less_detail) {
00173           // If we're fading from a more-detailed model to a
00174           // less-detailed model, reverse the fade effect for best
00175           // visual quality.
00176           elapsed = _fade_time - elapsed;
00177           int t = in_child;
00178           in_child = out_child;
00179           out_child = t;
00180         }
00181 
00182         nassertr(elapsed >= 0.0f && elapsed <= _fade_time, false);
00183         
00184         if (elapsed < half_fade_time) {
00185           // FIRST HALF OF FADE
00186           // Fade the new LOD in with z writing off
00187           // Keep drawing the old LOD opaque with z writing on
00188           if (out_child >= 0 && out_child < get_num_children()) {
00189             PandaNode *child = get_child(out_child);
00190             if (child != (PandaNode *)NULL) {
00191               CullTraverserData next_data_out(data, child);
00192               next_data_out._state = 
00193                 next_data_out._state->compose(get_fade_1_old_state());
00194               trav->traverse(next_data_out);
00195             }
00196           }
00197           
00198           if (in_child >= 0 && in_child < get_num_children()) {
00199             PandaNode *child = get_child(in_child);
00200             if (child != (PandaNode *)NULL) {
00201               CullTraverserData next_data_in(data, child);
00202               
00203               PN_stdfloat in_alpha = elapsed / half_fade_time;
00204               next_data_in._state = 
00205                 next_data_in._state->compose(get_fade_1_new_state(in_alpha));
00206               trav->traverse(next_data_in);
00207             }
00208           }
00209           
00210         } else {
00211           // SECOND HALF OF FADE:
00212           // Fade out the old LOD with z write off and 
00213           // draw the opaque new LOD with z write on
00214           if (in_child >= 0 && in_child < get_num_children()) {
00215             PandaNode *child = get_child(in_child);
00216             if (child != (PandaNode *)NULL) {
00217               CullTraverserData next_data_in(data, child);
00218               next_data_in._state = 
00219                 next_data_in._state->compose(get_fade_2_new_state());
00220               trav->traverse(next_data_in);
00221             }
00222           }
00223           
00224           if (out_child >= 0 && out_child < get_num_children()) {
00225             PandaNode *child = get_child(out_child);
00226             if (child != (PandaNode *)NULL) {
00227               CullTraverserData next_data_out(data, child);
00228               
00229               PN_stdfloat out_alpha = 1.0f - (elapsed - half_fade_time) / half_fade_time;  
00230               next_data_out._state = 
00231                 next_data_out._state->compose(get_fade_2_old_state(out_alpha));
00232               trav->traverse(next_data_out);
00233             }
00234           }
00235         }
00236       }
00237     }
00238   }
00239 
00240   if (ldata->_fade_mode == FadeLODNodeData::FM_solid) {
00241     // This is the normal case: we're not in the middle of a
00242     // transition; we're just drawing one child of the LOD.
00243     int index = ldata->_fade_in;
00244     if (index >= 0 && index < get_num_children()) {
00245       PandaNode *child = get_child(index);
00246       if (child != (PandaNode *)NULL) {
00247         CullTraverserData next_data(data, child);
00248         trav->traverse(next_data);
00249       }
00250     }
00251   }
00252 
00253   ldata->set_last_render_time(now);
00254   ldata->set_duration(_fade_time);
00255     
00256   return false;
00257 }
00258 
00259 ////////////////////////////////////////////////////////////////////
00260 //     Function: FadeLODNode::output
00261 //       Access: Public, Virtual
00262 //  Description:
00263 ////////////////////////////////////////////////////////////////////
00264 void FadeLODNode::
00265 output(ostream &out) const {
00266   LODNode::output(out);
00267   out << " fade time: " << _fade_time;
00268 }
00269 
00270 ////////////////////////////////////////////////////////////////////
00271 //     Function: FadeLODNode::set_fade_bin
00272 //       Access: Published
00273 //  Description: Specifies the cull bin and draw order that is
00274 //               assigned to the fading part of the geometry during a
00275 //               transition.
00276 ////////////////////////////////////////////////////////////////////
00277 void FadeLODNode::
00278 set_fade_bin(const string &name, int draw_order) {
00279   _fade_bin_name = name;
00280   _fade_bin_draw_order = draw_order;
00281   _fade_1_new_state.clear();
00282   _fade_2_old_state.clear();
00283 }
00284 
00285 ////////////////////////////////////////////////////////////////////
00286 //     Function: FadeLODNode::set_fade_state_override
00287 //       Access: Published
00288 //  Description: Specifies the override value that is applied to the
00289 //               state changes necessary to apply the fade effect.
00290 //               This should be larger than any attrib overrides on
00291 //               the fading geometry.
00292 ////////////////////////////////////////////////////////////////////
00293 void FadeLODNode::
00294 set_fade_state_override(int override) {
00295   _fade_state_override = override;
00296   _fade_1_old_state.clear();
00297   _fade_1_new_state.clear();
00298   _fade_2_old_state.clear();
00299   _fade_2_new_state.clear();
00300 }
00301 
00302 ////////////////////////////////////////////////////////////////////
00303 //     Function: FadeLODNode::get_fade_1_old_state
00304 //       Access: Protected
00305 //  Description: Returns a RenderState for rendering the old element
00306 //               during first half of fade.
00307 ////////////////////////////////////////////////////////////////////
00308 CPT(RenderState) FadeLODNode::
00309 get_fade_1_old_state() {
00310   if (_fade_1_old_state == (const RenderState *)NULL) {
00311     _fade_1_old_state = RenderState::make_empty();
00312   }
00313 
00314   return _fade_1_old_state;
00315 }
00316 
00317 ////////////////////////////////////////////////////////////////////
00318 //     Function: FadeLODNode::get_fade_1_new_state
00319 //       Access: Protected
00320 //  Description: Returns a RenderState for rendering the new element
00321 //               during first half of fade.
00322 ////////////////////////////////////////////////////////////////////
00323 CPT(RenderState) FadeLODNode::
00324 get_fade_1_new_state(PN_stdfloat in_alpha) {
00325   if (_fade_1_new_state == (const RenderState *)NULL) {
00326     _fade_1_new_state = RenderState::make
00327       (TransparencyAttrib::make(TransparencyAttrib::M_alpha),
00328        CullBinAttrib::make(_fade_bin_name, _fade_bin_draw_order),
00329        DepthOffsetAttrib::make(),
00330        _fade_state_override);
00331   }
00332 
00333   LVecBase4 alpha_scale(1.0f, 1.0f, 1.0f, in_alpha);
00334   return _fade_1_new_state->compose
00335     (RenderState::make(ColorScaleAttrib::make(alpha_scale)));
00336 }
00337 
00338 ////////////////////////////////////////////////////////////////////
00339 //     Function: FadeLODNode::get_fade_2_old_state
00340 //       Access: Protected
00341 //  Description: Returns a RenderState for rendering the old element
00342 //               during second half of fade.
00343 ////////////////////////////////////////////////////////////////////
00344 CPT(RenderState) FadeLODNode::
00345 get_fade_2_old_state(PN_stdfloat out_alpha) {
00346   if (_fade_2_old_state == (const RenderState *)NULL) {
00347     _fade_2_old_state = RenderState::make
00348       (TransparencyAttrib::make(TransparencyAttrib::M_alpha),
00349        DepthWriteAttrib::make(DepthWriteAttrib::M_off),
00350        CullBinAttrib::make(_fade_bin_name, _fade_bin_draw_order),
00351        _fade_state_override);
00352   }
00353 
00354   LVecBase4 alpha_scale(1.0f, 1.0f, 1.0f, out_alpha);
00355   return _fade_2_old_state->compose
00356     (RenderState::make(ColorScaleAttrib::make(alpha_scale)));
00357 }
00358 
00359 ////////////////////////////////////////////////////////////////////
00360 //     Function: FadeLODNode::get_fade_2_new_state
00361 //       Access: Protected
00362 //  Description: Returns a RenderState for rendering the new element
00363 //               during second half of fade.
00364 ////////////////////////////////////////////////////////////////////
00365 CPT(RenderState) FadeLODNode::
00366 get_fade_2_new_state() {
00367   if (_fade_2_new_state == (const RenderState *)NULL) {
00368     _fade_2_new_state = RenderState::make
00369       (DepthOffsetAttrib::make(),
00370        _fade_state_override);
00371   }
00372 
00373   return _fade_2_new_state;
00374 }
00375 
00376 ////////////////////////////////////////////////////////////////////
00377 //     Function: FadeLODNode::register_with_read_factory
00378 //       Access: Public, Static
00379 //  Description: Tells the BamReader how to create objects of type
00380 //               LODNode.
00381 ////////////////////////////////////////////////////////////////////
00382 void FadeLODNode::
00383 register_with_read_factory() {
00384   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00385 }
00386 
00387 ////////////////////////////////////////////////////////////////////
00388 //     Function: FadeLODNode::write_datagram
00389 //       Access: Public, Virtual
00390 //  Description: Writes the contents of this object to the datagram
00391 //               for shipping out to a Bam file.
00392 ////////////////////////////////////////////////////////////////////
00393 void FadeLODNode::
00394 write_datagram(BamWriter *manager, Datagram &dg) {
00395   LODNode::write_datagram(manager, dg);
00396 }
00397 
00398 ////////////////////////////////////////////////////////////////////
00399 //     Function: FadeLODNode::make_from_bam
00400 //       Access: Protected, Static
00401 //  Description: This function is called by the BamReader's factory
00402 //               when a new object of type LODNode is encountered
00403 //               in the Bam file.  It should create the LODNode
00404 //               and extract its information from the file.
00405 ////////////////////////////////////////////////////////////////////
00406 TypedWritable *FadeLODNode::
00407 make_from_bam(const FactoryParams &params) {
00408   FadeLODNode *node = new FadeLODNode("");
00409   DatagramIterator scan;
00410   BamReader *manager;
00411 
00412   parse_params(params, scan, manager);
00413   node->fillin(scan, manager);
00414 
00415   return node;
00416 }
00417 
00418 ////////////////////////////////////////////////////////////////////
00419 //     Function: FadeLODNode::fillin
00420 //       Access: Protected
00421 //  Description: This internal function is called by make_from_bam to
00422 //               read in all of the relevant data from the BamFile for
00423 //               the new FadeLODNode.
00424 ////////////////////////////////////////////////////////////////////
00425 void FadeLODNode::
00426 fillin(DatagramIterator &scan, BamReader *manager) {
00427   LODNode::fillin(scan, manager);
00428 }
 All Classes Functions Variables Enumerations