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.