39 SceneGraphAnalyzer() {
48 ~SceneGraphAnalyzer() {
60 _unique_vdatas.clear();
61 _unique_vadatas.clear();
67 _num_nodes_with_attribs = 0;
71 _num_geom_vertex_datas = 0;
72 _num_geom_vertex_formats = 0;
73 _vertex_data_size = 0;
86 _num_individual_tris = 0;
88 _num_triangles_in_strips = 0;
90 _num_triangles_in_fans = 0;
91 _num_vertices_in_patches = 0;
95 _num_long_normals = 0;
96 _num_short_normals = 0;
97 _total_normal_length = 0.0f;
107 collect_statistics(node,
false);
114 write(std::ostream &out,
int indent_level)
const {
116 << _num_nodes <<
" total nodes (including " 117 << _num_instances <<
" instances); " << _num_lod_nodes <<
" LODNodes.\n";
120 << _num_transforms <<
" transforms";
122 if (_num_nodes != 0) {
123 out <<
"; " << 100 * _num_nodes_with_attribs / _num_nodes
124 <<
"% of nodes have some render attribute.";
129 << _num_geoms <<
" Geoms, with " << _num_geom_vertex_datas
130 <<
" GeomVertexDatas and " << _num_geom_vertex_formats
131 <<
" GeomVertexFormats, appear on " << _num_geom_nodes
134 indent(out, indent_level);
135 if (_num_vertices_64 != 0) {
136 out << _num_vertices_64 <<
" 64-bit vertices, ";
137 if (_num_vertices != _num_vertices_64) {
138 out << _num_vertices - _num_vertices_64 <<
" 32-bit vertices, ";
141 out << _num_vertices <<
" vertices, ";
144 out << _num_normals <<
" normals, " 145 << _num_colors <<
" colors, " 146 << _num_texcoords <<
" texture coordinates.\n";
148 if (_num_long_normals != 0 || _num_short_normals != 0) {
150 << _num_long_normals <<
" normals are too long, " 151 << _num_short_normals <<
" are too short. Average normal length is " 152 << _total_normal_length / (PN_stdfloat)_num_normals <<
"\n";
156 <<
"GeomVertexData arrays occupy " << (_vertex_data_size + 1023) / 1024
160 <<
"GeomPrimitive arrays occupy " << (_prim_data_size + 1023) / 1024
163 int unreferenced_vertices = 0;
164 VDatas::const_iterator vdi;
165 for (vdi = _vdatas.begin(); vdi != _vdatas.end(); ++vdi) {
167 const VDataTracker &tracker = (*vdi).second;
168 int num_unreferenced = vdata->get_num_rows() - tracker._referenced_vertices.get_num_on_bits();
169 nassertv(num_unreferenced >= 0);
170 unreferenced_vertices += num_unreferenced;
172 if (unreferenced_vertices != 0) {
174 << unreferenced_vertices <<
" vertices are unreferenced by any GeomPrimitives.\n";
176 if (_unique_vdatas.size() != _vdatas.size()) {
178 << _vdatas.size() - _unique_vdatas.size()
179 <<
" GeomVertexDatas are redundantly duplicated\n";
181 if (_unique_vadatas.size() != _vadatas.size()) {
182 int wasted_bytes = 0;
184 UniqueVADatas::const_iterator uvai;
185 for (uvai = _unique_vadatas.begin();
186 uvai != _unique_vadatas.end();
189 int dup_count = (*uvai).second;
195 << _vadatas.size() - _unique_vadatas.size()
196 <<
" GeomVertexArrayDatas are redundant, wasting " 197 << (wasted_bytes + 1023) / 1024 <<
"K.\n";
199 if (_unique_prim_vadatas.size() != _prim_vadatas.size()) {
200 int wasted_bytes = 0;
202 UniqueVADatas::const_iterator uvai;
203 for (uvai = _unique_prim_vadatas.begin();
204 uvai != _unique_prim_vadatas.end();
207 int dup_count = (*uvai).second;
213 << _prim_vadatas.size() - _unique_prim_vadatas.size()
214 <<
" GeomPrimitive arrays are redundant, wasting " 215 << (wasted_bytes + 1023) / 1024 <<
"K.\n";
219 << _num_tris <<
" triangles:\n";
220 indent(out, indent_level + 2)
221 << _num_triangles_in_strips
222 <<
" of these are on " << _num_tristrips <<
" tristrips";
223 if (_num_tristrips != 0) {
225 << (double)_num_triangles_in_strips / (
double)_num_tristrips
226 <<
" average tris per strip)";
230 if (_num_trifans != 0) {
231 indent(out, indent_level + 2)
232 << _num_triangles_in_fans
233 <<
" of these are on " << _num_trifans <<
" trifans";
234 if (_num_trifans != 0) {
236 << (double)_num_triangles_in_fans / (
double)_num_trifans
237 <<
" average tris per fan)";
242 indent(out, indent_level + 2)
243 << _num_individual_tris
244 <<
" of these are independent triangles.\n";
246 if (_num_patches != 0) {
248 << _num_patches <<
" patches (" 249 << (double)_num_vertices_in_patches / (
double)_num_patches
250 <<
" average verts per patch).\n";
253 if (_num_lines != 0 || _num_points != 0) {
255 << _num_lines <<
" lines, " << _num_points <<
" points.\n";
259 << _textures.size() <<
" textures, estimated minimum " 260 << (_texture_bytes + 1023) / 1024 <<
"K texture memory required.\n";
266 void SceneGraphAnalyzer::
267 collect_statistics(
PandaNode *node,
bool under_instance) {
270 if (!under_instance) {
271 Nodes::iterator ni = _nodes.find(node);
272 if (ni == _nodes.end()) {
274 _nodes.insert(Nodes::value_type(node, 1));
279 under_instance =
true;
283 if (!node->get_state()->is_empty()) {
284 _num_nodes_with_attribs++;
286 node->get_attrib(TextureAttrib::get_class_slot());
287 if (attrib !=
nullptr) {
294 if (!node->get_transform()->is_identity()) {
299 collect_statistics(DCAST(
GeomNode, node));
311 if (sw >= 0 && sw < node->get_num_children()) {
313 collect_statistics(child, under_instance);
328 for (
int i = 0; i < num_children; i++) {
330 collect_statistics(child, under_instance);
337 void SceneGraphAnalyzer::
338 collect_statistics(
GeomNode *geom_node) {
339 nassertv(geom_node !=
nullptr);
344 _num_geoms += num_geoms;
346 for (
int i = 0; i < num_geoms; i++) {
347 const Geom *geom = geom_node->get_geom(i);
348 collect_statistics(geom);
353 geom_state->get_attrib(TextureAttrib::get_class_slot());
354 if (attrib !=
nullptr) {
366 void SceneGraphAnalyzer::
367 collect_statistics(
const Geom *geom) {
369 std::pair<VDatas::iterator, bool> result = _vdatas.insert(VDatas::value_type(vdata, VDataTracker()));
372 ++_num_geom_vertex_datas;
375 bool format_inserted = _vformats.insert(vformat).second;
376 if (format_inserted) {
378 ++_num_geom_vertex_formats;
381 int &dup_count = (*(_unique_vdatas.insert(UniqueVDatas::value_type(vdata, 0)).first)).second;
384 int num_rows = vdata->get_num_rows();
386 if (format->
has_column(InternalName::get_vertex())) {
387 _num_vertices += num_rows;
390 _num_vertices_64 += num_rows;
393 if (format->
has_column(InternalName::get_normal())) {
394 _num_normals += num_rows;
396 while (!rnormal.is_at_end()) {
397 LVector3f normal = rnormal.get_data3f();
398 float length = normal.length();
399 if (IS_NEARLY_EQUAL(length, 1.0f)) {
401 }
else if (length > 1.0f) {
404 ++_num_short_normals;
406 _total_normal_length += length;
409 if (format->
has_column(InternalName::get_color())) {
410 _num_colors += num_rows;
413 _num_texcoords += num_rows * num_texcoords;
415 int num_arrays = vdata->get_num_arrays();
416 for (
int i = 0; i < num_arrays; ++i) {
417 collect_statistics(vdata->get_array(i));
420 VDataTracker &tracker = (*(result.first)).second;
423 int num_primitives = geom->get_num_primitives();
424 for (
int i = 0; i < num_primitives; ++i) {
427 int num_vertices = prim->get_num_vertices();
428 for (
int vi = 0; vi < num_vertices; ++vi) {
429 tracker._referenced_vertices.set_bit(prim->get_vertex(vi));
432 if (prim->is_indexed()) {
433 collect_prim_statistics(prim->get_vertices());
434 if (prim->is_composite()) {
435 collect_statistics(prim->get_mins());
436 collect_statistics(prim->get_maxs());
440 if (prim->is_of_type(GeomPoints::get_class_type())) {
441 _num_points += prim->get_num_primitives();
443 }
else if (prim->is_of_type(GeomLines::get_class_type())) {
444 _num_lines += prim->get_num_primitives();
446 }
else if (prim->is_of_type(GeomLinestrips::get_class_type())) {
447 _num_lines += prim->get_num_faces();
449 }
else if (prim->is_of_type(GeomTriangles::get_class_type())) {
450 _num_tris += prim->get_num_primitives();
451 _num_individual_tris += prim->get_num_primitives();
453 }
else if (prim->is_of_type(GeomTristrips::get_class_type())) {
454 _num_tris += prim->get_num_faces();
455 _num_tristrips += prim->get_num_primitives();
456 _num_triangles_in_strips += prim->get_num_faces();
458 }
else if (prim->is_of_type(GeomTrifans::get_class_type())) {
459 _num_tris += prim->get_num_faces();
460 _num_trifans += prim->get_num_primitives();
461 _num_triangles_in_fans += prim->get_num_faces();
463 }
else if (prim->is_of_type(GeomPatches::get_class_type())) {
464 _num_patches += prim->get_num_primitives();
465 _num_vertices_in_patches += prim->get_num_vertices();
469 <<
"Unknown GeomPrimitive type in SceneGraphAnalyzer: " 470 << prim->get_type() <<
"\n";
478 void SceneGraphAnalyzer::
479 collect_statistics(
Texture *texture) {
480 nassertv(texture !=
nullptr);
482 Textures::iterator ti = _textures.find(texture);
483 if (ti == _textures.end()) {
485 _textures.insert(Textures::value_type(texture, 1));
496 _texture_bytes += bytes;
507 void SceneGraphAnalyzer::
509 nassertv(vadata !=
nullptr);
510 bool inserted = _vadatas.insert(vadata).second;
514 int &dup_count = (*(_unique_vadatas.insert(UniqueVADatas::value_type(vadata, 0)).first)).second;
524 void SceneGraphAnalyzer::
526 nassertv(vadata !=
nullptr);
527 bool inserted = _prim_vadatas.insert(vadata).second;
531 int &dup_count = (*(_unique_prim_vadatas.insert(UniqueVADatas::value_type(vadata, 0)).first)).second;
void write(std::ostream &out, int indent_level=0) const
Describes all the data collected.
get_geom_state
Returns the RenderState associated with the nth geom of the node.
get_y_size
Returns the height of the texture image in texels.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A basic node of the scene graph or data graph.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_highest_switch
Returns the index number of the child with the highest level of detail; that is, the one that is desi...
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.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
void add_node(PandaNode *node)
Adds a new node to the set of data for analysis.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
void clear()
Resets all of the data in the analyzer in preparation for a new run.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines how a single column is interleaved within a vertex array stored within a Geom.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
get_num_children
Returns the number of child nodes this node has.
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping,...
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
get_num_components
Returns the number of color components for each texel of the texture image.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
get_component_width
Returns the number of bytes stored for each color component of a texel.
get_data_size_bytes
Returns the number of bytes stored in the array.
virtual bool is_lod_node() const
A simple downcast check.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
get_lowest_switch
Returns the index number of the child with the lowest level of detail; that is, the one that is desig...
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.
get_num_geoms
Returns the number of geoms in the node.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
get_child
Returns the nth child node of this node.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool is_geom_node() const
A simple downcast check.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A node that holds Geom objects, renderable pieces of geometry.
get_x_size
Returns the width of the texture image in texels.
This is the data for one array of a GeomVertexData structure.
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.