Panda3D
|
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 ©) : 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 ©) { 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 ¶ms) { 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 }