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());
1045 make_adjacency()
const {
1054 get_num_bytes()
const {
1055 CDReader cdata(_cycler);
1056 int num_bytes = cdata->_ends.size() *
sizeof(int) +
sizeof(
GeomPrimitive);
1057 if (!cdata->_vertices.is_null()) {
1058 num_bytes += cdata->_vertices.get_read_pointer()->get_data_size_bytes();
1069 bool GeomPrimitive::
1070 request_resident(
Thread *current_thread)
const {
1071 CDReader cdata(_cycler, current_thread);
1073 bool resident =
true;
1075 if (!cdata->_vertices.is_null() &&
1076 !cdata->_vertices.get_read_pointer(current_thread)->request_resident(current_thread)) {
1081 if (!cdata->_mins.is_null() &&
1082 !cdata->_mins.get_read_pointer(current_thread)->request_resident(current_thread)) {
1085 if (!cdata->_maxs.is_null() &&
1086 !cdata->_maxs.get_read_pointer(current_thread)->request_resident(current_thread)) {
1097 void GeomPrimitive::
1098 output(std::ostream &out)
const {
1106 void GeomPrimitive::
1107 write(std::ostream &out,
int indent_level)
const {
1108 indent(out, indent_level)
1111 out <<
" (indexed)";
1113 out <<
" (nonindexed)";
1119 for (
int i = 0; i < num_primitives; ++i) {
1120 indent(out, indent_level + 2)
1124 for (
int vi = begin; vi < end; vi++) {
1128 if (end < num_vertices) {
1129 for (
int ui = 0; ui < num_unused_vertices_per_primitive; ++ui) {
1130 if (end + ui < num_vertices) {
1161 modify_vertices(
int num_vertices) {
1162 CDWriter cdata(_cycler,
true);
1164 cdata->_num_vertices = num_vertices;
1188 cdata->_num_vertices = num_vertices;
1193 cdata->_index_type = format->
get_column(0)->get_numeric_type();
1196 cdata->_got_minmax =
false;
1212 nassertv(num_vertices != -1);
1214 cdata->_vertices =
nullptr;
1215 cdata->_first_vertex = first_vertex;
1216 cdata->_num_vertices = num_vertices;
1219 cdata->_got_minmax =
false;
1222 recompute_minmax(cdata);
1246 cdata->_got_minmax =
false;
1248 if (cdata->_ends.get_ref_count() > 1) {
1250 new_ends.v() = cdata->_ends.v();
1251 cdata->_ends = new_ends;
1253 return cdata->_ends;
1275 cdata->_ends = ends;
1278 cdata->_got_minmax =
false;
1300 cdata->_min_vertex = min_vertex;
1301 cdata->_max_vertex = max_vertex;
1302 cdata->_mins = mins;
1303 cdata->_maxs = maxs;
1306 cdata->_got_minmax =
true;
1320 cdata->_got_minmax =
false;
1335 get_num_vertices_per_primitive()
const {
1348 get_min_num_vertices_per_primitive()
const {
1363 get_num_unused_vertices_per_primitive()
const {
1388 Contexts::const_iterator ci;
1389 ci = _contexts.find(prepared_objects);
1390 if (ci != _contexts.end()) {
1412 Contexts::const_iterator ci;
1413 ci = _contexts.find(prepared_objects);
1414 if (ci != _contexts.end()) {
1415 return (*ci).second;
1419 if (ibc !=
nullptr) {
1420 _contexts[prepared_objects] = ibc;
1431 Contexts::iterator ci;
1432 ci = _contexts.find(prepared_objects);
1433 if (ci != _contexts.end()) {
1454 int num_freed = (int)_contexts.size();
1456 Contexts::const_iterator ci;
1457 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1465 nassertr(_contexts.empty(), num_freed);
1476 switch (index_type) {
1480 if (cformat ==
nullptr) {
1481 cformat = make_index_format(NT_uint8);
1488 if (cformat ==
nullptr) {
1489 cformat = make_index_format(NT_uint16);
1496 if (cformat ==
nullptr) {
1497 cformat = make_index_format(NT_uint32);
1504 <<
"Not a valid index type: " << index_type <<
"\n";
1517 void GeomPrimitive::
1519 Contexts::iterator ci;
1520 ci = _contexts.find(prepared_objects);
1521 if (ci != _contexts.end()) {
1522 _contexts.erase(ci);
1526 nassert_raise(
"unknown PreparedGraphicsObjects");
1535 get_highest_index_value(NumericType index_type) {
1538 switch (index_type) {
1548 return 0x7fffffff - 1;
1562 get_strip_cut_index(NumericType index_type) {
1565 switch (index_type) {
1590 PN_stdfloat &sq_center_dist,
bool &found_any,
1592 bool got_mat,
const LMatrix4 &mat,
1594 Thread *current_thread)
const {
1601 CDReader cdata(_cycler, current_thread);
1604 if (cdata->_vertices.is_null()) {
1606 nassertv(cdata->_num_vertices != -1);
1607 if (cdata->_num_vertices == 0) {
1613 while (!found_any && i < cdata->_num_vertices) {
1614 reader.
set_row(cdata->_first_vertex + i);
1615 LPoint3 first_vertex = mat.xform_point(reader.
get_data3());
1616 if (!first_vertex.is_nan()) {
1617 min_point = first_vertex;
1618 max_point = first_vertex;
1619 sq_center_dist = first_vertex.length_squared();
1625 for (; i < cdata->_num_vertices; ++i) {
1627 LPoint3 vertex = mat.xform_point(reader.
get_data3());
1629 min_point.set(min(min_point[0], vertex[0]),
1630 min(min_point[1], vertex[1]),
1631 min(min_point[2], vertex[2]));
1632 max_point.set(max(max_point[0], vertex[0]),
1633 max(max_point[1], vertex[1]),
1634 max(max_point[2], vertex[2]));
1635 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1639 while (!found_any && i < cdata->_num_vertices) {
1640 reader.
set_row(cdata->_first_vertex + i);
1641 LPoint3 first_vertex = reader.
get_data3();
1642 if (!first_vertex.is_nan()) {
1643 min_point = first_vertex;
1644 max_point = first_vertex;
1645 sq_center_dist = first_vertex.length_squared();
1651 for (; i < cdata->_num_vertices; ++i) {
1653 const LVecBase3 &vertex = reader.
get_data3();
1655 min_point.set(min(min_point[0], vertex[0]),
1656 min(min_point[1], vertex[1]),
1657 min(min_point[2], vertex[2]));
1658 max_point.set(max(max_point[0], vertex[0]),
1659 max(max_point[1], vertex[1]),
1660 max(max_point[2], vertex[2]));
1661 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1667 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
1668 if (index.is_at_end()) {
1676 while (!found_any && !index.is_at_end()) {
1677 int ii = index.get_data1i();
1678 if (ii != strip_cut_index) {
1680 LPoint3 first_vertex = mat.xform_point(reader.
get_data3());
1681 if (!first_vertex.is_nan()) {
1682 min_point = first_vertex;
1683 max_point = first_vertex;
1684 sq_center_dist = first_vertex.length_squared();
1690 while (!index.is_at_end()) {
1691 int ii = index.get_data1i();
1692 if (ii == strip_cut_index) {
1696 LPoint3 vertex = mat.xform_point(reader.
get_data3());
1698 min_point.set(min(min_point[0], vertex[0]),
1699 min(min_point[1], vertex[1]),
1700 min(min_point[2], vertex[2]));
1701 max_point.set(max(max_point[0], vertex[0]),
1702 max(max_point[1], vertex[1]),
1703 max(max_point[2], vertex[2]));
1704 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1708 while (!found_any && !index.is_at_end()) {
1709 int ii = index.get_data1i();
1710 if (ii != strip_cut_index) {
1712 LVecBase3 first_vertex = reader.
get_data3();
1713 if (!first_vertex.is_nan()) {
1714 min_point = first_vertex;
1715 max_point = first_vertex;
1716 sq_center_dist = first_vertex.length_squared();
1722 while (!index.is_at_end()) {
1723 int ii = index.get_data1i();
1724 if (ii == strip_cut_index) {
1728 const LVecBase3 &vertex = reader.
get_data3();
1730 min_point.set(min(min_point[0], vertex[0]),
1731 min(min_point[1], vertex[1]),
1732 min(min_point[2], vertex[2]));
1733 max_point.set(max(max_point[0], vertex[0]),
1734 max(max_point[1], vertex[1]),
1735 max(max_point[2], vertex[2]));
1736 sq_center_dist = max(sq_center_dist, vertex.length_squared());
1752 Thread *current_thread)
const {
1753 GeomVertexReader reader(vertex_data, InternalName::get_vertex(), current_thread);
1763 CDReader cdata(_cycler, current_thread);
1765 if (cdata->_vertices.is_null()) {
1767 nassertv(cdata->_num_vertices != -1);
1768 if (cdata->_num_vertices == 0) {
1773 for (
int i = 0; i < cdata->_num_vertices; ++i) {
1775 const LVecBase3 &vertex = reader.
get_data3();
1777 sq_radius = max(sq_radius, (vertex - center).length_squared());
1782 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
1783 if (index.is_at_end()) {
1790 while (!index.is_at_end()) {
1791 int ii = index.get_data1i();
1792 if (ii == strip_cut_index) {
1796 const LVecBase3 &vertex = reader.
get_data3();
1798 sq_radius = max(sq_radius, (vertex - center).length_squared());
1814 decompose_impl()
const {
1822 rotate_impl()
const {
1824 nassertr(
false,
nullptr);
1832 doubleside_impl()
const {
1840 reverse_impl()
const {
1848 bool GeomPrimitive::
1849 requires_unused_vertices()
const {
1862 void GeomPrimitive::
1869 void GeomPrimitive::
1870 recompute_minmax(GeomPrimitive::CData *cdata) {
1871 if (cdata->_vertices.is_null()) {
1874 nassertv(cdata->_num_vertices != -1);
1875 cdata->_min_vertex = cdata->_first_vertex;
1876 cdata->_max_vertex = cdata->_first_vertex + cdata->_num_vertices - 1;
1877 cdata->_mins.clear();
1878 cdata->_maxs.clear();
1881 int num_vertices = cdata->_vertices.get_read_pointer()->get_num_rows();
1883 if (num_vertices == 0) {
1885 cdata->_min_vertex = 0;
1886 cdata->_max_vertex = 0;
1887 cdata->_mins.clear();
1888 cdata->_maxs.clear();
1895 cdata->_mins = make_index_data();
1896 cdata->_maxs = make_index_data();
1909 unsigned int vertex = index.get_data1i();
1910 cdata->_min_vertex = vertex;
1911 cdata->_max_vertex = vertex;
1912 unsigned int min_prim = vertex;
1913 unsigned int max_prim = vertex;
1917 for (
int vi = 1; vi < num_vertices; ++vi) {
1918 nassertv(!index.is_at_end());
1919 nassertv(pi < (
int)cdata->_ends.size());
1921 unsigned int vertex;
1923 if (vi == cdata->_ends[pi]) {
1926 if (num_unused_vertices > 0) {
1927 vi += num_unused_vertices;
1928 index.set_row_unsafe(vi);
1930 vertex = index.get_data1i();
1932 mins.set_data1i(min_prim);
1933 maxs.set_data1i(max_prim);
1939 vertex = index.get_data1i();
1940 min_prim = min(min_prim, vertex);
1941 max_prim = max(max_prim, vertex);
1944 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
1945 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
1948 mins.set_data1i(min_prim);
1949 maxs.set_data1i(max_prim);
1950 nassertv(mins.get_array_data()->get_num_rows() == (int)cdata->_ends.size());
1957 cdata->_mins.
clear();
1958 cdata->_maxs.clear();
1960 unsigned int vertex = index.get_data1i();
1961 cdata->_min_vertex = vertex;
1962 cdata->_max_vertex = vertex;
1964 for (
int vi = 1; vi < num_vertices; ++vi) {
1965 nassertv(!index.is_at_end());
1966 unsigned int vertex = index.get_data1i();
1967 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
1968 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
1973 cdata->_got_minmax =
true;
1979 void GeomPrimitive::
1980 do_make_indexed(CData *cdata) {
1981 if (cdata->_vertices.is_null()) {
1982 if (gobj_cat.is_debug()) {
1984 <<
this <<
".make_indexed()\n";
1987 nassertv(cdata->_num_vertices != -1);
1988 cdata->_vertices = make_index_data();
1994 for (
int i = 0; i < cdata->_num_vertices; ++i) {
1995 index.set_data1i(i + cdata->_first_vertex);
1997 cdata->_num_vertices = -1;
2005 void GeomPrimitive::
2006 consider_elevate_index_type(CData *cdata,
int vertex) {
2010 switch (cdata->_index_type) {
2012 if (vertex >= 0xff) {
2013 do_set_index_type(cdata, NT_uint16);
2018 if (vertex >= 0xffff) {
2019 do_set_index_type(cdata, NT_uint32);
2025 nassertv(vertex < 0x7fffffff);
2036 void GeomPrimitive::
2037 do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
2041 cdata->_index_type = index_type;
2043 if (gobj_cat.is_debug()) {
2045 <<
this <<
".set_index_type(" << index_type <<
")\n";
2048 if (!cdata->_vertices.is_null()) {
2052 if (array_obj->get_array_format() != new_format) {
2054 new_vertices->set_num_rows(array_obj->get_num_rows());
2059 while (!from.is_at_end()) {
2060 int index = from.get_data1i();
2061 if (index == old_strip_cut_index) {
2062 index = new_strip_cut_index;
2064 to.set_data1i(index);
2066 cdata->_vertices = new_vertices;
2067 cdata->_got_minmax =
false;
2076 do_modify_vertices(GeomPrimitive::CData *cdata) {
2077 if (cdata->_vertices.is_null()) {
2078 do_make_indexed(cdata);
2084 cdata->_got_minmax =
false;
2107 if (vertices !=
nullptr) {
2116 void GeomPrimitive::
2129 return new CData(*
this);
2136 void GeomPrimitive::CData::
2145 WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends);
2152 int GeomPrimitive::CData::
2172 void GeomPrimitive::CData::
2174 _shade_model = (ShadeModel)scan.
get_uint8();
2177 _index_type = (NumericType)scan.
get_uint8();
2178 _usage_hint = (UsageHint)scan.
get_uint8();
2181 READ_PTA(manager, scan, IPD_int::read_datagram, _ends);
2184 _got_minmax =
false;
2192 if (!_cdata->_got_minmax) {
2196 #ifdef DO_PIPELINING 2200 false, _current_thread);
2202 #ifdef DO_PIPELINING 2206 if (!fresh_cdata->_got_minmax) {
2208 ((
GeomPrimitive *)_object.p())->recompute_minmax(fresh_cdata);
2209 nassertv(fresh_cdata->_got_minmax);
2218 nassertv(_cdata->_got_minmax);
2224 int GeomPrimitivePipelineReader::
2225 get_first_vertex()
const {
2226 if (_vertices.is_null()) {
2227 return _cdata->_first_vertex;
2230 size_t size = _vertices_cdata->_buffer.get_size();
2236 return index.get_data1i();
2244 if (!_vertices.is_null()) {
2246 nassertr(i >= 0 && i < get_num_vertices(), -1);
2248 const unsigned char *ptr = get_read_pointer(
true);
2249 switch (_cdata->_index_type) {
2250 case GeomEnums::NT_uint8:
2251 return ((uint8_t *)ptr)[i];
2253 case GeomEnums::NT_uint16:
2254 return ((uint16_t *)ptr)[i];
2256 case GeomEnums::NT_uint32:
2257 return ((uint32_t *)ptr)[i];
2260 nassert_raise(
"unsupported index type");
2266 return _cdata->_first_vertex + i;
2273 int GeomPrimitivePipelineReader::
2274 get_num_primitives()
const {
2275 int num_vertices_per_primitive = _object->get_num_vertices_per_primitive();
2277 if (num_vertices_per_primitive == 0) {
2280 return _cdata->_ends.size();
2285 return (get_num_vertices() / num_vertices_per_primitive);
2295 int num_vertices = get_num_vertices();
2298 int strip_cut_index = get_strip_cut_index();
2299 const unsigned char *ptr = get_read_pointer(
true);
2300 switch (get_index_type()) {
2301 case GeomEnums::NT_uint8:
2302 for (
int vi = 0; vi < num_vertices; ++vi) {
2303 int index = ((
const uint8_t *)ptr)[vi];
2304 if (index != strip_cut_index) {
2309 case GeomEnums::NT_uint16:
2310 for (
int vi = 0; vi < num_vertices; ++vi) {
2311 int index = ((
const uint16_t *)ptr)[vi];
2312 if (index != strip_cut_index) {
2317 case GeomEnums::NT_uint32:
2318 for (
int vi = 0; vi < num_vertices; ++vi) {
2319 int index = ((
const uint32_t *)ptr)[vi];
2320 if (index != strip_cut_index) {
2326 nassert_raise(
"unsupported index type");
2331 bits.
set_range(get_first_vertex(), num_vertices);
2338 bool GeomPrimitivePipelineReader::
2340 if (get_num_vertices() != 0 &&
2341 data_reader->get_num_arrays() > 0 &&
2342 get_max_vertex() >= data_reader->get_num_rows()) {
2346 << get_object()->get_type() <<
" references vertices up to " 2347 << get_max_vertex() <<
", but GeomVertexData has only " 2348 << 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(),...
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,...
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,...
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(),...
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,...
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,...
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.