00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "geomTransformer.h"
00016 #include "sceneGraphReducer.h"
00017 #include "geomNode.h"
00018 #include "geom.h"
00019 #include "geomVertexRewriter.h"
00020 #include "renderState.h"
00021 #include "transformTable.h"
00022 #include "transformBlendTable.h"
00023 #include "sliderTable.h"
00024 #include "pStatCollector.h"
00025 #include "pStatTimer.h"
00026 #include "vector_int.h"
00027 #include "userVertexTransform.h"
00028 #include "geomMunger.h"
00029 #include "texture.h"
00030 #include "texturePeeker.h"
00031 #include "config_pgraph.h"
00032
00033 PStatCollector GeomTransformer::_apply_vertex_collector("*:Flatten:apply:vertex");
00034 PStatCollector GeomTransformer::_apply_texcoord_collector("*:Flatten:apply:texcoord");
00035 PStatCollector GeomTransformer::_apply_set_color_collector("*:Flatten:apply:set color");
00036 PStatCollector GeomTransformer::_apply_scale_color_collector("*:Flatten:apply:scale color");
00037 PStatCollector GeomTransformer::_apply_texture_color_collector("*:Flatten:apply:texture color");
00038 PStatCollector GeomTransformer::_apply_set_format_collector("*:Flatten:apply:set format");
00039
00040 TypeHandle GeomTransformer::NewCollectedData::_type_handle;
00041
00042
00043
00044
00045
00046
00047 GeomTransformer::
00048 GeomTransformer() :
00049
00050 _max_collect_vertices(max_collect_vertices)
00051 {
00052 }
00053
00054
00055
00056
00057
00058
00059 GeomTransformer::
00060 GeomTransformer(const GeomTransformer ©) :
00061 _max_collect_vertices(copy._max_collect_vertices)
00062 {
00063 }
00064
00065
00066
00067
00068
00069
00070 GeomTransformer::
00071 ~GeomTransformer() {
00072 finish_collect(false);
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082 void GeomTransformer::
00083 register_vertices(Geom *geom, bool might_have_unused) {
00084 VertexDataAssoc &assoc = _vdata_assoc[geom->get_vertex_data()];
00085 assoc._geoms.push_back(geom);
00086 if (might_have_unused) {
00087 assoc._might_have_unused = true;
00088 }
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098 void GeomTransformer::
00099 register_vertices(GeomNode *node, bool might_have_unused) {
00100 Thread *current_thread = Thread::get_current_thread();
00101 OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler, current_thread) {
00102 GeomNode::CDStageWriter cdata(node->_cycler, pipeline_stage, current_thread);
00103 GeomNode::GeomList::iterator gi;
00104 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00105 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00106 GeomNode::GeomEntry &entry = (*gi);
00107 PT(Geom) geom = entry._geom.get_write_pointer();
00108 register_vertices(geom, might_have_unused);
00109 }
00110 }
00111 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler);
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121 bool GeomTransformer::
00122 transform_vertices(Geom *geom, const LMatrix4 &mat) {
00123 PStatTimer timer(_apply_vertex_collector);
00124
00125 nassertr(geom != (Geom *)NULL, false);
00126 SourceVertices sv;
00127 sv._mat = mat;
00128 sv._vertex_data = geom->get_vertex_data();
00129
00130 NewVertexData &new_data = _vertices[sv];
00131 if (new_data._vdata.is_null()) {
00132
00133 PT(GeomVertexData) new_vdata = new GeomVertexData(*sv._vertex_data);
00134 new_vdata->transform_vertices(mat);
00135 new_data._vdata = new_vdata;
00136 }
00137
00138 geom->set_vertex_data(new_data._vdata);
00139 if (sv._vertex_data->get_ref_count() > 1) {
00140 _vdata_assoc[new_data._vdata]._might_have_unused = true;
00141 _vdata_assoc[sv._vertex_data]._might_have_unused = true;
00142 }
00143
00144 return true;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 bool GeomTransformer::
00160 transform_vertices(GeomNode *node, const LMatrix4 &mat) {
00161 bool any_changed = false;
00162
00163 Thread *current_thread = Thread::get_current_thread();
00164 OPEN_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler, current_thread) {
00165 GeomNode::CDStageWriter cdata(node->_cycler, pipeline_stage, current_thread);
00166 GeomNode::GeomList::iterator gi;
00167 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00168 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00169 GeomNode::GeomEntry &entry = (*gi);
00170 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
00171 if (transform_vertices(new_geom, mat)) {
00172 entry._geom = new_geom;
00173 any_changed = true;
00174 }
00175 }
00176 }
00177 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(node->_cycler);
00178
00179 if (any_changed) {
00180 node->mark_internal_bounds_stale();
00181 }
00182
00183 return any_changed;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 bool GeomTransformer::
00195 transform_texcoords(Geom *geom, const InternalName *from_name,
00196 InternalName *to_name, const LMatrix4 &mat) {
00197 PStatTimer timer(_apply_texcoord_collector);
00198
00199 nassertr(geom != (Geom *)NULL, false);
00200
00201 SourceTexCoords st;
00202 st._mat = mat;
00203 st._from = from_name;
00204 st._to = to_name;
00205 st._vertex_data = geom->get_vertex_data();
00206
00207 NewVertexData &new_data = _texcoords[st];
00208 if (new_data._vdata.is_null()) {
00209 if (!st._vertex_data->has_column(from_name)) {
00210
00211 return false;
00212 }
00213
00214 PT(GeomVertexData) new_vdata;
00215
00216
00217 if (st._vertex_data->has_column(to_name)) {
00218 new_vdata = new GeomVertexData(*st._vertex_data);
00219 } else {
00220 const GeomVertexColumn *old_column =
00221 st._vertex_data->get_format()->get_column(from_name);
00222 new_vdata = st._vertex_data->replace_column
00223 (to_name, old_column->get_num_components(),
00224 old_column->get_numeric_type(),
00225 old_column->get_contents());
00226 }
00227
00228 CPT(GeomVertexFormat) format = new_vdata->get_format();
00229
00230 GeomVertexWriter tdata(new_vdata, to_name);
00231 GeomVertexReader fdata(new_vdata, from_name);
00232
00233 while (!fdata.is_at_end()) {
00234 const LPoint4 &coord = fdata.get_data4();
00235 tdata.set_data4(coord * mat);
00236 }
00237 new_data._vdata = new_vdata;
00238 }
00239
00240 geom->set_vertex_data(new_data._vdata);
00241 if (st._vertex_data->get_ref_count() > 1) {
00242 _vdata_assoc[new_data._vdata]._might_have_unused = true;
00243 _vdata_assoc[st._vertex_data]._might_have_unused = true;
00244 }
00245
00246 return true;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 bool GeomTransformer::
00262 transform_texcoords(GeomNode *node, const InternalName *from_name,
00263 InternalName *to_name, const LMatrix4 &mat) {
00264 bool any_changed = false;
00265
00266 GeomNode::CDWriter cdata(node->_cycler);
00267 GeomNode::GeomList::iterator gi;
00268 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00269 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00270 GeomNode::GeomEntry &entry = (*gi);
00271 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
00272 if (transform_texcoords(new_geom, from_name, to_name, mat)) {
00273 entry._geom = new_geom;
00274 any_changed = true;
00275 }
00276 }
00277
00278 return any_changed;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 bool GeomTransformer::
00290 set_color(Geom *geom, const LColor &color) {
00291 PStatTimer timer(_apply_set_color_collector);
00292
00293 SourceColors sc;
00294 sc._color = color;
00295 sc._vertex_data = geom->get_vertex_data();
00296
00297 NewVertexData &new_data = _fcolors[sc];
00298 if (new_data._vdata.is_null()) {
00299
00300 if (sc._vertex_data->has_column(InternalName::get_color())) {
00301 new_data._vdata = sc._vertex_data->set_color(color);
00302 } else {
00303 new_data._vdata = sc._vertex_data->set_color
00304 (color, 1, Geom::NT_packed_dabc, Geom::C_color);
00305 }
00306 }
00307
00308 geom->set_vertex_data(new_data._vdata);
00309 if (sc._vertex_data->get_ref_count() > 1) {
00310 _vdata_assoc[new_data._vdata]._might_have_unused = true;
00311 _vdata_assoc[sc._vertex_data]._might_have_unused = true;
00312 }
00313
00314 return true;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 bool GeomTransformer::
00327 set_color(GeomNode *node, const LColor &color) {
00328 bool any_changed = false;
00329
00330 GeomNode::CDWriter cdata(node->_cycler);
00331 GeomNode::GeomList::iterator gi;
00332 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00333 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00334 GeomNode::GeomEntry &entry = (*gi);
00335 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
00336 if (set_color(new_geom, color)) {
00337 entry._geom = new_geom;
00338 any_changed = true;
00339 }
00340 }
00341
00342 return any_changed;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352 bool GeomTransformer::
00353 transform_colors(Geom *geom, const LVecBase4 &scale) {
00354 PStatTimer timer(_apply_scale_color_collector);
00355
00356 nassertr(geom != (Geom *)NULL, false);
00357
00358 SourceColors sc;
00359 sc._color = scale;
00360 sc._vertex_data = geom->get_vertex_data();
00361
00362 NewVertexData &new_data = _tcolors[sc];
00363 if (new_data._vdata.is_null()) {
00364
00365 if (sc._vertex_data->has_column(InternalName::get_color())) {
00366 new_data._vdata = sc._vertex_data->scale_color(scale);
00367 } else {
00368 new_data._vdata = sc._vertex_data->set_color
00369 (scale, 1, Geom::NT_packed_dabc, Geom::C_color);
00370 }
00371 }
00372
00373 geom->set_vertex_data(new_data._vdata);
00374 if (sc._vertex_data->get_ref_count() > 1) {
00375 _vdata_assoc[new_data._vdata]._might_have_unused = true;
00376 _vdata_assoc[sc._vertex_data]._might_have_unused = true;
00377 }
00378
00379 return true;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 bool GeomTransformer::
00394 transform_colors(GeomNode *node, const LVecBase4 &scale) {
00395 bool any_changed = false;
00396
00397 GeomNode::CDWriter cdata(node->_cycler);
00398 GeomNode::GeomList::iterator gi;
00399 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00400 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00401 GeomNode::GeomEntry &entry = (*gi);
00402 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
00403 if (transform_colors(new_geom, scale)) {
00404 entry._geom = new_geom;
00405 any_changed = true;
00406 }
00407 }
00408
00409 return any_changed;
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 bool GeomTransformer::
00422 apply_texture_colors(Geom *geom, TextureStage *ts, Texture *tex,
00423 const TexMatrixAttrib *tma, const LColor &base_color,
00424 bool keep_vertex_color) {
00425 PStatTimer timer(_apply_texture_color_collector);
00426
00427 nassertr(geom != (Geom *)NULL, false);
00428
00429 PT(TexturePeeker) peeker = tex->peek();
00430 if (peeker == (TexturePeeker *)NULL) {
00431 return false;
00432 }
00433
00434 if (peeker->get_x_size() == 1 &&
00435 peeker->get_y_size() == 1 &&
00436 peeker->get_z_size() == 1) {
00437
00438
00439
00440 LColor color;
00441 peeker->lookup(color, 0.0f, 0.0f);
00442 color.set(color[0] * base_color[0],
00443 color[1] * base_color[1],
00444 color[2] * base_color[2],
00445 color[3] * base_color[3]);
00446 if (keep_vertex_color) {
00447 return transform_colors(geom, color);
00448 } else {
00449 return set_color(geom, color);
00450 }
00451 }
00452
00453 bool got_mat = false;
00454 LMatrix4 mat = LMatrix4::ident_mat();
00455 if (tma != (TexMatrixAttrib *)NULL && tma->has_stage(ts)) {
00456 mat = tma->get_mat(ts);
00457 got_mat = !mat.almost_equal(LMatrix4::ident_mat());
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 SourceTextureColors stc;
00497 stc._ts = ts;
00498 stc._tex = tex;
00499 stc._tma = tma;
00500 stc._base_color = base_color;
00501 stc._keep_vertex_color = keep_vertex_color;
00502 stc._vertex_data = geom->get_vertex_data();
00503
00504 NewVertexData &new_data = _tex_colors[stc];
00505 if (new_data._vdata.is_null()) {
00506
00507
00508 PT(GeomVertexData) vdata;
00509
00510
00511 if (stc._vertex_data->has_column(InternalName::get_color())) {
00512 vdata = new GeomVertexData(*stc._vertex_data);
00513 } else {
00514
00515 vdata = new GeomVertexData(*stc._vertex_data->set_color
00516 (LColor(1.0f, 1.0f, 1.0f, 1.0f), 1, Geom::NT_packed_dabc, Geom::C_color));
00517 keep_vertex_color = false;
00518 }
00519
00520
00521 bool tex3d = false;
00522 const GeomVertexColumn *column = vdata->get_format()->get_column(ts->get_texcoord_name());
00523 if (column == (GeomVertexColumn *)NULL) {
00524 return false;
00525 }
00526 if (column->get_num_components() >= 3) {
00527 tex3d = true;
00528 }
00529
00530
00531
00532 if (keep_vertex_color) {
00533
00534 GeomVertexReader gtexcoord(vdata, ts->get_texcoord_name());
00535 GeomVertexRewriter gcolor(vdata, InternalName::get_color());
00536
00537 if (got_mat || tex3d) {
00538 while (!gtexcoord.is_at_end()) {
00539 LTexCoord3 p = gtexcoord.get_data3();
00540 LColor c = gcolor.get_data4();
00541 p = p * mat;
00542 LColor color;
00543 peeker->lookup(color, p[0], p[1], p[2]);
00544 color.set(color[0] * base_color[0] * c[0],
00545 color[1] * base_color[1] * c[1],
00546 color[2] * base_color[2] * c[2],
00547 color[3] * base_color[3] * c[3]);
00548 gcolor.set_data4(color);
00549 }
00550 } else {
00551 while (!gtexcoord.is_at_end()) {
00552 LTexCoord p = gtexcoord.get_data2();
00553 LColor c = gcolor.get_data4();
00554 LColor color;
00555 peeker->lookup(color, p[0], p[1]);
00556 color.set(color[0] * base_color[0] * c[0],
00557 color[1] * base_color[1] * c[1],
00558 color[2] * base_color[2] * c[2],
00559 color[3] * base_color[3] * c[3]);
00560 gcolor.set_data4(color);
00561 }
00562 }
00563 } else {
00564
00565 GeomVertexReader gtexcoord(vdata, ts->get_texcoord_name());
00566 GeomVertexWriter gcolor(vdata, InternalName::get_color());
00567
00568 if (got_mat || tex3d) {
00569 while (!gtexcoord.is_at_end()) {
00570 LTexCoord3 p = gtexcoord.get_data3();
00571 p = p * mat;
00572 LColor color;
00573 peeker->lookup(color, p[0], p[1], p[2]);
00574 color.set(color[0] * base_color[0],
00575 color[1] * base_color[1],
00576 color[2] * base_color[2],
00577 color[3] * base_color[3]);
00578 gcolor.set_data4(color);
00579 }
00580 } else {
00581 while (!gtexcoord.is_at_end()) {
00582 LTexCoord p = gtexcoord.get_data2();
00583 LColor color;
00584 peeker->lookup(color, p[0], p[1]);
00585 color.set(color[0] * base_color[0],
00586 color[1] * base_color[1],
00587 color[2] * base_color[2],
00588 color[3] * base_color[3]);
00589 gcolor.set_data4(color);
00590 }
00591 }
00592 }
00593
00594 new_data._vdata = vdata;
00595 }
00596
00597 geom->set_vertex_data(new_data._vdata);
00598 if (stc._vertex_data->get_ref_count() > 1) {
00599 _vdata_assoc[new_data._vdata]._might_have_unused = true;
00600 _vdata_assoc[stc._vertex_data]._might_have_unused = true;
00601 }
00602
00603 return true;
00604 }
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 bool GeomTransformer::
00624 apply_texture_colors(GeomNode *node, const RenderState *state) {
00625 bool any_changed = false;
00626
00627 GeomNode::CDWriter cdata(node->_cycler);
00628 GeomNode::GeomList::iterator gi;
00629 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00630 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00631 GeomNode::GeomEntry &entry = (*gi);
00632 CPT(RenderState) geom_state = state->compose(entry._state);
00633
00634 const TextureAttrib *ta = DCAST(TextureAttrib, geom_state->get_attrib(TextureAttrib::get_class_slot()));
00635 if (ta != (TextureAttrib *)NULL) {
00636 CPT(TextureAttrib) ta2 = ta->filter_to_max(1);
00637 if (ta2->get_num_on_stages() > 0) {
00638 TextureStage *ts = ta2->get_on_stage(0);
00639 Texture *tex = ta2->get_on_texture(ts);
00640 const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, geom_state->get_attrib(TexMatrixAttrib::get_class_slot()));
00641
00642 const ColorAttrib *ca = DCAST(ColorAttrib, geom_state->get_attrib(ColorAttrib::get_class_slot()));
00643 LColor base_color(1.0f, 1.0f, 1.0f, 1.0f);
00644 bool keep_vertex_color = true;
00645 if (ca != (ColorAttrib *)NULL && ca->get_color_type() == ColorAttrib::T_flat) {
00646 base_color = ca->get_color();
00647 keep_vertex_color = false;
00648 }
00649
00650 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
00651 if (apply_texture_colors(new_geom, ts, tex, tma, base_color, keep_vertex_color)) {
00652 entry._geom = new_geom;
00653 any_changed = true;
00654
00655 if (new_geom->get_vertex_data()->has_column(InternalName::get_color())) {
00656
00657 CPT(RenderState) color_state = entry._state->set_attrib(ColorAttrib::make_vertex());
00658 if (entry._state != color_state) {
00659 entry._state = color_state;
00660 any_changed = true;
00661 }
00662 }
00663 }
00664
00665
00666 CPT(RenderState) no_tex_state = entry._state->remove_attrib(TextureAttrib::get_class_slot());
00667 if (entry._state != no_tex_state) {
00668 entry._state = no_tex_state;
00669 any_changed = true;
00670 }
00671 }
00672 }
00673 }
00674
00675 return any_changed;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685 bool GeomTransformer::
00686 apply_state(GeomNode *node, const RenderState *state) {
00687 bool any_changed = false;
00688
00689 GeomNode::CDWriter cdata(node->_cycler);
00690 GeomNode::GeomList::iterator gi;
00691 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00692 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00693 GeomNode::GeomEntry &entry = (*gi);
00694 CPT(RenderState) new_state = state->compose(entry._state);
00695 if (entry._state != new_state) {
00696 entry._state = new_state;
00697 any_changed = true;
00698 }
00699 }
00700
00701 return any_changed;
00702 }
00703
00704
00705
00706
00707
00708
00709
00710 bool GeomTransformer::
00711 set_format(Geom *geom, const GeomVertexFormat *new_format) {
00712 PStatTimer timer(_apply_set_format_collector);
00713
00714 nassertr(geom != (Geom *)NULL, false);
00715
00716 SourceFormat sf;
00717 sf._format = new_format;
00718 sf._vertex_data = geom->get_vertex_data();
00719
00720 NewVertexData &new_data = _format[sf];
00721 if (new_data._vdata.is_null()) {
00722 if (sf._vertex_data->get_format() == new_format) {
00723
00724 return false;
00725 }
00726
00727
00728 PT(GeomVertexData) new_vdata = new GeomVertexData(*sf._vertex_data);
00729 new_vdata->set_format(new_format);
00730 new_data._vdata = new_vdata;
00731 }
00732
00733 geom->set_vertex_data(new_data._vdata);
00734 if (sf._vertex_data->get_ref_count() > 1) {
00735 _vdata_assoc[new_data._vdata]._might_have_unused = true;
00736 _vdata_assoc[sf._vertex_data]._might_have_unused = true;
00737 }
00738
00739 return true;
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749 bool GeomTransformer::
00750 remove_column(Geom *geom, const InternalName *column) {
00751 CPT(GeomVertexFormat) format = geom->get_vertex_data()->get_format();
00752 if (!format->has_column(column)) {
00753 return false;
00754 }
00755
00756 PT(GeomVertexFormat) new_format = new GeomVertexFormat(*format);
00757 new_format->remove_column(column);
00758 new_format->pack_columns();
00759 format = GeomVertexFormat::register_format(new_format);
00760
00761 return set_format(geom, format);
00762 }
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 bool GeomTransformer::
00773 remove_column(GeomNode *node, const InternalName *column) {
00774 bool any_changed = false;
00775
00776 GeomNode::CDWriter cdata(node->_cycler);
00777 GeomNode::GeomList::iterator gi;
00778 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00779 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00780 GeomNode::GeomEntry &entry = (*gi);
00781 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
00782 if (remove_column(new_geom, column)) {
00783 entry._geom = new_geom;
00784 any_changed = true;
00785 }
00786 }
00787
00788 return any_changed;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 bool GeomTransformer::
00801 make_compatible_state(GeomNode *node) {
00802 if (node->get_num_geoms() < 2) {
00803 return false;
00804 }
00805
00806 GeomNode::CDWriter cdata(node->_cycler);
00807 GeomNode::GeomList::iterator gi;
00808 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
00809
00810
00811
00812
00813
00814 typedef pmap <CPT(RenderState), pvector<int> > StateTable;
00815 StateTable state_table;
00816
00817 for (int i = 0; i < (int)geoms->size(); i++) {
00818 GeomNode::GeomEntry &entry = (*geoms)[i];
00819 CPT(RenderState) canon = entry._state->remove_attrib(ColorAttrib::get_class_slot());
00820 state_table[canon].push_back(i);
00821 }
00822
00823
00824
00825 bool any_changed = false;
00826 StateTable::iterator si;
00827 for (si = state_table.begin(); si != state_table.end(); si++) {
00828
00829
00830
00831
00832 const pvector<int> &indices = (*si).second;
00833 bool mismatch = false;
00834 for (int i = 1; i < (int)indices.size(); i++) {
00835 if ((*geoms)[indices[i]]._state != (*geoms)[indices[0]]._state) {
00836 mismatch = true;
00837 break;
00838 }
00839 }
00840 if (!mismatch) {
00841 continue;
00842 }
00843
00844
00845
00846
00847
00848 const RenderState *canon_state = (*si).first;
00849 for (int i = 0; i < (int)indices.size(); i++) {
00850 GeomNode::GeomEntry &entry = (*geoms)[indices[i]];
00851 const RenderAttrib *ra = entry._state->get_attrib_def(ColorAttrib::get_class_slot());
00852 const ColorAttrib *ca = DCAST(ColorAttrib, ra);
00853 if (ca->get_color_type() == ColorAttrib::T_vertex) {
00854
00855 if (!entry._geom.get_read_pointer()->get_vertex_data()->has_column(InternalName::get_color())) {
00856 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
00857 if (set_color(new_geom, LColor(1,1,1,1))) {
00858 entry._geom = new_geom;
00859 }
00860 }
00861 } else {
00862
00863
00864 LColor c = ca->get_color();
00865 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
00866 if (set_color(new_geom, c)) {
00867 entry._geom = new_geom;
00868 }
00869 }
00870 entry._state = canon_state->add_attrib(ColorAttrib::make_vertex());
00871 any_changed = true;
00872 }
00873 }
00874
00875 return any_changed;
00876 }
00877
00878
00879
00880
00881
00882
00883
00884
00885 bool GeomTransformer::
00886 reverse_normals(Geom *geom) {
00887 nassertr(geom != (Geom *)NULL, false);
00888 CPT(GeomVertexData) orig_data = geom->get_vertex_data();
00889 NewVertexData &new_data = _reversed_normals[orig_data];
00890 if (new_data._vdata.is_null()) {
00891 new_data._vdata = orig_data->reverse_normals();
00892 }
00893
00894 if (new_data._vdata == orig_data) {
00895
00896 return false;
00897 }
00898
00899 geom->set_vertex_data(new_data._vdata);
00900 if (orig_data->get_ref_count() > 1) {
00901 _vdata_assoc[new_data._vdata]._might_have_unused = true;
00902 _vdata_assoc[orig_data]._might_have_unused = true;
00903 }
00904
00905 return true;
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 bool GeomTransformer::
00930 doubleside(GeomNode *node) {
00931 int num_geoms = node->get_num_geoms();
00932 for (int i = 0; i < num_geoms; ++i) {
00933 CPT(Geom) orig_geom = node->get_geom(i);
00934 bool has_normals = (orig_geom->get_vertex_data()->has_column(InternalName::get_normal()));
00935 if (has_normals) {
00936
00937
00938 PT(Geom) new_geom = orig_geom->reverse();
00939 reverse_normals(new_geom);
00940 node->add_geom(new_geom, node->get_geom_state(i));
00941
00942 } else {
00943
00944
00945 orig_geom.clear();
00946 node->modify_geom(i)->doubleside_in_place();
00947 }
00948 }
00949
00950 return (num_geoms != 0);
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 bool GeomTransformer::
00972 reverse(GeomNode *node) {
00973 int num_geoms = node->get_num_geoms();
00974 for (int i = 0; i < num_geoms; ++i) {
00975 PT(Geom) geom = node->modify_geom(i);
00976 geom->reverse_in_place();
00977 reverse_normals(geom);
00978 }
00979
00980 return (num_geoms != 0);
00981 }
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 void GeomTransformer::
00996 finish_apply() {
00997 VertexDataAssocMap::iterator vi;
00998 for (vi = _vdata_assoc.begin(); vi != _vdata_assoc.end(); ++vi) {
00999 const GeomVertexData *vdata = (*vi).first;
01000 VertexDataAssoc &assoc = (*vi).second;
01001 if (assoc._might_have_unused) {
01002 assoc.remove_unused_vertices(vdata);
01003 }
01004 }
01005 _vdata_assoc.clear();
01006
01007 _texcoords.clear();
01008 _fcolors.clear();
01009 _tcolors.clear();
01010 _format.clear();
01011 _reversed_normals.clear();
01012 }
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 int GeomTransformer::
01031 collect_vertex_data(Geom *geom, int collect_bits, bool format_only) {
01032 CPT(GeomVertexData) vdata = geom->get_vertex_data();
01033 if (vdata->get_num_rows() > _max_collect_vertices) {
01034
01035 return 0;
01036 }
01037
01038 CPT(GeomVertexFormat) format = vdata->get_format();
01039
01040 NewCollectedKey key;
01041 if ((collect_bits & SceneGraphReducer::CVD_name) != 0) {
01042 key._name = vdata->get_name();
01043 }
01044 if ((collect_bits & SceneGraphReducer::CVD_format) != 0) {
01045 key._format = format;
01046 }
01047 if ((collect_bits & SceneGraphReducer::CVD_usage_hint) != 0) {
01048 key._usage_hint = vdata->get_usage_hint();
01049 } else {
01050 key._usage_hint = Geom::UH_unspecified;
01051 }
01052 if ((collect_bits & SceneGraphReducer::CVD_animation_type) != 0) {
01053 key._animation_type = format->get_animation().get_animation_type();
01054 } else {
01055 key._animation_type = Geom::AT_none;
01056 }
01057
01058 AlreadyCollectedMap::const_iterator ai;
01059 ai = _already_collected_map.find(vdata);
01060 if (ai != _already_collected_map.end()) {
01061
01062 const AlreadyCollectedData &acd = (*ai).second;
01063 SourceGeom source_geom;
01064 source_geom._geom = geom;
01065 source_geom._vertex_offset = acd._vertex_offset;
01066 acd._ncd->_source_geoms.push_back(source_geom);
01067 return 0;
01068 }
01069
01070
01071
01072 NewCollectedMap::iterator ni = _new_collected_map.find(key);
01073 NewCollectedData *ncd;
01074 if (ni != _new_collected_map.end()) {
01075 ncd = (*ni).second;
01076
01077 } else {
01078
01079
01080 ncd = new NewCollectedData(vdata);
01081 _new_collected_list.push_back(ncd);
01082 _new_collected_map[key] = ncd;
01083 }
01084
01085 if (ncd->_new_format != format) {
01086 ncd->_new_format = format->get_union_format(ncd->_new_format);
01087 }
01088
01089 int this_num_vertices = vdata->get_num_rows();
01090
01091 if (!format_only &&
01092 ncd->_num_vertices + this_num_vertices > _max_collect_vertices) {
01093
01094
01095 ncd = new NewCollectedData(vdata);
01096 _new_collected_list.push_back(ncd);
01097 _new_collected_map[key] = ncd;
01098 }
01099
01100 int vertex_offset = ncd->_num_vertices;
01101
01102 AlreadyCollectedData &acd = _already_collected_map[vdata];
01103 acd._ncd = ncd;
01104 acd._vertex_offset = vertex_offset;
01105
01106 SourceGeom source_geom;
01107 source_geom._geom = geom;
01108 source_geom._vertex_offset = vertex_offset;
01109 ncd->_source_geoms.push_back(source_geom);
01110
01111 SourceData source_data;
01112 source_data._vdata = vdata;
01113 source_data._num_vertices = this_num_vertices;
01114
01115 ncd->_source_datas.push_back(source_data);
01116 ncd->_num_vertices += this_num_vertices;
01117
01118 return 0;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139 int GeomTransformer::
01140 collect_vertex_data(GeomNode *node, int collect_bits, bool format_only) {
01141 int num_adjusted = 0;
01142 GeomTransformer *dynamic = NULL;
01143
01144 GeomNode::CDWriter cdata(node->_cycler);
01145 GeomNode::GeomList::iterator gi;
01146 PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
01147 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01148 GeomNode::GeomEntry &entry = (*gi);
01149 PT(Geom) new_geom = entry._geom.get_read_pointer()->make_copy();
01150 entry._geom = new_geom;
01151
01152 if ((collect_bits & SceneGraphReducer::CVD_avoid_dynamic) != 0 &&
01153 new_geom->get_vertex_data()->get_usage_hint() < Geom::UH_static) {
01154
01155
01156 if (dynamic == (GeomTransformer *)NULL) {
01157 dynamic = new GeomTransformer(*this);
01158 }
01159 num_adjusted += dynamic->collect_vertex_data(new_geom, collect_bits, format_only);
01160
01161 } else {
01162 num_adjusted += collect_vertex_data(new_geom, collect_bits, format_only);
01163 }
01164 }
01165
01166 if (dynamic != (GeomTransformer *)NULL) {
01167 num_adjusted += dynamic->finish_collect(format_only);
01168 delete dynamic;
01169 }
01170
01171 return num_adjusted;
01172 }
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188 int GeomTransformer::
01189 finish_collect(bool format_only) {
01190 int num_adjusted = 0;
01191
01192 NewCollectedList::iterator nci;
01193 for (nci = _new_collected_list.begin();
01194 nci != _new_collected_list.end();
01195 ++nci) {
01196 NewCollectedData *ncd = (*nci);
01197 if (format_only) {
01198 num_adjusted += ncd->apply_format_only_changes();
01199 } else {
01200 num_adjusted += ncd->apply_collect_changes();
01201 }
01202 delete ncd;
01203 }
01204
01205 _new_collected_list.clear();
01206 _new_collected_map.clear();
01207 _already_collected_map.clear();
01208
01209 return num_adjusted;
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219 PT(Geom) GeomTransformer::
01220 premunge_geom(const Geom *geom, GeomMunger *munger) {
01221
01222
01223
01224
01225
01226
01227
01228 CPT(GeomVertexData) vdata = geom->get_vertex_data();
01229 vdata = munger->premunge_data(vdata);
01230 CPT(Geom) pgeom = geom;
01231 munger->premunge_geom(pgeom, vdata);
01232
01233 PT(Geom) geom_copy = pgeom->make_copy();
01234 geom_copy->set_vertex_data(vdata);
01235
01236 return geom_copy;
01237 }
01238
01239
01240
01241
01242
01243
01244 GeomTransformer::NewCollectedData::
01245 NewCollectedData(const GeomVertexData *source_data) {
01246 _new_format = source_data->get_format();
01247 _vdata_name = source_data->get_name();
01248 _usage_hint = source_data->get_usage_hint();
01249 _num_vertices = 0;
01250 }
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 int GeomTransformer::NewCollectedData::
01261 apply_format_only_changes() {
01262 int num_modified = 0;
01263
01264
01265
01266
01267
01268 typedef pmap< CPT(GeomVertexData), CPT(GeomVertexData) > VDataMap;
01269 VDataMap vdata_map;
01270
01271 SourceGeoms::iterator sgi;
01272 for (sgi = _source_geoms.begin(); sgi != _source_geoms.end(); ++sgi) {
01273 SourceGeom &sg = (*sgi);
01274 CPT(GeomVertexData) orig_data = sg._geom->get_vertex_data();
01275
01276 if (orig_data->get_format() != _new_format) {
01277 VDataMap::iterator mi = vdata_map.find(orig_data);
01278 if (mi != vdata_map.end()) {
01279
01280 sg._geom->set_vertex_data((*mi).second);
01281
01282 } else {
01283
01284 CPT(GeomVertexData) new_data = orig_data->convert_to(_new_format);
01285 vdata_map[orig_data] = new_data;
01286 ++num_modified;
01287
01288 sg._geom->set_vertex_data(new_data);
01289 }
01290 }
01291 }
01292
01293 return num_modified;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302 int GeomTransformer::NewCollectedData::
01303 apply_collect_changes() {
01304 if (_num_vertices == 0) {
01305 return 0;
01306 }
01307
01308 _new_data =
01309 new GeomVertexData(_vdata_name, _new_format, _usage_hint);
01310
01311 _new_data->unclean_set_num_rows(_num_vertices);
01312
01313
01314 int vertex_offset = 0;
01315 SourceDatas::iterator sdi;
01316 for (sdi = _source_datas.begin(); sdi != _source_datas.end(); ++sdi) {
01317 SourceData &sd = (*sdi);
01318 CPT(GeomVertexData) vdata = sd._vdata;
01319
01320 if (_new_format != vdata->get_format()) {
01321
01322
01323
01324 vdata = vdata->convert_to(_new_format);
01325 }
01326
01327 append_vdata(vdata, vertex_offset);
01328 vertex_offset += sd._num_vertices;
01329 }
01330
01331 nassertr(vertex_offset == _num_vertices, 0);
01332
01333 if (_new_btable != (TransformBlendTable *)NULL) {
01334 _new_btable->set_rows(_new_btable_rows);
01335 _new_data->set_transform_blend_table(_new_btable);
01336 }
01337
01338 update_geoms();
01339
01340 _new_data.clear();
01341 _new_btable.clear();
01342 _new_btable_rows.clear();
01343
01344 return 1;
01345 }
01346
01347
01348
01349
01350
01351
01352
01353 void GeomTransformer::NewCollectedData::
01354 append_vdata(const GeomVertexData *vdata, int vertex_offset) {
01355 for (int i = 0; i < vdata->get_num_arrays(); ++i) {
01356 PT(GeomVertexArrayData) new_array = _new_data->modify_array(i);
01357 CPT(GeomVertexArrayData) old_array = vdata->get_array(i);
01358 int stride = _new_format->get_array(i)->get_stride();
01359 int start_byte = vertex_offset * stride;
01360 int copy_bytes = old_array->get_data_size_bytes();
01361 nassertv(start_byte + copy_bytes <= new_array->get_data_size_bytes());
01362
01363 new_array->modify_handle()->copy_subdata_from
01364 (start_byte, copy_bytes,
01365 old_array->get_handle(), 0, copy_bytes);
01366 }
01367
01368
01369
01370
01371
01372
01373
01374 if (vdata->get_transform_table() != (TransformTable *)NULL ||
01375 _new_data->get_transform_table() != (TransformTable *)NULL) {
01376
01377 CPT(TransformTable) old_table;
01378 if (vdata->get_transform_table() != (TransformTable *)NULL) {
01379 old_table = vdata->get_transform_table();
01380 } else {
01381 PT(TransformTable) temp_table = new TransformTable;
01382
01383 PT(VertexTransform) identity_transform = new UserVertexTransform("identity");
01384 temp_table->add_transform(identity_transform);
01385 old_table = TransformTable::register_table(temp_table);
01386 }
01387
01388
01389
01390
01391
01392 typedef pmap<const VertexTransform *, int> AddedTransforms;
01393 AddedTransforms added_transforms;
01394
01395 int num_old_transforms = old_table->get_num_transforms();
01396 for (int i = 0; i < num_old_transforms; i++) {
01397 added_transforms[old_table->get_transform(i)] = i;
01398 }
01399
01400
01401
01402
01403 PT(TransformTable) new_table;
01404 if (_new_data->get_transform_table() != (TransformTable *)NULL) {
01405 new_table = new TransformTable(*_new_data->get_transform_table());
01406 } else {
01407 new_table = new TransformTable;
01408 }
01409
01410
01411
01412
01413 IndexMap transform_map;
01414
01415 int num_transforms = old_table->get_num_transforms();
01416 transform_map.reserve(num_transforms);
01417 for (int ti = 0; ti < num_transforms; ++ti) {
01418 const VertexTransform *transform = old_table->get_transform(ti);
01419 AddedTransforms::iterator ai = added_transforms.find(transform);
01420 if (ai != added_transforms.end()) {
01421
01422 transform_map.push_back((*ai).second);
01423 } else {
01424
01425 int tj = new_table->add_transform(transform);
01426 transform_map.push_back(tj);
01427 added_transforms[transform] = tj;
01428 }
01429 }
01430 _new_data->set_transform_table(TransformTable::register_table(new_table));
01431
01432
01433
01434
01435
01436 GeomVertexRewriter index(_new_data, InternalName::get_transform_index());
01437 if (index.has_column()) {
01438 int num_values = index.get_column()->get_num_values();
01439 int num_rows = vdata->get_num_rows();
01440 int new_index[4];
01441
01442 index.set_row_unsafe(vertex_offset);
01443 for (int ci = 0; ci < num_rows; ++ci) {
01444 const int *orig_index = index.get_data4i();
01445 for (int i = 0; i < num_values; i++) {
01446 nassertv(orig_index[i] >= 0 && orig_index[i] < (int)transform_map.size());
01447 new_index[i] = transform_map[orig_index[i]];
01448 }
01449 index.set_data4i(new_index);
01450 }
01451 }
01452 }
01453
01454 if (vdata->get_transform_blend_table() != (TransformBlendTable *)NULL) {
01455
01456
01457
01458
01459
01460
01461
01462
01463 CPT(TransformBlendTable) old_btable = vdata->get_transform_blend_table();
01464
01465 if (_new_btable == (TransformBlendTable *)NULL) {
01466 _new_btable = new TransformBlendTable;
01467 _new_btable->add_blend(TransformBlend());
01468 }
01469
01470 SparseArray new_rows = old_btable->get_rows();
01471 new_rows <<= vertex_offset;
01472 _new_btable_rows |= new_rows;
01473
01474
01475 IndexMap blend_map;
01476
01477 int num_blends = old_btable->get_num_blends();
01478 blend_map.reserve(num_blends);
01479 for (int bi = 0; bi < num_blends; ++bi) {
01480 int bj = _new_btable->add_blend(old_btable->get_blend(bi));
01481 blend_map.push_back(bj);
01482 }
01483
01484
01485
01486
01487 GeomVertexRewriter index(_new_data, InternalName::get_transform_blend());
01488 if (index.has_column()) {
01489 int num_rows = vdata->get_num_rows();
01490 index.set_row_unsafe(vertex_offset);
01491
01492 for (int ci = 0; ci < num_rows; ++ci) {
01493 int orig_index = index.get_data1i();
01494 nassertv(orig_index >= 0 && orig_index < (int)blend_map.size());
01495 int new_index = blend_map[orig_index];
01496 index.set_data1i(new_index);
01497 }
01498 }
01499 }
01500
01501 if (vdata->get_slider_table() != (SliderTable *)NULL) {
01502
01503
01504
01505
01506
01507 const SliderTable *old_sliders = vdata->get_slider_table();
01508 PT(SliderTable) new_sliders;
01509 if (_new_data->get_slider_table() != (SliderTable *)NULL) {
01510 new_sliders = new SliderTable(*_new_data->get_slider_table());
01511 } else {
01512 new_sliders = new SliderTable;
01513 }
01514 int num_sliders = old_sliders->get_num_sliders();
01515 for (int si = 0; si < num_sliders; ++si) {
01516 SparseArray new_rows = old_sliders->get_slider_rows(si);
01517 new_rows <<= vertex_offset;
01518 new_sliders->add_slider(old_sliders->get_slider(si), new_rows);
01519 }
01520 _new_data->set_slider_table(SliderTable::register_table(new_sliders));
01521 }
01522 }
01523
01524
01525
01526
01527
01528
01529
01530 void GeomTransformer::NewCollectedData::
01531 update_geoms() {
01532 SourceGeoms::iterator sgi;
01533 for (sgi = _source_geoms.begin(); sgi != _source_geoms.end(); ++sgi) {
01534 SourceGeom &sg = (*sgi);
01535 sg._geom->offset_vertices(_new_data, sg._vertex_offset);
01536 }
01537 }
01538
01539
01540
01541
01542
01543
01544 void GeomTransformer::VertexDataAssoc::
01545 remove_unused_vertices(const GeomVertexData *vdata) {
01546 if (_geoms.empty()) {
01547
01548 return;
01549 }
01550
01551 PT(Thread) current_thread = Thread::get_current_thread();
01552
01553 BitArray referenced_vertices;
01554 bool any_referenced = false;
01555 GeomList::iterator gi;
01556 for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
01557 Geom *geom = (*gi);
01558 if (geom->get_vertex_data() != vdata) {
01559 continue;
01560 }
01561
01562 any_referenced = true;
01563 int num_primitives = geom->get_num_primitives();
01564 for (int i = 0; i < num_primitives; ++i) {
01565 CPT(GeomPrimitive) prim = geom->get_primitive(i);
01566
01567 GeomPrimitivePipelineReader reader(prim, current_thread);
01568 int num_vertices = reader.get_num_vertices();
01569 for (int vi = 0; vi < num_vertices; ++vi) {
01570 referenced_vertices.set_bit(reader.get_vertex(vi));
01571 }
01572 }
01573 }
01574
01575 if (!any_referenced) {
01576 return;
01577 }
01578
01579 int num_vertices = vdata->get_num_rows();
01580 int new_num_vertices = referenced_vertices.get_num_on_bits();
01581 if (num_vertices <= new_num_vertices) {
01582
01583 nassertv(num_vertices == new_num_vertices);
01584 return;
01585 }
01586
01587
01588 int *remap_array = (int *)alloca(sizeof(int) * num_vertices);
01589 int new_index = 0;
01590 int index;
01591 int next_index = 0;
01592 for (index = 0; index < num_vertices; ++index) {
01593 if (referenced_vertices.get_bit(index)) {
01594 while (next_index <= index) {
01595 remap_array[next_index] = new_index;
01596 ++next_index;
01597 }
01598 ++new_index;
01599 }
01600 }
01601 while (next_index < num_vertices) {
01602 remap_array[next_index] = new_num_vertices - 1;
01603 ++next_index;
01604 }
01605
01606
01607 PT(GeomVertexData) new_vdata = new GeomVertexData(*vdata);
01608 new_vdata->unclean_set_num_rows(new_num_vertices);
01609
01610 int num_arrays = vdata->get_num_arrays();
01611 nassertv(num_arrays == new_vdata->get_num_arrays());
01612
01613 GeomVertexDataPipelineReader reader(vdata, current_thread);
01614 reader.check_array_readers();
01615 GeomVertexDataPipelineWriter writer(new_vdata, true, current_thread);
01616 writer.check_array_writers();
01617
01618 for (int a = 0; a < num_arrays; ++a) {
01619 const GeomVertexArrayDataHandle *array_reader = reader.get_array_reader(a);
01620 GeomVertexArrayDataHandle *array_writer = writer.get_array_writer(a);
01621
01622 int stride = array_reader->get_array_format()->get_stride();
01623 nassertv(stride == array_writer->get_array_format()->get_stride());
01624
01625 int new_index = 0;
01626 int index;
01627 for (index = 0; index < num_vertices; ++index) {
01628 if (referenced_vertices.get_bit(index)) {
01629 array_writer->copy_subdata_from(new_index * stride, stride,
01630 array_reader,
01631 index * stride, stride);
01632 ++new_index;
01633 }
01634 }
01635 }
01636
01637
01638 PT(TransformBlendTable) tbtable = new_vdata->modify_transform_blend_table();
01639 if (!tbtable.is_null()) {
01640 const SparseArray &rows = tbtable->get_rows();
01641 SparseArray new_rows;
01642 int num_subranges = rows.get_num_subranges();
01643 for (int si = 0; si < num_subranges; ++si) {
01644 int from = rows.get_subrange_begin(si);
01645 int to = rows.get_subrange_end(si);
01646 nassertv(from >= 0 && from < num_vertices && to > from && to <= num_vertices);
01647 int new_from = remap_array[from];
01648 int new_to = remap_array[to - 1] + 1;
01649 nassertv(new_from >= 0 && new_from < new_num_vertices && new_to >= new_from && new_to <= new_num_vertices);
01650 new_rows.set_range(new_from, new_to - new_from);
01651 }
01652 tbtable->set_rows(new_rows);
01653 }
01654
01655
01656 for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) {
01657 Geom *geom = (*gi);
01658 if (geom->get_vertex_data() != vdata) {
01659 continue;
01660 }
01661
01662 int num_primitives = geom->get_num_primitives();
01663 for (int i = 0; i < num_primitives; ++i) {
01664 PT(GeomPrimitive) prim = geom->modify_primitive(i);
01665 prim->make_indexed();
01666 PT(GeomVertexArrayData) vertices = prim->modify_vertices();
01667 GeomVertexRewriter rewriter(vertices, 0, current_thread);
01668
01669 while (!rewriter.is_at_end()) {
01670 index = rewriter.get_data1i();
01671 nassertv(index >= 0 && index < num_vertices);
01672 new_index = remap_array[index];
01673 nassertv(new_index >= 0 && new_index < new_num_vertices);
01674 rewriter.set_data1i(new_index);
01675 }
01676 }
01677
01678 geom->set_vertex_data(new_vdata);
01679 }
01680 }