Panda3D
Loading...
Searching...
No Matches
geomPrimitive.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 geomPrimitive.I
10 * @author drose
11 * @date 2005-03-06
12 */
13
14/**
15 * Returns the ShadeModel hint for this primitive. This is intended as a hint
16 * to the renderer to tell it how the per-vertex colors and normals are
17 * applied.
18 */
19INLINE GeomPrimitive::ShadeModel GeomPrimitive::
20get_shade_model() const {
21 CDReader cdata(_cycler);
22 return cdata->_shade_model;
23}
24
25/**
26 * Changes the ShadeModel hint for this primitive. This is different from the
27 * ShadeModelAttrib that might also be applied from the scene graph. This
28 * does not affect the shade model that is in effect when rendering, but
29 * rather serves as a hint to the renderer to tell it how the per-vertex
30 * colors and normals on this primitive are applied.
31 *
32 * Don't call this in a downstream thread unless you don't mind it blowing
33 * away other changes you might have recently made in an upstream thread.
34 */
35INLINE void GeomPrimitive::
36set_shade_model(GeomPrimitive::ShadeModel shade_model) {
37 CDWriter cdata(_cycler, true);
38 cdata->_shade_model = shade_model;
39}
40
41/**
42 * Returns the usage hint for this primitive. See geomEnums.h. This has
43 * nothing to do with the usage hint associated with the primitive's vertices;
44 * this only specifies how often the vertex indices that define the primitive
45 * will be modified.
46 *
47 * It is perfectly legal (and, in fact, common) for a GeomPrimitive to have
48 * UH_static on itself, while referencing vertex data with UH_dynamic. This
49 * means that the vertices themselves will be animated, but the primitive will
50 * always reference the same set of vertices from the pool.
51 */
52INLINE GeomPrimitive::UsageHint GeomPrimitive::
53get_usage_hint() const {
54 CDReader cdata(_cycler);
55 return cdata->_usage_hint;
56}
57
58/**
59 * Returns the numeric type of the index column. Normally, this will be
60 * either NT_uint16 or NT_uint32.
61 */
62INLINE GeomPrimitive::NumericType GeomPrimitive::
63get_index_type() const {
64 CDReader cdata(_cycler);
65 return cdata->_index_type;
66}
67
68/**
69 * Returns true if the primitive is a composite primitive such as a tristrip
70 * or trifan, or false if it is a fundamental primitive such as a collection
71 * of triangles.
72 */
73INLINE bool GeomPrimitive::
74is_composite() const {
75 return (get_num_vertices_per_primitive() == 0);
76}
77
78/**
79 * Returns true if the primitive is indexed, false otherwise. An indexed
80 * primitive stores a table of index numbers into its GeomVertexData, so that
81 * it can reference the vertices in any order. A nonindexed primitive, on the
82 * other hand, stores only the first vertex number and number of vertices
83 * used, so that it can only reference the vertices consecutively.
84 */
85INLINE bool GeomPrimitive::
86is_indexed() const {
87 CDReader cdata(_cycler);
88 return (!cdata->_vertices.is_null());
89}
90
91/**
92 * Returns the first vertex number referenced by the primitive. This is
93 * particularly important in the case of a nonindexed primitive, in which case
94 * get_first_vertex() and get_num_vertices() completely define the extent of
95 * the vertex range.
96 */
98get_first_vertex() const {
100 return reader.get_first_vertex();
101}
102
103/**
104 * Returns the number of indices used by all the primitives in this object.
105 */
106INLINE int GeomPrimitive::
107get_num_vertices() const {
109 return reader.get_num_vertices();
110}
111
112/**
113 * Returns the ith vertex index in the table.
114 */
115INLINE int GeomPrimitive::
116get_vertex(int i) const {
118 return reader.get_vertex(i);
119}
120
121/**
122 * Returns the number of individual primitives stored within this object. All
123 * primitives are the same type.
124 */
126get_num_primitives() const {
127 int num_vertices_per_primitive = get_num_vertices_per_primitive();
128
129 if (num_vertices_per_primitive == 0) {
130 // This is a complex primitive type like a triangle strip: each primitive
131 // uses a different number of vertices.
132 CDReader cdata(_cycler);
133 return cdata->_ends.size();
134
135 } else {
136 // This is a simple primitive type like a triangle: each primitive uses
137 // the same number of vertices.
138 return (get_num_vertices() / num_vertices_per_primitive);
139 }
140}
141
142/**
143 * Returns the number of triangles or other fundamental type (such as line
144 * segments) represented by all the primitives in this object.
145 */
147get_num_faces() const {
148 int num_vertices_per_primitive = get_num_vertices_per_primitive();
149
150 if (num_vertices_per_primitive == 0) {
151 int num_primitives = get_num_primitives();
152 int num_vertices = get_num_vertices();
153 int min_num_vertices_per_primitive = get_min_num_vertices_per_primitive();
154 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
155 return num_vertices - (num_primitives * (min_num_vertices_per_primitive - 1)) - ((num_primitives - 1) * num_unused_vertices_per_primitive);
156 } else {
157 return get_num_primitives();
158 }
159}
160
161/**
162 * Returns the number of triangles or other fundamental type (such as line
163 * segments) represented by the nth primitive in this object.
164 */
166get_primitive_num_faces(int n) const {
167 int num_vertices_per_primitive = get_num_vertices_per_primitive();
168
169 if (num_vertices_per_primitive == 0) {
171 } else {
172 return 1;
173 }
174}
175
176/**
177 * Returns the minimum vertex index number used by all the primitives in this
178 * object.
179 */
181get_min_vertex() const {
183 reader.check_minmax();
184 return reader.get_min_vertex();
185}
186
187/**
188 * Returns the maximum vertex index number used by all the primitives in this
189 * object.
190 */
192get_max_vertex() const {
194 reader.check_minmax();
195 return reader.get_max_vertex();
196}
197
198/**
199 * Returns the number of bytes stored in the vertices array.
200 */
201INLINE int GeomPrimitive::
202get_data_size_bytes() const {
203 CDReader cdata(_cycler);
204 nassertr(!cdata->_vertices.is_null(), 0);
205 return cdata->_vertices.get_read_pointer()->get_data_size_bytes();
206}
207
208/**
209 * Returns a sequence number which is guaranteed to change at least every time
210 * the vertex index array is modified.
211 */
213get_modified() const {
214 CDReader cdata(_cycler);
215 return cdata->_modified;
216}
217
218/**
219 * Verifies that the primitive only references vertices that actually exist
220 * within the indicated GeomVertexData. Returns true if the primitive appears
221 * to be valid, false otherwise.
222 */
224check_valid(const GeomVertexData *vertex_data) const {
225 Thread *current_thread = Thread::get_current_thread();
226 GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
227 data_reader.check_array_readers();
228 return check_valid(&data_reader);
229}
230
231/**
232 *
233 */
234INLINE bool GeomPrimitive::
235check_valid(const GeomVertexDataPipelineReader *data_reader) const {
236 GeomPrimitivePipelineReader reader(this, data_reader->get_current_thread());
237 reader.check_minmax();
238 return reader.check_valid(data_reader);
239}
240
241/**
242 * Returns a const pointer to the vertex index array so application code can
243 * read it directly. This might return NULL if the primitive is nonindexed.
244 * Do not attempt to modify the returned array; use modify_vertices() or
245 * set_vertices() for this.
246 *
247 * This method is intended for low-level usage only. There are higher-level
248 * methods for more common usage. We recommend you do not use this method
249 * directly. If you do, be sure you know what you are doing!
250 */
251INLINE CPT(GeomVertexArrayData) GeomPrimitive::
252get_vertices() const {
253 CDReader cdata(_cycler);
254 return cdata->_vertices.get_read_pointer();
255}
256
257/**
258 * Equivalent to get_vertices().get_handle().
259 */
260INLINE CPT(GeomVertexArrayDataHandle) GeomPrimitive::
261get_vertices_handle(Thread *current_thread) const {
262 CDReader cdata(_cycler, current_thread);
263 return new GeomVertexArrayDataHandle(cdata->_vertices.get_read_pointer(current_thread), current_thread);
264}
265
266/**
267 * Equivalent to modify_vertices().get_handle().
268 */
269INLINE PT(GeomVertexArrayDataHandle) GeomPrimitive::
270modify_vertices_handle(Thread *current_thread) {
271 CDWriter cdata(_cycler, true, current_thread);
272 return new GeomVertexArrayDataHandle(do_modify_vertices(cdata), current_thread);
273}
274
275/**
276 * A convenience function to return the gap between successive index numbers,
277 * in bytes, of the index data.
278 *
279 * This method is intended for low-level usage only. There are higher-level
280 * methods for more common usage. We recommend you do not use this method
281 * directly. If you do, be sure you know what you are doing!
282 */
283INLINE int GeomPrimitive::
284get_index_stride() const {
286 return reader.get_index_stride();
287}
288
289/**
290 * If relevant, returns the index value that may be used in some cases to
291 * signify the end of a primitive. This is typically the highest value that
292 * the numeric type can store.
293 */
294INLINE int GeomPrimitive::
295get_strip_cut_index() const {
296 CDReader cdata(_cycler);
297 return get_strip_cut_index(cdata->_index_type);
298}
299
300/**
301 * Returns a const pointer to the primitive ends array so application code can
302 * read it directly. Do not attempt to modify the returned array; use
303 * modify_ends() or set_ends() for this.
304 *
305 * Note that simple primitive types, like triangles, do not have a ends array:
306 * since all the primitives have the same number of vertices, it is not
307 * needed.
308 *
309 * This method is intended for low-level usage only. There are higher-level
310 * methods for more common usage. We recommend you do not use this method
311 * directly. If you do, be sure you know what you are doing!
312 */
314get_ends() const {
315 CDReader cdata(_cycler);
316 return cdata->_ends;
317}
318
319/**
320 * Returns a const pointer to the primitive mins array so application code can
321 * read it directly. Do not attempt to modify the returned array; use
322 * set_minmax() for this.
323 *
324 * Note that simple primitive types, like triangles, do not have a mins array.
325 *
326 * This method is intended for low-level usage only. There are higher-level
327 * methods for more common usage. We recommend you do not use this method
328 * directly. If you do, be sure you know what you are doing!
329 */
330INLINE CPT(GeomVertexArrayData) GeomPrimitive::
331get_mins() const {
333 reader.check_minmax();
334 return reader.get_mins();
335}
336
337/**
338 * Returns a const pointer to the primitive maxs array so application code can
339 * read it directly. Do not attempt to modify the returned array; use
340 * set_minmax().
341 *
342 * Note that simple primitive types, like triangles, do not have a maxs array.
343 *
344 * This method is intended for low-level usage only. There are higher-level
345 * methods for more common usage. We recommend you do not use this method
346 * directly. If you do, be sure you know what you are doing!
347 */
348INLINE CPT(GeomVertexArrayData) GeomPrimitive::
349get_maxs() const {
351 reader.check_minmax();
352 return reader.get_maxs();
353}
354
355/**
356 * Adds several vertices in a row.
357 */
358INLINE void GeomPrimitive::
359add_vertices(int v1, int v2) {
360 add_vertex(v1);
361 add_vertex(v2);
362}
363
364/**
365 * Adds several vertices in a row.
366 */
367INLINE void GeomPrimitive::
368add_vertices(int v1, int v2, int v3) {
369 add_vertex(v1);
370 add_vertex(v2);
371 add_vertex(v3);
372}
373
374/**
375 * Adds several vertices in a row.
376 */
377INLINE void GeomPrimitive::
378add_vertices(int v1, int v2, int v3, int v4) {
379 add_vertex(v1);
380 add_vertex(v2);
381 add_vertex(v3);
382 add_vertex(v4);
383}
384
385/**
386 * Returns a registered format appropriate for using to store the index table.
387 */
392
393/**
394 * Creates and returns a new, empty index table.
395 */
396INLINE PT(GeomVertexArrayData) GeomPrimitive::
397make_index_data() const {
399}
400
401/**
402 * Returns a registered format appropriate for using to store the index table.
403 */
404INLINE CPT(GeomVertexArrayFormat) GeomPrimitive::
405make_index_format(NumericType index_type) {
407 // It's important that the index format *not* respect the global setting of
408 // vertex-column-alignment. It needs to be tightly packed, so we specify an
409 // explict column_alignment of 1.
410 format->add_column(InternalName::get_index(), 1, index_type, C_index, 0, 1);
411 return GeomVertexArrayFormat::register_format(format);
412}
413
414/**
415 *
416 */
417INLINE GeomPrimitive::CData::
418CData() :
419 _shade_model(SM_smooth),
420 _first_vertex(0),
421 _num_vertices(0),
422 _index_type(NT_uint16),
423 _usage_hint(UH_unspecified),
424 _got_minmax(true),
425 _min_vertex(0),
426 _max_vertex(0)
427{
428}
429
430/**
431 *
432 */
433INLINE GeomPrimitive::CData::
434CData(const GeomPrimitive::CData &copy) :
435 _shade_model(copy._shade_model),
436 _first_vertex(copy._first_vertex),
437 _num_vertices(copy._num_vertices),
438 _index_type(copy._index_type),
439 _usage_hint(copy._usage_hint),
440 _vertices(copy._vertices),
441 _ends(copy._ends),
442 _mins(copy._mins),
443 _maxs(copy._maxs),
444 _modified(copy._modified),
445 _got_minmax(copy._got_minmax),
446 _min_vertex(copy._min_vertex),
447 _max_vertex(copy._max_vertex)
448{
449}
450/**
451 *
452 */
453INLINE GeomPrimitivePipelineReader::
454GeomPrimitivePipelineReader(CPT(GeomPrimitive) object,
455 Thread *current_thread) :
456 _object(std::move(object)),
457 _current_thread(current_thread),
458#ifndef CPPPARSER
459 _cdata(_object->_cycler.read_unlocked(current_thread)),
460#endif
461 _vertices_cdata(nullptr)
462{
463 nassertv(_object->test_ref_count_nonzero());
464#ifdef DO_PIPELINING
465 _cdata->ref();
466#endif // DO_PIPELINING
467
468 if (!_cdata->_vertices.is_null()) {
469 _vertices = _cdata->_vertices.get_read_pointer(current_thread);
470 _vertices_cdata = _vertices->_cycler.read_unlocked(current_thread);
471#ifdef DO_PIPELINING
472 _vertices_cdata->ref();
473#endif // DO_PIPELINING
474 // We must grab the lock *after* we have incremented the reference count,
475 // above.
476 _vertices_cdata->_rw_lock.acquire();
477 }
478}
479
480/**
481 *
482 */
483INLINE GeomPrimitivePipelineReader::
484~GeomPrimitivePipelineReader() {
485#ifdef _DEBUG
486 nassertv(_object->test_ref_count_nonzero());
487#endif // _DEBUG
488 // _object->_cycler.release_read(_cdata);
489
490#ifdef DO_PIPELINING
491 unref_delete((CycleData *)_cdata);
492#endif // DO_PIPELINING
493
494 if (_vertices_cdata != nullptr) {
495 // We must release the lock *before* we decrement the reference count,
496 // below.
497 _vertices_cdata->_rw_lock.release();
498
499#ifdef DO_PIPELINING
500 unref_delete((CycleData *)_vertices_cdata);
501#endif // DO_PIPELINING
502 }
503
504#ifdef _DEBUG
505 _object = nullptr;
506 _cdata = nullptr;
507#endif // _DEBUG
508}
509
510/**
511 *
512 */
513INLINE const GeomPrimitive *GeomPrimitivePipelineReader::
514get_object() const {
515 return _object;
516}
517
518/**
519 *
520 */
521INLINE Thread *GeomPrimitivePipelineReader::
522get_current_thread() const {
523 return _current_thread;
524}
525
526/**
527 *
528 */
529INLINE GeomPrimitivePipelineReader::ShadeModel GeomPrimitivePipelineReader::
530get_shade_model() const {
531 return _cdata->_shade_model;
532}
533
534/**
535 *
536 */
537INLINE GeomPrimitivePipelineReader::UsageHint GeomPrimitivePipelineReader::
538get_usage_hint() const {
539 return _cdata->_usage_hint;
540}
541
542/**
543 *
544 */
545INLINE GeomPrimitivePipelineReader::NumericType GeomPrimitivePipelineReader::
546get_index_type() const {
547 return _cdata->_index_type;
548}
549
550/**
551 *
552 */
553INLINE bool GeomPrimitivePipelineReader::
554is_indexed() const {
555 return (!_vertices.is_null());
556}
557
558/**
559 *
560 */
561INLINE int GeomPrimitivePipelineReader::
562get_num_vertices() const {
563 if (_cdata->_num_vertices != -1) {
564 return _cdata->_num_vertices;
565 } else {
566 nassertr(!_vertices.is_null(), 0);
567 size_t stride = _vertices->_array_format->get_stride();
568 nassertr(stride != 0, 0);
569 return get_data_size_bytes() / stride;
570 }
571}
572
573/**
574 *
575 */
576INLINE int GeomPrimitivePipelineReader::
577get_min_vertex() const {
578 nassertr(_cdata->_got_minmax, 0);
579 return _cdata->_min_vertex;
580}
581
582/**
583 *
584 */
585INLINE int GeomPrimitivePipelineReader::
586get_max_vertex() const {
587 nassertr(_cdata->_got_minmax, 0);
588 return _cdata->_max_vertex;
589}
590
591/**
592 * Returns the number of bytes stored in the vertices array.
593 */
595get_data_size_bytes() const {
596 return _vertices_cdata->_buffer.get_size();
597}
598
599/**
600 *
601 */
602INLINE UpdateSeq GeomPrimitivePipelineReader::
603get_modified() const {
604 return _cdata->_modified;
605}
606
607/**
608 *
609 */
610INLINE int GeomPrimitivePipelineReader::
611get_index_stride() const {
612 nassertr(is_indexed(), 0);
613 return _vertices->_array_format->get_stride();
614}
615
616/**
617 *
618 */
619INLINE const unsigned char *GeomPrimitivePipelineReader::
620get_read_pointer(bool force) const {
621 ((GeomVertexArrayData *)_vertices.p())->mark_used();
622 return _vertices_cdata->_buffer.get_read_pointer(force);
623}
624
625/**
626 *
627 */
628INLINE int GeomPrimitivePipelineReader::
629get_strip_cut_index() const {
630 return GeomPrimitive::get_strip_cut_index(_cdata->_index_type);
631}
632
633/**
634 *
635 */
636INLINE CPTA_int GeomPrimitivePipelineReader::
637get_ends() const {
638 return _cdata->_ends;
639}
640
641/**
642 *
643 */
644INLINE CPT(GeomVertexArrayData) GeomPrimitivePipelineReader::
645get_mins() const {
646 nassertr(is_indexed(), nullptr);
647 nassertr(_cdata->_got_minmax, nullptr);
648 return _cdata->_mins.get_read_pointer();
649}
650
651/**
652 *
653 */
654INLINE CPT(GeomVertexArrayData) GeomPrimitivePipelineReader::
655get_maxs() const {
656 nassertr(is_indexed(), nullptr);
657 nassertr(_cdata->_got_minmax, nullptr);
658 return _cdata->_maxs.get_read_pointer();
659}
660
661/**
662 *
663 */
664INLINE IndexBufferContext *GeomPrimitivePipelineReader::
665prepare_now(PreparedGraphicsObjects *prepared_objects,
666 GraphicsStateGuardianBase *gsg) const {
667 return ((GeomPrimitive *)_object.p())->prepare_now(prepared_objects, gsg);
668}
669
670/**
671 * Calls the appropriate method on the GSG to draw the primitive.
672 */
673INLINE bool GeomPrimitivePipelineReader::
674draw(GraphicsStateGuardianBase *gsg, bool force) const {
675 return _object->draw(gsg, this, force);
676}
677
678INLINE std::ostream &
679operator << (std::ostream &out, const GeomPrimitive &obj) {
680 obj.output(out);
681 return out;
682}
Similar to PointerToArray, except that its contents may not be modified.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A single page of data maintained by a PipelineCycler.
Definition cycleData.h:50
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
int get_data_size_bytes() const
Returns the number of bytes stored in the vertices array.
void check_minmax() const
Ensures that the primitive's minmax cache has been computed.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
get_data_size_bytes
Returns the number of bytes stored in the vertices array.
get_min_num_vertices_per_primitive
Returns the minimum number of vertices that must be added before close_primitive() may legally be cal...
int get_primitive_num_faces(int n) const
Returns the number of triangles or other fundamental type (such as line segments) represented by the ...
int get_max_vertex() const
Returns the maximum vertex index number used by all the primitives in this object.
int get_num_primitives() const
Returns the number of individual primitives stored within this object.
CPTA_int get_ends() const
Returns a const pointer to the primitive ends array so application code can read it directly.
get_modified
Returns a sequence number which is guaranteed to change at least every time the vertex index array is...
get_vertex
Returns the ith vertex index in the table.
int get_num_faces() const
Returns the number of triangles or other fundamental type (such as line segments) represented by all ...
get_usage_hint
Returns the usage hint for this primitive.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
bool check_valid(const GeomVertexData *vertex_data) const
Verifies that the primitive only references vertices that actually exist within the indicated GeomVer...
bool is_composite() const
Returns true if the primitive is a composite primitive such as a tristrip or trifan,...
get_strip_cut_index
Returns the index of the indicated type that is reserved for use as a strip cut index,...
int get_first_vertex() const
Returns the first vertex number referenced by the primitive.
void set_shade_model(ShadeModel shade_model)
Changes the ShadeModel hint for this primitive.
get_index_type
Returns the numeric type of the index column.
const GeomVertexArrayFormat * get_index_format() const
Returns a registered format appropriate for using to store the index table.
get_num_unused_vertices_per_primitive
Returns the number of vertices that are added between primitives that aren't, strictly speaking,...
get_index_stride
A convenience function to return the gap between successive index numbers, in bytes,...
get_num_vertices_per_primitive
If the primitive type is a simple type in which all primitives have the same number of vertices,...
int get_min_vertex() const
Returns the minimum vertex index number used by all the primitives in this object.
get_shade_model
Returns the ShadeModel hint for this primitive.
int get_primitive_num_vertices(int n) const
Returns the number of vertices used by the nth primitive.
void add_vertex(int vertex)
Adds the indicated vertex to the list of vertex indices used by the graphics primitive type.
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
This is the data for one array of a GeomVertexData structure.
This describes the structure of a single array within a Geom data.
int add_column(CPT_InternalName name, int num_components, NumericType numeric_type, Contents contents, int start=-1, int column_alignment=0)
Adds a new column to the specification.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
This is a special class object that holds all the information returned by a particular GSG to indicat...
A table of objects that are saved within the graphics context for reference by handle later.
void release() const
Releases the reMutex.
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 is a sequence number that increments monotonically.
Definition updateSeq.h:37
const unsigned char * get_read_pointer(bool force) const
Returns a read-only pointer to the raw data, or NULL if the data is not currently resident.
size_t get_size() const
Returns the number of bytes in the buffer.
STL namespace.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...