Panda3D
 All Classes Functions Variables Enumerations
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            int column_alignment) {
00235   if (start < 0) {
00236     start = _total_bytes;
00237   }
00238 
00239   return add_column(GeomVertexColumn(name, num_components, numeric_type, contents, 
00240                                      start, column_alignment));
00241 }
00242 
00243 ////////////////////////////////////////////////////////////////////
00244 //     Function: GeomVertexArrayFormat::add_column
00245 //       Access: Published
00246 //  Description: Adds a new column to the specification.  This is a
00247 //               table of per-vertex floating-point numbers such as
00248 //               "vertex" or "normal"; you must specify where in each
00249 //               record the table starts, and how many components
00250 //               (dimensions) exist per vertex.
00251 //
00252 //               Adding a column with the same name as a previous
00253 //               type, or that overlaps with one or more previous
00254 //               types, quietly removes the previous type(s).
00255 //
00256 //               The return value is the index number of the new data
00257 //               type.
00258 ////////////////////////////////////////////////////////////////////
00259 int GeomVertexArrayFormat::
00260 add_column(const GeomVertexColumn &column) {
00261   nassertr(!_is_registered, -1);
00262 
00263   // Make sure there isn't already a column with this name.
00264   remove_column(column.get_name());
00265 
00266   // Also make sure there aren't any columns that overlap with this
00267   // one.
00268   const GeomVertexColumn *orig_column = get_column(column.get_start(), column.get_total_bytes());
00269   while (orig_column != (const GeomVertexColumn *)NULL) {
00270     remove_column(orig_column->get_name());
00271     orig_column = get_column(column.get_start(), column.get_total_bytes());
00272   }
00273 
00274   _total_bytes = max(_total_bytes, column.get_start() + column.get_total_bytes());
00275   _pad_to = max(_pad_to, column.get_column_alignment());
00276   _stride = max(_stride, _total_bytes);
00277   if (_pad_to > 1) {
00278     _stride = ((_stride + _pad_to - 1) / _pad_to) * _pad_to;
00279   }
00280 
00281   GeomVertexColumn *new_column = new GeomVertexColumn(column);
00282 
00283   if (!_columns.empty() && *new_column < *_columns.back()) {
00284     _columns_unsorted = true;
00285   }
00286 
00287   int new_index = (int)_columns.size();
00288   _columns.push_back(new_column);
00289   _columns_by_name.insert(ColumnsByName::value_type(new_column->get_name(), new_column));
00290 
00291   return new_index;
00292 }
00293 
00294 ////////////////////////////////////////////////////////////////////
00295 //     Function: GeomVertexArrayFormat::remove_column
00296 //       Access: Published
00297 //  Description: Removes the column with the indicated name, if
00298 //               any.  This leaves a gap in the byte structure.
00299 ////////////////////////////////////////////////////////////////////
00300 void GeomVertexArrayFormat::
00301 remove_column(const InternalName *name) {
00302   nassertv(!_is_registered);
00303   ColumnsByName::iterator ni;
00304   ni = _columns_by_name.find(name);
00305   if (ni != _columns_by_name.end()) {
00306     GeomVertexColumn *column = (*ni).second;
00307     _columns_by_name.erase(ni);
00308 
00309     Columns::iterator ci;
00310     ci = find(_columns.begin(), _columns.end(), column);
00311     nassertv(ci != _columns.end());
00312     _columns.erase(ci);
00313 
00314     delete column;
00315 
00316     // Maybe we just removed the tail column.  If that's so, we
00317     // should recompute _total_bytes to reflect the new tail.
00318     if (_columns.empty()) {
00319       _total_bytes = 0;
00320     } else {
00321       consider_sort_columns();
00322       GeomVertexColumn *last = _columns.back();
00323       _total_bytes = last->get_start() + last->get_total_bytes();
00324     }
00325   }
00326 }
00327 
00328 ////////////////////////////////////////////////////////////////////
00329 //     Function: GeomVertexArrayFormat::clear_columns
00330 //       Access: Published
00331 //  Description: Removes all columns previously added, sets the
00332 //               stride to zero, and prepares to start over.
00333 ////////////////////////////////////////////////////////////////////
00334 void GeomVertexArrayFormat::
00335 clear_columns() {
00336   nassertv(!_is_registered);
00337 
00338   _columns.clear();
00339   _columns_by_name.clear();
00340   _columns_unsorted = false;
00341   _stride = 0;
00342   _total_bytes = 0;
00343   _pad_to = 1;
00344 }
00345 
00346 ////////////////////////////////////////////////////////////////////
00347 //     Function: GeomVertexArrayFormat::pack_columns
00348 //       Access: Published
00349 //  Description: Removes wasted space between columns.
00350 ////////////////////////////////////////////////////////////////////
00351 void GeomVertexArrayFormat::
00352 pack_columns() {
00353   nassertv(!_is_registered);
00354 
00355   Columns orig_columns;
00356   orig_columns.swap(_columns);
00357   clear_columns();
00358 
00359   Columns::const_iterator ci;
00360   for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
00361     GeomVertexColumn *column = (*ci);
00362     add_column(column->get_name(), column->get_num_components(),
00363                column->get_numeric_type(), column->get_contents());
00364   }
00365 }
00366 
00367 ////////////////////////////////////////////////////////////////////
00368 //     Function: GeomVertexArrayFormat::align_columns_for_animation
00369 //       Access: Published
00370 //  Description: Reprocesses the columns in the format to align the
00371 //               C_point and C_vector columns to 16-byte boundaries to
00372 //               allow for the more efficient SSE2 operations
00373 //               (assuming SSE2 is enabled in the build).
00374 //
00375 //               The caller is responsible for testing
00376 //               vertex_animation_align_16 to decide whether to call
00377 //               this method.
00378 ////////////////////////////////////////////////////////////////////
00379 void GeomVertexArrayFormat::
00380 align_columns_for_animation() {
00381   nassertv(!_is_registered);
00382 
00383   Columns orig_columns;
00384   orig_columns.swap(_columns);
00385   clear_columns();
00386 
00387   Columns::const_iterator ci;
00388   for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
00389     GeomVertexColumn *column = (*ci);
00390     if ((column->get_contents() == C_point || column->get_contents() == C_vector) &&
00391         (column->get_numeric_type() == NT_float32 || column->get_numeric_type() == NT_float64) &&
00392         column->get_num_components() >= 3) {
00393       add_column(column->get_name(), 4, column->get_numeric_type(), column->get_contents(), -1, 16);
00394     } else {
00395       add_column(column->get_name(), column->get_num_components(),
00396                  column->get_numeric_type(), column->get_contents());
00397     }
00398   }
00399 }
00400 
00401 
00402 ////////////////////////////////////////////////////////////////////
00403 //     Function: GeomVertexArrayFormat::get_column
00404 //       Access: Published
00405 //  Description: Returns the specification with the indicated name, or
00406 //               NULL if the name is not used.
00407 ////////////////////////////////////////////////////////////////////
00408 const GeomVertexColumn *GeomVertexArrayFormat::
00409 get_column(const InternalName *name) const {
00410   ColumnsByName::const_iterator ni;
00411   ni = _columns_by_name.find(name);
00412   if (ni != _columns_by_name.end()) {
00413     return (*ni).second;
00414   }
00415   return NULL;
00416 }
00417 
00418 ////////////////////////////////////////////////////////////////////
00419 //     Function: GeomVertexArrayFormat::get_column
00420 //       Access: Published
00421 //  Description: Returns the first specification that overlaps with
00422 //               any of the indicated bytes in the range, or NULL if
00423 //               none do.
00424 ////////////////////////////////////////////////////////////////////
00425 const GeomVertexColumn *GeomVertexArrayFormat::
00426 get_column(int start_byte, int num_bytes) const {
00427   consider_sort_columns();
00428   Columns::const_iterator ci;
00429   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00430     const GeomVertexColumn *column = (*ci);
00431     if (column->overlaps_with(start_byte, num_bytes)) {
00432       return column;
00433     }
00434   }
00435 
00436   return NULL;
00437 }
00438 
00439 ////////////////////////////////////////////////////////////////////
00440 //     Function: GeomVertexArrayFormat::is_data_subset_of
00441 //       Access: Published
00442 //  Description: Returns true if all of the fields in this array
00443 //               format are also present and equivalent in the other
00444 //               array format, and in the same byte positions, and the
00445 //               stride is the same.  That is, true if this format can
00446 //               share the same data pointer as the other format (with
00447 //               possibly some unused gaps).
00448 ////////////////////////////////////////////////////////////////////
00449 bool GeomVertexArrayFormat::
00450 is_data_subset_of(const GeomVertexArrayFormat &other) const {
00451   if (_columns.size() > other._columns.size() ||
00452       get_stride() != other.get_stride()) {
00453     return false;
00454   }
00455 
00456   consider_sort_columns();
00457   other.consider_sort_columns();
00458   size_t i = 0;
00459   size_t j = 0;
00460   while (i < _columns.size() && j < other._columns.size()) {
00461     if (*_columns[i] == *other._columns[j]) {
00462       ++i;
00463     }
00464     ++j;
00465   }
00466 
00467   // If we reached the end of our list, all fields matched.
00468   return (i == _columns.size());
00469 }
00470 
00471 ////////////////////////////////////////////////////////////////////
00472 //     Function: GeomVertexArrayFormat::count_unused_space
00473 //       Access: Published
00474 //  Description: Returns the number of bytes per row that are not
00475 //               assigned to any column.
00476 ////////////////////////////////////////////////////////////////////
00477 int GeomVertexArrayFormat::
00478 count_unused_space() const {
00479   consider_sort_columns();
00480 
00481   int unused_space = 0;
00482   int last_pos = 0;
00483 
00484   Columns::const_iterator ci;
00485   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00486     const GeomVertexColumn *column = (*ci);
00487     if (column->get_start() > last_pos) {
00488       unused_space += (column->get_start() - last_pos);
00489     }
00490     last_pos = column->get_start() + column->get_total_bytes();
00491   }
00492 
00493   if (_stride > last_pos) {
00494     unused_space += (_stride - last_pos);
00495   }
00496 
00497   return unused_space;
00498 }
00499 
00500 ////////////////////////////////////////////////////////////////////
00501 //     Function: GeomVertexArrayFormat::output
00502 //       Access: Published
00503 //  Description: 
00504 ////////////////////////////////////////////////////////////////////
00505 void GeomVertexArrayFormat::
00506 output(ostream &out) const {
00507   Columns::const_iterator ci;
00508   int last_pos = 0;
00509   out << "[";
00510   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00511     const GeomVertexColumn *column = (*ci);
00512     if (column->get_start() > last_pos) {
00513       out << " (..." << (column->get_start() - last_pos) << "...)";
00514     }
00515     out << " " << *column;
00516     last_pos = column->get_start() + column->get_total_bytes();
00517   }
00518 
00519   if (_stride > last_pos) {
00520     out << " ..." << (_stride - last_pos) << "...";
00521   }
00522 
00523   out << " ]";
00524 }
00525 
00526 ////////////////////////////////////////////////////////////////////
00527 //     Function: GeomVertexArrayFormat::write
00528 //       Access: Published
00529 //  Description: 
00530 ////////////////////////////////////////////////////////////////////
00531 void GeomVertexArrayFormat::
00532 write(ostream &out, int indent_level) const {
00533   indent(out, indent_level)
00534     << "Array format (stride = " << get_stride() << "):\n";
00535   consider_sort_columns();
00536   Columns::const_iterator ci;
00537   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00538     const GeomVertexColumn *column = (*ci);
00539     indent(out, indent_level + 2)
00540       << *column 
00541       << " " << column->get_numeric_type()
00542       << " " << column->get_contents()
00543       << " start at " << column->get_start() << "\n";
00544   }
00545 }
00546 
00547 ////////////////////////////////////////////////////////////////////
00548 //     Function: GeomVertexArrayFormat::write_with_data
00549 //       Access: Published
00550 //  Description: 
00551 ////////////////////////////////////////////////////////////////////
00552 void GeomVertexArrayFormat::
00553 write_with_data(ostream &out, int indent_level,
00554                 const GeomVertexArrayData *array_data) const {
00555   consider_sort_columns();
00556   int num_rows = array_data->get_num_rows();
00557 
00558   GeomVertexReader reader(array_data);
00559 
00560   for (int i = 0; i < num_rows; i++) {
00561     indent(out, indent_level)
00562       << "row " << i << ":\n";
00563     reader.set_row_unsafe(i);
00564     Columns::const_iterator ci;
00565     for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00566       const GeomVertexColumn *column = (*ci);
00567       int num_values = min(column->get_num_values(), 4);
00568       reader.set_column(0, column);
00569       const LVecBase4f &d = reader.get_data4f();
00570 
00571       indent(out, indent_level + 2) 
00572         << *column->get_name();
00573       for (int v = 0; v < num_values; v++) {
00574         out << " " << d[v];
00575       }
00576       out << "\n";
00577     }
00578   }
00579 }
00580 
00581 ////////////////////////////////////////////////////////////////////
00582 //     Function: GeomVertexArrayFormat::compare_to
00583 //       Access: Public
00584 //  Description: 
00585 ////////////////////////////////////////////////////////////////////
00586 int GeomVertexArrayFormat::
00587 compare_to(const GeomVertexArrayFormat &other) const {
00588   if (_stride != other._stride) {
00589     return _stride - other._stride;
00590   }
00591   if (_total_bytes != other._total_bytes) {
00592     return _total_bytes - other._total_bytes;
00593   }
00594   if (_pad_to != other._pad_to) {
00595     return _pad_to - other._pad_to;
00596   }
00597   if (_columns.size() != other._columns.size()) {
00598     return (int)_columns.size() - (int)other._columns.size();
00599   }
00600   consider_sort_columns();
00601   other.consider_sort_columns();
00602   for (size_t i = 0; i < _columns.size(); i++) {
00603     int compare = _columns[i]->compare_to(*other._columns[i]);
00604     if (compare != 0) {
00605       return compare;
00606     }
00607   }
00608 
00609   return 0;
00610 }
00611 
00612 ////////////////////////////////////////////////////////////////////
00613 //     Function: GeomVertexArrayFormat::sort_columns
00614 //       Access: Private
00615 //  Description: Resorts the _columns vector so that the columns
00616 //               are listed in the same order they appear in the
00617 //               record.
00618 ////////////////////////////////////////////////////////////////////
00619 void GeomVertexArrayFormat::
00620 sort_columns() {
00621   sort(_columns.begin(), _columns.end(), IndirectLess<GeomVertexColumn>());
00622 }
00623 
00624 ////////////////////////////////////////////////////////////////////
00625 //     Function: GeomVertexArrayFormat::make_registry
00626 //       Access: Private
00627 //  Description: Returns the global registry object.
00628 ////////////////////////////////////////////////////////////////////
00629 void GeomVertexArrayFormat::
00630 make_registry() {
00631   if (_registry == (Registry *)NULL) {
00632     _registry = new Registry;
00633   }
00634 }
00635 
00636 ////////////////////////////////////////////////////////////////////
00637 //     Function: GeomVertexArrayFormat::do_register
00638 //       Access: Private
00639 //  Description: Called internally when the format is registered.
00640 ////////////////////////////////////////////////////////////////////
00641 void GeomVertexArrayFormat::
00642 do_register() {
00643   nassertv(!_is_registered);
00644   _is_registered = true;
00645 }
00646  
00647 ////////////////////////////////////////////////////////////////////
00648 //     Function: GeomVertexArrayFormat::do_unregister
00649 //       Access: Private
00650 //  Description: Called internally when the format is unregistered.
00651 ////////////////////////////////////////////////////////////////////
00652 void GeomVertexArrayFormat::
00653 do_unregister() {
00654   nassertv(_is_registered);
00655   _is_registered = false;
00656 }
00657 
00658 ////////////////////////////////////////////////////////////////////
00659 //     Function: GeomVertexArrayFormat::register_with_read_factory
00660 //       Access: Public, Static
00661 //  Description: Tells the BamReader how to create objects of type
00662 //               GeomVertexArrayFormat.
00663 ////////////////////////////////////////////////////////////////////
00664 void GeomVertexArrayFormat::
00665 register_with_read_factory() {
00666   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00667 }
00668 
00669 ////////////////////////////////////////////////////////////////////
00670 //     Function: GeomVertexArrayFormat::write_datagram
00671 //       Access: Public, Virtual
00672 //  Description: Writes the contents of this object to the datagram
00673 //               for shipping out to a Bam file.
00674 ////////////////////////////////////////////////////////////////////
00675 void GeomVertexArrayFormat::
00676 write_datagram(BamWriter *manager, Datagram &dg) {
00677   TypedWritableReferenceCount::write_datagram(manager, dg);
00678 
00679   dg.add_uint16(_stride);
00680   dg.add_uint16(_total_bytes);
00681   dg.add_uint8(_pad_to);
00682 
00683   consider_sort_columns();
00684 
00685   dg.add_uint16(_columns.size());
00686   Columns::iterator ci;
00687   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00688     GeomVertexColumn *column = (*ci);
00689     column->write_datagram(manager, dg);
00690   }
00691 }
00692 
00693 ////////////////////////////////////////////////////////////////////
00694 //     Function: GeomVertexArrayFormat::complete_pointers
00695 //       Access: Public, Virtual
00696 //  Description: Receives an array of pointers, one for each time
00697 //               manager->read_pointer() was called in fillin().
00698 //               Returns the number of pointers processed.
00699 ////////////////////////////////////////////////////////////////////
00700 int GeomVertexArrayFormat::
00701 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00702   int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
00703 
00704   Columns::iterator ci;
00705   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00706     GeomVertexColumn *column = (*ci);
00707     pi += column->complete_pointers(p_list + pi, manager);
00708   }
00709 
00710   return pi;
00711 }
00712 
00713 ////////////////////////////////////////////////////////////////////
00714 //     Function: GeomVertexArrayFormat::finalize
00715 //       Access: Public, Virtual
00716 //  Description: Called by the BamReader to perform any final actions
00717 //               needed for setting up the object after all objects
00718 //               have been read and all pointers have been completed.
00719 ////////////////////////////////////////////////////////////////////
00720 void GeomVertexArrayFormat::
00721 finalize(BamReader *manager) {
00722   // Now we can build up the _columns_by_name index.  We have to wait
00723   // until finalize(), since the index is based on the nested name
00724   // pointer within each column, which might not be available at the
00725   // time complete_pointers() is called.
00726   _columns_by_name.clear();
00727   Columns::iterator ci;
00728   for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
00729     GeomVertexColumn *column = (*ci);
00730     _columns_by_name.insert(ColumnsByName::value_type(column->get_name(), column));
00731   }
00732 }
00733 
00734 ////////////////////////////////////////////////////////////////////
00735 //     Function: GeomVertexArrayFormat::make_from_bam
00736 //       Access: Protected, Static
00737 //  Description: This function is called by the BamReader's factory
00738 //               when a new object of type GeomVertexArrayFormat is
00739 //               encountered in the Bam file.  It should create the
00740 //               GeomVertexArrayFormat and extract its information
00741 //               from the file.
00742 ////////////////////////////////////////////////////////////////////
00743 TypedWritable *GeomVertexArrayFormat::
00744 make_from_bam(const FactoryParams &params) {
00745   GeomVertexArrayFormat *object = new GeomVertexArrayFormat;
00746   DatagramIterator scan;
00747   BamReader *manager;
00748 
00749   parse_params(params, scan, manager);
00750   object->fillin(scan, manager);
00751   manager->register_finalize(object);
00752 
00753   return object;
00754 }
00755 
00756 ////////////////////////////////////////////////////////////////////
00757 //     Function: GeomVertexArrayFormat::fillin
00758 //       Access: Protected
00759 //  Description: This internal function is called by make_from_bam to
00760 //               read in all of the relevant data from the BamFile for
00761 //               the new GeomVertexArrayFormat.
00762 ////////////////////////////////////////////////////////////////////
00763 void GeomVertexArrayFormat::
00764 fillin(DatagramIterator &scan, BamReader *manager) {
00765   TypedWritableReferenceCount::fillin(scan, manager);
00766   nassertv(!_is_registered);
00767 
00768   _stride = scan.get_uint16();
00769   _total_bytes = scan.get_uint16();
00770   _pad_to = scan.get_uint8();
00771 
00772   int num_columns = scan.get_uint16();
00773   _columns.reserve(num_columns);
00774   for (int i = 0; i < num_columns; ++i) {
00775     GeomVertexColumn *column = new GeomVertexColumn;
00776     column->fillin(scan, manager);
00777     _columns.push_back(column);
00778   }
00779   _columns_unsorted = false;
00780 }
00781 
00782 ////////////////////////////////////////////////////////////////////
00783 //     Function: GeomVertexArrayFormat::Registry::Constructor
00784 //       Access: Public
00785 //  Description: 
00786 ////////////////////////////////////////////////////////////////////
00787 GeomVertexArrayFormat::Registry::
00788 Registry() {
00789 }
00790 
00791 ////////////////////////////////////////////////////////////////////
00792 //     Function: GeomVertexArrayFormat::Registry::register_format
00793 //       Access: Public
00794 //  Description: Adds the indicated format to the registry, if there
00795 //               is not an equivalent format already there; in either
00796 //               case, returns the pointer to the equivalent format
00797 //               now in the registry.
00798 //
00799 //               This must be called before a format may be used in a
00800 //               Geom.  After this call, you should discard the
00801 //               original pointer you passed in (which may or may not
00802 //               now be invalid) and let its reference count decrement
00803 //               normally; you should use only the returned value from
00804 //               this point on.
00805 ////////////////////////////////////////////////////////////////////
00806 CPT(GeomVertexArrayFormat) GeomVertexArrayFormat::Registry::
00807 register_format(GeomVertexArrayFormat *format) {
00808   if (format->is_registered()) {
00809     return format;
00810   }
00811 
00812   // Save the incoming pointer in a local PointerTo, so that if it has
00813   // a zero reference count and is not added into the map below, it
00814   // will be automatically deleted when this function returns.
00815   PT(GeomVertexArrayFormat) pt_format = format;
00816   
00817   GeomVertexArrayFormat *new_format;
00818   {
00819     LightMutexHolder holder(_lock);
00820     ArrayFormats::iterator fi = _formats.insert(format).first;
00821     new_format = (*fi);
00822     if (!new_format->is_registered()) {
00823       new_format->do_register();
00824     }
00825   }
00826 
00827   return new_format;
00828 }
00829 
00830 ////////////////////////////////////////////////////////////////////
00831 //     Function: GeomVertexArrayFormat::Registry::unregister_format
00832 //       Access: Public
00833 //  Description: Removes the indicated format from the registry.
00834 //               Normally this should not be done until the format is
00835 //               destructing.
00836 //
00837 //               The lock should be held prior to calling this method.
00838 ////////////////////////////////////////////////////////////////////
00839 void GeomVertexArrayFormat::Registry::
00840 unregister_format(GeomVertexArrayFormat *format) {
00841   nassertv(format->is_registered());
00842   ArrayFormats::iterator fi = _formats.find(format);
00843   nassertv(fi != _formats.end());
00844   _formats.erase(fi);
00845   format->do_unregister();
00846 }
 All Classes Functions Variables Enumerations