Panda3D
|
00001 // Filename: sceneGraphAnalyzerMeter.cxx 00002 // Created by: pratt (14Feb07) 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 "sceneGraphAnalyzerMeter.h" 00016 #include "camera.h" 00017 #include "displayRegion.h" 00018 #include "orthographicLens.h" 00019 #include "config_grutil.h" 00020 #include "depthTestAttrib.h" 00021 #include "depthWriteAttrib.h" 00022 #include "pStatTimer.h" 00023 #include <stdio.h> // For sprintf/snprintf 00024 00025 PStatCollector SceneGraphAnalyzerMeter::_show_analyzer_pcollector("*:Show scene graph analysis"); 00026 00027 TypeHandle SceneGraphAnalyzerMeter::_type_handle; 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: SceneGraphAnalyzerMeter::Constructor 00031 // Access: Published 00032 // Description: 00033 //////////////////////////////////////////////////////////////////// 00034 SceneGraphAnalyzerMeter:: 00035 SceneGraphAnalyzerMeter(const string &name, PandaNode *node) : TextNode(name) { 00036 set_cull_callback(); 00037 00038 Thread *current_thread = Thread::get_current_thread(); 00039 00040 _update_interval = scene_graph_analyzer_meter_update_interval; 00041 _last_update = 0.0f; 00042 _node = node; 00043 _clock_object = ClockObject::get_global_clock(); 00044 00045 set_align(A_left); 00046 set_transform(LMatrix4::scale_mat(scene_graph_analyzer_meter_scale) * 00047 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))); 00048 set_card_color(0.0f, 0.0f, 0.0f, 0.4); 00049 set_card_as_margin(scene_graph_analyzer_meter_side_margins, scene_graph_analyzer_meter_side_margins, 0.1f, 0.0f); 00050 set_usage_hint(Geom::UH_client); 00051 00052 do_update(current_thread); 00053 } 00054 00055 //////////////////////////////////////////////////////////////////// 00056 // Function: SceneGraphAnalyzerMeter::Destructor 00057 // Access: Published, Virtual 00058 // Description: 00059 //////////////////////////////////////////////////////////////////// 00060 SceneGraphAnalyzerMeter:: 00061 ~SceneGraphAnalyzerMeter() { 00062 clear_window(); 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: SceneGraphAnalyzerMeter::setup_window 00067 // Access: Published 00068 // Description: Sets up the frame rate meter to create a 00069 // DisplayRegion to render itself into the indicated 00070 // window. 00071 //////////////////////////////////////////////////////////////////// 00072 void SceneGraphAnalyzerMeter:: 00073 setup_window(GraphicsOutput *window) { 00074 clear_window(); 00075 00076 _window = window; 00077 00078 _root = NodePath("scene_graph_analyzer_root"); 00079 _root.attach_new_node(this); 00080 00081 CPT(RenderAttrib) dt = DepthTestAttrib::make(DepthTestAttrib::M_none); 00082 CPT(RenderAttrib) dw = DepthWriteAttrib::make(DepthWriteAttrib::M_off); 00083 _root.node()->set_attrib(dt, 1); 00084 _root.node()->set_attrib(dw, 1); 00085 _root.set_material_off(1); 00086 _root.set_two_sided(1, 1); 00087 00088 // Create a display region that covers the entire window. 00089 _display_region = _window->make_display_region(); 00090 _display_region->set_sort(scene_graph_analyzer_meter_layer_sort); 00091 00092 // Finally, we need a camera to associate with the display region. 00093 PT(Camera) camera = new Camera("scene_graph_analyzer_camera"); 00094 NodePath camera_np = _root.attach_new_node(camera); 00095 00096 PT(Lens) lens = new OrthographicLens; 00097 00098 static const PN_stdfloat left = -1.0f; 00099 static const PN_stdfloat right = 1.0f; 00100 static const PN_stdfloat bottom = -1.0f; 00101 static const PN_stdfloat top = 1.0f; 00102 lens->set_film_size(right - left, top - bottom); 00103 lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5); 00104 lens->set_near_far(-1000, 1000); 00105 00106 camera->set_lens(lens); 00107 camera->set_scene(_root); 00108 _display_region->set_camera(camera_np); 00109 } 00110 00111 //////////////////////////////////////////////////////////////////// 00112 // Function: SceneGraphAnalyzerMeter::clear_window 00113 // Access: Published 00114 // Description: Undoes the effect of a previous call to 00115 // setup_window(). 00116 //////////////////////////////////////////////////////////////////// 00117 void SceneGraphAnalyzerMeter:: 00118 clear_window() { 00119 if (_window != (GraphicsOutput *)NULL) { 00120 _window->remove_display_region(_display_region); 00121 _window = (GraphicsOutput *)NULL; 00122 _display_region = (DisplayRegion *)NULL; 00123 } 00124 _root = NodePath(); 00125 } 00126 00127 //////////////////////////////////////////////////////////////////// 00128 // Function: SceneGraphAnalyzerMeter::cull_callback 00129 // Access: Protected, Virtual 00130 // Description: This function will be called during the cull 00131 // traversal to perform any additional operations that 00132 // should be performed at cull time. This may include 00133 // additional manipulation of render state or additional 00134 // visible/invisible decisions, or any other arbitrary 00135 // operation. 00136 // 00137 // Note that this function will *not* be called unless 00138 // set_cull_callback() is called in the constructor of 00139 // the derived class. It is necessary to call 00140 // set_cull_callback() to indicated that we require 00141 // cull_callback() to be called. 00142 // 00143 // By the time this function is called, the node has 00144 // already passed the bounding-volume test for the 00145 // viewing frustum, and the node's transform and state 00146 // have already been applied to the indicated 00147 // CullTraverserData object. 00148 // 00149 // The return value is true if this node should be 00150 // visible, or false if it should be culled. 00151 //////////////////////////////////////////////////////////////////// 00152 bool SceneGraphAnalyzerMeter:: 00153 cull_callback(CullTraverser *trav, CullTraverserData &data) { 00154 Thread *current_thread = trav->get_current_thread(); 00155 00156 // Statistics 00157 PStatTimer timer(_show_analyzer_pcollector, current_thread); 00158 00159 // Check to see if it's time to update. 00160 double now = _clock_object->get_frame_time(current_thread); 00161 double elapsed = now - _last_update; 00162 if (elapsed < 0.0 || elapsed >= _update_interval) { 00163 do_update(current_thread); 00164 } 00165 00166 return TextNode::cull_callback(trav, data); 00167 } 00168 00169 //////////////////////////////////////////////////////////////////// 00170 // Function: SceneGraphAnalyzerMeter::do_update 00171 // Access: Private 00172 // Description: Resets the text according to the current frame rate. 00173 //////////////////////////////////////////////////////////////////// 00174 void SceneGraphAnalyzerMeter:: 00175 do_update(Thread *current_thread) { 00176 _last_update = _clock_object->get_frame_time(current_thread); 00177 00178 _scene_graph_analyzer.clear(); 00179 _scene_graph_analyzer.add_node( _node ); 00180 00181 static const size_t buffer_size = 1024; 00182 char buffer[buffer_size]; 00183 00184 const char *pattern = "Nodes: %d\n" 00185 "Instances: %d\n" 00186 "Transforms: %d\n" 00187 "Nodes with Attribs: %d\n" 00188 "GeomNodes: %d\n" 00189 "Geoms: %d\n" 00190 "GeomVertexDatas: %d\n" 00191 "Vertices: %d\n" 00192 "Normals: %d\n" 00193 "TexCoords: %d\n" 00194 "Tris: %d\n" 00195 "Lines: %d\n" 00196 "Points: %d\n" 00197 "Texture memory: %.1f KB\n"; 00198 00199 #if defined(WIN32_VC) || defined(WIN64_VC) 00200 _snprintf(buffer, buffer_size, pattern, 00201 _scene_graph_analyzer.get_num_nodes(), 00202 _scene_graph_analyzer.get_num_instances(), 00203 _scene_graph_analyzer.get_num_transforms(), 00204 _scene_graph_analyzer.get_num_nodes_with_attribs(), 00205 _scene_graph_analyzer.get_num_geom_nodes(), 00206 _scene_graph_analyzer.get_num_geoms(), 00207 _scene_graph_analyzer.get_num_geom_vertex_datas(), 00208 _scene_graph_analyzer.get_num_vertices(), 00209 _scene_graph_analyzer.get_num_normals(), 00210 _scene_graph_analyzer.get_num_texcoords(), 00211 _scene_graph_analyzer.get_num_tris(), 00212 _scene_graph_analyzer.get_num_lines(), 00213 _scene_graph_analyzer.get_num_points(), 00214 _scene_graph_analyzer.get_texture_bytes()/1024.0); 00215 #else 00216 snprintf(buffer, buffer_size, pattern, 00217 _scene_graph_analyzer.get_num_nodes(), 00218 _scene_graph_analyzer.get_num_instances(), 00219 _scene_graph_analyzer.get_num_transforms(), 00220 _scene_graph_analyzer.get_num_nodes_with_attribs(), 00221 _scene_graph_analyzer.get_num_geom_nodes(), 00222 _scene_graph_analyzer.get_num_geoms(), 00223 _scene_graph_analyzer.get_num_geom_vertex_datas(), 00224 _scene_graph_analyzer.get_num_vertices(), 00225 _scene_graph_analyzer.get_num_normals(), 00226 _scene_graph_analyzer.get_num_texcoords(), 00227 _scene_graph_analyzer.get_num_tris(), 00228 _scene_graph_analyzer.get_num_lines(), 00229 _scene_graph_analyzer.get_num_points(), 00230 _scene_graph_analyzer.get_texture_bytes()/1024.0); 00231 #endif 00232 nassertv(strlen(buffer) < buffer_size); 00233 00234 if (get_text() == buffer) { 00235 // Never mind; the data hasn't changed. 00236 return; 00237 } 00238 00239 set_text(buffer); 00240 }