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