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 if (start < 0) { 00235 start = _total_bytes; 00236 00237 GeomVertexColumn temp_column 00238 (name, num_components, numeric_type, contents, 0); 00239 int pad_to = temp_column.get_component_bytes(); 00240 start = ((start + pad_to - 1) / pad_to) * pad_to; 00241 } 00242 00243 return add_column(GeomVertexColumn(name, num_components, 00244 numeric_type, contents, start)); 00245 } 00246 00247 //////////////////////////////////////////////////////////////////// 00248 // Function: GeomVertexArrayFormat::add_column 00249 // Access: Published 00250 // Description: Adds a new column to the specification. This is a 00251 // table of per-vertex floating-point numbers such as 00252 // "vertex" or "normal"; you must specify where in each 00253 // record the table starts, and how many components 00254 // (dimensions) exist per vertex. 00255 // 00256 // Adding a column with the same name as a previous 00257 // type, or that overlaps with one or more previous 00258 // types, quietly removes the previous type(s). 00259 // 00260 // The return value is the index number of the new data 00261 // type. 00262 //////////////////////////////////////////////////////////////////// 00263 int GeomVertexArrayFormat:: 00264 add_column(const GeomVertexColumn &column) { 00265 nassertr(!_is_registered, -1); 00266 00267 // Make sure there isn't already a column with this name. 00268 remove_column(column.get_name()); 00269 00270 // Also make sure there aren't any columns that overlap with this 00271 // one. 00272 const GeomVertexColumn *orig_column = get_column(column.get_start(), column.get_total_bytes()); 00273 while (orig_column != (const GeomVertexColumn *)NULL) { 00274 remove_column(orig_column->get_name()); 00275 orig_column = get_column(column.get_start(), column.get_total_bytes()); 00276 } 00277 00278 _total_bytes = max(_total_bytes, column.get_start() + column.get_total_bytes()); 00279 _pad_to = max(_pad_to, column.get_component_bytes()); 00280 _stride = max(_stride, ((_total_bytes + _pad_to - 1) / _pad_to) * _pad_to); 00281 00282 GeomVertexColumn *new_column = new GeomVertexColumn(column); 00283 00284 if (!_columns.empty() && *new_column < *_columns.back()) { 00285 _columns_unsorted = true; 00286 } 00287 00288 int new_index = (int)_columns.size(); 00289 _columns.push_back(new_column); 00290 _columns_by_name.insert(ColumnsByName::value_type(new_column->get_name(), new_column)); 00291 00292 return new_index; 00293 } 00294 00295 //////////////////////////////////////////////////////////////////// 00296 // Function: GeomVertexArrayFormat::remove_column 00297 // Access: Published 00298 // Description: Removes the column with the indicated name, if 00299 // any. This leaves a gap in the byte structure. 00300 //////////////////////////////////////////////////////////////////// 00301 void GeomVertexArrayFormat:: 00302 remove_column(const InternalName *name) { 00303 nassertv(!_is_registered); 00304 ColumnsByName::iterator ni; 00305 ni = _columns_by_name.find(name); 00306 if (ni != _columns_by_name.end()) { 00307 GeomVertexColumn *column = (*ni).second; 00308 _columns_by_name.erase(ni); 00309 00310 Columns::iterator ci; 00311 ci = find(_columns.begin(), _columns.end(), column); 00312 nassertv(ci != _columns.end()); 00313 _columns.erase(ci); 00314 00315 delete column; 00316 00317 // Maybe we just removed the tail column. If that's so, we 00318 // should recompute _total_bytes to reflect the new tail. 00319 if (_columns.empty()) { 00320 _total_bytes = 0; 00321 } else { 00322 consider_sort_columns(); 00323 GeomVertexColumn *last = _columns.back(); 00324 _total_bytes = last->get_start() + last->get_total_bytes(); 00325 } 00326 } 00327 } 00328 00329 //////////////////////////////////////////////////////////////////// 00330 // Function: GeomVertexArrayFormat::clear_columns 00331 // Access: Published 00332 // Description: Removes all columns previously added, sets the 00333 // stride to zero, and prepares to start over. 00334 //////////////////////////////////////////////////////////////////// 00335 void GeomVertexArrayFormat:: 00336 clear_columns() { 00337 nassertv(!_is_registered); 00338 00339 _columns.clear(); 00340 _columns_by_name.clear(); 00341 _columns_unsorted = false; 00342 _stride = 0; 00343 _total_bytes = 0; 00344 _pad_to = 1; 00345 } 00346 00347 //////////////////////////////////////////////////////////////////// 00348 // Function: GeomVertexArrayFormat::pack_columns 00349 // Access: Published 00350 // Description: Removes wasted space between columns. 00351 //////////////////////////////////////////////////////////////////// 00352 void GeomVertexArrayFormat:: 00353 pack_columns() { 00354 nassertv(!_is_registered); 00355 00356 Columns orig_columns; 00357 orig_columns.swap(_columns); 00358 clear_columns(); 00359 00360 Columns::const_iterator ci; 00361 for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) { 00362 GeomVertexColumn *column = (*ci); 00363 add_column(column->get_name(), column->get_num_components(), 00364 column->get_numeric_type(), column->get_contents()); 00365 } 00366 } 00367 00368 //////////////////////////////////////////////////////////////////// 00369 // Function: GeomVertexArrayFormat::get_column 00370 // Access: Published 00371 // Description: Returns the specification with the indicated name, or 00372 // NULL if the name is not used. 00373 //////////////////////////////////////////////////////////////////// 00374 const GeomVertexColumn *GeomVertexArrayFormat:: 00375 get_column(const InternalName *name) const { 00376 ColumnsByName::const_iterator ni; 00377 ni = _columns_by_name.find(name); 00378 if (ni != _columns_by_name.end()) { 00379 return (*ni).second; 00380 } 00381 return NULL; 00382 } 00383 00384 //////////////////////////////////////////////////////////////////// 00385 // Function: GeomVertexArrayFormat::get_column 00386 // Access: Published 00387 // Description: Returns the first specification that overlaps with 00388 // any of the indicated bytes in the range, or NULL if 00389 // none do. 00390 //////////////////////////////////////////////////////////////////// 00391 const GeomVertexColumn *GeomVertexArrayFormat:: 00392 get_column(int start_byte, int num_bytes) const { 00393 consider_sort_columns(); 00394 Columns::const_iterator ci; 00395 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00396 const GeomVertexColumn *column = (*ci); 00397 if (column->overlaps_with(start_byte, num_bytes)) { 00398 return column; 00399 } 00400 } 00401 00402 return NULL; 00403 } 00404 00405 //////////////////////////////////////////////////////////////////// 00406 // Function: GeomVertexArrayFormat::is_data_subset_of 00407 // Access: Published 00408 // Description: Returns true if all of the fields in this array 00409 // format are also present and equivalent in the other 00410 // array format, and in the same byte positions, and the 00411 // stride is the same. That is, true if this format can 00412 // share the same data pointer as the other format (with 00413 // possibly some unused gaps). 00414 //////////////////////////////////////////////////////////////////// 00415 bool GeomVertexArrayFormat:: 00416 is_data_subset_of(const GeomVertexArrayFormat &other) const { 00417 if (_columns.size() > other._columns.size() || 00418 get_stride() != other.get_stride()) { 00419 return false; 00420 } 00421 00422 consider_sort_columns(); 00423 other.consider_sort_columns(); 00424 size_t i = 0; 00425 size_t j = 0; 00426 while (i < _columns.size() && j < other._columns.size()) { 00427 if (*_columns[i] == *other._columns[j]) { 00428 ++i; 00429 } 00430 ++j; 00431 } 00432 00433 // If we reached the end of our list, all fields matched. 00434 return (i == _columns.size()); 00435 } 00436 00437 //////////////////////////////////////////////////////////////////// 00438 // Function: GeomVertexArrayFormat::count_unused_space 00439 // Access: Published 00440 // Description: Returns the number of bytes per row that are not 00441 // assigned to any column. 00442 //////////////////////////////////////////////////////////////////// 00443 int GeomVertexArrayFormat:: 00444 count_unused_space() const { 00445 consider_sort_columns(); 00446 00447 int unused_space = 0; 00448 int last_pos = 0; 00449 00450 Columns::const_iterator ci; 00451 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00452 const GeomVertexColumn *column = (*ci); 00453 if (column->get_start() > last_pos) { 00454 unused_space += (column->get_start() - last_pos); 00455 } 00456 last_pos = column->get_start() + column->get_total_bytes(); 00457 } 00458 00459 if (_stride > last_pos) { 00460 unused_space += (_stride - last_pos); 00461 } 00462 00463 return unused_space; 00464 } 00465 00466 //////////////////////////////////////////////////////////////////// 00467 // Function: GeomVertexArrayFormat::output 00468 // Access: Published 00469 // Description: 00470 //////////////////////////////////////////////////////////////////// 00471 void GeomVertexArrayFormat:: 00472 output(ostream &out) const { 00473 Columns::const_iterator ci; 00474 int last_pos = 0; 00475 out << "["; 00476 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00477 const GeomVertexColumn *column = (*ci); 00478 if (column->get_start() > last_pos) { 00479 out << " ..." << (column->get_start() - last_pos) << "..."; 00480 } 00481 out << " " << *column; 00482 last_pos = column->get_start() + column->get_total_bytes(); 00483 } 00484 00485 if (_stride > last_pos) { 00486 out << " ..." << (_stride - last_pos) << "..."; 00487 } 00488 00489 out << " ]"; 00490 } 00491 00492 //////////////////////////////////////////////////////////////////// 00493 // Function: GeomVertexArrayFormat::write 00494 // Access: Published 00495 // Description: 00496 //////////////////////////////////////////////////////////////////// 00497 void GeomVertexArrayFormat:: 00498 write(ostream &out, int indent_level) const { 00499 indent(out, indent_level) 00500 << "Array format (stride = " << get_stride() << "):\n"; 00501 consider_sort_columns(); 00502 Columns::const_iterator ci; 00503 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00504 const GeomVertexColumn *column = (*ci); 00505 indent(out, indent_level + 2) 00506 << *column 00507 << " " << column->get_numeric_type() 00508 << " " << column->get_contents() 00509 << " start at " << column->get_start() << "\n"; 00510 } 00511 } 00512 00513 //////////////////////////////////////////////////////////////////// 00514 // Function: GeomVertexArrayFormat::write_with_data 00515 // Access: Published 00516 // Description: 00517 //////////////////////////////////////////////////////////////////// 00518 void GeomVertexArrayFormat:: 00519 write_with_data(ostream &out, int indent_level, 00520 const GeomVertexArrayData *array_data) const { 00521 consider_sort_columns(); 00522 int num_rows = array_data->get_num_rows(); 00523 00524 GeomVertexReader reader(array_data); 00525 00526 for (int i = 0; i < num_rows; i++) { 00527 indent(out, indent_level) 00528 << "row " << i << ":\n"; 00529 reader.set_row(i); 00530 Columns::const_iterator ci; 00531 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00532 const GeomVertexColumn *column = (*ci); 00533 int num_values = min(column->get_num_values(), 4); 00534 reader.set_column(0, column); 00535 const LVecBase4f &d = reader.get_data4f(); 00536 00537 indent(out, indent_level + 2) 00538 << *column->get_name(); 00539 for (int v = 0; v < num_values; v++) { 00540 out << " " << d[v]; 00541 } 00542 out << "\n"; 00543 } 00544 } 00545 } 00546 00547 //////////////////////////////////////////////////////////////////// 00548 // Function: GeomVertexArrayFormat::compare_to 00549 // Access: Public 00550 // Description: 00551 //////////////////////////////////////////////////////////////////// 00552 int GeomVertexArrayFormat:: 00553 compare_to(const GeomVertexArrayFormat &other) const { 00554 if (_stride != other._stride) { 00555 return _stride - other._stride; 00556 } 00557 if (_total_bytes != other._total_bytes) { 00558 return _total_bytes - other._total_bytes; 00559 } 00560 if (_pad_to != other._pad_to) { 00561 return _pad_to - other._pad_to; 00562 } 00563 if (_columns.size() != other._columns.size()) { 00564 return (int)_columns.size() - (int)other._columns.size(); 00565 } 00566 consider_sort_columns(); 00567 other.consider_sort_columns(); 00568 for (size_t i = 0; i < _columns.size(); i++) { 00569 int compare = _columns[i]->compare_to(*other._columns[i]); 00570 if (compare != 0) { 00571 return compare; 00572 } 00573 } 00574 00575 return 0; 00576 } 00577 00578 //////////////////////////////////////////////////////////////////// 00579 // Function: GeomVertexArrayFormat::sort_columns 00580 // Access: Private 00581 // Description: Resorts the _columns vector so that the columns 00582 // are listed in the same order they appear in the 00583 // record. 00584 //////////////////////////////////////////////////////////////////// 00585 void GeomVertexArrayFormat:: 00586 sort_columns() { 00587 sort(_columns.begin(), _columns.end(), IndirectLess<GeomVertexColumn>()); 00588 } 00589 00590 //////////////////////////////////////////////////////////////////// 00591 // Function: GeomVertexArrayFormat::make_registry 00592 // Access: Private 00593 // Description: Returns the global registry object. 00594 //////////////////////////////////////////////////////////////////// 00595 void GeomVertexArrayFormat:: 00596 make_registry() { 00597 if (_registry == (Registry *)NULL) { 00598 _registry = new Registry; 00599 } 00600 } 00601 00602 //////////////////////////////////////////////////////////////////// 00603 // Function: GeomVertexArrayFormat::do_register 00604 // Access: Private 00605 // Description: Called internally when the format is registered. 00606 //////////////////////////////////////////////////////////////////// 00607 void GeomVertexArrayFormat:: 00608 do_register() { 00609 nassertv(!_is_registered); 00610 _is_registered = true; 00611 } 00612 00613 //////////////////////////////////////////////////////////////////// 00614 // Function: GeomVertexArrayFormat::do_unregister 00615 // Access: Private 00616 // Description: Called internally when the format is unregistered. 00617 //////////////////////////////////////////////////////////////////// 00618 void GeomVertexArrayFormat:: 00619 do_unregister() { 00620 nassertv(_is_registered); 00621 _is_registered = false; 00622 } 00623 00624 //////////////////////////////////////////////////////////////////// 00625 // Function: GeomVertexArrayFormat::register_with_read_factory 00626 // Access: Public, Static 00627 // Description: Tells the BamReader how to create objects of type 00628 // GeomVertexArrayFormat. 00629 //////////////////////////////////////////////////////////////////// 00630 void GeomVertexArrayFormat:: 00631 register_with_read_factory() { 00632 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00633 } 00634 00635 //////////////////////////////////////////////////////////////////// 00636 // Function: GeomVertexArrayFormat::write_datagram 00637 // Access: Public, Virtual 00638 // Description: Writes the contents of this object to the datagram 00639 // for shipping out to a Bam file. 00640 //////////////////////////////////////////////////////////////////// 00641 void GeomVertexArrayFormat:: 00642 write_datagram(BamWriter *manager, Datagram &dg) { 00643 TypedWritableReferenceCount::write_datagram(manager, dg); 00644 00645 dg.add_uint16(_stride); 00646 dg.add_uint16(_total_bytes); 00647 dg.add_uint8(_pad_to); 00648 00649 consider_sort_columns(); 00650 00651 dg.add_uint16(_columns.size()); 00652 Columns::iterator ci; 00653 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00654 GeomVertexColumn *column = (*ci); 00655 column->write_datagram(manager, dg); 00656 } 00657 } 00658 00659 //////////////////////////////////////////////////////////////////// 00660 // Function: GeomVertexArrayFormat::complete_pointers 00661 // Access: Public, Virtual 00662 // Description: Receives an array of pointers, one for each time 00663 // manager->read_pointer() was called in fillin(). 00664 // Returns the number of pointers processed. 00665 //////////////////////////////////////////////////////////////////// 00666 int GeomVertexArrayFormat:: 00667 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00668 int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager); 00669 00670 Columns::iterator ci; 00671 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00672 GeomVertexColumn *column = (*ci); 00673 pi += column->complete_pointers(p_list + pi, manager); 00674 } 00675 00676 return pi; 00677 } 00678 00679 //////////////////////////////////////////////////////////////////// 00680 // Function: GeomVertexArrayFormat::finalize 00681 // Access: Public, Virtual 00682 // Description: Called by the BamReader to perform any final actions 00683 // needed for setting up the object after all objects 00684 // have been read and all pointers have been completed. 00685 //////////////////////////////////////////////////////////////////// 00686 void GeomVertexArrayFormat:: 00687 finalize(BamReader *manager) { 00688 // Now we can build up the _columns_by_name index. We have to wait 00689 // until finalize(), since the index is based on the nested name 00690 // pointer within each column, which might not be available at the 00691 // time complete_pointers() is called. 00692 _columns_by_name.clear(); 00693 Columns::iterator ci; 00694 for (ci = _columns.begin(); ci != _columns.end(); ++ci) { 00695 GeomVertexColumn *column = (*ci); 00696 _columns_by_name.insert(ColumnsByName::value_type(column->get_name(), column)); 00697 } 00698 } 00699 00700 //////////////////////////////////////////////////////////////////// 00701 // Function: GeomVertexArrayFormat::make_from_bam 00702 // Access: Protected, Static 00703 // Description: This function is called by the BamReader's factory 00704 // when a new object of type GeomVertexArrayFormat is 00705 // encountered in the Bam file. It should create the 00706 // GeomVertexArrayFormat and extract its information 00707 // from the file. 00708 //////////////////////////////////////////////////////////////////// 00709 TypedWritable *GeomVertexArrayFormat:: 00710 make_from_bam(const FactoryParams ¶ms) { 00711 GeomVertexArrayFormat *object = new GeomVertexArrayFormat; 00712 DatagramIterator scan; 00713 BamReader *manager; 00714 00715 parse_params(params, scan, manager); 00716 object->fillin(scan, manager); 00717 manager->register_finalize(object); 00718 00719 return object; 00720 } 00721 00722 //////////////////////////////////////////////////////////////////// 00723 // Function: GeomVertexArrayFormat::fillin 00724 // Access: Protected 00725 // Description: This internal function is called by make_from_bam to 00726 // read in all of the relevant data from the BamFile for 00727 // the new GeomVertexArrayFormat. 00728 //////////////////////////////////////////////////////////////////// 00729 void GeomVertexArrayFormat:: 00730 fillin(DatagramIterator &scan, BamReader *manager) { 00731 TypedWritableReferenceCount::fillin(scan, manager); 00732 nassertv(!_is_registered); 00733 00734 _stride = scan.get_uint16(); 00735 _total_bytes = scan.get_uint16(); 00736 _pad_to = scan.get_uint8(); 00737 00738 int num_columns = scan.get_uint16(); 00739 _columns.reserve(num_columns); 00740 for (int i = 0; i < num_columns; ++i) { 00741 GeomVertexColumn *column = new GeomVertexColumn; 00742 column->fillin(scan, manager); 00743 _columns.push_back(column); 00744 } 00745 _columns_unsorted = false; 00746 } 00747 00748 //////////////////////////////////////////////////////////////////// 00749 // Function: GeomVertexArrayFormat::Registry::Constructor 00750 // Access: Public 00751 // Description: 00752 //////////////////////////////////////////////////////////////////// 00753 GeomVertexArrayFormat::Registry:: 00754 Registry() { 00755 } 00756 00757 //////////////////////////////////////////////////////////////////// 00758 // Function: GeomVertexArrayFormat::Registry::register_format 00759 // Access: Public 00760 // Description: Adds the indicated format to the registry, if there 00761 // is not an equivalent format already there; in either 00762 // case, returns the pointer to the equivalent format 00763 // now in the registry. 00764 // 00765 // This must be called before a format may be used in a 00766 // Geom. After this call, you should discard the 00767 // original pointer you passed in (which may or may not 00768 // now be invalid) and let its reference count decrement 00769 // normally; you should use only the returned value from 00770 // this point on. 00771 //////////////////////////////////////////////////////////////////// 00772 CPT(GeomVertexArrayFormat) GeomVertexArrayFormat::Registry:: 00773 register_format(GeomVertexArrayFormat *format) { 00774 if (format->is_registered()) { 00775 return format; 00776 } 00777 00778 // Save the incoming pointer in a local PointerTo, so that if it has 00779 // a zero reference count and is not added into the map below, it 00780 // will be automatically deleted when this function returns. 00781 PT(GeomVertexArrayFormat) pt_format = format; 00782 00783 GeomVertexArrayFormat *new_format; 00784 { 00785 LightMutexHolder holder(_lock); 00786 ArrayFormats::iterator fi = _formats.insert(format).first; 00787 new_format = (*fi); 00788 if (!new_format->is_registered()) { 00789 new_format->do_register(); 00790 } 00791 } 00792 00793 return new_format; 00794 } 00795 00796 //////////////////////////////////////////////////////////////////// 00797 // Function: GeomVertexArrayFormat::Registry::unregister_format 00798 // Access: Public 00799 // Description: Removes the indicated format from the registry. 00800 // Normally this should not be done until the format is 00801 // destructing. 00802 // 00803 // The lock should be held prior to calling this method. 00804 //////////////////////////////////////////////////////////////////// 00805 void GeomVertexArrayFormat::Registry:: 00806 unregister_format(GeomVertexArrayFormat *format) { 00807 nassertv(format->is_registered()); 00808 ArrayFormats::iterator fi = _formats.find(format); 00809 nassertv(fi != _formats.end()); 00810 _formats.erase(fi); 00811 format->do_unregister(); 00812 }