34PStatCollector GeomTransformer::_apply_vertex_collector(
"*:Flatten:apply:vertex");
35PStatCollector GeomTransformer::_apply_texcoord_collector(
"*:Flatten:apply:texcoord");
36PStatCollector GeomTransformer::_apply_set_color_collector(
"*:Flatten:apply:set color");
37PStatCollector GeomTransformer::_apply_scale_color_collector(
"*:Flatten:apply:scale color");
38PStatCollector GeomTransformer::_apply_texture_color_collector(
"*:Flatten:apply:texture color");
39PStatCollector GeomTransformer::_apply_set_format_collector(
"*:Flatten:apply:set format");
41TypeHandle GeomTransformer::NewCollectedData::_type_handle;
49 _max_collect_vertices(max_collect_vertices)
58 _max_collect_vertices(copy._max_collect_vertices)
76 VertexDataAssoc &assoc = _vdata_assoc[geom->get_vertex_data()];
77 assoc._geoms.push_back(geom);
78 if (might_have_unused) {
79 assoc._might_have_unused =
true;
90 OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler, current_thread) {
91 GeomNode::CDStageWriter cdata(node->_cycler, pipeline_stage, current_thread);
92 GeomNode::GeomList::iterator gi;
93 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
94 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
100 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler);
111 nassertr(geom !=
nullptr,
false);
114 sv._vertex_data = geom->get_vertex_data();
116 NewVertexData &new_data = _vertices[sv];
117 if (new_data._vdata.
is_null()) {
120 new_vdata->transform_vertices(mat);
121 new_data._vdata = new_vdata;
126 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
127 _vdata_assoc[sv._vertex_data]._might_have_unused =
true;
143 bool any_changed =
false;
146 OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler, current_thread) {
147 GeomNode::CDStageWriter cdata(node->_cycler, pipeline_stage, current_thread);
148 GeomNode::GeomList::iterator gi;
149 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
150 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
154 entry._geom = std::move(new_geom);
159 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler);
178 nassertr(geom !=
nullptr,
false);
182 st._from = from_name;
184 st._vertex_data = geom->get_vertex_data();
186 NewVertexData &new_data = _texcoords[st];
187 if (new_data._vdata.
is_null()) {
188 if (!st._vertex_data->has_column(from_name)) {
196 if (st._vertex_data->has_column(to_name)) {
200 st._vertex_data->get_format()->get_column(from_name);
201 new_vdata = st._vertex_data->replace_column
213 const LPoint4 &coord = fdata.
get_data4();
216 new_data._vdata = new_vdata;
221 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
222 _vdata_assoc[st._vertex_data]._might_have_unused =
true;
239 bool any_changed =
false;
241 GeomNode::CDWriter cdata(node->_cycler);
242 GeomNode::GeomList::iterator gi;
243 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
244 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
248 entry._geom = new_geom;
267 sc._vertex_data = geom->get_vertex_data();
269 NewVertexData &new_data = _fcolors[sc];
270 if (new_data._vdata.
is_null()) {
272 if (sc._vertex_data->has_column(InternalName::get_color())) {
273 new_data._vdata = sc._vertex_data->set_color(color);
275 new_data._vdata = sc._vertex_data->set_color
276 (color, 1, Geom::NT_packed_dabc, Geom::C_color);
282 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
283 _vdata_assoc[sc._vertex_data]._might_have_unused =
true;
297 bool any_changed =
false;
299 GeomNode::CDWriter cdata(node->_cycler);
300 GeomNode::GeomList::iterator gi;
301 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
302 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
306 entry._geom = new_geom;
320 PStatTimer timer(_apply_scale_color_collector);
322 nassertr(geom !=
nullptr,
false);
326 sc._vertex_data = geom->get_vertex_data();
328 NewVertexData &new_data = _tcolors[sc];
329 if (new_data._vdata.
is_null()) {
331 if (sc._vertex_data->has_column(InternalName::get_color())) {
332 new_data._vdata = sc._vertex_data->scale_color(scale);
334 new_data._vdata = sc._vertex_data->set_color
335 (scale, 1, Geom::NT_packed_dabc, Geom::C_color);
341 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
342 _vdata_assoc[sc._vertex_data]._might_have_unused =
true;
358 bool any_changed =
false;
360 GeomNode::CDWriter cdata(node->_cycler);
361 GeomNode::GeomList::iterator gi;
362 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
363 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
367 entry._geom = new_geom;
384 bool keep_vertex_color) {
385 PStatTimer timer(_apply_texture_color_collector);
387 nassertr(geom !=
nullptr,
false);
390 if (peeker ==
nullptr) {
394 if (peeker->get_x_size() == 1 &&
395 peeker->get_y_size() == 1 &&
396 peeker->get_z_size() == 1) {
400 peeker->lookup(color, 0.0f, 0.0f);
401 color.set(color[0] * base_color[0],
402 color[1] * base_color[1],
403 color[2] * base_color[2],
404 color[3] * base_color[3]);
405 if (keep_vertex_color) {
412 bool got_mat =
false;
413 LMatrix4 mat = LMatrix4::ident_mat();
414 if (tma !=
nullptr && tma->
has_stage(ts)) {
416 got_mat = !mat.almost_equal(LMatrix4::ident_mat());
454 SourceTextureColors stc;
458 stc._base_color = base_color;
459 stc._keep_vertex_color = keep_vertex_color;
460 stc._vertex_data = geom->get_vertex_data();
462 NewVertexData &new_data = _tex_colors[stc];
463 if (new_data._vdata.
is_null()) {
469 if (stc._vertex_data->has_column(InternalName::get_color())) {
474 (LColor(1.0f, 1.0f, 1.0f, 1.0f), 1, Geom::NT_packed_dabc, Geom::C_color));
475 keep_vertex_color =
false;
481 if (column ==
nullptr) {
490 if (keep_vertex_color) {
495 if (got_mat || tex3d) {
501 peeker->lookup(color, p[0], p[1], p[2]);
502 color.set(color[0] * base_color[0] * c[0],
503 color[1] * base_color[1] * c[1],
504 color[2] * base_color[2] * c[2],
505 color[3] * base_color[3] * c[3]);
513 peeker->lookup(color, p[0], p[1]);
514 color.set(color[0] * base_color[0] * c[0],
515 color[1] * base_color[1] * c[1],
516 color[2] * base_color[2] * c[2],
517 color[3] * base_color[3] * c[3]);
526 if (got_mat || tex3d) {
531 peeker->lookup(color, p[0], p[1], p[2]);
532 color.set(color[0] * base_color[0],
533 color[1] * base_color[1],
534 color[2] * base_color[2],
535 color[3] * base_color[3]);
542 peeker->lookup(color, p[0], p[1]);
543 color.set(color[0] * base_color[0],
544 color[1] * base_color[1],
545 color[2] * base_color[2],
546 color[3] * base_color[3]);
552 new_data._vdata = vdata;
557 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
558 _vdata_assoc[stc._vertex_data]._might_have_unused =
true;
578 bool any_changed =
false;
580 GeomNode::CDWriter cdata(node->_cycler);
581 GeomNode::GeomList::iterator gi;
582 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
583 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
590 if (ta2->get_num_on_stages() > 0) {
592 Texture *tex = ta2->get_on_texture(ts);
596 LColor base_color(1.0f, 1.0f, 1.0f, 1.0f);
597 bool keep_vertex_color =
true;
598 if (ca !=
nullptr && ca->
get_color_type() == ColorAttrib::T_flat) {
600 keep_vertex_color =
false;
605 entry._geom = new_geom;
608 if (new_geom->get_vertex_data()->has_column(InternalName::get_color())) {
611 if (entry._state != color_state) {
612 entry._state = color_state;
619 CPT(
RenderState) no_tex_state = entry._state->remove_attrib(TextureAttrib::get_class_slot());
620 if (entry._state != no_tex_state) {
621 entry._state = no_tex_state;
637 bool any_changed =
false;
639 GeomNode::CDWriter cdata(node->_cycler);
640 GeomNode::GeomList::iterator gi;
641 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
642 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
645 if (entry._state != new_state) {
646 entry._state = new_state;
660 PStatTimer timer(_apply_set_format_collector);
662 nassertr(geom !=
nullptr,
false);
665 sf._format = new_format;
666 sf._vertex_data = geom->get_vertex_data();
668 NewVertexData &new_data = _format[sf];
669 if (new_data._vdata.
is_null()) {
670 if (sf._vertex_data->get_format() == new_format) {
677 new_vdata->set_format(new_format);
678 new_data._vdata = new_vdata;
683 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
684 _vdata_assoc[sf._vertex_data]._might_have_unused =
true;
697 if (!format->has_column(column)) {
702 new_format->remove_column(column);
703 new_format->pack_columns();
704 format = GeomVertexFormat::register_format(new_format);
716 bool any_changed =
false;
718 GeomNode::CDWriter cdata(node->_cycler);
719 GeomNode::GeomList::iterator gi;
720 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
721 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
725 entry._geom = new_geom;
744 GeomNode::CDWriter cdata(node->_cycler);
745 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
751 typedef pmap <CPT(
RenderState), pvector<int> > StateTable;
752 StateTable state_table;
754 for (
int i = 0; i < (int)geoms->size(); i++) {
756 CPT(
RenderState) canon = entry._state->remove_attrib(ColorAttrib::get_class_slot());
757 state_table[canon].push_back(i);
762 bool any_changed =
false;
763 StateTable::iterator si;
764 for (si = state_table.begin(); si != state_table.end(); si++) {
769 const pvector<int> &indices = (*si).second;
770 bool mismatch =
false;
771 for (
int i = 1; i < (int)indices.size(); i++) {
772 if ((*geoms)[indices[i]]._state != (*geoms)[indices[0]]._state) {
786 for (
int i = 0; i < (int)indices.size(); i++) {
788 const RenderAttrib *ra = entry._state->get_attrib_def(ColorAttrib::get_class_slot());
792 if (!entry._geom.
get_read_pointer()->get_vertex_data()->has_column(InternalName::get_color())) {
794 if (
set_color(new_geom, LColor(1,1,1,1))) {
795 entry._geom = new_geom;
804 entry._geom = new_geom;
821 nassertr(geom !=
nullptr,
false);
823 NewVertexData &new_data = _reversed_normals[orig_data];
824 if (new_data._vdata.
is_null()) {
825 new_data._vdata = orig_data->reverse_normals();
828 if (new_data._vdata == orig_data) {
834 if (orig_data->get_ref_count() > 1) {
835 _vdata_assoc[new_data._vdata]._might_have_unused =
true;
836 _vdata_assoc[orig_data]._might_have_unused =
true;
859 for (
int i = 0; i < num_geoms; ++i) {
860 CPT(
Geom) orig_geom = node->get_geom(i);
861 bool has_normals = (orig_geom->get_vertex_data()->has_column(InternalName::get_normal()));
865 PT(
Geom) new_geom = orig_geom->reverse();
873 node->modify_geom(i)->doubleside_in_place();
877 return (num_geoms != 0);
896 for (
int i = 0; i < num_geoms; ++i) {
897 PT(
Geom) geom = node->modify_geom(i);
898 geom->reverse_in_place();
902 return (num_geoms != 0);
914 VertexDataAssocMap::iterator vi;
915 for (vi = _vdata_assoc.begin(); vi != _vdata_assoc.end(); ++vi) {
917 VertexDataAssoc &assoc = (*vi).second;
918 if (assoc._might_have_unused) {
919 assoc.remove_unused_vertices(vdata);
922 _vdata_assoc.clear();
928 _reversed_normals.clear();
946 if (vdata->get_num_rows() > _max_collect_vertices) {
954 if ((collect_bits & SceneGraphReducer::CVD_name) != 0) {
955 key._name = vdata->get_name();
957 if ((collect_bits & SceneGraphReducer::CVD_format) != 0) {
958 key._format = format;
960 if ((collect_bits & SceneGraphReducer::CVD_usage_hint) != 0) {
961 key._usage_hint = vdata->get_usage_hint();
963 key._usage_hint = Geom::UH_unspecified;
965 if ((collect_bits & SceneGraphReducer::CVD_animation_type) != 0) {
966 key._animation_type = format->get_animation().get_animation_type();
968 key._animation_type = Geom::AT_none;
971 AlreadyCollectedMap::const_iterator ai;
972 ai = _already_collected_map.find(vdata);
973 if (ai != _already_collected_map.end()) {
975 const AlreadyCollectedData &acd = (*ai).second;
976 SourceGeom source_geom;
977 source_geom._geom = geom;
978 source_geom._vertex_offset = acd._vertex_offset;
979 acd._ncd->_source_geoms.push_back(source_geom);
984 NewCollectedMap::iterator ni = _new_collected_map.find(key);
985 NewCollectedData *ncd;
986 if (ni != _new_collected_map.end()) {
992 ncd =
new NewCollectedData(vdata);
993 _new_collected_list.push_back(ncd);
994 _new_collected_map[key] = ncd;
997 if (ncd->_new_format != format) {
998 ncd->_new_format = format->get_union_format(ncd->_new_format);
1001 int this_num_vertices = vdata->get_num_rows();
1004 ncd->_num_vertices + this_num_vertices > _max_collect_vertices) {
1007 ncd =
new NewCollectedData(vdata);
1008 _new_collected_list.push_back(ncd);
1009 _new_collected_map[key] = ncd;
1012 int vertex_offset = ncd->_num_vertices;
1014 AlreadyCollectedData &acd = _already_collected_map[vdata];
1016 acd._vertex_offset = vertex_offset;
1018 SourceGeom source_geom;
1019 source_geom._geom = geom;
1020 source_geom._vertex_offset = vertex_offset;
1021 ncd->_source_geoms.push_back(source_geom);
1023 SourceData source_data;
1024 source_data._vdata = vdata;
1025 source_data._num_vertices = this_num_vertices;
1027 ncd->_source_datas.push_back(source_data);
1028 ncd->_num_vertices += this_num_vertices;
1048 int num_adjusted = 0;
1049 GeomTransformer *dynamic =
nullptr;
1051 GeomNode::CDWriter cdata(node->_cycler);
1052 GeomNode::GeomList::iterator gi;
1053 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
1054 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
1057 entry._geom = new_geom;
1059 if ((collect_bits & SceneGraphReducer::CVD_avoid_dynamic) != 0 &&
1060 new_geom->get_vertex_data()->get_usage_hint() < Geom::UH_static) {
1063 if (dynamic ==
nullptr) {
1064 dynamic =
new GeomTransformer(*
this);
1073 if (dynamic !=
nullptr) {
1078 return num_adjusted;
1092 int num_adjusted = 0;
1094 NewCollectedList::iterator nci;
1095 for (nci = _new_collected_list.begin();
1096 nci != _new_collected_list.end();
1098 NewCollectedData *ncd = (*nci);
1100 num_adjusted += ncd->apply_format_only_changes();
1102 num_adjusted += ncd->apply_collect_changes();
1107 _new_collected_list.clear();
1108 _new_collected_map.clear();
1109 _already_collected_map.clear();
1111 return num_adjusted;
1128 vdata = munger->premunge_data(vdata);
1129 CPT(
Geom) pgeom = geom;
1130 munger->premunge_geom(pgeom, vdata);
1132 PT(
Geom) geom_copy = pgeom->make_copy();
1133 geom_copy->set_vertex_data(vdata);
1141GeomTransformer::NewCollectedData::
1144 _vdata_name = source_data->
get_name();
1154int GeomTransformer::NewCollectedData::
1155apply_format_only_changes() {
1156 int num_modified = 0;
1161 typedef pmap< CPT(GeomVertexData), CPT(GeomVertexData) > VDataMap;
1164 SourceGeoms::iterator sgi;
1165 for (sgi = _source_geoms.begin(); sgi != _source_geoms.end(); ++sgi) {
1166 SourceGeom &sg = (*sgi);
1167 CPT(GeomVertexData) orig_data = sg._geom->get_vertex_data();
1169 if (orig_data->get_format() != _new_format) {
1170 VDataMap::iterator mi = vdata_map.find(orig_data);
1171 if (mi != vdata_map.end()) {
1173 sg._geom->set_vertex_data((*mi).second);
1177 CPT(GeomVertexData) new_data = orig_data->convert_to(_new_format);
1178 vdata_map[orig_data] = new_data;
1181 sg._geom->set_vertex_data(new_data);
1186 return num_modified;
1193int GeomTransformer::NewCollectedData::
1194apply_collect_changes() {
1195 if (_num_vertices == 0) {
1200 new GeomVertexData(_vdata_name, _new_format, _usage_hint);
1202 _new_data->unclean_set_num_rows(_num_vertices);
1205 int vertex_offset = 0;
1206 SourceDatas::iterator sdi;
1207 for (sdi = _source_datas.begin(); sdi != _source_datas.end(); ++sdi) {
1208 SourceData &sd = (*sdi);
1209 CPT(GeomVertexData) vdata = sd._vdata;
1211 if (_new_format != vdata->get_format()) {
1215 vdata = vdata->convert_to(_new_format);
1218 append_vdata(vdata, vertex_offset);
1219 vertex_offset += sd._num_vertices;
1222 nassertr(vertex_offset == _num_vertices, 0);
1224 if (_new_btable !=
nullptr) {
1225 _new_btable->set_rows(_new_btable_rows);
1226 _new_data->set_transform_blend_table(_new_btable);
1232 _new_btable.clear();
1233 _new_btable_rows.clear();
1242void GeomTransformer::NewCollectedData::
1243append_vdata(
const GeomVertexData *vdata,
int vertex_offset) {
1245 PT(GeomVertexArrayDataHandle) new_handle = _new_data->modify_array_handle(i);
1246 CPT(GeomVertexArrayDataHandle) old_handle = vdata->get_array_handle(i);
1247 size_t stride = (size_t)_new_format->get_array(i)->get_stride();
1248 size_t start_byte = (size_t)vertex_offset * stride;
1249 size_t copy_bytes = old_handle->get_data_size_bytes();
1250 nassertv(start_byte + copy_bytes <= new_handle->get_data_size_bytes());
1252 new_handle->copy_subdata_from(start_byte, copy_bytes, old_handle, 0, copy_bytes);
1261 _new_data->get_transform_table() !=
nullptr) {
1263 CPT(TransformTable) old_table;
1267 PT(TransformTable) temp_table =
new TransformTable;
1269 PT(VertexTransform) identity_transform =
new UserVertexTransform(
"identity");
1270 temp_table->add_transform(identity_transform);
1271 old_table = TransformTable::register_table(temp_table);
1277 typedef pmap<const VertexTransform *, int> AddedTransforms;
1278 AddedTransforms added_transforms;
1280 int num_old_transforms = old_table->get_num_transforms();
1281 for (
int i = 0; i < num_old_transforms; i++) {
1282 added_transforms[old_table->get_transform(i)] = i;
1288 PT(TransformTable) new_table;
1289 if (_new_data->get_transform_table() !=
nullptr) {
1290 new_table =
new TransformTable(*_new_data->get_transform_table());
1292 new_table =
new TransformTable;
1298 IndexMap transform_map;
1300 int num_transforms = old_table->get_num_transforms();
1301 transform_map.reserve(num_transforms);
1302 for (
int ti = 0; ti < num_transforms; ++ti) {
1303 const VertexTransform *transform = old_table->get_transform(ti);
1304 AddedTransforms::iterator ai = added_transforms.find(transform);
1305 if (ai != added_transforms.end()) {
1307 transform_map.push_back((*ai).second);
1310 int tj = new_table->add_transform(transform);
1311 transform_map.push_back(tj);
1312 added_transforms[transform] = tj;
1315 _new_data->set_transform_table(TransformTable::register_table(new_table));
1320 GeomVertexRewriter index(_new_data, InternalName::get_transform_index());
1321 if (index.has_column()) {
1322 int num_values = index.get_column()->get_num_values();
1325 index.set_row_unsafe(vertex_offset);
1326 for (
int ci = 0; ci < num_rows; ++ci) {
1327 LVecBase4i indices = index.get_data4i();
1328 for (
int i = 0; i < num_values; i++) {
1329 nassertv(indices[i] >= 0 && indices[i] < (
int)transform_map.size());
1330 indices[i] = transform_map[indices[i]];
1332 index.set_data4i(indices);
1337 if (vdata->get_transform_blend_table() !=
nullptr) {
1345 CPT(TransformBlendTable) old_btable = vdata->get_transform_blend_table();
1347 if (_new_btable ==
nullptr) {
1348 _new_btable =
new TransformBlendTable;
1349 _new_btable->add_blend(TransformBlend());
1352 SparseArray new_rows = old_btable->get_rows();
1353 new_rows <<= vertex_offset;
1354 _new_btable_rows |= new_rows;
1359 int num_blends = old_btable->get_num_blends();
1360 blend_map.reserve(num_blends);
1361 for (
int bi = 0; bi < num_blends; ++bi) {
1362 int bj = _new_btable->add_blend(old_btable->get_blend(bi));
1363 blend_map.push_back(bj);
1368 GeomVertexRewriter index(_new_data, InternalName::get_transform_blend());
1369 if (index.has_column()) {
1371 index.set_row_unsafe(vertex_offset);
1373 for (
int ci = 0; ci < num_rows; ++ci) {
1374 int orig_index = index.get_data1i();
1375 nassertv(orig_index >= 0 && orig_index < (
int)blend_map.size());
1376 int new_index = blend_map[orig_index];
1377 index.set_data1i(new_index);
1389 PT(SliderTable) new_sliders;
1390 if (_new_data->get_slider_table() !=
nullptr) {
1391 new_sliders =
new SliderTable(*_new_data->get_slider_table());
1393 new_sliders =
new SliderTable;
1396 for (
int si = 0; si < num_sliders; ++si) {
1398 new_rows <<= vertex_offset;
1399 new_sliders->add_slider(old_sliders->
get_slider(si), new_rows);
1401 _new_data->set_slider_table(SliderTable::register_table(new_sliders));
1408void GeomTransformer::NewCollectedData::
1410 SourceGeoms::iterator sgi;
1411 for (sgi = _source_geoms.begin(); sgi != _source_geoms.end(); ++sgi) {
1412 SourceGeom &sg = (*sgi);
1413 sg._geom->offset_vertices(_new_data, sg._vertex_offset);
1420void GeomTransformer::VertexDataAssoc::
1421remove_unused_vertices(
const GeomVertexData *vdata) {
1422 if (_geoms.empty()) {
1429 BitArray referenced_vertices;
1430 bool any_referenced =
false;
1431 GeomList::iterator gi;
1432 for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
1434 if (geom->get_vertex_data() != vdata) {
1438 any_referenced =
true;
1439 int num_primitives = geom->get_num_primitives();
1440 for (
int i = 0; i < num_primitives; ++i) {
1441 GeomPrimitivePipelineReader reader(geom->get_primitive(i), current_thread);
1442 reader.get_referenced_vertices(referenced_vertices);
1446 if (!any_referenced) {
1452 if (num_vertices <= new_num_vertices) {
1454 nassertv(num_vertices == new_num_vertices);
1459 int *remap_array = (
int *)alloca(
sizeof(
int) * num_vertices);
1463 for (index = 0; index < num_vertices; ++index) {
1464 if (referenced_vertices.
get_bit(index)) {
1465 while (next_index <= index) {
1466 remap_array[next_index] = new_index;
1472 while (next_index < num_vertices) {
1473 remap_array[next_index] = new_num_vertices - 1;
1478 PT(GeomVertexData) new_vdata =
new GeomVertexData(*vdata);
1479 new_vdata->unclean_set_num_rows(new_num_vertices);
1482 nassertv(num_arrays == new_vdata->get_num_arrays());
1484 GeomVertexDataPipelineReader reader(vdata, current_thread);
1485 reader.check_array_readers();
1486 GeomVertexDataPipelineWriter writer(new_vdata,
true, current_thread);
1487 writer.check_array_writers();
1489 for (
size_t a = 0; a < num_arrays; ++a) {
1490 const GeomVertexArrayDataHandle *array_reader = reader.get_array_reader(a);
1491 GeomVertexArrayDataHandle *array_writer = writer.get_array_writer(a);
1493 int stride = array_reader->get_array_format()->get_stride();
1494 nassertv(stride == array_writer->get_array_format()->get_stride());
1498 for (index = 0; index < num_vertices; ++index) {
1499 if (referenced_vertices.
get_bit(index)) {
1502 index * stride, stride);
1509 PT(TransformBlendTable) tbtable = new_vdata->modify_transform_blend_table();
1510 if (!tbtable.is_null()) {
1511 const SparseArray &rows = tbtable->get_rows();
1512 SparseArray new_rows;
1514 for (
int si = 0; si < num_subranges; ++si) {
1517 nassertv(from >= 0 && from < num_vertices && to > from && to <= num_vertices);
1518 int new_from = remap_array[from];
1519 int new_to = remap_array[to - 1] + 1;
1520 nassertv(new_from >= 0 && new_from < new_num_vertices && new_to >= new_from && new_to <= new_num_vertices);
1521 new_rows.
set_range(new_from, new_to - new_from);
1523 tbtable->set_rows(new_rows);
1527 for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
1529 if (geom->get_vertex_data() != vdata) {
1533 int num_primitives = geom->get_num_primitives();
1534 for (
int i = 0; i < num_primitives; ++i) {
1535 PT(GeomPrimitive) prim = geom->modify_primitive(i);
1536 prim->make_indexed();
1537 PT(GeomVertexArrayData) vertices = prim->modify_vertices();
1538 GeomVertexRewriter rewriter(vertices, 0, current_thread);
1540 while (!rewriter.is_at_end()) {
1541 index = rewriter.get_data1i();
1542 nassertv(index >= 0 && index < num_vertices);
1543 new_index = remap_array[index];
1544 nassertv(new_index >= 0 && new_index < new_num_vertices);
1545 rewriter.set_data1i(new_index);
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the array.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
Indicates what color should be applied to renderable geometry.
get_color
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
static ConstPointerTo< RenderAttrib > make_vertex()
Constructs a new ColorAttrib object that indicates geometry should be rendered according to its own v...
get_color_type
Returns the type of color specified by this ColorAttrib.
To * get_write_pointer()
See CopyOnWritePointer::get_write_pointer().
const To * get_read_pointer(Thread *current_thread=Thread::get_current_thread()) const
See CopyOnWritePointer::get_read_pointer().
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
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.
get_num_geoms
Returns the number of geoms in the node.
get_geom_state
Returns the RenderState associated with the nth geom of the node.
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...
This defines how a single column is interleaved within a vertex array stored within a Geom.
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
get_name
Returns the name passed to the constructor, if any.
get_transform_table
Returns a const pointer to the TransformTable assigned to this data.
int get_num_rows() const
Returns the number of rows stored within all the arrays.
get_num_arrays
Returns the number of individual arrays stored within the data.
get_slider_table
Returns a const pointer to the SliderTable assigned to this data.
get_format
Returns a pointer to the GeomVertexFormat structure that defines this data.
get_usage_hint
Returns the usage hint that was passed to the constructor, and which will be passed to each array dat...
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
bool is_at_end() const
Returns true if the reader is currently at the end of the list of vertices, false otherwise.
const LVecBase4 & get_data4()
Returns the data associated with the read row, expressed as a 4-component value, and advances the rea...
const LVecBase2 & get_data2()
Returns the data associated with the read row, expressed as a 2-component value, and advances the rea...
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
This object provides the functionality of both a GeomVertexReader and a GeomVertexWriter,...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
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.
A container for geometry primitives.
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
void set_vertex_data(const GeomVertexData *data)
Replaces the Geom's underlying vertex data table with a completely new table.
Encodes a string name in a hash table, mapping it to a pointer.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
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...
constexpr bool is_null() const
Returns true if the PointerTo is a NULL pointer, false otherwise.
get_ref_count
Returns the current reference count.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
ConstPointerTo< RenderState > add_attrib(const RenderAttrib *attrib, int override=0) const
Returns a new RenderState object that represents the same as the source state, with the new RenderAtt...
ConstPointerTo< RenderState > compose(const RenderState *other) const
Returns a new RenderState object that represents the composition of this state with the other state.
get_slider
Returns the nth slider in the table.
get_num_sliders
Returns the number of sliders in the table.
const SparseArray & get_slider_rows(size_t n) const
Returns the set of rows (vertices) governed by the nth slider in the table.
int get_subrange_begin(size_t n) const
Returns the first numeric element in the nth subrange.
void set_range(int low_bit, int size)
Sets the indicated range of bits on.
size_t get_num_subranges() const
Returns the number of separate subranges stored in the SparseArray.
int get_subrange_end(size_t n) const
Returns the last numeric element, plus one, in the nth subrange.
Applies a transform matrix to UV's before they are rendered.
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...
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
ConstPointerTo< TextureAttrib > filter_to_max(int max_texture_stages) const
Returns a new TextureAttrib, very much like this one, but with the number of on_stages reduced to be ...
An instance of this object is returned by Texture::peek().
Defines the properties of a named stage of the multitexture pipeline.
get_texcoord_name
See set_texcoord_name.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
A thread; that is, a lightweight process.
get_current_thread
Returns a pointer to the currently-executing Thread object.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.