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);
114write(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";
266void SceneGraphAnalyzer::
267collect_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);
337void SceneGraphAnalyzer::
338collect_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) {
366void SceneGraphAnalyzer::
367collect_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 int strip_cut_index = prim->get_strip_cut_index();
429 for (
int vi = 0; vi < num_vertices; ++vi) {
430 int index = prim->get_vertex(vi);
431 if (index != strip_cut_index) {
432 tracker._referenced_vertices.set_bit(index);
436 if (prim->is_indexed()) {
437 collect_prim_statistics(prim->get_vertices());
438 if (prim->is_composite()) {
439 collect_statistics(prim->get_mins());
440 collect_statistics(prim->get_maxs());
444 if (prim->is_of_type(GeomPoints::get_class_type())) {
445 _num_points += prim->get_num_primitives();
447 }
else if (prim->is_of_type(GeomLines::get_class_type())) {
448 _num_lines += prim->get_num_primitives();
450 }
else if (prim->is_of_type(GeomLinestrips::get_class_type())) {
451 _num_lines += prim->get_num_faces();
453 }
else if (prim->is_of_type(GeomTriangles::get_class_type())) {
454 _num_tris += prim->get_num_primitives();
455 _num_individual_tris += prim->get_num_primitives();
457 }
else if (prim->is_of_type(GeomTristrips::get_class_type())) {
458 _num_tris += prim->get_num_faces();
459 _num_tristrips += prim->get_num_primitives();
460 _num_triangles_in_strips += prim->get_num_faces();
462 }
else if (prim->is_of_type(GeomTrifans::get_class_type())) {
463 _num_tris += prim->get_num_faces();
464 _num_trifans += prim->get_num_primitives();
465 _num_triangles_in_fans += prim->get_num_faces();
467 }
else if (prim->is_of_type(GeomPatches::get_class_type())) {
468 _num_patches += prim->get_num_primitives();
469 _num_vertices_in_patches += prim->get_num_vertices();
473 <<
"Unknown GeomPrimitive type in SceneGraphAnalyzer: "
474 << prim->get_type() <<
"\n";
482void SceneGraphAnalyzer::
483collect_statistics(
Texture *texture) {
484 nassertv(texture !=
nullptr);
486 Textures::iterator ti = _textures.find(texture);
487 if (ti == _textures.end()) {
489 _textures.insert(Textures::value_type(texture, 1));
500 _texture_bytes += bytes;
511void SceneGraphAnalyzer::
513 nassertv(vadata !=
nullptr);
514 bool inserted = _vadatas.insert(vadata).second;
518 int &dup_count = (*(_unique_vadatas.insert(UniqueVADatas::value_type(vadata, 0)).first)).second;
528void SceneGraphAnalyzer::
530 nassertv(vadata !=
nullptr);
531 bool inserted = _prim_vadatas.insert(vadata).second;
535 int &dup_count = (*(_unique_prim_vadatas.insert(UniqueVADatas::value_type(vadata, 0)).first)).second;
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the array.
A node that holds Geom objects, renderable pieces of geometry.
get_num_geoms
Returns the number of geoms in the node.
get_geom_state
Returns the RenderState associated with the nth geom of the node.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
This is the data for one array of a GeomVertexData structure.
get_data_size_bytes
Returns the number of bytes stored in the array.
This defines how a single column is interleaved within a vertex array stored within a Geom.
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
A container for geometry primitives.
get_lowest_switch
Returns the index number of the child with the lowest level of detail; that is, the one that is desig...
get_highest_switch
Returns the index number of the child with the highest level of detail; that is, the one that is desi...
A basic node of the scene graph or data graph.
virtual bool is_geom_node() const
A simple downcast check.
get_child
Returns the nth child node of this node.
virtual bool is_lod_node() const
A simple downcast check.
get_num_children
Returns the number of child nodes this node has.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
void add_node(PandaNode *node)
Adds a new node to the set of data for analysis.
void write(std::ostream &out, int indent_level=0) const
Describes all the data collected.
void clear()
Resets all of the data in the analyzer in preparation for a new run.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
get_component_width
Returns the number of bytes stored for each color component of a texel.
get_y_size
Returns the height of the texture image in texels.
get_num_components
Returns the number of color components for each texel of the texture image.
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping,...
get_x_size
Returns the width of the texture image in texels.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
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.