39 TypeHandle GeomPrimitivePipelineReader::_type_handle;
41 PStatCollector GeomPrimitive::_decompose_pcollector(
"*:Munge:Decompose");
42 PStatCollector GeomPrimitive::_doubleside_pcollector(
"*:Munge:Doubleside");
43 PStatCollector GeomPrimitive::_reverse_pcollector(
"*:Munge:Reverse");
44 PStatCollector GeomPrimitive::_rotate_pcollector(
"*:Munge:Rotate");
65 GeomPrimitive(GeomPrimitive::UsageHint usage_hint) {
66 CDWriter cdata(_cycler,
true);
67 cdata->_usage_hint = usage_hint;
87 CopyOnWriteObject::operator = (copy);
88 _cycler = copy._cycler;
106 return GR_indexed_other;
121 cdata->_usage_hint = usage_hint;
123 if (!cdata->_vertices.is_null()) {
125 cdata->_usage_hint = usage_hint;
143 nassertv(
get_max_vertex() <= get_highest_index_value(index_type));
146 if (cdata->_index_type != index_type) {
147 do_set_index_type(cdata, index_type);
164 if (gobj_cat.is_spam()) {
166 <<
this <<
".add_vertex(" << vertex <<
")\n";
169 consider_elevate_index_type(cdata, vertex);
171 if (requires_unused_vertices()) {
173 if (num_primitives > 0 &&
177 if (cdata->_vertices.is_null()) {
178 do_make_indexed(cdata);
180 append_unused_vertices(cdata->_vertices.get_write_pointer(), vertex);
184 if (cdata->_vertices.is_null()) {
187 nassertv(cdata->_num_vertices != -1);
188 if (cdata->_num_vertices == 0) {
189 cdata->_first_vertex = vertex;
190 cdata->_num_vertices = 1;
192 cdata->_got_minmax =
false;
195 }
else if (vertex == cdata->_first_vertex + cdata->_num_vertices) {
196 ++cdata->_num_vertices;
198 cdata->_got_minmax =
false;
203 do_make_indexed(cdata);
209 int num_rows = handle.get_num_rows();
210 handle.set_num_rows(num_rows + 1);
213 switch (cdata->_index_type) {
214 case GeomEnums::NT_uint8:
215 ((uint8_t *)ptr)[num_rows] = vertex;
217 case GeomEnums::NT_uint16:
218 ((uint16_t *)ptr)[num_rows] = vertex;
220 case GeomEnums::NT_uint32:
221 ((uint32_t *)ptr)[num_rows] = vertex;
224 nassert_raise(
"unsupported index type");
230 cdata->_got_minmax =
false;
242 if (num_vertices == 0) {
245 int end = (start + num_vertices) - 1;
249 consider_elevate_index_type(cdata, end);
252 if (num_primitives > 0 &&
256 if (cdata->_vertices.is_null()) {
257 do_make_indexed(cdata);
259 append_unused_vertices(cdata->_vertices.get_write_pointer(), start);
262 if (cdata->_vertices.is_null()) {
265 nassertv(cdata->_num_vertices != -1);
266 if (cdata->_num_vertices == 0) {
267 cdata->_first_vertex = start;
268 cdata->_num_vertices = num_vertices;
270 cdata->_got_minmax =
false;
273 }
else if (start == cdata->_first_vertex + cdata->_num_vertices) {
274 cdata->_num_vertices += num_vertices;
276 cdata->_got_minmax =
false;
281 do_make_indexed(cdata);
285 int old_num_rows = array_obj->get_num_rows();
286 array_obj->set_num_rows(old_num_rows + num_vertices);
291 for (
int v = start; v <= end; ++v) {
296 cdata->_got_minmax =
false;
334 if (gobj_cat.is_debug()) {
336 <<
this <<
".reserve_num_vertices(" << num_vertices <<
")\n";
340 consider_elevate_index_type(cdata, num_vertices);
341 do_make_indexed(cdata);
343 array_obj->reserve_num_rows(num_vertices);
359 if (num_vertices_per_primitive == 0) {
364 if (cdata->_ends.empty()) {
372 if (cdata->_ends.get_ref_count() > 1) {
374 new_ends.v() = cdata->_ends.v();
375 cdata->_ends = new_ends;
388 nassertr((num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0,
false)
407 cdata->_first_vertex = 0;
408 cdata->_num_vertices = 0;
413 cdata->_index_type = NT_uint16;
415 cdata->_vertices.clear();
416 cdata->_ends.clear();
417 cdata->_mins.clear();
418 cdata->_maxs.clear();
420 cdata->_got_minmax =
false;
438 if (!cdata->_got_minmax) {
439 recompute_minmax(cdata);
440 nassertv(cdata->_got_minmax);
443 consider_elevate_index_type(cdata, cdata->_max_vertex + offset);
449 size_t num_rows = (size_t)handle.get_num_rows();
451 switch (cdata->_index_type) {
452 case GeomEnums::NT_uint8:
453 for (
size_t i = 0; i < num_rows; ++i) {
454 uint8_t &v = ((uint8_t *)ptr)[i];
461 case GeomEnums::NT_uint16:
462 for (
size_t i = 0; i < num_rows; ++i) {
463 uint16_t &v = ((uint16_t *)ptr)[i];
470 case GeomEnums::NT_uint32:
471 for (
size_t i = 0; i < num_rows; ++i) {
472 uint32_t &v = ((uint32_t *)ptr)[i];
473 if (v != 0xffffffff) {
480 nassert_raise(
"unsupported index type");
486 cdata->_got_minmax =
false;
491 cdata->_first_vertex += offset;
493 cdata->_got_minmax =
false;
495 consider_elevate_index_type(cdata,
496 cdata->_first_vertex + cdata->_num_vertices - 1);
513 if (offset == 0 || end_row <= begin_row) {
517 nassertv(begin_row >= 0 && end_row >= 0);
535 for (
int j = begin_row; j < end_row; ++j) {
537 if (vertex != strip_cut_index) {
538 max_vertex = max(max_vertex, vertex);
543 consider_elevate_index_type(cdata, max_vertex + offset);
550 switch (cdata->_index_type) {
551 case GeomEnums::NT_uint8:
552 for (
int i = begin_row; i < end_row; ++i) {
553 uint8_t &v = ((uint8_t *)ptr)[i];
560 case GeomEnums::NT_uint16:
561 for (
int i = begin_row; i < end_row; ++i) {
562 uint16_t &v = ((uint16_t *)ptr)[i];
569 case GeomEnums::NT_uint32:
570 for (
int i = begin_row; i < end_row; ++i) {
571 uint32_t &v = ((uint32_t *)ptr)[i];
572 if (v != 0xffffffff) {
579 nassert_raise(
"unsupported index type");
585 cdata->_got_minmax =
false;
592 cdata->_first_vertex += offset;
594 cdata->_got_minmax =
false;
596 consider_elevate_index_type(cdata,
597 cdata->_first_vertex + cdata->_num_vertices - 1);
610 int num_vertices, dest_start;
613 num_vertices = reader.get_num_vertices();
614 int strip_cut_index = reader.get_strip_cut_index();
617 data_writer.check_array_writers();
618 dest_start = data_writer.get_num_rows();
619 data_writer.set_num_rows(dest_start + num_vertices);
622 data_reader.check_array_readers();
624 for (
int i = 0; i < num_vertices; ++i) {
626 nassertd(v != strip_cut_index)
continue;
652 CopiedIndices copied_indices;
658 for (
int i = 0; i < num_vertices; ++i) {
660 if (v == strip_cut_index) {
666 std::pair<CopiedIndices::iterator, bool> result =
667 copied_indices.insert(CopiedIndices::value_type(v, (
int)copied_indices.size()));
668 int v2 = (*result.first).second + dest_start;
694 do_make_indexed(cdata);
712 if (num_vertices_per_primitive == 0) {
716 nassertr(n >= 0 && n <= (
int)cdata->_ends.size(), -1);
720 return cdata->_ends[n - 1] + num_unused_vertices_per_primitive;
726 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive);
738 if (num_vertices_per_primitive == 0) {
742 nassertr(n >= 0 && n < (
int)cdata->_ends.size(), -1);
743 return cdata->_ends[n];
749 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive) + num_vertices_per_primitive;
761 if (num_vertices_per_primitive == 0) {
765 nassertr(n >= 0 && n < (
int)cdata->_ends.size(), 0);
767 return cdata->_ends[0];
770 return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive;
776 return num_vertices_per_primitive;
790 if (num_primitives > 0) {
806 nassertr(n >= 0 && n < mins->get_num_rows(), -1);
824 nassertr(n >= 0 && n < maxs->get_num_rows(), -1);
846 if (gobj_cat.is_debug()) {
848 <<
"Decomposing " << get_type() <<
": " << (
void *)
this <<
"\n";
852 return decompose_impl();
866 if (gobj_cat.is_debug()) {
868 <<
"Rotating " << get_type() <<
": " << (
void *)
this <<
"\n";
874 if (rotated_vertices ==
nullptr) {
880 new_prim->set_vertices(rotated_vertices);
883 case SM_flat_first_vertex:
884 new_prim->set_shade_model(SM_flat_last_vertex);
887 case SM_flat_last_vertex:
888 new_prim->set_shade_model(SM_flat_first_vertex);
910 if (gobj_cat.is_debug()) {
912 <<
"Doublesiding " << get_type() <<
": " << (
void *)
this <<
"\n";
916 return doubleside_impl();
931 if (gobj_cat.is_debug()) {
933 <<
"Reversing " << get_type() <<
": " << (
void *)
this <<
"\n";
937 return reverse_impl();
949 match_shade_model(GeomPrimitive::ShadeModel shade_model)
const {
951 if (this_shade_model == shade_model) {
956 if (this_shade_model == SM_uniform || shade_model == SM_uniform) {
961 if ((this_shade_model == SM_flat_first_vertex && shade_model == SM_flat_last_vertex) ||
962 (this_shade_model == SM_flat_last_vertex && shade_model == SM_flat_first_vertex)) {
965 if (rotated.p() ==
this) {
983 make_points()
const {
993 reader.get_referenced_vertices(bits);
1004 new_index.set_data1i(p);
1015 points->set_vertices(new_vertices);
1026 make_lines()
const {
1031 PrimitiveType prim_type = get_primitive_type();
1032 if (prim_type == PT_lines) {
1036 }
else if (prim_type != PT_polygons && prim_type != PT_patches) {
1041 if (prim_type == PT_polygons && !
is_exact_type(GeomTriangles::get_class_type())) {
1044 return decompose()->make_lines();
1052 new_vertices->unclean_set_num_rows(num_primitives * verts_per_prim * 2);
1056 for (
int i = 0; i < num_primitives; ++i) {
1062 for (
int vi = begin; vi < end - 1; vi++) {
1071 lines->set_vertices(new_vertices);
1086 make_patches()
const {
1092 int num_vertices_per_patch = prim->get_num_vertices_per_primitive();
1096 if (prim->is_indexed()) {
1097 patches->set_vertices(prim->get_vertices());
1099 patches->set_nonindexed_vertices(prim->get_first_vertex(),
1100 prim->get_num_vertices());
1113 make_adjacency()
const {
1122 get_num_bytes()
const {
1123 CDReader cdata(_cycler);
1124 int num_bytes = cdata->_ends.size() *
sizeof(int) +
sizeof(
GeomPrimitive);
1125 if (!cdata->_vertices.is_null()) {
1126 num_bytes += cdata->_vertices.get_read_pointer()->get_data_size_bytes();
1137 bool GeomPrimitive::
1138 request_resident(
Thread *current_thread)
const {
1139 CDReader cdata(_cycler, current_thread);
1141 bool resident =
true;
1143 if (!cdata->_vertices.is_null() &&
1144 !cdata->_vertices.get_read_pointer(current_thread)->request_resident(current_thread)) {
1149 if (!cdata->_mins.is_null() &&
1150 !cdata->_mins.get_read_pointer(current_thread)->request_resident(current_thread)) {
1153 if (!cdata->_maxs.is_null() &&
1154 !cdata->_maxs.get_read_pointer(current_thread)->request_resident(current_thread)) {
1165 void GeomPrimitive::
1166 output(std::ostream &out)
const {
1174 void GeomPrimitive::
1175 write(std::ostream &out,
int indent_level)
const {
1176 indent(out, indent_level)
1179 out <<
" (indexed)";
1181 out <<
" (nonindexed)";
1187 for (
int i = 0; i < num_primitives; ++i) {
1188 indent(out, indent_level + 2)
1192 for (
int vi = begin; vi < end; vi++) {
1196 if (end < num_vertices) {
1197 for (
int ui = 0; ui < num_unused_vertices_per_primitive; ++ui) {
1198 if (end + ui < num_vertices) {
1229 modify_vertices(
int num_vertices) {
1230 CDWriter cdata(_cycler,
true);
1232 cdata->_num_vertices = num_vertices;
1256 cdata->_num_vertices = num_vertices;
1261 cdata->_index_type = format->
get_column(0)->get_numeric_type();
1264 cdata->_got_minmax =
false;
1280 nassertv(num_vertices != -1);
1282 cdata->_vertices =
nullptr;
1283 cdata->_first_vertex = first_vertex;
1284 cdata->_num_vertices = num_vertices;
1287 cdata->_got_minmax =
false;
1290 recompute_minmax(cdata);
1314 cdata->_got_minmax =
false;
1316 if (cdata->_ends.get_ref_count() > 1) {
1318 new_ends.v() = cdata->_ends.v();
1319 cdata->_ends = new_ends;
1321 return cdata->_ends;
1343 cdata->_ends = ends;
1346 cdata->_got_minmax =
false;
1368 cdata->_min_vertex = min_vertex;
1369 cdata->_max_vertex = max_vertex;
1370 cdata->_mins = mins;
1371 cdata->_maxs = maxs;
1374 cdata->_got_minmax =
true;
1388 cdata->_got_minmax =
false;
1456 Contexts::const_iterator ci;
1457 ci = _contexts.find(prepared_objects);
1458 if (ci != _contexts.end()) {
1480 Contexts::const_iterator ci;
1481 ci = _contexts.find(prepared_objects);
1482 if (ci != _contexts.end()) {
1483 return (*ci).second;
1487 if (ibc !=
nullptr) {
1488 _contexts[prepared_objects] = ibc;
1499 Contexts::iterator ci;
1500 ci = _contexts.find(prepared_objects);
1501 if (ci != _contexts.end()) {
1522 int num_freed = (int)_contexts.size();
1524 Contexts::const_iterator ci;
1525 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1533 nassertr(_contexts.empty(), num_freed);
1544 switch (index_type) {
1548 if (cformat ==
nullptr) {
1549 cformat = make_index_format(NT_uint8);
1556 if (cformat ==
nullptr) {
1557 cformat = make_index_format(NT_uint16);
1564 if (cformat ==
nullptr) {
1565 cformat = make_index_format(NT_uint32);
1572 <<
"Not a valid index type: " << index_type <<
"\n";
1585 void GeomPrimitive::
1587 Contexts::iterator ci;
1588 ci = _contexts.find(prepared_objects);
1589 if (ci != _contexts.end()) {
1590 _contexts.erase(ci);
1594 nassert_raise(
"unknown PreparedGraphicsObjects");
1603 get_highest_index_value(NumericType index_type) {
1606 switch (index_type) {
1616 return 0x7fffffff - 1;
1633 switch (index_type) {
1658 PN_stdfloat &sq_center_dist,
bool &found_any,
1660 bool got_mat,
const LMatrix4 &mat,
1662 Thread *current_thread)
const {
1669 CDReader cdata(_cycler, current_thread);
1672 if (cdata->_vertices.is_null()) {
1674 nassertv(cdata->_num_vertices != -1);
1675 if (cdata->_num_vertices == 0) {
1681 while (!found_any && i < cdata->_num_vertices) {
1682 reader.
set_row(cdata->_first_vertex + i);
1683 LPoint3 first_vertex = mat.xform_point_general(reader.
get_data3());
1684 if (!first_vertex.is_nan()) {
1685 min_point = first_vertex;
1686 max_point = first_vertex;
1687 sq_center_dist = first_vertex.length_squared();
1693 for (; i < cdata->_num_vertices; ++i) {
1697 LPoint3 vertex = mat.xform_point_general(reader.
get_data3());
1699 min_point.set(min(min_point[0], vertex[0]),
1700 min(min_point[1], vertex[1]),
1701 min(min_point[2], vertex[2]));
1702 max_point.set(max(max_point[0], vertex[0]),
1703 max(max_point[1], vertex[1]),
1704 max(max_point[2], vertex[2]));
1705 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1709 while (!found_any && i < cdata->_num_vertices) {
1710 reader.
set_row(cdata->_first_vertex + i);
1711 LPoint3 first_vertex = reader.
get_data3();
1712 if (!first_vertex.is_nan()) {
1713 min_point = first_vertex;
1714 max_point = first_vertex;
1715 sq_center_dist = first_vertex.length_squared();
1721 for (; i < cdata->_num_vertices; ++i) {
1725 const LVecBase3 &vertex = reader.
get_data3();
1727 min_point.set(min(min_point[0], vertex[0]),
1728 min(min_point[1], vertex[1]),
1729 min(min_point[2], vertex[2]));
1730 max_point.set(max(max_point[0], vertex[0]),
1731 max(max_point[1], vertex[1]),
1732 max(max_point[2], vertex[2]));
1733 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1739 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
1748 while (!found_any && !index.
is_at_end()) {
1750 if (ii != strip_cut_index) {
1752 LPoint3 first_vertex = mat.xform_point_general(reader.
get_data3());
1753 if (!first_vertex.is_nan()) {
1754 min_point = first_vertex;
1755 max_point = first_vertex;
1756 sq_center_dist = first_vertex.length_squared();
1764 if (ii == strip_cut_index) {
1770 LPoint3 vertex = mat.xform_point_general(reader.
get_data3());
1772 min_point.set(min(min_point[0], vertex[0]),
1773 min(min_point[1], vertex[1]),
1774 min(min_point[2], vertex[2]));
1775 max_point.set(max(max_point[0], vertex[0]),
1776 max(max_point[1], vertex[1]),
1777 max(max_point[2], vertex[2]));
1778 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1782 while (!found_any && !index.
is_at_end()) {
1784 if (ii != strip_cut_index) {
1786 LVecBase3 first_vertex = reader.
get_data3();
1787 if (!first_vertex.is_nan()) {
1788 min_point = first_vertex;
1789 max_point = first_vertex;
1790 sq_center_dist = first_vertex.length_squared();
1798 if (ii == strip_cut_index) {
1804 const LVecBase3 &vertex = reader.
get_data3();
1806 min_point.set(min(min_point[0], vertex[0]),
1807 min(min_point[1], vertex[1]),
1808 min(min_point[2], vertex[2]));
1809 max_point.set(max(max_point[0], vertex[0]),
1810 max(max_point[1], vertex[1]),
1811 max(max_point[2], vertex[2]));
1812 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1828 Thread *current_thread)
const {
1829 GeomVertexReader reader(vertex_data, InternalName::get_vertex(), current_thread);
1839 CDReader cdata(_cycler, current_thread);
1841 if (cdata->_vertices.is_null()) {
1843 nassertv(cdata->_num_vertices != -1);
1844 if (cdata->_num_vertices == 0) {
1849 for (
int i = 0; i < cdata->_num_vertices; ++i) {
1851 const LVecBase3 &vertex = reader.
get_data3();
1853 sq_radius = max(sq_radius, (vertex - center).length_squared());
1858 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
1868 if (ii == strip_cut_index) {
1872 const LVecBase3 &vertex = reader.
get_data3();
1874 sq_radius = max(sq_radius, (vertex - center).length_squared());
1890 decompose_impl()
const {
1898 rotate_impl()
const {
1900 nassertr(
false,
nullptr);
1908 doubleside_impl()
const {
1916 reverse_impl()
const {
1924 bool GeomPrimitive::
1925 requires_unused_vertices()
const {
1938 void GeomPrimitive::
1945 void GeomPrimitive::
1946 recompute_minmax(GeomPrimitive::CData *cdata) {
1947 if (cdata->_vertices.is_null()) {
1950 nassertv(cdata->_num_vertices != -1);
1951 cdata->_min_vertex = cdata->_first_vertex;
1952 cdata->_max_vertex = cdata->_first_vertex + cdata->_num_vertices - 1;
1953 cdata->_mins.clear();
1954 cdata->_maxs.clear();
1957 int num_vertices = cdata->_vertices.get_read_pointer()->get_num_rows();
1959 if (num_vertices == 0) {
1961 cdata->_min_vertex = 0;
1962 cdata->_max_vertex = 0;
1963 cdata->_mins.clear();
1964 cdata->_maxs.clear();
1971 cdata->_mins = make_index_data();
1972 cdata->_maxs = make_index_data();
1985 unsigned int vertex = index.get_data1i();
1986 cdata->_min_vertex = vertex;
1987 cdata->_max_vertex = vertex;
1988 unsigned int min_prim = vertex;
1989 unsigned int max_prim = vertex;
1993 for (
int vi = 1; vi < num_vertices; ++vi) {
1994 nassertv(!index.is_at_end());
1995 nassertv(pi < (
int)cdata->_ends.size());
1997 unsigned int vertex;
1999 if (vi == cdata->_ends[pi]) {
2002 if (num_unused_vertices > 0) {
2003 vi += num_unused_vertices;
2004 index.set_row_unsafe(vi);
2006 vertex = index.get_data1i();
2008 mins.set_data1i(min_prim);
2009 maxs.set_data1i(max_prim);
2015 vertex = index.get_data1i();
2016 min_prim = min(min_prim, vertex);
2017 max_prim = max(max_prim, vertex);
2020 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
2021 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
2024 mins.set_data1i(min_prim);
2025 maxs.set_data1i(max_prim);
2026 nassertv(mins.get_array_data()->get_num_rows() == (
int)cdata->_ends.size());
2033 cdata->_mins.clear();
2034 cdata->_maxs.clear();
2036 unsigned int vertex = index.get_data1i();
2037 cdata->_min_vertex = vertex;
2038 cdata->_max_vertex = vertex;
2040 for (
int vi = 1; vi < num_vertices; ++vi) {
2041 nassertv(!index.is_at_end());
2042 unsigned int vertex = index.get_data1i();
2043 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
2044 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
2049 cdata->_got_minmax =
true;
2055 void GeomPrimitive::
2056 do_make_indexed(CData *cdata) {
2057 if (cdata->_vertices.is_null()) {
2058 if (gobj_cat.is_debug()) {
2060 <<
this <<
".make_indexed()\n";
2063 nassertv(cdata->_num_vertices != -1);
2064 cdata->_vertices = make_index_data();
2070 for (
int i = 0; i < cdata->_num_vertices; ++i) {
2071 index.set_data1i(i + cdata->_first_vertex);
2073 cdata->_num_vertices = -1;
2081 void GeomPrimitive::
2082 consider_elevate_index_type(CData *cdata,
int vertex) {
2086 switch (cdata->_index_type) {
2088 if (vertex >= 0xff) {
2089 do_set_index_type(cdata, NT_uint16);
2094 if (vertex >= 0xffff) {
2095 do_set_index_type(cdata, NT_uint32);
2101 nassertv(vertex < 0x7fffffff);
2112 void GeomPrimitive::
2113 do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
2117 cdata->_index_type = index_type;
2119 if (gobj_cat.is_debug()) {
2121 <<
this <<
".set_index_type(" << index_type <<
")\n";
2124 if (!cdata->_vertices.is_null()) {
2128 if (array_obj->get_array_format() != new_format) {
2130 new_vertices->set_num_rows(array_obj->get_num_rows());
2135 while (!from.is_at_end()) {
2136 int index = from.get_data1i();
2137 if (index == old_strip_cut_index) {
2138 index = new_strip_cut_index;
2140 to.set_data1i(index);
2142 cdata->_vertices = new_vertices;
2143 cdata->_got_minmax =
false;
2152 do_modify_vertices(GeomPrimitive::CData *cdata) {
2153 if (cdata->_vertices.is_null()) {
2154 do_make_indexed(cdata);
2160 cdata->_got_minmax =
false;
2183 if (vertices !=
nullptr) {
2192 void GeomPrimitive::
2205 return new CData(*
this);
2212 void GeomPrimitive::CData::
2221 WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends);
2228 int GeomPrimitive::CData::
2248 void GeomPrimitive::CData::
2250 _shade_model = (ShadeModel)scan.
get_uint8();
2253 _index_type = (NumericType)scan.
get_uint8();
2254 _usage_hint = (UsageHint)scan.
get_uint8();
2257 READ_PTA(manager, scan, IPD_int::read_datagram, _ends);
2260 _got_minmax =
false;
2268 if (!_cdata->_got_minmax) {
2272 #ifdef DO_PIPELINING
2276 false, _current_thread);
2278 #ifdef DO_PIPELINING
2282 if (!fresh_cdata->_got_minmax) {
2284 ((
GeomPrimitive *)_object.p())->recompute_minmax(fresh_cdata);
2285 nassertv(fresh_cdata->_got_minmax);
2294 nassertv(_cdata->_got_minmax);
2300 int GeomPrimitivePipelineReader::
2301 get_first_vertex()
const {
2302 if (_vertices.is_null()) {
2303 return _cdata->_first_vertex;
2306 size_t size = _vertices_cdata->_buffer.get_size();
2312 return index.get_data1i();
2320 if (!_vertices.is_null()) {
2322 nassertr(i >= 0 && i < get_num_vertices(), -1);
2324 const unsigned char *ptr = get_read_pointer(
true);
2325 switch (_cdata->_index_type) {
2326 case GeomEnums::NT_uint8:
2327 return ((uint8_t *)ptr)[i];
2329 case GeomEnums::NT_uint16:
2330 return ((uint16_t *)ptr)[i];
2332 case GeomEnums::NT_uint32:
2333 return ((uint32_t *)ptr)[i];
2336 nassert_raise(
"unsupported index type");
2342 return _cdata->_first_vertex + i;
2349 int GeomPrimitivePipelineReader::
2350 get_num_primitives()
const {
2351 int num_vertices_per_primitive = _object->get_num_vertices_per_primitive();
2353 if (num_vertices_per_primitive == 0) {
2356 return _cdata->_ends.size();
2361 return (get_num_vertices() / num_vertices_per_primitive);
2371 int num_vertices = get_num_vertices();
2374 int strip_cut_index = get_strip_cut_index();
2375 const unsigned char *ptr = get_read_pointer(
true);
2376 switch (get_index_type()) {
2377 case GeomEnums::NT_uint8:
2378 for (
int vi = 0; vi < num_vertices; ++vi) {
2379 int index = ((
const uint8_t *)ptr)[vi];
2380 if (index != strip_cut_index) {
2385 case GeomEnums::NT_uint16:
2386 for (
int vi = 0; vi < num_vertices; ++vi) {
2387 int index = ((
const uint16_t *)ptr)[vi];
2388 if (index != strip_cut_index) {
2393 case GeomEnums::NT_uint32:
2394 for (
int vi = 0; vi < num_vertices; ++vi) {
2395 int index = ((
const uint32_t *)ptr)[vi];
2396 if (index != strip_cut_index) {
2402 nassert_raise(
"unsupported index type");
2407 bits.
set_range(get_first_vertex(), num_vertices);
2414 bool GeomPrimitivePipelineReader::
2416 if (get_num_vertices() != 0 &&
2417 data_reader->get_num_arrays() > 0 &&
2418 get_max_vertex() >= data_reader->get_num_rows()) {
2422 << get_object()->get_type() <<
" references vertices up to "
2423 << get_max_vertex() <<
", but GeomVertexData has only "
2424 << data_reader->get_num_rows() <<
" rows!\n";
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
A dynamic array with an unlimited number of bits.
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the array.
int get_next_higher_different_bit(int low_bit) const
Returns the index of the next bit in the array, above low_bit, whose value is different that the valu...
int get_lowest_on_bit() const
Returns the index of the lowest 1 bit in the array.
void set_range(int low_bit, int size)
Sets the indicated range of bits on.
void set_bit(int index)
Sets the nth bit on.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
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.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
A class to retrieve the individual data elements previously stored in a Datagram.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
int32_t get_int32()
Extracts a signed 32-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
Defines a series of disconnected line segments.
Defines a series of "patches", fixed-size groupings of vertices that must be processed by a tessellat...
Defines a series of disconnected points.
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
void get_referenced_vertices(BitArray &bits) const
Turns on all the bits corresponding to the vertices that are referenced by this GeomPrimitive.
void check_minmax() const
Ensures that the primitive's minmax cache has been computed.
int get_vertex(int i) const
Returns the ith vertex index in the table.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
get_min_num_vertices_per_primitive
Returns the minimum number of vertices that must be added before close_primitive() may legally be cal...
void clear_vertices()
Removes all of the vertices and primitives from the object, so they can be re-added.
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.
void calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, PN_stdfloat &sq_center_dist, bool &found_any, const GeomVertexData *vertex_data, bool got_mat, const LMatrix4 &mat, const InternalName *column_name, Thread *current_thread) const
Expands min_point and max_point to include all of the vertices in the Geom, if any (or the data of an...
get_geom_rendering
Returns the set of GeomRendering bits that represent the rendering properties required to properly re...
get_vertex
Returns the ith vertex index in the table.
void reserve_num_vertices(int num_vertices)
This ensures that enough memory space for n vertices is allocated, so that you may increase the numbe...
int get_num_used_vertices() const
Returns the number of vertices used by all of the primitives.
get_usage_hint
Returns the usage hint for this primitive.
void operator=(const GeomPrimitive ©)
The copy assignment operator is not pipeline-safe.
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the data has already been prepared or enqueued for preparation on the indicated GSG,...
void make_indexed()
Converts the primitive from nonindexed form to indexed form.
void add_consecutive_vertices(int start, int num_vertices)
Adds a consecutive sequence of vertices, beginning at start, to the primitive.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
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,...
void pack_vertices(GeomVertexData *dest, const GeomVertexData *source)
Packs the vertices used by the primitive from the indicated source array onto the end of the indicate...
bool close_primitive()
Indicates that the previous n calls to add_vertex(), since the last call to close_primitive(),...
int get_primitive_max_vertex(int n) const
Returns the maximum vertex index number used by the nth primitive in this object.
const GeomVertexArrayFormat * get_index_format() const
Returns a registered format appropriate for using to store the index table.
void set_nonindexed_vertices(int first_vertex, int num_vertices)
Sets the primitive up as a nonindexed primitive, using the indicated vertex range.
get_num_unused_vertices_per_primitive
Returns the number of vertices that are added between primitives that aren't, strictly speaking,...
void set_index_type(NumericType index_type)
Changes the numeric type of the index column.
void set_vertices(const GeomVertexArrayData *vertices, int num_vertices=-1)
Completely replaces the vertex index list with a new table.
void set_ends(PTA_int ends)
Completely replaces the primitive ends array with a new table.
void offset_vertices(int offset)
Adds the indicated offset to all vertices used by the primitive.
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the data context only on the indicated object, if it exists there.
get_num_vertices_per_primitive
If the primitive type is a simple type in which all primitives have the same number of vertices,...
PTA_int modify_ends()
Returns a modifiable pointer to the primitive ends array, so application code can directly fiddle wit...
int get_primitive_min_vertex(int n) const
Returns the minimum vertex index number used by the nth primitive in this object.
void add_next_vertices(int num_vertices)
Adds the next n vertices in sequence, beginning from the last vertex added to the primitive + 1.
void make_nonindexed(GeomVertexData *dest, const GeomVertexData *source)
Converts the primitive from indexed to nonindexed by duplicating vertices as necessary into the indic...
void set_usage_hint(UsageHint usage_hint)
Changes the UsageHint hint for this primitive.
int get_primitive_start(int n) const
Returns the element within the _vertices list at which the nth primitive starts.
get_shade_model
Returns the ShadeModel hint for this primitive.
void clear_minmax()
Undoes a previous call to set_minmax(), and allows the minimum and maximum values to be recomputed no...
void calc_sphere_radius(const LPoint3 ¢er, PN_stdfloat &sq_radius, bool &found_any, const GeomVertexData *vertex_data, Thread *current_thread) const
Expands radius so that a sphere with the given center point fits all of the vertices.
int release_all()
Frees the context allocated on all objects for which the data has been declared.
int get_primitive_num_vertices(int n) const
Returns the number of vertices used by the nth primitive.
int get_primitive_end(int n) const
Returns the element within the _vertices list at which the nth primitive ends.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
void add_vertex(int vertex)
Adds the indicated vertex to the list of vertex indices used by the graphics primitive type.
void prepare(PreparedGraphicsObjects *prepared_objects)
Indicates that the data should be enqueued to be prepared in the indicated prepared_objects at the be...
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
IndexBufferContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the data on the particular GSG, if it does not already exist.
void set_minmax(int min_vertex, int max_vertex, GeomVertexArrayData *mins, GeomVertexArrayData *maxs)
Explicitly specifies the minimum and maximum vertices, as well as the lists of per-component min and ...
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
unsigned char * get_write_pointer()
Returns a writable pointer to the beginning of the actual data stream.
This is the data for one array of a GeomVertexData structure.
get_usage_hint
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
get_array_format
Returns the format object that describes this array.
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
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.
void copy_row_from(int dest_row, const GeomVertexDataPipelineReader &source, int source_row)
Copies a single row of the data from the other array into the indicated row of this array.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
void copy_row_from(int dest_row, const GeomVertexData *source, int source_row, Thread *current_thread)
Copies a single row of the data from the other array into the indicated row of this array.
int get_num_rows() const
Returns the number of rows stored within all the arrays.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
bool is_at_end() const
Returns true if the reader is currently at the end of the list of vertices, false otherwise.
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
int get_data1i()
Returns the data associated with the read row, expressed as a 1-component value, and advances the rea...
bool has_column() const
Returns true if a valid data type has been successfully set, or false if the data type does not exist...
void set_row(int row)
Sets the start row to the indicated value.
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void add_data1i(int data)
Sets the write row to a particular 1-component value, and advances the write row.
void set_data1i(int data)
Sets the write row to a particular 1-component value, and advances the write row.
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
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...
Encodes a string name in a hash table, mapping it to a pointer.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
A table of objects that are saved within the graphics context for reference by handle later.
bool is_index_buffer_queued(const GeomPrimitive *data) const
Returns true if the index buffer has been queued on this GSG, false otherwise.
void release_index_buffer(IndexBufferContext *ibc)
Indicates that a data context, created by a previous call to prepare_index_buffer(),...
void enqueue_index_buffer(GeomPrimitive *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
IndexBufferContext * prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg)
Immediately creates a new IndexBufferContext for the indicated data and returns it.
bool dequeue_index_buffer(GeomPrimitive *data)
Removes a buffer from the queued list of data arrays to be prepared.
A thread; that is, a lightweight process.
get_current_thread
Returns a pointer to the currently-executing Thread object.
TypeHandle is the identifier used to differentiate C++ class types.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Base class for objects that can be written to and read from Bam files.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(CopyOnWriteObject) GeomPrimitive
Required to implement CopyOnWriteObject.
CPT(GeomPrimitive) GeomPrimitive
Decomposes a complex primitive type into a simpler primitive type, for instance triangle strips to tr...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...