00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "geomNode.h"
00016 #include "geom.h"
00017 #include "geomTransformer.h"
00018 #include "sceneGraphReducer.h"
00019 #include "accumulatedAttribs.h"
00020 #include "colorAttrib.h"
00021 #include "colorScaleAttrib.h"
00022 #include "texMatrixAttrib.h"
00023 #include "textureAttrib.h"
00024 #include "bamReader.h"
00025 #include "bamWriter.h"
00026 #include "datagram.h"
00027 #include "datagramIterator.h"
00028 #include "indent.h"
00029 #include "pset.h"
00030 #include "config_pgraph.h"
00031 #include "graphicsStateGuardianBase.h"
00032 #include "boundingBox.h"
00033 #include "config_mathutil.h"
00034
00035
00036 bool allow_flatten_color = ConfigVariableBool
00037 ("allow-flatten-color", false,
00038 PRC_DESC("allows color to always be flattened to vertices"));
00039
00040 TypeHandle GeomNode::_type_handle;
00041
00042
00043
00044
00045
00046
00047 GeomNode::
00048 GeomNode(const string &name) :
00049 PandaNode(name)
00050 {
00051 _preserved = preserve_geom_nodes;
00052
00053
00054 set_into_collide_mask(get_default_collide_mask());
00055 }
00056
00057
00058
00059
00060
00061
00062 GeomNode::
00063 GeomNode(const GeomNode ©) :
00064 PandaNode(copy),
00065 _preserved(copy._preserved),
00066 _cycler(copy._cycler)
00067 {
00068 }
00069
00070
00071
00072
00073
00074
00075 GeomNode::
00076 ~GeomNode() {
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 PandaNode *GeomNode::
00089 make_copy() const {
00090 return new GeomNode(*this);
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 void GeomNode::
00106 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00107 GeomTransformer &transformer) {
00108 if (pgraph_cat.is_debug()) {
00109 pgraph_cat.debug()
00110 << "Transforming geometry:\n";
00111 attribs.write(pgraph_cat.debug(false), attrib_types, 2);
00112 }
00113
00114 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00115 if (!attribs._transform->is_identity()) {
00116 transformer.transform_vertices(this, attribs._transform->get_mat());
00117 }
00118 }
00119
00120 Thread *current_thread = Thread::get_current_thread();
00121 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00122 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00123 GeomList::iterator gi;
00124 PT(GeomList) geoms = cdata->modify_geoms();
00125
00126
00127
00128
00129
00130 size_t num_geoms = geoms->size();
00131 for (size_t i = 0; i < num_geoms; ++i) {
00132 GeomEntry *entry = &(*geoms)[i];
00133 PT(Geom) new_geom = entry->_geom.get_read_pointer()->make_copy();
00134
00135 AccumulatedAttribs geom_attribs = attribs;
00136 entry->_state = geom_attribs.collect(entry->_state, attrib_types);
00137
00138 bool any_changed = false;
00139
00140 if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
00141 CPT(RenderAttrib) ra = geom_attribs._color;
00142 if (ra != (const RenderAttrib *)NULL) {
00143 int override = geom_attribs._color_override;
00144 entry->_state = entry->_state->add_attrib(ra, override);
00145 }
00146
00147 ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
00148 CPT (ColorAttrib) ca = DCAST(ColorAttrib, ra);
00149 if (ca->get_color_type() != ColorAttrib::T_vertex) {
00150 if(allow_flatten_color) {
00151 if(transformer.set_color(new_geom, ca->get_color())) {
00152 any_changed = true;
00153 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
00154 }
00155 } else {
00156 if (transformer.remove_column(new_geom, InternalName::get_color())) {
00157 any_changed = true;
00158 }
00159 }
00160 }
00161 }
00162 if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
00163 if (geom_attribs._color_scale != (const RenderAttrib *)NULL) {
00164 CPT(ColorScaleAttrib) csa = DCAST(ColorScaleAttrib, geom_attribs._color_scale);
00165 if (csa->get_scale() != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
00166
00167
00168
00169
00170
00171 CPT(RenderAttrib) ra = entry->_state->get_attrib_def(ColorAttrib::get_class_slot());
00172 CPT(ColorAttrib) ca = DCAST(ColorAttrib, ra);
00173 if(allow_flatten_color) {
00174 if (transformer.transform_colors(new_geom, csa->get_scale())) {
00175 any_changed = true;
00176 }
00177 } else {
00178 if (ca->get_color_type() == ColorAttrib::T_off) {
00179 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
00180
00181
00182 entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(csa->get_scale()));
00183
00184 } else if (ca->get_color_type() == ColorAttrib::T_flat) {
00185
00186
00187 const LColor &c1 = ca->get_color();
00188 const LVecBase4 &c2 = csa->get_scale();
00189 LColor color(c1[0] * c2[0], c1[1] * c2[1],
00190 c1[2] * c2[2], c1[3] * c2[3]);
00191 entry->_state = entry->_state->set_attrib(ColorAttrib::make_flat(color));
00192
00193 } else {
00194
00195
00196 if (transformer.transform_colors(new_geom, csa->get_scale())) {
00197 any_changed = true;
00198 }
00199 entry->_state = entry->_state->set_attrib(ColorAttrib::make_vertex());
00200 }
00201 }
00202 }
00203 }
00204 }
00205
00206 if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
00207 if (geom_attribs._tex_matrix != (const RenderAttrib *)NULL) {
00208
00209
00210
00211
00212
00213
00214 NameCount name_count;
00215
00216 if (geom_attribs._texture != (RenderAttrib *)NULL) {
00217 const TextureAttrib *ta = DCAST(TextureAttrib, geom_attribs._texture);
00218 int num_on_stages = ta->get_num_on_stages();
00219 for (int si = 0; si < num_on_stages; si++) {
00220 TextureStage *stage = ta->get_on_stage(si);
00221 const InternalName *name = stage->get_texcoord_name();
00222 count_name(name_count, name);
00223 }
00224 }
00225
00226 const TexMatrixAttrib *tma =
00227 DCAST(TexMatrixAttrib, geom_attribs._tex_matrix);
00228
00229 CPT(TexMatrixAttrib) new_tma = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
00230
00231 int num_stages = tma->get_num_stages();
00232 for (int i = 0; i < num_stages; i++) {
00233 TextureStage *stage = tma->get_stage(i);
00234 InternalName *name = stage->get_texcoord_name();
00235 if (get_name_count(name_count, name) > 1) {
00236
00237
00238 new_tma = DCAST(TexMatrixAttrib, new_tma->add_stage(stage, tma->get_transform(stage)));
00239
00240 } else {
00241
00242
00243 if (transformer.transform_texcoords(new_geom, name, name, tma->get_mat(stage))) {
00244 any_changed = true;
00245 }
00246 }
00247 }
00248
00249 if (!new_tma->is_empty()) {
00250 entry->_state = entry->_state->add_attrib(new_tma);
00251 }
00252 }
00253 }
00254
00255 if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
00256 entry->_state = geom_attribs._other->compose(entry->_state);
00257 }
00258
00259
00260
00261
00262
00263 if ((attrib_types & SceneGraphReducer::TT_cull_face) != 0) {
00264 if (geom_attribs._cull_face != (const RenderAttrib *)NULL) {
00265 const CullFaceAttrib *cfa = DCAST(CullFaceAttrib, geom_attribs._cull_face);
00266 CullFaceAttrib::Mode mode = cfa->get_effective_mode();
00267 switch (mode) {
00268 case CullFaceAttrib::M_cull_none:
00269
00270 {
00271 bool has_normals = (new_geom->get_vertex_data()->has_column(InternalName::get_normal()));
00272 if (has_normals) {
00273
00274
00275 PT(Geom) dup_geom = new_geom->reverse();
00276 transformer.reverse_normals(dup_geom);
00277
00278 geoms->push_back(GeomEntry(dup_geom, entry->_state));
00279
00280
00281
00282
00283 entry = &(*geoms)[i];
00284
00285 } else {
00286
00287
00288 new_geom->doubleside_in_place();
00289 any_changed = true;
00290 }
00291 }
00292 break;
00293
00294 case CullFaceAttrib::M_cull_counter_clockwise:
00295
00296 new_geom->reverse_in_place();
00297 transformer.reverse_normals(new_geom);
00298 any_changed = true;
00299 break;
00300
00301 default:
00302 break;
00303 }
00304 }
00305 }
00306
00307 if (any_changed) {
00308 entry->_geom = new_geom;
00309 }
00310 }
00311 }
00312 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00313
00314 if ((attrib_types & SceneGraphReducer::TT_apply_texture_color) != 0) {
00315 transformer.apply_texture_colors(this, attribs._other);
00316 }
00317
00318 transformer.register_vertices(this, false);
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 void GeomNode::
00334 xform(const LMatrix4 &mat) {
00335 GeomTransformer transformer;
00336 transformer.transform_vertices(this, mat);
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 bool GeomNode::
00351 safe_to_flatten() const {
00352 if (_preserved) {
00353 return false;
00354 }
00355
00356 return true;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 bool GeomNode::
00370 safe_to_combine() const {
00371 if (_preserved) {
00372 return false;
00373 }
00374
00375 return true;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 void GeomNode::
00387 r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
00388 GeomTransformer &transformer, Thread *current_thread) {
00389 PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects();
00390
00391 CDReader cdata(_cycler, current_thread);
00392 GeomList::const_iterator gi;
00393 CPT(GeomList) geoms = cdata->get_geoms();
00394 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00395 const GeomEntry &entry = (*gi);
00396 CPT(RenderState) geom_state = node_state->compose(entry._state);
00397 CPT(Geom) geom = entry._geom.get_read_pointer();
00398
00399
00400 PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
00401 geom = transformer.premunge_geom(geom, munger);
00402
00403
00404 CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
00405 vdata = vdata->animate_vertices(false, current_thread);
00406 GeomVertexDataPipelineReader vdata_reader(vdata, current_thread);
00407 int num_arrays = vdata_reader.get_num_arrays();
00408 for (int i = 0; i < num_arrays; ++i) {
00409 CPT(GeomVertexArrayData) array = vdata_reader.get_array(i);
00410 ((GeomVertexArrayData *)array.p())->prepare(prepared_objects);
00411 }
00412
00413
00414 int num_primitives = geom->get_num_primitives();
00415 for (int i = 0; i < num_primitives; ++i) {
00416 CPT(GeomPrimitive) prim = geom->get_primitive(i);
00417 ((GeomPrimitive *)prim.p())->prepare(prepared_objects);
00418 }
00419
00420
00421 const RenderAttrib *attrib =
00422 geom_state->get_attrib(TextureAttrib::get_class_slot());
00423 if (attrib != (const RenderAttrib *)NULL) {
00424 const TextureAttrib *ta;
00425 DCAST_INTO_V(ta, attrib);
00426 int num_stages = ta->get_num_on_stages();
00427 for (int i = 0; i < num_stages; ++i) {
00428 Texture *texture = ta->get_on_texture(ta->get_on_stage(i));
00429 if (texture != (Texture *)NULL) {
00430 texture->prepare(prepared_objects);
00431 }
00432 }
00433 }
00434 }
00435
00436 PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 PandaNode *GeomNode::
00456 combine_with(PandaNode *other) {
00457 if (is_exact_type(get_class_type()) &&
00458 other->is_exact_type(get_class_type())) {
00459
00460 GeomNode *gother = DCAST(GeomNode, other);
00461 add_geoms_from(gother);
00462 return this;
00463 }
00464
00465 return PandaNode::combine_with(other);
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 CPT(TransformState) GeomNode::
00485 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
00486 const TransformState *transform, Thread *current_thread) const {
00487 CPT(TransformState) next_transform =
00488 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
00489 current_thread);
00490
00491 const LMatrix4 &mat = next_transform->get_mat();
00492
00493 CDReader cdata(_cycler, current_thread);
00494 GeomList::const_iterator gi;
00495 CPT(GeomList) geoms = cdata->get_geoms();
00496 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00497 CPT(Geom) geom = (*gi)._geom.get_read_pointer();
00498 geom->calc_tight_bounds(min_point, max_point, found_any,
00499 geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread),
00500 !next_transform->is_identity(), mat,
00501 current_thread);
00502 }
00503
00504 return next_transform;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 bool GeomNode::
00518 is_renderable() const {
00519 return true;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 void GeomNode::
00531 add_for_draw(CullTraverser *trav, CullTraverserData &data) {
00532 trav->_geom_nodes_pcollector.add_level(1);
00533
00534 if (pgraph_cat.is_spam()) {
00535 pgraph_cat.spam()
00536 << "Found " << *this << " in state " << *data._state
00537 << " draw_mask = " << data._draw_mask << "\n";
00538 }
00539
00540
00541 Geoms geoms = get_geoms(trav->get_current_thread());
00542 int num_geoms = geoms.get_num_geoms();
00543 trav->_geoms_pcollector.add_level(num_geoms);
00544 CPT(TransformState) net_transform = data.get_net_transform(trav);
00545 CPT(TransformState) modelview_transform = data.get_modelview_transform(trav);
00546 CPT(TransformState) internal_transform = trav->get_gsg()->get_cs_transform()->compose(modelview_transform);
00547
00548 for (int i = 0; i < num_geoms; i++) {
00549 const Geom *geom = geoms.get_geom(i);
00550 if (geom->is_empty()) {
00551 continue;
00552 }
00553
00554 CPT(RenderState) state = data._state->compose(geoms.get_geom_state(i));
00555 if (state->has_cull_callback() && !state->cull_callback(trav, data)) {
00556
00557 continue;
00558 }
00559
00560
00561
00562
00563
00564
00565 if (num_geoms > 1) {
00566 if (data._view_frustum != (GeometricBoundingVolume *)NULL) {
00567
00568 CPT(BoundingVolume) geom_volume = geom->get_bounds();
00569 const GeometricBoundingVolume *geom_gbv =
00570 DCAST(GeometricBoundingVolume, geom_volume);
00571
00572 int result = data._view_frustum->contains(geom_gbv);
00573 if (result == BoundingVolume::IF_no_intersection) {
00574
00575 continue;
00576 }
00577 }
00578 if (!data._cull_planes->is_empty()) {
00579
00580 CPT(BoundingVolume) geom_volume = geom->get_bounds();
00581 const GeometricBoundingVolume *geom_gbv =
00582 DCAST(GeometricBoundingVolume, geom_volume);
00583 int result;
00584 data._cull_planes->do_cull(result, state, geom_gbv);
00585 if (result == BoundingVolume::IF_no_intersection) {
00586
00587 continue;
00588 }
00589 }
00590 }
00591
00592 CullableObject *object =
00593 new CullableObject(geom, state, net_transform,
00594 modelview_transform, internal_transform);
00595 trav->get_cull_handler()->record_object(object, trav);
00596 }
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 CollideMask GeomNode::
00611 get_legal_collide_mask() const {
00612 return CollideMask::all_on();
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 void GeomNode::
00624 add_geom(Geom *geom, const RenderState *state) {
00625 nassertv(geom != (Geom *)NULL);
00626 nassertv(geom->check_valid());
00627 nassertv(state != (RenderState *)NULL);
00628
00629 Thread *current_thread = Thread::get_current_thread();
00630 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00631 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00632
00633 cdata->modify_geoms()->push_back(GeomEntry(geom, state));
00634 }
00635 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00636
00637 mark_internal_bounds_stale();
00638 }
00639
00640
00641
00642
00643
00644
00645
00646 void GeomNode::
00647 add_geoms_from(const GeomNode *other) {
00648 Thread *current_thread = Thread::get_current_thread();
00649 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00650 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00651 CDStageReader cdata_other(other->_cycler, pipeline_stage, current_thread);
00652
00653 GeomList::const_iterator gi;
00654 CPT(GeomList) other_geoms = cdata_other->get_geoms();
00655 PT(GeomList) this_geoms = cdata->modify_geoms();
00656 for (gi = other_geoms->begin(); gi != other_geoms->end(); ++gi) {
00657 const GeomEntry &entry = (*gi);
00658 nassertv(entry._geom.get_read_pointer()->check_valid());
00659 this_geoms->push_back(entry);
00660 }
00661 }
00662 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00663
00664 mark_internal_bounds_stale();
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 void GeomNode::
00681 set_geom(int n, Geom *geom) {
00682 nassertv(geom != (Geom *)NULL);
00683 nassertv(geom->check_valid());
00684
00685 CDWriter cdata(_cycler, true);
00686 PT(GeomList) geoms = cdata->modify_geoms();
00687 nassertv(n >= 0 && n < (int)geoms->size());
00688 (*geoms)[n]._geom = geom;
00689
00690 mark_internal_bounds_stale();
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 bool GeomNode::
00702 check_valid() const {
00703 int num_geoms = get_num_geoms();
00704 for (int i = 0; i < num_geoms; i++) {
00705 const Geom *geom = get_geom(i);
00706 if (!geom->check_valid()) {
00707 return false;
00708 }
00709 }
00710
00711 return true;
00712 }
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 void GeomNode::
00729 decompose() {
00730 Thread *current_thread = Thread::get_current_thread();
00731 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00732 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00733
00734 GeomList::iterator gi;
00735 PT(GeomList) geoms = cdata->modify_geoms();
00736 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00737 GeomEntry &entry = (*gi);
00738 nassertv(entry._geom.test_ref_count_integrity());
00739 PT(Geom) geom = entry._geom.get_write_pointer();
00740 geom->decompose_in_place();
00741 }
00742 }
00743 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00744 }
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 void GeomNode::
00771 unify(int max_indices, bool preserve_order) {
00772 bool any_changed = false;
00773
00774 Thread *current_thread = Thread::get_current_thread();
00775 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00776 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00777
00778 PT(GeomList) new_geoms = new GeomList;
00779
00780
00781
00782
00783 GeomList::const_iterator gi;
00784 CPT(GeomList) old_geoms = cdata->get_geoms();
00785 for (gi = old_geoms->begin(); gi != old_geoms->end(); ++gi) {
00786 const GeomEntry &old_entry = (*gi);
00787
00788 bool unified = false;
00789
00790
00791 GeomList::reverse_iterator gj;
00792 for (gj = new_geoms->rbegin(); gj != new_geoms->rend() && !unified; ++gj) {
00793 GeomEntry &new_entry = (*gj);
00794 if (old_entry._state == new_entry._state) {
00795
00796 CPT(Geom) old_geom = old_entry._geom.get_read_pointer();
00797 PT(Geom) new_geom = new_entry._geom.get_write_pointer();
00798 if (new_geom->copy_primitives_from(old_geom)) {
00799
00800 unified = true;
00801 any_changed = true;
00802 }
00803 }
00804
00805 if (preserve_order) {
00806
00807
00808 break;
00809 }
00810 }
00811
00812 if (!unified) {
00813
00814
00815 new_geoms->push_back(old_entry);
00816 }
00817 }
00818
00819
00820 cdata->set_geoms(new_geoms);
00821
00822
00823 GeomList::iterator wgi;
00824 for (wgi = new_geoms->begin(); wgi != new_geoms->end(); ++wgi) {
00825 GeomEntry &entry = (*wgi);
00826 nassertv(entry._geom.test_ref_count_integrity());
00827 PT(Geom) geom = entry._geom.get_write_pointer();
00828 geom->unify_in_place(max_indices, preserve_order);
00829 }
00830 }
00831 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00832
00833 if (any_changed) {
00834 mark_internal_bounds_stale();
00835 }
00836 }
00837
00838
00839
00840
00841
00842
00843
00844 void GeomNode::
00845 write_geoms(ostream &out, int indent_level) const {
00846 CDReader cdata(_cycler);
00847 write(out, indent_level);
00848 GeomList::const_iterator gi;
00849 CPT(GeomList) geoms = cdata->get_geoms();
00850 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00851 const GeomEntry &entry = (*gi);
00852 indent(out, indent_level + 2)
00853 << *entry._geom.get_read_pointer() << " " << *entry._state << "\n";
00854 }
00855 }
00856
00857
00858
00859
00860
00861
00862
00863 void GeomNode::
00864 write_verbose(ostream &out, int indent_level) const {
00865 CDReader cdata(_cycler);
00866 write(out, indent_level);
00867 GeomList::const_iterator gi;
00868 CPT(GeomList) geoms = cdata->get_geoms();
00869 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00870 const GeomEntry &entry = (*gi);
00871 CPT(Geom) geom = entry._geom.get_read_pointer();
00872 indent(out, indent_level + 2)
00873 << *geom << " " << *entry._state << "\n";
00874 geom->write(out, indent_level + 4);
00875 }
00876 }
00877
00878
00879
00880
00881
00882
00883 void GeomNode::
00884 output(ostream &out) const {
00885
00886
00887
00888
00889
00890 CDReader cdata(_cycler);
00891
00892 pset<TypeHandle> attrib_types;
00893
00894 GeomList::const_iterator gi;
00895 CPT(RenderState) common = RenderState::make_empty();
00896
00897 CPT(GeomList) geoms = cdata->get_geoms();
00898 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00899 const GeomEntry &entry = (*gi);
00900 common = common->compose(entry._state);
00901 }
00902
00903 PandaNode::output(out);
00904 out << " (" << geoms->size() << " geoms";
00905
00906 if (!common->is_empty()) {
00907 out << ": " << *common;
00908 }
00909
00910 out << ")";
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924 bool GeomNode::
00925 is_geom_node() const {
00926 return true;
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936 void GeomNode::
00937 do_premunge(GraphicsStateGuardianBase *gsg,
00938 const RenderState *node_state,
00939 GeomTransformer &transformer) {
00940 Thread *current_thread = Thread::get_current_thread();
00941
00942 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00943 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00944
00945 GeomList::iterator gi;
00946 PT(GeomList) geoms = cdata->modify_geoms();
00947 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00948 GeomEntry &entry = (*gi);
00949 CPT(RenderState) geom_state = node_state->compose(entry._state);
00950 CPT(Geom) geom = entry._geom.get_read_pointer();
00951 PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread);
00952 entry._geom = transformer.premunge_geom(geom, munger);
00953 }
00954 }
00955 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00956 }
00957
00958
00959
00960
00961
00962
00963
00964 void GeomNode::
00965 r_mark_geom_bounds_stale(Thread *current_thread) {
00966 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
00967 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
00968
00969 GeomList::iterator gi;
00970 PT(GeomList) geoms = cdata->modify_geoms();
00971 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
00972 GeomEntry &entry = (*gi);
00973 entry._geom.get_read_pointer()->mark_bounds_stale();
00974 }
00975 }
00976 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
00977 mark_internal_bounds_stale();
00978
00979 PandaNode::r_mark_geom_bounds_stale(current_thread);
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 void GeomNode::
00991 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00992 int &internal_vertices,
00993 int pipeline_stage,
00994 Thread *current_thread) const {
00995 int num_vertices = 0;
00996
00997 CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
00998
00999 pvector<const BoundingVolume *> child_volumes;
01000 pvector<CPT(BoundingVolume) > child_volumes_ref;
01001 bool all_box = true;
01002
01003 GeomList::const_iterator gi;
01004 CPT(GeomList) geoms = cdata->get_geoms();
01005 child_volumes.reserve(geoms->size());
01006 child_volumes_ref.reserve(geoms->size());
01007
01008 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01009 const GeomEntry &entry = (*gi);
01010 CPT(Geom) geom = entry._geom.get_read_pointer();
01011 CPT(BoundingVolume) volume = geom->get_bounds();
01012
01013 if (!volume->is_empty()) {
01014 child_volumes.push_back(volume);
01015 child_volumes_ref.push_back(volume);
01016 if (!volume->is_exact_type(BoundingBox::get_class_type())) {
01017 all_box = false;
01018 }
01019 }
01020 num_vertices += geom->get_nested_vertices();
01021 }
01022
01023 PT(GeometricBoundingVolume) gbv;
01024
01025 BoundingVolume::BoundsType btype = get_bounds_type();
01026 if (btype == BoundingVolume::BT_default) {
01027 btype = bounds_type;
01028 }
01029
01030 if (btype == BoundingVolume::BT_box ||
01031 (btype != BoundingVolume::BT_sphere && all_box)) {
01032
01033
01034 gbv = new BoundingBox;
01035 } else {
01036
01037 gbv = new BoundingSphere;
01038 }
01039
01040 if (child_volumes.size() > 0) {
01041 const BoundingVolume **child_begin = &child_volumes[0];
01042 const BoundingVolume **child_end = child_begin + child_volumes.size();
01043 ((BoundingVolume *)gbv)->around(child_begin, child_end);
01044 }
01045
01046 internal_bounds = gbv;
01047 internal_vertices = num_vertices;
01048 }
01049
01050
01051
01052
01053
01054
01055
01056 void GeomNode::
01057 register_with_read_factory() {
01058 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
01059 }
01060
01061
01062
01063
01064
01065
01066
01067 void GeomNode::
01068 write_datagram(BamWriter *manager, Datagram &dg) {
01069 PandaNode::write_datagram(manager, dg);
01070 manager->write_cdata(dg, _cycler);
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080 void GeomNode::
01081 finalize(BamReader *manager) {
01082 if (manager->get_file_minor_ver() < 14) {
01083
01084
01085
01086
01087
01088
01089
01090
01091 CPT(InternalName) color = InternalName::get_color();
01092 CPT(RenderAttrib) vertex_color = ColorAttrib::make_vertex();
01093
01094 Thread *current_thread = Thread::get_current_thread();
01095 OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
01096 CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
01097
01098 GeomList::iterator gi;
01099 PT(GeomList) geoms = cdata->modify_geoms();
01100 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01101 GeomEntry &entry = (*gi);
01102 CPT(Geom) geom = entry._geom.get_read_pointer();
01103
01104
01105
01106
01107 CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
01108 CPT(GeomVertexFormat) vformat = vdata->get_format();
01109 for (int i = 0; i < vformat->get_num_arrays(); ++i) {
01110 const GeomVertexArrayFormat *varray = vformat->get_array(i);
01111 manager->finalize_now((GeomVertexArrayFormat *)varray);
01112 }
01113
01114 if (vdata->has_column(color) &&
01115 !entry._state->has_attrib(ColorAttrib::get_class_slot())) {
01116
01117
01118 PT(BamAuxData) aux_data = new BamAuxData;
01119 aux_data->_hold_state = entry._state;
01120 manager->set_aux_data((RenderState *)entry._state.p(), "hold_state", aux_data);
01121
01122 entry._state = entry._state->add_attrib(vertex_color, -1);
01123 }
01124 }
01125 }
01126 CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
01127 }
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138 TypedWritable *GeomNode::
01139 make_from_bam(const FactoryParams ¶ms) {
01140 GeomNode *node = new GeomNode("");
01141 DatagramIterator scan;
01142 BamReader *manager;
01143
01144 parse_params(params, scan, manager);
01145 node->fillin(scan, manager);
01146
01147 if (manager->get_file_minor_ver() < 14) {
01148 manager->register_finalize(node);
01149 }
01150
01151 return node;
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161 void GeomNode::
01162 fillin(DatagramIterator &scan, BamReader *manager) {
01163 PandaNode::fillin(scan, manager);
01164 manager->read_cdata(scan, _cycler);
01165 }
01166
01167
01168
01169
01170
01171
01172 GeomNode::CData::
01173 CData(const GeomNode::CData ©) :
01174 _geoms(copy._geoms)
01175 {
01176 }
01177
01178
01179
01180
01181
01182
01183 CycleData *GeomNode::CData::
01184 make_copy() const {
01185 return new CData(*this);
01186 }
01187
01188
01189
01190
01191
01192
01193
01194 void GeomNode::CData::
01195 write_datagram(BamWriter *manager, Datagram &dg) const {
01196 CPT(GeomList) geoms = _geoms.get_read_pointer();
01197 int num_geoms = geoms->size();
01198 nassertv(num_geoms == (int)(PN_uint16)num_geoms);
01199 dg.add_uint16(num_geoms);
01200
01201 GeomList::const_iterator gi;
01202 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01203 const GeomEntry &entry = (*gi);
01204 manager->write_pointer(dg, entry._geom.get_read_pointer());
01205 manager->write_pointer(dg, entry._state);
01206 }
01207 }
01208
01209
01210
01211
01212
01213
01214
01215
01216 int GeomNode::CData::
01217 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01218 int pi = CycleData::complete_pointers(p_list, manager);
01219
01220
01221 GeomList::iterator gi;
01222 PT(GeomList) geoms = _geoms.get_write_pointer();
01223 for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
01224 GeomEntry &entry = (*gi);
01225 entry._geom = DCAST(Geom, p_list[pi++]);
01226 entry._state = DCAST(RenderState, p_list[pi++]);
01227 }
01228
01229 return pi;
01230 }
01231
01232
01233
01234
01235
01236
01237
01238
01239 void GeomNode::CData::
01240 fillin(DatagramIterator &scan, BamReader *manager) {
01241 int num_geoms = scan.get_uint16();
01242
01243 PT(GeomList) geoms = new GeomList;
01244 geoms->reserve(num_geoms);
01245 for (int i = 0; i < num_geoms; i++) {
01246 manager->read_pointer(scan);
01247 manager->read_pointer(scan);
01248 geoms->push_back(GeomEntry(NULL, NULL));
01249 }
01250 _geoms = geoms;
01251 }