Panda3D
Loading...
Searching...
No Matches
bamInfo.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 bamInfo.cxx
10 * @author drose
11 * @date 2000-07-02
12 */
13
14#include "bamInfo.h"
15
16#include "bamFile.h"
17#include "pandaNode.h"
18#include "geomNode.h"
19#include "texture.h"
20#include "recorderHeader.h"
21#include "recorderFrame.h"
22#include "recorderTable.h"
23#include "dcast.h"
24#include "pvector.h"
25#include "bamCacheRecord.h"
26#include "bamCacheIndex.h"
27
28/**
29 *
30 */
31BamInfo::
32BamInfo() {
33 set_program_brief("describe the contents of .bam files");
34 set_program_description
35 ("This program scans one or more Bam files--Panda's Binary Animation "
36 "and Models native binary format--and describes their contents.");
37
38 clear_runlines();
39 add_runline("[opts] input.bam [input.bam ... ]");
40
41 add_option
42 ("ls", "", 0,
43 "List the scene graph hierarchy in the bam file.",
44 &BamInfo::dispatch_none, &_ls);
45
46 add_option
47 ("t", "", 0,
48 "List explicitly each transition in the hierarchy.",
49 &BamInfo::dispatch_none, &_verbose_transitions);
50
51 add_option
52 ("g", "", 0,
53 "Output verbose information about each Geom in the Bam file.",
54 &BamInfo::dispatch_none, &_verbose_geoms);
55
56 _num_scene_graphs = 0;
57}
58
59
60/**
61 *
62 */
63void BamInfo::
64run() {
65 bool okflag = true;
66
67 Filenames::const_iterator fi;
68 for (fi = _filenames.begin(); fi != _filenames.end(); ++fi) {
69 if (!get_info(*fi)) {
70 okflag = false;
71 }
72 }
73
74 if (_num_scene_graphs > 0) {
75 nout << "\nScene graph statistics:\n";
76 _analyzer.write(nout, 2);
77 }
78 nout << "\n";
79
80 if (!okflag) {
81 // Exit with an error if any of the files was unreadable.
82 exit(1);
83 }
84}
85
86
87/**
88 *
89 */
90bool BamInfo::
91handle_args(ProgramBase::Args &args) {
92 if (args.empty()) {
93 nout << "You must specify the Bam file(s) to read on the command line.\n";
94 return false;
95 }
96
97 ProgramBase::Args::const_iterator ai;
98 for (ai = args.begin(); ai != args.end(); ++ai) {
99 _filenames.push_back(*ai);
100 }
101
102 return true;
103}
104
105
106/**
107 * Reads a single Bam file and displays its contents. Returns true if
108 * successful, false on error.
109 */
110bool BamInfo::
111get_info(const Filename &filename) {
112 BamFile bam_file;
113
114 if (!bam_file.open_read(filename)) {
115 nout << "Unable to read.\n";
116 return false;
117 }
118
119 const char *endian = "little-endian";
120 if (bam_file.get_file_endian() == BamEnums::BE_bigendian) {
121 endian = "big-endian";
122 }
123 int float_width = 32;
124 if (bam_file.get_file_stdfloat_double()) {
125 float_width = 64;
126 }
127
128 nout << filename << " : Bam version " << bam_file.get_file_major_ver()
129 << "." << bam_file.get_file_minor_ver()
130 << ", " << endian << ", " << float_width << "-bit floats.\n";
131
132 Objects objects;
133 TypedWritable *object = bam_file.read_object();
134
135 if (object != nullptr &&
136 object->is_exact_type(BamCacheRecord::get_class_type())) {
137 // Here's a special case: if the first object in the file is a
138 // BamCacheRecord, it's a cache data file; in this case, we output the
139 // cache record, and then pretend it doesn't exist.
140 DCAST(BamCacheRecord, object)->write(nout, 2);
141 nout << "\n";
142 object = bam_file.read_object();
143 }
144
145 while (object != nullptr || !bam_file.is_eof()) {
146 if (object != nullptr) {
147 objects.push_back(object);
148 }
149 object = bam_file.read_object();
150 }
151 if (!bam_file.resolve()) {
152 nout << "Unable to fully resolve file.\n";
153 return false;
154 }
155
156 // We can't close the bam file until we have examined the objects, since
157 // closing it will decrement reference counts.
158
159 if (objects.size() == 1 &&
160 objects[0]->is_of_type(PandaNode::get_class_type())) {
161 describe_scene_graph(DCAST(PandaNode, objects[0]));
162
163 } else if (objects.size() == 1 &&
164 objects[0]->is_of_type(Texture::get_class_type())) {
165 describe_texture(DCAST(Texture, objects[0]));
166
167 } else if (objects.size() == 1 &&
168 objects[0]->is_of_type(BamCacheIndex::get_class_type())) {
169 describe_cache_index(DCAST(BamCacheIndex, objects[0]));
170
171 } else if (!objects.empty() && objects[0]->is_of_type(RecorderHeader::get_class_type())) {
172 describe_session(DCAST(RecorderHeader, objects[0]), objects);
173
174 } else {
175 nout << "file contains " << objects.size() << " objects:\n";
176 for (int i = 0; i < (int)objects.size(); i++) {
177 describe_general_object(objects[i]);
178 }
179 }
180
181 return true;
182}
183
184
185/**
186 * Called for Bam files that contain a single scene graph and no other
187 * objects. This should describe that scene graph in some meaningful way.
188 */
189void BamInfo::
190describe_scene_graph(PandaNode *node) {
191 // Parent the node to our own scene graph root, so we can (a) guarantee it
192 // won't accidentally be deleted before we're done, (b) easily determine the
193 // bounding volume of the scene, and (c) report statistics on all the bam
194 // file's scene graphs together when we've finished.
195
196 PT(PandaNode) root = new PandaNode("root");
197 root->add_child(node);
198 _num_scene_graphs++;
199
200 int num_nodes = _analyzer.get_num_nodes();
201 _analyzer.add_node(node);
202 num_nodes = _analyzer.get_num_nodes() - num_nodes;
203
204 nout << " " << num_nodes << " nodes, bounding volume is "
205 << *root->get_bounds() << "\n";
206
207 if (_ls || _verbose_geoms || _verbose_transitions) {
208 list_hierarchy(node, 0);
209 }
210}
211
212/**
213 * Called for Bam files that contain a Texture object.
214 */
215void BamInfo::
216describe_texture(Texture *tex) {
217 tex->write(nout, 2);
218}
219
220/**
221 * Called for Bam files that contain a BamCacheIndex object.
222 */
223void BamInfo::
224describe_cache_index(BamCacheIndex *index) {
225 index->write(nout, 2);
226}
227
228/**
229 * Called for Bam files that contain a recorded session table.
230 */
231void BamInfo::
232describe_session(RecorderHeader *header, const BamInfo::Objects &objects) {
233 char time_buffer[1024];
234 strftime(time_buffer, 1024, "%c",
235 localtime(&header->_start_time));
236
237 pset<std::string> recorders;
238 double last_timestamp = 0.0;
239
240 for (size_t i = 1; i < objects.size(); i++) {
241 if (objects[i]->is_of_type(RecorderFrame::get_class_type())) {
242 RecorderFrame *frame = DCAST(RecorderFrame, objects[i]);
243 if (frame->_table_changed) {
244 RecorderTable::Recorders::const_iterator ri;
245 for (ri = frame->_table->_recorders.begin();
246 ri != frame->_table->_recorders.end();
247 ++ri) {
248 recorders.insert((*ri).first);
249 }
250 }
251 last_timestamp = frame->_timestamp;
252 }
253 }
254
255 nout << "Session, " << last_timestamp
256 << " secs, " << objects.size() - 1 << " frames, "
257 << time_buffer << ".\n"
258 << "Recorders:";
259 for (pset<std::string>::iterator ni = recorders.begin();
260 ni != recorders.end();
261 ++ni) {
262 nout << " " << (*ni);
263 }
264 nout << "\n";
265}
266
267/**
268 * Called for Bam files that contain multiple objects which may or may not be
269 * scene graph nodes. This should describe each object in some meaningful
270 * way.
271 */
272void BamInfo::
273describe_general_object(TypedWritable *object) {
274 nassertv(object != nullptr);
275 nout << " " << object->get_type() << "\n";
276}
277
278/**
279 * Outputs the hierarchy and all of the verbose GeomNode information.
280 */
281void BamInfo::
282list_hierarchy(PandaNode *node, int indent_level) {
283 indent(nout, indent_level) << *node;
284
285 if (_verbose_transitions) {
286 nout << "\n";
287 if (!node->get_transform()->is_identity()) {
288 node->get_transform()->write(nout, indent_level);
289 }
290 if (!node->get_state()->is_empty()) {
291 node->get_state()->write(nout, indent_level);
292 }
293 if (!node->get_effects()->is_empty()) {
294 node->get_effects()->write(nout, indent_level);
295 }
296
297 } else {
298 if (!node->get_transform()->is_identity()) {
299 nout << " " << *node->get_transform();
300 }
301 if (!node->get_state()->is_empty()) {
302 nout << " " << *node->get_state();
303 }
304 if (!node->get_effects()->is_empty()) {
305 nout << " " << *node->get_effects();
306 }
307 nout << "\n";
308 }
309
310 if (_verbose_geoms && node->is_geom_node()) {
311 GeomNode *geom_node;
312 DCAST_INTO_V(geom_node, node);
313 geom_node->write_verbose(nout, indent_level);
314 }
315
316 int num_children = node->get_num_children();
317 for (int i = 0; i < num_children; i++) {
318 PandaNode *child = node->get_child(i);
319 list_hierarchy(child, indent_level + 2);
320 }
321}
322
323int main(int argc, char *argv[]) {
324 BamInfo prog;
325 prog.parse_command_line(argc, argv);
326 prog.run();
327 return 0;
328}
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 represents the in-memory index that records the list of files stored in the BamCache.
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
The principle public interface to reading and writing Bam disk files.
Definition bamFile.h:41
get_file_stdfloat_double
Returns true if the file stores all "standard" floats as 64-bit doubles, or false if they are 32-bit ...
Definition bamFile.h:83
int get_file_minor_ver()
Returns the minor version number of the file currently being read, or the system current minor versio...
Definition bamFile.cxx:277
TypedWritable * read_object()
Reads and returns the next object from the Bam file, or NULL if the end of the file has been reached,...
Definition bamFile.cxx:85
int get_file_major_ver()
Returns the major version number of the file currently being read, or the system current major versio...
Definition bamFile.cxx:264
get_file_endian
Returns the endian preference indicated by the Bam file currently being read or written.
Definition bamFile.h:82
bool open_read(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated filename for reading.
Definition bamFile.cxx:51
bool resolve()
This must be called after one or more objects have been read via calls to read_object() in order to r...
Definition bamFile.cxx:110
bool is_eof() const
Returns true if the reader has reached end-of-file, false otherwise.
Definition bamFile.cxx:98
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
A node that holds Geom objects, renderable pieces of geometry.
Definition geomNode.h:34
void write_verbose(std::ostream &out, int indent_level) const
Writes a detailed description of all the Geoms in the node.
Definition geomNode.cxx:827
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
virtual bool is_geom_node() const
A simple downcast check.
get_child
Returns the nth child node of this node.
Definition pandaNode.h:124
get_num_children
Returns the number of child nodes this node has.
Definition pandaNode.h:124
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
This object represents one frame of data in the recorded session file.
This object contains the header information written out at the beginning of a recorded session file.
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.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition texture.h:72
bool write(const Filename &fullpath)
Writes the texture to the named filename.
Definition texture.I:299
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition typedObject.I:38
Base class for objects that can be written to and read from Bam files.
This is our own Panda specialization on the default STL set.
Definition pset.h:49
This is our own Panda specialization on the default STL vector.
Definition pvector.h:42
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.
Definition indent.cxx:20
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.