Panda3D
geomVertexData.I
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 geomVertexData.I
10  * @author drose
11  * @date 2005-03-06
12  */
13 
14 /**
15  * Returns the name passed to the constructor, if any. This name is reported
16  * on the PStats graph for vertex computations.
17  */
18 INLINE const std::string &GeomVertexData::
19 get_name() const {
20  return _name;
21 }
22 
23 /**
24  * Returns the usage hint that was passed to the constructor, and which will
25  * be passed to each array data object created initially, and arrays created
26  * as the result of a convert_to() operation. See geomEnums.h.
27  *
28  * However, each individual array may be replaced with a different array
29  * object with an independent usage hint specified, so there is no guarantee
30  * that the individual arrays all have the same usage_hint.
31  */
32 INLINE GeomVertexData::UsageHint GeomVertexData::
33 get_usage_hint() const {
34  CDReader cdata(_cycler);
35  return cdata->_usage_hint;
36 }
37 
38 /**
39  * Returns a pointer to the GeomVertexFormat structure that defines this data.
40  */
42 get_format() const {
43  CDReader cdata(_cycler);
44  return cdata->_format;
45 }
46 
47 /**
48  * Returns true if the data has the named column, false otherwise. This is
49  * really just a shortcut for asking the same thing from the format.
50  */
51 INLINE bool GeomVertexData::
52 has_column(const InternalName *name) const {
53  CDReader cdata(_cycler);
54  return cdata->_format->has_column(name);
55 }
56 
57 /**
58  * Returns the number of rows stored within all the arrays. All arrays store
59  * data for the same n rows.
60  */
61 INLINE int GeomVertexData::
62 get_num_rows() const {
63  CPT(GeomVertexArrayData) array;
64  {
65  CDReader cdata(_cycler);
66  nassertr(cdata->_format->get_num_arrays() == cdata->_arrays.size(), 0);
67 
68  if (cdata->_arrays.size() == 0) {
69  // No arrays means no rows. Weird but legal.
70  return 0;
71  }
72 
73  array = cdata->_arrays[0].get_read_pointer();
74  }
75 
76  return array->get_num_rows();
77 }
78 
79 /**
80  * Sets the length of the array to n rows in all of the various arrays
81  * (presumably by adding rows).
82  *
83  * The new vertex data is initialized to 0, except for the "color" column,
84  * which is initialized to (1, 1, 1, 1).
85  *
86  * The return value is true if the number of rows was changed, false if the
87  * object already contained n rows (or if there was some error).
88  *
89  * This can be used when you know exactly how many rows you will be needing.
90  * It is faster than reserve_num_rows(). Also see unclean_set_num_rows() if
91  * you are planning to fill in all the data yourself.
92  *
93  * Don't call this in a downstream thread unless you don't mind it blowing
94  * away other changes you might have recently made in an upstream thread.
95  */
96 INLINE bool GeomVertexData::
97 set_num_rows(int n) {
99  writer.check_array_writers();
100  return writer.set_num_rows(n);
101 }
102 
103 /**
104  * This method behaves like set_num_rows(), except the new data is not
105  * initialized. Furthermore, after this call, *any* of the data in the
106  * GeomVertexData may be uninitialized, including the earlier rows.
107  *
108  * This is intended for applications that are about to completely fill the
109  * GeomVertexData with new data anyway; it provides a tiny performance boost
110  * over set_num_rows().
111  *
112  * This can be used when you know exactly how many rows you will be needing.
113  * It is faster than reserve_num_rows().
114  */
115 INLINE bool GeomVertexData::
116 unclean_set_num_rows(int n) {
118  writer.check_array_writers();
119  return writer.unclean_set_num_rows(n);
120 }
121 
122 /**
123  * This ensures that enough memory space for n rows is allocated, so that you
124  * may increase the number of rows to n without causing a new memory
125  * allocation. This is a performance optimization only; it is especially
126  * useful when you know ahead of time that you will be adding n rows to the
127  * data.
128  *
129  * If you know exactly how many rows you will be needing, it is significantly
130  * faster to use set_num_rows() or unclean_set_num_rows() instead.
131  */
132 INLINE bool GeomVertexData::
133 reserve_num_rows(int n) {
135  writer.check_array_writers();
136  return writer.reserve_num_rows(n);
137 }
138 
139 /**
140  * Returns the number of individual arrays stored within the data. This must
141  * match get_format()->get_num_arrays().
142  */
143 INLINE size_t GeomVertexData::
144 get_num_arrays() const {
145  CDReader cdata(_cycler);
146  return cdata->_arrays.size();
147 }
148 
149 /**
150  * Returns a const pointer to the vertex data for the indicated array, for
151  * application code to directly examine (but not modify) the underlying vertex
152  * data.
153  */
154 INLINE CPT(GeomVertexArrayData) GeomVertexData::
155 get_array(size_t i) const {
156  CDReader cdata(_cycler);
157  nassertr(i < cdata->_arrays.size(), nullptr);
158  return cdata->_arrays[i].get_read_pointer();
159 }
160 
161 /**
162  * Equivalent to get_array(i).get_handle().
163  */
164 INLINE CPT(GeomVertexArrayDataHandle) GeomVertexData::
165 get_array_handle(size_t i) const {
166  Thread *current_thread = Thread::get_current_thread();
167  CDReader cdata(_cycler, current_thread);
168  nassertr(i < cdata->_arrays.size(), nullptr);
169  return new GeomVertexArrayDataHandle(cdata->_arrays[i].get_read_pointer(), current_thread);
170 }
171 
172 /**
173  * Returns a modifiable pointer to the indicated vertex array, so that
174  * application code may directly manipulate the data. You should avoid
175  * changing the length of this array, since all of the arrays should be kept
176  * in sync--use set_num_rows() instead.
177  *
178  * Don't call this in a downstream thread unless you don't mind it blowing
179  * away other changes you might have recently made in an upstream thread.
180  */
181 INLINE PT(GeomVertexArrayData) GeomVertexData::
182 modify_array(size_t i) {
184  return writer.modify_array(i);
185 }
186 
187 /**
188  * Equivalent to modify_array(i).modify_handle().
189  */
190 INLINE PT(GeomVertexArrayDataHandle) GeomVertexData::
191 modify_array_handle(size_t i) {
192  Thread *current_thread = Thread::get_current_thread();
193  GeomVertexDataPipelineWriter writer(this, true, current_thread);
194  return new GeomVertexArrayDataHandle(writer.modify_array(i), current_thread);
195 }
196 
197 /**
198  * Replaces the indicated vertex data array with a completely new array. You
199  * should be careful that the new array has the same length and format as the
200  * old one, unless you know what you are doing.
201  *
202  * Don't call this in a downstream thread unless you don't mind it blowing
203  * away other changes you might have recently made in an upstream thread.
204  */
205 INLINE void GeomVertexData::
206 set_array(size_t i, const GeomVertexArrayData *array) {
208  writer.set_array(i, array);
209 }
210 
211 /**
212  * Returns a const pointer to the TransformTable assigned to this data.
213  * Vertices within the table will index into this table to indicate their
214  * dynamic skinning information; this table is used when the vertex animation
215  * is to be performed by the graphics hardware (but also see
216  * get_transform_blend_table()).
217  *
218  * This will return NULL if the vertex data does not have a TransformTable
219  * assigned (which implies the vertices will not be animated by the graphics
220  * hardware).
221  */
222 INLINE const TransformTable *GeomVertexData::
223 get_transform_table() const {
224  CDReader cdata(_cycler);
225  return cdata->_transform_table;
226 }
227 
228 /**
229  * Sets the TransformTable pointer to NULL, removing the table from the vertex
230  * data. This disables hardware-driven vertex animation.
231  */
232 INLINE void GeomVertexData::
234  set_transform_table(nullptr);
235 }
236 
237 /**
238  * Returns a const pointer to the TransformBlendTable assigned to this data.
239  * Vertices within the table will index into this table to indicate their
240  * dynamic skinning information; this table is used when the vertex animation
241  * is to be performed by the CPU (but also see get_transform_table()).
242  *
243  * This will return NULL if the vertex data does not have a
244  * TransformBlendTable assigned (which implies the vertices will not be
245  * animated by the CPU).
246  */
247 INLINE CPT(TransformBlendTable) GeomVertexData::
248 get_transform_blend_table() const {
249  CDReader cdata(_cycler);
250  return cdata->_transform_blend_table.get_read_pointer();
251 }
252 
253 /**
254  * Sets the TransformBlendTable pointer to NULL, removing the table from the
255  * vertex data. This disables CPU-driven vertex animation.
256  */
257 INLINE void GeomVertexData::
258 clear_transform_blend_table() {
259  set_transform_blend_table(nullptr);
260 }
261 
262 /**
263  * Returns a const pointer to the SliderTable assigned to this data. Vertices
264  * within the vertex data will look up their morph offsets, if any, within
265  * this table.
266  *
267  * This will return NULL if the vertex data does not have a SliderTable
268  * assigned.
269  */
270 INLINE const SliderTable *GeomVertexData::
271 get_slider_table() const {
272  CDReader cdata(_cycler);
273  return cdata->_slider_table;
274 }
275 
276 /**
277  * Sets the SliderTable pointer to NULL, removing the table from the vertex
278  * data. This disables morph (blend shape) animation.
279  */
280 INLINE void GeomVertexData::
282  set_slider_table(nullptr);
283 }
284 
285 /**
286  * Returns the total number of bytes consumed by the different arrays of the
287  * vertex data.
288  */
289 INLINE int GeomVertexData::
290 get_num_bytes() const {
292  return reader.get_num_bytes();
293 }
294 
295 /**
296  * Returns a sequence number which is guaranteed to change at least every time
297  * the vertex data is modified.
298  */
300 get_modified(Thread *current_thread) const {
301  CDReader cdata(_cycler, current_thread);
302  return cdata->_modified;
303 }
304 
305 /**
306  * Packs four values in a DirectX-style NT_packed_abcd value.
307  */
308 INLINE uint32_t GeomVertexData::
309 pack_abcd(unsigned int a, unsigned int b,
310  unsigned int c, unsigned int d) {
311  return (((a & 0xff) << 24) |
312  ((b & 0xff) << 16) |
313  ((c & 0xff) << 8) |
314  (d & 0xff));
315 }
316 
317 /**
318  * Returns the first packed value from a DirectX-style NT_packed_abcd.
319  */
320 INLINE unsigned int GeomVertexData::
321 unpack_abcd_a(uint32_t data) {
322  return (data >> 24) & 0xff;
323 }
324 
325 /**
326  * Returns the second packed value from a DirectX-style NT_packed_abcd.
327  */
328 INLINE unsigned int GeomVertexData::
329 unpack_abcd_b(uint32_t data) {
330  return (data >> 16) & 0xff;
331 }
332 
333 /**
334  * Returns the third packed value from a DirectX-style NT_packed_abcd.
335  */
336 INLINE unsigned int GeomVertexData::
337 unpack_abcd_c(uint32_t data) {
338  return (data >> 8) & 0xff;
339 }
340 
341 /**
342  * Returns the fourth packed value from a DirectX-style NT_packed_abcd.
343  */
344 INLINE unsigned int GeomVertexData::
345 unpack_abcd_d(uint32_t data) {
346  return data & 0xff;
347 }
348 
349 /**
350  * Packs three float values in an unsigned 32-bit int.
351  */
352 INLINE uint32_t GeomVertexData::
353 pack_ufloat(float a, float b, float c) {
354  // Since we have to clamp both low exponents and negative numbers to 0, it's
355  // easier to see a float as having a 9-bit signed exponent.
356  union {
357  int32_t _packed;
358  float _float;
359  } f0, f1, f2;
360 
361  f0._float = a;
362  f1._float = b;
363  f2._float = c;
364 
365  // There are several cases here: 1. exponent 0xff: NaN or infinity (negative
366  // infinity excluded) 2. exponent too large: clamped to maximum value 3.
367  // normalized float 4. exponent 0: denormal float 5. zero or anything
368  // negative, clamped to 0
369 
370  uint32_t packed = 0;
371 
372  if ((f0._packed & 0x7f800000) == 0x7f800000 && (unsigned)f0._packed != 0xff800000u) {
373  packed |= (f0._packed >> 17) & 0x7ffu;
374  } else if (f0._packed >= 0x47800000) {
375  packed |= 0x7bf;
376  } else if (f0._packed >= 0x38800000) {
377  packed |= (f0._packed >> 17) - 0x1c00;
378  } else if (f0._packed >= 0x35000000) {
379  packed |= ((f0._packed & 0x7c0000u) | 0x800000u) >> (130 - (f0._packed >> 23));
380  }
381 
382  if ((f1._packed & 0x7f800000) == 0x7f800000 && (unsigned)f1._packed != 0xff800000u) {
383  packed |= (f1._packed >> 6) & 0x3ff800u;
384  } else if (f1._packed >= 0x47800000) {
385  packed |= 0x3df800;
386  } else if (f1._packed >= 0x38800000) {
387  packed |= ((f1._packed >> 6) - 0xe00000) & 0x3ff800;
388  } else if (f1._packed >= 0x35000000) {
389  packed |= (((f1._packed & 0x7c0000u) | 0x800000u) >> (119 - (f1._packed >> 23))) & 0x1f800u;
390  }
391 
392  if ((f2._packed & 0x7f800000) == 0x7f800000 && (unsigned)f2._packed != 0xff800000u) {
393  packed |= (f2._packed & 0x0ffe0000u) << 4;
394  } else if (f2._packed >= 0x47800000) {
395  packed |= 0xf7c00000;
396  } else if (f2._packed >= 0x38800000) {
397  packed |= ((f2._packed - 0x38000000) << 4) & 0xffc00000;
398  } else if (f2._packed >= 0x35000000) {
399  packed |= ((((f2._packed << 3) & 0x03c00000u) | 0x04000000u) >> (112 - (f2._packed >> 23))) & 0x07c00000u;
400  }
401 
402  return packed;
403 }
404 
405 /**
406  * Unpacks an unsigned float11 value from an uint32.
407  */
408 INLINE float GeomVertexData::
409 unpack_ufloat_a(uint32_t data) {
410  if ((data & 0x7c0) == 0) {
411  // Denormal float (includes zero).
412  return ldexpf((data & 63) / 64.0f, -14);
413  }
414 
415  union {
416  uint32_t _packed;
417  float _float;
418  } value;
419  value._packed = ((data & 0x7ff) << 17);
420 
421  if ((data & 0x7c0) == 0x7c0) {
422  // Infinity NaN
423  value._packed |= 0x7f800000;
424  } else {
425  value._packed += 0x38000000;
426  }
427 
428  return value._float;
429 }
430 
431 /**
432  * Unpacks an unsigned float11 value from an uint32.
433  */
434 INLINE float GeomVertexData::
435 unpack_ufloat_b(uint32_t data) {
436  if ((data & 0x3e0000) == 0) {
437  // Denormal float (includes zero).
438  return ldexpf(((data >> 11) & 63) / 64.0f, -14);
439  }
440 
441  union {
442  uint32_t _packed;
443  float _float;
444  } value;
445  value._packed = ((data & 0x3ff800) << 6);
446 
447  if ((data & 0x3e0000) == 0x3e0000) {
448  // Infinity NaN
449  value._packed |= 0x7f800000;
450  } else {
451  value._packed += 0x38000000;
452  }
453 
454  return value._float;
455 }
456 
457 /**
458  * Unpacks an unsigned float10 value from an uint32.
459  */
460 INLINE float GeomVertexData::
461 unpack_ufloat_c(uint32_t data) {
462  if ((data & 0xf8000000u) == 0) {
463  // Denormal float (includes zero).
464  return ldexpf(((data >> 22) & 31) / 32.0f, -14);
465  }
466 
467  union {
468  uint32_t _packed;
469  float _float;
470  } value;
471  value._packed = ((data & 0xffc00000u) >> 4);
472 
473  if ((data & 0xf8000000u) == 0xf8000000u) {
474  // Infinity NaN
475  value._packed |= 0x7f800000;
476  } else {
477  value._packed += 0x38000000;
478  }
479 
480  return value._float;
481 }
482 
483 /**
484  * Adds the indicated transform to the table, if it is not already there, and
485  * returns its index number.
486  */
487 INLINE int GeomVertexData::
488 add_transform(TransformTable *table, const VertexTransform *transform,
489  TransformMap &already_added) {
490  std::pair<TransformMap::iterator, bool> result = already_added.insert(TransformMap::value_type(transform, table->get_num_transforms()));
491 
492  if (result.second) {
493  table->add_transform(transform);
494  }
495 
496  return (*(result.first)).second;
497 }
498 
499 /**
500  *
501  */
502 INLINE GeomVertexData::CDataCache::
503 CDataCache() {
504 }
505 
506 /**
507  *
508  */
509 INLINE GeomVertexData::CDataCache::
510 CDataCache(const GeomVertexData::CDataCache &copy) :
511  _result(copy._result)
512 {
513 }
514 
515 /**
516  *
517  */
518 INLINE GeomVertexData::CacheKey::
519 CacheKey(const GeomVertexFormat *modifier) :
520  _modifier(modifier)
521 {
522 }
523 
524 /**
525  *
526  */
527 INLINE GeomVertexData::CacheKey::
528 CacheKey(const CacheKey &copy) :
529  _modifier(copy._modifier)
530 {
531 }
532 
533 /**
534  *
535  */
536 INLINE GeomVertexData::CacheKey::
537 CacheKey(CacheKey &&from) noexcept :
538  _modifier(std::move(from._modifier))
539 {
540 }
541 
542 /**
543  * Provides a unique ordering within the set.
544  */
546 operator < (const CacheKey &other) const {
547  return _modifier < other._modifier;
548 }
549 
550 /**
551  *
552  */
553 INLINE GeomVertexData::CacheEntry::
554 CacheEntry(GeomVertexData *source, const GeomVertexFormat *modifier) :
555  _source(source),
556  _key(modifier)
557 {
558 }
559 
560 /**
561  *
562  */
563 INLINE GeomVertexData::CacheEntry::
564 CacheEntry(GeomVertexData *source, const CacheKey &key) :
565  _source(source),
566  _key(key)
567 {
568 }
569 
570 /**
571  *
572  */
573 INLINE GeomVertexData::CacheEntry::
574 CacheEntry(GeomVertexData *source, CacheKey &&key) noexcept :
575  _source(source),
576  _key(std::move(key))
577 {
578 }
579 
580 /**
581  *
582  */
583 INLINE GeomVertexData::CData::
584 CData() :
585  _format(nullptr),
586  _usage_hint(UH_unspecified)
587 {
588 }
589 
590 /**
591  *
592  */
593 INLINE GeomVertexData::CData::
594 CData(const GeomVertexFormat *format, GeomVertexData::UsageHint usage_hint) :
595  _format(format),
596  _usage_hint(usage_hint)
597 {
598  size_t num_arrays = format->get_num_arrays();
599  for (size_t i = 0; i < num_arrays; ++i) {
600  _arrays.push_back(new GeomVertexArrayData(format->get_array(i), usage_hint));
601  }
602 }
603 
604 /**
605  *
606  */
607 INLINE GeomVertexDataPipelineBase::
608 GeomVertexDataPipelineBase(Thread *current_thread) :
609  _object(nullptr),
610  _current_thread(current_thread),
611  _cdata(nullptr)
612 {
613 }
614 
615 /**
616  *
617  */
618 INLINE GeomVertexDataPipelineBase::
619 GeomVertexDataPipelineBase(GeomVertexData *object,
620  Thread *current_thread,
621  GeomVertexData::CData *cdata) :
622  _object(object),
623  _current_thread(current_thread),
624  _cdata(cdata)
625 {
626 #ifdef _DEBUG
627  nassertv(_object->test_ref_count_nonzero());
628 #endif // _DEBUG
629 #ifdef DO_PIPELINING
630  _cdata->ref();
631 #endif // DO_PIPELINING
632 }
633 
634 /**
635  *
636  */
637 INLINE GeomVertexDataPipelineBase::
638 ~GeomVertexDataPipelineBase() {
639 #ifdef _DEBUG
640  if (_object != nullptr) {
641  nassertv(_object->test_ref_count_nonzero());
642  }
643 #endif // _DEBUG
644 
645 #ifdef DO_PIPELINING
646  if (_cdata != nullptr) {
647  unref_delete((CycleData *)_cdata);
648  }
649 #endif // DO_PIPELINING
650 
651 #ifdef _DEBUG
652  _object = nullptr;
653  _cdata = nullptr;
654 #endif // _DEBUG
655 }
656 
657 /**
658  *
659  */
660 INLINE Thread *GeomVertexDataPipelineBase::
661 get_current_thread() const {
662  return _current_thread;
663 }
664 
665 /**
666  *
667  */
668 INLINE GeomVertexDataPipelineBase::UsageHint GeomVertexDataPipelineBase::
669 get_usage_hint() const {
670  return _cdata->_usage_hint;
671 }
672 
673 /**
674  *
675  */
676 INLINE const GeomVertexFormat *GeomVertexDataPipelineBase::
677 get_format() const {
678  return _cdata->_format;
679 }
680 
681 /**
682  *
683  */
684 INLINE bool GeomVertexDataPipelineBase::
685 has_column(const InternalName *name) const {
686  return _cdata->_format->has_column(name);
687 }
688 
689 /**
690  *
691  */
692 INLINE size_t GeomVertexDataPipelineBase::
693 get_num_arrays() const {
694  return _cdata->_arrays.size();
695 }
696 
697 /**
698  *
699  */
700 INLINE CPT(GeomVertexArrayData) GeomVertexDataPipelineBase::
701 get_array(size_t i) const {
702  nassertr(i < _cdata->_arrays.size(), nullptr);
703  return _cdata->_arrays[i].get_read_pointer();
704 }
705 
706 /**
707  *
708  */
709 INLINE const TransformTable *GeomVertexDataPipelineBase::
710 get_transform_table() const {
711  return _cdata->_transform_table;
712 }
713 
714 /**
715  *
716  */
717 INLINE CPT(TransformBlendTable) GeomVertexDataPipelineBase::
718 get_transform_blend_table() const {
719  return _cdata->_transform_blend_table.get_read_pointer();
720 }
721 
722 /**
723  *
724  */
725 INLINE const SliderTable *GeomVertexDataPipelineBase::
726 get_slider_table() const {
727  return _cdata->_slider_table;
728 }
729 
730 /**
731  *
732  */
733 INLINE UpdateSeq GeomVertexDataPipelineBase::
734 get_modified() const {
735  return _cdata->_modified;
736 }
737 
738 /**
739  *
740  */
741 INLINE GeomVertexDataPipelineReader::
742 GeomVertexDataPipelineReader(Thread *current_thread) :
743  GeomVertexDataPipelineBase(current_thread),
744  _got_array_readers(false)
745 {
746 }
747 
748 /**
749  *
750  */
751 INLINE GeomVertexDataPipelineReader::
752 GeomVertexDataPipelineReader(const GeomVertexData *object,
753  Thread *current_thread) :
754  GeomVertexDataPipelineBase((GeomVertexData *)object, current_thread,
755  (GeomVertexData::CData *)object->_cycler.read_unlocked(current_thread)),
756  _got_array_readers(false)
757 {
758 }
759 
760 /**
761  *
762  */
763 INLINE void GeomVertexDataPipelineReader::
764 set_object(const GeomVertexData *object) {
765 #ifdef DO_PIPELINING
766  if (_cdata != nullptr) {
767  unref_delete((CycleData *)_cdata);
768  }
769 #endif // DO_PIPELINING
770  _array_readers.clear();
771 
772  _object = (GeomVertexData *)object;
773  _cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
774  _got_array_readers = false;
775 
776 #ifdef DO_PIPELINING
777  _cdata->ref();
778 #endif // DO_PIPELINING
779 }
780 
781 /**
782  *
783  */
784 INLINE const GeomVertexData *GeomVertexDataPipelineReader::
785 get_object() const {
786  return _object;
787 }
788 
789 /**
790  *
791  */
792 INLINE void GeomVertexDataPipelineReader::
793 check_array_readers() const {
794  if (!_got_array_readers) {
795  ((GeomVertexDataPipelineReader *)this)->make_array_readers();
796  }
797 }
798 
799 /**
800  *
801  */
802 INLINE const GeomVertexArrayDataHandle *GeomVertexDataPipelineReader::
803 get_array_reader(int i) const {
804  nassertr(_got_array_readers, nullptr);
805  nassertr(i >= 0 && i < (int)_array_readers.size(), nullptr);
806  return _array_readers[i];
807 }
808 
809 /**
810  *
811  */
812 INLINE bool GeomVertexDataPipelineReader::
813 has_vertex() const {
814  return (_cdata->_format->get_vertex_column() != nullptr);
815 }
816 
817 /**
818  *
819  */
820 INLINE bool GeomVertexDataPipelineReader::
821 is_vertex_transformed() const {
822  const GeomVertexColumn *column = _cdata->_format->get_vertex_column();
823  if (column != nullptr) {
824  return column->get_contents() == C_clip_point;
825  }
826 
827  return false;
828 }
829 
830 /**
831  *
832  */
833 INLINE bool GeomVertexDataPipelineReader::
834 has_normal() const {
835  return (_cdata->_format->get_normal_column() != nullptr);
836 }
837 
838 /**
839  *
840  */
841 INLINE bool GeomVertexDataPipelineReader::
842 has_color() const {
843  return (_cdata->_format->get_color_column() != nullptr);
844 }
845 
846 /**
847  *
848  */
849 INLINE GeomVertexDataPipelineWriter::
850 GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0,
851  Thread *current_thread) :
852  GeomVertexDataPipelineBase(object, current_thread,
853  object->_cycler.write_upstream(force_to_0, current_thread)),
854  _got_array_writers(false)
855 {
856 #ifdef _DEBUG
857  nassertv(_object->test_ref_count_nonzero());
858 #ifdef DO_PIPELINING
859  nassertv(_cdata->test_ref_count_nonzero());
860 #endif // DO_PIPELINING
861 #endif // _DEBUG
862 }
863 
864 /**
865  *
866  */
867 INLINE GeomVertexDataPipelineWriter::
868 ~GeomVertexDataPipelineWriter() {
869  if (_got_array_writers) {
870  delete_array_writers();
871  }
872  _object->_cycler.release_write(_cdata);
873 }
874 
875 /**
876  *
877  */
878 INLINE GeomVertexData *GeomVertexDataPipelineWriter::
879 get_object() const {
880  return _object;
881 }
882 
883 /**
884  *
885  */
886 INLINE void GeomVertexDataPipelineWriter::
887 check_array_writers() const {
888  if (!_got_array_writers) {
889  ((GeomVertexDataPipelineWriter *)this)->make_array_writers();
890  }
891 }
892 
893 /**
894  *
895  */
896 INLINE GeomVertexArrayDataHandle *GeomVertexDataPipelineWriter::
897 get_array_writer(size_t i) const {
898  nassertr(_got_array_writers, nullptr);
899  nassertr(i < _array_writers.size(), nullptr);
900  return _array_writers[i];
901 }
902 
903 INLINE std::ostream &
904 operator << (std::ostream &out, const GeomVertexData &obj) {
905  obj.output(out);
906  return out;
907 }
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:50
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
This is the data for one array of a GeomVertexData structure.
This defines how a single column is interleaved within a vertex array stored within a Geom.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
The common code from GeomVertexDataPipelineReader and GeomVertexDataPipelineWriter.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
bool operator<(const CacheKey &other) const
Provides a unique ordering within the set.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
bool set_num_rows(int n)
Sets the length of the array to n rows in all of the various arrays (presumably by adding rows).
static uint32_t pack_ufloat(float a, float b, float c)
Packs three float values in an unsigned 32-bit int.
get_name
Returns the name passed to the constructor, if any.
get_transform_table
Returns a const pointer to the TransformTable assigned to this data.
static float unpack_ufloat_c(uint32_t data)
Unpacks an unsigned float10 value from an uint32.
static float unpack_ufloat_a(uint32_t data)
Unpacks an unsigned float11 value from an uint32.
void clear_transform_table()
Sets the TransformTable pointer to NULL, removing the table from the vertex data.
bool has_column(const InternalName *name) const
Returns true if the data has the named column, false otherwise.
int get_num_rows() const
Returns the number of rows stored within all the arrays.
static float unpack_ufloat_b(uint32_t data)
Unpacks an unsigned float11 value from an uint32.
set_array
Replaces the indicated vertex data array with a completely new array.
bool reserve_num_rows(int n)
This ensures that enough memory space for n rows is allocated, so that you may increase the number of...
get_num_arrays
Returns the number of individual arrays stored within the data.
get_slider_table
Returns a const pointer to the SliderTable assigned to this data.
set_transform_table
Replaces the TransformTable on this vertex data with the indicated table.
static unsigned int unpack_abcd_b(uint32_t data)
Returns the second packed value from a DirectX-style NT_packed_abcd.
static unsigned int unpack_abcd_a(uint32_t data)
Returns the first packed value from a DirectX-style NT_packed_abcd.
set_slider_table
Replaces the SliderTable on this vertex data with the indicated table.
get_num_bytes
Returns the total number of bytes consumed by the different arrays of the vertex data.
void set_transform_blend_table(const TransformBlendTable *table)
Replaces the TransformBlendTable on this vertex data with the indicated table.
static uint32_t pack_abcd(unsigned int a, unsigned int b, unsigned int c, unsigned int d)
Packs four values in a DirectX-style NT_packed_abcd value.
get_modified
Returns a sequence number which is guaranteed to change at least every time the vertex data is modifi...
static unsigned int unpack_abcd_c(uint32_t data)
Returns the third packed value from a DirectX-style NT_packed_abcd.
static unsigned int unpack_abcd_d(uint32_t data)
Returns the fourth packed value from a DirectX-style NT_packed_abcd.
get_format
Returns a pointer to the GeomVertexFormat structure that defines this data.
get_usage_hint
Returns the usage hint that was passed to the constructor, and which will be passed to each array dat...
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
void clear_slider_table()
Sets the SliderTable pointer to NULL, removing the table from the vertex data.
This class defines the physical layout of the vertex data stored within a Geom.
get_num_arrays
Returns the number of individual arrays required by the format.
get_array
Returns the description of the nth array used by the format.
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
Stores the total set of VertexSliders that the vertices in a particular GeomVertexData object might d...
Definition: sliderTable.h:37
A thread; that is, a lightweight process.
Definition: thread.h:46
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
This structure collects together the different combinations of transforms and blend amounts used by a...
Stores the total set of VertexTransforms that the vertices in a particular GeomVertexData object migh...
size_t add_transform(const VertexTransform *transform)
Adds a new transform to the table and returns the index number of the new transform.
get_num_transforms
Returns the number of transforms in the table.
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
This is an abstract base class that holds a pointer to some transform, computed in some arbitrary way...
PT(GeomVertexArrayDataHandle) GeomVertexData
Equivalent to modify_array(i).modify_handle().
CPT(GeomVertexArrayData) GeomVertexData
Returns a const pointer to the vertex data for the indicated array, for application code to directly ...
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...