Panda3D
sceneGraphAnalyzerMeter.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 sceneGraphAnalyzerMeter.cxx
10  * @author pratt
11  * @date 2007-02-14
12  */
13 
15 #include "camera.h"
16 #include "displayRegion.h"
17 #include "orthographicLens.h"
18 #include "config_grutil.h"
19 #include "depthTestAttrib.h"
20 #include "depthWriteAttrib.h"
21 #include "pStatTimer.h"
22 #include "omniBoundingVolume.h"
23 #include <stdio.h> // For sprintf/snprintf
24 
25 PStatCollector SceneGraphAnalyzerMeter::_show_analyzer_pcollector("*:Show scene graph analysis");
26 
27 TypeHandle SceneGraphAnalyzerMeter::_type_handle;
28 
29 /**
30  *
31  */
32 SceneGraphAnalyzerMeter::
33 SceneGraphAnalyzerMeter(const std::string &name, PandaNode *node) :
34  TextNode(name),
35  _last_aspect_ratio(-1) {
36 
37  set_cull_callback();
38 
39  // Don't do frustum culling, as the text will always be in view.
41  set_final(true);
42 
43  Thread *current_thread = Thread::get_current_thread();
44 
45  _update_interval = scene_graph_analyzer_meter_update_interval;
46  _last_update = 0.0f;
47  _node = node;
48  _clock_object = ClockObject::get_global_clock();
49 
50  set_align(A_left);
51  set_transform(LMatrix4::scale_mat(scene_graph_analyzer_meter_scale) *
52  LMatrix4::translate_mat(LVector3::rfu(scene_graph_analyzer_meter_side_margins * scene_graph_analyzer_meter_scale, 0.0f, -scene_graph_analyzer_meter_scale)));
53  set_card_color(0.0f, 0.0f, 0.0f, 0.4);
54  set_card_as_margin(scene_graph_analyzer_meter_side_margins, scene_graph_analyzer_meter_side_margins, 0.1f, 0.0f);
55  set_usage_hint(Geom::UH_client);
56 
57  do_update(current_thread);
58 }
59 
60 /**
61  *
62  */
63 SceneGraphAnalyzerMeter::
64 ~SceneGraphAnalyzerMeter() {
65  clear_window();
66 }
67 
68 /**
69  * Sets up the frame rate meter to create a DisplayRegion to render itself
70  * into the indicated window.
71  */
74  clear_window();
75 
76  _window = window;
77 
78  _root = NodePath("scene_graph_analyzer_root");
79  _root.attach_new_node(this);
80 
81  CPT(RenderAttrib) dt = DepthTestAttrib::make(DepthTestAttrib::M_none);
82  CPT(RenderAttrib) dw = DepthWriteAttrib::make(DepthWriteAttrib::M_off);
83  _root.node()->set_attrib(dt, 1);
84  _root.node()->set_attrib(dw, 1);
85  _root.set_material_off(1);
86  _root.set_two_sided(1, 1);
87 
88  // If we don't set this explicitly, Panda will cause it to be rendered
89  // in a back-to-front cull bin, which will cause the bounding volume
90  // to be computed unnecessarily. Saves a little bit of overhead.
91  _root.set_bin("unsorted", 0);
92 
93  // Create a display region that covers the entire window.
94  _display_region = _window->make_display_region();
95  _display_region->set_sort(scene_graph_analyzer_meter_layer_sort);
96 
97  // Finally, we need a camera to associate with the display region.
98  PT(Camera) camera = new Camera("scene_graph_analyzer_camera");
99  NodePath camera_np = _root.attach_new_node(camera);
100 
101  PT(Lens) lens = new OrthographicLens;
102 
103  // We choose these values such that we can place the text against (0, 0).
104  static const PN_stdfloat left = 0.0f;
105  static const PN_stdfloat right = 2.0f;
106  static const PN_stdfloat bottom = -2.0f;
107  static const PN_stdfloat top = 0.0f;
108  lens->set_film_size(right - left, top - bottom);
109  lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5);
110  lens->set_near_far(-1000, 1000);
111 
112  camera->set_lens(lens);
113  camera->set_scene(_root);
114  _display_region->set_camera(camera_np);
115 }
116 
117 /**
118  * Undoes the effect of a previous call to setup_window().
119  */
122  if (_window != nullptr) {
123  _window->remove_display_region(_display_region);
124  _window = nullptr;
125  _display_region = nullptr;
126  }
127  _root = NodePath();
128 }
129 
130 /**
131  * This function will be called during the cull traversal to perform any
132  * additional operations that should be performed at cull time. This may
133  * include additional manipulation of render state or additional
134  * visible/invisible decisions, or any other arbitrary operation.
135  *
136  * Note that this function will *not* be called unless set_cull_callback() is
137  * called in the constructor of the derived class. It is necessary to call
138  * set_cull_callback() to indicated that we require cull_callback() to be
139  * called.
140  *
141  * By the time this function is called, the node has already passed the
142  * bounding-volume test for the viewing frustum, and the node's transform and
143  * state have already been applied to the indicated CullTraverserData object.
144  *
145  * The return value is true if this node should be visible, or false if it
146  * should be culled.
147  */
148 bool SceneGraphAnalyzerMeter::
149 cull_callback(CullTraverser *trav, CullTraverserData &data) {
150  Thread *current_thread = trav->get_current_thread();
151 
152  // Statistics
153  PStatTimer timer(_show_analyzer_pcollector, current_thread);
154 
155  // This is probably a good time to check if the aspect ratio on the window
156  // has changed.
157  int width = _display_region->get_pixel_width();
158  int height = _display_region->get_pixel_height();
159  PN_stdfloat aspect_ratio = 1;
160  if (width != 0 && height != 0) {
161  aspect_ratio = (PN_stdfloat)height / (PN_stdfloat)width;
162  }
163 
164  // Scale the transform by the calculated aspect ratio.
165  if (aspect_ratio != _last_aspect_ratio) {
166  _aspect_ratio_transform = TransformState::make_scale(LVecBase3(aspect_ratio, 1, 1));
167  _last_aspect_ratio = aspect_ratio;
168  }
169  data._net_transform = data._net_transform->compose(_aspect_ratio_transform);
170 
171  // Check to see if it's time to update.
172  double now = _clock_object->get_frame_time(current_thread);
173  double elapsed = now - _last_update;
174  if (elapsed < 0.0 || elapsed >= _update_interval) {
175  do_update(current_thread);
176  }
177 
178  return TextNode::cull_callback(trav, data);
179 }
180 
181 /**
182  * Resets the text according to the current frame rate.
183  */
184 void SceneGraphAnalyzerMeter::
185 do_update(Thread *current_thread) {
186  _last_update = _clock_object->get_frame_time(current_thread);
187 
188  _scene_graph_analyzer.clear();
189  _scene_graph_analyzer.add_node( _node );
190 
191  static const size_t buffer_size = 1024;
192  char buffer[buffer_size];
193 
194  const char *pattern = "Nodes: %d\n"
195  "Instances: %d\n"
196  "Transforms: %d\n"
197  "Nodes with Attribs: %d\n"
198  "GeomNodes: %d\n"
199  "Geoms: %d\n"
200  "GeomVertexDatas: %d\n"
201  "Vertices: %d\n"
202  "Normals: %d\n"
203  "TexCoords: %d\n"
204  "Tris: %d\n"
205  "Lines: %d\n"
206  "Points: %d\n"
207  "Texture memory: %.1f KB\n";
208 
209 #if defined(WIN32_VC) || defined(WIN64_VC)
210  _snprintf(buffer, buffer_size, pattern,
211  _scene_graph_analyzer.get_num_nodes(),
212  _scene_graph_analyzer.get_num_instances(),
213  _scene_graph_analyzer.get_num_transforms(),
214  _scene_graph_analyzer.get_num_nodes_with_attribs(),
215  _scene_graph_analyzer.get_num_geom_nodes(),
216  _scene_graph_analyzer.get_num_geoms(),
217  _scene_graph_analyzer.get_num_geom_vertex_datas(),
218  _scene_graph_analyzer.get_num_vertices(),
219  _scene_graph_analyzer.get_num_normals(),
220  _scene_graph_analyzer.get_num_texcoords(),
221  _scene_graph_analyzer.get_num_tris(),
222  _scene_graph_analyzer.get_num_lines(),
223  _scene_graph_analyzer.get_num_points(),
224  _scene_graph_analyzer.get_texture_bytes()/1024.0);
225 #else
226  snprintf(buffer, buffer_size, pattern,
227  _scene_graph_analyzer.get_num_nodes(),
228  _scene_graph_analyzer.get_num_instances(),
229  _scene_graph_analyzer.get_num_transforms(),
230  _scene_graph_analyzer.get_num_nodes_with_attribs(),
231  _scene_graph_analyzer.get_num_geom_nodes(),
232  _scene_graph_analyzer.get_num_geoms(),
233  _scene_graph_analyzer.get_num_geom_vertex_datas(),
234  _scene_graph_analyzer.get_num_vertices(),
235  _scene_graph_analyzer.get_num_normals(),
236  _scene_graph_analyzer.get_num_texcoords(),
237  _scene_graph_analyzer.get_num_tris(),
238  _scene_graph_analyzer.get_num_lines(),
239  _scene_graph_analyzer.get_num_points(),
240  _scene_graph_analyzer.get_texture_bytes()/1024.0);
241 #endif
242  nassertv(strlen(buffer) < buffer_size);
243 
244  if (get_text() == buffer) {
245  // Never mind; the data hasn't changed.
246  return;
247  }
248 
249  set_text(buffer);
250 }
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_bounds(const BoundingVolume *volume)
Resets the bounding volume so that it is the indicated volume.
Definition: pandaNode.cxx:1913
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_bin(const std::string &bin_name, int draw_order, int priority=0)
Assigns the geometry at this level and below to the named rendering bin.
Definition: nodePath.cxx:2801
void add_node(PandaNode *node)
Adds a new node to the set of data for analysis.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear()
Resets all of the data in the analyzer in preparation for a new run.
set_text
Changes the text that is stored in the encoder.
Definition: textEncoder.h:124
set_transform
Sets the transform that will be applied to this node and below.
Definition: pandaNode.h:183
A lightweight class that represents a single element that may be timed and/or counted via stats.
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
set_film_size
Sets the horizontal size of the film without changing its shape.
Definition: lens.h:82
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
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition: nodePath.cxx:563
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_text
Returns the current text, as encoded via the current encoding system.
Definition: textEncoder.h:124
This is a base class for the various different classes that represent the result of a frame of render...
void set_attrib(const RenderAttrib *attrib, int override=0)
Adds the indicated render attribute to the scene graph on this node.
Definition: pandaNode.cxx:944
void clear_window()
Undoes the effect of a previous call to setup_window().
An orthographic lens.
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
A thread; that is, a lightweight process.
Definition: thread.h:46
void set_material_off(int priority=0)
Sets the geometry at this level and below to render using no material.
Definition: nodePath.cxx:4113
The primary interface to this module.
Definition: textNode.h:48
void setup_window(GraphicsOutput *window)
Sets up the frame rate meter to create a DisplayRegion to render itself into the indicated window.
This is a special kind of GeometricBoundingVolume that fills all of space.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
void set_two_sided(bool two_sided, int priority=0)
Specifically sets or disables two-sided rendering mode on this particular node.
Definition: nodePath.cxx:4430
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.