Panda3D

geomVertexFormat.cxx

00001 // Filename: geomVertexFormat.cxx
00002 // Created by:  drose (07Mar05)
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 "geomVertexData.h"
00017 #include "geomMunger.h"
00018 #include "lightReMutexHolder.h"
00019 #include "indent.h"
00020 #include "bamReader.h"
00021 #include "bamWriter.h"
00022 
00023 GeomVertexFormat::Registry *GeomVertexFormat::_registry = NULL;
00024 TypeHandle GeomVertexFormat::_type_handle;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: GeomVertexFormat::Constructor
00028 //       Access: Published
00029 //  Description: 
00030 ////////////////////////////////////////////////////////////////////
00031 GeomVertexFormat::
00032 GeomVertexFormat() :
00033   _is_registered(false),
00034   _post_animated_format(NULL)
00035 {
00036 }
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: GeomVertexFormat::Constructor
00040 //       Access: Published
00041 //  Description: 
00042 ////////////////////////////////////////////////////////////////////
00043 GeomVertexFormat::
00044 GeomVertexFormat(const GeomVertexArrayFormat *array_format) :
00045   _is_registered(false),
00046   _post_animated_format(NULL)
00047 {
00048   add_array(array_format);
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: GeomVertexFormat::Copy Constructor
00053 //       Access: Published
00054 //  Description: 
00055 ////////////////////////////////////////////////////////////////////
00056 GeomVertexFormat::
00057 GeomVertexFormat(const GeomVertexFormat &copy) :
00058   _is_registered(false),
00059   _animation(copy._animation),
00060   _arrays(copy._arrays),
00061   _post_animated_format(NULL)
00062 {
00063 }
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: GeomVertexFormat::Copy Assignment Operator
00067 //       Access: Published
00068 //  Description: 
00069 ////////////////////////////////////////////////////////////////////
00070 void GeomVertexFormat::
00071 operator = (const GeomVertexFormat &copy) {
00072   nassertv(!is_registered());
00073 
00074   _animation = copy._animation;
00075   _arrays = copy._arrays;
00076 }
00077 
00078 ////////////////////////////////////////////////////////////////////
00079 //     Function: GeomVertexFormat::Destructor
00080 //       Access: Published, Virtual
00081 //  Description: 
00082 ////////////////////////////////////////////////////////////////////
00083 GeomVertexFormat::
00084 ~GeomVertexFormat() {
00085   // unref() should have unregistered us.
00086   nassertv(!is_registered());
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 //     Function: GeomVertexFormat::unref
00091 //       Access: Published, Virtual
00092 //  Description: This method overrides ReferenceCount::unref() to
00093 //               unregister the object when its reference count goes
00094 //               to zero.
00095 ////////////////////////////////////////////////////////////////////
00096 bool GeomVertexFormat::
00097 unref() const {
00098   Registry *registry = get_registry();
00099   LightReMutexHolder holder(registry->_lock);
00100 
00101   if (ReferenceCount::unref()) {
00102     return true;
00103   }
00104 
00105   if (is_registered()) {
00106     registry->unregister_format((GeomVertexFormat *)this);
00107   }
00108 
00109   return false;
00110 }
00111 
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: GeomVertexFormat::get_post_animated_format
00115 //       Access: Published
00116 //  Description: Returns a suitable vertex format for sending the
00117 //               animated vertices to the graphics backend.  This is
00118 //               the same format as the source format, with the
00119 //               CPU-animation data elements removed.
00120 //
00121 //               This may only be called after the format has been
00122 //               registered.  The return value will have been already
00123 //               registered.
00124 ////////////////////////////////////////////////////////////////////
00125 CPT(GeomVertexFormat) GeomVertexFormat::
00126 get_post_animated_format() const {
00127   nassertr(is_registered(), NULL);
00128 
00129   if (_post_animated_format == (GeomVertexFormat *)NULL) {
00130     PT(GeomVertexFormat) new_format = new GeomVertexFormat(*this);
00131     new_format->remove_column(InternalName::get_transform_blend());
00132     
00133     int num_morphs = get_num_morphs();
00134     for (int mi = 0; mi < num_morphs; mi++) {
00135       CPT(InternalName) delta_name = get_morph_delta(mi);
00136       new_format->remove_column(delta_name);
00137     }
00138 
00139     new_format->_animation.set_none();
00140 
00141     CPT(GeomVertexFormat) registered = 
00142       GeomVertexFormat::register_format(new_format);
00143     ((GeomVertexFormat *)this)->_post_animated_format = registered;
00144     if (_post_animated_format != this) {
00145       // We only keep the reference count if the new pointer is not
00146       // the same as this, to avoid a circular dependency.
00147       _post_animated_format->ref();
00148     }
00149   }
00150 
00151   _post_animated_format->test_ref_count_integrity();
00152 
00153   return _post_animated_format;
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////
00157 //     Function: GeomVertexFormat::get_union_format
00158 //       Access: Published
00159 //  Description: Returns a new GeomVertexFormat that includes all of
00160 //               the columns defined in either this GeomVertexFormat
00161 //               or the other one.  If any column is defined in both
00162 //               formats with different sizes (for instance, texcoord2
00163 //               vs. texcoord3), the new format will include the
00164 //               larger of the two definitions.
00165 //
00166 //               This may only be called after both source formats
00167 //               have been registered.  The return value will also
00168 //               have been already registered.
00169 ////////////////////////////////////////////////////////////////////
00170 CPT(GeomVertexFormat) GeomVertexFormat::
00171 get_union_format(const GeomVertexFormat *other) const {
00172   nassertr(is_registered() && other->is_registered(), NULL);
00173 
00174   PT(GeomVertexFormat) new_format = new GeomVertexFormat;
00175 
00176   // Preserve whichever animation type is not AT_None.  (If both
00177   // animation types are not AT_None, but they are different, this
00178   // whole operation is questionable.)
00179   if (_animation.get_animation_type() != AT_none) {
00180     new_format->set_animation(_animation);
00181   } else {
00182     new_format->set_animation(other->get_animation());
00183   }
00184 
00185   // Keep track of the columns we have already added.
00186   typedef pset< CPT(InternalName) > ColumnNames;
00187   ColumnNames column_names;
00188 
00189   // We go through all the (0)-level arrays first, then all the
00190   // (1)-level arrays, and so on.  We do this to ensure that the new
00191   // format gets written out with all the (0)-level columns appearing
00192   // before all the (1)-level columns, which might lead to a small
00193   // optimization at render time.
00194 
00195   // We also try to keep the structure as similar as possible.  If
00196   // both source formats have columns (A, B) in array 0, and columns
00197   // (C, D, E) in array 1, then the resulting union format will also
00198   // have (A, B) in array 0 and (C, D, E) in array 1.  In general, a
00199   // column will appear in the result in the first array it appears in
00200   // either of the inputs.
00201 
00202   size_t num_arrays = max(_arrays.size(), other->_arrays.size());
00203   for (size_t ai = 0; ai < num_arrays; ++ai) {
00204     PT(GeomVertexArrayFormat) new_array = new GeomVertexArrayFormat;
00205 
00206     // Add the columns from the first format.
00207     if (ai < _arrays.size()) {
00208       GeomVertexArrayFormat *array_format = _arrays[ai];
00209       int num_columns = array_format->get_num_columns();
00210       for (int i = 0; i < num_columns; ++i) {
00211         const GeomVertexColumn *column_a = array_format->get_column(i);
00212         bool inserted = column_names.insert(column_a->get_name()).second;
00213         if (inserted) {
00214           const GeomVertexColumn *column_b = other->get_column(column_a->get_name());
00215           if (column_b != (GeomVertexColumn *)NULL &&
00216               column_b->get_total_bytes() > column_a->get_total_bytes()) {
00217             // Column b is larger.  Keep it.
00218             new_array->add_column(column_b->get_name(), 
00219                                   column_b->get_num_components(),
00220                                   column_b->get_numeric_type(),
00221                                   column_b->get_contents());
00222           } else {
00223             // Column a is larger.  Keep it.
00224             new_array->add_column(column_a->get_name(), 
00225                                   column_a->get_num_components(),
00226                                   column_a->get_numeric_type(),
00227                                   column_a->get_contents());
00228           }
00229         }
00230       }
00231     }
00232 
00233     // Add the columns from the second format.
00234     if (ai < other->_arrays.size()) {
00235       GeomVertexArrayFormat *array_format = other->_arrays[ai];
00236       int num_columns = array_format->get_num_columns();
00237       for (int i = 0; i < num_columns; ++i) {
00238         const GeomVertexColumn *column_a = array_format->get_column(i);
00239         bool inserted = column_names.insert(column_a->get_name()).second;
00240         if (inserted) {
00241           const GeomVertexColumn *column_b = get_column(column_a->get_name());
00242           if (column_b != (GeomVertexColumn *)NULL &&
00243               column_b->get_total_bytes() > column_a->get_total_bytes()) {
00244             // Column b is larger.  Keep it.
00245             new_array->add_column(column_b->get_name(), 
00246                                   column_b->get_num_components(),
00247                                   column_b->get_numeric_type(),
00248                                   column_b->get_contents());
00249           } else {
00250             // Column a is larger.  Keep it.
00251             new_array->add_column(column_a->get_name(), 
00252                                   column_a->get_num_components(),
00253                                   column_a->get_numeric_type(),
00254                                   column_a->get_contents());
00255           }
00256         }
00257       }
00258     }
00259 
00260     if (new_array->get_num_columns() != 0) {
00261       new_format->add_array(new_array);
00262     }
00263   }
00264 
00265   // Finally, register the format for the thing.
00266   return GeomVertexFormat::register_format(new_format);
00267 }
00268 
00269 ////////////////////////////////////////////////////////////////////
00270 //     Function: GeomVertexFormat::modify_array
00271 //       Access: Published
00272 //  Description: Returns a modifiable pointer to the indicated array.
00273 //               This means duplicating it if it is shared or
00274 //               registered.
00275 //
00276 //               This may not be called once the format has been
00277 //               registered.
00278 ////////////////////////////////////////////////////////////////////
00279 GeomVertexArrayFormat *GeomVertexFormat::
00280 modify_array(int array) {
00281   nassertr(!is_registered(), NULL);
00282   nassertr(array >= 0 && array < (int)_arrays.size(), NULL);
00283 
00284   if (_arrays[array]->is_registered() ||
00285       _arrays[array]->get_ref_count() > 1) {
00286     _arrays[array] = new GeomVertexArrayFormat(*_arrays[array]);
00287   }
00288 
00289   return _arrays[array];
00290 }
00291 
00292 ////////////////////////////////////////////////////////////////////
00293 //     Function: GeomVertexFormat::set_array
00294 //       Access: Published
00295 //  Description: Replaces the definition of the indicated array.
00296 //
00297 //               This may not be called once the format has been
00298 //               registered.
00299 ////////////////////////////////////////////////////////////////////
00300 void GeomVertexFormat::
00301 set_array(int array, const GeomVertexArrayFormat *format) {
00302   nassertv(!is_registered());
00303   nassertv(array >= 0 && array < (int)_arrays.size());
00304   _arrays[array] = (GeomVertexArrayFormat *)format;
00305 }
00306 
00307 ////////////////////////////////////////////////////////////////////
00308 //     Function: GeomVertexFormat::remove_array
00309 //       Access: Published
00310 //  Description: Removes the nth array from the format.
00311 //
00312 //               This may not be called once the format has been
00313 //               registered.
00314 ////////////////////////////////////////////////////////////////////
00315 void GeomVertexFormat::
00316 remove_array(int array) {
00317   nassertv(!is_registered());
00318 
00319   nassertv(array >= 0 && array < (int)_arrays.size());
00320   _arrays.erase(_arrays.begin() + array);
00321 }
00322 
00323 ////////////////////////////////////////////////////////////////////
00324 //     Function: GeomVertexFormat::add_array
00325 //       Access: Published
00326 //  Description: Adds the indicated array definition to the list of
00327 //               arrays included within this vertex format definition.
00328 //               The return value is the index number of the new
00329 //               array.
00330 //
00331 //               This may not be called once the format has been
00332 //               registered.
00333 ////////////////////////////////////////////////////////////////////
00334 int GeomVertexFormat::
00335 add_array(const GeomVertexArrayFormat *array_format) {
00336   nassertr(!is_registered(), -1);
00337 
00338   int new_array = (int)_arrays.size();
00339   _arrays.push_back((GeomVertexArrayFormat *)array_format);
00340   return new_array;
00341 }
00342 
00343 ////////////////////////////////////////////////////////////////////
00344 //     Function: GeomVertexFormat::insert_array
00345 //       Access: Published
00346 //  Description: Adds the indicated array definition to the list of
00347 //               arrays at the indicated position.  This works just
00348 //               like add_array(), except that you can specify which
00349 //               array index the new array should have.
00350 //
00351 //               This may not be called once the format has been
00352 //               registered.
00353 ////////////////////////////////////////////////////////////////////
00354 void GeomVertexFormat::
00355 insert_array(int array, const GeomVertexArrayFormat *array_format) {
00356   nassertv(!is_registered());
00357   nassertv(array >= 0 && array <= (int)_arrays.size());
00358 
00359   _arrays.insert(_arrays.begin() + array, (GeomVertexArrayFormat *)array_format);
00360 }
00361 
00362 ////////////////////////////////////////////////////////////////////
00363 //     Function: GeomVertexFormat::clear_arrays
00364 //       Access: Published
00365 //  Description: Removes all of the array definitions from the format
00366 //               and starts over.
00367 //
00368 //               This may not be called once the format has been
00369 //               registered.
00370 ////////////////////////////////////////////////////////////////////
00371 void GeomVertexFormat::
00372 clear_arrays() {
00373   nassertv(!is_registered());
00374 
00375   _arrays.clear();
00376 }
00377 
00378 ////////////////////////////////////////////////////////////////////
00379 //     Function: GeomVertexFormat::get_num_columns
00380 //       Access: Published
00381 //  Description: Returns the total number of different columns in
00382 //               the specification, across all arrays.
00383 ////////////////////////////////////////////////////////////////////
00384 int GeomVertexFormat::
00385 get_num_columns() const {
00386   int num_columns = 0;
00387   Arrays::const_iterator ai;
00388   for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00389     num_columns += (*ai)->get_num_columns();
00390   }
00391   return num_columns;
00392 }
00393 
00394 ////////////////////////////////////////////////////////////////////
00395 //     Function: GeomVertexFormat::get_column
00396 //       Access: Published
00397 //  Description: Returns the ith column of the specification,
00398 //               across all arrays.
00399 ////////////////////////////////////////////////////////////////////
00400 const GeomVertexColumn *GeomVertexFormat::
00401 get_column(int i) const {
00402   Arrays::const_iterator ai;
00403   for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00404     if (i < (*ai)->get_num_columns()) {
00405       return (*ai)->get_column(i);
00406     }
00407     i -= (*ai)->get_num_columns();
00408   }
00409 
00410   return NULL;
00411 }
00412 
00413 ////////////////////////////////////////////////////////////////////
00414 //     Function: GeomVertexFormat::get_array_with
00415 //       Access: Published
00416 //  Description: Returns the index number of the array with the
00417 //               ith column.
00418 //
00419 //               The return value can be passed to get_array_format()
00420 //               to get the format of the array.  It may also be
00421 //               passed to GeomVertexData::get_array_data() or
00422 //               get_data() or set_data() to manipulate the actual
00423 //               array data.
00424 ////////////////////////////////////////////////////////////////////
00425 int GeomVertexFormat::
00426 get_array_with(int i) const {
00427   int array_index = 0;
00428   for (array_index = 0; array_index < (int)_arrays.size(); array_index++) {
00429     if (i < _arrays[array_index]->get_num_columns()) {
00430       return array_index;
00431     }
00432     i -= _arrays[array_index]->get_num_columns();
00433   }
00434 
00435   return -1;
00436 }
00437 
00438 ////////////////////////////////////////////////////////////////////
00439 //     Function: GeomVertexFormat::get_array_with
00440 //       Access: Published
00441 //  Description: Returns the index number of the array with the
00442 //               indicated column, or -1 if no arrays contained
00443 //               that name.
00444 //
00445 //               The return value can be passed to get_array_format()
00446 //               to get the format of the array.  It may also be
00447 //               passed to GeomVertexData::get_array_data() or
00448 //               get_data() or set_data() to manipulate the actual
00449 //               array data.
00450 //
00451 //               This may only be called after the format has been
00452 //               registered.
00453 ////////////////////////////////////////////////////////////////////
00454 int GeomVertexFormat::
00455 get_array_with(const InternalName *name) const {
00456   nassertr(_is_registered, -1);
00457 
00458   DataTypesByName::const_iterator ai;
00459   ai = _columns_by_name.find(name);
00460   if (ai != _columns_by_name.end()) {
00461     return (*ai).second._array_index;
00462   }
00463   return -1;
00464 }
00465 
00466 ////////////////////////////////////////////////////////////////////
00467 //     Function: GeomVertexFormat::get_column
00468 //       Access: Published
00469 //  Description: Returns the specification with the indicated name, or
00470 //               NULL if the name is not used.  Use get_array_with()
00471 //               to determine which array this column is associated
00472 //               with.
00473 ////////////////////////////////////////////////////////////////////
00474 const GeomVertexColumn *GeomVertexFormat::
00475 get_column(const InternalName *name) const {
00476   if (!_is_registered) {
00477     // If the format hasn't yet been registered, we have to search for
00478     // the column the hard way.
00479     Arrays::const_iterator ai;
00480     for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00481       const GeomVertexColumn *column = (*ai)->get_column(name);
00482       if (column != (GeomVertexColumn *)NULL) {
00483         return column;
00484       }
00485     }
00486     return NULL;
00487 
00488   } else {
00489     // If the format has been registered, we can just check the
00490     // toplevel index.
00491 
00492     DataTypesByName::const_iterator ai;
00493     ai = _columns_by_name.find(name);
00494     if (ai != _columns_by_name.end()) {
00495       int array_index = (*ai).second._array_index;
00496       int column_index = (*ai).second._column_index;
00497       
00498       nassertr(array_index >= 0 && array_index < (int)_arrays.size(), NULL);
00499       return _arrays[array_index]->get_column(column_index);
00500     }
00501     return NULL;
00502   }
00503 }
00504 
00505 ////////////////////////////////////////////////////////////////////
00506 //     Function: GeomVertexFormat::remove_column
00507 //       Access: Published
00508 //  Description: Removes the named column from the format, from
00509 //               whichever array it exists in.  If there are other
00510 //               columns remaining in the array, the array is left
00511 //               with a gap where the column used to be; if this
00512 //               was the only column in the array, the array is
00513 //               removed.
00514 //
00515 //               This may not be called once the format has been
00516 //               registered.
00517 ////////////////////////////////////////////////////////////////////
00518 void GeomVertexFormat::
00519 remove_column(const InternalName *name) {
00520   nassertv(!_is_registered);
00521 
00522   // Since the format's not registered, it doesn't yet have an index
00523   // of columns--so we have to search all of the arrays, one at a
00524   // time, until we find it.
00525   for (int array = 0; array < (int)_arrays.size(); ++array) {
00526     GeomVertexArrayFormat *array_format = _arrays[array];
00527 
00528     if (array_format->get_column(name) != (GeomVertexColumn *)NULL) {
00529       // Here's the array with the named column!
00530       if (array_format->is_registered() ||
00531           array_format->get_ref_count() > 1) {
00532         // Get a safe-to-modify copy of the array format.
00533         _arrays[array] = new GeomVertexArrayFormat(*array_format);
00534         array_format = _arrays[array];
00535       }
00536 
00537       array_format->remove_column(name);
00538 
00539       // Are there any columns remaining in the array?
00540       if (array_format->get_num_columns() == 0) {
00541         // Remove the whole array.
00542         remove_array(array);
00543       }
00544       return;
00545     }
00546   }
00547 
00548   // It appears that column wasn't part of the format anyway.  No
00549   // problem; quietly return.
00550 }
00551 
00552 ////////////////////////////////////////////////////////////////////
00553 //     Function: GeomVertexFormat::pack_columns
00554 //       Access: Published
00555 //  Description: Removes wasted space between columns.
00556 ////////////////////////////////////////////////////////////////////
00557 void GeomVertexFormat::
00558 pack_columns() {
00559   nassertv(!_is_registered);
00560   Arrays::iterator ai;
00561   for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00562     if ((*ai)->is_registered()) {
00563       (*ai) = new GeomVertexArrayFormat(*(*ai));
00564     }
00565     (*ai)->pack_columns();
00566   }
00567 }
00568 
00569 
00570 ////////////////////////////////////////////////////////////////////
00571 //     Function: GeomVertexFormat::output
00572 //       Access: Published
00573 //  Description: 
00574 ////////////////////////////////////////////////////////////////////
00575 void GeomVertexFormat::
00576 output(ostream &out) const {
00577   if (_arrays.empty()) {
00578     out << "(empty)";
00579 
00580   } else {
00581     Arrays::const_iterator ai;
00582     ai = _arrays.begin();
00583     out << *(*ai);
00584     ++ai;
00585     while (ai != _arrays.end()) {
00586       out << ", " << *(*ai);
00587       ++ai;
00588     }
00589   }
00590 
00591   if (_animation.get_animation_type() != AT_none) {
00592     out << ", anim " << _animation;
00593   }
00594 }
00595 
00596 ////////////////////////////////////////////////////////////////////
00597 //     Function: GeomVertexFormat::write
00598 //       Access: Published
00599 //  Description: 
00600 ////////////////////////////////////////////////////////////////////
00601 void GeomVertexFormat::
00602 write(ostream &out, int indent_level) const {
00603   for (size_t i = 0; i < _arrays.size(); i++) {
00604     indent(out, indent_level)
00605       << "Array " << i << ":\n";
00606     _arrays[i]->write(out, indent_level + 2);
00607   }
00608 
00609   if (_animation.get_animation_type() != AT_none) {
00610     indent(out, indent_level)
00611       << "anim " << _animation;
00612   }
00613 }
00614 
00615 ////////////////////////////////////////////////////////////////////
00616 //     Function: GeomVertexFormat::write_with_data
00617 //       Access: Published
00618 //  Description: 
00619 ////////////////////////////////////////////////////////////////////
00620 void GeomVertexFormat::
00621 write_with_data(ostream &out, int indent_level, 
00622                 const GeomVertexData *data) const {
00623   indent(out, indent_level)
00624     << data->get_num_rows() << " rows.\n";
00625   for (size_t i = 0; i < _arrays.size(); i++) {
00626     CPT(GeomVertexArrayDataHandle) handle = data->get_array(i)->get_handle();
00627     const unsigned char *array_data = handle->get_read_pointer(true);
00628     indent(out, indent_level)
00629       << "Array " << i << " (" << (void *)array_data << ", "
00630       << *_arrays[i] << "):\n";
00631     _arrays[i]->write_with_data(out, indent_level + 2, data->get_array(i));
00632   }
00633 }
00634 
00635 ////////////////////////////////////////////////////////////////////
00636 //     Function: GeomVertexFormat::get_array_info
00637 //       Access: Public
00638 //  Description: Quickly looks up the indicated column within all
00639 //               of the nested arrays and sets array_index and
00640 //               column appropriately.  Returns true if the data
00641 //               type exists in this format, false if it does not.  If
00642 //               it returns false, array_index is set to -1, and
00643 //               column is set to NULL.
00644 //
00645 //               This may only be called after the format has been
00646 //               registered.
00647 ////////////////////////////////////////////////////////////////////
00648 bool GeomVertexFormat::
00649 get_array_info(const InternalName *name, int &array_index,
00650                const GeomVertexColumn *&column) const {
00651   nassertr(_is_registered, false);
00652 
00653   DataTypesByName::const_iterator ai;
00654   ai = _columns_by_name.find(name);
00655   if (ai != _columns_by_name.end()) {
00656     array_index = (*ai).second._array_index;
00657     column = _arrays[array_index]->get_column((*ai).second._column_index);
00658     return true;
00659   }
00660 
00661   array_index = -1;
00662   column = NULL;
00663 
00664   return false;
00665 }
00666 
00667 ////////////////////////////////////////////////////////////////////
00668 //     Function: GeomVertexFormat::compare_to
00669 //       Access: Public
00670 //  Description: 
00671 ////////////////////////////////////////////////////////////////////
00672 int GeomVertexFormat::
00673 compare_to(const GeomVertexFormat &other) const {
00674   int compare = _animation.compare_to(other._animation);
00675   if (compare != 0) {
00676     return compare;
00677   }
00678 
00679   if (_arrays.size() != other._arrays.size()) {
00680     return (int)_arrays.size() - (int)other._arrays.size();
00681   }
00682 
00683   for (size_t i = 0; i < _arrays.size(); i++) {
00684     int compare = _arrays[i]->compare_to(*other._arrays[i]);
00685     if (compare != 0) {
00686       return compare;
00687     }
00688   }
00689 
00690   return 0;
00691 }
00692 
00693 ////////////////////////////////////////////////////////////////////
00694 //     Function: GeomVertexFormat::make_registry
00695 //       Access: Private
00696 //  Description: Returns the global registry object.
00697 ////////////////////////////////////////////////////////////////////
00698 void GeomVertexFormat::
00699 make_registry() {
00700   if (_registry == (Registry *)NULL) {
00701     _registry = new Registry;
00702     _registry->make_standard_formats();
00703   }
00704 }
00705  
00706 ////////////////////////////////////////////////////////////////////
00707 //     Function: GeomVertexFormat::do_register
00708 //       Access: Private
00709 //  Description: Called internally when the format is registered.
00710 ////////////////////////////////////////////////////////////////////
00711 void GeomVertexFormat::
00712 do_register() {
00713   nassertv(!is_registered());
00714   nassertv(_columns_by_name.empty());
00715 
00716   for (int array = 0; array < (int)_arrays.size(); ++array) {
00717     CPT(GeomVertexArrayFormat) array_format = _arrays[array];
00718     if (!array_format->is_registered()) {
00719       array_format = GeomVertexArrayFormat::register_format(array_format);
00720       _arrays[array] = (GeomVertexArrayFormat *)array_format.p();
00721     }
00722 
00723     // Now add the names to the index.
00724     int num_columns = array_format->get_num_columns();
00725     for (int i = 0; i < num_columns; i++) {
00726       const GeomVertexColumn *column = array_format->get_column(i);
00727       pair<DataTypesByName::iterator, bool> result;
00728       result = _columns_by_name.insert(DataTypesByName::value_type(column->get_name(), DataTypeRecord()));
00729       if (!result.second) {
00730         gobj_cat.warning()
00731           << "Column " << *column->get_name() << " repeated in format.\n";
00732       } else {
00733         DataTypeRecord &record = (*result.first).second;
00734         record._array_index = array;
00735         record._column_index = i;
00736       }
00737     }
00738   }
00739 
00740   // Go back through the index now and identify the points, vectors,
00741   // and morph descriptions, so we can quickly look these up later.
00742   DataTypesByName::iterator ni;
00743   for (ni = _columns_by_name.begin(); 
00744        ni != _columns_by_name.end();
00745        ++ni) {
00746     const DataTypeRecord &record = (*ni).second;
00747     const GeomVertexColumn *column = _arrays[record._array_index]->get_column(record._column_index);
00748 
00749     switch (column->get_contents()) {
00750     case C_point:
00751       // It's a point.
00752       _points.push_back(column->get_name());
00753       break;
00754 
00755     case C_vector:
00756       // It's a vector.
00757       _vectors.push_back(column->get_name());
00758       break;
00759 
00760     case C_texcoord:
00761       // It's a texcoord.
00762       _texcoords.push_back(column->get_name());
00763       break;
00764 
00765     case C_morph_delta:
00766       {
00767         // It's a morph description.
00768         MorphRecord morph;
00769         morph._delta = column->get_name();
00770         
00771         // The delta name must be of the form "basename.morph.slidername".  
00772         int n = morph._delta->find_ancestor("morph");
00773         if (n < 0) {
00774           gobj_cat.warning()
00775             << "vertex format defines " << *column->get_name()
00776             << ", which is stored as a C_morph_delta, but its name does not include \"morph\".\n";
00777         } else {
00778           morph._slider = InternalName::make(morph._delta->get_net_basename(n - 1));
00779           morph._base = morph._delta->get_ancestor(n + 1);
00780           
00781           if (_columns_by_name.find(morph._base) == _columns_by_name.end()) {
00782             gobj_cat.warning()
00783               << "vertex format defines " 
00784               << *column->get_name() << " but does not define "
00785               << *morph._base << "\n";
00786           } else {
00787             _morphs.push_back(morph);
00788           }
00789         }
00790       }
00791       break;
00792 
00793     default:
00794       // Some other type of value we don't care about caching a
00795       // pointer to.
00796       break;
00797     }
00798   }
00799 
00800   _is_registered = true;
00801 
00802   get_array_info(InternalName::get_vertex(), _vertex_array_index,
00803                  _vertex_column);
00804   get_array_info(InternalName::get_normal(), _normal_array_index,
00805                  _normal_column);
00806   get_array_info(InternalName::get_color(), _color_array_index,
00807                  _color_column);
00808 }
00809  
00810 ////////////////////////////////////////////////////////////////////
00811 //     Function: GeomVertexFormat::do_unregister
00812 //       Access: Private
00813 //  Description: Called internally when the format is unregistered.
00814 ////////////////////////////////////////////////////////////////////
00815 void GeomVertexFormat::
00816 do_unregister() {
00817   nassertv(_is_registered);
00818   _is_registered = false;
00819 
00820   _columns_by_name.clear();
00821   _points.clear();
00822   _vectors.clear();
00823   _texcoords.clear();
00824   _morphs.clear();
00825 
00826   if (_post_animated_format != (GeomVertexFormat *)NULL && 
00827       _post_animated_format != this) {
00828     unref_delete(_post_animated_format);
00829   }
00830   _post_animated_format = NULL;
00831 }
00832 
00833 ////////////////////////////////////////////////////////////////////
00834 //     Function: GeomVertexFormat::register_with_read_factory
00835 //       Access: Public, Static
00836 //  Description: Tells the BamReader how to create objects of type
00837 //               GeomVertexFormat.
00838 ////////////////////////////////////////////////////////////////////
00839 void GeomVertexFormat::
00840 register_with_read_factory() {
00841   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00842 }
00843 
00844 ////////////////////////////////////////////////////////////////////
00845 //     Function: GeomVertexFormat::write_datagram
00846 //       Access: Public, Virtual
00847 //  Description: Writes the contents of this object to the datagram
00848 //               for shipping out to a Bam file.
00849 ////////////////////////////////////////////////////////////////////
00850 void GeomVertexFormat::
00851 write_datagram(BamWriter *manager, Datagram &dg) {
00852   TypedWritableReferenceCount::write_datagram(manager, dg);
00853 
00854   _animation.write_datagram(manager, dg);
00855 
00856   dg.add_uint16(_arrays.size());
00857   Arrays::const_iterator ai;
00858   for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00859     manager->write_pointer(dg, *ai);
00860   }
00861 }
00862 
00863 ////////////////////////////////////////////////////////////////////
00864 //     Function: GeomVertexFormat::complete_pointers
00865 //       Access: Public, Virtual
00866 //  Description: Receives an array of pointers, one for each time
00867 //               manager->read_pointer() was called in fillin().
00868 //               Returns the number of pointers processed.
00869 ////////////////////////////////////////////////////////////////////
00870 int GeomVertexFormat::
00871 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00872   int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
00873 
00874   Arrays::iterator ai;
00875   for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00876     (*ai) = DCAST(GeomVertexArrayFormat, p_list[pi++]);
00877   }
00878 
00879   return pi;
00880 }
00881 
00882 ////////////////////////////////////////////////////////////////////
00883 //     Function: GeomVertexFormat::make_from_bam
00884 //       Access: Protected, Static
00885 //  Description: This function is called by the BamReader's factory
00886 //               when a new object of type GeomVertexFormat is
00887 //               encountered in the Bam file.  It should create the
00888 //               GeomVertexFormat and extract its information
00889 //               from the file.
00890 ////////////////////////////////////////////////////////////////////
00891 TypedWritable *GeomVertexFormat::
00892 make_from_bam(const FactoryParams &params) {
00893   GeomVertexFormat *object = new GeomVertexFormat;
00894   DatagramIterator scan;
00895   BamReader *manager;
00896 
00897   parse_params(params, scan, manager);
00898   object->fillin(scan, manager);
00899 
00900   return object;
00901 }
00902 
00903 ////////////////////////////////////////////////////////////////////
00904 //     Function: GeomVertexFormat::fillin
00905 //       Access: Protected
00906 //  Description: This internal function is called by make_from_bam to
00907 //               read in all of the relevant data from the BamFile for
00908 //               the new GeomVertexFormat.
00909 ////////////////////////////////////////////////////////////////////
00910 void GeomVertexFormat::
00911 fillin(DatagramIterator &scan, BamReader *manager) {
00912   TypedWritableReferenceCount::fillin(scan, manager);
00913 
00914   _animation.fillin(scan, manager);
00915 
00916   int num_arrays = scan.get_uint16();
00917   _arrays.reserve(num_arrays);
00918   for (int i = 0; i < num_arrays; i++) {
00919     manager->read_pointer(scan);
00920     _arrays.push_back(NULL);
00921   }
00922 }
00923 
00924 ////////////////////////////////////////////////////////////////////
00925 //     Function: GeomVertexFormat::Registry::Constructor
00926 //       Access: Public
00927 //  Description: 
00928 ////////////////////////////////////////////////////////////////////
00929 GeomVertexFormat::Registry::
00930 Registry() {
00931 }
00932 
00933 ////////////////////////////////////////////////////////////////////
00934 //     Function: GeomVertexFormat::Registry::make_standard_formats
00935 //       Access: Public
00936 //  Description: 
00937 ////////////////////////////////////////////////////////////////////
00938 void GeomVertexFormat::Registry::
00939 make_standard_formats() {
00940   _v3 = register_format(new GeomVertexArrayFormat
00941                         (InternalName::get_vertex(), 3, 
00942                          NT_float32, C_point));
00943 
00944   _v3n3 = register_format(new GeomVertexArrayFormat
00945                           (InternalName::get_vertex(), 3, 
00946                            NT_float32, C_point,
00947                            InternalName::get_normal(), 3, 
00948                            NT_float32, C_vector));
00949 
00950   _v3t2 = register_format(new GeomVertexArrayFormat
00951                           (InternalName::get_vertex(), 3, 
00952                            NT_float32, C_point,
00953                            InternalName::get_texcoord(), 2, 
00954                            NT_float32, C_texcoord));
00955 
00956   _v3n3t2 = register_format(new GeomVertexArrayFormat
00957                             (InternalName::get_vertex(), 3, 
00958                              NT_float32, C_point,
00959                              InternalName::get_normal(), 3,
00960                              NT_float32, C_vector,
00961                              InternalName::get_texcoord(), 2, 
00962                              NT_float32, C_texcoord));
00963 
00964   // Define the DirectX-style packed color formats
00965   _v3cp = register_format(new GeomVertexArrayFormat
00966                           (InternalName::get_vertex(), 3,
00967                            NT_float32, C_point,
00968                            InternalName::get_color(), 1,
00969                            NT_packed_dabc, C_color));
00970 
00971   _v3n3cp = register_format(new GeomVertexArrayFormat
00972                             (InternalName::get_vertex(), 3,
00973                              NT_float32, C_point,
00974                              InternalName::get_normal(), 3,
00975                              NT_float32, C_vector,
00976                              InternalName::get_color(), 1,
00977                              NT_packed_dabc, C_color));
00978 
00979   _v3cpt2 = register_format(new GeomVertexArrayFormat
00980                             (InternalName::get_vertex(), 3,
00981                              NT_float32, C_point,
00982                              InternalName::get_color(), 1,
00983                              NT_packed_dabc, C_color,
00984                              InternalName::get_texcoord(), 2,
00985                              NT_float32, C_texcoord));
00986 
00987   _v3n3cpt2 = register_format(new GeomVertexArrayFormat
00988                               (InternalName::get_vertex(), 3,
00989                                NT_float32, C_point,
00990                                InternalName::get_normal(), 3,
00991                                NT_float32, C_vector,
00992                                InternalName::get_color(), 1,
00993                                NT_packed_dabc, C_color,
00994                                InternalName::get_texcoord(), 2,
00995                                NT_float32, C_texcoord));
00996 
00997   // Define the OpenGL-style per-byte color formats.  This is not the
00998   // same as a packed format, above, because the resulting byte order
00999   // is endian-independent.
01000   _v3c4 = register_format(new GeomVertexArrayFormat
01001                           (InternalName::get_vertex(), 3,
01002                            NT_float32, C_point,
01003                            InternalName::get_color(), 4,
01004                            NT_uint8, C_color));
01005 
01006   _v3n3c4 = register_format(new GeomVertexArrayFormat
01007                             (InternalName::get_vertex(), 3,
01008                              NT_float32, C_point,
01009                              InternalName::get_normal(), 3,
01010                              NT_float32, C_vector,
01011                              InternalName::get_color(), 4,
01012                              NT_uint8, C_color));
01013 
01014   _v3c4t2 = register_format(new GeomVertexArrayFormat
01015                             (InternalName::get_vertex(), 3,
01016                              NT_float32, C_point,
01017                              InternalName::get_color(), 4,
01018                              NT_uint8, C_color,
01019                              InternalName::get_texcoord(), 2,
01020                              NT_float32, C_texcoord));
01021 
01022   _v3n3c4t2 = register_format(new GeomVertexArrayFormat
01023                               (InternalName::get_vertex(), 3,
01024                                NT_float32, C_point,
01025                                InternalName::get_normal(), 3,
01026                                NT_float32, C_vector,
01027                                InternalName::get_color(), 4,
01028                                NT_uint8, C_color,
01029                                InternalName::get_texcoord(), 2,
01030                                NT_float32, C_texcoord));
01031 }
01032 
01033 ////////////////////////////////////////////////////////////////////
01034 //     Function: GeomVertexFormat::Registry::register_format
01035 //       Access: Public
01036 //  Description: Adds the indicated format to the registry, if there
01037 //               is not an equivalent format already there; in either
01038 //               case, returns the pointer to the equivalent format
01039 //               now in the registry.
01040 //
01041 //               This must be called before a format may be used in a
01042 //               Geom.  After this call, you should discard the
01043 //               original pointer you passed in (which may or may not
01044 //               now be invalid) and let its reference count decrement
01045 //               normally; you should use only the returned value from
01046 //               this point on.
01047 ////////////////////////////////////////////////////////////////////
01048 CPT(GeomVertexFormat) GeomVertexFormat::Registry::
01049 register_format(GeomVertexFormat *format) {
01050   if (format->is_registered()) {
01051     return format;
01052   }
01053 
01054   // Save the incoming pointer in a local PointerTo, so that if it has
01055   // a zero reference count and is not added into the map below, it
01056   // will be automatically deleted when this function returns.
01057   PT(GeomVertexFormat) pt_format = format;
01058 
01059   GeomVertexFormat *new_format;
01060   {
01061     LightReMutexHolder holder(_lock);
01062     Formats::iterator fi = _formats.insert(format).first;
01063     new_format = (*fi);
01064     if (!new_format->is_registered()) {
01065       new_format->do_register();
01066     }
01067   }
01068 
01069   return new_format;
01070 }
01071 
01072 ////////////////////////////////////////////////////////////////////
01073 //     Function: GeomVertexFormat::Registry::unregister_format
01074 //       Access: Public
01075 //  Description: Removes the indicated format from the registry.
01076 //               Normally this should not be done until the format is
01077 //               destructing.
01078 //
01079 //               The lock should be held prior to calling this method.
01080 ////////////////////////////////////////////////////////////////////
01081 void GeomVertexFormat::Registry::
01082 unregister_format(GeomVertexFormat *format) {
01083   nassertv(format->is_registered());
01084   Formats::iterator fi = _formats.find(format);
01085   nassertv(fi != _formats.end());
01086   _formats.erase(fi);
01087   format->do_unregister();
01088 }
 All Classes Functions Variables Enumerations