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  */
41 INLINE const GeomVertexFormat *GeomVertexData::
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) {
98  GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
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::
117  GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
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::
134  GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
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) {
183  GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
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) {
207  GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
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 {
291  GeomVertexDataPipelineReader reader(this, Thread::get_current_thread());
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  */
545 INLINE bool GeomVertexData::CacheKey::
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  _usage_hint(UH_unspecified)
586 {
587 }
588 
589 /**
590  *
591  */
592 INLINE GeomVertexData::CData::
593 CData(const GeomVertexFormat *format, GeomVertexData::UsageHint usage_hint) :
594  _format(format),
595  _usage_hint(usage_hint)
596 {
597  size_t num_arrays = format->get_num_arrays();
598  for (size_t i = 0; i < num_arrays; ++i) {
599  _arrays.push_back(new GeomVertexArrayData(format->get_array(i), usage_hint));
600  }
601 }
602 
603 /**
604  *
605  */
606 INLINE GeomVertexDataPipelineBase::
607 GeomVertexDataPipelineBase(Thread *current_thread) :
608  _object(nullptr),
609  _current_thread(current_thread),
610  _cdata(nullptr)
611 {
612 }
613 
614 /**
615  *
616  */
617 INLINE GeomVertexDataPipelineBase::
618 GeomVertexDataPipelineBase(GeomVertexData *object,
619  Thread *current_thread,
620  GeomVertexData::CData *cdata) :
621  _object(object),
622  _current_thread(current_thread),
623  _cdata(cdata)
624 {
625 #ifdef _DEBUG
626  nassertv(_object->test_ref_count_nonzero());
627 #endif // _DEBUG
628 #ifdef DO_PIPELINING
629  _cdata->ref();
630 #endif // DO_PIPELINING
631 }
632 
633 /**
634  *
635  */
636 INLINE GeomVertexDataPipelineBase::
637 ~GeomVertexDataPipelineBase() {
638 #ifdef _DEBUG
639  if (_object != nullptr) {
640  nassertv(_object->test_ref_count_nonzero());
641  }
642 #endif // _DEBUG
643 
644 #ifdef DO_PIPELINING
645  if (_cdata != nullptr) {
646  unref_delete((CycleData *)_cdata);
647  }
648 #endif // DO_PIPELINING
649 
650 #ifdef _DEBUG
651  _object = nullptr;
652  _cdata = nullptr;
653 #endif // _DEBUG
654 }
655 
656 /**
657  *
658  */
659 INLINE Thread *GeomVertexDataPipelineBase::
660 get_current_thread() const {
661  return _current_thread;
662 }
663 
664 /**
665  *
666  */
667 INLINE GeomVertexDataPipelineBase::UsageHint GeomVertexDataPipelineBase::
668 get_usage_hint() const {
669  return _cdata->_usage_hint;
670 }
671 
672 /**
673  *
674  */
675 INLINE const GeomVertexFormat *GeomVertexDataPipelineBase::
676 get_format() const {
677  return _cdata->_format;
678 }
679 
680 /**
681  *
682  */
683 INLINE bool GeomVertexDataPipelineBase::
684 has_column(const InternalName *name) const {
685  return _cdata->_format->has_column(name);
686 }
687 
688 /**
689  *
690  */
691 INLINE size_t GeomVertexDataPipelineBase::
692 get_num_arrays() const {
693  return _cdata->_arrays.size();
694 }
695 
696 /**
697  *
698  */
699 INLINE CPT(GeomVertexArrayData) GeomVertexDataPipelineBase::
700 get_array(size_t i) const {
701  nassertr(i < _cdata->_arrays.size(), nullptr);
702  return _cdata->_arrays[i].get_read_pointer();
703 }
704 
705 /**
706  *
707  */
708 INLINE const TransformTable *GeomVertexDataPipelineBase::
709 get_transform_table() const {
710  return _cdata->_transform_table;
711 }
712 
713 /**
714  *
715  */
716 INLINE CPT(TransformBlendTable) GeomVertexDataPipelineBase::
717 get_transform_blend_table() const {
718  return _cdata->_transform_blend_table.get_read_pointer();
719 }
720 
721 /**
722  *
723  */
724 INLINE const SliderTable *GeomVertexDataPipelineBase::
725 get_slider_table() const {
726  return _cdata->_slider_table;
727 }
728 
729 /**
730  *
731  */
732 INLINE UpdateSeq GeomVertexDataPipelineBase::
733 get_modified() const {
734  return _cdata->_modified;
735 }
736 
737 /**
738  *
739  */
740 INLINE GeomVertexDataPipelineReader::
741 GeomVertexDataPipelineReader(Thread *current_thread) :
742  GeomVertexDataPipelineBase(current_thread),
743  _got_array_readers(false)
744 {
745 }
746 
747 /**
748  *
749  */
750 INLINE GeomVertexDataPipelineReader::
751 GeomVertexDataPipelineReader(const GeomVertexData *object,
752  Thread *current_thread) :
753  GeomVertexDataPipelineBase((GeomVertexData *)object, current_thread,
754  (GeomVertexData::CData *)object->_cycler.read_unlocked(current_thread)),
755  _got_array_readers(false)
756 {
757 }
758 
759 /**
760  *
761  */
762 INLINE void GeomVertexDataPipelineReader::
763 set_object(const GeomVertexData *object) {
764 #ifdef DO_PIPELINING
765  if (_cdata != nullptr) {
766  unref_delete((CycleData *)_cdata);
767  }
768 #endif // DO_PIPELINING
769  _array_readers.clear();
770 
771  _object = (GeomVertexData *)object;
772  _cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
773  _got_array_readers = false;
774 
775 #ifdef DO_PIPELINING
776  _cdata->ref();
777 #endif // DO_PIPELINING
778 }
779 
780 /**
781  *
782  */
783 INLINE const GeomVertexData *GeomVertexDataPipelineReader::
784 get_object() const {
785  return _object;
786 }
787 
788 /**
789  *
790  */
791 INLINE void GeomVertexDataPipelineReader::
792 check_array_readers() const {
793  if (!_got_array_readers) {
794  ((GeomVertexDataPipelineReader *)this)->make_array_readers();
795  }
796 }
797 
798 /**
799  *
800  */
801 INLINE const GeomVertexArrayDataHandle *GeomVertexDataPipelineReader::
802 get_array_reader(int i) const {
803  nassertr(_got_array_readers, nullptr);
804  nassertr(i >= 0 && i < (int)_array_readers.size(), nullptr);
805  return _array_readers[i];
806 }
807 
808 /**
809  *
810  */
811 INLINE bool GeomVertexDataPipelineReader::
812 has_vertex() const {
813  return (_cdata->_format->get_vertex_column() != nullptr);
814 }
815 
816 /**
817  *
818  */
819 INLINE bool GeomVertexDataPipelineReader::
820 is_vertex_transformed() const {
821  const GeomVertexColumn *column = _cdata->_format->get_vertex_column();
822  if (column != nullptr) {
823  return column->get_contents() == C_clip_point;
824  }
825 
826  return false;
827 }
828 
829 /**
830  *
831  */
832 INLINE bool GeomVertexDataPipelineReader::
833 has_normal() const {
834  return (_cdata->_format->get_normal_column() != nullptr);
835 }
836 
837 /**
838  *
839  */
840 INLINE bool GeomVertexDataPipelineReader::
841 has_color() const {
842  return (_cdata->_format->get_color_column() != nullptr);
843 }
844 
845 /**
846  *
847  */
848 INLINE GeomVertexDataPipelineWriter::
849 GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0,
850  Thread *current_thread) :
851  GeomVertexDataPipelineBase(object, current_thread,
852  object->_cycler.write_upstream(force_to_0, current_thread)),
853  _got_array_writers(false)
854 {
855 #ifdef _DEBUG
856  nassertv(_object->test_ref_count_nonzero());
857 #ifdef DO_PIPELINING
858  nassertv(_cdata->test_ref_count_nonzero());
859 #endif // DO_PIPELINING
860 #endif // _DEBUG
861 }
862 
863 /**
864  *
865  */
866 INLINE GeomVertexDataPipelineWriter::
867 ~GeomVertexDataPipelineWriter() {
868  if (_got_array_writers) {
869  delete_array_writers();
870  }
871  _object->_cycler.release_write(_cdata);
872 }
873 
874 /**
875  *
876  */
877 INLINE GeomVertexData *GeomVertexDataPipelineWriter::
878 get_object() const {
879  return _object;
880 }
881 
882 /**
883  *
884  */
885 INLINE void GeomVertexDataPipelineWriter::
886 check_array_writers() const {
887  if (!_got_array_writers) {
888  ((GeomVertexDataPipelineWriter *)this)->make_array_writers();
889  }
890 }
891 
892 /**
893  *
894  */
895 INLINE GeomVertexArrayDataHandle *GeomVertexDataPipelineWriter::
896 get_array_writer(size_t i) const {
897  nassertr(_got_array_writers, nullptr);
898  nassertr(i < _array_writers.size(), nullptr);
899  return _array_writers[i];
900 }
901 
902 INLINE std::ostream &
903 operator << (std::ostream &out, const GeomVertexData &obj) {
904  obj.output(out);
905  return out;
906 }
set_transform_table
Replaces the TransformTable on this vertex data with the indicated table.
static unsigned int unpack_abcd_d(uint32_t data)
Returns the fourth packed value from a DirectX-style NT_packed_abcd.
The common code from GeomVertexDataPipelineReader and GeomVertexDataPipelineWriter.
get_num_transforms
Returns the number of transforms in the table.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
PT(GeomVertexArrayDataHandle) GeomVertexData
Equivalent to modify_array(i).modify_handle().
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:47
static unsigned int unpack_abcd_b(uint32_t data)
Returns the second packed value from a DirectX-style NT_packed_abcd.
get_modified
Returns a sequence number which is guaranteed to change at least every time the vertex data is modifi...
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
static unsigned int unpack_abcd_c(uint32_t data)
Returns the third packed value from a DirectX-style NT_packed_abcd.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
static float unpack_ufloat_a(uint32_t data)
Unpacks an unsigned float11 value from an uint32.
This defines how a single column is interleaved within a vertex array stored within a Geom.
set_array
Replaces the indicated vertex data array with a completely new array.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
void set_transform_blend_table(const TransformBlendTable *table)
Replaces the TransformBlendTable on this vertex data with the indicated table.
set_slider_table
Replaces the SliderTable on this vertex data with the indicated table.
Stores the total set of VertexSliders that the vertices in a particular GeomVertexData object might d...
Definition: sliderTable.h:37
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...
void clear_transform_table()
Sets the TransformTable pointer to NULL, removing the table from the vertex data.
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
static float unpack_ufloat_b(uint32_t data)
Unpacks an unsigned float11 value from an uint32.
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.
This is an abstract base class that holds a pointer to some transform, computed in some arbitrary way...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
get_num_arrays
Returns the number of individual arrays required by the format.
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).
void clear_slider_table()
Sets the SliderTable pointer to NULL, removing the table from the vertex data.
int get_num_rows() const
Returns the number of rows stored within all the arrays.
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
static uint32_t pack_ufloat(float a, float b, float c)
Packs three float values in an unsigned 32-bit int.
This class defines the physical layout of the vertex data stored within a Geom.
static unsigned int unpack_abcd_a(uint32_t data)
Returns the first packed value from a DirectX-style NT_packed_abcd.
Stores the total set of VertexTransforms that the vertices in a particular GeomVertexData object migh...
bool has_column(const InternalName *name) const
Returns true if the data has the named column, false otherwise.
A thread; that is, a lightweight process.
Definition: thread.h:46
bool operator<(const CacheKey &other) const
Provides a unique ordering within the set.
This structure collects together the different combinations of transforms and blend amounts used by a...
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
CPT(GeomVertexArrayData) GeomVertexData
Returns a const pointer to the vertex data for the indicated array, for application code to directly ...
This is a sequence number that increments monotonically.
Definition: updateSeq.h:37
static float unpack_ufloat_c(uint32_t data)
Unpacks an unsigned float10 value from an uint32.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
get_array
Returns the description of the nth array used by the format.
This is the data for one array of a GeomVertexData structure.
size_t add_transform(const VertexTransform *transform)
Adds a new transform to the table and returns the index number of the new transform.