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 // 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 ¶ms) { 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 }