Panda3D
|
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 ©) : 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 ¶ms) { 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 }