Panda3D

geomVertexArrayFormat.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file geomVertexArrayFormat.cxx
10 * @author drose
11 * @date 2005-03-06
12 */
13
14 #include "geomVertexFormat.h"
15 #include "geomVertexColumn.h"
16 #include "geomVertexData.h"
17 #include "geomVertexReader.h"
18 #include "indent.h"
19 #include "bamReader.h"
20 #include "bamWriter.h"
21 #include "indirectLess.h"
22 #include "lightMutexHolder.h"
23
24 using std::max;
25 using std::min;
26 using std::move;
27
28 GeomVertexArrayFormat::Registry *GeomVertexArrayFormat::_registry = nullptr;
29 TypeHandle GeomVertexArrayFormat::_type_handle;
30
31 /**
32 *
33 */
34 GeomVertexArrayFormat::
35 GeomVertexArrayFormat() :
36 _is_registered(false),
37 _stride(0),
38 _total_bytes(0),
39 _pad_to(1),
40 _divisor(0),
41 _columns_unsorted(false)
42 {
43 }
44
45 /**
46 *
47 */
48 GeomVertexArrayFormat::
49 GeomVertexArrayFormat(CPT_InternalName name0, int num_components0,
50 GeomVertexArrayFormat::NumericType numeric_type0,
51 GeomVertexArrayFormat::Contents contents0) :
52 _is_registered(false),
53 _stride(0),
54 _total_bytes(0),
55 _pad_to(1),
56 _divisor(0),
57 _columns_unsorted(false)
58 {
59 add_column(move(name0), num_components0, numeric_type0, contents0);
60 }
61
62 /**
63 *
64 */
65 GeomVertexArrayFormat::
66 GeomVertexArrayFormat(CPT_InternalName name0, int num_components0,
67 GeomVertexArrayFormat::NumericType numeric_type0,
68 GeomVertexArrayFormat::Contents contents0,
69 CPT_InternalName name1, int num_components1,
70 GeomVertexArrayFormat::NumericType numeric_type1,
71 GeomVertexArrayFormat::Contents contents1) :
72 _is_registered(false),
73 _stride(0),
74 _total_bytes(0),
75 _pad_to(1),
76 _divisor(0),
77 _columns_unsorted(false)
78 {
79 add_column(move(name0), num_components0, numeric_type0, contents0);
80 add_column(move(name1), num_components1, numeric_type1, contents1);
81 }
82
83 /**
84 *
85 */
86 GeomVertexArrayFormat::
87 GeomVertexArrayFormat(CPT_InternalName name0, int num_components0,
88 GeomVertexArrayFormat::NumericType numeric_type0,
89 GeomVertexArrayFormat::Contents contents0,
90 CPT_InternalName name1, int num_components1,
91 GeomVertexArrayFormat::NumericType numeric_type1,
92 GeomVertexArrayFormat::Contents contents1,
93 CPT_InternalName name2, int num_components2,
94 GeomVertexArrayFormat::NumericType numeric_type2,
95 GeomVertexArrayFormat::Contents contents2) :
96 _is_registered(false),
97 _stride(0),
98 _total_bytes(0),
99 _pad_to(1),
100 _divisor(0),
101 _columns_unsorted(false)
102 {
103 add_column(move(name0), num_components0, numeric_type0, contents0);
104 add_column(move(name1), num_components1, numeric_type1, contents1);
105 add_column(move(name2), num_components2, numeric_type2, contents2);
106 }
107
108 /**
109 *
110 */
111 GeomVertexArrayFormat::
112 GeomVertexArrayFormat(CPT_InternalName name0, int num_components0,
113 GeomVertexArrayFormat::NumericType numeric_type0,
114 GeomVertexArrayFormat::Contents contents0,
115 CPT_InternalName name1, int num_components1,
116 GeomVertexArrayFormat::NumericType numeric_type1,
117 GeomVertexArrayFormat::Contents contents1,
118 CPT_InternalName name2, int num_components2,
119 GeomVertexArrayFormat::NumericType numeric_type2,
120 GeomVertexArrayFormat::Contents contents2,
121 CPT_InternalName name3, int num_components3,
122 GeomVertexArrayFormat::NumericType numeric_type3,
123 GeomVertexArrayFormat::Contents contents3) :
124 _is_registered(false),
125 _stride(0),
126 _total_bytes(0),
127 _pad_to(1),
128 _divisor(0),
129 _columns_unsorted(false)
130 {
131 add_column(move(name0), num_components0, numeric_type0, contents0);
132 add_column(move(name1), num_components1, numeric_type1, contents1);
133 add_column(move(name2), num_components2, numeric_type2, contents2);
134 add_column(move(name3), num_components3, numeric_type3, contents3);
135 }
136
137 /**
138 *
139 */
140 GeomVertexArrayFormat::
141 GeomVertexArrayFormat(const GeomVertexArrayFormat &copy) :
142 _is_registered(false),
143 _stride(copy._stride),
144 _total_bytes(copy._total_bytes),
145 _pad_to(copy._pad_to),
146 _divisor(copy._divisor),
147 _columns_unsorted(copy._columns_unsorted)
148 {
149 Columns::const_iterator dti;
150 for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) {
151 add_column(*(*dti));
152 }
153 }
154
155 /**
156 *
157 */
158 void GeomVertexArrayFormat::
159 operator = (const GeomVertexArrayFormat &copy) {
160 nassertv(!_is_registered);
161 _stride = copy._stride;
162 _total_bytes = copy._total_bytes;
163 _pad_to = copy._pad_to;
164 _divisor = copy._divisor;
165
166 _columns.clear();
167 _columns_by_name.clear();
168 _columns_unsorted = false;
169 Columns::const_iterator dti;
170 for (dti = copy._columns.begin(); dti != copy._columns.end(); ++dti) {
171 add_column(*(*dti));
172 }
173 }
174
175 /**
176 *
177 */
178 GeomVertexArrayFormat::
179 ~GeomVertexArrayFormat() {
180 // unref() should have unregistered us.
181 nassertv(!is_registered());
182
183 Columns::iterator ci;
184 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
185 delete (*ci);
186 }
187 }
188
189 /**
190 * This method overrides ReferenceCount::unref() to unregister the object when
191 * its reference count goes to zero.
192 */
193 bool GeomVertexArrayFormat::
194 unref() const {
195 Registry *registry = get_registry();
196 LightMutexHolder holder(registry->_lock);
197
198 if (ReferenceCount::unref()) {
199 return true;
200 }
201
202 if (is_registered()) {
203 registry->unregister_format((GeomVertexArrayFormat *)this);
204 }
205
206 return false;
207 }
208
209 /**
210 * Adds a new column to the specification. This is a table of per-vertex
211 * floating-point numbers such as "vertex" or "normal"; you must specify where
212 * in each record the table starts, and how many components (dimensions) exist
213 * per vertex.
214 *
215 * The return value is the index number of the new data type.
216 */
217 int GeomVertexArrayFormat::
218 add_column(CPT_InternalName name, int num_components,
219 GeomVertexArrayFormat::NumericType numeric_type,
220 GeomVertexArrayFormat::Contents contents, int start,
221 int column_alignment) {
222 if (start < 0) {
223 start = _total_bytes;
224 }
225
226 return add_column(GeomVertexColumn(move(name), num_components, numeric_type, contents,
227 start, column_alignment));
228 }
229
230 /**
231 * Adds a new column to the specification. This is a table of per-vertex
232 * floating-point numbers such as "vertex" or "normal"; you must specify where
233 * in each record the table starts, and how many components (dimensions) exist
234 * per vertex.
235 *
236 * Adding a column with the same name as a previous type, or that overlaps
237 * with one or more previous types, quietly removes the previous type(s).
238 *
239 * The return value is the index number of the new data type.
240 */
241 int GeomVertexArrayFormat::
242 add_column(const GeomVertexColumn &column) {
243 nassertr(!_is_registered, -1);
244
245 // Make sure there isn't already a column with this name.
246 remove_column(column.get_name());
247
248 // Also make sure there aren't any columns that overlap with this one.
249 const GeomVertexColumn *orig_column = get_column(column.get_start(), column.get_total_bytes());
250 while (orig_column != nullptr) {
251 remove_column(orig_column->get_name());
252 orig_column = get_column(column.get_start(), column.get_total_bytes());
253 }
254
255 _total_bytes = max(_total_bytes, column.get_start() + column.get_total_bytes());
256 _pad_to = max(_pad_to, column.get_column_alignment());
257 _stride = max(_stride, _total_bytes);
258 if (_pad_to > 1) {
259 _stride = ((_stride + _pad_to - 1) / _pad_to) * _pad_to;
260 }
261
262 GeomVertexColumn *new_column = new GeomVertexColumn(column);
263
264 if (!_columns.empty() && *new_column < *_columns.back()) {
265 _columns_unsorted = true;
266 }
267
268 int new_index = (int)_columns.size();
269 _columns.push_back(new_column);
270 _columns_by_name.insert(ColumnsByName::value_type(new_column->get_name(), new_column));
271
272 return new_index;
273 }
274
275 /**
276 * Removes the column with the indicated name, if any. This leaves a gap in
277 * the byte structure.
278 */
279 void GeomVertexArrayFormat::
280 remove_column(const InternalName *name) {
281 nassertv(!_is_registered);
282 ColumnsByName::iterator ni;
283 ni = _columns_by_name.find(name);
284 if (ni != _columns_by_name.end()) {
285 GeomVertexColumn *column = (*ni).second;
286 _columns_by_name.erase(ni);
287
288 Columns::iterator ci;
289 ci = find(_columns.begin(), _columns.end(), column);
290 nassertv(ci != _columns.end());
291 _columns.erase(ci);
292
293 delete column;
294
295 // Maybe we just removed the tail column. If that's so, we should
296 // recompute _total_bytes to reflect the new tail.
297 if (_columns.empty()) {
298 _total_bytes = 0;
299 } else {
300 consider_sort_columns();
301 GeomVertexColumn *last = _columns.back();
302 _total_bytes = last->get_start() + last->get_total_bytes();
303 }
304 }
305 }
306
307 /**
308 * Removes all columns previously added, sets the stride to zero, and prepares
309 * to start over.
310 */
311 void GeomVertexArrayFormat::
312 clear_columns() {
313 nassertv(!_is_registered);
314
315 _columns.clear();
316 _columns_by_name.clear();
317 _columns_unsorted = false;
318 _stride = 0;
319 _total_bytes = 0;
320 _pad_to = 1;
321 }
322
323 /**
324 * Removes wasted space between columns.
325 */
326 void GeomVertexArrayFormat::
327 pack_columns() {
328 nassertv(!_is_registered);
329
330 Columns orig_columns;
331 orig_columns.swap(_columns);
332 clear_columns();
333
334 Columns::const_iterator ci;
335 for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
336 GeomVertexColumn *column = (*ci);
337 add_column(column->get_name(), column->get_num_components(),
338 column->get_numeric_type(), column->get_contents());
339 }
340 }
341
342 /**
343 * Reprocesses the columns in the format to align the C_point and C_vector
344 * columns to 16-byte boundaries to allow for the more efficient SSE2
345 * operations (assuming SSE2 is enabled in the build).
346 *
347 * The caller is responsible for testing vertex_animation_align_16 to decide
348 * whether to call this method.
349 */
350 void GeomVertexArrayFormat::
351 align_columns_for_animation() {
352 nassertv(!_is_registered);
353
354 Columns orig_columns;
355 orig_columns.swap(_columns);
356 clear_columns();
357
358 Columns::const_iterator ci;
359 for (ci = orig_columns.begin(); ci != orig_columns.end(); ++ci) {
360 GeomVertexColumn *column = (*ci);
361 if ((column->get_contents() == C_point ||
362 column->get_contents() == C_vector ||
363 column->get_contents() == C_normal) &&
364 (column->get_numeric_type() == NT_float32 ||
365 column->get_numeric_type() == NT_float64) &&
366 column->get_num_components() >= 3) {
367 add_column(column->get_name(), 4, column->get_numeric_type(), column->get_contents(), -1, 16);
368 } else {
369 add_column(column->get_name(), column->get_num_components(),
370 column->get_numeric_type(), column->get_contents(),
371 -1, column->get_column_alignment());
372 }
373 }
374 }
375
376
377 /**
378 * Returns the specification with the indicated name, or NULL if the name is
379 * not used.
380 */
381 const GeomVertexColumn *GeomVertexArrayFormat::
382 get_column(const InternalName *name) const {
383 ColumnsByName::const_iterator ni;
384 ni = _columns_by_name.find(name);
385 if (ni != _columns_by_name.end()) {
386 return (*ni).second;
387 }
388 return nullptr;
389 }
390
391 /**
392 * Returns the first specification that overlaps with any of the indicated
393 * bytes in the range, or NULL if none do.
394 */
395 const GeomVertexColumn *GeomVertexArrayFormat::
396 get_column(int start_byte, int num_bytes) const {
397 consider_sort_columns();
398 Columns::const_iterator ci;
399 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
400 const GeomVertexColumn *column = (*ci);
401 if (column->overlaps_with(start_byte, num_bytes)) {
402 return column;
403 }
404 }
405
406 return nullptr;
407 }
408
409 /**
410 * Returns true if all of the fields in this array format are also present and
411 * equivalent in the other array format, and in the same byte positions, and
412 * the stride is the same. That is, true if this format can share the same
413 * data pointer as the other format (with possibly some unused gaps).
414 */
415 bool GeomVertexArrayFormat::
416 is_data_subset_of(const GeomVertexArrayFormat &other) const {
417 if (_columns.size() > other._columns.size() ||
418 get_stride() != other.get_stride()) {
419 return false;
420 }
421
422 consider_sort_columns();
423 other.consider_sort_columns();
424 size_t i = 0;
425 size_t j = 0;
426 while (i < _columns.size() && j < other._columns.size()) {
427 if (*_columns[i] == *other._columns[j]) {
428 ++i;
429 }
430 ++j;
431 }
432
433 // If we reached the end of our list, all fields matched.
434 return (i == _columns.size());
435 }
436
437 /**
438 * Returns the number of bytes per row that are not assigned to any column.
439 */
440 int GeomVertexArrayFormat::
441 count_unused_space() const {
442 consider_sort_columns();
443
444 int unused_space = 0;
445 int last_pos = 0;
446
447 Columns::const_iterator ci;
448 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
449 const GeomVertexColumn *column = (*ci);
450 if (column->get_start() > last_pos) {
451 unused_space += (column->get_start() - last_pos);
452 }
453 last_pos = column->get_start() + column->get_total_bytes();
454 }
455
456 if (_stride > last_pos) {
457 unused_space += (_stride - last_pos);
458 }
459
460 return unused_space;
461 }
462
463 /**
464 *
465 */
466 void GeomVertexArrayFormat::
467 output(std::ostream &out) const {
468 Columns::const_iterator ci;
469 int last_pos = 0;
470 out << "[";
471 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
472 const GeomVertexColumn *column = (*ci);
473 if (column->get_start() > last_pos) {
474 out << " (..." << (column->get_start() - last_pos) << "...)";
475 }
476 out << " " << *column;
477 last_pos = column->get_start() + column->get_total_bytes();
478 }
479
480 if (_stride > last_pos) {
481 out << " ..." << (_stride - last_pos) << "...";
482 }
483
484 out << " ]";
485 }
486
487 /**
488 *
489 */
490 void GeomVertexArrayFormat::
491 write(std::ostream &out, int indent_level) const {
492 indent(out, indent_level)
493 << "Array format (stride = " << get_stride() << "):\n";
494 consider_sort_columns();
495 Columns::const_iterator ci;
496 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
497 const GeomVertexColumn *column = (*ci);
498 indent(out, indent_level + 2)
499 << *column
500 << " " << column->get_numeric_type()
501 << " " << column->get_contents()
502 << " start at " << column->get_start() << "\n";
503 }
504 }
505
506 /**
507 *
508 */
509 void GeomVertexArrayFormat::
510 write_with_data(std::ostream &out, int indent_level,
511 const GeomVertexArrayData *array_data) const {
512 consider_sort_columns();
513 int num_rows = array_data->get_num_rows();
514
515 GeomVertexReader reader(array_data);
516
517 for (int i = 0; i < num_rows; i++) {
518 indent(out, indent_level)
519 << "row " << i << ":\n";
520 reader.set_row_unsafe(i);
521 Columns::const_iterator ci;
522 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
523 const GeomVertexColumn *column = (*ci);
524 int num_values = min(column->get_num_values(), 4);
525 reader.set_column(0, column);
526 const LVecBase4f &d = reader.get_data4f();
527
528 indent(out, indent_level + 2)
529 << *column->get_name();
530 for (int v = 0; v < num_values; v++) {
531 out << " " << d[v];
532 }
533 out << "\n";
534 }
535 }
536 }
537
538 /**
539 * Returns a string with format codes representing the exact memory layout of
540 * the columns in memory, as understood by Python's struct module. If pad is
541 * true, extra padding bytes are added to the end as 'x' characters as needed.
542 */
543 std::string GeomVertexArrayFormat::
544 get_format_string(bool pad) const {
545 consider_sort_columns();
546
547 int row_size;
548 if (pad) {
549 row_size = get_stride();
550 } else {
551 row_size = get_total_bytes();
552 }
553
554 // Synthesize the format string.
555 char *fmt = (char*) malloc(row_size + 1);
556 memset((void*) fmt, 0, row_size + 1);
557 int fi = 0;
558 int offset = 0;
559
560 for (const GeomVertexColumn *column : _columns) {
561 if (offset < column->get_start()) {
562 // Add padding bytes to fill the gap.
563 int pad = column->get_start() - offset;
564 memset((void*) (fmt + fi), 'x', pad);
565 fi += pad;
566 offset += pad;
567 }
568
569 char fmt_code = 'x';
570 switch (column->get_numeric_type()) {
571 case NT_uint8:
572 fmt_code = 'B';
573 break;
574
575 case NT_uint16:
576 fmt_code = 'H';
577 break;
578
579 case NT_uint32:
580 case NT_packed_dcba:
581 case NT_packed_dabc:
582 fmt_code = 'I';
583 break;
584
585 case NT_float32:
586 fmt_code = 'f';
587 break;
588
589 case NT_float64:
590 fmt_code = 'd';
591 break;
592
593 case NT_int8:
594 fmt_code = 'b';
595 break;
596
597 case NT_int16:
598 fmt_code = 'h';
599 break;
600
601 case NT_int32:
602 fmt_code = 'i';
603 break;
604
605 default:
606 gobj_cat.error()
607 << "Unknown numeric type " << column->get_numeric_type() << "!\n";
608 return nullptr;
609 }
610 memset((void*) (fmt + fi), fmt_code, column->get_num_components());
611 offset += column->get_total_bytes();
612 fi += column->get_num_components();
613 }
614
615 if (offset < row_size) {
616 // Add padding bytes.
617 int pad = row_size - offset;
618 memset((void*) (fmt + fi), 'x', pad);
619 }
620
621 std::string fmt_string (fmt);
622 free(fmt);
623 return fmt_string;
624 }
625
626 /**
627 *
628 */
629 int GeomVertexArrayFormat::
630 compare_to(const GeomVertexArrayFormat &other) const {
631 if (_stride != other._stride) {
632 return _stride - other._stride;
633 }
634 if (_total_bytes != other._total_bytes) {
635 return _total_bytes - other._total_bytes;
636 }
637 if (_pad_to != other._pad_to) {
638 return _pad_to - other._pad_to;
639 }
640 if (_divisor != other._divisor) {
641 return _divisor - other._divisor;
642 }
643 if (_columns.size() != other._columns.size()) {
644 return (int)_columns.size() - (int)other._columns.size();
645 }
646 consider_sort_columns();
647 other.consider_sort_columns();
648 for (size_t i = 0; i < _columns.size(); i++) {
649 int compare = _columns[i]->compare_to(*other._columns[i]);
650 if (compare != 0) {
651 return compare;
652 }
653 }
654
655 return 0;
656 }
657
658 /**
659 * Resorts the _columns vector so that the columns are listed in the same
660 * order they appear in the record.
661 */
662 void GeomVertexArrayFormat::
663 sort_columns() {
664 sort(_columns.begin(), _columns.end(), IndirectLess<GeomVertexColumn>());
665 }
666
667 /**
668 * Returns the global registry object.
669 */
670 void GeomVertexArrayFormat::
671 make_registry() {
672 if (_registry == nullptr) {
673 _registry = new Registry;
674 }
675 }
676
677 /**
678 * Called internally when the format is registered.
679 */
680 void GeomVertexArrayFormat::
681 do_register() {
682 nassertv(!_is_registered);
683 _is_registered = true;
684 }
685
686 /**
687 * Called internally when the format is unregistered.
688 */
689 void GeomVertexArrayFormat::
690 do_unregister() {
691 nassertv(_is_registered);
692 _is_registered = false;
693 }
694
695 /**
696 * Tells the BamReader how to create objects of type GeomVertexArrayFormat.
697 */
698 void GeomVertexArrayFormat::
699 register_with_read_factory() {
700 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
701 }
702
703 /**
704 * Writes the contents of this object to the datagram for shipping out to a
705 * Bam file.
706 */
707 void GeomVertexArrayFormat::
708 write_datagram(BamWriter *manager, Datagram &dg) {
709 TypedWritableReferenceCount::write_datagram(manager, dg);
710
711 dg.add_uint16(_stride);
712 dg.add_uint16(_total_bytes);
713 dg.add_uint8(_pad_to);
714
715 if (manager->get_file_minor_ver() > 36) {
716 dg.add_uint16(_divisor);
717 }
718
719 consider_sort_columns();
720
721 dg.add_uint16(_columns.size());
722 Columns::iterator ci;
723 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
724 GeomVertexColumn *column = (*ci);
725 column->write_datagram(manager, dg);
726 }
727 }
728
729 /**
730 * Receives an array of pointers, one for each time manager->read_pointer()
731 * was called in fillin(). Returns the number of pointers processed.
732 */
733 int GeomVertexArrayFormat::
734 complete_pointers(TypedWritable **p_list, BamReader *manager) {
735 int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
736
737 Columns::iterator ci;
738 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
739 GeomVertexColumn *column = (*ci);
740 pi += column->complete_pointers(p_list + pi, manager);
741 }
742
743 return pi;
744 }
745
746 /**
747 * Called by the BamReader to perform any final actions needed for setting up
748 * the object after all objects have been read and all pointers have been
749 * completed.
750 */
751 void GeomVertexArrayFormat::
752 finalize(BamReader *manager) {
753 // Now we can build up the _columns_by_name index. We have to wait until
754 // finalize(), since the index is based on the nested name pointer within
755 // each column, which might not be available at the time complete_pointers()
756 // is called.
757 _columns_by_name.clear();
758 Columns::iterator ci;
759 for (ci = _columns.begin(); ci != _columns.end(); ++ci) {
760 GeomVertexColumn *column = (*ci);
761 _columns_by_name.insert(ColumnsByName::value_type(column->get_name(), column));
762 }
763 }
764
765 /**
766 * This function is called by the BamReader's factory when a new object of
767 * type GeomVertexArrayFormat is encountered in the Bam file. It should
768 * create the GeomVertexArrayFormat and extract its information from the file.
769 */
770 TypedWritable *GeomVertexArrayFormat::
771 make_from_bam(const FactoryParams &params) {
772 GeomVertexArrayFormat *object = new GeomVertexArrayFormat;
773 DatagramIterator scan;
774 BamReader *manager;
775
776 parse_params(params, scan, manager);
777 object->fillin(scan, manager);
778 manager->register_finalize(object);
779
780 return object;
781 }
782
783 /**
784 * This internal function is called by make_from_bam to read in all of the
785 * relevant data from the BamFile for the new GeomVertexArrayFormat.
786 */
787 void GeomVertexArrayFormat::
788 fillin(DatagramIterator &scan, BamReader *manager) {
789 TypedWritableReferenceCount::fillin(scan, manager);
790 nassertv(!_is_registered);
791
792 _stride = scan.get_uint16();
793 _total_bytes = scan.get_uint16();
794 _pad_to = scan.get_uint8();
795 if (manager->get_file_minor_ver() > 36) {
796 _divisor = scan.get_uint16();
797 } else {
798 _divisor = 0;
799 }
800
801 int num_columns = scan.get_uint16();
802 _columns.reserve(num_columns);
803 for (int i = 0; i < num_columns; ++i) {
804 GeomVertexColumn *column = new GeomVertexColumn;
805 column->fillin(scan, manager);
806 _columns.push_back(column);
807 }
808 _columns_unsorted = false;
809 }
810
811 /**
812 *
813 */
814 GeomVertexArrayFormat::Registry::
815 Registry() {
816 }
817
818 /**
819 * Adds the indicated format to the registry, if there is not an equivalent
820 * format already there; in either case, returns the pointer to the equivalent
821 * format now in the registry.
822 *
823 * This must be called before a format may be used in a Geom. After this
824 * call, you should discard the original pointer you passed in (which may or
825 * may not now be invalid) and let its reference count decrement normally; you
826 * should use only the returned value from this point on.
827 */
828 CPT(GeomVertexArrayFormat) GeomVertexArrayFormat::Registry::
829 register_format(GeomVertexArrayFormat *format) {
830 if (format->is_registered()) {
831 return format;
832 }
833
834 // Save the incoming pointer in a local PointerTo, so that if it has a zero
835 // reference count and is not added into the map below, it will be
836 // automatically deleted when this function returns.
837 PT(GeomVertexArrayFormat) pt_format = format;
838
839 GeomVertexArrayFormat *new_format;
840 {
841 LightMutexHolder holder(_lock);
842 ArrayFormats::iterator fi = _formats.insert(format).first;
843 new_format = (*fi);
844 if (!new_format->is_registered()) {
845 new_format->do_register();
846 }
847 }
848
849 return new_format;
850 }
851
852 /**
853 * Removes the indicated format from the registry. Normally this should not
854 * be done until the format is destructing.
855 *
856 * The lock should be held prior to calling this method.
857 */
858 void GeomVertexArrayFormat::Registry::
859 unregister_format(GeomVertexArrayFormat *format) {
860 nassertv(format->is_registered());
861 ArrayFormats::iterator fi = _formats.find(format);
862 nassertv(fi != _formats.end());
863 _formats.erase(fi);
864 format->do_unregister();
865 }
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
parse_params
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
BamReader::register_finalize
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
Definition: bamReader.cxx:808
BamReader::get_file_minor_ver
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
BamWriter::get_file_minor_ver
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being written.
Definition: bamWriter.I:59
CPT_InternalName
This is a const pointer to an InternalName, and should be used in lieu of a CPT(InternalName) in func...
Definition: internalName.h:193
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
DatagramIterator::get_uint8
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
Definition: datagramIterator.I:72
DatagramIterator::get_uint16
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
Definition: datagramIterator.I:145
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
Datagram::add_uint8
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:50
Datagram::add_uint16
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
Factory::register_factory
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:73
GeomVertexArrayData
This is the data for one array of a GeomVertexData structure.
Definition: geomVertexArrayData.h:58
GeomVertexArrayData::get_num_rows
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride.
Definition: geomVertexArrayData.I:47
GeomVertexArrayFormat
This describes the structure of a single array within a Geom data.
Definition: geomVertexArrayFormat.h:47
GeomVertexArrayFormat::remove_column
void remove_column(const InternalName *name)
Removes the column with the indicated name, if any.
Definition: geomVertexArrayFormat.cxx:280
GeomVertexArrayFormat::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: geomVertexArrayFormat.cxx:708
GeomVertexArrayFormat::get_column
get_column
Returns the specification with the indicated name, or NULL if the name is not used.
Definition: geomVertexArrayFormat.h:106
GeomVertexArrayFormat::align_columns_for_animation
void align_columns_for_animation()
Reprocesses the columns in the format to align the C_point and C_vector columns to 16-byte boundaries...
Definition: geomVertexArrayFormat.cxx:351
GeomVertexArrayFormat::get_total_bytes
get_total_bytes
Returns the total number of bytes used by the data types within the format, including gaps between el...
Definition: geomVertexArrayFormat.h:93
GeomVertexArrayFormat::get_stride
get_stride
Returns the total number of bytes reserved in the array for each vertex.
Definition: geomVertexArrayFormat.h:82
GeomVertexArrayFormat::is_registered
is_registered
Returns true if this format has been registered, false if it has not.
Definition: geomVertexArrayFormat.h:78
GeomVertexArrayFormat::unref
virtual bool unref() const
This method overrides ReferenceCount::unref() to unregister the object when its reference count goes ...
Definition: geomVertexArrayFormat.cxx:194
GeomVertexArrayFormat::finalize
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Definition: geomVertexArrayFormat.cxx:752
GeomVertexArrayFormat::count_unused_space
int count_unused_space() const
Returns the number of bytes per row that are not assigned to any column.
Definition: geomVertexArrayFormat.cxx:441
GeomVertexArrayFormat::get_format_string
std::string get_format_string(bool pad=true) const
Returns a string with format codes representing the exact memory layout of the columns in memory,...
Definition: geomVertexArrayFormat.cxx:544
GeomVertexArrayFormat::clear_columns
void clear_columns()
Removes all columns previously added, sets the stride to zero, and prepares to start over.
Definition: geomVertexArrayFormat.cxx:312
GeomVertexArrayFormat::complete_pointers
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition: geomVertexArrayFormat.cxx:734
GeomVertexArrayFormat::register_with_read_factory
static void register_with_read_factory()
Tells the BamReader how to create objects of type GeomVertexArrayFormat.
Definition: geomVertexArrayFormat.cxx:699
GeomVertexArrayFormat::pack_columns
void pack_columns()
Removes wasted space between columns.
Definition: geomVertexArrayFormat.cxx:327
GeomVertexArrayFormat::add_column
int add_column(CPT_InternalName name, int num_components, NumericType numeric_type, Contents contents, int start=-1, int column_alignment=0)
Adds a new column to the specification.
Definition: geomVertexArrayFormat.cxx:218
GeomVertexArrayFormat::is_data_subset_of
bool is_data_subset_of(const GeomVertexArrayFormat &other) const
Returns true if all of the fields in this array format are also present and equivalent in the other a...
Definition: geomVertexArrayFormat.cxx:416
GeomVertexColumn
This defines how a single column is interleaved within a vertex array stored within a Geom.
Definition: geomVertexColumn.h:37
GeomVertexColumn::get_num_values
int get_num_values() const
Returns the number of numeric values of the column: the number of distinct numeric values that go int...
Definition: geomVertexColumn.I:99
GeomVertexColumn::fillin
void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is called by make_from_bam to read in all of the relevant data from the BamFil...
Definition: geomVertexColumn.cxx:430
GeomVertexColumn::get_start
int get_start() const
Returns the byte within the array record at which this column starts.
Definition: geomVertexColumn.I:133
GeomVertexColumn::get_numeric_type
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
Definition: geomVertexColumn.I:116
GeomVertexColumn::write_datagram
void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: geomVertexColumn.cxx:386
GeomVertexColumn::get_column_alignment
int get_column_alignment() const
Returns the alignment requirements for this column.
Definition: geomVertexColumn.I:144
GeomVertexColumn::overlaps_with
bool overlaps_with(int start_byte, int num_bytes) const
Returns true if this column overlaps with any of the bytes in the indicated range,...
Definition: geomVertexColumn.I:199
GeomVertexColumn::complete_pointers
int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition: geomVertexColumn.cxx:410
GeomVertexColumn::get_name
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
Definition: geomVertexColumn.I:77
GeomVertexColumn::get_contents
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
Definition: geomVertexColumn.I:124
GeomVertexColumn::get_total_bytes
int get_total_bytes() const
Returns the number of bytes used by each element of the column: component_bytes * num_components.
Definition: geomVertexColumn.I:171
GeomVertexColumn::get_num_components
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
Definition: geomVertexColumn.I:87
GeomVertexReader
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
Definition: geomVertexReader.h:47
IndirectLess
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
Definition: indirectLess.h:25
InternalName
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
ReferenceCount::unref
virtual bool unref() const
Explicitly decrements the reference count.
Definition: referenceCount.I:179
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
TypedWritable::fillin
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
Definition: typedWritable.cxx:103
TypedWritable::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: typedWritable.cxx:54
TypedWritable::complete_pointers
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition: typedWritable.cxx:81
pvector< GeomVertexColumn * >
CPT
CPT(GeomVertexArrayFormat) GeomVertexArrayFormat
Adds the indicated format to the registry, if there is not an equivalent format already there; in eit...
Definition: geomVertexArrayFormat.cxx:828
geomVertexColumn.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexFormat.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
indirectLess.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.