Panda3D

geomVertexArrayFormat.cxx

00001 // Filename: geomVertexArrayFormat.cxx
00002 // Created by:  drose (06Mar05)
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 "geomVertexFormat.h"
00016 #include "geomVertexColumn.h"
00017 #include "geomVertexData.h"
00018 #include "geomVertexReader.h"
00019 #include "indent.h"
00020 #include "bamReader.h"
00021 #include "bamWriter.h"
00022 #include "indirectLess.h"
00023 #include "lightMutexHolder.h"
00024 
00025 GeomVertexArrayFormat::Registry *GeomVertexArrayFormat::_registry = NULL;
00026 TypeHandle GeomVertexArrayFormat::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: GeomVertexArrayFormat::Constructor
00030 //       Access: Published
00031 //  Description: 
00032 ////////////////////////////////////////////////////////////////////
00033 GeomVertexArrayFormat::
00034 GeomVertexArrayFormat() :
00035   _is_registered(false),
00036   _stride(0),
00037   _total_bytes(0),
00038   _pad_to(1),
00039   _columns_unsorted(false)
00040 {
00041 }
00042 
00043 ////////////////////////////////////////////////////////////////////
00044 //     Function: GeomVertexArrayFormat::Constructor
00045 //       Access: Published
00046 //  Description: 
00047 ////////////////////////////////////////////////////////////////////
00048 GeomVertexArrayFormat::
00049 GeomVertexArrayFormat(InternalName *name0, int num_components0,
00050                       GeomVertexArrayFormat::NumericType numeric_type0,
00051                       GeomVertexArrayFormat::Contents contents0) :
00052   _is_registered(false),
00053   _stride(0),
00054   _total_bytes(0),
00055   _pad_to(1),
00056   _columns_unsorted(false)
00057 {
00058   add_column(name0, num_components0, numeric_type0, contents0);
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: GeomVertexArrayFormat::Constructor
00063 //       Access: Published
00064 //  Description: 
00065 ////////////////////////////////////////////////////////////////////
00066 GeomVertexArrayFormat::
00067 GeomVertexArrayFormat(InternalName *name0, int num_components0,
00068                       GeomVertexArrayFormat::NumericType numeric_type0,
00069                       GeomVertexArrayFormat::Contents contents0,
00070                       InternalName *name1, int num_components1,
00071                       GeomVertexArrayFormat::NumericType numeric_type1,
00072                       GeomVertexArrayFormat::Contents contents1) :
00073   _is_registered(false),
00074   _stride(0),
00075   _total_bytes(0),
00076   _pad_to(1),
00077   _columns_unsorted(false)
00078 {
00079   add_column(name0, num_components0, numeric_type0, contents0);
00080   add_column(name1, num_components1, numeric_type1, contents1);
00081 }
00082 
00083 ////////////////////////////////////////////////////////////////////
00084 //     Function: GeomVertexArrayFormat::Constructor
00085 //       Access: Published
00086 //  Description: 
00087 ////////////////////////////////////////////////////////////////////
00088 GeomVertexArrayFormat::
00089 GeomVertexArrayFormat(InternalName *name0, int num_components0,
00090                       GeomVertexArrayFormat::NumericType numeric_type0,
00091                       GeomVertexArrayFormat::Contents contents0,
00092                       InternalName *name1, int num_components1,
00093                       GeomVertexArrayFormat::NumericType numeric_type1,
00094                       GeomVertexArrayFormat::Contents contents1,
00095                       InternalName *name2, int num_components2,
00096                       GeomVertexArrayFormat::NumericType numeric_type2,
00097                       GeomVertexArrayFormat::Contents contents2) :
00098   _is_registered(false),
00099   _stride(0),
00100   _total_bytes(0),
00101   _pad_to(1),
00102   _columns_unsorted(false)
00103 {
00104   add_column(name0, num_components0, numeric_type0, contents0);
00105   add_column(name1, num_components1, numeric_type1, contents1);
00106   add_column(name2, num_components2, numeric_type2, contents2);
00107 }
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: GeomVertexArrayFormat::Constructor
00111 //       Access: Published
00112 //  Description: 
00113 ////////////////////////////////////////////////////////////////////
00114 GeomVertexArrayFormat::
00115 GeomVertexArrayFormat(InternalName *name0, int num_components0,
00116                       GeomVertexArrayFormat::NumericType numeric_type0,
00117                       GeomVertexArrayFormat::Contents contents0,
00118                       InternalName *name1, int num_components1,
00119                       GeomVertexArrayFormat::NumericType numeric_type1,
00120                       GeomVertexArrayFormat::Contents contents1,
00121                       InternalName *name2, int num_components2,
00122                       GeomVertexArrayFormat::NumericType numeric_type2,
00123                       GeomVertexArrayFormat::Contents contents2,
00124                       InternalName *name3, int num_components3,
00125                       GeomVertexArrayFormat::NumericType numeric_type3,
00126                       GeomVertexArrayFormat::Contents contents3) :
00127   _is_registered(false),
00128   _stride(0),
00129   _total_bytes(0),
00130   _pad_to(1),
00131   _columns_unsorted(false)
00132 {
00133   add_column(name0, num_components0, numeric_type0, contents0);
00134   add_column(name1, num_components1, numeric_type1, contents1);
00135   add_column(name2, num_components2, numeric_type2, contents2);
00136   add_column(name3, num_components3, numeric_type3, contents3);
00137 }
00138 
00139 ////////////////////////////////////////////////////////////////////
00140 //     Function: GeomVertexArrayFormat::Copy Constructor
00141 //       Access: Published
00142 //  Description: 
00143 ////////////////////////////////////////////////////////////////////
00144 GeomVertexArrayFormat::
00145 GeomVertexArrayFormat(const GeomVertexArrayFormat &copy) :
00146   _is_registered(false),
00147   _stride(copy._stride),
00148   _total_bytes(copy._total_bytes),
00149   _pad_to(copy._pad_to),
00150   _columns_unsorted(copy._columns_unsorted)
00151 {
00152   Columns::const_iterator dti;
00153   for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) {
00154     add_column(*(*dti));
00155   }
00156 }
00157 
00158 ////////////////////////////////////////////////////////////////////
00159 //     Function: GeomVertexArrayFormat::Copy Assignment Operator
00160 //       Access: Published
00161 //  Description: 
00162 ////////////////////////////////////////////////////////////////////
00163 void GeomVertexArrayFormat::
00164 operator = (const GeomVertexArrayFormat &copy) {
00165   nassertv(!_is_registered);
00166   _stride = copy._stride;
00167   _total_bytes = copy._total_bytes;
00168   _pad_to = copy._pad_to;
00169 
00170   _columns.clear();
00171   _columns_by_name.clear();
00172   _columns_unsorted = false;
00173   Columns::const_iterator dti;
00174   for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) {
00175     add_column(*(*dti));
00176   }
00177 }
00178   
00179 ////////////////////////////////////////////////////////////////////
00180 //     Function: GeomVertexArrayFormat::Destructor
00181 //       Access: Published, Virtual
00182 //  Description: 
00183 ////////////////////////////////////////////////////////////////////
00184 GeomVertexArrayFormat::
00185 ~GeomVertexArrayFormat() {
00186   // unref() should have unregistered us.
00187   nassertv(!is_registered());
00188 
00189   Columns::iterator ci;
00190   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00191     delete (*ci);
00192   }
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: GeomVertexArrayFormat::unref
00197 //       Access: Published, Virtual
00198 //  Description: This method overrides ReferenceCount::unref() to
00199 //               unregister the object when its reference count goes
00200 //               to zero.
00201 ////////////////////////////////////////////////////////////////////
00202 bool GeomVertexArrayFormat::
00203 unref() const {
00204   Registry *registry = get_registry();
00205   LightMutexHolder holder(registry->_lock);
00206 
00207   if (ReferenceCount::unref()) {
00208     return true;
00209   }
00210 
00211   if (is_registered()) {
00212     registry->unregister_format((GeomVertexArrayFormat *)this);
00213   }
00214 
00215   return false;
00216 }
00217 
00218 ////////////////////////////////////////////////////////////////////
00219 //     Function: GeomVertexArrayFormat::add_column
00220 //       Access: Published
00221 //  Description: Adds a new column to the specification.  This is a
00222 //               table of per-vertex floating-point numbers such as
00223 //               "vertex" or "normal"; you must specify where in each
00224 //               record the table starts, and how many components
00225 //               (dimensions) exist per vertex.
00226 //
00227 //               The return value is the index number of the new data
00228 //               type.
00229 ////////////////////////////////////////////////////////////////////
00230 int GeomVertexArrayFormat::
00231 add_column(InternalName *name, int num_components, 
00232            GeomVertexArrayFormat::NumericType numeric_type, 
00233            GeomVertexArrayFormat::Contents contents, int start) {
00234   if (start < 0) {
00235     start = _total_bytes;
00236 
00237     GeomVertexColumn temp_column
00238       (name, num_components, numeric_type, contents, 0);
00239     int pad_to = temp_column.get_component_bytes();
00240     start = ((start + pad_to - 1) / pad_to) * pad_to;
00241   }
00242 
00243   return add_column(GeomVertexColumn(name, num_components, 
00244                                      numeric_type, contents, start));
00245 }
00246 
00247 ////////////////////////////////////////////////////////////////////
00248 //     Function: GeomVertexArrayFormat::add_column
00249 //       Access: Published
00250 //  Description: Adds a new column to the specification.  This is a
00251 //               table of per-vertex floating-point numbers such as
00252 //               "vertex" or "normal"; you must specify where in each
00253 //               record the table starts, and how many components
00254 //               (dimensions) exist per vertex.
00255 //
00256 //               Adding a column with the same name as a previous
00257 //               type, or that overlaps with one or more previous
00258 //               types, quietly removes the previous type(s).
00259 //
00260 //               The return value is the index number of the new data
00261 //               type.
00262 ////////////////////////////////////////////////////////////////////
00263 int GeomVertexArrayFormat::
00264 add_column(const GeomVertexColumn &column) {
00265   nassertr(!_is_registered, -1);
00266 
00267   // Make sure there isn't already a column with this name.
00268   remove_column(column.get_name());
00269 
00270   // Also make sure there aren't any columns that overlap with this
00271   // one.
00272   const GeomVertexColumn *orig_column = get_column(column.get_start(), column.get_total_bytes());
00273   while (orig_column != (const GeomVertexColumn *)NULL) {
00274     remove_column(orig_column->get_name());
00275     orig_column = get_column(column.get_start(), column.get_total_bytes());
00276   }
00277 
00278   _total_bytes = max(_total_bytes, column.get_start() + column.get_total_bytes());
00279   _pad_to = max(_pad_to, column.get_component_bytes());
00280   _stride = max(_stride, ((_total_bytes + _pad_to - 1) / _pad_to) * _pad_to);
00281 
00282   GeomVertexColumn *new_column = new GeomVertexColumn(column);
00283 
00284   if (!_columns.empty() && *new_column < *_columns.back()) {
00285     _columns_unsorted = true;
00286   }
00287 
00288   int new_index = (int)_columns.size();
00289   _columns.push_back(new_column);
00290   _columns_by_name.insert(ColumnsByName::value_type(new_column->get_name(), new_column));
00291 
00292   return new_index;
00293 }
00294 
00295 ////////////////////////////////////////////////////////////////////
00296 //     Function: GeomVertexArrayFormat::remove_column
00297 //       Access: Published
00298 //  Description: Removes the column with the indicated name, if
00299 //               any.  This leaves a gap in the byte structure.
00300 ////////////////////////////////////////////////////////////////////
00301 void GeomVertexArrayFormat::
00302 remove_column(const InternalName *name) {
00303   nassertv(!_is_registered);
00304   ColumnsByName::iterator ni;
00305   ni = _columns_by_name.find(name);
00306   if (ni != _columns_by_name.end()) {
00307     GeomVertexColumn *column = (*ni).second;
00308     _columns_by_name.erase(ni);
00309 
00310     Columns::iterator ci;
00311     ci = find(_columns.begin(), _columns.end(), column);
00312     nassertv(ci != _columns.end());
00313     _columns.erase(ci);
00314 
00315     delete column;
00316 
00317     // Maybe we just removed the tail column.  If that's so, we
00318     // should recompute _total_bytes to reflect the new tail.
00319     if (_columns.empty()) {
00320       _total_bytes = 0;
00321     } else {
00322       consider_sort_columns();
00323       GeomVertexColumn *last = _columns.back();
00324       _total_bytes = last->get_start() + last->get_total_bytes();
00325     }
00326   }
00327 }
00328 
00329 ////////////////////////////////////////////////////////////////////
00330 //     Function: GeomVertexArrayFormat::clear_columns
00331 //       Access: Published
00332 //  Description: Removes all columns previously added, sets the
00333 //               stride to zero, and prepares to start over.
00334 ////////////////////////////////////////////////////////////////////
00335 void GeomVertexArrayFormat::
00336 clear_columns() {
00337   nassertv(!_is_registered);
00338 
00339   _columns.clear();
00340   _columns_by_name.clear();
00341   _columns_unsorted = false;
00342   _stride = 0;
00343   _total_bytes = 0;
00344   _pad_to = 1;
00345 }
00346 
00347 ////////////////////////////////////////////////////////////////////
00348 //     Function: GeomVertexArrayFormat::pack_columns
00349 //       Access: Published
00350 //  Description: Removes wasted space between columns.
00351 ////////////////////////////////////////////////////////////////////
00352 void GeomVertexArrayFormat::
00353 pack_columns() {
00354   nassertv(!_is_registered);
00355 
00356   Columns orig_columns;
00357   orig_columns.swap(_columns);
00358   clear_columns();
00359 
00360   Columns::const_iterator ci;
00361   for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
00362     GeomVertexColumn *column = (*ci);
00363     add_column(column->get_name(), column->get_num_components(),
00364                column->get_numeric_type(), column->get_contents());
00365   }
00366 }
00367 
00368 ////////////////////////////////////////////////////////////////////
00369 //     Function: GeomVertexArrayFormat::get_column
00370 //       Access: Published
00371 //  Description: Returns the specification with the indicated name, or
00372 //               NULL if the name is not used.
00373 ////////////////////////////////////////////////////////////////////
00374 const GeomVertexColumn *GeomVertexArrayFormat::
00375 get_column(const InternalName *name) const {
00376   ColumnsByName::const_iterator ni;
00377   ni = _columns_by_name.find(name);
00378   if (ni != _columns_by_name.end()) {
00379     return (*ni).second;
00380   }
00381   return NULL;
00382 }
00383 
00384 ////////////////////////////////////////////////////////////////////
00385 //     Function: GeomVertexArrayFormat::get_column
00386 //       Access: Published
00387 //  Description: Returns the first specification that overlaps with
00388 //               any of the indicated bytes in the range, or NULL if
00389 //               none do.
00390 ////////////////////////////////////////////////////////////////////
00391 const GeomVertexColumn *GeomVertexArrayFormat::
00392 get_column(int start_byte, int num_bytes) const {
00393   consider_sort_columns();
00394   Columns::const_iterator ci;
00395   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00396     const GeomVertexColumn *column = (*ci);
00397     if (column->overlaps_with(start_byte, num_bytes)) {
00398       return column;
00399     }
00400   }
00401 
00402   return NULL;
00403 }
00404 
00405 ////////////////////////////////////////////////////////////////////
00406 //     Function: GeomVertexArrayFormat::is_data_subset_of
00407 //       Access: Published
00408 //  Description: Returns true if all of the fields in this array
00409 //               format are also present and equivalent in the other
00410 //               array format, and in the same byte positions, and the
00411 //               stride is the same.  That is, true if this format can
00412 //               share the same data pointer as the other format (with
00413 //               possibly some unused gaps).
00414 ////////////////////////////////////////////////////////////////////
00415 bool GeomVertexArrayFormat::
00416 is_data_subset_of(const GeomVertexArrayFormat &other) const {
00417   if (_columns.size() > other._columns.size() ||
00418       get_stride() != other.get_stride()) {
00419     return false;
00420   }
00421 
00422   consider_sort_columns();
00423   other.consider_sort_columns();
00424   size_t i = 0;
00425   size_t j = 0;
00426   while (i < _columns.size() && j < other._columns.size()) {
00427     if (*_columns[i] == *other._columns[j]) {
00428       ++i;
00429     }
00430     ++j;
00431   }
00432 
00433   // If we reached the end of our list, all fields matched.
00434   return (i == _columns.size());
00435 }
00436 
00437 ////////////////////////////////////////////////////////////////////
00438 //     Function: GeomVertexArrayFormat::count_unused_space
00439 //       Access: Published
00440 //  Description: Returns the number of bytes per row that are not
00441 //               assigned to any column.
00442 ////////////////////////////////////////////////////////////////////
00443 int GeomVertexArrayFormat::
00444 count_unused_space() const {
00445   consider_sort_columns();
00446 
00447   int unused_space = 0;
00448   int last_pos = 0;
00449 
00450   Columns::const_iterator ci;
00451   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00452     const GeomVertexColumn *column = (*ci);
00453     if (column->get_start() > last_pos) {
00454       unused_space += (column->get_start() - last_pos);
00455     }
00456     last_pos = column->get_start() + column->get_total_bytes();
00457   }
00458 
00459   if (_stride > last_pos) {
00460     unused_space += (_stride - last_pos);
00461   }
00462 
00463   return unused_space;
00464 }
00465 
00466 ////////////////////////////////////////////////////////////////////
00467 //     Function: GeomVertexArrayFormat::output
00468 //       Access: Published
00469 //  Description: 
00470 ////////////////////////////////////////////////////////////////////
00471 void GeomVertexArrayFormat::
00472 output(ostream &out) const {
00473   Columns::const_iterator ci;
00474   int last_pos = 0;
00475   out << "[";
00476   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00477     const GeomVertexColumn *column = (*ci);
00478     if (column->get_start() > last_pos) {
00479       out << " ..." << (column->get_start() - last_pos) << "...";
00480     }
00481     out << " " << *column;
00482     last_pos = column->get_start() + column->get_total_bytes();
00483   }
00484 
00485   if (_stride > last_pos) {
00486     out << " ..." << (_stride - last_pos) << "...";
00487   }
00488 
00489   out << " ]";
00490 }
00491 
00492 ////////////////////////////////////////////////////////////////////
00493 //     Function: GeomVertexArrayFormat::write
00494 //       Access: Published
00495 //  Description: 
00496 ////////////////////////////////////////////////////////////////////
00497 void GeomVertexArrayFormat::
00498 write(ostream &out, int indent_level) const {
00499   indent(out, indent_level)
00500     << "Array format (stride = " << get_stride() << "):\n";
00501   consider_sort_columns();
00502   Columns::const_iterator ci;
00503   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00504     const GeomVertexColumn *column = (*ci);
00505     indent(out, indent_level + 2)
00506       << *column 
00507       << " " << column->get_numeric_type()
00508       << " " << column->get_contents()
00509       << " start at " << column->get_start() << "\n";
00510   }
00511 }
00512 
00513 ////////////////////////////////////////////////////////////////////
00514 //     Function: GeomVertexArrayFormat::write_with_data
00515 //       Access: Published
00516 //  Description: 
00517 ////////////////////////////////////////////////////////////////////
00518 void GeomVertexArrayFormat::
00519 write_with_data(ostream &out, int indent_level,
00520                 const GeomVertexArrayData *array_data) const {
00521   consider_sort_columns();
00522   int num_rows = array_data->get_num_rows();
00523 
00524   GeomVertexReader reader(array_data);
00525 
00526   for (int i = 0; i < num_rows; i++) {
00527     indent(out, indent_level)
00528       << "row " << i << ":\n";
00529     reader.set_row(i);
00530     Columns::const_iterator ci;
00531     for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00532       const GeomVertexColumn *column = (*ci);
00533       int num_values = min(column->get_num_values(), 4);
00534       reader.set_column(0, column);
00535       const LVecBase4f &d = reader.get_data4f();
00536 
00537       indent(out, indent_level + 2) 
00538         << *column->get_name();
00539       for (int v = 0; v < num_values; v++) {
00540         out << " " << d[v];
00541       }
00542       out << "\n";
00543     }
00544   }
00545 }
00546 
00547 ////////////////////////////////////////////////////////////////////
00548 //     Function: GeomVertexArrayFormat::compare_to
00549 //       Access: Public
00550 //  Description: 
00551 ////////////////////////////////////////////////////////////////////
00552 int GeomVertexArrayFormat::
00553 compare_to(const GeomVertexArrayFormat &other) const {
00554   if (_stride != other._stride) {
00555     return _stride - other._stride;
00556   }
00557   if (_total_bytes != other._total_bytes) {
00558     return _total_bytes - other._total_bytes;
00559   }
00560   if (_pad_to != other._pad_to) {
00561     return _pad_to - other._pad_to;
00562   }
00563   if (_columns.size() != other._columns.size()) {
00564     return (int)_columns.size() - (int)other._columns.size();
00565   }
00566   consider_sort_columns();
00567   other.consider_sort_columns();
00568   for (size_t i = 0; i < _columns.size(); i++) {
00569     int compare = _columns[i]->compare_to(*other._columns[i]);
00570     if (compare != 0) {
00571       return compare;
00572     }
00573   }
00574 
00575   return 0;
00576 }
00577 
00578 ////////////////////////////////////////////////////////////////////
00579 //     Function: GeomVertexArrayFormat::sort_columns
00580 //       Access: Private
00581 //  Description: Resorts the _columns vector so that the columns
00582 //               are listed in the same order they appear in the
00583 //               record.
00584 ////////////////////////////////////////////////////////////////////
00585 void GeomVertexArrayFormat::
00586 sort_columns() {
00587   sort(_columns.begin(), _columns.end(), IndirectLess<GeomVertexColumn>());
00588 }
00589 
00590 ////////////////////////////////////////////////////////////////////
00591 //     Function: GeomVertexArrayFormat::make_registry
00592 //       Access: Private
00593 //  Description: Returns the global registry object.
00594 ////////////////////////////////////////////////////////////////////
00595 void GeomVertexArrayFormat::
00596 make_registry() {
00597   if (_registry == (Registry *)NULL) {
00598     _registry = new Registry;
00599   }
00600 }
00601 
00602 ////////////////////////////////////////////////////////////////////
00603 //     Function: GeomVertexArrayFormat::do_register
00604 //       Access: Private
00605 //  Description: Called internally when the format is registered.
00606 ////////////////////////////////////////////////////////////////////
00607 void GeomVertexArrayFormat::
00608 do_register() {
00609   nassertv(!_is_registered);
00610   _is_registered = true;
00611 }
00612  
00613 ////////////////////////////////////////////////////////////////////
00614 //     Function: GeomVertexArrayFormat::do_unregister
00615 //       Access: Private
00616 //  Description: Called internally when the format is unregistered.
00617 ////////////////////////////////////////////////////////////////////
00618 void GeomVertexArrayFormat::
00619 do_unregister() {
00620   nassertv(_is_registered);
00621   _is_registered = false;
00622 }
00623 
00624 ////////////////////////////////////////////////////////////////////
00625 //     Function: GeomVertexArrayFormat::register_with_read_factory
00626 //       Access: Public, Static
00627 //  Description: Tells the BamReader how to create objects of type
00628 //               GeomVertexArrayFormat.
00629 ////////////////////////////////////////////////////////////////////
00630 void GeomVertexArrayFormat::
00631 register_with_read_factory() {
00632   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00633 }
00634 
00635 ////////////////////////////////////////////////////////////////////
00636 //     Function: GeomVertexArrayFormat::write_datagram
00637 //       Access: Public, Virtual
00638 //  Description: Writes the contents of this object to the datagram
00639 //               for shipping out to a Bam file.
00640 ////////////////////////////////////////////////////////////////////
00641 void GeomVertexArrayFormat::
00642 write_datagram(BamWriter *manager, Datagram &dg) {
00643   TypedWritableReferenceCount::write_datagram(manager, dg);
00644 
00645   dg.add_uint16(_stride);
00646   dg.add_uint16(_total_bytes);
00647   dg.add_uint8(_pad_to);
00648 
00649   consider_sort_columns();
00650 
00651   dg.add_uint16(_columns.size());
00652   Columns::iterator ci;
00653   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00654     GeomVertexColumn *column = (*ci);
00655     column->write_datagram(manager, dg);
00656   }
00657 }
00658 
00659 ////////////////////////////////////////////////////////////////////
00660 //     Function: GeomVertexArrayFormat::complete_pointers
00661 //       Access: Public, Virtual
00662 //  Description: Receives an array of pointers, one for each time
00663 //               manager->read_pointer() was called in fillin().
00664 //               Returns the number of pointers processed.
00665 ////////////////////////////////////////////////////////////////////
00666 int GeomVertexArrayFormat::
00667 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00668   int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
00669 
00670   Columns::iterator ci;
00671   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00672     GeomVertexColumn *column = (*ci);
00673     pi += column->complete_pointers(p_list + pi, manager);
00674   }
00675 
00676   return pi;
00677 }
00678 
00679 ////////////////////////////////////////////////////////////////////
00680 //     Function: GeomVertexArrayFormat::finalize
00681 //       Access: Public, Virtual
00682 //  Description: Called by the BamReader to perform any final actions
00683 //               needed for setting up the object after all objects
00684 //               have been read and all pointers have been completed.
00685 ////////////////////////////////////////////////////////////////////
00686 void GeomVertexArrayFormat::
00687 finalize(BamReader *manager) {
00688   // Now we can build up the _columns_by_name index.  We have to wait
00689   // until finalize(), since the index is based on the nested name
00690   // pointer within each column, which might not be available at the
00691   // time complete_pointers() is called.
00692   _columns_by_name.clear();
00693   Columns::iterator ci;
00694   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00695     GeomVertexColumn *column = (*ci);
00696     _columns_by_name.insert(ColumnsByName::value_type(column->get_name(), column));
00697   }
00698 }
00699 
00700 ////////////////////////////////////////////////////////////////////
00701 //     Function: GeomVertexArrayFormat::make_from_bam
00702 //       Access: Protected, Static
00703 //  Description: This function is called by the BamReader's factory
00704 //               when a new object of type GeomVertexArrayFormat is
00705 //               encountered in the Bam file.  It should create the
00706 //               GeomVertexArrayFormat and extract its information
00707 //               from the file.
00708 ////////////////////////////////////////////////////////////////////
00709 TypedWritable *GeomVertexArrayFormat::
00710 make_from_bam(const FactoryParams &params) {
00711   GeomVertexArrayFormat *object = new GeomVertexArrayFormat;
00712   DatagramIterator scan;
00713   BamReader *manager;
00714 
00715   parse_params(params, scan, manager);
00716   object->fillin(scan, manager);
00717   manager->register_finalize(object);
00718 
00719   return object;
00720 }
00721 
00722 ////////////////////////////////////////////////////////////////////
00723 //     Function: GeomVertexArrayFormat::fillin
00724 //       Access: Protected
00725 //  Description: This internal function is called by make_from_bam to
00726 //               read in all of the relevant data from the BamFile for
00727 //               the new GeomVertexArrayFormat.
00728 ////////////////////////////////////////////////////////////////////
00729 void GeomVertexArrayFormat::
00730 fillin(DatagramIterator &scan, BamReader *manager) {
00731   TypedWritableReferenceCount::fillin(scan, manager);
00732   nassertv(!_is_registered);
00733 
00734   _stride = scan.get_uint16();
00735   _total_bytes = scan.get_uint16();
00736   _pad_to = scan.get_uint8();
00737 
00738   int num_columns = scan.get_uint16();
00739   _columns.reserve(num_columns);
00740   for (int i = 0; i < num_columns; ++i) {
00741     GeomVertexColumn *column = new GeomVertexColumn;
00742     column->fillin(scan, manager);
00743     _columns.push_back(column);
00744   }
00745   _columns_unsorted = false;
00746 }
00747 
00748 ////////////////////////////////////////////////////////////////////
00749 //     Function: GeomVertexArrayFormat::Registry::Constructor
00750 //       Access: Public
00751 //  Description: 
00752 ////////////////////////////////////////////////////////////////////
00753 GeomVertexArrayFormat::Registry::
00754 Registry() {
00755 }
00756 
00757 ////////////////////////////////////////////////////////////////////
00758 //     Function: GeomVertexArrayFormat::Registry::register_format
00759 //       Access: Public
00760 //  Description: Adds the indicated format to the registry, if there
00761 //               is not an equivalent format already there; in either
00762 //               case, returns the pointer to the equivalent format
00763 //               now in the registry.
00764 //
00765 //               This must be called before a format may be used in a
00766 //               Geom.  After this call, you should discard the
00767 //               original pointer you passed in (which may or may not
00768 //               now be invalid) and let its reference count decrement
00769 //               normally; you should use only the returned value from
00770 //               this point on.
00771 ////////////////////////////////////////////////////////////////////
00772 CPT(GeomVertexArrayFormat) GeomVertexArrayFormat::Registry::
00773 register_format(GeomVertexArrayFormat *format) {
00774   if (format->is_registered()) {
00775     return format;
00776   }
00777 
00778   // Save the incoming pointer in a local PointerTo, so that if it has
00779   // a zero reference count and is not added into the map below, it
00780   // will be automatically deleted when this function returns.
00781   PT(GeomVertexArrayFormat) pt_format = format;
00782   
00783   GeomVertexArrayFormat *new_format;
00784   {
00785     LightMutexHolder holder(_lock);
00786     ArrayFormats::iterator fi = _formats.insert(format).first;
00787     new_format = (*fi);
00788     if (!new_format->is_registered()) {
00789       new_format->do_register();
00790     }
00791   }
00792 
00793   return new_format;
00794 }
00795 
00796 ////////////////////////////////////////////////////////////////////
00797 //     Function: GeomVertexArrayFormat::Registry::unregister_format
00798 //       Access: Public
00799 //  Description: Removes the indicated format from the registry.
00800 //               Normally this should not be done until the format is
00801 //               destructing.
00802 //
00803 //               The lock should be held prior to calling this method.
00804 ////////////////////////////////////////////////////////////////////
00805 void GeomVertexArrayFormat::Registry::
00806 unregister_format(GeomVertexArrayFormat *format) {
00807   nassertv(format->is_registered());
00808   ArrayFormats::iterator fi = _formats.find(format);
00809   nassertv(fi != _formats.end());
00810   _formats.erase(fi);
00811   format->do_unregister();
00812 }
 All Classes Functions Variables Enumerations