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);
202 if (num_primitives > 0 &&
203 requires_unused_vertices() &&
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);
267 if (num_primitives > 0 &&
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;
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);
387 if (num_vertices_per_primitive == 0) {
392 if (cdata->_ends.empty()) {
400 if (cdata->_ends.get_ref_count() > 1) {
402 new_ends.v() = cdata->_ends.v();
403 cdata->_ends = new_ends;
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);
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);
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);
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);
618 CopiedIndices copied_indices;
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;
666 do_make_indexed(cdata);
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);
717 if (num_vertices_per_primitive == 0) {
721 nassertr(n >= 0 && n < (
int)cdata->_ends.size(), -1);
722 return cdata->_ends[n];
728 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive) + 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];
752 return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive;
758 return num_vertices_per_primitive;
776 if (num_primitives > 0) {
794 nassertr(n >= 0 && n < mins->get_num_rows(), -1);
814 nassertr(n >= 0 && n < maxs->get_num_rows(), -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) {
1014 nassertr(!index.is_at_end(), NULL);
1015 int vertex = index.get_data1i();
1016 if (vertex != strip_cut_index) {
1021 int first_vertex = get_first_vertex();
1022 bits.
set_range(first_vertex, num_vertices);
1027 new_vertices->unclean_set_num_rows(bits.get_num_on_bits());
1030 int p = bits.get_lowest_on_bit();
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();
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());
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();
1172 bool resident =
true;
1174 if (!cdata->_vertices.is_null() &&
1175 !cdata->_vertices.get_read_pointer()->request_resident()) {
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 {
1209 void GeomPrimitive::
1210 write(ostream &out,
int indent_level)
const {
1211 indent(out, indent_level)
1214 out <<
" (indexed)";
1216 out <<
" (nonindexed)";
1222 for (
int i = 0; i < num_primitives; ++i) {
1223 indent(out, indent_level + 2)
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) {
1271 CDWriter cdata(_cycler,
true);
1273 cdata->_num_vertices = num_vertices;
1302 cdata->_num_vertices = num_vertices;
1305 const GeomVertexArrayFormat *format = vertices->get_array_format();
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()) {
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;
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()) {
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()) {
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();
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;
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();
2124 mins.set_data1i(min_prim);
2125 maxs.set_data1i(max_prim);
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);
2140 mins.set_data1i(min_prim);
2141 maxs.set_data1i(max_prim);
2142 nassertv(mins.get_array_data()->get_num_rows() == (int)cdata->_ends.size());
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) {
2189 index.set_data1i(i + cdata->_first_vertex);
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) {
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()) {
2251 if (array_obj->get_array_format() != new_format) {
2253 new_vertices->set_num_rows(array_obj->get_num_rows());
2258 while (!from.is_at_end()) {
2259 int index = from.get_data1i();
2260 if (index == old_strip_cut_index) {
2261 index = new_strip_cut_index;
2265 cdata->_vertices = new_vertices;
2266 cdata->_got_minmax =
false;
2278 if (cdata->_vertices.is_null()) {
2279 do_make_indexed(cdata);
2285 cdata->_got_minmax = false;
2299 manager->write_cdata(dg, _cycler);
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";
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
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 get_num_used_vertices() const
Returns the number of vertices used by all of the primitives.
int get_primitive_start(int n) const
Returns the element within the _vertices list at which the nth primitive starts.
int release_all()
Frees the context allocated on all objects for which the data has been declared.
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_indexed() const
Returns true if the primitive is indexed, false otherwise.
UsageHint get_usage_hint() const
Returns the usage hint that describes to the rendering backend how often the vertex data will be modi...
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...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Defines a series of disconnected points.
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.
bool dequeue_index_buffer(GeomPrimitive *data)
Removes a buffer from the queued list of data arrays to be prepared.
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...
int get_strip_cut_index() const
If relevant, returns the index value that may be used in some cases to signify the end of a primitive...
void set_index_type(NumericType index_type)
Changes the numeric type of the index column.
A single page of data maintained by a PipelineCycler.
const GeomVertexArrayFormat * get_index_format() const
Returns a registered format appropriate for using to store the index table.
int get_primitive_end(int n) const
Returns the element within the _vertices list at which the nth primitive ends.
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...
IndexBufferContext * prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg)
Immediately creates a new IndexBufferContext for the indicated data and returns it.
float length_squared() const
Returns the square of the vector's length, cheap and easy.
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...
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...
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
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. ...
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 lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
virtual int get_num_unused_vertices_per_primitive() const
Returns the number of vertices that are added between primitives that aren't, strictly speaking...
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...
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...
bool is_index_buffer_queued(const GeomPrimitive *data) const
Returns true if the index buffer has been queued on this GSG, false otherwise.
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...
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...
A dynamic array with an unlimited number of bits.
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 represents a single element that may be timed and/or counted via stats...
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 add_vertex(int vertex)
Adds the indicated vertex to the list of vertex indices used by the graphics primitive type...
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
int get_primitive_max_vertex(int n) const
Returns the maximum vertex index number used by the nth primitive in this object. ...
Defines a series of "patches", fixed-size groupings of vertices that must be processed by a tessellat...
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.
int get_max_vertex() const
Returns the maximum vertex index number used by all the primitives in this object.
This is a 4-by-4 transform matrix.
virtual int get_geom_rendering() const
Returns the set of GeomRendering bits that represent the rendering properties required to properly re...
bool request_resident() const
Returns true if the primitive data is currently resident in memory.
int get_primitive_num_vertices(int n) const
Returns the number of vertices used by the nth primitive.
void clear_vertices()
Removes all of the vertices and primitives from the object, so they can be re-added.
void clear_minmax()
Undoes a previous call to set_minmax(), and allows the minimum and maximum values to be recomputed no...
ShadeModel get_shade_model() const
Returns the shade model common to all of the individual GeomPrimitives that have been added to the ge...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
UsageHint get_usage_hint() const
Returns the minimum (i.e.
A container for geometry primitives.
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
bool has_column() const
Returns true if a valid data type has been successfully set, or false if the data type does not exist...
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
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()...
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.
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_bytes() const
Returns the number of bytes consumed by the primitive and its index table(s).
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...
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.
bool is_at_end() const
Returns true if the reader or writer is currently at the end of the list of vertices, false otherwise.
This base class provides basic reference counting, but also can be used with a CopyOnWritePointer to ...
void check_minmax() const
Ensures that the primitive's minmax cache has been computed.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
int get_num_vertices() const
Returns the number of indices used by all the primitives in this object.
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...
static UpdateSeq get_next_modified()
Returns a monotonically increasing sequence.
int get_primitive_min_vertex(int n) const
Returns the minimum vertex index number used by the nth primitive in this object. ...
int get_vertex(int i) const
Returns the ith vertex index in the table.
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.
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
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.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
TypeHandle is the identifier used to differentiate C++ class types.
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
int get_vertex(int i) const
Returns the ith vertex index in the table.
void make_indexed()
Converts the primitive from nonindexed form to indexed form.
LVecBase3f xform_point(const LVecBase3f &v) const
The matrix transforms a 3-component point (including translation component) and returns the result...
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter, combined together into one convenient package.
int get_num_primitives() const
Returns the number of individual primitives stored within this object.
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.
int get_num_primitives() const
Returns the number of GeomPrimitive objects stored within the Geom, each of which represents a number...
int get_num_rows() const
Returns the number of rows stored within all the arrays.