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);
182 node->mark_internal_bounds_stale();
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;
458 mat = tma->get_mat(ts);
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);
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;
1221 PT(
Geom) GeomTransformer::
1231 vdata = munger->premunge_data(vdata);
1232 CPT(
Geom) pgeom = geom;
1233 munger->premunge_geom(pgeom, vdata);
1235 PT(
Geom) geom_copy = pgeom->make_copy();
1236 geom_copy->set_vertex_data(vdata);
1246 GeomTransformer::NewCollectedData::
1249 _vdata_name = source_data->
get_name();
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;
1304 int GeomTransformer::NewCollectedData::
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);
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++) {
1399 added_transforms[old_table->get_transform(i)] = i;
1406 if (_new_data->get_transform_table() != (
TransformTable *)NULL) {
1407 new_table =
new TransformTable(*_new_data->get_transform_table());
1415 IndexMap transform_map;
1418 transform_map.reserve(num_transforms);
1419 for (
int ti = 0; ti < num_transforms; ++ti) {
1421 AddedTransforms::iterator ai = added_transforms.find(transform);
1422 if (ai != added_transforms.end()) {
1424 transform_map.push_back((*ai).second);
1427 int tj = new_table->add_transform(transform);
1428 transform_map.push_back(tj);
1429 added_transforms[transform] = tj;
1432 _new_data->set_transform_table(TransformTable::register_table(new_table));
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]];
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);
1493 for (
int ci = 0; ci < num_rows; ++ci) {
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;
1519 new_sliders->add_slider(old_sliders->
get_slider(si), new_rows);
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()) {
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;
1564 int num_primitives = geom->get_num_primitives();
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) {
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);
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) {
1663 int num_primitives = geom->get_num_primitives();
1664 for (
int i = 0; i < num_primitives; ++i) {
1666 prim->make_indexed();
1672 nassertv(index >= 0 && index < num_vertices);
1673 new_index = remap_array[index];
1674 nassertv(new_index >= 0 && new_index < new_num_vertices);
const RenderState * get_geom_state(int n) const
Returns the RenderState associated with the nth geom of the node.
const SliderTable * get_slider_table() const
Returns a const pointer to the SliderTable assigned to this data.
This class records a set of integers, where each integer is either present or not present in the set...
bool is_at_end() const
Returns true if the reader or writer is currently at the end of the list of vertices, false otherwise.
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...
const TransformTable * get_transform_table() const
Returns a const pointer to the TransformTable assigned to this data.
This is our own Panda specialization on the default STL map.
const SparseArray & get_slider_rows(int n) const
Returns the set of rows (vertices) governed by the nth slider in the table.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
const LColor & get_color() const
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
int get_num_arrays() const
Returns the number of individual arrays stored within the data.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
bool almost_equal(const LMatrix4f &other, float threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
void set_data4i(int a, int b, int c, int d)
Sets the write row to a particular 4-component value, and advances the write row. ...
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
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...
void reverse_in_place()
Reverses all of the primitives within this Geom, leaving the results in place.
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 ...
int get_num_geoms() const
Returns the number of geoms in the node.
This data object is returned by GeomVertexArrayData::get_handle() or modify_handle().
Type get_color_type() const
Returns the type of color specified by this ColorAttrib.
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.
int get_subrange_end(int n) const
Returns the last numeric element, plus one, in the nth subrange.
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.
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...
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
int get_subrange_begin(int n) const
Returns the first numeric element in the nth subrange.
This is a 4-by-4 transform matrix.
const VertexSlider * get_slider(int n) const
Returns the nth slider in the table.
const GeomVertexFormat * get_format() const
Returns a pointer to the GeomVertexFormat structure that defines this data.
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the array.
UsageHint get_usage_hint() const
Returns the usage hint that was passed to the constructor, and which will be passed to each array dat...
int get_num_sliders() const
Returns the number of sliders in the table.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
int get_num_values() const
Returns the number of numeric values of the column: the number of distinct numeric values that go int...
int get_vertex(int i) const
Returns the ith vertex index in the table.
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. ...
InternalName * get_texcoord_name() const
See set_texcoord_name.
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
int get_num_rows() const
Returns the number of rows stored within all the arrays.
int get_data1i()
Returns the data associated with the read row, expressed as a 1-component value, and advances the rea...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
int get_num_subranges() const
Returns the number of separate subranges stored in the SparseArray.
An instance of this object is returned by Texture::peek().
This is the base class for all three-component vectors and points.
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 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.
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...
bool is_at_end() const
Returns true if the reader is currently at the end of the list of vertices, false otherwise...
This is similar to RefCountObj, but it implements a CopyOnWriteObject inheritance instead of a Refere...
static int size()
Returns 4: the number of components of a LVecBase4.
Indicates what color should be applied to renderable geometry.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This is a two-component point in space.
const GeomVertexColumn * get_column() const
Returns the description of the data type that the rewriter is working on.
TypeHandle is the identifier used to differentiate C++ class types.
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
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.
const LVecBase4i & get_data4i()
Returns the data associated with the read row, expressed as a 4-component value, and advances the rea...
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.
const string & get_name() const
Returns the name passed to the constructor, if any.
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.