Panda3D
 All Classes Functions Variables Enumerations
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 //     Function: GeomVertexFormat::align_columns_for_animation
00571 //       Access: Published
00572 //  Description: Reprocesses the columns in the format to align the
00573 //               C_point and C_vector columns to 16-byte boundaries to
00574 //               allow for the more efficient SSE2 operations
00575 //               (assuming SSE2 is enabled in the build).
00576 //
00577 //               Also see maybe_align_columns_for_animation().
00578 ////////////////////////////////////////////////////////////////////
00579 void GeomVertexFormat::
00580 align_columns_for_animation() {
00581   nassertv(!_is_registered);
00582   Arrays::iterator ai;
00583   for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00584     if ((*ai)->is_registered()) {
00585       (*ai) = new GeomVertexArrayFormat(*(*ai));
00586     }
00587     (*ai)->align_columns_for_animation();
00588   }
00589 }
00590 
00591 ////////////////////////////////////////////////////////////////////
00592 //     Function: GeomVertexFormat::maybe_align_columns_for_animation
00593 //       Access: Published
00594 //  Description: Calls align_columns_for_animation() if this format's
00595 //               AnimationSpec indicates that it contains animated
00596 //               vertices, and if vertex-animation-align-16 is true.
00597 ////////////////////////////////////////////////////////////////////
00598 void GeomVertexFormat::
00599 maybe_align_columns_for_animation() {
00600   if (_animation.get_animation_type() == AT_panda && vertex_animation_align_16) {
00601     align_columns_for_animation();
00602   }
00603 }
00604 
00605 ////////////////////////////////////////////////////////////////////
00606 //     Function: GeomVertexFormat::output
00607 //       Access: Published
00608 //  Description: 
00609 ////////////////////////////////////////////////////////////////////
00610 void GeomVertexFormat::
00611 output(ostream &out) const {
00612   if (_arrays.empty()) {
00613     out << "(empty)";
00614 
00615   } else {
00616     Arrays::const_iterator ai;
00617     ai = _arrays.begin();
00618     out << *(*ai);
00619     ++ai;
00620     while (ai != _arrays.end()) {
00621       out << ", " << *(*ai);
00622       ++ai;
00623     }
00624   }
00625 
00626   if (_animation.get_animation_type() != AT_none) {
00627     out << ", anim " << _animation;
00628   }
00629 }
00630 
00631 ////////////////////////////////////////////////////////////////////
00632 //     Function: GeomVertexFormat::write
00633 //       Access: Published
00634 //  Description: 
00635 ////////////////////////////////////////////////////////////////////
00636 void GeomVertexFormat::
00637 write(ostream &out, int indent_level) const {
00638   for (size_t i = 0; i < _arrays.size(); i++) {
00639     indent(out, indent_level)
00640       << "Array " << i << ":\n";
00641     _arrays[i]->write(out, indent_level + 2);
00642   }
00643 
00644   if (_animation.get_animation_type() != AT_none) {
00645     indent(out, indent_level)
00646       << "anim " << _animation << "\n";
00647   }
00648 }
00649 
00650 ////////////////////////////////////////////////////////////////////
00651 //     Function: GeomVertexFormat::write_with_data
00652 //       Access: Published
00653 //  Description: 
00654 ////////////////////////////////////////////////////////////////////
00655 void GeomVertexFormat::
00656 write_with_data(ostream &out, int indent_level, 
00657                 const GeomVertexData *data) const {
00658   indent(out, indent_level)
00659     << data->get_num_rows() << " rows.\n";
00660   for (size_t i = 0; i < _arrays.size(); i++) {
00661     CPT(GeomVertexArrayDataHandle) handle = data->get_array(i)->get_handle();
00662     const unsigned char *array_data = handle->get_read_pointer(true);
00663     indent(out, indent_level)
00664       << "Array " << i << " (" << (void *)array_data << ", "
00665       << *_arrays[i] << "):\n";
00666     _arrays[i]->write_with_data(out, indent_level + 2, data->get_array(i));
00667   }
00668 }
00669 
00670 ////////////////////////////////////////////////////////////////////
00671 //     Function: GeomVertexFormat::get_array_info
00672 //       Access: Public
00673 //  Description: Quickly looks up the indicated column within all
00674 //               of the nested arrays and sets array_index and
00675 //               column appropriately.  Returns true if the data
00676 //               type exists in this format, false if it does not.  If
00677 //               it returns false, array_index is set to -1, and
00678 //               column is set to NULL.
00679 //
00680 //               This may only be called after the format has been
00681 //               registered.
00682 ////////////////////////////////////////////////////////////////////
00683 bool GeomVertexFormat::
00684 get_array_info(const InternalName *name, int &array_index,
00685                const GeomVertexColumn *&column) const {
00686   nassertr(_is_registered, false);
00687 
00688   DataTypesByName::const_iterator ai;
00689   ai = _columns_by_name.find(name);
00690   if (ai != _columns_by_name.end()) {
00691     array_index = (*ai).second._array_index;
00692     column = _arrays[array_index]->get_column((*ai).second._column_index);
00693     return true;
00694   }
00695 
00696   array_index = -1;
00697   column = NULL;
00698 
00699   return false;
00700 }
00701 
00702 ////////////////////////////////////////////////////////////////////
00703 //     Function: GeomVertexFormat::compare_to
00704 //       Access: Public
00705 //  Description: 
00706 ////////////////////////////////////////////////////////////////////
00707 int GeomVertexFormat::
00708 compare_to(const GeomVertexFormat &other) const {
00709   int compare = _animation.compare_to(other._animation);
00710   if (compare != 0) {
00711     return compare;
00712   }
00713 
00714   if (_arrays.size() != other._arrays.size()) {
00715     return (int)_arrays.size() - (int)other._arrays.size();
00716   }
00717 
00718   for (size_t i = 0; i < _arrays.size(); i++) {
00719     int compare = _arrays[i]->compare_to(*other._arrays[i]);
00720     if (compare != 0) {
00721       return compare;
00722     }
00723   }
00724 
00725   return 0;
00726 }
00727 
00728 ////////////////////////////////////////////////////////////////////
00729 //     Function: GeomVertexFormat::make_registry
00730 //       Access: Private
00731 //  Description: Returns the global registry object.
00732 ////////////////////////////////////////////////////////////////////
00733 void GeomVertexFormat::
00734 make_registry() {
00735   if (_registry == (Registry *)NULL) {
00736     _registry = new Registry;
00737     _registry->make_standard_formats();
00738   }
00739 }
00740  
00741 ////////////////////////////////////////////////////////////////////
00742 //     Function: GeomVertexFormat::do_register
00743 //       Access: Private
00744 //  Description: Called internally when the format is registered.
00745 ////////////////////////////////////////////////////////////////////
00746 void GeomVertexFormat::
00747 do_register() {
00748   nassertv(!is_registered());
00749   nassertv(_columns_by_name.empty());
00750 
00751   Arrays orig_arrays;
00752   orig_arrays.swap(_arrays);
00753   Arrays::const_iterator ai;
00754   for (ai = orig_arrays.begin(); ai != orig_arrays.end(); ++ai) {
00755     CPT(GeomVertexArrayFormat) array_format = (*ai);
00756     if (!array_format->is_registered()) {
00757       array_format = GeomVertexArrayFormat::register_format(array_format);
00758     }
00759     if (array_format->get_num_columns() == 0) {
00760       // Don't keep an empty array.
00761       gobj_cat.warning()
00762         << "Dropping empty array from GeomVertexFormat.\n";
00763       continue;
00764     }
00765 
00766     int array = (int)_arrays.size();
00767     _arrays.push_back((GeomVertexArrayFormat *)array_format.p());
00768 
00769     // Now add the names to the index.
00770     int num_columns = array_format->get_num_columns();
00771     for (int i = 0; i < num_columns; i++) {
00772       const GeomVertexColumn *column = array_format->get_column(i);
00773       pair<DataTypesByName::iterator, bool> result;
00774       result = _columns_by_name.insert(DataTypesByName::value_type(column->get_name(), DataTypeRecord()));
00775       if (!result.second) {
00776         gobj_cat.warning()
00777           << "Column " << *column->get_name() << " repeated in format.\n";
00778       } else {
00779         DataTypeRecord &record = (*result.first).second;
00780         record._array_index = array;
00781         record._column_index = i;
00782       }
00783     }
00784   }
00785 
00786   // Go back through the index now and identify the points, vectors,
00787   // and morph descriptions, so we can quickly look these up later.
00788   DataTypesByName::iterator ni;
00789   for (ni = _columns_by_name.begin(); 
00790        ni != _columns_by_name.end();
00791        ++ni) {
00792     const DataTypeRecord &record = (*ni).second;
00793     const GeomVertexColumn *column = _arrays[record._array_index]->get_column(record._column_index);
00794 
00795     switch (column->get_contents()) {
00796     case C_point:
00797       // It's a point.
00798       _points.push_back(column->get_name());
00799       break;
00800 
00801     case C_vector:
00802       // It's a vector.
00803       _vectors.push_back(column->get_name());
00804       break;
00805 
00806     case C_texcoord:
00807       // It's a texcoord.
00808       _texcoords.push_back(column->get_name());
00809       break;
00810 
00811     case C_morph_delta:
00812       {
00813         // It's a morph description.
00814         MorphRecord morph;
00815         morph._delta = column->get_name();
00816         
00817         // The delta name must be of the form "basename.morph.slidername".  
00818         int n = morph._delta->find_ancestor("morph");
00819         if (n < 0) {
00820           gobj_cat.warning()
00821             << "vertex format defines " << *column->get_name()
00822             << ", which is stored as a C_morph_delta, but its name does not include \"morph\".\n";
00823         } else {
00824           morph._slider = InternalName::make(morph._delta->get_net_basename(n - 1));
00825           morph._base = morph._delta->get_ancestor(n + 1);
00826           
00827           if (_columns_by_name.find(morph._base) == _columns_by_name.end()) {
00828             gobj_cat.warning()
00829               << "vertex format defines " 
00830               << *column->get_name() << " but does not define "
00831               << *morph._base << "\n";
00832           } else {
00833             _morphs.push_back(morph);
00834           }
00835         }
00836       }
00837       break;
00838 
00839     default:
00840       // Some other type of value we don't care about caching a
00841       // pointer to.
00842       break;
00843     }
00844   }
00845 
00846   _is_registered = true;
00847 
00848   get_array_info(InternalName::get_vertex(), _vertex_array_index,
00849                  _vertex_column);
00850   get_array_info(InternalName::get_normal(), _normal_array_index,
00851                  _normal_column);
00852   get_array_info(InternalName::get_color(), _color_array_index,
00853                  _color_column);
00854 }
00855  
00856 ////////////////////////////////////////////////////////////////////
00857 //     Function: GeomVertexFormat::do_unregister
00858 //       Access: Private
00859 //  Description: Called internally when the format is unregistered.
00860 ////////////////////////////////////////////////////////////////////
00861 void GeomVertexFormat::
00862 do_unregister() {
00863   nassertv(_is_registered);
00864   _is_registered = false;
00865 
00866   _columns_by_name.clear();
00867   _points.clear();
00868   _vectors.clear();
00869   _texcoords.clear();
00870   _morphs.clear();
00871 
00872   if (_post_animated_format != (GeomVertexFormat *)NULL && 
00873       _post_animated_format != this) {
00874     unref_delete(_post_animated_format);
00875   }
00876   _post_animated_format = NULL;
00877 }
00878 
00879 ////////////////////////////////////////////////////////////////////
00880 //     Function: GeomVertexFormat::register_with_read_factory
00881 //       Access: Public, Static
00882 //  Description: Tells the BamReader how to create objects of type
00883 //               GeomVertexFormat.
00884 ////////////////////////////////////////////////////////////////////
00885 void GeomVertexFormat::
00886 register_with_read_factory() {
00887   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00888 }
00889 
00890 ////////////////////////////////////////////////////////////////////
00891 //     Function: GeomVertexFormat::write_datagram
00892 //       Access: Public, Virtual
00893 //  Description: Writes the contents of this object to the datagram
00894 //               for shipping out to a Bam file.
00895 ////////////////////////////////////////////////////////////////////
00896 void GeomVertexFormat::
00897 write_datagram(BamWriter *manager, Datagram &dg) {
00898   TypedWritableReferenceCount::write_datagram(manager, dg);
00899 
00900   _animation.write_datagram(manager, dg);
00901 
00902   dg.add_uint16(_arrays.size());
00903   Arrays::const_iterator ai;
00904   for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00905     manager->write_pointer(dg, *ai);
00906   }
00907 }
00908 
00909 ////////////////////////////////////////////////////////////////////
00910 //     Function: GeomVertexFormat::complete_pointers
00911 //       Access: Public, Virtual
00912 //  Description: Receives an array of pointers, one for each time
00913 //               manager->read_pointer() was called in fillin().
00914 //               Returns the number of pointers processed.
00915 ////////////////////////////////////////////////////////////////////
00916 int GeomVertexFormat::
00917 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00918   int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
00919 
00920   Arrays::iterator ai;
00921   for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
00922     (*ai) = DCAST(GeomVertexArrayFormat, p_list[pi++]);
00923   }
00924 
00925   return pi;
00926 }
00927 
00928 ////////////////////////////////////////////////////////////////////
00929 //     Function: GeomVertexFormat::make_from_bam
00930 //       Access: Protected, Static
00931 //  Description: This function is called by the BamReader's factory
00932 //               when a new object of type GeomVertexFormat is
00933 //               encountered in the Bam file.  It should create the
00934 //               GeomVertexFormat and extract its information
00935 //               from the file.
00936 ////////////////////////////////////////////////////////////////////
00937 TypedWritable *GeomVertexFormat::
00938 make_from_bam(const FactoryParams &params) {
00939   GeomVertexFormat *object = new GeomVertexFormat;
00940   DatagramIterator scan;
00941   BamReader *manager;
00942 
00943   parse_params(params, scan, manager);
00944   object->fillin(scan, manager);
00945 
00946   return object;
00947 }
00948 
00949 ////////////////////////////////////////////////////////////////////
00950 //     Function: GeomVertexFormat::fillin
00951 //       Access: Protected
00952 //  Description: This internal function is called by make_from_bam to
00953 //               read in all of the relevant data from the BamFile for
00954 //               the new GeomVertexFormat.
00955 ////////////////////////////////////////////////////////////////////
00956 void GeomVertexFormat::
00957 fillin(DatagramIterator &scan, BamReader *manager) {
00958   TypedWritableReferenceCount::fillin(scan, manager);
00959 
00960   _animation.fillin(scan, manager);
00961 
00962   int num_arrays = scan.get_uint16();
00963   _arrays.reserve(num_arrays);
00964   for (int i = 0; i < num_arrays; i++) {
00965     manager->read_pointer(scan);
00966     _arrays.push_back(NULL);
00967   }
00968 }
00969 
00970 ////////////////////////////////////////////////////////////////////
00971 //     Function: GeomVertexFormat::Registry::Constructor
00972 //       Access: Public
00973 //  Description: 
00974 ////////////////////////////////////////////////////////////////////
00975 GeomVertexFormat::Registry::
00976 Registry() {
00977 }
00978 
00979 ////////////////////////////////////////////////////////////////////
00980 //     Function: GeomVertexFormat::Registry::make_standard_formats
00981 //       Access: Public
00982 //  Description: 
00983 ////////////////////////////////////////////////////////////////////
00984 void GeomVertexFormat::Registry::
00985 make_standard_formats() {
00986   _v3 = register_format(new GeomVertexArrayFormat
00987                         (InternalName::get_vertex(), 3, 
00988                          NT_stdfloat, C_point));
00989 
00990   _v3n3 = register_format(new GeomVertexArrayFormat
00991                           (InternalName::get_vertex(), 3, 
00992                            NT_stdfloat, C_point,
00993                            InternalName::get_normal(), 3, 
00994                            NT_stdfloat, C_vector));
00995 
00996   _v3t2 = register_format(new GeomVertexArrayFormat
00997                           (InternalName::get_vertex(), 3, 
00998                            NT_stdfloat, C_point,
00999                            InternalName::get_texcoord(), 2, 
01000                            NT_stdfloat, C_texcoord));
01001 
01002   _v3n3t2 = register_format(new GeomVertexArrayFormat
01003                             (InternalName::get_vertex(), 3, 
01004                              NT_stdfloat, C_point,
01005                              InternalName::get_normal(), 3,
01006                              NT_stdfloat, C_vector,
01007                              InternalName::get_texcoord(), 2, 
01008                              NT_stdfloat, C_texcoord));
01009 
01010   // Define the DirectX-style packed color formats
01011   _v3cp = register_format(new GeomVertexArrayFormat
01012                           (InternalName::get_vertex(), 3,
01013                            NT_stdfloat, C_point,
01014                            InternalName::get_color(), 1,
01015                            NT_packed_dabc, C_color));
01016 
01017   _v3n3cp = register_format(new GeomVertexArrayFormat
01018                             (InternalName::get_vertex(), 3,
01019                              NT_stdfloat, C_point,
01020                              InternalName::get_normal(), 3,
01021                              NT_stdfloat, C_vector,
01022                              InternalName::get_color(), 1,
01023                              NT_packed_dabc, C_color));
01024 
01025   _v3cpt2 = register_format(new GeomVertexArrayFormat
01026                             (InternalName::get_vertex(), 3,
01027                              NT_stdfloat, C_point,
01028                              InternalName::get_color(), 1,
01029                              NT_packed_dabc, C_color,
01030                              InternalName::get_texcoord(), 2,
01031                              NT_stdfloat, C_texcoord));
01032 
01033   _v3n3cpt2 = register_format(new GeomVertexArrayFormat
01034                               (InternalName::get_vertex(), 3,
01035                                NT_stdfloat, C_point,
01036                                InternalName::get_normal(), 3,
01037                                NT_stdfloat, C_vector,
01038                                InternalName::get_color(), 1,
01039                                NT_packed_dabc, C_color,
01040                                InternalName::get_texcoord(), 2,
01041                                NT_stdfloat, C_texcoord));
01042 
01043   // Define the OpenGL-style per-byte color formats.  This is not the
01044   // same as a packed format, above, because the resulting byte order
01045   // is endian-independent.
01046   _v3c4 = register_format(new GeomVertexArrayFormat
01047                           (InternalName::get_vertex(), 3,
01048                            NT_stdfloat, C_point,
01049                            InternalName::get_color(), 4,
01050                            NT_uint8, C_color));
01051 
01052   _v3n3c4 = register_format(new GeomVertexArrayFormat
01053                             (InternalName::get_vertex(), 3,
01054                              NT_stdfloat, C_point,
01055                              InternalName::get_normal(), 3,
01056                              NT_stdfloat, C_vector,
01057                              InternalName::get_color(), 4,
01058                              NT_uint8, C_color));
01059 
01060   _v3c4t2 = register_format(new GeomVertexArrayFormat
01061                             (InternalName::get_vertex(), 3,
01062                              NT_stdfloat, C_point,
01063                              InternalName::get_color(), 4,
01064                              NT_uint8, C_color,
01065                              InternalName::get_texcoord(), 2,
01066                              NT_stdfloat, C_texcoord));
01067 
01068   _v3n3c4t2 = register_format(new GeomVertexArrayFormat
01069                               (InternalName::get_vertex(), 3,
01070                                NT_stdfloat, C_point,
01071                                InternalName::get_normal(), 3,
01072                                NT_stdfloat, C_vector,
01073                                InternalName::get_color(), 4,
01074                                NT_uint8, C_color,
01075                                InternalName::get_texcoord(), 2,
01076                                NT_stdfloat, C_texcoord));
01077 }
01078 
01079 ////////////////////////////////////////////////////////////////////
01080 //     Function: GeomVertexFormat::Registry::register_format
01081 //       Access: Public
01082 //  Description: Adds the indicated format to the registry, if there
01083 //               is not an equivalent format already there; in either
01084 //               case, returns the pointer to the equivalent format
01085 //               now in the registry.
01086 //
01087 //               This must be called before a format may be used in a
01088 //               Geom.  After this call, you should discard the
01089 //               original pointer you passed in (which may or may not
01090 //               now be invalid) and let its reference count decrement
01091 //               normally; you should use only the returned value from
01092 //               this point on.
01093 ////////////////////////////////////////////////////////////////////
01094 CPT(GeomVertexFormat) GeomVertexFormat::Registry::
01095 register_format(GeomVertexFormat *format) {
01096   if (format->is_registered()) {
01097     return format;
01098   }
01099 
01100   // Save the incoming pointer in a local PointerTo, so that if it has
01101   // a zero reference count and is not added into the map below, it
01102   // will be automatically deleted when this function returns.
01103   PT(GeomVertexFormat) pt_format = format;
01104 
01105   GeomVertexFormat *new_format;
01106   {
01107     LightReMutexHolder holder(_lock);
01108     Formats::iterator fi = _formats.insert(format).first;
01109     new_format = (*fi);
01110     if (!new_format->is_registered()) {
01111       new_format->do_register();
01112       if (new_format->get_num_arrays() == 0) {
01113         gobj_cat.warning()
01114           << "Empty GeomVertexFormat registered.\n";
01115       }
01116     }
01117   }
01118 
01119   return new_format;
01120 }
01121 
01122 ////////////////////////////////////////////////////////////////////
01123 //     Function: GeomVertexFormat::Registry::unregister_format
01124 //       Access: Public
01125 //  Description: Removes the indicated format from the registry.
01126 //               Normally this should not be done until the format is
01127 //               destructing.
01128 //
01129 //               The lock should be held prior to calling this method.
01130 ////////////////////////////////////////////////////////////////////
01131 void GeomVertexFormat::Registry::
01132 unregister_format(GeomVertexFormat *format) {
01133   nassertv(format->is_registered());
01134   Formats::iterator fi = _formats.find(format);
01135   nassertv(fi != _formats.end());
01136   _formats.erase(fi);
01137   format->do_unregister();
01138 }
 All Classes Functions Variables Enumerations