Panda3D
|
00001 // Filename: geomVertexArrayFormat.cxx 00002 // Created by: drose (06Mar05) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "geomVertexFormat.h" 00016 #include "geomVertexColumn.h" 00017 #include "geomVertexData.h" 00018 #include "geomVertexReader.h" 00019 #include "indent.h" 00020 #include "bamReader.h" 00021 #include "bamWriter.h" 00022 #include "indirectLess.h" 00023 #include "lightMutexHolder.h" 00024 00025 GeomVertexArrayFormat::Registry *GeomVertexArrayFormat::_registry = NULL; 00026 TypeHandle GeomVertexArrayFormat::_type_handle; 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: GeomVertexArrayFormat::Constructor 00030 // Access: Published 00031 // Description: 00032 //////////////////////////////////////////////////////////////////// 00033 GeomVertexArrayFormat:: 00034 GeomVertexArrayFormat() : 00035 _is_registered(false), 00036 _stride(0), 00037 _total_bytes(0), 00038 _pad_to(1), 00039 _columns_unsorted(false) 00040 { 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: GeomVertexArrayFormat::Constructor 00045 // Access: Published 00046 // Description: 00047 //////////////////////////////////////////////////////////////////// 00048 GeomVertexArrayFormat:: 00049 GeomVertexArrayFormat(InternalName *name0, int num_components0, 00050 GeomVertexArrayFormat::NumericType numeric_type0, 00051 GeomVertexArrayFormat::Contents contents0) : 00052 _is_registered(false), 00053 _stride(0), 00054 _total_bytes(0), 00055 _pad_to(1), 00056 _columns_unsorted(false) 00057 { 00058 add_column(name0, num_components0, numeric_type0, contents0); 00059 } 00060 00061 //////////////////////////////////////////////////////////////////// 00062 // Function: GeomVertexArrayFormat::Constructor 00063 // Access: Published 00064 // Description: 00065 //////////////////////////////////////////////////////////////////// 00066 GeomVertexArrayFormat:: 00067 GeomVertexArrayFormat(InternalName *name0, int num_components0, 00068 GeomVertexArrayFormat::NumericType numeric_type0, 00069 GeomVertexArrayFormat::Contents contents0, 00070 InternalName *name1, int num_components1, 00071 GeomVertexArrayFormat::NumericType numeric_type1, 00072 GeomVertexArrayFormat::Contents contents1) : 00073 _is_registered(false), 00074 _stride(0), 00075 _total_bytes(0), 00076 _pad_to(1), 00077 _columns_unsorted(false) 00078 { 00079 add_column(name0, num_components0, numeric_type0, contents0); 00080 add_column(name1, num_components1, numeric_type1, contents1); 00081 } 00082 00083 //////////////////////////////////////////////////////////////////// 00084 // Function: GeomVertexArrayFormat::Constructor 00085 // Access: Published 00086 // Description: 00087 //////////////////////////////////////////////////////////////////// 00088 GeomVertexArrayFormat:: 00089 GeomVertexArrayFormat(InternalName *name0, int num_components0, 00090 GeomVertexArrayFormat::NumericType numeric_type0, 00091 GeomVertexArrayFormat::Contents contents0, 00092 InternalName *name1, int num_components1, 00093 GeomVertexArrayFormat::NumericType numeric_type1, 00094 GeomVertexArrayFormat::Contents contents1, 00095 InternalName *name2, int num_components2, 00096 GeomVertexArrayFormat::NumericType numeric_type2, 00097 GeomVertexArrayFormat::Contents contents2) : 00098 _is_registered(false), 00099 _stride(0), 00100 _total_bytes(0), 00101 _pad_to(1), 00102 _columns_unsorted(false) 00103 { 00104 add_column(name0, num_components0, numeric_type0, contents0); 00105 add_column(name1, num_components1, numeric_type1, contents1); 00106 add_column(name2, num_components2, numeric_type2, contents2); 00107 } 00108 00109 //////////////////////////////////////////////////////////////////// 00110 // Function: GeomVertexArrayFormat::Constructor 00111 // Access: Published 00112 // Description: 00113 //////////////////////////////////////////////////////////////////// 00114 GeomVertexArrayFormat:: 00115 GeomVertexArrayFormat(InternalName *name0, int num_components0, 00116 GeomVertexArrayFormat::NumericType numeric_type0, 00117 GeomVertexArrayFormat::Contents contents0, 00118 InternalName *name1, int num_components1, 00119 GeomVertexArrayFormat::NumericType numeric_type1, 00120 GeomVertexArrayFormat::Contents contents1, 00121 InternalName *name2, int num_components2, 00122 GeomVertexArrayFormat::NumericType numeric_type2, 00123 GeomVertexArrayFormat::Contents contents2, 00124 InternalName *name3, int num_components3, 00125 GeomVertexArrayFormat::NumericType numeric_type3, 00126 GeomVertexArrayFormat::Contents contents3) : 00127 _is_registered(false), 00128 _stride(0), 00129 _total_bytes(0), 00130 _pad_to(1), 00131 _columns_unsorted(false) 00132 { 00133 add_column(name0, num_components0, numeric_type0, contents0); 00134 add_column(name1, num_components1, numeric_type1, contents1); 00135 add_column(name2, num_components2, numeric_type2, contents2); 00136 add_column(name3, num_components3, numeric_type3, contents3); 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: GeomVertexArrayFormat::Copy Constructor 00141 // Access: Published 00142 // Description: 00143 //////////////////////////////////////////////////////////////////// 00144 GeomVertexArrayFormat:: 00145 GeomVertexArrayFormat(const GeomVertexArrayFormat ©) : 00146 _is_registered(false), 00147 _stride(copy._stride), 00148 _total_bytes(copy._total_bytes), 00149 _pad_to(copy._pad_to), 00150 _columns_unsorted(copy._columns_unsorted) 00151 { 00152 Columns::const_iterator dti; 00153 for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) { 00154 add_column(*(*dti)); 00155 } 00156 } 00157 00158 //////////////////////////////////////////////////////////////////// 00159 // Function: GeomVertexArrayFormat::Copy Assignment Operator 00160 // Access: Published 00161 // Description: 00162 //////////////////////////////////////////////////////////////////// 00163 void GeomVertexArrayFormat:: 00164 operator = (const GeomVertexArrayFormat ©) { 00165 nassertv(!_is_registered); 00166 _stride = copy._stride; 00167 _total_bytes = copy._total_bytes; 00168 _pad_to = copy._pad_to; 00169 00170 _columns.clear(); 00171 _columns_by_name.clear(); 00172 _columns_unsorted = false; 00173 Columns::const_iterator dti; 00174 for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) { 00175 add_column(*(*dti)); 00176 } 00177 } 00178 00179 //////////////////////////////////////////////////////////////////// 00180 // Function: GeomVertexArrayFormat::Destructor 00181 // Access: Published, Virtual 00182 // Description: 00183 //////////////////////////////////////////////////////////////////// 00184 GeomVertexArrayFormat:: 00185 ~GeomVertexArrayFormat() { 00186 // unref() should have unregistered us. 00187 nassertv(!is_registered()); 00188 00189 Columns::iterator ci; 00190 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00191 delete (*ci); 00192 } 00193 } 00194 00195 //////////////////////////////////////////////////////////////////// 00196 // Function: GeomVertexArrayFormat::unref 00197 // Access: Published, Virtual 00198 // Description: This method overrides ReferenceCount::unref() to 00199 // unregister the object when its reference count goes 00200 // to zero. 00201 //////////////////////////////////////////////////////////////////// 00202 bool GeomVertexArrayFormat:: 00203 unref() const { 00204 Registry *registry = get_registry(); 00205 LightMutexHolder holder(registry->_lock); 00206 00207 if (ReferenceCount::unref()) { 00208 return true; 00209 } 00210 00211 if (is_registered()) { 00212 registry->unregister_format((GeomVertexArrayFormat *)this); 00213 } 00214 00215 return false; 00216 } 00217 00218 //////////////////////////////////////////////////////////////////// 00219 // Function: GeomVertexArrayFormat::add_column 00220 // Access: Published 00221 // Description: Adds a new column to the specification. This is a 00222 // table of per-vertex floating-point numbers such as 00223 // "vertex" or "normal"; you must specify where in each 00224 // record the table starts, and how many components 00225 // (dimensions) exist per vertex. 00226 // 00227 // The return value is the index number of the new data 00228 // type. 00229 //////////////////////////////////////////////////////////////////// 00230 int GeomVertexArrayFormat:: 00231 add_column(InternalName *name, int num_components, 00232 GeomVertexArrayFormat::NumericType numeric_type, 00233 GeomVertexArrayFormat::Contents contents, int start, 00234 int column_alignment) { 00235 if (start < 0) { 00236 start = _total_bytes; 00237 } 00238 00239 return add_column(GeomVertexColumn(name, num_components, numeric_type, contents, 00240 start, column_alignment)); 00241 } 00242 00243 //////////////////////////////////////////////////////////////////// 00244 // Function: GeomVertexArrayFormat::add_column 00245 // Access: Published 00246 // Description: Adds a new column to the specification. This is a 00247 // table of per-vertex floating-point numbers such as 00248 // "vertex" or "normal"; you must specify where in each 00249 // record the table starts, and how many components 00250 // (dimensions) exist per vertex. 00251 // 00252 // Adding a column with the same name as a previous 00253 // type, or that overlaps with one or more previous 00254 // types, quietly removes the previous type(s). 00255 // 00256 // The return value is the index number of the new data 00257 // type. 00258 //////////////////////////////////////////////////////////////////// 00259 int GeomVertexArrayFormat:: 00260 add_column(const GeomVertexColumn &column) { 00261 nassertr(!_is_registered, -1); 00262 00263 // Make sure there isn't already a column with this name. 00264 remove_column(column.get_name()); 00265 00266 // Also make sure there aren't any columns that overlap with this 00267 // one. 00268 const GeomVertexColumn *orig_column = get_column(column.get_start(), column.get_total_bytes()); 00269 while (orig_column != (const GeomVertexColumn *)NULL) { 00270 remove_column(orig_column->get_name()); 00271 orig_column = get_column(column.get_start(), column.get_total_bytes()); 00272 } 00273 00274 _total_bytes = max(_total_bytes, column.get_start() + column.get_total_bytes()); 00275 _pad_to = max(_pad_to, column.get_column_alignment()); 00276 _stride = max(_stride, _total_bytes); 00277 if (_pad_to > 1) { 00278 _stride = ((_stride + _pad_to - 1) / _pad_to) * _pad_to; 00279 } 00280 00281 GeomVertexColumn *new_column = new GeomVertexColumn(column); 00282 00283 if (!_columns.empty() && *new_column < *_columns.back()) { 00284 _columns_unsorted = true; 00285 } 00286 00287 int new_index = (int)_columns.size(); 00288 _columns.push_back(new_column); 00289 _columns_by_name.insert(ColumnsByName::value_type(new_column->get_name(), new_column)); 00290 00291 return new_index; 00292 } 00293 00294 //////////////////////////////////////////////////////////////////// 00295 // Function: GeomVertexArrayFormat::remove_column 00296 // Access: Published 00297 // Description: Removes the column with the indicated name, if 00298 // any. This leaves a gap in the byte structure. 00299 //////////////////////////////////////////////////////////////////// 00300 void GeomVertexArrayFormat:: 00301 remove_column(const InternalName *name) { 00302 nassertv(!_is_registered); 00303 ColumnsByName::iterator ni; 00304 ni = _columns_by_name.find(name); 00305 if (ni != _columns_by_name.end()) { 00306 GeomVertexColumn *column = (*ni).second; 00307 _columns_by_name.erase(ni); 00308 00309 Columns::iterator ci; 00310 ci = find(_columns.begin(), _columns.end(), column); 00311 nassertv(ci != _columns.end()); 00312 _columns.erase(ci); 00313 00314 delete column; 00315 00316 // Maybe we just removed the tail column. If that's so, we 00317 // should recompute _total_bytes to reflect the new tail. 00318 if (_columns.empty()) { 00319 _total_bytes = 0; 00320 } else { 00321 consider_sort_columns(); 00322 GeomVertexColumn *last = _columns.back(); 00323 _total_bytes = last->get_start() + last->get_total_bytes(); 00324 } 00325 } 00326 } 00327 00328 //////////////////////////////////////////////////////////////////// 00329 // Function: GeomVertexArrayFormat::clear_columns 00330 // Access: Published 00331 // Description: Removes all columns previously added, sets the 00332 // stride to zero, and prepares to start over. 00333 //////////////////////////////////////////////////////////////////// 00334 void GeomVertexArrayFormat:: 00335 clear_columns() { 00336 nassertv(!_is_registered); 00337 00338 _columns.clear(); 00339 _columns_by_name.clear(); 00340 _columns_unsorted = false; 00341 _stride = 0; 00342 _total_bytes = 0; 00343 _pad_to = 1; 00344 } 00345 00346 //////////////////////////////////////////////////////////////////// 00347 // Function: GeomVertexArrayFormat::pack_columns 00348 // Access: Published 00349 // Description: Removes wasted space between columns. 00350 //////////////////////////////////////////////////////////////////// 00351 void GeomVertexArrayFormat:: 00352 pack_columns() { 00353 nassertv(!_is_registered); 00354 00355 Columns orig_columns; 00356 orig_columns.swap(_columns); 00357 clear_columns(); 00358 00359 Columns::const_iterator ci; 00360 for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) { 00361 GeomVertexColumn *column = (*ci); 00362 add_column(column->get_name(), column->get_num_components(), 00363 column->get_numeric_type(), column->get_contents()); 00364 } 00365 } 00366 00367 //////////////////////////////////////////////////////////////////// 00368 // Function: GeomVertexArrayFormat::align_columns_for_animation 00369 // Access: Published 00370 // Description: Reprocesses the columns in the format to align the 00371 // C_point and C_vector columns to 16-byte boundaries to 00372 // allow for the more efficient SSE2 operations 00373 // (assuming SSE2 is enabled in the build). 00374 // 00375 // The caller is responsible for testing 00376 // vertex_animation_align_16 to decide whether to call 00377 // this method. 00378 //////////////////////////////////////////////////////////////////// 00379 void GeomVertexArrayFormat:: 00380 align_columns_for_animation() { 00381 nassertv(!_is_registered); 00382 00383 Columns orig_columns; 00384 orig_columns.swap(_columns); 00385 clear_columns(); 00386 00387 Columns::const_iterator ci; 00388 for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) { 00389 GeomVertexColumn *column = (*ci); 00390 if ((column->get_contents() == C_point || column->get_contents() == C_vector) && 00391 (column->get_numeric_type() == NT_float32 || column->get_numeric_type() == NT_float64) && 00392 column->get_num_components() >= 3) { 00393 add_column(column->get_name(), 4, column->get_numeric_type(), column->get_contents(), -1, 16); 00394 } else { 00395 add_column(column->get_name(), column->get_num_components(), 00396 column->get_numeric_type(), column->get_contents()); 00397 } 00398 } 00399 } 00400 00401 00402 //////////////////////////////////////////////////////////////////// 00403 // Function: GeomVertexArrayFormat::get_column 00404 // Access: Published 00405 // Description: Returns the specification with the indicated name, or 00406 // NULL if the name is not used. 00407 //////////////////////////////////////////////////////////////////// 00408 const GeomVertexColumn *GeomVertexArrayFormat:: 00409 get_column(const InternalName *name) const { 00410 ColumnsByName::const_iterator ni; 00411 ni = _columns_by_name.find(name); 00412 if (ni != _columns_by_name.end()) { 00413 return (*ni).second; 00414 } 00415 return NULL; 00416 } 00417 00418 //////////////////////////////////////////////////////////////////// 00419 // Function: GeomVertexArrayFormat::get_column 00420 // Access: Published 00421 // Description: Returns the first specification that overlaps with 00422 // any of the indicated bytes in the range, or NULL if 00423 // none do. 00424 //////////////////////////////////////////////////////////////////// 00425 const GeomVertexColumn *GeomVertexArrayFormat:: 00426 get_column(int start_byte, int num_bytes) const { 00427 consider_sort_columns(); 00428 Columns::const_iterator ci; 00429 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00430 const GeomVertexColumn *column = (*ci); 00431 if (column->overlaps_with(start_byte, num_bytes)) { 00432 return column; 00433 } 00434 } 00435 00436 return NULL; 00437 } 00438 00439 //////////////////////////////////////////////////////////////////// 00440 // Function: GeomVertexArrayFormat::is_data_subset_of 00441 // Access: Published 00442 // Description: Returns true if all of the fields in this array 00443 // format are also present and equivalent in the other 00444 // array format, and in the same byte positions, and the 00445 // stride is the same. That is, true if this format can 00446 // share the same data pointer as the other format (with 00447 // possibly some unused gaps). 00448 //////////////////////////////////////////////////////////////////// 00449 bool GeomVertexArrayFormat:: 00450 is_data_subset_of(const GeomVertexArrayFormat &other) const { 00451 if (_columns.size() > other._columns.size() || 00452 get_stride() != other.get_stride()) { 00453 return false; 00454 } 00455 00456 consider_sort_columns(); 00457 other.consider_sort_columns(); 00458 size_t i = 0; 00459 size_t j = 0; 00460 while (i < _columns.size() && j < other._columns.size()) { 00461 if (*_columns[i] == *other._columns[j]) { 00462 ++i; 00463 } 00464 ++j; 00465 } 00466 00467 // If we reached the end of our list, all fields matched. 00468 return (i == _columns.size()); 00469 } 00470 00471 //////////////////////////////////////////////////////////////////// 00472 // Function: GeomVertexArrayFormat::count_unused_space 00473 // Access: Published 00474 // Description: Returns the number of bytes per row that are not 00475 // assigned to any column. 00476 //////////////////////////////////////////////////////////////////// 00477 int GeomVertexArrayFormat:: 00478 count_unused_space() const { 00479 consider_sort_columns(); 00480 00481 int unused_space = 0; 00482 int last_pos = 0; 00483 00484 Columns::const_iterator ci; 00485 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00486 const GeomVertexColumn *column = (*ci); 00487 if (column->get_start() > last_pos) { 00488 unused_space += (column->get_start() - last_pos); 00489 } 00490 last_pos = column->get_start() + column->get_total_bytes(); 00491 } 00492 00493 if (_stride > last_pos) { 00494 unused_space += (_stride - last_pos); 00495 } 00496 00497 return unused_space; 00498 } 00499 00500 //////////////////////////////////////////////////////////////////// 00501 // Function: GeomVertexArrayFormat::output 00502 // Access: Published 00503 // Description: 00504 //////////////////////////////////////////////////////////////////// 00505 void GeomVertexArrayFormat:: 00506 output(ostream &out) const { 00507 Columns::const_iterator ci; 00508 int last_pos = 0; 00509 out << "["; 00510 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00511 const GeomVertexColumn *column = (*ci); 00512 if (column->get_start() > last_pos) { 00513 out << " (..." << (column->get_start() - last_pos) << "...)"; 00514 } 00515 out << " " << *column; 00516 last_pos = column->get_start() + column->get_total_bytes(); 00517 } 00518 00519 if (_stride > last_pos) { 00520 out << " ..." << (_stride - last_pos) << "..."; 00521 } 00522 00523 out << " ]"; 00524 } 00525 00526 //////////////////////////////////////////////////////////////////// 00527 // Function: GeomVertexArrayFormat::write 00528 // Access: Published 00529 // Description: 00530 //////////////////////////////////////////////////////////////////// 00531 void GeomVertexArrayFormat:: 00532 write(ostream &out, int indent_level) const { 00533 indent(out, indent_level) 00534 << "Array format (stride = " << get_stride() << "):\n"; 00535 consider_sort_columns(); 00536 Columns::const_iterator ci; 00537 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00538 const GeomVertexColumn *column = (*ci); 00539 indent(out, indent_level + 2) 00540 << *column 00541 << " " << column->get_numeric_type() 00542 << " " << column->get_contents() 00543 << " start at " << column->get_start() << "\n"; 00544 } 00545 } 00546 00547 //////////////////////////////////////////////////////////////////// 00548 // Function: GeomVertexArrayFormat::write_with_data 00549 // Access: Published 00550 // Description: 00551 //////////////////////////////////////////////////////////////////// 00552 void GeomVertexArrayFormat:: 00553 write_with_data(ostream &out, int indent_level, 00554 const GeomVertexArrayData *array_data) const { 00555 consider_sort_columns(); 00556 int num_rows = array_data->get_num_rows(); 00557 00558 GeomVertexReader reader(array_data); 00559 00560 for (int i = 0; i < num_rows; i++) { 00561 indent(out, indent_level) 00562 << "row " << i << ":\n"; 00563 reader.set_row_unsafe(i); 00564 Columns::const_iterator ci; 00565 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00566 const GeomVertexColumn *column = (*ci); 00567 int num_values = min(column->get_num_values(), 4); 00568 reader.set_column(0, column); 00569 const LVecBase4f &d = reader.get_data4f(); 00570 00571 indent(out, indent_level + 2) 00572 << *column->get_name(); 00573 for (int v = 0; v < num_values; v++) { 00574 out << " " << d[v]; 00575 } 00576 out << "\n"; 00577 } 00578 } 00579 } 00580 00581 //////////////////////////////////////////////////////////////////// 00582 // Function: GeomVertexArrayFormat::compare_to 00583 // Access: Public 00584 // Description: 00585 //////////////////////////////////////////////////////////////////// 00586 int GeomVertexArrayFormat:: 00587 compare_to(const GeomVertexArrayFormat &other) const { 00588 if (_stride != other._stride) { 00589 return _stride - other._stride; 00590 } 00591 if (_total_bytes != other._total_bytes) { 00592 return _total_bytes - other._total_bytes; 00593 } 00594 if (_pad_to != other._pad_to) { 00595 return _pad_to - other._pad_to; 00596 } 00597 if (_columns.size() != other._columns.size()) { 00598 return (int)_columns.size() - (int)other._columns.size(); 00599 } 00600 consider_sort_columns(); 00601 other.consider_sort_columns(); 00602 for (size_t i = 0; i < _columns.size(); i++) { 00603 int compare = _columns[i]->compare_to(*other._columns[i]); 00604 if (compare != 0) { 00605 return compare; 00606 } 00607 } 00608 00609 return 0; 00610 } 00611 00612 //////////////////////////////////////////////////////////////////// 00613 // Function: GeomVertexArrayFormat::sort_columns 00614 // Access: Private 00615 // Description: Resorts the _columns vector so that the columns 00616 // are listed in the same order they appear in the 00617 // record. 00618 //////////////////////////////////////////////////////////////////// 00619 void GeomVertexArrayFormat:: 00620 sort_columns() { 00621 sort(_columns.begin(), _columns.end(), IndirectLess<GeomVertexColumn>()); 00622 } 00623 00624 //////////////////////////////////////////////////////////////////// 00625 // Function: GeomVertexArrayFormat::make_registry 00626 // Access: Private 00627 // Description: Returns the global registry object. 00628 //////////////////////////////////////////////////////////////////// 00629 void GeomVertexArrayFormat:: 00630 make_registry() { 00631 if (_registry == (Registry *)NULL) { 00632 _registry = new Registry; 00633 } 00634 } 00635 00636 //////////////////////////////////////////////////////////////////// 00637 // Function: GeomVertexArrayFormat::do_register 00638 // Access: Private 00639 // Description: Called internally when the format is registered. 00640 //////////////////////////////////////////////////////////////////// 00641 void GeomVertexArrayFormat:: 00642 do_register() { 00643 nassertv(!_is_registered); 00644 _is_registered = true; 00645 } 00646 00647 //////////////////////////////////////////////////////////////////// 00648 // Function: GeomVertexArrayFormat::do_unregister 00649 // Access: Private 00650 // Description: Called internally when the format is unregistered. 00651 //////////////////////////////////////////////////////////////////// 00652 void GeomVertexArrayFormat:: 00653 do_unregister() { 00654 nassertv(_is_registered); 00655 _is_registered = false; 00656 } 00657 00658 //////////////////////////////////////////////////////////////////// 00659 // Function: GeomVertexArrayFormat::register_with_read_factory 00660 // Access: Public, Static 00661 // Description: Tells the BamReader how to create objects of type 00662 // GeomVertexArrayFormat. 00663 //////////////////////////////////////////////////////////////////// 00664 void GeomVertexArrayFormat:: 00665 register_with_read_factory() { 00666 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00667 } 00668 00669 //////////////////////////////////////////////////////////////////// 00670 // Function: GeomVertexArrayFormat::write_datagram 00671 // Access: Public, Virtual 00672 // Description: Writes the contents of this object to the datagram 00673 // for shipping out to a Bam file. 00674 //////////////////////////////////////////////////////////////////// 00675 void GeomVertexArrayFormat:: 00676 write_datagram(BamWriter *manager, Datagram &dg) { 00677 TypedWritableReferenceCount::write_datagram(manager, dg); 00678 00679 dg.add_uint16(_stride); 00680 dg.add_uint16(_total_bytes); 00681 dg.add_uint8(_pad_to); 00682 00683 consider_sort_columns(); 00684 00685 dg.add_uint16(_columns.size()); 00686 Columns::iterator ci; 00687 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00688 GeomVertexColumn *column = (*ci); 00689 column->write_datagram(manager, dg); 00690 } 00691 } 00692 00693 //////////////////////////////////////////////////////////////////// 00694 // Function: GeomVertexArrayFormat::complete_pointers 00695 // Access: Public, Virtual 00696 // Description: Receives an array of pointers, one for each time 00697 // manager->read_pointer() was called in fillin(). 00698 // Returns the number of pointers processed. 00699 //////////////////////////////////////////////////////////////////// 00700 int GeomVertexArrayFormat:: 00701 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00702 int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager); 00703 00704 Columns::iterator ci; 00705 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00706 GeomVertexColumn *column = (*ci); 00707 pi += column->complete_pointers(p_list + pi, manager); 00708 } 00709 00710 return pi; 00711 } 00712 00713 //////////////////////////////////////////////////////////////////// 00714 // Function: GeomVertexArrayFormat::finalize 00715 // Access: Public, Virtual 00716 // Description: Called by the BamReader to perform any final actions 00717 // needed for setting up the object after all objects 00718 // have been read and all pointers have been completed. 00719 //////////////////////////////////////////////////////////////////// 00720 void GeomVertexArrayFormat:: 00721 finalize(BamReader *manager) { 00722 // Now we can build up the _columns_by_name index. We have to wait 00723 // until finalize(), since the index is based on the nested name 00724 // pointer within each column, which might not be available at the 00725 // time complete_pointers() is called. 00726 _columns_by_name.clear(); 00727 Columns::iterator ci; 00728 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00729 GeomVertexColumn *column = (*ci); 00730 _columns_by_name.insert(ColumnsByName::value_type(column->get_name(), column)); 00731 } 00732 } 00733 00734 //////////////////////////////////////////////////////////////////// 00735 // Function: GeomVertexArrayFormat::make_from_bam 00736 // Access: Protected, Static 00737 // Description: This function is called by the BamReader's factory 00738 // when a new object of type GeomVertexArrayFormat is 00739 // encountered in the Bam file. It should create the 00740 // GeomVertexArrayFormat and extract its information 00741 // from the file. 00742 //////////////////////////////////////////////////////////////////// 00743 TypedWritable *GeomVertexArrayFormat:: 00744 make_from_bam(const FactoryParams ¶ms) { 00745 GeomVertexArrayFormat *object = new GeomVertexArrayFormat; 00746 DatagramIterator scan; 00747 BamReader *manager; 00748 00749 parse_params(params, scan, manager); 00750 object->fillin(scan, manager); 00751 manager->register_finalize(object); 00752 00753 return object; 00754 } 00755 00756 //////////////////////////////////////////////////////////////////// 00757 // Function: GeomVertexArrayFormat::fillin 00758 // Access: Protected 00759 // Description: This internal function is called by make_from_bam to 00760 // read in all of the relevant data from the BamFile for 00761 // the new GeomVertexArrayFormat. 00762 //////////////////////////////////////////////////////////////////// 00763 void GeomVertexArrayFormat:: 00764 fillin(DatagramIterator &scan, BamReader *manager) { 00765 TypedWritableReferenceCount::fillin(scan, manager); 00766 nassertv(!_is_registered); 00767 00768 _stride = scan.get_uint16(); 00769 _total_bytes = scan.get_uint16(); 00770 _pad_to = scan.get_uint8(); 00771 00772 int num_columns = scan.get_uint16(); 00773 _columns.reserve(num_columns); 00774 for (int i = 0; i < num_columns; ++i) { 00775 GeomVertexColumn *column = new GeomVertexColumn; 00776 column->fillin(scan, manager); 00777 _columns.push_back(column); 00778 } 00779 _columns_unsorted = false; 00780 } 00781 00782 //////////////////////////////////////////////////////////////////// 00783 // Function: GeomVertexArrayFormat::Registry::Constructor 00784 // Access: Public 00785 // Description: 00786 //////////////////////////////////////////////////////////////////// 00787 GeomVertexArrayFormat::Registry:: 00788 Registry() { 00789 } 00790 00791 //////////////////////////////////////////////////////////////////// 00792 // Function: GeomVertexArrayFormat::Registry::register_format 00793 // Access: Public 00794 // Description: Adds the indicated format to the registry, if there 00795 // is not an equivalent format already there; in either 00796 // case, returns the pointer to the equivalent format 00797 // now in the registry. 00798 // 00799 // This must be called before a format may be used in a 00800 // Geom. After this call, you should discard the 00801 // original pointer you passed in (which may or may not 00802 // now be invalid) and let its reference count decrement 00803 // normally; you should use only the returned value from 00804 // this point on. 00805 //////////////////////////////////////////////////////////////////// 00806 CPT(GeomVertexArrayFormat) GeomVertexArrayFormat::Registry:: 00807 register_format(GeomVertexArrayFormat *format) { 00808 if (format->is_registered()) { 00809 return format; 00810 } 00811 00812 // Save the incoming pointer in a local PointerTo, so that if it has 00813 // a zero reference count and is not added into the map below, it 00814 // will be automatically deleted when this function returns. 00815 PT(GeomVertexArrayFormat) pt_format = format; 00816 00817 GeomVertexArrayFormat *new_format; 00818 { 00819 LightMutexHolder holder(_lock); 00820 ArrayFormats::iterator fi = _formats.insert(format).first; 00821 new_format = (*fi); 00822 if (!new_format->is_registered()) { 00823 new_format->do_register(); 00824 } 00825 } 00826 00827 return new_format; 00828 } 00829 00830 //////////////////////////////////////////////////////////////////// 00831 // Function: GeomVertexArrayFormat::Registry::unregister_format 00832 // Access: Public 00833 // Description: Removes the indicated format from the registry. 00834 // Normally this should not be done until the format is 00835 // destructing. 00836 // 00837 // The lock should be held prior to calling this method. 00838 //////////////////////////////////////////////////////////////////// 00839 void GeomVertexArrayFormat::Registry:: 00840 unregister_format(GeomVertexArrayFormat *format) { 00841 nassertv(format->is_registered()); 00842 ArrayFormats::iterator fi = _formats.find(format); 00843 nassertv(fi != _formats.end()); 00844 _formats.erase(fi); 00845 format->do_unregister(); 00846 }