15 #include "geomTransformer.h"
16 #include "sceneGraphReducer.h"
19 #include "geomVertexRewriter.h"
20 #include "renderState.h"
21 #include "transformTable.h"
22 #include "transformBlendTable.h"
23 #include "sliderTable.h"
24 #include "pStatCollector.h"
25 #include "pStatTimer.h"
26 #include "vector_int.h"
27 #include "userVertexTransform.h"
28 #include "geomMunger.h"
30 #include "texturePeeker.h"
31 #include "textureAttrib.h"
32 #include "colorAttrib.h"
33 #include "config_pgraph.h"
35 PStatCollector GeomTransformer::_apply_vertex_collector(
"*:Flatten:apply:vertex");
36 PStatCollector GeomTransformer::_apply_texcoord_collector(
"*:Flatten:apply:texcoord");
37 PStatCollector GeomTransformer::_apply_set_color_collector(
"*:Flatten:apply:set color");
38 PStatCollector GeomTransformer::_apply_scale_color_collector(
"*:Flatten:apply:scale color");
39 PStatCollector GeomTransformer::_apply_texture_color_collector(
"*:Flatten:apply:texture color");
40 PStatCollector GeomTransformer::_apply_set_format_collector(
"*:Flatten:apply:set format");
42 TypeHandle GeomTransformer::NewCollectedData::_type_handle;
52 _max_collect_vertices(max_collect_vertices)
63 _max_collect_vertices(copy._max_collect_vertices)
86 VertexDataAssoc &assoc = _vdata_assoc[geom->get_vertex_data()];
87 assoc._geoms.push_back(geom);
88 if (might_have_unused) {
89 assoc._might_have_unused =
true;
103 OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler, current_thread) {
105 GeomNode::GeomList::iterator gi;
107 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
109 PT(
Geom) geom = entry._geom.get_write_pointer();
113 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler);
127 nassertr(geom != (
Geom *)NULL,
false);
130 sv._vertex_data = geom->get_vertex_data();
132 NewVertexData &new_data = _vertices[sv];
133 if (new_data._vdata.is_null()) {
136 new_vdata->transform_vertices(mat);
137 new_data._vdata = new_vdata;
141 if (sv._vertex_data->get_ref_count() > 1) {
142 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
143 _vdata_assoc[sv._vertex_data]._might_have_unused =
true;
163 bool any_changed =
false;
166 OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler, current_thread) {
168 GeomNode::GeomList::iterator gi;
170 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
172 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
174 entry._geom = new_geom;
179 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler);
198 InternalName *to_name,
const LMatrix4 &mat) {
201 nassertr(geom != (
Geom *)NULL,
false);
205 st._from = from_name;
207 st._vertex_data = geom->get_vertex_data();
209 NewVertexData &new_data = _texcoords[st];
210 if (new_data._vdata.is_null()) {
211 if (!st._vertex_data->has_column(from_name)) {
219 if (st._vertex_data->has_column(to_name)) {
223 st._vertex_data->get_format()->get_column(from_name);
224 new_vdata = st._vertex_data->replace_column
230 CPT(GeomVertexFormat) format = new_vdata->get_format();
239 new_data._vdata = new_vdata;
243 if (st._vertex_data->get_ref_count() > 1) {
244 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
245 _vdata_assoc[st._vertex_data]._might_have_unused =
true;
265 InternalName *to_name,
const LMatrix4 &mat) {
266 bool any_changed =
false;
269 GeomNode::GeomList::iterator gi;
271 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
273 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
275 entry._geom = new_geom;
297 sc._vertex_data = geom->get_vertex_data();
299 NewVertexData &new_data = _fcolors[sc];
300 if (new_data._vdata.is_null()) {
302 if (sc._vertex_data->has_column(InternalName::get_color())) {
303 new_data._vdata = sc._vertex_data->set_color(color);
305 new_data._vdata = sc._vertex_data->set_color
306 (color, 1, Geom::NT_packed_dabc, Geom::C_color);
311 if (sc._vertex_data->get_ref_count() > 1) {
312 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
313 _vdata_assoc[sc._vertex_data]._might_have_unused =
true;
330 bool any_changed =
false;
333 GeomNode::GeomList::iterator gi;
335 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
337 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
339 entry._geom = new_geom;
356 PStatTimer timer(_apply_scale_color_collector);
358 nassertr(geom != (
Geom *)NULL,
false);
362 sc._vertex_data = geom->get_vertex_data();
364 NewVertexData &new_data = _tcolors[sc];
365 if (new_data._vdata.is_null()) {
367 if (sc._vertex_data->has_column(InternalName::get_color())) {
368 new_data._vdata = sc._vertex_data->scale_color(scale);
370 new_data._vdata = sc._vertex_data->set_color
371 (scale, 1, Geom::NT_packed_dabc, Geom::C_color);
376 if (sc._vertex_data->get_ref_count() > 1) {
377 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
378 _vdata_assoc[sc._vertex_data]._might_have_unused =
true;
397 bool any_changed =
false;
400 GeomNode::GeomList::iterator gi;
402 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
404 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
406 entry._geom = new_geom;
426 bool keep_vertex_color) {
427 PStatTimer timer(_apply_texture_color_collector);
429 nassertr(geom != (
Geom *)NULL,
false);
436 if (peeker->get_x_size() == 1 &&
437 peeker->get_y_size() == 1 &&
438 peeker->get_z_size() == 1) {
443 peeker->lookup(color, 0.0f, 0.0f);
444 color.set(color[0] * base_color[0],
445 color[1] * base_color[1],
446 color[2] * base_color[2],
447 color[3] * base_color[3]);
448 if (keep_vertex_color) {
455 bool got_mat =
false;
498 SourceTextureColors stc;
502 stc._base_color = base_color;
503 stc._keep_vertex_color = keep_vertex_color;
504 stc._vertex_data = geom->get_vertex_data();
506 NewVertexData &new_data = _tex_colors[stc];
507 if (new_data._vdata.is_null()) {
513 if (stc._vertex_data->has_column(InternalName::get_color())) {
518 (
LColor(1.0f, 1.0f, 1.0f, 1.0f), 1, Geom::NT_packed_dabc, Geom::C_color));
519 keep_vertex_color =
false;
534 if (keep_vertex_color) {
539 if (got_mat || tex3d) {
540 while (!gtexcoord.is_at_end()) {
542 LColor c = gcolor.get_data4();
545 peeker->lookup(color, p[0], p[1], p[2]);
546 color.set(color[0] * base_color[0] * c[0],
547 color[1] * base_color[1] * c[1],
548 color[2] * base_color[2] * c[2],
549 color[3] * base_color[3] * c[3]);
550 gcolor.set_data4(color);
553 while (!gtexcoord.is_at_end()) {
555 LColor c = gcolor.get_data4();
557 peeker->lookup(color, p[0], p[1]);
558 color.set(color[0] * base_color[0] * c[0],
559 color[1] * base_color[1] * c[1],
560 color[2] * base_color[2] * c[2],
561 color[3] * base_color[3] * c[3]);
562 gcolor.set_data4(color);
570 if (got_mat || tex3d) {
571 while (!gtexcoord.is_at_end()) {
575 peeker->lookup(color, p[0], p[1], p[2]);
576 color.set(color[0] * base_color[0],
577 color[1] * base_color[1],
578 color[2] * base_color[2],
579 color[3] * base_color[3]);
580 gcolor.set_data4(color);
583 while (!gtexcoord.is_at_end()) {
586 peeker->lookup(color, p[0], p[1]);
587 color.set(color[0] * base_color[0],
588 color[1] * base_color[1],
589 color[2] * base_color[2],
590 color[3] * base_color[3]);
591 gcolor.set_data4(color);
596 new_data._vdata = vdata;
600 if (stc._vertex_data->get_ref_count() > 1) {
601 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
602 _vdata_assoc[stc._vertex_data]._might_have_unused =
true;
627 bool any_changed =
false;
630 GeomNode::GeomList::iterator gi;
632 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
634 CPT(
RenderState) geom_state = state->compose(entry._state);
639 if (ta2->get_num_on_stages() > 0) {
641 Texture *tex = ta2->get_on_texture(ts);
645 LColor base_color(1.0f, 1.0f, 1.0f, 1.0f);
646 bool keep_vertex_color =
true;
647 if (ca != (
ColorAttrib *)NULL && ca->get_color_type() == ColorAttrib::T_flat) {
648 base_color = ca->get_color();
649 keep_vertex_color =
false;
652 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
654 entry._geom = new_geom;
657 if (new_geom->get_vertex_data()->has_column(InternalName::get_color())) {
659 CPT(
RenderState) color_state = entry._state->set_attrib(ColorAttrib::make_vertex());
660 if (entry._state != color_state) {
661 entry._state = color_state;
668 CPT(
RenderState) no_tex_state = entry._state->remove_attrib(TextureAttrib::get_class_slot());
669 if (entry._state != no_tex_state) {
670 entry._state = no_tex_state;
689 bool any_changed =
false;
692 GeomNode::GeomList::iterator gi;
694 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
696 CPT(
RenderState) new_state = state->compose(entry._state);
697 if (entry._state != new_state) {
698 entry._state = new_state;
714 PStatTimer timer(_apply_set_format_collector);
716 nassertr(geom != (
Geom *)NULL,
false);
719 sf._format = new_format;
720 sf._vertex_data = geom->get_vertex_data();
722 NewVertexData &new_data = _format[sf];
723 if (new_data._vdata.is_null()) {
724 if (sf._vertex_data->get_format() == new_format) {
731 new_vdata->set_format(new_format);
732 new_data._vdata = new_vdata;
736 if (sf._vertex_data->get_ref_count() > 1) {
737 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
738 _vdata_assoc[sf._vertex_data]._might_have_unused =
true;
753 CPT(GeomVertexFormat) format = geom->get_vertex_data()->get_format();
754 if (!format->has_column(column)) {
758 PT(GeomVertexFormat) new_format =
new GeomVertexFormat(*format);
759 new_format->remove_column(column);
760 new_format->pack_columns();
761 format = GeomVertexFormat::register_format(new_format);
776 bool any_changed =
false;
779 GeomNode::GeomList::iterator gi;
781 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
783 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
785 entry._geom = new_geom;
809 GeomNode::GeomList::iterator gi;
817 StateTable state_table;
819 for (
int i = 0; i < (int)geoms->size(); i++) {
821 CPT(
RenderState) canon = entry._state->remove_attrib(ColorAttrib::get_class_slot());
822 state_table[canon].push_back(i);
827 bool any_changed =
false;
828 StateTable::iterator si;
829 for (si = state_table.begin(); si != state_table.end(); si++) {
835 bool mismatch =
false;
836 for (
int i = 1; i < (int)indices.size(); i++) {
837 if ((*geoms)[indices[i]]._state != (*geoms)[indices[0]]._state) {
851 for (
int i = 0; i < (int)indices.size(); i++) {
853 const RenderAttrib *ra = entry._state->get_attrib_def(ColorAttrib::get_class_slot());
857 if (!entry._geom.get_read_pointer()->get_vertex_data()->has_column(InternalName::get_color())) {
858 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
860 entry._geom = new_geom;
867 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
869 entry._geom = new_geom;
872 entry._state = canon_state->add_attrib(ColorAttrib::make_vertex());
889 nassertr(geom != (
Geom *)NULL,
false);
891 NewVertexData &new_data = _reversed_normals[orig_data];
892 if (new_data._vdata.is_null()) {
893 new_data._vdata = orig_data->reverse_normals();
896 if (new_data._vdata == orig_data) {
902 if (orig_data->get_ref_count() > 1) {
903 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
904 _vdata_assoc[orig_data]._might_have_unused =
true;
934 for (
int i = 0; i < num_geoms; ++i) {
935 CPT(
Geom) orig_geom = node->get_geom(i);
936 bool has_normals = (orig_geom->get_vertex_data()->has_column(InternalName::get_normal()));
940 PT(
Geom) new_geom = orig_geom->reverse();
948 node->modify_geom(i)->doubleside_in_place();
952 return (num_geoms != 0);
976 for (
int i = 0; i < num_geoms; ++i) {
977 PT(
Geom) geom = node->modify_geom(i);
978 geom->reverse_in_place();
982 return (num_geoms != 0);
999 VertexDataAssocMap::iterator vi;
1000 for (vi = _vdata_assoc.begin(); vi != _vdata_assoc.end(); ++vi) {
1002 VertexDataAssoc &assoc = (*vi).second;
1003 if (assoc._might_have_unused) {
1004 assoc.remove_unused_vertices(vdata);
1007 _vdata_assoc.clear();
1013 _reversed_normals.clear();
1040 CPT(GeomVertexFormat) format = vdata->
get_format();
1042 NewCollectedKey key;
1043 if ((collect_bits & SceneGraphReducer::CVD_name) != 0) {
1046 if ((collect_bits & SceneGraphReducer::CVD_format) != 0) {
1047 key._format = format;
1049 if ((collect_bits & SceneGraphReducer::CVD_usage_hint) != 0) {
1052 key._usage_hint = Geom::UH_unspecified;
1054 if ((collect_bits & SceneGraphReducer::CVD_animation_type) != 0) {
1055 key._animation_type = format->get_animation().get_animation_type();
1057 key._animation_type = Geom::AT_none;
1060 AlreadyCollectedMap::const_iterator ai;
1061 ai = _already_collected_map.find(vdata);
1062 if (ai != _already_collected_map.end()) {
1064 const AlreadyCollectedData &acd = (*ai).second;
1065 SourceGeom source_geom;
1066 source_geom._geom = geom;
1067 source_geom._vertex_offset = acd._vertex_offset;
1068 acd._ncd->_source_geoms.push_back(source_geom);
1074 NewCollectedMap::iterator ni = _new_collected_map.find(key);
1075 NewCollectedData *ncd;
1076 if (ni != _new_collected_map.end()) {
1082 ncd =
new NewCollectedData(vdata);
1083 _new_collected_list.push_back(ncd);
1084 _new_collected_map[key] = ncd;
1087 if (ncd->_new_format != format) {
1088 ncd->_new_format = format->get_union_format(ncd->_new_format);
1094 ncd->_num_vertices + this_num_vertices > _max_collect_vertices) {
1097 ncd =
new NewCollectedData(vdata);
1098 _new_collected_list.push_back(ncd);
1099 _new_collected_map[key] = ncd;
1102 int vertex_offset = ncd->_num_vertices;
1104 AlreadyCollectedData &acd = _already_collected_map[vdata];
1106 acd._vertex_offset = vertex_offset;
1108 SourceGeom source_geom;
1109 source_geom._geom = geom;
1110 source_geom._vertex_offset = vertex_offset;
1111 ncd->_source_geoms.push_back(source_geom);
1113 SourceData source_data;
1114 source_data._vdata = vdata;
1115 source_data._num_vertices = this_num_vertices;
1117 ncd->_source_datas.push_back(source_data);
1118 ncd->_num_vertices += this_num_vertices;
1143 int num_adjusted = 0;
1147 GeomNode::GeomList::iterator gi;
1149 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1151 PT(
Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
1152 entry._geom = new_geom;
1154 if ((collect_bits & SceneGraphReducer::CVD_avoid_dynamic) != 0 &&
1155 new_geom->get_vertex_data()->get_usage_hint() < Geom::UH_static) {
1173 return num_adjusted;
1192 int num_adjusted = 0;
1194 NewCollectedList::iterator nci;
1195 for (nci = _new_collected_list.begin();
1196 nci != _new_collected_list.end();
1198 NewCollectedData *ncd = (*nci);
1200 num_adjusted += ncd->apply_format_only_changes();
1202 num_adjusted += ncd->apply_collect_changes();
1207 _new_collected_list.clear();
1208 _new_collected_map.clear();
1209 _already_collected_map.clear();
1211 return num_adjusted;
1231 vdata = munger->premunge_data(vdata);
1232 CPT(
Geom) pgeom = geom;
1233 munger->premunge_geom(pgeom, vdata);
1236 geom_copy->set_vertex_data(vdata);
1248 _new_format = source_data->get_format();
1249 _vdata_name = source_data->get_name();
1250 _usage_hint = source_data->get_usage_hint();
1262 int GeomTransformer::NewCollectedData::
1263 apply_format_only_changes() {
1264 int num_modified = 0;
1273 SourceGeoms::iterator sgi;
1274 for (sgi = _source_geoms.begin(); sgi != _source_geoms.end(); ++sgi) {
1275 SourceGeom &sg = (*sgi);
1278 if (orig_data->get_format() != _new_format) {
1279 VDataMap::iterator mi = vdata_map.find(orig_data);
1280 if (mi != vdata_map.end()) {
1282 sg._geom->set_vertex_data((*mi).second);
1286 CPT(
GeomVertexData) new_data = orig_data->convert_to(_new_format);
1287 vdata_map[orig_data] = new_data;
1290 sg._geom->set_vertex_data(new_data);
1295 return num_modified;
1305 apply_collect_changes() {
1306 if (_num_vertices == 0) {
1313 _new_data->unclean_set_num_rows(_num_vertices);
1316 int vertex_offset = 0;
1317 SourceDatas::iterator sdi;
1318 for (sdi = _source_datas.begin(); sdi != _source_datas.end(); ++sdi) {
1319 SourceData &sd = (*sdi);
1322 if (_new_format != vdata->get_format()) {
1326 vdata = vdata->convert_to(_new_format);
1329 append_vdata(vdata, vertex_offset);
1330 vertex_offset += sd._num_vertices;
1333 nassertr(vertex_offset == _num_vertices, 0);
1336 _new_btable->set_rows(_new_btable_rows);
1337 _new_data->set_transform_blend_table(_new_btable);
1343 _new_btable.clear();
1344 _new_btable_rows.clear();
1355 void GeomTransformer::NewCollectedData::
1360 int stride = _new_format->get_array(i)->get_stride();
1361 int start_byte = vertex_offset * stride;
1362 int copy_bytes = old_array->get_data_size_bytes();
1363 nassertv(start_byte + copy_bytes <= new_array->get_data_size_bytes());
1365 new_array->modify_handle()->copy_subdata_from
1366 (start_byte, copy_bytes,
1367 old_array->get_handle(), 0, copy_bytes);
1386 temp_table->add_transform(identity_transform);
1387 old_table = TransformTable::register_table(temp_table);
1395 AddedTransforms added_transforms;
1397 int num_old_transforms = old_table->get_num_transforms();
1398 for (
int i = 0; i < num_old_transforms; i++) {
1405 PT(TransformTable) new_table;
1406 if (_new_data->get_transform_table() != (TransformTable *)NULL) {
1407 new_table =
new TransformTable(*_new_data->get_transform_table());
1409 new_table =
new TransformTable;
1415 IndexMap transform_map;
1418 transform_map.reserve(num_transforms);
1419 for (
int ti = 0; ti < num_transforms; ++ti) {
1420 const VertexTransform *transform = old_table->
get_transform(ti);
1421 AddedTransforms::iterator ai = added_transforms.find(transform);
1422 if (ai != added_transforms.end()) {
1424 transform_map.push_back((*ai).second);
1428 transform_map.push_back(tj);
1429 added_transforms[transform] = tj;
1432 _new_data->set_transform_table(TransformTable::register_table(new_table));
1439 if (index.has_column()) {
1440 int num_values = index.get_column()->get_num_values();
1443 index.set_row_unsafe(vertex_offset);
1444 for (
int ci = 0; ci < num_rows; ++ci) {
1446 for (
int i = 0; i < num_values; i++) {
1447 nassertv(indices[i] >= 0 && indices[i] < (
int)transform_map.
size());
1448 indices[i] = transform_map[indices[i]];
1450 index.set_data4i(indices);
1472 new_rows <<= vertex_offset;
1473 _new_btable_rows |= new_rows;
1478 int num_blends = old_btable->get_num_blends();
1479 blend_map.reserve(num_blends);
1480 for (
int bi = 0; bi < num_blends; ++bi) {
1481 int bj = _new_btable->add_blend(old_btable->get_blend(bi));
1482 blend_map.push_back(bj);
1489 if (index.has_column()) {
1491 index.set_row_unsafe(vertex_offset);
1493 for (
int ci = 0; ci < num_rows; ++ci) {
1494 int orig_index = index.get_data1i();
1495 nassertv(orig_index >= 0 && orig_index < (
int)blend_map.size());
1496 int new_index = blend_map[orig_index];
1510 if (_new_data->get_slider_table() != (
SliderTable *)NULL) {
1511 new_sliders =
new SliderTable(*_new_data->get_slider_table());
1516 for (
int si = 0; si < num_sliders; ++si) {
1518 new_rows <<= vertex_offset;
1521 _new_data->set_slider_table(SliderTable::register_table(new_sliders));
1531 void GeomTransformer::NewCollectedData::
1533 SourceGeoms::iterator sgi;
1534 for (sgi = _source_geoms.begin(); sgi != _source_geoms.end(); ++sgi) {
1535 SourceGeom &sg = (*sgi);
1536 sg._geom->offset_vertices(_new_data, sg._vertex_offset);
1545 void GeomTransformer::VertexDataAssoc::
1547 if (_geoms.empty()) {
1552 PT(
Thread) current_thread =
Thread::get_current_thread();
1555 bool any_referenced = false;
1556 GeomList::iterator gi;
1557 for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
1559 if (geom->get_vertex_data() != vdata) {
1563 any_referenced =
true;
1565 for (
int i = 0; i < num_primitives; ++i) {
1569 int num_vertices = reader.get_num_vertices();
1570 for (
int vi = 0; vi < num_vertices; ++vi) {
1571 referenced_vertices.
set_bit(reader.get_vertex(vi));
1576 if (!any_referenced) {
1582 if (num_vertices <= new_num_vertices) {
1584 nassertv(num_vertices == new_num_vertices);
1589 int *remap_array = (
int *)alloca(
sizeof(
int) * num_vertices);
1593 for (index = 0; index < num_vertices; ++index) {
1594 if (referenced_vertices.
get_bit(index)) {
1595 while (next_index <= index) {
1596 remap_array[next_index] = new_index;
1602 while (next_index < num_vertices) {
1603 remap_array[next_index] = new_num_vertices - 1;
1609 new_vdata->unclean_set_num_rows(new_num_vertices);
1611 int num_arrays = vdata->get_num_arrays();
1612 nassertv(num_arrays == new_vdata->get_num_arrays());
1615 reader.check_array_readers();
1617 writer.check_array_writers();
1619 for (
int a = 0; a < num_arrays; ++a) {
1623 int stride = array_reader->get_array_format()->get_stride();
1624 nassertv(stride == array_writer->get_array_format()->get_stride());
1628 for (index = 0; index < num_vertices; ++index) {
1629 if (referenced_vertices.
get_bit(index)) {
1632 index * stride, stride);
1640 if (!tbtable.is_null()) {
1644 for (
int si = 0; si < num_subranges; ++si) {
1647 nassertv(from >= 0 && from < num_vertices && to > from && to <= num_vertices);
1648 int new_from = remap_array[from];
1649 int new_to = remap_array[to - 1] + 1;
1650 nassertv(new_from >= 0 && new_from < new_num_vertices && new_to >= new_from && new_to <= new_num_vertices);
1651 new_rows.
set_range(new_from, new_to - new_from);
1653 tbtable->set_rows(new_rows);
1657 for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
1659 if (geom->get_vertex_data() != vdata) {
1664 for (
int i = 0; i < num_primitives; ++i) {
1666 prim->make_indexed();
1670 while (!rewriter.is_at_end()) {
1672 nassertv(index >= 0 && index < num_vertices);
1673 new_index = remap_array[index];
1674 nassertv(new_index >= 0 && new_index < new_num_vertices);
1675 rewriter.set_data1i(new_index);
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
This class records a set of integers, where each integer is either present or not present in the set...
static const LMatrix4f & ident_mat()
Returns an identity matrix.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
This is our own Panda specialization on the default STL map.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
const SparseArray & get_slider_rows(int n) const
Returns the set of rows (vertices) governed by the nth slider in the table.
const TransformTable * get_transform_table() const
Returns a const pointer to the TransformTable assigned to this data.
UsageHint get_usage_hint() const
Returns the usage hint that was passed to the constructor, and which will be passed to each array dat...
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
const LVecBase4 & get_data4()
Returns the data associated with the read row, expressed as a 4-component value, and advances the rea...
void set_data1i(int data)
Sets the write row to a particular 1-component value, and advances the write row. ...
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 ...
Type get_color_type() const
Returns the type of color specified by this ColorAttrib.
bool is_at_end() const
Returns true if the reader is currently at the end of the list of vertices, false otherwise...
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
const SliderTable * get_slider_table() const
Returns a const pointer to the SliderTable assigned to this data.
This is the base class for all three-component vectors and points.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This defines how a single column is interleaved within a vertex array stored within a Geom...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
const string & get_name() const
Returns the name passed to the constructor, if any.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
A dynamic array with an unlimited number of bits.
int get_subrange_end(int n) const
Returns the last numeric element, plus one, in the nth subrange.
InternalName * get_texcoord_name() const
See set_texcoord_name.
A lightweight class that represents a single element that may be timed and/or counted via stats...
Stores the total set of VertexSliders that the vertices in a particular GeomVertexData object might d...
int get_num_sliders() const
Returns the number of sliders in the table.
void mark_internal_bounds_stale(Thread *current_thread=Thread::get_current_thread())
Should be called by a derived class to mark the internal bounding volume stale, so that compute_inter...
const LColor & get_color() const
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
This is a 4-by-4 transform matrix.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
int add_slider(const VertexSlider *slider, const SparseArray &rows)
Adds a new slider to the table, and returns the index number of the new slider.
const GeomVertexFormat * get_format() const
Returns a pointer to the GeomVertexFormat structure that defines this data.
void set_data4(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat w)
Sets the write row to a particular 4-component value, and advances the write row. ...
int get_num_arrays() const
Returns the number of individual arrays stored within the data.
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
int get_data1i()
Returns the data associated with the read row, expressed as a 1-component value, and advances the rea...
const RenderState * get_geom_state(int n) const
Returns the RenderState associated with the nth geom of the node.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
const LMatrix4 & get_mat() const
Returns the transformation matrix associated with the default texture stage.
bool has_stage(TextureStage *stage) const
Returns true if there is a transform associated with the indicated stage, or false otherwise (in whic...
An instance of this object is returned by Texture::peek().
This is the base class for all three-component vectors and points.
void set_bit(int index)
Sets the nth bit on.
Applies a transform matrix to UV's before they are rendered.
void set_range(int low_bit, int size)
Sets the indicated range of bits on.
int get_num_subranges() const
Returns the number of separate subranges stored in the SparseArray.
void set_vertex_data(const GeomVertexData *data)
Replaces the Geom's underlying vertex data table with a completely new table.
This is a four-component point in space.
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...
void copy_subdata_from(size_t to_start, size_t to_size, const GeomVertexArrayDataHandle *other, size_t from_start, size_t from_size)
Copies a portion of the data array from the other object into a portion of the data array of this obj...
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
This is similar to RefCountObj, but it implements a CopyOnWriteObject inheritance instead of a Refere...
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
static int size()
Returns 4: the number of components of a LVecBase4.
Indicates what color should be applied to renderable geometry.
bool almost_equal(const LMatrix4f &other, float threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
int get_subrange_begin(int n) const
Returns the first numeric element in the nth subrange.
This is a two-component point in space.
const VertexSlider * get_slider(int n) const
Returns the nth slider in the table.
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the array.
TypeHandle is the identifier used to differentiate C++ class types.
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
Defines the properties of a named stage of the multitexture pipeline.
A node that holds Geom objects, renderable pieces of geometry.
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
int get_num_geoms() const
Returns the number of geoms in the node.
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter, combined together into one convenient package.
This is the data for one array of a GeomVertexData structure.
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
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.