15 #include "geomPrimitive.h" 17 #include "geomPatches.h" 18 #include "geomVertexData.h" 19 #include "geomVertexArrayFormat.h" 20 #include "geomVertexColumn.h" 21 #include "geomVertexReader.h" 22 #include "geomVertexWriter.h" 23 #include "geomVertexRewriter.h" 24 #include "geomPoints.h" 25 #include "geomLines.h" 26 #include "geomTriangles.h" 27 #include "preparedGraphicsObjects.h" 28 #include "internalName.h" 29 #include "bamReader.h" 30 #include "bamWriter.h" 31 #include "ioPtaDatagramInt.h" 33 #include "pStatTimer.h" 37 TypeHandle GeomPrimitivePipelineReader::_type_handle;
39 PStatCollector GeomPrimitive::_decompose_pcollector(
"*:Munge:Decompose");
40 PStatCollector GeomPrimitive::_doubleside_pcollector(
"*:Munge:Doubleside");
41 PStatCollector GeomPrimitive::_reverse_pcollector(
"*:Munge:Reverse");
42 PStatCollector GeomPrimitive::_rotate_pcollector(
"*:Munge:Rotate");
70 GeomPrimitive(GeomPrimitive::UsageHint usage_hint) {
71 CDWriter cdata(_cycler,
true);
72 cdata->_usage_hint = usage_hint;
97 CopyOnWriteObject::operator = (copy);
98 _cycler = copy._cycler;
121 return GR_indexed_other;
140 cdata->_usage_hint = usage_hint;
142 if (!cdata->_vertices.is_null()) {
144 cdata->_usage_hint = usage_hint;
168 nassertv(get_max_vertex() <= get_highest_index_value(index_type));
171 if (cdata->_index_type != index_type) {
172 do_set_index_type(cdata, index_type);
194 if (gobj_cat.is_spam()) {
196 <<
this <<
".add_vertex(" << vertex <<
")\n";
199 consider_elevate_index_type(cdata, vertex);
201 int num_primitives = get_num_primitives();
202 if (num_primitives > 0 &&
203 requires_unused_vertices() &&
204 get_num_vertices() == get_primitive_end(num_primitives - 1)) {
207 if (cdata->_vertices.is_null()) {
208 do_make_indexed(cdata);
210 append_unused_vertices(cdata->_vertices.get_write_pointer(), vertex);
213 if (cdata->_vertices.is_null()) {
216 nassertv(cdata->_num_vertices != -1);
217 if (cdata->_num_vertices == 0) {
218 cdata->_first_vertex = vertex;
219 cdata->_num_vertices = 1;
221 cdata->_got_minmax =
false;
224 }
else if (vertex == cdata->_first_vertex + cdata->_num_vertices) {
225 ++cdata->_num_vertices;
227 cdata->_got_minmax =
false;
232 do_make_indexed(cdata);
242 cdata->_got_minmax =
false;
257 if (num_vertices == 0) {
260 int end = (start + num_vertices) - 1;
264 consider_elevate_index_type(cdata, end);
266 int num_primitives = get_num_primitives();
267 if (num_primitives > 0 &&
268 get_num_vertices() == get_primitive_end(num_primitives - 1)) {
271 if (cdata->_vertices.is_null()) {
272 do_make_indexed(cdata);
274 append_unused_vertices(cdata->_vertices.get_write_pointer(), start);
277 if (cdata->_vertices.is_null()) {
280 nassertv(cdata->_num_vertices != -1);
281 if (cdata->_num_vertices == 0) {
282 cdata->_first_vertex = start;
283 cdata->_num_vertices = num_vertices;
285 cdata->_got_minmax =
false;
288 }
else if (start == cdata->_first_vertex + cdata->_num_vertices) {
289 cdata->_num_vertices += num_vertices;
291 cdata->_got_minmax =
false;
296 do_make_indexed(cdata);
300 int old_num_rows = array_obj->get_num_rows();
301 array_obj->set_num_rows(old_num_rows + num_vertices);
306 for (
int v = start; v <= end; ++v) {
311 cdata->_got_minmax =
false;
327 if (get_num_vertices() == 0) {
328 add_consecutive_vertices(0, num_vertices);
330 add_consecutive_vertices(
get_vertex(get_num_vertices() - 1) + 1, num_vertices);
358 if (gobj_cat.is_debug()) {
360 <<
this <<
".reserve_num_vertices(" << num_vertices <<
")\n";
364 consider_elevate_index_type(cdata, num_vertices);
365 do_make_indexed(cdata);
367 array_obj->reserve_num_rows(num_vertices);
384 int num_vertices_per_primitive = get_num_vertices_per_primitive();
387 if (num_vertices_per_primitive == 0) {
392 if (cdata->_ends.empty()) {
393 num_added = get_num_vertices();
395 num_added = get_num_vertices() - cdata->_ends.back();
396 num_added -= get_num_unused_vertices_per_primitive();
398 nassertr(num_added >= get_min_num_vertices_per_primitive(),
false);
400 if (cdata->_ends.get_ref_count() > 1) {
402 new_ends.v() = cdata->_ends.v();
403 cdata->_ends = new_ends;
405 cdata->_ends.push_back(get_num_vertices());
412 int num_vertices_per_primitive = get_num_vertices_per_primitive();
413 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
415 int num_vertices = get_num_vertices();
416 nassertr((num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0,
false)
438 cdata->_first_vertex = 0;
439 cdata->_num_vertices = 0;
444 cdata->_index_type = NT_uint16;
446 cdata->_vertices.clear();
447 cdata->_ends.clear();
448 cdata->_mins.clear();
449 cdata->_maxs.clear();
451 cdata->_got_minmax =
false;
473 if (!cdata->_got_minmax) {
474 recompute_minmax(cdata);
475 nassertv(cdata->_got_minmax);
478 consider_elevate_index_type(cdata, cdata->_max_vertex + offset);
480 int strip_cut_index = get_strip_cut_index(cdata->_index_type);
486 if (vertex != strip_cut_index) {
494 cdata->_first_vertex += offset;
496 cdata->_got_minmax =
false;
498 consider_elevate_index_type(cdata,
499 cdata->_first_vertex + cdata->_num_vertices - 1);
517 if (offset == 0 || end_row <= begin_row) {
521 nassertv(begin_row >= 0 && end_row >= 0);
522 nassertv(end_row <= get_num_vertices());
524 if (!is_indexed() && (begin_row > 0 || end_row < get_num_vertices())) {
532 int strip_cut_index = get_strip_cut_index(cdata->_index_type);
539 for (
int j = begin_row; j < end_row; ++j) {
540 int vertex = index_r.get_data1i();
541 if (vertex != strip_cut_index) {
542 max_vertex = max(max_vertex, vertex);
547 consider_elevate_index_type(cdata, max_vertex + offset);
551 for (
int j = begin_row; j < end_row; ++j) {
553 if (vertex != strip_cut_index) {
563 cdata->_first_vertex += offset;
565 cdata->_got_minmax =
false;
567 consider_elevate_index_type(cdata,
568 cdata->_first_vertex + cdata->_num_vertices - 1);
583 int num_vertices = get_num_vertices();
585 int strip_cut_index = get_strip_cut_index();
588 for (
int i = 0; i < num_vertices; ++i) {
590 nassertd(v != strip_cut_index)
continue;
591 dest->
copy_row_from(dest_start + i, source, v, current_thread);
594 set_nonindexed_vertices(dest_start, num_vertices);
618 CopiedIndices copied_indices;
620 int num_vertices = get_num_vertices();
622 int strip_cut_index = get_strip_cut_index();
624 for (
int i = 0; i < num_vertices; ++i) {
626 if (v == strip_cut_index) {
633 pair<CopiedIndices::iterator, bool> result =
634 copied_indices.insert(CopiedIndices::value_type(v, (
int)copied_indices.size()));
635 int v2 = (*result.first).second + dest_start;
644 set_vertices(new_vertices);
666 do_make_indexed(cdata);
685 int num_vertices_per_primitive = get_num_vertices_per_primitive();
686 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
688 if (num_vertices_per_primitive == 0) {
692 nassertr(n >= 0 && n <= (
int)cdata->_ends.size(), -1);
696 return cdata->_ends[n - 1] + num_unused_vertices_per_primitive;
702 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive);
715 int num_vertices_per_primitive = get_num_vertices_per_primitive();
717 if (num_vertices_per_primitive == 0) {
721 nassertr(n >= 0 && n < (
int)cdata->_ends.size(), -1);
722 return cdata->_ends[n];
727 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
728 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive) + num_vertices_per_primitive;
741 int num_vertices_per_primitive = get_num_vertices_per_primitive();
743 if (num_vertices_per_primitive == 0) {
747 nassertr(n >= 0 && n < (
int)cdata->_ends.size(), 0);
749 return cdata->_ends[0];
751 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
752 return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive;
758 return num_vertices_per_primitive;
774 int num_primitives = get_num_primitives();
776 if (num_primitives > 0) {
777 return get_num_vertices() - ((num_primitives - 1) *
778 get_num_unused_vertices_per_primitive());
794 nassertr(n >= 0 && n < mins->get_num_rows(), -1);
800 return get_primitive_start(n);
814 nassertr(n >= 0 && n < maxs->get_num_rows(), -1);
820 return get_primitive_end(n) - 1;
840 if (gobj_cat.is_debug()) {
842 <<
"Decomposing " << get_type() <<
": " << (
void *)
this <<
"\n";
846 return decompose_impl();
865 if (gobj_cat.is_debug()) {
867 <<
"Rotating " << get_type() <<
": " << (
void *)
this <<
"\n";
879 new_prim->set_vertices(rotated_vertices);
882 case SM_flat_first_vertex:
883 new_prim->set_shade_model(SM_flat_last_vertex);
886 case SM_flat_last_vertex:
887 new_prim->set_shade_model(SM_flat_first_vertex);
914 if (gobj_cat.is_debug()) {
916 <<
"Doublesiding " << get_type() <<
": " << (
void *)
this <<
"\n";
920 return doubleside_impl();
940 if (gobj_cat.is_debug()) {
942 <<
"Reversing " << get_type() <<
": " << (
void *)
this <<
"\n";
946 return reverse_impl();
963 match_shade_model(GeomPrimitive::ShadeModel shade_model)
const {
965 if (this_shade_model == shade_model) {
970 if (this_shade_model == SM_uniform || shade_model == SM_uniform) {
975 if ((this_shade_model == SM_flat_first_vertex && shade_model == SM_flat_last_vertex) ||
976 (this_shade_model == SM_flat_last_vertex && shade_model == SM_flat_first_vertex)) {
979 if (rotated.p() ==
this) {
1000 make_points()
const {
1008 int num_vertices = get_num_vertices();
1011 int strip_cut_index = get_strip_cut_index();
1013 for (
int vi = 0; vi < num_vertices; ++vi) {
1016 if (vertex != strip_cut_index) {
1021 int first_vertex = get_first_vertex();
1022 bits.
set_range(first_vertex, num_vertices);
1044 points->set_vertices(new_vertices);
1059 make_lines()
const {
1065 if (prim_type == PT_lines) {
1069 }
else if (prim_type != PT_polygons && prim_type != PT_patches) {
1074 if (prim_type == PT_polygons && !
is_exact_type(GeomTriangles::get_class_type())) {
1077 return decompose()->make_lines();
1081 int num_primitives = get_num_primitives();
1082 int verts_per_prim = get_num_vertices_per_primitive();
1085 new_vertices->unclean_set_num_rows(num_primitives * verts_per_prim * 2);
1089 for (
int i = 0; i < num_primitives; ++i) {
1090 int begin = get_primitive_start(i);
1091 int end = get_primitive_end(i);
1095 for (
int vi = begin; vi < end - 1; vi++) {
1104 lines->set_vertices(new_vertices);
1123 make_patches()
const {
1129 int num_vertices_per_patch = prim->get_num_vertices_per_primitive();
1133 if (prim->is_indexed()) {
1134 patches->set_vertices(prim->get_vertices());
1136 patches->set_nonindexed_vertices(prim->get_first_vertex(),
1137 prim->get_num_vertices());
1150 get_num_bytes()
const {
1152 int num_bytes = cdata->_ends.size() *
sizeof(int) +
sizeof(
GeomPrimitive);
1153 if (!cdata->_vertices.is_null()) {
1154 num_bytes += cdata->_vertices.get_read_pointer()->get_data_size_bytes();
1168 bool GeomPrimitive::
1169 request_resident()
const {
1172 bool resident =
true;
1174 if (!cdata->_vertices.is_null() &&
1175 !cdata->_vertices.get_read_pointer()->request_resident()) {
1179 if (is_composite() && cdata->_got_minmax) {
1180 if (!cdata->_mins.is_null() &&
1181 !cdata->_mins.get_read_pointer()->request_resident()) {
1184 if (!cdata->_maxs.is_null() &&
1185 !cdata->_maxs.get_read_pointer()->request_resident()) {
1198 void GeomPrimitive::
1199 output(ostream &out)
const {
1200 out << get_type() <<
", " << get_num_primitives()
1201 <<
", " << get_num_vertices();
1209 void GeomPrimitive::
1210 write(ostream &out,
int indent_level)
const {
1211 indent(out, indent_level)
1214 out <<
" (indexed)";
1216 out <<
" (nonindexed)";
1219 int num_primitives = get_num_primitives();
1220 int num_vertices = get_num_vertices();
1221 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
1222 for (
int i = 0; i < num_primitives; ++i) {
1223 indent(out, indent_level + 2)
1225 int begin = get_primitive_start(i);
1226 int end = get_primitive_end(i);
1227 for (
int vi = begin; vi < end; vi++) {
1231 if (end < num_vertices) {
1232 for (
int ui = 0; ui < num_unused_vertices_per_primitive; ++ui) {
1233 if (end + ui < num_vertices) {
1270 modify_vertices(
int num_vertices) {
1273 cdata->_num_vertices = num_vertices;
1302 cdata->_num_vertices = num_vertices;
1306 nassertv(format->get_num_columns() == 1);
1307 cdata->_index_type = format->get_column(0)->get_numeric_type();
1310 cdata->_got_minmax =
false;
1330 nassertv(num_vertices != -1);
1333 cdata->_first_vertex = first_vertex;
1334 cdata->_num_vertices = num_vertices;
1337 cdata->_got_minmax =
false;
1340 recompute_minmax(cdata);
1369 cdata->_got_minmax =
false;
1371 if (cdata->_ends.get_ref_count() > 1) {
1373 new_ends.v() = cdata->_ends.v();
1374 cdata->_ends = new_ends;
1376 return cdata->_ends;
1403 cdata->_ends = (PTA_int &)ends;
1406 cdata->_got_minmax =
false;
1434 cdata->_min_vertex = min_vertex;
1435 cdata->_max_vertex = max_vertex;
1436 cdata->_mins = mins;
1437 cdata->_maxs = maxs;
1440 cdata->_got_minmax =
true;
1458 cdata->_got_minmax =
false;
1545 Contexts::const_iterator ci;
1546 ci = _contexts.find(prepared_objects);
1547 if (ci != _contexts.end()) {
1572 nassertr(is_indexed(), NULL);
1574 Contexts::const_iterator ci;
1575 ci = _contexts.find(prepared_objects);
1576 if (ci != _contexts.end()) {
1577 return (*ci).second;
1582 _contexts[prepared_objects] = ibc;
1596 Contexts::iterator ci;
1597 ci = _contexts.find(prepared_objects);
1598 if (ci != _contexts.end()) {
1622 int num_freed = (int)_contexts.size();
1624 Contexts::const_iterator ci;
1625 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1633 nassertr(_contexts.empty(), num_freed);
1647 switch (index_type) {
1650 static CPT(GeomVertexArrayFormat) cformat = NULL;
1651 if (cformat == NULL) {
1652 cformat = make_index_format(NT_uint8);
1658 static CPT(GeomVertexArrayFormat) cformat = NULL;
1659 if (cformat == NULL) {
1660 cformat = make_index_format(NT_uint16);
1666 static CPT(GeomVertexArrayFormat) cformat = NULL;
1667 if (cformat == NULL) {
1668 cformat = make_index_format(NT_uint32);
1675 <<
"Not a valid index type: " << index_type <<
"\n";
1692 void GeomPrimitive::
1694 Contexts::iterator ci;
1695 ci = _contexts.find(prepared_objects);
1696 if (ci != _contexts.end()) {
1697 _contexts.erase(ci);
1713 get_highest_index_value(NumericType index_type) {
1716 switch (index_type) {
1726 return 0x7fffffff - 1;
1743 get_strip_cut_index(NumericType index_type) {
1746 switch (index_type) {
1776 PN_stdfloat &sq_center_dist,
bool &found_any,
1779 const InternalName *column_name,
1780 Thread *current_thread)
const {
1787 CDReader cdata(_cycler, current_thread);
1790 if (cdata->_vertices.is_null()) {
1792 nassertv(cdata->_num_vertices != -1);
1793 if (cdata->_num_vertices == 0) {
1801 min_point = first_vertex;
1802 max_point = first_vertex;
1808 for (; i < cdata->_num_vertices; ++i) {
1812 min_point.set(min(min_point[0], vertex[0]),
1813 min(min_point[1], vertex[1]),
1814 min(min_point[2], vertex[2]));
1815 max_point.set(max(max_point[0], vertex[0]),
1816 max(max_point[1], vertex[1]),
1817 max(max_point[2], vertex[2]));
1824 min_point = first_vertex;
1825 max_point = first_vertex;
1831 for (; i < cdata->_num_vertices; ++i) {
1835 min_point.set(min(min_point[0], vertex[0]),
1836 min(min_point[1], vertex[1]),
1837 min(min_point[2], vertex[2]));
1838 max_point.set(max(max_point[0], vertex[0]),
1839 max(max_point[1], vertex[1]),
1840 max(max_point[2], vertex[2]));
1847 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
1848 if (index.is_at_end()) {
1852 int strip_cut_index = get_strip_cut_index(cdata->_index_type);
1856 int first_index = index.get_data1i();
1857 nassertv(first_index != strip_cut_index);
1860 min_point = first_vertex;
1861 max_point = first_vertex;
1866 while (!index.is_at_end()) {
1867 int ii = index.get_data1i();
1868 if (ii == strip_cut_index) {
1874 min_point.set(min(min_point[0], vertex[0]),
1875 min(min_point[1], vertex[1]),
1876 min(min_point[2], vertex[2]));
1877 max_point.set(max(max_point[0], vertex[0]),
1878 max(max_point[1], vertex[1]),
1879 max(max_point[2], vertex[2]));
1884 int first_index = index.get_data1i();
1885 nassertv(first_index != strip_cut_index);
1888 min_point = first_vertex;
1889 max_point = first_vertex;
1894 while (!index.is_at_end()) {
1895 int ii = index.get_data1i();
1896 if (ii == strip_cut_index) {
1902 min_point.set(min(min_point[0], vertex[0]),
1903 min(min_point[1], vertex[1]),
1904 min(min_point[2], vertex[2]));
1905 max_point.set(max(max_point[0], vertex[0]),
1906 max(max_point[1], vertex[1]),
1907 max(max_point[2], vertex[2]));
1926 Thread *current_thread)
const {
1927 GeomVertexReader reader(vertex_data, InternalName::get_vertex(), current_thread);
1937 CDReader cdata(_cycler, current_thread);
1939 if (cdata->_vertices.is_null()) {
1941 nassertv(cdata->_num_vertices != -1);
1942 if (cdata->_num_vertices == 0) {
1947 for (
int i = 0; i < cdata->_num_vertices; ++i) {
1951 sq_radius = max(sq_radius, (vertex - center).length_squared());
1956 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
1957 if (index.is_at_end()) {
1962 int strip_cut_index = get_strip_cut_index(cdata->_index_type);
1964 while (!index.is_at_end()) {
1965 int ii = index.get_data1i();
1966 if (ii == strip_cut_index) {
1972 sq_radius = max(sq_radius, (vertex - center).length_squared());
1992 decompose_impl()
const {
2002 rotate_impl()
const {
2004 nassertr(
false, NULL);
2014 doubleside_impl()
const {
2024 reverse_impl()
const {
2034 bool GeomPrimitive::
2035 requires_unused_vertices()
const {
2051 void GeomPrimitive::
2061 void GeomPrimitive::
2062 recompute_minmax(GeomPrimitive::CData *cdata) {
2063 if (cdata->_vertices.is_null()) {
2066 nassertv(cdata->_num_vertices != -1);
2067 cdata->_min_vertex = cdata->_first_vertex;
2068 cdata->_max_vertex = cdata->_first_vertex + cdata->_num_vertices - 1;
2069 cdata->_mins.clear();
2070 cdata->_maxs.clear();
2073 int num_vertices = cdata->_vertices.get_read_pointer()->get_num_rows();
2075 if (num_vertices == 0) {
2077 cdata->_min_vertex = 0;
2078 cdata->_max_vertex = 0;
2079 cdata->_mins.clear();
2080 cdata->_maxs.clear();
2082 }
else if (get_num_vertices_per_primitive() == 0) {
2087 cdata->_mins = make_index_data();
2088 cdata->_maxs = make_index_data();
2101 unsigned int vertex = index.get_data1i();
2102 cdata->_min_vertex = vertex;
2103 cdata->_max_vertex = vertex;
2104 unsigned int min_prim = vertex;
2105 unsigned int max_prim = vertex;
2107 int num_unused_vertices = get_num_unused_vertices_per_primitive();
2109 for (
int vi = 1; vi < num_vertices; ++vi) {
2110 nassertv(!index.is_at_end());
2111 nassertv(pi < (
int)cdata->_ends.size());
2113 unsigned int vertex;
2115 if (vi == cdata->_ends[pi]) {
2118 if (num_unused_vertices > 0) {
2119 vi += num_unused_vertices;
2120 index.set_row_unsafe(vi);
2122 vertex = index.get_data1i();
2131 vertex = index.get_data1i();
2132 min_prim = min(min_prim, vertex);
2133 max_prim = max(max_prim, vertex);
2136 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
2137 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
2149 cdata->_mins.
clear();
2150 cdata->_maxs.clear();
2152 unsigned int vertex = index.get_data1i();
2153 cdata->_min_vertex = vertex;
2154 cdata->_max_vertex = vertex;
2156 for (
int vi = 1; vi < num_vertices; ++vi) {
2157 nassertv(!index.is_at_end());
2158 unsigned int vertex = index.get_data1i();
2159 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
2160 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
2165 cdata->_got_minmax =
true;
2173 void GeomPrimitive::
2174 do_make_indexed(CData *cdata) {
2175 if (cdata->_vertices.is_null()) {
2176 if (gobj_cat.is_debug()) {
2178 <<
this <<
".make_indexed()\n";
2181 nassertv(cdata->_num_vertices != -1);
2182 cdata->_vertices = make_index_data();
2188 for (
int i = 0; i < cdata->_num_vertices; ++i) {
2191 cdata->_num_vertices = -1;
2202 void GeomPrimitive::
2203 consider_elevate_index_type(CData *cdata,
int vertex) {
2207 switch (cdata->_index_type) {
2209 if (vertex >= 0xff) {
2210 do_set_index_type(cdata, NT_uint16);
2215 if (vertex >= 0xffff) {
2216 do_set_index_type(cdata, NT_uint32);
2222 nassertv(vertex < 0x7fffffff);
2235 void GeomPrimitive::
2236 do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
2237 int old_strip_cut_index = get_strip_cut_index(cdata->_index_type);
2238 int new_strip_cut_index = get_strip_cut_index(index_type);
2240 cdata->_index_type = index_type;
2242 if (gobj_cat.is_debug()) {
2244 <<
this <<
".set_index_type(" << index_type <<
")\n";
2247 if (!cdata->_vertices.is_null()) {
2248 CPT(GeomVertexArrayFormat) new_format = get_index_format();
2251 if (array_obj->get_array_format() != new_format) {
2253 new_vertices->set_num_rows(array_obj->get_num_rows());
2260 if (index == old_strip_cut_index) {
2261 index = new_strip_cut_index;
2265 cdata->_vertices = new_vertices;
2266 cdata->_got_minmax =
false;
2277 do_modify_vertices(GeomPrimitive::CData *cdata) {
2278 if (cdata->_vertices.is_null()) {
2279 do_make_indexed(cdata);
2285 cdata->_got_minmax =
false;
2324 void GeomPrimitive::
2339 return new CData(*
this);
2348 void GeomPrimitive::CData::
2357 WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends);
2367 int GeomPrimitive::CData::
2390 void GeomPrimitive::CData::
2392 _shade_model = (ShadeModel)scan.
get_uint8();
2395 _index_type = (NumericType)scan.
get_uint8();
2396 _usage_hint = (UsageHint)scan.
get_uint8();
2399 READ_PTA(manager, scan, IPD_int::read_datagram, _ends);
2402 _got_minmax =
false;
2413 if (!_cdata->_got_minmax) {
2418 #ifdef DO_PIPELINING 2422 false, _current_thread);
2424 #ifdef DO_PIPELINING 2428 if (!fresh_cdata->_got_minmax) {
2431 ((
GeomPrimitive *)_object.p())->recompute_minmax(fresh_cdata);
2432 nassertv(fresh_cdata->_got_minmax);
2441 nassertv(_cdata->_got_minmax);
2449 int GeomPrimitivePipelineReader::
2450 get_first_vertex()
const {
2451 if (_cdata->_vertices.is_null()) {
2452 return _cdata->_first_vertex;
2453 }
else if (_vertices_reader->get_num_rows() == 0) {
2468 if (!_cdata->_vertices.is_null()) {
2470 nassertr(i >= 0 && i < _vertices_reader->get_num_rows(), -1);
2474 return index.get_data1i();
2478 return _cdata->_first_vertex + i;
2487 int GeomPrimitivePipelineReader::
2488 get_num_primitives()
const {
2489 int num_vertices_per_primitive = _object->get_num_vertices_per_primitive();
2491 if (num_vertices_per_primitive == 0) {
2494 return _cdata->_ends.size();
2499 return (get_num_vertices() / num_vertices_per_primitive);
2508 bool GeomPrimitivePipelineReader::
2510 if (get_num_vertices() != 0 &&
2511 get_max_vertex() >= data_reader->get_num_rows()) {
2515 << get_object()->get_type() <<
" references vertices up to " 2516 << get_max_vertex() <<
", but GeomVertexData has only " 2517 << 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.
float length_squared() const
Returns the square of the vector's length, cheap and easy.
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...
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
This is the base class for all three-component vectors and points.
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.
int get_primitive_num_vertices(int n) const
Returns the number of vertices used by the nth primitive.
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.
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 set_ends(CPTA_int ends)
Completely replaces the primitive ends array with a new 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...
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.
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...
PrimitiveType get_primitive_type() const
Returns the fundamental primitive type that is common to all GeomPrimitives added within the Geom...
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...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
PN_int32 get_int32()
Extracts a signed 32-bit integer.
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
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 make_nonindexed(GeomVertexData *dest, const GeomVertexData *source)
Converts the primitive from indexed to nonindexed by duplicating vertices as necessary into the indic...
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 int get_num_unused_vertices_per_primitive() const
Returns the number of vertices that are added between primitives that aren't, strictly speaking...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
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.
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
LVecBase3f xform_point(const LVecBase3f &v) const
The matrix transforms a 3-component point (including translation component) and returns the result...
This is a 4-by-4 transform matrix.
void clear_vertices()
Removes all of the vertices and primitives from the object, so they can be re-added.
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.
bool set_num_rows(int n)
Sets the length of the array to n rows in all of the various arrays (presumably by adding rows)...
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...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
int get_num_rows() const
Returns the number of rows stored within all the arrays.
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...
const GeomVertexArrayFormat * get_array_format() const
Returns the format object that describes this array.
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...
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.
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
int get_num_rows() const
Returns the number of rows stored in the array, based on the number of bytes and the stride...
virtual int get_geom_rendering() const
Returns the set of GeomRendering bits that represent the rendering properties required to properly re...
ShadeModel get_shade_model() const
Returns the shade model common to all of the individual GeomPrimitives that have been added to the ge...
A thread; that is, a lightweight process.
int release_all()
Frees the context allocated on all objects for which the geom has been declared.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
UsageHint get_usage_hint() const
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
bool is_at_end() const
Returns true if the reader is currently at the end of the list of vertices, false otherwise...
GeomVertexArrayData * get_array_data() const
Returns the particular array object that the writer is currently processing.
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.
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
int make_nonindexed(bool composite_only)
Converts the geom from indexed to nonindexed by duplicating vertices as necessary.
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
virtual int get_num_vertices_per_primitive() const
If the primitive type is a simple type in which all primitives have the same number of vertices...
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.
void set_usage_hint(UsageHint usage_hint)
Changes the UsageHint hint for all of the primitives on this Geom to the same value.
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.
virtual int get_min_num_vertices_per_primitive() const
Returns the minimum number of vertices that must be added before close_primitive() may legally be cal...
int get_primitive_end(int n) const
Returns the element within the _vertices list at which the nth primitive ends.
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter, combined together into one convenient package.
Similar to PointerToArray, except that its contents may not be modified.
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.
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.