Panda3D
geomVertexFormat.cxx
1 // Filename: geomVertexFormat.cxx
2 // Created by: drose (07Mar05)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "geomVertexFormat.h"
16 #include "geomVertexData.h"
17 #include "geomMunger.h"
18 #include "lightReMutexHolder.h"
19 #include "indent.h"
20 #include "bamReader.h"
21 #include "bamWriter.h"
22 
23 GeomVertexFormat::Registry *GeomVertexFormat::_registry = NULL;
24 TypeHandle GeomVertexFormat::_type_handle;
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: GeomVertexFormat::Constructor
28 // Access: Published
29 // Description:
30 ////////////////////////////////////////////////////////////////////
31 GeomVertexFormat::
32 GeomVertexFormat() :
33  _is_registered(false),
34  _post_animated_format(NULL)
35 {
36 }
37 
38 ////////////////////////////////////////////////////////////////////
39 // Function: GeomVertexFormat::Constructor
40 // Access: Published
41 // Description:
42 ////////////////////////////////////////////////////////////////////
43 GeomVertexFormat::
44 GeomVertexFormat(const GeomVertexArrayFormat *array_format) :
45  _is_registered(false),
46  _post_animated_format(NULL)
47 {
48  add_array(array_format);
49 }
50 
51 ////////////////////////////////////////////////////////////////////
52 // Function: GeomVertexFormat::Copy Constructor
53 // Access: Published
54 // Description:
55 ////////////////////////////////////////////////////////////////////
56 GeomVertexFormat::
57 GeomVertexFormat(const GeomVertexFormat &copy) :
58  _is_registered(false),
59  _animation(copy._animation),
60  _arrays(copy._arrays),
61  _post_animated_format(NULL)
62 {
63 }
64 
65 ////////////////////////////////////////////////////////////////////
66 // Function: GeomVertexFormat::Copy Assignment Operator
67 // Access: Published
68 // Description:
69 ////////////////////////////////////////////////////////////////////
70 void GeomVertexFormat::
71 operator = (const GeomVertexFormat &copy) {
72  nassertv(!is_registered());
73 
74  _animation = copy._animation;
75  _arrays = copy._arrays;
76 }
77 
78 ////////////////////////////////////////////////////////////////////
79 // Function: GeomVertexFormat::Destructor
80 // Access: Published, Virtual
81 // Description:
82 ////////////////////////////////////////////////////////////////////
83 GeomVertexFormat::
84 ~GeomVertexFormat() {
85  // unref() should have unregistered us.
86  nassertv(!is_registered());
87 }
88 
89 ////////////////////////////////////////////////////////////////////
90 // Function: GeomVertexFormat::unref
91 // Access: Published, Virtual
92 // Description: This method overrides ReferenceCount::unref() to
93 // unregister the object when its reference count goes
94 // to zero.
95 ////////////////////////////////////////////////////////////////////
96 bool GeomVertexFormat::
97 unref() const {
98  Registry *registry = get_registry();
99  LightReMutexHolder holder(registry->_lock);
100 
101  if (ReferenceCount::unref()) {
102  return true;
103  }
104 
105  if (is_registered()) {
106  registry->unregister_format((GeomVertexFormat *)this);
107  }
108 
109  return false;
110 }
111 
112 ////////////////////////////////////////////////////////////////////
113 // Function: GeomVertexFormat::get_post_animated_format
114 // Access: Published
115 // Description: Returns a suitable vertex format for sending the
116 // animated vertices to the graphics backend. This is
117 // the same format as the source format, with the
118 // CPU-animation data elements removed.
119 //
120 // This may only be called after the format has been
121 // registered. The return value will have been already
122 // registered.
123 ////////////////////////////////////////////////////////////////////
124 CPT(GeomVertexFormat) GeomVertexFormat::
125 get_post_animated_format() const {
126  nassertr(is_registered(), NULL);
127 
128  if (_post_animated_format == (GeomVertexFormat *)NULL) {
129  PT(GeomVertexFormat) new_format = new GeomVertexFormat(*this);
130  new_format->remove_column(InternalName::get_transform_blend());
131 
132  int num_morphs = get_num_morphs();
133  for (int mi = 0; mi < num_morphs; mi++) {
134  CPT(InternalName) delta_name = get_morph_delta(mi);
135  new_format->remove_column(delta_name);
136  }
137 
138  new_format->_animation.set_none();
139 
140  CPT(GeomVertexFormat) registered =
141  GeomVertexFormat::register_format(new_format);
142  ((GeomVertexFormat *)this)->_post_animated_format = registered;
143  if (_post_animated_format != this) {
144  // We only keep the reference count if the new pointer is not
145  // the same as this, to avoid a circular dependency.
146  _post_animated_format->ref();
147  }
148  }
149 
150  _post_animated_format->test_ref_count_integrity();
151 
152  return _post_animated_format;
153 }
154 
155 ////////////////////////////////////////////////////////////////////
156 // Function: GeomVertexFormat::get_union_format
157 // Access: Published
158 // Description: Returns a new GeomVertexFormat that includes all of
159 // the columns defined in either this GeomVertexFormat
160 // or the other one. If any column is defined in both
161 // formats with different sizes (for instance, texcoord2
162 // vs. texcoord3), the new format will include the
163 // larger of the two definitions.
164 //
165 // This may only be called after both source formats
166 // have been registered. The return value will also
167 // have been already registered.
168 ////////////////////////////////////////////////////////////////////
169 CPT(GeomVertexFormat) GeomVertexFormat::
170 get_union_format(const GeomVertexFormat *other) const {
171  nassertr(is_registered() && other->is_registered(), NULL);
172 
173  PT(GeomVertexFormat) new_format = new GeomVertexFormat;
174 
175  // Preserve whichever animation type is not AT_None. (If both
176  // animation types are not AT_None, but they are different, this
177  // whole operation is questionable.)
178  if (_animation.get_animation_type() != AT_none) {
179  new_format->set_animation(_animation);
180  } else {
181  new_format->set_animation(other->get_animation());
182  }
183 
184  // Keep track of the columns we have already added.
185  typedef pset< CPT(InternalName) > ColumnNames;
186  ColumnNames column_names;
187 
188  // We go through all the (0)-level arrays first, then all the
189  // (1)-level arrays, and so on. We do this to ensure that the new
190  // format gets written out with all the (0)-level columns appearing
191  // before all the (1)-level columns, which might lead to a small
192  // optimization at render time.
193 
194  // We also try to keep the structure as similar as possible. If
195  // both source formats have columns (A, B) in array 0, and columns
196  // (C, D, E) in array 1, then the resulting union format will also
197  // have (A, B) in array 0 and (C, D, E) in array 1. In general, a
198  // column will appear in the result in the first array it appears in
199  // either of the inputs.
200 
201  size_t num_arrays = max(_arrays.size(), other->_arrays.size());
202  for (size_t ai = 0; ai < num_arrays; ++ai) {
203  PT(GeomVertexArrayFormat) new_array = new GeomVertexArrayFormat;
204 
205  // Add the columns from the first format.
206  if (ai < _arrays.size()) {
207  GeomVertexArrayFormat *array_format = _arrays[ai];
208  int num_columns = array_format->get_num_columns();
209  for (int i = 0; i < num_columns; ++i) {
210  const GeomVertexColumn *column_a = array_format->get_column(i);
211  bool inserted = column_names.insert(column_a->get_name()).second;
212  if (inserted) {
213  const GeomVertexColumn *column_b = other->get_column(column_a->get_name());
214  if (column_b != (GeomVertexColumn *)NULL &&
215  column_b->get_total_bytes() > column_a->get_total_bytes()) {
216  // Column b is larger. Keep it.
217  new_array->add_column(column_b->get_name(),
218  column_b->get_num_components(),
219  column_b->get_numeric_type(),
220  column_b->get_contents());
221  } else {
222  // Column a is larger. Keep it.
223  new_array->add_column(column_a->get_name(),
224  column_a->get_num_components(),
225  column_a->get_numeric_type(),
226  column_a->get_contents());
227  }
228  }
229  }
230  }
231 
232  // Add the columns from the second format.
233  if (ai < other->_arrays.size()) {
234  GeomVertexArrayFormat *array_format = other->_arrays[ai];
235  int num_columns = array_format->get_num_columns();
236  for (int i = 0; i < num_columns; ++i) {
237  const GeomVertexColumn *column_a = array_format->get_column(i);
238  bool inserted = column_names.insert(column_a->get_name()).second;
239  if (inserted) {
240  const GeomVertexColumn *column_b = get_column(column_a->get_name());
241  if (column_b != (GeomVertexColumn *)NULL &&
242  column_b->get_total_bytes() > column_a->get_total_bytes()) {
243  // Column b is larger. Keep it.
244  new_array->add_column(column_b->get_name(),
245  column_b->get_num_components(),
246  column_b->get_numeric_type(),
247  column_b->get_contents());
248  } else {
249  // Column a is larger. Keep it.
250  new_array->add_column(column_a->get_name(),
251  column_a->get_num_components(),
252  column_a->get_numeric_type(),
253  column_a->get_contents());
254  }
255  }
256  }
257  }
258 
259  if (new_array->get_num_columns() != 0) {
260  new_format->add_array(new_array);
261  }
262  }
263 
264  // Finally, register the format for the thing.
265  return GeomVertexFormat::register_format(new_format);
266 }
267 
268 ////////////////////////////////////////////////////////////////////
269 // Function: GeomVertexFormat::modify_array
270 // Access: Published
271 // Description: Returns a modifiable pointer to the indicated array.
272 // This means duplicating it if it is shared or
273 // registered.
274 //
275 // This may not be called once the format has been
276 // registered.
277 ////////////////////////////////////////////////////////////////////
278 GeomVertexArrayFormat *GeomVertexFormat::
279 modify_array(int array) {
280  nassertr(!is_registered(), NULL);
281  nassertr(array >= 0 && array < (int)_arrays.size(), NULL);
282 
283  if (_arrays[array]->is_registered() ||
284  _arrays[array]->get_ref_count() > 1) {
285  _arrays[array] = new GeomVertexArrayFormat(*_arrays[array]);
286  }
287 
288  return _arrays[array];
289 }
290 
291 ////////////////////////////////////////////////////////////////////
292 // Function: GeomVertexFormat::set_array
293 // Access: Published
294 // Description: Replaces the definition of the indicated array.
295 //
296 // This may not be called once the format has been
297 // registered.
298 ////////////////////////////////////////////////////////////////////
299 void GeomVertexFormat::
300 set_array(int array, const GeomVertexArrayFormat *format) {
301  nassertv(!is_registered());
302  nassertv(array >= 0 && array < (int)_arrays.size());
303  _arrays[array] = (GeomVertexArrayFormat *)format;
304 }
305 
306 ////////////////////////////////////////////////////////////////////
307 // Function: GeomVertexFormat::remove_array
308 // Access: Published
309 // Description: Removes the nth array from the format.
310 //
311 // This may not be called once the format has been
312 // registered.
313 ////////////////////////////////////////////////////////////////////
314 void GeomVertexFormat::
315 remove_array(int array) {
316  nassertv(!is_registered());
317 
318  nassertv(array >= 0 && array < (int)_arrays.size());
319  _arrays.erase(_arrays.begin() + array);
320 }
321 
322 ////////////////////////////////////////////////////////////////////
323 // Function: GeomVertexFormat::add_array
324 // Access: Published
325 // Description: Adds the indicated array definition to the list of
326 // arrays included within this vertex format definition.
327 // The return value is the index number of the new
328 // array.
329 //
330 // This may not be called once the format has been
331 // registered.
332 ////////////////////////////////////////////////////////////////////
333 int GeomVertexFormat::
334 add_array(const GeomVertexArrayFormat *array_format) {
335  nassertr(!is_registered(), -1);
336 
337  int new_array = (int)_arrays.size();
338  _arrays.push_back((GeomVertexArrayFormat *)array_format);
339  return new_array;
340 }
341 
342 ////////////////////////////////////////////////////////////////////
343 // Function: GeomVertexFormat::insert_array
344 // Access: Published
345 // Description: Adds the indicated array definition to the list of
346 // arrays at the indicated position. This works just
347 // like add_array(), except that you can specify which
348 // array index the new array should have.
349 //
350 // This may not be called once the format has been
351 // registered.
352 ////////////////////////////////////////////////////////////////////
353 void GeomVertexFormat::
354 insert_array(int array, const GeomVertexArrayFormat *array_format) {
355  nassertv(!is_registered());
356  nassertv(array >= 0 && array <= (int)_arrays.size());
357 
358  _arrays.insert(_arrays.begin() + array, (GeomVertexArrayFormat *)array_format);
359 }
360 
361 ////////////////////////////////////////////////////////////////////
362 // Function: GeomVertexFormat::clear_arrays
363 // Access: Published
364 // Description: Removes all of the array definitions from the format
365 // and starts over.
366 //
367 // This may not be called once the format has been
368 // registered.
369 ////////////////////////////////////////////////////////////////////
370 void GeomVertexFormat::
371 clear_arrays() {
372  nassertv(!is_registered());
373 
374  _arrays.clear();
375 }
376 
377 ////////////////////////////////////////////////////////////////////
378 // Function: GeomVertexFormat::remove_empty_arrays
379 // Access: Published
380 // Description: Removes the arrays that define no columns.
381 //
382 // This may not be called once the format has been
383 // registered.
384 ////////////////////////////////////////////////////////////////////
385 void GeomVertexFormat::
386 remove_empty_arrays() {
387  nassertv(!is_registered());
388 
389  Arrays orig_arrays;
390  orig_arrays.swap(_arrays);
391  Arrays::const_iterator ai;
392  for (ai = orig_arrays.begin(); ai != orig_arrays.end(); ++ai) {
393  GeomVertexArrayFormat *array_format = (*ai);
394  if (array_format->get_num_columns() != 0) {
395  _arrays.push_back(array_format);
396  }
397  }
398 }
399 
400 ////////////////////////////////////////////////////////////////////
401 // Function: GeomVertexFormat::get_num_columns
402 // Access: Published
403 // Description: Returns the total number of different columns in
404 // the specification, across all arrays.
405 ////////////////////////////////////////////////////////////////////
406 int GeomVertexFormat::
407 get_num_columns() const {
408  int num_columns = 0;
409  Arrays::const_iterator ai;
410  for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
411  num_columns += (*ai)->get_num_columns();
412  }
413  return num_columns;
414 }
415 
416 ////////////////////////////////////////////////////////////////////
417 // Function: GeomVertexFormat::get_column
418 // Access: Published
419 // Description: Returns the ith column of the specification,
420 // across all arrays.
421 ////////////////////////////////////////////////////////////////////
422 const GeomVertexColumn *GeomVertexFormat::
423 get_column(int i) const {
424  Arrays::const_iterator ai;
425  for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
426  if (i < (*ai)->get_num_columns()) {
427  return (*ai)->get_column(i);
428  }
429  i -= (*ai)->get_num_columns();
430  }
431 
432  return NULL;
433 }
434 
435 ////////////////////////////////////////////////////////////////////
436 // Function: GeomVertexFormat::get_array_with
437 // Access: Published
438 // Description: Returns the index number of the array with the
439 // ith column.
440 //
441 // The return value can be passed to get_array_format()
442 // to get the format of the array. It may also be
443 // passed to GeomVertexData::get_array_data() or
444 // get_data() or set_data() to manipulate the actual
445 // array data.
446 ////////////////////////////////////////////////////////////////////
447 int GeomVertexFormat::
448 get_array_with(int i) const {
449  int array_index = 0;
450  for (array_index = 0; array_index < (int)_arrays.size(); array_index++) {
451  if (i < _arrays[array_index]->get_num_columns()) {
452  return array_index;
453  }
454  i -= _arrays[array_index]->get_num_columns();
455  }
456 
457  return -1;
458 }
459 
460 ////////////////////////////////////////////////////////////////////
461 // Function: GeomVertexFormat::get_array_with
462 // Access: Published
463 // Description: Returns the index number of the array with the
464 // indicated column, or -1 if no arrays contained
465 // that name.
466 //
467 // The return value can be passed to get_array_format()
468 // to get the format of the array. It may also be
469 // passed to GeomVertexData::get_array_data() or
470 // get_data() or set_data() to manipulate the actual
471 // array data.
472 //
473 // This may only be called after the format has been
474 // registered.
475 ////////////////////////////////////////////////////////////////////
476 int GeomVertexFormat::
477 get_array_with(const InternalName *name) const {
478  nassertr(_is_registered, -1);
479 
480  DataTypesByName::const_iterator ai;
481  ai = _columns_by_name.find(name);
482  if (ai != _columns_by_name.end()) {
483  return (*ai).second._array_index;
484  }
485  return -1;
486 }
487 
488 ////////////////////////////////////////////////////////////////////
489 // Function: GeomVertexFormat::get_column
490 // Access: Published
491 // Description: Returns the specification with the indicated name, or
492 // NULL if the name is not used. Use get_array_with()
493 // to determine which array this column is associated
494 // with.
495 ////////////////////////////////////////////////////////////////////
496 const GeomVertexColumn *GeomVertexFormat::
497 get_column(const InternalName *name) const {
498  if (!_is_registered) {
499  // If the format hasn't yet been registered, we have to search for
500  // the column the hard way.
501  Arrays::const_iterator ai;
502  for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
503  const GeomVertexColumn *column = (*ai)->get_column(name);
504  if (column != (GeomVertexColumn *)NULL) {
505  return column;
506  }
507  }
508  return NULL;
509 
510  } else {
511  // If the format has been registered, we can just check the
512  // toplevel index.
513 
514  DataTypesByName::const_iterator ai;
515  ai = _columns_by_name.find(name);
516  if (ai != _columns_by_name.end()) {
517  int array_index = (*ai).second._array_index;
518  int column_index = (*ai).second._column_index;
519 
520  nassertr(array_index >= 0 && array_index < (int)_arrays.size(), NULL);
521  return _arrays[array_index]->get_column(column_index);
522  }
523  return NULL;
524  }
525 }
526 
527 ////////////////////////////////////////////////////////////////////
528 // Function: GeomVertexFormat::remove_column
529 // Access: Published
530 // Description: Removes the named column from the format, from
531 // whichever array it exists in. If there are other
532 // columns remaining in the array, the array is left
533 // with a gap where the column used to be; if this
534 // was the only column in the array, the array is
535 // removed (unless keep_empty_array is true).
536 //
537 // This may not be called once the format has been
538 // registered.
539 ////////////////////////////////////////////////////////////////////
540 void GeomVertexFormat::
541 remove_column(const InternalName *name, bool keep_empty_array) {
542  nassertv(!_is_registered);
543 
544  // Since the format's not registered, it doesn't yet have an index
545  // of columns--so we have to search all of the arrays, one at a
546  // time, until we find it.
547  for (int array = 0; array < (int)_arrays.size(); ++array) {
548  GeomVertexArrayFormat *array_format = _arrays[array];
549 
550  if (array_format->get_column(name) != (GeomVertexColumn *)NULL) {
551  // Here's the array with the named column!
552  if (array_format->is_registered() ||
553  array_format->get_ref_count() > 1) {
554  // Get a safe-to-modify copy of the array format.
555  _arrays[array] = new GeomVertexArrayFormat(*array_format);
556  array_format = _arrays[array];
557  }
558 
559  array_format->remove_column(name);
560 
561  // Are there any columns remaining in the array?
562  if (!keep_empty_array && array_format->get_num_columns() == 0) {
563  // Remove the whole array.
564  remove_array(array);
565  }
566  return;
567  }
568  }
569 
570  // It appears that column wasn't part of the format anyway. No
571  // problem; quietly return.
572 }
573 
574 ////////////////////////////////////////////////////////////////////
575 // Function: GeomVertexFormat::pack_columns
576 // Access: Published
577 // Description: Removes wasted space between columns.
578 ////////////////////////////////////////////////////////////////////
579 void GeomVertexFormat::
580 pack_columns() {
581  nassertv(!_is_registered);
582  Arrays::iterator ai;
583  for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
584  if ((*ai)->is_registered()) {
585  (*ai) = new GeomVertexArrayFormat(*(*ai));
586  }
587  (*ai)->pack_columns();
588  }
589 }
590 
591 ////////////////////////////////////////////////////////////////////
592 // Function: GeomVertexFormat::align_columns_for_animation
593 // Access: Published
594 // Description: Reprocesses the columns in the format to align the
595 // C_point and C_vector columns to 16-byte boundaries to
596 // allow for the more efficient SSE2 operations
597 // (assuming SSE2 is enabled in the build).
598 //
599 // Also see maybe_align_columns_for_animation().
600 ////////////////////////////////////////////////////////////////////
601 void GeomVertexFormat::
602 align_columns_for_animation() {
603  nassertv(!_is_registered);
604  Arrays::iterator ai;
605  for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
606  if ((*ai)->is_registered()) {
607  (*ai) = new GeomVertexArrayFormat(*(*ai));
608  }
609  (*ai)->align_columns_for_animation();
610  }
611 }
612 
613 ////////////////////////////////////////////////////////////////////
614 // Function: GeomVertexFormat::maybe_align_columns_for_animation
615 // Access: Published
616 // Description: Calls align_columns_for_animation() if this format's
617 // AnimationSpec indicates that it contains animated
618 // vertices, and if vertex-animation-align-16 is true.
619 ////////////////////////////////////////////////////////////////////
620 void GeomVertexFormat::
621 maybe_align_columns_for_animation() {
622  if (_animation.get_animation_type() == AT_panda && vertex_animation_align_16) {
623  align_columns_for_animation();
624  }
625 }
626 
627 ////////////////////////////////////////////////////////////////////
628 // Function: GeomVertexFormat::output
629 // Access: Published
630 // Description:
631 ////////////////////////////////////////////////////////////////////
632 void GeomVertexFormat::
633 output(ostream &out) const {
634  if (_arrays.empty()) {
635  out << "(empty)";
636 
637  } else {
638  Arrays::const_iterator ai;
639  ai = _arrays.begin();
640  out << *(*ai);
641  ++ai;
642  while (ai != _arrays.end()) {
643  out << ", " << *(*ai);
644  ++ai;
645  }
646  }
647 
648  if (_animation.get_animation_type() != AT_none) {
649  out << ", anim " << _animation;
650  }
651 }
652 
653 ////////////////////////////////////////////////////////////////////
654 // Function: GeomVertexFormat::write
655 // Access: Published
656 // Description:
657 ////////////////////////////////////////////////////////////////////
658 void GeomVertexFormat::
659 write(ostream &out, int indent_level) const {
660  for (size_t i = 0; i < _arrays.size(); i++) {
661  indent(out, indent_level)
662  << "Array " << i << ":\n";
663  _arrays[i]->write(out, indent_level + 2);
664  }
665 
666  if (_animation.get_animation_type() != AT_none) {
667  indent(out, indent_level)
668  << "anim " << _animation << "\n";
669  }
670 }
671 
672 ////////////////////////////////////////////////////////////////////
673 // Function: GeomVertexFormat::write_with_data
674 // Access: Published
675 // Description:
676 ////////////////////////////////////////////////////////////////////
677 void GeomVertexFormat::
678 write_with_data(ostream &out, int indent_level,
679  const GeomVertexData *data) const {
680  indent(out, indent_level)
681  << data->get_num_rows() << " rows.\n";
682  for (size_t i = 0; i < _arrays.size(); i++) {
683  CPT(GeomVertexArrayDataHandle) handle = data->get_array(i)->get_handle();
684  const unsigned char *array_data = handle->get_read_pointer(true);
685  indent(out, indent_level)
686  << "Array " << i << " (" << (void *)array_data << ", "
687  << *_arrays[i] << "):\n";
688  _arrays[i]->write_with_data(out, indent_level + 2, data->get_array(i));
689  }
690 }
691 
692 ////////////////////////////////////////////////////////////////////
693 // Function: GeomVertexFormat::get_array_info
694 // Access: Public
695 // Description: Quickly looks up the indicated column within all
696 // of the nested arrays and sets array_index and
697 // column appropriately. Returns true if the data
698 // type exists in this format, false if it does not. If
699 // it returns false, array_index is set to -1, and
700 // column is set to NULL.
701 //
702 // This may only be called after the format has been
703 // registered.
704 ////////////////////////////////////////////////////////////////////
705 bool GeomVertexFormat::
706 get_array_info(const InternalName *name, int &array_index,
707  const GeomVertexColumn *&column) const {
708  nassertr(_is_registered, false);
709 
710  DataTypesByName::const_iterator ai;
711  ai = _columns_by_name.find(name);
712  if (ai != _columns_by_name.end()) {
713  array_index = (*ai).second._array_index;
714  column = _arrays[array_index]->get_column((*ai).second._column_index);
715  return true;
716  }
717 
718  array_index = -1;
719  column = NULL;
720 
721  return false;
722 }
723 
724 ////////////////////////////////////////////////////////////////////
725 // Function: GeomVertexFormat::compare_to
726 // Access: Public
727 // Description:
728 ////////////////////////////////////////////////////////////////////
729 int GeomVertexFormat::
730 compare_to(const GeomVertexFormat &other) const {
731  int compare = _animation.compare_to(other._animation);
732  if (compare != 0) {
733  return compare;
734  }
735 
736  if (_arrays.size() != other._arrays.size()) {
737  return (int)_arrays.size() - (int)other._arrays.size();
738  }
739 
740  for (size_t i = 0; i < _arrays.size(); i++) {
741  int compare = _arrays[i]->compare_to(*other._arrays[i]);
742  if (compare != 0) {
743  return compare;
744  }
745  }
746 
747  return 0;
748 }
749 
750 ////////////////////////////////////////////////////////////////////
751 // Function: GeomVertexFormat::make_registry
752 // Access: Private
753 // Description: Returns the global registry object.
754 ////////////////////////////////////////////////////////////////////
755 void GeomVertexFormat::
756 make_registry() {
757  if (_registry == (Registry *)NULL) {
758  _registry = new Registry;
759  _registry->make_standard_formats();
760  }
761 }
762 
763 ////////////////////////////////////////////////////////////////////
764 // Function: GeomVertexFormat::do_register
765 // Access: Private
766 // Description: Called internally when the format is registered.
767 ////////////////////////////////////////////////////////////////////
768 void GeomVertexFormat::
769 do_register() {
770  nassertv(!is_registered());
771  nassertv(_columns_by_name.empty());
772 
773  Arrays orig_arrays;
774  orig_arrays.swap(_arrays);
775  Arrays::const_iterator ai;
776  for (ai = orig_arrays.begin(); ai != orig_arrays.end(); ++ai) {
777  CPT(GeomVertexArrayFormat) array_format = (*ai);
778  if (!array_format->is_registered()) {
779  array_format = GeomVertexArrayFormat::register_format(array_format);
780  }
781 
782  // Let's keep arrays with nonzero stride but no used columns;
783  // they're needed to preserve the isomorphic nature of matching
784  // formats. But we'll toss arrays with 0 stride, which add
785  // nothing of value and only cause problems later.
786  if (array_format->get_stride() == 0) {
787  gobj_cat.warning()
788  << "Dropping empty array from GeomVertexFormat.\n";
789  continue;
790  }
791 
792  int array = (int)_arrays.size();
793  _arrays.push_back((GeomVertexArrayFormat *)array_format.p());
794 
795  // Now add the names to the index.
796  int num_columns = array_format->get_num_columns();
797  for (int i = 0; i < num_columns; i++) {
798  const GeomVertexColumn *column = array_format->get_column(i);
799  pair<DataTypesByName::iterator, bool> result;
800  result = _columns_by_name.insert(DataTypesByName::value_type(column->get_name(), DataTypeRecord()));
801  if (!result.second) {
802  gobj_cat.warning()
803  << "Column " << *column->get_name() << " repeated in format.\n";
804  } else {
805  DataTypeRecord &record = (*result.first).second;
806  record._array_index = array;
807  record._column_index = i;
808  }
809  }
810  }
811 
812  // Go back through the index now and identify the points, vectors,
813  // and morph descriptions, so we can quickly look these up later.
814  DataTypesByName::iterator ni;
815  for (ni = _columns_by_name.begin();
816  ni != _columns_by_name.end();
817  ++ni) {
818  const DataTypeRecord &record = (*ni).second;
819  const GeomVertexColumn *column = _arrays[record._array_index]->get_column(record._column_index);
820 
821  switch (column->get_contents()) {
822  case C_point:
823  // It's a point.
824  _points.push_back(column->get_name());
825  break;
826 
827  case C_vector:
828  case C_normal:
829  // It's a vector.
830  _vectors.push_back(column->get_name());
831  break;
832 
833  case C_texcoord:
834  // It's a texcoord.
835  _texcoords.push_back(column->get_name());
836  break;
837 
838  case C_morph_delta:
839  {
840  // It's a morph description.
841  MorphRecord morph;
842  morph._delta = column->get_name();
843 
844  // The delta name must be of the form "basename.morph.slidername".
845  int n = morph._delta->find_ancestor("morph");
846  if (n < 0) {
847  gobj_cat.warning()
848  << "vertex format defines " << *column->get_name()
849  << ", which is stored as a C_morph_delta, but its name does not include \"morph\".\n";
850  } else {
851  morph._slider = InternalName::make(morph._delta->get_net_basename(n - 1));
852  morph._base = morph._delta->get_ancestor(n + 1);
853 
854  if (_columns_by_name.find(morph._base) == _columns_by_name.end()) {
855  gobj_cat.warning()
856  << "vertex format defines "
857  << *column->get_name() << " but does not define "
858  << *morph._base << "\n";
859  } else {
860  _morphs.push_back(morph);
861  }
862  }
863  }
864  break;
865 
866  default:
867  // Some other type of value we don't care about caching a
868  // pointer to.
869  break;
870  }
871  }
872 
873  _is_registered = true;
874 
875  get_array_info(InternalName::get_vertex(), _vertex_array_index,
876  _vertex_column);
877  get_array_info(InternalName::get_normal(), _normal_array_index,
878  _normal_column);
879  get_array_info(InternalName::get_color(), _color_array_index,
880  _color_column);
881 }
882 
883 ////////////////////////////////////////////////////////////////////
884 // Function: GeomVertexFormat::do_unregister
885 // Access: Private
886 // Description: Called internally when the format is unregistered.
887 ////////////////////////////////////////////////////////////////////
888 void GeomVertexFormat::
889 do_unregister() {
890  nassertv(_is_registered);
891  _is_registered = false;
892 
893  _columns_by_name.clear();
894  _points.clear();
895  _vectors.clear();
896  _texcoords.clear();
897  _morphs.clear();
898 
899  if (_post_animated_format != (GeomVertexFormat *)NULL &&
900  _post_animated_format != this) {
901  unref_delete(_post_animated_format);
902  }
903  _post_animated_format = NULL;
904 }
905 
906 ////////////////////////////////////////////////////////////////////
907 // Function: GeomVertexFormat::register_with_read_factory
908 // Access: Public, Static
909 // Description: Tells the BamReader how to create objects of type
910 // GeomVertexFormat.
911 ////////////////////////////////////////////////////////////////////
912 void GeomVertexFormat::
913 register_with_read_factory() {
914  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
915 }
916 
917 ////////////////////////////////////////////////////////////////////
918 // Function: GeomVertexFormat::write_datagram
919 // Access: Public, Virtual
920 // Description: Writes the contents of this object to the datagram
921 // for shipping out to a Bam file.
922 ////////////////////////////////////////////////////////////////////
923 void GeomVertexFormat::
924 write_datagram(BamWriter *manager, Datagram &dg) {
926 
927  _animation.write_datagram(manager, dg);
928 
929  dg.add_uint16(_arrays.size());
930  Arrays::const_iterator ai;
931  for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
932  manager->write_pointer(dg, *ai);
933  }
934 }
935 
936 ////////////////////////////////////////////////////////////////////
937 // Function: GeomVertexFormat::complete_pointers
938 // Access: Public, Virtual
939 // Description: Receives an array of pointers, one for each time
940 // manager->read_pointer() was called in fillin().
941 // Returns the number of pointers processed.
942 ////////////////////////////////////////////////////////////////////
943 int GeomVertexFormat::
944 complete_pointers(TypedWritable **p_list, BamReader *manager) {
945  int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
946 
947  Arrays::iterator ai;
948  for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
949  (*ai) = DCAST(GeomVertexArrayFormat, p_list[pi++]);
950  }
951 
952  return pi;
953 }
954 
955 ////////////////////////////////////////////////////////////////////
956 // Function: GeomVertexFormat::make_from_bam
957 // Access: Protected, Static
958 // Description: This function is called by the BamReader's factory
959 // when a new object of type GeomVertexFormat is
960 // encountered in the Bam file. It should create the
961 // GeomVertexFormat and extract its information
962 // from the file.
963 ////////////////////////////////////////////////////////////////////
964 TypedWritable *GeomVertexFormat::
965 make_from_bam(const FactoryParams &params) {
966  GeomVertexFormat *object = new GeomVertexFormat;
967  DatagramIterator scan;
968  BamReader *manager;
969 
970  parse_params(params, scan, manager);
971  object->fillin(scan, manager);
972 
973  return object;
974 }
975 
976 ////////////////////////////////////////////////////////////////////
977 // Function: GeomVertexFormat::fillin
978 // Access: Protected
979 // Description: This internal function is called by make_from_bam to
980 // read in all of the relevant data from the BamFile for
981 // the new GeomVertexFormat.
982 ////////////////////////////////////////////////////////////////////
983 void GeomVertexFormat::
984 fillin(DatagramIterator &scan, BamReader *manager) {
986 
987  _animation.fillin(scan, manager);
988 
989  int num_arrays = scan.get_uint16();
990  _arrays.reserve(num_arrays);
991  for (int i = 0; i < num_arrays; i++) {
992  manager->read_pointer(scan);
993  _arrays.push_back(NULL);
994  }
995 }
996 
997 ////////////////////////////////////////////////////////////////////
998 // Function: GeomVertexFormat::Registry::Constructor
999 // Access: Public
1000 // Description:
1001 ////////////////////////////////////////////////////////////////////
1002 GeomVertexFormat::Registry::
1003 Registry() {
1004 }
1005 
1006 ////////////////////////////////////////////////////////////////////
1007 // Function: GeomVertexFormat::Registry::make_standard_formats
1008 // Access: Public
1009 // Description:
1010 ////////////////////////////////////////////////////////////////////
1011 void GeomVertexFormat::Registry::
1012 make_standard_formats() {
1013  _v3 = register_format(new GeomVertexArrayFormat
1014  (InternalName::get_vertex(), 3,
1015  NT_stdfloat, C_point));
1016 
1017  _v3n3 = register_format(new GeomVertexArrayFormat
1018  (InternalName::get_vertex(), 3,
1019  NT_stdfloat, C_point,
1020  InternalName::get_normal(), 3,
1021  NT_stdfloat, C_normal));
1022 
1023  _v3t2 = register_format(new GeomVertexArrayFormat
1024  (InternalName::get_vertex(), 3,
1025  NT_stdfloat, C_point,
1026  InternalName::get_texcoord(), 2,
1027  NT_stdfloat, C_texcoord));
1028 
1029  _v3n3t2 = register_format(new GeomVertexArrayFormat
1030  (InternalName::get_vertex(), 3,
1031  NT_stdfloat, C_point,
1032  InternalName::get_normal(), 3,
1033  NT_stdfloat, C_normal,
1034  InternalName::get_texcoord(), 2,
1035  NT_stdfloat, C_texcoord));
1036 
1037  // Define the DirectX-style packed color formats
1038  _v3cp = register_format(new GeomVertexArrayFormat
1039  (InternalName::get_vertex(), 3,
1040  NT_stdfloat, C_point,
1041  InternalName::get_color(), 1,
1042  NT_packed_dabc, C_color));
1043 
1044  _v3n3cp = register_format(new GeomVertexArrayFormat
1045  (InternalName::get_vertex(), 3,
1046  NT_stdfloat, C_point,
1047  InternalName::get_normal(), 3,
1048  NT_stdfloat, C_normal,
1049  InternalName::get_color(), 1,
1050  NT_packed_dabc, C_color));
1051 
1052  _v3cpt2 = register_format(new GeomVertexArrayFormat
1053  (InternalName::get_vertex(), 3,
1054  NT_stdfloat, C_point,
1055  InternalName::get_color(), 1,
1056  NT_packed_dabc, C_color,
1057  InternalName::get_texcoord(), 2,
1058  NT_stdfloat, C_texcoord));
1059 
1060  _v3n3cpt2 = register_format(new GeomVertexArrayFormat
1061  (InternalName::get_vertex(), 3,
1062  NT_stdfloat, C_point,
1063  InternalName::get_normal(), 3,
1064  NT_stdfloat, C_normal,
1065  InternalName::get_color(), 1,
1066  NT_packed_dabc, C_color,
1067  InternalName::get_texcoord(), 2,
1068  NT_stdfloat, C_texcoord));
1069 
1070  // Define the OpenGL-style per-byte color formats. This is not the
1071  // same as a packed format, above, because the resulting byte order
1072  // is endian-independent.
1073  _v3c4 = register_format(new GeomVertexArrayFormat
1074  (InternalName::get_vertex(), 3,
1075  NT_stdfloat, C_point,
1076  InternalName::get_color(), 4,
1077  NT_uint8, C_color));
1078 
1079  _v3n3c4 = register_format(new GeomVertexArrayFormat
1080  (InternalName::get_vertex(), 3,
1081  NT_stdfloat, C_point,
1082  InternalName::get_normal(), 3,
1083  NT_stdfloat, C_normal,
1084  InternalName::get_color(), 4,
1085  NT_uint8, C_color));
1086 
1087  _v3c4t2 = register_format(new GeomVertexArrayFormat
1088  (InternalName::get_vertex(), 3,
1089  NT_stdfloat, C_point,
1090  InternalName::get_color(), 4,
1091  NT_uint8, C_color,
1092  InternalName::get_texcoord(), 2,
1093  NT_stdfloat, C_texcoord));
1094 
1095  _v3n3c4t2 = register_format(new GeomVertexArrayFormat
1096  (InternalName::get_vertex(), 3,
1097  NT_stdfloat, C_point,
1098  InternalName::get_normal(), 3,
1099  NT_stdfloat, C_normal,
1100  InternalName::get_color(), 4,
1101  NT_uint8, C_color,
1102  InternalName::get_texcoord(), 2,
1103  NT_stdfloat, C_texcoord));
1104 }
1105 
1106 ////////////////////////////////////////////////////////////////////
1107 // Function: GeomVertexFormat::Registry::register_format
1108 // Access: Public
1109 // Description: Adds the indicated format to the registry, if there
1110 // is not an equivalent format already there; in either
1111 // case, returns the pointer to the equivalent format
1112 // now in the registry.
1113 //
1114 // This must be called before a format may be used in a
1115 // Geom. After this call, you should discard the
1116 // original pointer you passed in (which may or may not
1117 // now be invalid) and let its reference count decrement
1118 // normally; you should use only the returned value from
1119 // this point on.
1120 ////////////////////////////////////////////////////////////////////
1121 CPT(GeomVertexFormat) GeomVertexFormat::Registry::
1122 register_format(GeomVertexFormat *format) {
1123  if (format->is_registered()) {
1124  return format;
1125  }
1126 
1127  // Save the incoming pointer in a local PointerTo, so that if it has
1128  // a zero reference count and is not added into the map below, it
1129  // will be automatically deleted when this function returns.
1130  PT(GeomVertexFormat) pt_format = format;
1131 
1132  GeomVertexFormat *new_format;
1133  {
1134  LightReMutexHolder holder(_lock);
1135  Formats::iterator fi = _formats.insert(format).first;
1136  new_format = (*fi);
1137  if (!new_format->is_registered()) {
1138  new_format->do_register();
1139  if (new_format->get_num_arrays() == 0) {
1140  gobj_cat.warning()
1141  << "Empty GeomVertexFormat registered.\n";
1142  }
1143  }
1144  }
1145 
1146  return new_format;
1147 }
1148 
1149 ////////////////////////////////////////////////////////////////////
1150 // Function: GeomVertexFormat::Registry::unregister_format
1151 // Access: Public
1152 // Description: Removes the indicated format from the registry.
1153 // Normally this should not be done until the format is
1154 // destructing.
1155 //
1156 // The lock should be held prior to calling this method.
1157 ////////////////////////////////////////////////////////////////////
1158 void GeomVertexFormat::Registry::
1159 unregister_format(GeomVertexFormat *format) {
1160  nassertv(format->is_registered());
1161  Formats::iterator fi = _formats.find(format);
1162  nassertv(fi != _formats.end());
1163  _formats.erase(fi);
1164  format->do_unregister();
1165 }
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class&#39;s make_from_bam() method to read in all...
This defines how a single column is interleaved within a vertex array stored within a Geom...
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
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()...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
int get_num_rows() const
Returns the number of rows stored within all the arrays.
Similar to MutexHolder, but for a light reentrant mutex.
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:181
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
This is our own Panda specialization on the default STL set.
Definition: pset.h:52
A class to retrieve the individual data elements previously stored in a Datagram. ...
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
int get_total_bytes() const
Returns the number of bytes used by each element of the column: component_bytes * num_components...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
virtual bool unref() const
Explicitly decrements the reference count.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:279
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:658
int compare_to(const GeomVertexColumn &other) const
This is used to unquify columns, and hence formats, for the GeomVertexFormat registry.