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;
104 get_geom_rendering()
const {
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);
208 Thread::get_current_thread());
209 int num_rows = handle.get_num_rows();
210 handle.set_num_rows(num_rows + 1);
212 unsigned char *ptr = handle.get_write_pointer();
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);
451 if (vertex != strip_cut_index) {
459 cdata->_first_vertex += offset;
461 cdata->_got_minmax =
false;
463 consider_elevate_index_type(cdata,
464 cdata->_first_vertex + cdata->_num_vertices - 1);
478 if (offset == 0 || end_row <= begin_row) {
482 nassertv(begin_row >= 0 && end_row >= 0);
500 for (
int j = begin_row; j < end_row; ++j) {
501 int vertex = index_r.get_data1i();
502 if (vertex != strip_cut_index) {
503 max_vertex = max(max_vertex, vertex);
508 consider_elevate_index_type(cdata, max_vertex + offset);
512 for (
int j = begin_row; j < end_row; ++j) {
514 if (vertex != strip_cut_index) {
524 cdata->_first_vertex += offset;
526 cdata->_got_minmax =
false;
528 consider_elevate_index_type(cdata,
529 cdata->_first_vertex + cdata->_num_vertices - 1);
540 Thread *current_thread = Thread::get_current_thread();
542 int num_vertices, dest_start;
545 num_vertices = reader.get_num_vertices();
546 int strip_cut_index = reader.get_strip_cut_index();
549 data_writer.check_array_writers();
550 dest_start = data_writer.get_num_rows();
551 data_writer.set_num_rows(dest_start + num_vertices);
554 data_reader.check_array_readers();
556 for (
int i = 0; i < num_vertices; ++i) {
558 nassertd(v != strip_cut_index)
continue;
572 Thread *current_thread = Thread::get_current_thread();
584 CopiedIndices copied_indices;
590 for (
int i = 0; i < num_vertices; ++i) {
592 if (v == strip_cut_index) {
598 std::pair<CopiedIndices::iterator, bool> result =
599 copied_indices.insert(CopiedIndices::value_type(v, (
int)copied_indices.size()));
600 int v2 = (*result.first).second + dest_start;
626 do_make_indexed(cdata);
644 if (num_vertices_per_primitive == 0) {
648 nassertr(n >= 0 && n <= (
int)cdata->_ends.size(), -1);
652 return cdata->_ends[n - 1] + num_unused_vertices_per_primitive;
658 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive);
670 if (num_vertices_per_primitive == 0) {
674 nassertr(n >= 0 && n < (
int)cdata->_ends.size(), -1);
675 return cdata->_ends[n];
681 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive) + num_vertices_per_primitive;
693 if (num_vertices_per_primitive == 0) {
697 nassertr(n >= 0 && n < (
int)cdata->_ends.size(), 0);
699 return cdata->_ends[0];
702 return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive;
708 return num_vertices_per_primitive;
722 if (num_primitives > 0) {
738 nassertr(n >= 0 && n < mins->get_num_rows(), -1);
756 nassertr(n >= 0 && n < maxs->get_num_rows(), -1);
778 if (gobj_cat.is_debug()) {
780 <<
"Decomposing " << get_type() <<
": " << (
void *)
this <<
"\n";
784 return decompose_impl();
798 if (gobj_cat.is_debug()) {
800 <<
"Rotating " << get_type() <<
": " << (
void *)
this <<
"\n";
806 if (rotated_vertices ==
nullptr) {
812 new_prim->set_vertices(rotated_vertices);
815 case SM_flat_first_vertex:
816 new_prim->set_shade_model(SM_flat_last_vertex);
819 case SM_flat_last_vertex:
820 new_prim->set_shade_model(SM_flat_first_vertex);
842 if (gobj_cat.is_debug()) {
844 <<
"Doublesiding " << get_type() <<
": " << (
void *)
this <<
"\n";
848 return doubleside_impl();
863 if (gobj_cat.is_debug()) {
865 <<
"Reversing " << get_type() <<
": " << (
void *)
this <<
"\n";
869 return reverse_impl();
881 match_shade_model(GeomPrimitive::ShadeModel shade_model)
const {
883 if (this_shade_model == shade_model) {
888 if (this_shade_model == SM_uniform || shade_model == SM_uniform) {
893 if ((this_shade_model == SM_flat_first_vertex && shade_model == SM_flat_last_vertex) ||
894 (this_shade_model == SM_flat_last_vertex && shade_model == SM_flat_first_vertex)) {
897 if (rotated.p() ==
this) {
915 make_points()
const {
925 reader.get_referenced_vertices(bits);
936 new_index.set_data1i(p);
947 points->set_vertices(new_vertices);
963 PrimitiveType prim_type = get_primitive_type();
964 if (prim_type == PT_lines) {
968 }
else if (prim_type != PT_polygons && prim_type != PT_patches) {
973 if (prim_type == PT_polygons && !
is_exact_type(GeomTriangles::get_class_type())) {
976 return decompose()->make_lines();
984 new_vertices->unclean_set_num_rows(num_primitives * verts_per_prim * 2);
988 for (
int i = 0; i < num_primitives; ++i) {
994 for (
int vi = begin; vi < end - 1; vi++) {
1003 lines->set_vertices(new_vertices);
1018 make_patches()
const {
1024 int num_vertices_per_patch = prim->get_num_vertices_per_primitive();
1028 if (prim->is_indexed()) {
1029 patches->set_vertices(prim->get_vertices());
1031 patches->set_nonindexed_vertices(prim->get_first_vertex(),
1032 prim->get_num_vertices());
1043 make_adjacency()
const {
1052 get_num_bytes()
const {
1053 CDReader cdata(_cycler);
1054 int num_bytes = cdata->_ends.size() *
sizeof(int) +
sizeof(
GeomPrimitive);
1055 if (!cdata->_vertices.is_null()) {
1056 num_bytes += cdata->_vertices.get_read_pointer()->get_data_size_bytes();
1067 bool GeomPrimitive::
1068 request_resident(
Thread *current_thread)
const {
1069 CDReader cdata(_cycler, current_thread);
1071 bool resident =
true;
1073 if (!cdata->_vertices.is_null() &&
1074 !cdata->_vertices.get_read_pointer(current_thread)->request_resident(current_thread)) {
1079 if (!cdata->_mins.is_null() &&
1080 !cdata->_mins.get_read_pointer(current_thread)->request_resident(current_thread)) {
1083 if (!cdata->_maxs.is_null() &&
1084 !cdata->_maxs.get_read_pointer(current_thread)->request_resident(current_thread)) {
1095 void GeomPrimitive::
1096 output(std::ostream &out)
const {
1104 void GeomPrimitive::
1105 write(std::ostream &out,
int indent_level)
const {
1106 indent(out, indent_level)
1109 out <<
" (indexed)";
1111 out <<
" (nonindexed)";
1117 for (
int i = 0; i < num_primitives; ++i) {
1118 indent(out, indent_level + 2)
1122 for (
int vi = begin; vi < end; vi++) {
1126 if (end < num_vertices) {
1127 for (
int ui = 0; ui < num_unused_vertices_per_primitive; ++ui) {
1128 if (end + ui < num_vertices) {
1159 modify_vertices(
int num_vertices) {
1160 CDWriter cdata(_cycler,
true);
1162 cdata->_num_vertices = num_vertices;
1186 cdata->_num_vertices = num_vertices;
1191 cdata->_index_type = format->
get_column(0)->get_numeric_type();
1194 cdata->_got_minmax =
false;
1210 nassertv(num_vertices != -1);
1212 cdata->_vertices =
nullptr;
1213 cdata->_first_vertex = first_vertex;
1214 cdata->_num_vertices = num_vertices;
1217 cdata->_got_minmax =
false;
1220 recompute_minmax(cdata);
1244 cdata->_got_minmax =
false;
1246 if (cdata->_ends.get_ref_count() > 1) {
1248 new_ends.v() = cdata->_ends.v();
1249 cdata->_ends = new_ends;
1251 return cdata->_ends;
1273 cdata->_ends = ends;
1276 cdata->_got_minmax =
false;
1298 cdata->_min_vertex = min_vertex;
1299 cdata->_max_vertex = max_vertex;
1300 cdata->_mins = mins;
1301 cdata->_maxs = maxs;
1304 cdata->_got_minmax =
true;
1318 cdata->_got_minmax =
false;
1333 get_num_vertices_per_primitive()
const {
1346 get_min_num_vertices_per_primitive()
const {
1361 get_num_unused_vertices_per_primitive()
const {
1386 Contexts::const_iterator ci;
1387 ci = _contexts.find(prepared_objects);
1388 if (ci != _contexts.end()) {
1410 Contexts::const_iterator ci;
1411 ci = _contexts.find(prepared_objects);
1412 if (ci != _contexts.end()) {
1413 return (*ci).second;
1417 if (ibc !=
nullptr) {
1418 _contexts[prepared_objects] = ibc;
1429 Contexts::iterator ci;
1430 ci = _contexts.find(prepared_objects);
1431 if (ci != _contexts.end()) {
1452 int num_freed = (int)_contexts.size();
1454 Contexts::const_iterator ci;
1455 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1463 nassertr(_contexts.empty(), num_freed);
1474 switch (index_type) {
1478 if (cformat ==
nullptr) {
1479 cformat = make_index_format(NT_uint8);
1486 if (cformat ==
nullptr) {
1487 cformat = make_index_format(NT_uint16);
1494 if (cformat ==
nullptr) {
1495 cformat = make_index_format(NT_uint32);
1502 <<
"Not a valid index type: " << index_type <<
"\n";
1515 void GeomPrimitive::
1517 Contexts::iterator ci;
1518 ci = _contexts.find(prepared_objects);
1519 if (ci != _contexts.end()) {
1520 _contexts.erase(ci);
1524 nassert_raise(
"unknown PreparedGraphicsObjects");
1533 get_highest_index_value(NumericType index_type) {
1536 switch (index_type) {
1546 return 0x7fffffff - 1;
1560 get_strip_cut_index(NumericType index_type) {
1563 switch (index_type) {
1588 PN_stdfloat &sq_center_dist,
bool &found_any,
1590 bool got_mat,
const LMatrix4 &mat,
1592 Thread *current_thread)
const {
1599 CDReader cdata(_cycler, current_thread);
1602 if (cdata->_vertices.is_null()) {
1604 nassertv(cdata->_num_vertices != -1);
1605 if (cdata->_num_vertices == 0) {
1611 while (!found_any && i < cdata->_num_vertices) {
1612 reader.
set_row(cdata->_first_vertex + i);
1613 LPoint3 first_vertex = mat.xform_point(reader.
get_data3());
1614 if (!first_vertex.is_nan()) {
1615 min_point = first_vertex;
1616 max_point = first_vertex;
1617 sq_center_dist = first_vertex.length_squared();
1623 for (; i < cdata->_num_vertices; ++i) {
1625 LPoint3 vertex = mat.xform_point(reader.
get_data3());
1627 min_point.set(min(min_point[0], vertex[0]),
1628 min(min_point[1], vertex[1]),
1629 min(min_point[2], vertex[2]));
1630 max_point.set(max(max_point[0], vertex[0]),
1631 max(max_point[1], vertex[1]),
1632 max(max_point[2], vertex[2]));
1633 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1637 while (!found_any && i < cdata->_num_vertices) {
1638 reader.
set_row(cdata->_first_vertex + i);
1639 LPoint3 first_vertex = reader.
get_data3();
1640 if (!first_vertex.is_nan()) {
1641 min_point = first_vertex;
1642 max_point = first_vertex;
1643 sq_center_dist = first_vertex.length_squared();
1649 for (; i < cdata->_num_vertices; ++i) {
1651 const LVecBase3 &vertex = reader.
get_data3();
1653 min_point.set(min(min_point[0], vertex[0]),
1654 min(min_point[1], vertex[1]),
1655 min(min_point[2], vertex[2]));
1656 max_point.set(max(max_point[0], vertex[0]),
1657 max(max_point[1], vertex[1]),
1658 max(max_point[2], vertex[2]));
1659 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1665 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
1666 if (index.is_at_end()) {
1674 while (!found_any && !index.is_at_end()) {
1675 int ii = index.get_data1i();
1676 if (ii != strip_cut_index) {
1678 LPoint3 first_vertex = mat.xform_point(reader.
get_data3());
1679 if (!first_vertex.is_nan()) {
1680 min_point = first_vertex;
1681 max_point = first_vertex;
1682 sq_center_dist = first_vertex.length_squared();
1688 while (!index.is_at_end()) {
1689 int ii = index.get_data1i();
1690 if (ii == strip_cut_index) {
1694 LPoint3 vertex = mat.xform_point(reader.
get_data3());
1696 min_point.set(min(min_point[0], vertex[0]),
1697 min(min_point[1], vertex[1]),
1698 min(min_point[2], vertex[2]));
1699 max_point.set(max(max_point[0], vertex[0]),
1700 max(max_point[1], vertex[1]),
1701 max(max_point[2], vertex[2]));
1702 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1706 while (!found_any && !index.is_at_end()) {
1707 int ii = index.get_data1i();
1708 if (ii != strip_cut_index) {
1710 LVecBase3 first_vertex = reader.
get_data3();
1711 if (!first_vertex.is_nan()) {
1712 min_point = first_vertex;
1713 max_point = first_vertex;
1714 sq_center_dist = first_vertex.length_squared();
1720 while (!index.is_at_end()) {
1721 int ii = index.get_data1i();
1722 if (ii == strip_cut_index) {
1726 const LVecBase3 &vertex = reader.
get_data3();
1728 min_point.set(min(min_point[0], vertex[0]),
1729 min(min_point[1], vertex[1]),
1730 min(min_point[2], vertex[2]));
1731 max_point.set(max(max_point[0], vertex[0]),
1732 max(max_point[1], vertex[1]),
1733 max(max_point[2], vertex[2]));
1734 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1750 Thread *current_thread)
const {
1751 GeomVertexReader reader(vertex_data, InternalName::get_vertex(), current_thread);
1761 CDReader cdata(_cycler, current_thread);
1763 if (cdata->_vertices.is_null()) {
1765 nassertv(cdata->_num_vertices != -1);
1766 if (cdata->_num_vertices == 0) {
1771 for (
int i = 0; i < cdata->_num_vertices; ++i) {
1773 const LVecBase3 &vertex = reader.
get_data3();
1775 sq_radius = max(sq_radius, (vertex - center).length_squared());
1780 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
1781 if (index.is_at_end()) {
1788 while (!index.is_at_end()) {
1789 int ii = index.get_data1i();
1790 if (ii == strip_cut_index) {
1794 const LVecBase3 &vertex = reader.
get_data3();
1796 sq_radius = max(sq_radius, (vertex - center).length_squared());
1812 decompose_impl()
const {
1820 rotate_impl()
const {
1822 nassertr(
false,
nullptr);
1830 doubleside_impl()
const {
1838 reverse_impl()
const {
1846 bool GeomPrimitive::
1847 requires_unused_vertices()
const {
1860 void GeomPrimitive::
1867 void GeomPrimitive::
1868 recompute_minmax(GeomPrimitive::CData *cdata) {
1869 if (cdata->_vertices.is_null()) {
1872 nassertv(cdata->_num_vertices != -1);
1873 cdata->_min_vertex = cdata->_first_vertex;
1874 cdata->_max_vertex = cdata->_first_vertex + cdata->_num_vertices - 1;
1875 cdata->_mins.clear();
1876 cdata->_maxs.clear();
1879 int num_vertices = cdata->_vertices.get_read_pointer()->get_num_rows();
1881 if (num_vertices == 0) {
1883 cdata->_min_vertex = 0;
1884 cdata->_max_vertex = 0;
1885 cdata->_mins.clear();
1886 cdata->_maxs.clear();
1893 cdata->_mins = make_index_data();
1894 cdata->_maxs = make_index_data();
1907 unsigned int vertex = index.get_data1i();
1908 cdata->_min_vertex = vertex;
1909 cdata->_max_vertex = vertex;
1910 unsigned int min_prim = vertex;
1911 unsigned int max_prim = vertex;
1915 for (
int vi = 1; vi < num_vertices; ++vi) {
1916 nassertv(!index.is_at_end());
1917 nassertv(pi < (
int)cdata->_ends.size());
1919 unsigned int vertex;
1921 if (vi == cdata->_ends[pi]) {
1924 if (num_unused_vertices > 0) {
1925 vi += num_unused_vertices;
1926 index.set_row_unsafe(vi);
1928 vertex = index.get_data1i();
1930 mins.set_data1i(min_prim);
1931 maxs.set_data1i(max_prim);
1937 vertex = index.get_data1i();
1938 min_prim = min(min_prim, vertex);
1939 max_prim = max(max_prim, vertex);
1942 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
1943 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
1946 mins.set_data1i(min_prim);
1947 maxs.set_data1i(max_prim);
1948 nassertv(mins.get_array_data()->get_num_rows() == (int)cdata->_ends.size());
1955 cdata->_mins.
clear();
1956 cdata->_maxs.clear();
1958 unsigned int vertex = index.get_data1i();
1959 cdata->_min_vertex = vertex;
1960 cdata->_max_vertex = vertex;
1962 for (
int vi = 1; vi < num_vertices; ++vi) {
1963 nassertv(!index.is_at_end());
1964 unsigned int vertex = index.get_data1i();
1965 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
1966 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
1971 cdata->_got_minmax =
true;
1977 void GeomPrimitive::
1978 do_make_indexed(CData *cdata) {
1979 if (cdata->_vertices.is_null()) {
1980 if (gobj_cat.is_debug()) {
1982 <<
this <<
".make_indexed()\n";
1985 nassertv(cdata->_num_vertices != -1);
1986 cdata->_vertices = make_index_data();
1992 for (
int i = 0; i < cdata->_num_vertices; ++i) {
1993 index.set_data1i(i + cdata->_first_vertex);
1995 cdata->_num_vertices = -1;
2003 void GeomPrimitive::
2004 consider_elevate_index_type(CData *cdata,
int vertex) {
2008 switch (cdata->_index_type) {
2010 if (vertex >= 0xff) {
2011 do_set_index_type(cdata, NT_uint16);
2016 if (vertex >= 0xffff) {
2017 do_set_index_type(cdata, NT_uint32);
2023 nassertv(vertex < 0x7fffffff);
2034 void GeomPrimitive::
2035 do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
2039 cdata->_index_type = index_type;
2041 if (gobj_cat.is_debug()) {
2043 <<
this <<
".set_index_type(" << index_type <<
")\n";
2046 if (!cdata->_vertices.is_null()) {
2050 if (array_obj->get_array_format() != new_format) {
2052 new_vertices->set_num_rows(array_obj->get_num_rows());
2057 while (!from.is_at_end()) {
2058 int index = from.get_data1i();
2059 if (index == old_strip_cut_index) {
2060 index = new_strip_cut_index;
2062 to.set_data1i(index);
2064 cdata->_vertices = new_vertices;
2065 cdata->_got_minmax =
false;
2074 do_modify_vertices(GeomPrimitive::CData *cdata) {
2075 if (cdata->_vertices.is_null()) {
2076 do_make_indexed(cdata);
2082 cdata->_got_minmax =
false;
2105 if (vertices !=
nullptr) {
2114 void GeomPrimitive::
2127 return new CData(*
this);
2134 void GeomPrimitive::CData::
2143 WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends);
2150 int GeomPrimitive::CData::
2170 void GeomPrimitive::CData::
2172 _shade_model = (ShadeModel)scan.
get_uint8();
2175 _index_type = (NumericType)scan.
get_uint8();
2176 _usage_hint = (UsageHint)scan.
get_uint8();
2179 READ_PTA(manager, scan, IPD_int::read_datagram, _ends);
2182 _got_minmax =
false;
2190 if (!_cdata->_got_minmax) {
2194 #ifdef DO_PIPELINING 2198 false, _current_thread);
2200 #ifdef DO_PIPELINING 2204 if (!fresh_cdata->_got_minmax) {
2206 ((
GeomPrimitive *)_object.p())->recompute_minmax(fresh_cdata);
2207 nassertv(fresh_cdata->_got_minmax);
2216 nassertv(_cdata->_got_minmax);
2222 int GeomPrimitivePipelineReader::
2223 get_first_vertex()
const {
2224 if (_vertices.is_null()) {
2225 return _cdata->_first_vertex;
2228 size_t size = _vertices_cdata->_buffer.get_size();
2234 return index.get_data1i();
2242 if (!_vertices.is_null()) {
2244 nassertr(i >= 0 && i < get_num_vertices(), -1);
2246 const unsigned char *ptr = get_read_pointer(
true);
2247 switch (_cdata->_index_type) {
2248 case GeomEnums::NT_uint8:
2249 return ((uint8_t *)ptr)[i];
2251 case GeomEnums::NT_uint16:
2252 return ((uint16_t *)ptr)[i];
2254 case GeomEnums::NT_uint32:
2255 return ((uint32_t *)ptr)[i];
2258 nassert_raise(
"unsupported index type");
2264 return _cdata->_first_vertex + i;
2271 int GeomPrimitivePipelineReader::
2272 get_num_primitives()
const {
2273 int num_vertices_per_primitive = _object->get_num_vertices_per_primitive();
2275 if (num_vertices_per_primitive == 0) {
2278 return _cdata->_ends.size();
2283 return (get_num_vertices() / num_vertices_per_primitive);
2293 int num_vertices = get_num_vertices();
2296 int strip_cut_index = get_strip_cut_index();
2297 const unsigned char *ptr = get_read_pointer(
true);
2298 switch (get_index_type()) {
2299 case GeomEnums::NT_uint8:
2300 for (
int vi = 0; vi < num_vertices; ++vi) {
2301 int index = ((
const uint8_t *)ptr)[vi];
2302 if (index != strip_cut_index) {
2307 case GeomEnums::NT_uint16:
2308 for (
int vi = 0; vi < num_vertices; ++vi) {
2309 int index = ((
const uint16_t *)ptr)[vi];
2310 if (index != strip_cut_index) {
2315 case GeomEnums::NT_uint32:
2316 for (
int vi = 0; vi < num_vertices; ++vi) {
2317 int index = ((
const uint32_t *)ptr)[vi];
2318 if (index != strip_cut_index) {
2324 nassert_raise(
"unsupported index type");
2329 bits.
set_range(get_first_vertex(), num_vertices);
2336 bool GeomPrimitivePipelineReader::
2338 if (get_num_vertices() != 0 &&
2339 data_reader->get_num_arrays() > 0 &&
2340 get_max_vertex() >= data_reader->get_num_rows()) {
2344 << get_object()->get_type() <<
" references vertices up to " 2345 << get_max_vertex() <<
", but GeomVertexData has only " 2346 << data_reader->get_num_rows() <<
" rows!\n";
IndexBufferContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the data on the particular GSG, if it does not already exist.
bool close_primitive()
Indicates that the previous n calls to add_vertex(), since the last call to close_primitive(), have fully defined a new primitive.
int release_all()
Frees the context allocated on all objects for which the data has been declared.
bool is_at_end() const
Returns true if the reader or writer is currently at the end of the list of vertices, false otherwise.
bool is_index_buffer_queued(const GeomPrimitive *data) const
Returns true if the index buffer has been queued on this GSG, false otherwise.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_composite() const
Returns true if the primitive is a composite primitive such as a tristrip or trifan, or false if it is a fundamental primitive such as a collection of triangles.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
const GeomVertexArrayFormat * get_index_format() const
Returns a registered format appropriate for using to store the index table.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
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_max_vertex() const
Returns the maximum vertex index number used by all the primitives in this object.
int get_primitive_num_vertices(int n) const
Returns the number of vertices used by the nth primitive.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Defines a series of disconnected points.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the data context only on the indicated object, if it exists there.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void add_data1i(int data)
Sets the write row to a particular 1-component value, and advances the write row. ...
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
int get_num_used_vertices() const
Returns the number of vertices used by all of the primitives.
get_vertex
Returns the ith vertex index in the table.
bool dequeue_index_buffer(GeomPrimitive *data)
Removes a buffer from the queued list of data arrays to be prepared.
UsageHint get_usage_hint() const
Returns the minimum (i.e.
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...
This is a special class object that holds all the information returned by a particular GSG to indicat...
void set_index_type(NumericType index_type)
Changes the numeric type of the index column.
A single page of data maintained by a PipelineCycler.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
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...
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...
PTA_int modify_ends()
Returns a modifiable pointer to the primitive ends array, so application code can directly fiddle wit...
Base class for objects that can be written to and read from Bam files.
void operator=(const GeomPrimitive ©)
The copy assignment operator is not pipeline-safe.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
IndexBufferContext * prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg)
Immediately creates a new IndexBufferContext for the indicated data and returns it.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
int get_primitive_max_vertex(int n) const
Returns the maximum vertex index number used by the nth primitive in this object. ...
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...
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...
void set_data1i(int data)
Sets the write row to a particular 1-component value, and advances the write row. ...
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the data has already been prepared or enqueued for preparation on the indicated GSG...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
void get_referenced_vertices(BitArray &bits) const
Turns on all the bits corresponding to the vertices that are referenced by this GeomPrimitive.
int32_t get_int32()
Extracts a signed 32-bit integer.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
A table of objects that are saved within the graphics context for reference by handle later...
void set_usage_hint(UsageHint usage_hint)
Changes the UsageHint hint for this primitive.
void set_ends(PTA_int ends)
Completely replaces the primitive ends array with a new table.
void make_nonindexed(GeomVertexData *dest, const GeomVertexData *source)
Converts the primitive from indexed to nonindexed by duplicating vertices as necessary into the indic...
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
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.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
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.
A dynamic array with an unlimited number of bits.
A lightweight class that represents a single element that may be timed and/or counted via stats...
void add_vertex(int vertex)
Adds the indicated vertex to the list of vertex indices used by the graphics primitive type...
int get_primitive_min_vertex(int n) const
Returns the minimum vertex index number used by the nth primitive in this object. ...
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
Defines a series of "patches", fixed-size groupings of vertices that must be processed by a tessellat...
int get_primitive_start(int n) const
Returns the element within the _vertices list at which the nth primitive starts.
void set_range(int low_bit, int size)
Sets the indicated range of bits on.
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 ...
void add_consecutive_vertices(int start, int num_vertices)
Adds a consecutive sequence of vertices, beginning at start, to the primitive.
void release_index_buffer(IndexBufferContext *ibc)
Indicates that a data context, created by a previous call to prepare_index_buffer(), is no longer needed.
get_array_format
Returns the format object that describes this array.
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
void clear_vertices()
Removes all of the vertices and primitives from the object, so they can be re-added.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_lowest_on_bit() const
Returns the index of the lowest 1 bit in the array.
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 clear_minmax()
Undoes a previous call to set_minmax(), and allows the minimum and maximum values to be recomputed no...
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the array.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
int get_vertex(int i) const
Returns the ith vertex index in the table.
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()...
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
void set_row(int row)
Sets the start row to the indicated value.
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_strip_cut_index
Returns the index of the indicated type that is reserved for use as a strip cut index, if enabled for the primitive.
PT(CopyOnWriteObject) GeomPrimitive
Required to implement CopyOnWriteObject.
int get_num_rows() const
Returns the number of rows stored within all the arrays.
CPT(GeomPrimitive) GeomPrimitive
Decomposes a complex primitive type into a simpler primitive type, for instance triangle strips to tr...
void offset_vertices(int offset)
Adds the indicated offset to all vertices used by the primitive.
int get_data1i()
Returns the data associated with the read row, expressed as a 1-component value, and advances the rea...
Encodes a string name in a hash table, mapping it to a pointer.
void prepare(PreparedGraphicsObjects *prepared_objects)
Indicates that the data should be enqueued to be prepared in the indicated prepared_objects at the be...
Defines a series of disconnected line segments.
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 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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_bit(int index)
Sets the nth bit on.
void set_vertices(const GeomVertexArrayData *vertices, int num_vertices=-1)
Completely replaces the vertex index list with a new table.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
int get_num_primitives() const
Returns the number of individual primitives stored within this object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
get_shade_model
Returns the ShadeModel hint for this primitive.
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
get_usage_hint
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
A class to retrieve the individual data elements previously stored in a Datagram. ...
void set_nonindexed_vertices(int first_vertex, int num_vertices)
Sets the primitive up as a nonindexed primitive, using the indicated vertex range.
void clear()
Resets the GeomVertexReader to the initial state.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
void check_minmax() const
Ensures that the primitive's minmax cache has been computed.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void make_indexed()
Converts the primitive from nonindexed form to indexed form.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
int get_primitive_end(int n) const
Returns the element within the _vertices list at which the nth primitive ends.
get_num_unused_vertices_per_primitive
Returns the number of vertices that are added between primitives that aren't, strictly speaking...
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_num_vertices_per_primitive
If the primitive type is a simple type in which all primitives have the same number of vertices...
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter, combined together into one convenient package.
This is the data for one array of a GeomVertexData structure.
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.