David Rose 12 years ago
parent
commit
9beae889a2
3 changed files with 327 additions and 0 deletions
  1. 9 0
      pandatool/src/bam/Sources.pp
  2. 253 0
      pandatool/src/bam/ptsToBam.cxx
  3. 65 0
      pandatool/src/bam/ptsToBam.h

+ 9 - 0
pandatool/src/bam/Sources.pp

@@ -45,3 +45,12 @@
   #define SOURCES \
     bamToEgg.cxx bamToEgg.h
 #end bin_target
+
+#begin bin_target
+  #define TARGET pts2bam
+  #define LOCAL_LIBS \
+   p3progbase
+
+  #define SOURCES \
+    ptsToBam.cxx ptsToBam.h
+#end bin_target

+ 253 - 0
pandatool/src/bam/ptsToBam.cxx

@@ -0,0 +1,253 @@
+// Filename: ptsToBam.cxx
+// Created by:  drose (28Jun00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "ptsToBam.h"
+
+#include "config_util.h"
+#include "geomPoints.h"
+#include "bamFile.h"
+#include "pandaNode.h"
+#include "geomNode.h"
+#include "dcast.h"
+#include "pystub.h"
+#include "string_utils.h"
+#include "config_egg2pg.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: PtsToBam::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+PtsToBam::
+PtsToBam() : WithOutputFile(true, false, true)
+{
+  set_program_description
+    ("This program reads a point clound in a pts file and outputs a bam files, "
+     "suitable for viewing in Panda.");
+
+  clear_runlines();
+  add_runline("[opts] input.pts output.bam");
+  add_runline("[opts] -o output.bam input.pts");
+
+  add_option
+    ("o", "filename", 0,
+     "Specify the filename to which the resulting .bam file will be written.  "
+     "If this option is omitted, the last parameter name is taken to be the "
+     "name of the output file.",
+     &PtsToBam::dispatch_filename, &_got_output_filename, &_output_filename);
+
+  add_option
+    ("d", "divisor", 0,
+     "Decimates the point cloud by the indicated divisor.  The number of points\n"
+     "added is 1/divisor; numbers larger than 1.0 mean correspondingly fewer\n"
+     "points.",
+     &PtsToBam::dispatch_double, NULL, &_decimate_divisor);
+
+  _decimate_divisor = 1.0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PtsToBam::run
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void PtsToBam::
+run() {
+  pifstream pts;
+  _pts_filename.set_text();
+  if (!_pts_filename.open_read(pts)) {
+    nout << "Cannot open " << _pts_filename << "\n";
+    exit(1);
+  }
+
+  _gnode = new GeomNode(_pts_filename.get_basename());
+
+  _num_points_expected = 0;
+  _num_points_found = 0;
+  _decimate_factor = 1.0 / _decimate_divisor;
+  _line_number = 0;
+  _point_number = 0;
+  _decimated_point_number = 0.0;
+  _num_vdatas = 0;
+  string line;
+  while (getline(pts, line)) {
+    process_line(line);
+  }
+  close_vertex_data();
+  
+  nout << "\nFound " << _num_points_found << " points of " << _num_points_expected << " expected.\n";
+  nout << "Generated " << _point_number << " points to bam file.\n";
+
+  // This should be guaranteed because we pass false to the
+  // constructor, above.
+  nassertv(has_output_filename());
+
+  Filename filename = get_output_filename();
+  filename.make_dir();
+  nout << "Writing " << filename << "\n";
+  BamFile bam_file;
+  if (!bam_file.open_write(filename)) {
+    nout << "Error in writing.\n";
+    exit(1);
+  }
+  
+  if (!bam_file.write_object(_gnode.p())) {
+    nout << "Error in writing.\n";
+    exit(1);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PtsToBam::handle_args
+//       Access: Protected, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool PtsToBam::
+handle_args(ProgramBase::Args &args) {
+  if (args.empty()) {
+    nout << "You must specify the pts file to read on the command line.\n";
+    return false;
+  }
+
+  if (args.size() > 1) {
+    nout << "Specify only one pts on the command line.\n";
+    return false;
+  }
+
+  _pts_filename = Filename::from_os_specific(args[0]);
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PtsToBam::process_line
+//       Access: Private
+//  Description: Reads a single line from the pts file.
+////////////////////////////////////////////////////////////////////
+void PtsToBam::
+process_line(const string &line) {
+  _line_number++;
+
+  if (_line_number % 1000000 == 0) {
+    cerr << "." << flush;
+  }
+
+  if (line.empty() || !isdigit(line[0])) {
+    return;
+  }
+
+  if (_line_number == 1) {
+    // The first line might be just the number of points.
+    vector_string words;
+    tokenize(trim(line), words, " \t", true);
+    if (words.size() == 1) {
+      string tail;
+      _num_points_expected = string_to_int(words[0], tail);
+      nout << "Expecting " << _num_points_expected << " points, will generate "
+           << (int)(_num_points_expected * _decimate_factor) << "\n";
+      return;
+    }
+  }
+
+  // Here we might have a point.
+  _num_points_found++;
+  _decimated_point_number += _decimate_factor;
+  int point_number = int(_decimated_point_number);
+  if (point_number > _point_number) {
+    _point_number = point_number;
+
+    vector_string words;
+    tokenize(trim(line), words, " \t", true);
+    if (words.size() >= 3) {
+      add_point(words);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PtsToBam::add_point
+//       Access: Private
+//  Description: Adds a point from the pts file.
+////////////////////////////////////////////////////////////////////
+void PtsToBam::
+add_point(const vector_string &words) {
+  if (_data == NULL || _data->get_num_rows() >= egg_max_vertices) {
+    open_vertex_data();
+  }
+
+  string tail;
+  double x, y, z;
+  x = string_to_double(words[0], tail);
+  y = string_to_double(words[1], tail);
+  z = string_to_double(words[2], tail);
+  _vertex.add_data3d(x, y, z);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PtsToBam::open_vertex_data
+//       Access: Private
+//  Description: Creates a new GeomVertexData.
+////////////////////////////////////////////////////////////////////
+void PtsToBam::
+open_vertex_data() {
+  if (_data != (GeomVertexData *)NULL) {
+    close_vertex_data();
+  }
+  CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3();
+  _data = new GeomVertexData("pts", format, GeomEnums::UH_static);
+  _vertex = GeomVertexWriter(_data, "vertex");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PtsToBam::close_vertex_data
+//       Access: Private
+//  Description: Closes a previous GeomVertexData and adds it to the
+//               scene graph.
+////////////////////////////////////////////////////////////////////
+void PtsToBam::
+close_vertex_data() {
+  if (_data == NULL) {
+    return;
+  }
+
+  _num_vdatas++;
+  nout << "\nGenerating " << _point_number << " points in " << _num_vdatas << " GeomVertexDatas\n";
+
+  PT(Geom) geom = new Geom(_data);
+
+  int num_vertices = _data->get_num_rows();
+  int vertices_so_far = 0;
+  while (num_vertices > 0) {
+    int this_num_vertices = min(num_vertices, (int)egg_max_indices);
+    PT(GeomPrimitive) points = new GeomPoints(GeomEnums::UH_static);
+    points->add_consecutive_vertices(vertices_so_far, this_num_vertices);
+    geom->add_primitive(points);
+    vertices_so_far += this_num_vertices;
+    num_vertices -= this_num_vertices;
+  }
+
+  _gnode->add_geom(geom);
+
+  _data = NULL;
+}
+
+int main(int argc, char *argv[]) {
+  // A call to pystub() to force libpystub.so to be linked in.
+  pystub();
+
+  PtsToBam prog;
+  prog.parse_command_line(argc, argv);
+  prog.run();
+  return 0;
+}

+ 65 - 0
pandatool/src/bam/ptsToBam.h

@@ -0,0 +1,65 @@
+// Filename: ptsToBam.h
+// Created by:  drose (28Jun00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PTSTOBAM_H
+#define PTSTOBAM_H
+
+#include "pandatoolbase.h"
+
+#include "programBase.h"
+#include "withOutputFile.h"
+#include "filename.h"
+#include "vector_string.h"
+#include "geomVertexData.h"
+#include "geomVertexWriter.h"
+#include "geomNode.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : PtsToBam
+// Description :
+////////////////////////////////////////////////////////////////////
+class PtsToBam : public ProgramBase, public WithOutputFile {
+public:
+  PtsToBam();
+
+  void run();
+
+protected:
+  virtual bool handle_args(Args &args);
+
+private:
+  void process_line(const string &line);
+  void add_point(const vector_string &words);
+
+  void open_vertex_data();
+  void close_vertex_data();
+
+private:
+  Filename _pts_filename;
+  double _decimate_divisor;
+  double _decimate_factor;
+
+  int _line_number;
+  int _point_number;
+  int _num_points_expected;
+  int _num_points_found;
+  int _num_vdatas;
+
+  double _decimated_point_number;
+  PT(GeomNode) _gnode;
+  PT(GeomVertexData) _data;
+  GeomVertexWriter _vertex;
+};
+
+#endif