Panda3D
sceneGraphAnalyzerMeter.cxx
1 // Filename: sceneGraphAnalyzerMeter.cxx
2 // Created by: pratt (14Feb07)
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 "sceneGraphAnalyzerMeter.h"
16 #include "camera.h"
17 #include "displayRegion.h"
18 #include "orthographicLens.h"
19 #include "config_grutil.h"
20 #include "depthTestAttrib.h"
21 #include "depthWriteAttrib.h"
22 #include "pStatTimer.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 // Function: SceneGraphAnalyzerMeter::Constructor
31 // Access: Published
32 // Description:
33 ////////////////////////////////////////////////////////////////////
34 SceneGraphAnalyzerMeter::
35 SceneGraphAnalyzerMeter(const string &name, PandaNode *node) : TextNode(name) {
36  set_cull_callback();
37 
38  Thread *current_thread = Thread::get_current_thread();
39 
40  _update_interval = scene_graph_analyzer_meter_update_interval;
41  _last_update = 0.0f;
42  _node = node;
43  _clock_object = ClockObject::get_global_clock();
44 
45  set_align(A_left);
46  set_transform(LMatrix4::scale_mat(scene_graph_analyzer_meter_scale) *
47  LMatrix4::translate_mat(LVector3::rfu(-1.0f + scene_graph_analyzer_meter_side_margins * scene_graph_analyzer_meter_scale, 0.0f, 1.0f - scene_graph_analyzer_meter_scale)));
48  set_card_color(0.0f, 0.0f, 0.0f, 0.4);
49  set_card_as_margin(scene_graph_analyzer_meter_side_margins, scene_graph_analyzer_meter_side_margins, 0.1f, 0.0f);
50  set_usage_hint(Geom::UH_client);
51 
52  do_update(current_thread);
53 }
54 
55 ////////////////////////////////////////////////////////////////////
56 // Function: SceneGraphAnalyzerMeter::Destructor
57 // Access: Published, Virtual
58 // Description:
59 ////////////////////////////////////////////////////////////////////
60 SceneGraphAnalyzerMeter::
61 ~SceneGraphAnalyzerMeter() {
62  clear_window();
63 }
64 
65 ////////////////////////////////////////////////////////////////////
66 // Function: SceneGraphAnalyzerMeter::setup_window
67 // Access: Published
68 // Description: Sets up the frame rate meter to create a
69 // DisplayRegion to render itself into the indicated
70 // 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  // Create a display region that covers the entire window.
89  _display_region = _window->make_display_region();
90  _display_region->set_sort(scene_graph_analyzer_meter_layer_sort);
91 
92  // Finally, we need a camera to associate with the display region.
93  PT(Camera) camera = new Camera("scene_graph_analyzer_camera");
94  NodePath camera_np = _root.attach_new_node(camera);
95 
96  PT(Lens) lens = new OrthographicLens;
97 
98  static const PN_stdfloat left = -1.0f;
99  static const PN_stdfloat right = 1.0f;
100  static const PN_stdfloat bottom = -1.0f;
101  static const PN_stdfloat top = 1.0f;
102  lens->set_film_size(right - left, top - bottom);
103  lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5);
104  lens->set_near_far(-1000, 1000);
105 
106  camera->set_lens(lens);
107  camera->set_scene(_root);
108  _display_region->set_camera(camera_np);
109 }
110 
111 ////////////////////////////////////////////////////////////////////
112 // Function: SceneGraphAnalyzerMeter::clear_window
113 // Access: Published
114 // Description: Undoes the effect of a previous call to
115 // setup_window().
116 ////////////////////////////////////////////////////////////////////
119  if (_window != (GraphicsOutput *)NULL) {
120  _window->remove_display_region(_display_region);
121  _window = (GraphicsOutput *)NULL;
122  _display_region = (DisplayRegion *)NULL;
123  }
124  _root = NodePath();
125 }
126 
127 ////////////////////////////////////////////////////////////////////
128 // Function: SceneGraphAnalyzerMeter::cull_callback
129 // Access: Protected, Virtual
130 // Description: This function will be called during the cull
131 // traversal to perform any additional operations that
132 // should be performed at cull time. This may include
133 // additional manipulation of render state or additional
134 // visible/invisible decisions, or any other arbitrary
135 // operation.
136 //
137 // Note that this function will *not* be called unless
138 // set_cull_callback() is called in the constructor of
139 // the derived class. It is necessary to call
140 // set_cull_callback() to indicated that we require
141 // cull_callback() to be called.
142 //
143 // By the time this function is called, the node has
144 // already passed the bounding-volume test for the
145 // viewing frustum, and the node's transform and state
146 // have already been applied to the indicated
147 // CullTraverserData object.
148 //
149 // The return value is true if this node should be
150 // visible, or false if it should be culled.
151 ////////////////////////////////////////////////////////////////////
152 bool SceneGraphAnalyzerMeter::
153 cull_callback(CullTraverser *trav, CullTraverserData &data) {
154  Thread *current_thread = trav->get_current_thread();
155 
156  // Statistics
157  PStatTimer timer(_show_analyzer_pcollector, current_thread);
158 
159  // Check to see if it's time to update.
160  double now = _clock_object->get_frame_time(current_thread);
161  double elapsed = now - _last_update;
162  if (elapsed < 0.0 || elapsed >= _update_interval) {
163  do_update(current_thread);
164  }
165 
166  return TextNode::cull_callback(trav, data);
167 }
168 
169 ////////////////////////////////////////////////////////////////////
170 // Function: SceneGraphAnalyzerMeter::do_update
171 // Access: Private
172 // Description: Resets the text according to the current frame rate.
173 ////////////////////////////////////////////////////////////////////
174 void SceneGraphAnalyzerMeter::
175 do_update(Thread *current_thread) {
176  _last_update = _clock_object->get_frame_time(current_thread);
177 
178  _scene_graph_analyzer.clear();
179  _scene_graph_analyzer.add_node( _node );
180 
181  static const size_t buffer_size = 1024;
182  char buffer[buffer_size];
183 
184  const char *pattern = "Nodes: %d\n"
185  "Instances: %d\n"
186  "Transforms: %d\n"
187  "Nodes with Attribs: %d\n"
188  "GeomNodes: %d\n"
189  "Geoms: %d\n"
190  "GeomVertexDatas: %d\n"
191  "Vertices: %d\n"
192  "Normals: %d\n"
193  "TexCoords: %d\n"
194  "Tris: %d\n"
195  "Lines: %d\n"
196  "Points: %d\n"
197  "Texture memory: %.1f KB\n";
198 
199 #if defined(WIN32_VC) || defined(WIN64_VC)
200  _snprintf(buffer, buffer_size, pattern,
201  _scene_graph_analyzer.get_num_nodes(),
202  _scene_graph_analyzer.get_num_instances(),
203  _scene_graph_analyzer.get_num_transforms(),
204  _scene_graph_analyzer.get_num_nodes_with_attribs(),
205  _scene_graph_analyzer.get_num_geom_nodes(),
206  _scene_graph_analyzer.get_num_geoms(),
207  _scene_graph_analyzer.get_num_geom_vertex_datas(),
208  _scene_graph_analyzer.get_num_vertices(),
209  _scene_graph_analyzer.get_num_normals(),
210  _scene_graph_analyzer.get_num_texcoords(),
211  _scene_graph_analyzer.get_num_tris(),
212  _scene_graph_analyzer.get_num_lines(),
213  _scene_graph_analyzer.get_num_points(),
214  _scene_graph_analyzer.get_texture_bytes()/1024.0);
215 #else
216  snprintf(buffer, buffer_size, pattern,
217  _scene_graph_analyzer.get_num_nodes(),
218  _scene_graph_analyzer.get_num_instances(),
219  _scene_graph_analyzer.get_num_transforms(),
220  _scene_graph_analyzer.get_num_nodes_with_attribs(),
221  _scene_graph_analyzer.get_num_geom_nodes(),
222  _scene_graph_analyzer.get_num_geoms(),
223  _scene_graph_analyzer.get_num_geom_vertex_datas(),
224  _scene_graph_analyzer.get_num_vertices(),
225  _scene_graph_analyzer.get_num_normals(),
226  _scene_graph_analyzer.get_num_texcoords(),
227  _scene_graph_analyzer.get_num_tris(),
228  _scene_graph_analyzer.get_num_lines(),
229  _scene_graph_analyzer.get_num_points(),
230  _scene_graph_analyzer.get_texture_bytes()/1024.0);
231 #endif
232  nassertv(strlen(buffer) < buffer_size);
233 
234  if (get_text() == buffer) {
235  // Never mind; the data hasn't changed.
236  return;
237  }
238 
239  set_text(buffer);
240 }
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:271
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:60
static LMatrix4f scale_mat(const LVecBase3f &scale)
Returns a matrix that applies the indicated scale in each of the three axes.
Definition: lmatrix.h:2456
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:45
static LMatrix4f translate_mat(const LVecBase3f &trans)
Returns a matrix that applies the indicated translation.
Definition: lmatrix.h:2397
void set_text(const string &text)
Changes the text that is displayed under the TextNode.
Definition: textNode.I:1171
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:33
void set_film_size(PN_stdfloat width)
Sets the horizontal size of the film without changing its shape.
Definition: lens.I:226
void add_node(PandaNode *node)
Adds a new node to the set of data for analysis.
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:34
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
void clear()
Resets all of the data in the analyzer in preparation for a new run.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
static LVector3f rfu(float right, float fwd, float up, CoordinateSystem cs=CS_default)
Returns a vector that is described by its right, forward, and up components, in whatever way the coor...
Definition: lvector3.h:645
A lightweight class that represents a single element that may be timed and/or counted via stats...
void set_card_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Specifies that a (possibly opaque or semitransparent) card will be held behind the text when it is ne...
Definition: textNode.I:455
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:723
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:1107
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:284
A thread; that is, a lightweight process.
Definition: thread.h:51
void set_material_off(int priority=0)
Sets the geometry at this level and below to render using no material.
Definition: nodePath.cxx:4760
The primary interface to this module.
Definition: textNode.h:52
void setup_window(GraphicsOutput *window)
Sets up the frame rate meter to create a DisplayRegion to render itself into the indicated window...
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:61
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
void set_usage_hint(Geom::UsageHint usage_hint)
Specifies the UsageHint that will be applied to generated geometry.
Definition: textNode.I:667
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:5135
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
void set_transform(const LMatrix4 &transform)
Sets an additional transform that is applied to the entire text paragraph.
Definition: textNode.I:619
string get_text() const
Returns the current text, as encoded via the current encoding system.
Definition: textEncoder.I:167