Panda3D
Loading...
Searching...
No Matches
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 */
18INLINE const std::string &GeomVertexData::
19get_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 */
32INLINE GeomVertexData::UsageHint GeomVertexData::
33get_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 */
42get_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 */
52has_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 */
62get_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 */
97set_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 */
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 */
133reserve_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 */
143INLINE size_t GeomVertexData::
144get_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 */
154INLINE CPT(GeomVertexArrayData) GeomVertexData::
155get_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 */
164INLINE CPT(GeomVertexArrayDataHandle) GeomVertexData::
165get_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 */
181INLINE PT(GeomVertexArrayData) GeomVertexData::
182modify_array(size_t i) {
184 return writer.modify_array(i);
185}
186
187/**
188 * Equivalent to modify_array(i).modify_handle().
189 */
190INLINE PT(GeomVertexArrayDataHandle) GeomVertexData::
191modify_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 */
205INLINE void GeomVertexData::
206set_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 */
223get_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 */
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 */
247INLINE CPT(TransformBlendTable) GeomVertexData::
248get_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 */
257INLINE void GeomVertexData::
258clear_transform_blend_table() {
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 */
270INLINE const SliderTable *GeomVertexData::
271get_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 */
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 */
289INLINE int GeomVertexData::
290get_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 */
300get_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 */
308INLINE uint32_t GeomVertexData::
309pack_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 */
320INLINE unsigned int GeomVertexData::
321unpack_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 */
328INLINE unsigned int GeomVertexData::
329unpack_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 */
336INLINE unsigned int GeomVertexData::
337unpack_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 */
344INLINE unsigned int GeomVertexData::
345unpack_abcd_d(uint32_t data) {
346 return data & 0xff;
347}
348
349/**
350 * Packs three float values in an unsigned 32-bit int.
351 */
352INLINE uint32_t GeomVertexData::
353pack_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 */
409unpack_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 */
435unpack_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 */
461unpack_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 */
487INLINE int GeomVertexData::
488add_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 */
502INLINE GeomVertexData::CDataCache::
503CDataCache() {
504}
505
506/**
507 *
508 */
509INLINE GeomVertexData::CDataCache::
510CDataCache(const GeomVertexData::CDataCache &copy) :
511 _result(copy._result)
512{
513}
514
515/**
516 *
517 */
518INLINE GeomVertexData::CacheKey::
519CacheKey(const GeomVertexFormat *modifier) :
520 _modifier(modifier)
521{
522}
523
524/**
525 *
526 */
527INLINE GeomVertexData::CacheKey::
528CacheKey(const CacheKey &copy) :
529 _modifier(copy._modifier)
530{
531}
532
533/**
534 *
535 */
536INLINE GeomVertexData::CacheKey::
537CacheKey(CacheKey &&from) noexcept :
538 _modifier(std::move(from._modifier))
539{
540}
541
542/**
543 * Provides a unique ordering within the set.
544 */
546operator < (const CacheKey &other) const {
547 return _modifier < other._modifier;
548}
549
550/**
551 *
552 */
553INLINE GeomVertexData::CacheEntry::
554CacheEntry(GeomVertexData *source, const GeomVertexFormat *modifier) :
555 _source(source),
556 _key(modifier)
557{
558}
559
560/**
561 *
562 */
563INLINE GeomVertexData::CacheEntry::
564CacheEntry(GeomVertexData *source, const CacheKey &key) :
565 _source(source),
566 _key(key)
567{
568}
569
570/**
571 *
572 */
573INLINE GeomVertexData::CacheEntry::
574CacheEntry(GeomVertexData *source, CacheKey &&key) noexcept :
575 _source(source),
576 _key(std::move(key))
577{
578}
579
580/**
581 *
582 */
583INLINE GeomVertexData::CData::
584CData() :
585 _format(nullptr),
586 _usage_hint(UH_unspecified)
587{
588}
589
590/**
591 *
592 */
593INLINE GeomVertexData::CData::
594CData(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 */
607INLINE GeomVertexDataPipelineBase::
608GeomVertexDataPipelineBase(Thread *current_thread) :
609 _object(nullptr),
610 _current_thread(current_thread),
611 _cdata(nullptr)
612{
613}
614
615/**
616 *
617 */
618INLINE GeomVertexDataPipelineBase::
619GeomVertexDataPipelineBase(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 */
637INLINE 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 */
660INLINE Thread *GeomVertexDataPipelineBase::
661get_current_thread() const {
662 return _current_thread;
663}
664
665/**
666 *
667 */
668INLINE GeomVertexDataPipelineBase::UsageHint GeomVertexDataPipelineBase::
669get_usage_hint() const {
670 return _cdata->_usage_hint;
671}
672
673/**
674 *
675 */
676INLINE const GeomVertexFormat *GeomVertexDataPipelineBase::
677get_format() const {
678 return _cdata->_format;
679}
680
681/**
682 *
683 */
684INLINE bool GeomVertexDataPipelineBase::
685has_column(const InternalName *name) const {
686 return _cdata->_format->has_column(name);
687}
688
689/**
690 *
691 */
692INLINE size_t GeomVertexDataPipelineBase::
693get_num_arrays() const {
694 return _cdata->_arrays.size();
695}
696
697/**
698 *
699 */
700INLINE CPT(GeomVertexArrayData) GeomVertexDataPipelineBase::
701get_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 */
709INLINE const TransformTable *GeomVertexDataPipelineBase::
710get_transform_table() const {
711 return _cdata->_transform_table;
712}
713
714/**
715 *
716 */
717INLINE CPT(TransformBlendTable) GeomVertexDataPipelineBase::
718get_transform_blend_table() const {
719 return _cdata->_transform_blend_table.get_read_pointer();
720}
721
722/**
723 *
724 */
725INLINE const SliderTable *GeomVertexDataPipelineBase::
726get_slider_table() const {
727 return _cdata->_slider_table;
728}
729
730/**
731 *
732 */
733INLINE UpdateSeq GeomVertexDataPipelineBase::
734get_modified() const {
735 return _cdata->_modified;
736}
737
738/**
739 *
740 */
741INLINE GeomVertexDataPipelineReader::
742GeomVertexDataPipelineReader(Thread *current_thread) :
743 GeomVertexDataPipelineBase(current_thread),
744 _got_array_readers(false)
745{
746}
747
748/**
749 *
750 */
751INLINE GeomVertexDataPipelineReader::
752GeomVertexDataPipelineReader(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 */
763INLINE void GeomVertexDataPipelineReader::
764set_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 */
784INLINE const GeomVertexData *GeomVertexDataPipelineReader::
785get_object() const {
786 return _object;
787}
788
789/**
790 *
791 */
792INLINE void GeomVertexDataPipelineReader::
793check_array_readers() const {
794 if (!_got_array_readers) {
795 ((GeomVertexDataPipelineReader *)this)->make_array_readers();
796 }
797}
798
799/**
800 *
801 */
802INLINE const GeomVertexArrayDataHandle *GeomVertexDataPipelineReader::
803get_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 */
812INLINE bool GeomVertexDataPipelineReader::
813has_vertex() const {
814 return (_cdata->_format->get_vertex_column() != nullptr);
815}
816
817/**
818 *
819 */
820INLINE bool GeomVertexDataPipelineReader::
821is_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 */
833INLINE bool GeomVertexDataPipelineReader::
834has_normal() const {
835 return (_cdata->_format->get_normal_column() != nullptr);
836}
837
838/**
839 *
840 */
841INLINE bool GeomVertexDataPipelineReader::
842has_color() const {
843 return (_cdata->_format->get_color_column() != nullptr);
844}
845
846/**
847 *
848 */
849INLINE GeomVertexDataPipelineWriter::
850GeomVertexDataPipelineWriter(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 */
867INLINE GeomVertexDataPipelineWriter::
868~GeomVertexDataPipelineWriter() {
869 if (_got_array_writers) {
870 delete_array_writers();
871 }
872 _object->_cycler.release_write(_cdata);
873}
874
875/**
876 *
877 */
878INLINE GeomVertexData *GeomVertexDataPipelineWriter::
879get_object() const {
880 return _object;
881}
882
883/**
884 *
885 */
886INLINE void GeomVertexDataPipelineWriter::
887check_array_writers() const {
888 if (!_got_array_writers) {
889 ((GeomVertexDataPipelineWriter *)this)->make_array_writers();
890 }
891}
892
893/**
894 *
895 */
896INLINE GeomVertexArrayDataHandle *GeomVertexDataPipelineWriter::
897get_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
903INLINE std::ostream &
904operator << (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.
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...
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...