00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "geom.h"
00016 #include "geomPoints.h"
00017 #include "geomVertexReader.h"
00018 #include "geomVertexRewriter.h"
00019 #include "graphicsStateGuardianBase.h"
00020 #include "preparedGraphicsObjects.h"
00021 #include "pStatTimer.h"
00022 #include "bamReader.h"
00023 #include "bamWriter.h"
00024 #include "boundingSphere.h"
00025 #include "boundingBox.h"
00026 #include "lightMutexHolder.h"
00027 #include "config_mathutil.h"
00028
00029 UpdateSeq Geom::_next_modified;
00030 PStatCollector Geom::_draw_primitive_setup_pcollector("Draw:Primitive:Setup");
00031
00032 TypeHandle Geom::_type_handle;
00033 TypeHandle Geom::CDataCache::_type_handle;
00034 TypeHandle Geom::CacheEntry::_type_handle;
00035 TypeHandle Geom::CData::_type_handle;
00036 TypeHandle GeomPipelineReader::_type_handle;
00037
00038
00039
00040
00041
00042
00043 PT(CopyOnWriteObject) Geom::
00044 make_cow_copy() {
00045 return make_copy();
00046 }
00047
00048
00049
00050
00051
00052
00053 Geom::
00054 Geom(const GeomVertexData *data) {
00055
00056 OPEN_ITERATE_ALL_STAGES(_cycler) {
00057 CDStageWriter cdata(_cycler, pipeline_stage);
00058 cdata->_data = (GeomVertexData *)data;
00059 }
00060 CLOSE_ITERATE_ALL_STAGES(_cycler);
00061 }
00062
00063
00064
00065
00066
00067
00068 Geom::
00069 Geom(const Geom ©) :
00070 CopyOnWriteObject(copy),
00071 _cycler(copy._cycler)
00072 {
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 void Geom::
00084 operator = (const Geom ©) {
00085 CopyOnWriteObject::operator = (copy);
00086
00087 clear_cache();
00088
00089 _cycler = copy._cycler;
00090
00091 OPEN_ITERATE_ALL_STAGES(_cycler) {
00092 CDStageWriter cdata(_cycler, pipeline_stage);
00093 mark_internal_bounds_stale(cdata);
00094 }
00095 CLOSE_ITERATE_ALL_STAGES(_cycler);
00096 }
00097
00098
00099
00100
00101
00102
00103 Geom::
00104 ~Geom() {
00105 clear_cache();
00106 release_all();
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 Geom *Geom::
00118 make_copy() const {
00119 return new Geom(*this);
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 void Geom::
00134 set_usage_hint(Geom::UsageHint usage_hint) {
00135 Thread *current_thread = Thread::get_current_thread();
00136 CDWriter cdata(_cycler, true, current_thread);
00137 cdata->_usage_hint = usage_hint;
00138
00139 Primitives::iterator pi;
00140 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00141 PT(GeomPrimitive) prim = (*pi).get_write_pointer();
00142 prim->set_usage_hint(usage_hint);
00143 }
00144
00145 clear_cache_stage(current_thread);
00146 cdata->_modified = Geom::get_next_modified();
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 PT(GeomVertexData) Geom::
00161 modify_vertex_data() {
00162 Thread *current_thread = Thread::get_current_thread();
00163
00164
00165
00166 CDWriter cdata(_cycler, true, current_thread);
00167 clear_cache_stage(current_thread);
00168 mark_internal_bounds_stale(cdata);
00169 return cdata->_data.get_write_pointer();
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 void Geom::
00183 set_vertex_data(const GeomVertexData *data) {
00184 Thread *current_thread = Thread::get_current_thread();
00185 nassertv(check_will_be_valid(data));
00186 CDWriter cdata(_cycler, true, current_thread);
00187 cdata->_data = (GeomVertexData *)data;
00188 clear_cache_stage(current_thread);
00189 mark_internal_bounds_stale(cdata);
00190 reset_geom_rendering(cdata);
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 void Geom::
00209 offset_vertices(const GeomVertexData *data, int offset) {
00210 Thread *current_thread = Thread::get_current_thread();
00211 CDWriter cdata(_cycler, true, current_thread);
00212 cdata->_data = (GeomVertexData *)data;
00213
00214 #ifndef NDEBUG
00215 bool all_is_valid = true;
00216 #endif
00217 Primitives::iterator pi;
00218 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00219 PT(GeomPrimitive) prim = (*pi).get_write_pointer();
00220 prim->offset_vertices(offset);
00221
00222 #ifndef NDEBUG
00223 if (!prim->check_valid(data)) {
00224 gobj_cat.warning()
00225 << *prim << " is invalid for " << *data << ":\n";
00226 prim->write(gobj_cat.warning(false), 4);
00227
00228 all_is_valid = false;
00229 }
00230 #endif
00231 }
00232
00233 cdata->_modified = Geom::get_next_modified();
00234 clear_cache_stage(current_thread);
00235 nassertv(all_is_valid);
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 int Geom::
00252 make_nonindexed(bool composite_only) {
00253 Thread *current_thread = Thread::get_current_thread();
00254 int num_changed = 0;
00255
00256 CDWriter cdata(_cycler, true, current_thread);
00257 CPT(GeomVertexData) orig_data = cdata->_data.get_read_pointer();
00258 PT(GeomVertexData) new_data = new GeomVertexData(*orig_data);
00259 new_data->clear_rows();
00260
00261 #ifndef NDEBUG
00262 bool all_is_valid = true;
00263 #endif
00264 Primitives::iterator pi;
00265 Primitives new_prims;
00266 new_prims.reserve(cdata->_primitives.size());
00267 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00268 PT(GeomPrimitive) primitive = (*pi).get_read_pointer()->make_copy();
00269 new_prims.push_back(primitive.p());
00270
00271
00272
00273
00274
00275 if (primitive->is_indexed() &&
00276 (primitive->is_composite() ||
00277 primitive->is_exact_type(GeomPoints::get_class_type()) ||
00278 !composite_only)) {
00279 primitive->make_nonindexed(new_data, orig_data);
00280 ++num_changed;
00281 } else {
00282
00283
00284 primitive->pack_vertices(new_data, orig_data);
00285 }
00286
00287 #ifndef NDEBUG
00288 if (!primitive->check_valid(new_data)) {
00289 all_is_valid = false;
00290 }
00291 #endif
00292 }
00293
00294 nassertr(all_is_valid, 0);
00295
00296 if (num_changed != 0) {
00297
00298
00299
00300 cdata->_data = new_data;
00301 cdata->_primitives.swap(new_prims);
00302 cdata->_modified = Geom::get_next_modified();
00303 clear_cache_stage(current_thread);
00304 }
00305
00306 return num_changed;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 void Geom::
00320 set_primitive(int i, const GeomPrimitive *primitive) {
00321 Thread *current_thread = Thread::get_current_thread();
00322 CDWriter cdata(_cycler, true, current_thread);
00323 nassertv(i >= 0 && i < (int)cdata->_primitives.size());
00324 nassertv(primitive->check_valid(cdata->_data.get_read_pointer()));
00325
00326
00327
00328 nassertv(cdata->_primitive_type == PT_none ||
00329 cdata->_primitive_type == primitive->get_primitive_type());
00330
00331
00332 CPT(GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
00333 nassertv_always(compat != (GeomPrimitive *)NULL);
00334
00335 cdata->_primitives[i] = (GeomPrimitive *)compat.p();
00336 PrimitiveType new_primitive_type = compat->get_primitive_type();
00337 if (new_primitive_type != cdata->_primitive_type) {
00338 cdata->_primitive_type = new_primitive_type;
00339 }
00340 ShadeModel new_shade_model = compat->get_shade_model();
00341 if (new_shade_model != cdata->_shade_model &&
00342 new_shade_model != SM_uniform) {
00343 cdata->_shade_model = new_shade_model;
00344 }
00345
00346 reset_geom_rendering(cdata);
00347 cdata->_got_usage_hint = false;
00348 cdata->_modified = Geom::get_next_modified();
00349 clear_cache_stage(current_thread);
00350 mark_internal_bounds_stale(cdata);
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 void Geom::
00366 add_primitive(const GeomPrimitive *primitive) {
00367 Thread *current_thread = Thread::get_current_thread();
00368 CDWriter cdata(_cycler, true, current_thread);
00369
00370 nassertv(primitive->check_valid(cdata->_data.get_read_pointer()));
00371
00372
00373
00374 nassertv(cdata->_primitive_type == PT_none ||
00375 cdata->_primitive_type == primitive->get_primitive_type());
00376
00377
00378 CPT(GeomPrimitive) compat = primitive->match_shade_model(cdata->_shade_model);
00379 nassertv_always(compat != (GeomPrimitive *)NULL);
00380
00381 cdata->_primitives.push_back((GeomPrimitive *)compat.p());
00382 PrimitiveType new_primitive_type = compat->get_primitive_type();
00383 if (new_primitive_type != cdata->_primitive_type) {
00384 cdata->_primitive_type = new_primitive_type;
00385 }
00386 ShadeModel new_shade_model = compat->get_shade_model();
00387 if (new_shade_model != cdata->_shade_model &&
00388 new_shade_model != SM_uniform) {
00389 cdata->_shade_model = new_shade_model;
00390 }
00391
00392 reset_geom_rendering(cdata);
00393 cdata->_got_usage_hint = false;
00394 cdata->_modified = Geom::get_next_modified();
00395 clear_cache_stage(current_thread);
00396 mark_internal_bounds_stale(cdata);
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 void Geom::
00409 remove_primitive(int i) {
00410 Thread *current_thread = Thread::get_current_thread();
00411 CDWriter cdata(_cycler, true, current_thread);
00412 nassertv(i >= 0 && i < (int)cdata->_primitives.size());
00413 cdata->_primitives.erase(cdata->_primitives.begin() + i);
00414 if (cdata->_primitives.empty()) {
00415 cdata->_primitive_type = PT_none;
00416 cdata->_shade_model = SM_uniform;
00417 }
00418 reset_geom_rendering(cdata);
00419 cdata->_got_usage_hint = false;
00420 cdata->_modified = Geom::get_next_modified();
00421 clear_cache_stage(current_thread);
00422 mark_internal_bounds_stale(cdata);
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 void Geom::
00438 clear_primitives() {
00439 Thread *current_thread = Thread::get_current_thread();
00440 CDWriter cdata(_cycler, true, current_thread);
00441 cdata->_primitives.clear();
00442 cdata->_primitive_type = PT_none;
00443 cdata->_shade_model = SM_uniform;
00444 reset_geom_rendering(cdata);
00445 clear_cache_stage(current_thread);
00446 mark_internal_bounds_stale(cdata);
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 void Geom::
00461 decompose_in_place() {
00462 Thread *current_thread = Thread::get_current_thread();
00463 CDWriter cdata(_cycler, true, current_thread);
00464
00465 #ifndef NDEBUG
00466 bool all_is_valid = true;
00467 #endif
00468 Primitives::iterator pi;
00469 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00470 CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->decompose();
00471 (*pi) = (GeomPrimitive *)new_prim.p();
00472
00473 #ifndef NDEBUG
00474 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00475 all_is_valid = false;
00476 }
00477 #endif
00478 }
00479
00480 cdata->_modified = Geom::get_next_modified();
00481 reset_geom_rendering(cdata);
00482 clear_cache_stage(current_thread);
00483
00484 nassertv(all_is_valid);
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 void Geom::
00499 doubleside_in_place() {
00500 Thread *current_thread = Thread::get_current_thread();
00501 CDWriter cdata(_cycler, true, current_thread);
00502
00503 #ifndef NDEBUG
00504 bool all_is_valid = true;
00505 #endif
00506 Primitives::iterator pi;
00507 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00508 CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->doubleside();
00509 (*pi) = (GeomPrimitive *)new_prim.p();
00510
00511 #ifndef NDEBUG
00512 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00513 all_is_valid = false;
00514 }
00515 #endif
00516 }
00517
00518 cdata->_modified = Geom::get_next_modified();
00519 reset_geom_rendering(cdata);
00520 clear_cache_stage(current_thread);
00521
00522 nassertv(all_is_valid);
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 void Geom::
00537 reverse_in_place() {
00538 Thread *current_thread = Thread::get_current_thread();
00539 CDWriter cdata(_cycler, true, current_thread);
00540
00541 #ifndef NDEBUG
00542 bool all_is_valid = true;
00543 #endif
00544 Primitives::iterator pi;
00545 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00546 CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->reverse();
00547 (*pi) = (GeomPrimitive *)new_prim.p();
00548
00549 #ifndef NDEBUG
00550 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00551 all_is_valid = false;
00552 }
00553 #endif
00554 }
00555
00556 cdata->_modified = Geom::get_next_modified();
00557 reset_geom_rendering(cdata);
00558 clear_cache_stage(current_thread);
00559
00560 nassertv(all_is_valid);
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 void Geom::
00575 rotate_in_place() {
00576 Thread *current_thread = Thread::get_current_thread();
00577 CDWriter cdata(_cycler, true, current_thread);
00578
00579 #ifndef NDEBUG
00580 bool all_is_valid = true;
00581 #endif
00582 Primitives::iterator pi;
00583 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00584 CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->rotate();
00585 (*pi) = (GeomPrimitive *)new_prim.p();
00586
00587 #ifndef NDEBUG
00588 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00589 all_is_valid = false;
00590 }
00591 #endif
00592 }
00593
00594 cdata->_modified = Geom::get_next_modified();
00595 clear_cache_stage(current_thread);
00596
00597 nassertv(all_is_valid);
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 void Geom::
00621 unify_in_place(int max_indices, bool preserve_order) {
00622 if (gobj_cat.is_debug()) {
00623 gobj_cat.debug()
00624 << "unify_in_place(" << max_indices << ", " << preserve_order
00625 << "): " << *this << "\n";
00626 }
00627
00628 Thread *current_thread = Thread::get_current_thread();
00629 if (get_num_primitives() <= 1) {
00630
00631
00632 return;
00633 }
00634
00635 CDWriter cdata(_cycler, true, current_thread);
00636
00637 typedef pmap<TypeHandle, PT(GeomPrimitive) > NewPrims;
00638
00639 NewPrims new_prims;
00640
00641 bool keep_different_types = preserve_triangle_strips && !preserve_order;
00642
00643 Primitives::const_iterator pi;
00644 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00645 CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
00646 NewPrims::iterator npi = new_prims.find(primitive->get_type());
00647 if (npi == new_prims.end()) {
00648
00649 if (!keep_different_types && !new_prims.empty()) {
00650
00651
00652
00653
00654
00655
00656 primitive = primitive->decompose();
00657 npi = new_prims.find(primitive->get_type());
00658 if (npi == new_prims.end()) {
00659
00660
00661 nassertv(new_prims.size() == 1);
00662 npi = new_prims.begin();
00663 CPT(GeomPrimitive) np = (*npi).second->decompose();
00664 new_prims.clear();
00665 new_prims.insert(NewPrims::value_type(np->get_type(), np->make_copy()));
00666 npi = new_prims.find(primitive->get_type());
00667 }
00668 }
00669 }
00670
00671 if (npi == new_prims.end()) {
00672
00673 new_prims.insert(NewPrims::value_type(primitive->get_type(), primitive->make_copy()));
00674
00675 } else {
00676
00677
00678 combine_primitives((*npi).second, primitive, current_thread);
00679 }
00680 }
00681
00682
00683 #ifndef NDEBUG
00684 if (!keep_different_types && new_prims.size() > 1) {
00685
00686
00687
00688 nassertv(false);
00689 }
00690 #endif
00691
00692
00693
00694 cdata->_primitives.clear();
00695 NewPrims::iterator npi;
00696 for (npi = new_prims.begin(); npi != new_prims.end(); ++npi) {
00697 GeomPrimitive *prim = (*npi).second;
00698
00699 nassertv(prim->check_valid(cdata->_data.get_read_pointer()));
00700
00701
00702
00703 prim->set_shade_model(cdata->_shade_model);
00704
00705
00706 if (prim->get_num_vertices() > max_indices) {
00707
00708
00709 int i = 0;
00710
00711 while (i < prim->get_num_primitives()) {
00712 PT(GeomPrimitive) smaller = prim->make_copy();
00713 smaller->clear_vertices();
00714 while (i < prim->get_num_primitives() &&
00715 smaller->get_num_vertices() + prim->get_primitive_num_vertices(i) < max_indices) {
00716 int start = prim->get_primitive_start(i);
00717 int end = prim->get_primitive_end(i);
00718 for (int n = start; n < end; ++n) {
00719 smaller->add_vertex(prim->get_vertex(n));
00720 }
00721 smaller->close_primitive();
00722
00723 ++i;
00724 }
00725
00726 cdata->_primitives.push_back(smaller.p());
00727 }
00728
00729 } else {
00730
00731 cdata->_primitives.push_back(prim);
00732 }
00733 }
00734
00735 cdata->_modified = Geom::get_next_modified();
00736 clear_cache_stage(current_thread);
00737 reset_geom_rendering(cdata);
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 void Geom::
00752 make_points_in_place() {
00753 Thread *current_thread = Thread::get_current_thread();
00754 CDWriter cdata(_cycler, true, current_thread);
00755
00756 #ifndef NDEBUG
00757 bool all_is_valid = true;
00758 #endif
00759 Primitives::iterator pi;
00760 for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
00761 CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer()->make_points();
00762 (*pi) = (GeomPrimitive *)new_prim.p();
00763
00764 #ifndef NDEBUG
00765 if (!new_prim->check_valid(cdata->_data.get_read_pointer())) {
00766 all_is_valid = false;
00767 }
00768 #endif
00769 }
00770
00771 cdata->_modified = Geom::get_next_modified();
00772 reset_geom_rendering(cdata);
00773 clear_cache_stage(current_thread);
00774
00775 nassertv(all_is_valid);
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 bool Geom::
00794 copy_primitives_from(const Geom *other) {
00795 if (get_primitive_type() != PT_none &&
00796 other->get_primitive_type() != get_primitive_type()) {
00797 return false;
00798 }
00799 if (get_vertex_data() != other->get_vertex_data()) {
00800 return false;
00801 }
00802 if (get_type() != other->get_type()) {
00803 return false;
00804 }
00805
00806 ShadeModel this_shade_model = get_shade_model();
00807 ShadeModel other_shade_model = other->get_shade_model();
00808 if (this_shade_model != SM_uniform && other_shade_model != SM_uniform &&
00809 this_shade_model != other_shade_model) {
00810 if ((this_shade_model == SM_flat_first_vertex && other_shade_model == SM_flat_last_vertex) ||
00811 (this_shade_model == SM_flat_last_vertex && other_shade_model == SM_flat_first_vertex)) {
00812
00813
00814 } else {
00815
00816 return false;
00817 }
00818 }
00819
00820 int num_primitives = other->get_num_primitives();
00821 for (int i = 0; i < num_primitives; i++) {
00822 add_primitive(other->get_primitive(i));
00823 }
00824
00825 return true;
00826 }
00827
00828
00829
00830
00831
00832
00833
00834 int Geom::
00835 get_num_bytes() const {
00836 CDReader cdata(_cycler);
00837
00838 int num_bytes = sizeof(Geom);
00839 Primitives::const_iterator pi;
00840 for (pi = cdata->_primitives.begin();
00841 pi != cdata->_primitives.end();
00842 ++pi) {
00843 num_bytes += (*pi).get_read_pointer()->get_num_bytes();
00844 }
00845
00846 return num_bytes;
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860 bool Geom::
00861 request_resident() const {
00862 CDReader cdata(_cycler);
00863
00864 bool resident = true;
00865
00866 Primitives::const_iterator pi;
00867 for (pi = cdata->_primitives.begin();
00868 pi != cdata->_primitives.end();
00869 ++pi) {
00870 if (!(*pi).get_read_pointer()->request_resident()) {
00871 resident = false;
00872 }
00873 }
00874
00875 return resident;
00876 }
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 void Geom::
00892 transform_vertices(const LMatrix4 &mat) {
00893 PT(GeomVertexData) new_data = modify_vertex_data();
00894 CPT(GeomVertexFormat) format = new_data->get_format();
00895
00896 int ci;
00897 for (ci = 0; ci < format->get_num_points(); ci++) {
00898 GeomVertexRewriter data(new_data, format->get_point(ci));
00899
00900 while (!data.is_at_end()) {
00901 const LPoint3 &point = data.get_data3();
00902 data.set_data3(point * mat);
00903 }
00904 }
00905 for (ci = 0; ci < format->get_num_vectors(); ci++) {
00906 GeomVertexRewriter data(new_data, format->get_vector(ci));
00907
00908 while (!data.is_at_end()) {
00909 const LVector3 &vector = data.get_data3();
00910 data.set_data3(normalize(vector * mat));
00911 }
00912 }
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 bool Geom::
00924 check_valid() const {
00925 Thread *current_thread = Thread::get_current_thread();
00926 GeomPipelineReader geom_reader(this, current_thread);
00927 GeomVertexDataPipelineReader data_reader(geom_reader.get_vertex_data(), current_thread);
00928 data_reader.check_array_readers();
00929 return geom_reader.check_valid(&data_reader);
00930 }
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 bool Geom::
00941 check_valid(const GeomVertexData *vertex_data) const {
00942 Thread *current_thread = Thread::get_current_thread();
00943 GeomPipelineReader geom_reader(this, current_thread);
00944 GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
00945 data_reader.check_array_readers();
00946 return geom_reader.check_valid(&data_reader);
00947 }
00948
00949
00950
00951
00952
00953
00954 CPT(BoundingVolume) Geom::
00955 get_bounds(Thread *current_thread) const {
00956 CDLockedReader cdata(_cycler, current_thread);
00957 if (cdata->_user_bounds != (BoundingVolume *)NULL) {
00958 return cdata->_user_bounds;
00959 }
00960
00961 if (cdata->_internal_bounds_stale) {
00962 CDWriter cdataw(((Geom *)this)->_cycler, cdata, false);
00963 compute_internal_bounds(cdataw, current_thread);
00964 return cdataw->_internal_bounds;
00965 }
00966 return cdata->_internal_bounds;
00967 }
00968
00969
00970
00971
00972
00973
00974
00975 int Geom::
00976 get_nested_vertices(Thread *current_thread) const {
00977 CDLockedReader cdata(_cycler, current_thread);
00978 if (cdata->_internal_bounds_stale) {
00979 CDWriter cdataw(((Geom *)this)->_cycler, cdata, false);
00980 compute_internal_bounds(cdataw, current_thread);
00981 return cdataw->_nested_vertices;
00982 }
00983 return cdata->_nested_vertices;
00984 }
00985
00986
00987
00988
00989
00990
00991 void Geom::
00992 output(ostream &out) const {
00993 CDReader cdata(_cycler);
00994
00995
00996 int num_faces = 0;
00997 pset<TypeHandle> types;
00998 Primitives::const_iterator pi;
00999 for (pi = cdata->_primitives.begin();
01000 pi != cdata->_primitives.end();
01001 ++pi) {
01002 CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
01003 num_faces += prim->get_num_faces();
01004 types.insert(prim->get_type());
01005 }
01006
01007 out << get_type() << " [";
01008 pset<TypeHandle>::iterator ti;
01009 for (ti = types.begin(); ti != types.end(); ++ti) {
01010 out << " " << (*ti);
01011 }
01012 out << " ], " << num_faces << " faces";
01013 }
01014
01015
01016
01017
01018
01019
01020 void Geom::
01021 write(ostream &out, int indent_level) const {
01022 CDReader cdata(_cycler);
01023
01024
01025 Primitives::const_iterator pi;
01026 for (pi = cdata->_primitives.begin();
01027 pi != cdata->_primitives.end();
01028 ++pi) {
01029 (*pi).get_read_pointer()->write(out, indent_level);
01030 }
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 void Geom::
01045 clear_cache() {
01046 LightMutexHolder holder(_cache_lock);
01047 for (Cache::iterator ci = _cache.begin();
01048 ci != _cache.end();
01049 ++ci) {
01050 CacheEntry *entry = (*ci).second;
01051 entry->erase();
01052 }
01053 _cache.clear();
01054 }
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 void Geom::
01068 clear_cache_stage(Thread *current_thread) {
01069 LightMutexHolder holder(_cache_lock);
01070 for (Cache::iterator ci = _cache.begin();
01071 ci != _cache.end();
01072 ++ci) {
01073 CacheEntry *entry = (*ci).second;
01074 CDCacheWriter cdata(entry->_cycler, current_thread);
01075 cdata->set_result(NULL, NULL);
01076 }
01077 }
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 void Geom::
01092 prepare(PreparedGraphicsObjects *prepared_objects) {
01093 prepared_objects->enqueue_geom(this);
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103 bool Geom::
01104 is_prepared(PreparedGraphicsObjects *prepared_objects) const {
01105 Contexts::const_iterator ci;
01106 ci = _contexts.find(prepared_objects);
01107 if (ci != _contexts.end()) {
01108 return true;
01109 }
01110 return prepared_objects->is_geom_queued(this);
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120 bool Geom::
01121 release(PreparedGraphicsObjects *prepared_objects) {
01122 Contexts::iterator ci;
01123 ci = _contexts.find(prepared_objects);
01124 if (ci != _contexts.end()) {
01125 GeomContext *gc = (*ci).second;
01126 prepared_objects->release_geom(gc);
01127 return true;
01128 }
01129
01130
01131 return prepared_objects->dequeue_geom(this);
01132 }
01133
01134
01135
01136
01137
01138
01139
01140
01141 int Geom::
01142 release_all() {
01143
01144
01145
01146
01147 Contexts temp = _contexts;
01148 int num_freed = (int)_contexts.size();
01149
01150 Contexts::const_iterator ci;
01151 for (ci = temp.begin(); ci != temp.end(); ++ci) {
01152 PreparedGraphicsObjects *prepared_objects = (*ci).first;
01153 GeomContext *gc = (*ci).second;
01154 prepared_objects->release_geom(gc);
01155 }
01156
01157
01158
01159 nassertr(_contexts.empty(), num_freed);
01160
01161 return num_freed;
01162 }
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180 GeomContext *Geom::
01181 prepare_now(PreparedGraphicsObjects *prepared_objects,
01182 GraphicsStateGuardianBase *gsg) {
01183 Contexts::const_iterator ci;
01184 ci = _contexts.find(prepared_objects);
01185 if (ci != _contexts.end()) {
01186 return (*ci).second;
01187 }
01188
01189 GeomContext *gc = prepared_objects->prepare_geom_now(this, gsg);
01190 if (gc != (GeomContext *)NULL) {
01191 _contexts[prepared_objects] = gc;
01192 }
01193 return gc;
01194 }
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 bool Geom::
01210 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
01211 const GeomVertexData *vertex_data, bool force,
01212 Thread *current_thread) const {
01213 GeomPipelineReader geom_reader(this, current_thread);
01214 geom_reader.check_usage_hint();
01215
01216 GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
01217 data_reader.check_array_readers();
01218
01219 return geom_reader.draw(gsg, munger, &data_reader, force);
01220 }
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235 UpdateSeq Geom::
01236 get_next_modified() {
01237 ++_next_modified;
01238 return _next_modified;
01239 }
01240
01241
01242
01243
01244
01245
01246
01247 void Geom::
01248 compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
01249 int num_vertices = 0;
01250
01251
01252 CPT(GeomVertexData) vertex_data = cdata->_data.get_read_pointer();
01253 vertex_data = vertex_data->animate_vertices(true, current_thread);
01254
01255
01256
01257 LPoint3 min, max;
01258 bool found_any = false;
01259 do_calc_tight_bounds(min, max, found_any, vertex_data,
01260 false, LMatrix4::ident_mat(),
01261 InternalName::get_vertex(),
01262 cdata, current_thread);
01263
01264 BoundingVolume::BoundsType btype = cdata->_bounds_type;
01265 if (btype == BoundingVolume::BT_default) {
01266 btype = bounds_type;
01267 }
01268
01269 if (found_any) {
01270
01271 if (btype == BoundingVolume::BT_sphere) {
01272
01273 BoundingBox box(min, max);
01274 box.local_object();
01275
01276 PT(BoundingSphere) sphere = new BoundingSphere;
01277 sphere->extend_by(&box);
01278 cdata->_internal_bounds = sphere;
01279
01280 } else {
01281
01282 cdata->_internal_bounds = new BoundingBox(min, max);
01283 }
01284
01285 Primitives::const_iterator pi;
01286 for (pi = cdata->_primitives.begin();
01287 pi != cdata->_primitives.end();
01288 ++pi) {
01289 CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
01290 num_vertices += prim->get_num_vertices();
01291 }
01292
01293 } else {
01294
01295 if (btype == BoundingVolume::BT_sphere) {
01296 cdata->_internal_bounds = new BoundingSphere;
01297 } else {
01298 cdata->_internal_bounds = new BoundingBox;
01299 }
01300 }
01301
01302 cdata->_nested_vertices = num_vertices;
01303 cdata->_internal_bounds_stale = false;
01304 }
01305
01306
01307
01308
01309
01310
01311 void Geom::
01312 do_calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
01313 bool &found_any,
01314 const GeomVertexData *vertex_data,
01315 bool got_mat, const LMatrix4 &mat,
01316 const InternalName *column_name,
01317 const CData *cdata, Thread *current_thread) const {
01318 Primitives::const_iterator pi;
01319 for (pi = cdata->_primitives.begin();
01320 pi != cdata->_primitives.end();
01321 ++pi) {
01322 CPT(GeomPrimitive) prim = (*pi).get_read_pointer();
01323 prim->calc_tight_bounds(min_point, max_point, found_any, vertex_data,
01324 got_mat, mat, column_name, current_thread);
01325 }
01326 }
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337 void Geom::
01338 clear_prepared(PreparedGraphicsObjects *prepared_objects) {
01339 Contexts::iterator ci;
01340 ci = _contexts.find(prepared_objects);
01341 if (ci != _contexts.end()) {
01342 _contexts.erase(ci);
01343 } else {
01344
01345
01346 nassertv(false);
01347 }
01348 }
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 bool Geom::
01361 check_will_be_valid(const GeomVertexData *vertex_data) const {
01362 CDReader cdata(_cycler);
01363
01364 Primitives::const_iterator pi;
01365 for (pi = cdata->_primitives.begin();
01366 pi != cdata->_primitives.end();
01367 ++pi) {
01368 if (!(*pi).get_read_pointer()->check_valid(vertex_data)) {
01369 return false;
01370 }
01371 }
01372
01373 return true;
01374 }
01375
01376
01377
01378
01379
01380
01381 void Geom::
01382 reset_usage_hint(Geom::CData *cdata) {
01383 cdata->_usage_hint = UH_unspecified;
01384 Primitives::const_iterator pi;
01385 for (pi = cdata->_primitives.begin();
01386 pi != cdata->_primitives.end();
01387 ++pi) {
01388 cdata->_usage_hint = min(cdata->_usage_hint,
01389 (*pi).get_read_pointer()->get_usage_hint());
01390 }
01391 cdata->_got_usage_hint = true;
01392 }
01393
01394
01395
01396
01397
01398
01399 void Geom::
01400 reset_geom_rendering(Geom::CData *cdata) {
01401 cdata->_geom_rendering = 0;
01402 Primitives::const_iterator pi;
01403 for (pi = cdata->_primitives.begin();
01404 pi != cdata->_primitives.end();
01405 ++pi) {
01406 cdata->_geom_rendering |= (*pi).get_read_pointer()->get_geom_rendering();
01407 }
01408
01409 if ((cdata->_geom_rendering & GR_point) != 0) {
01410 CPT(GeomVertexData) data = cdata->_data.get_read_pointer();
01411 if (data->has_column(InternalName::get_size())) {
01412 cdata->_geom_rendering |= GR_per_point_size;
01413 }
01414 if (data->has_column(InternalName::get_aspect_ratio())) {
01415 cdata->_geom_rendering |= GR_point_aspect_ratio;
01416 }
01417 if (data->has_column(InternalName::get_rotate())) {
01418 cdata->_geom_rendering |= GR_point_rotate;
01419 }
01420 }
01421
01422 switch (get_shade_model()) {
01423 case SM_flat_first_vertex:
01424 cdata->_geom_rendering |= GR_flat_first_vertex;
01425 break;
01426
01427 case SM_flat_last_vertex:
01428 cdata->_geom_rendering |= GR_flat_last_vertex;
01429 break;
01430
01431 default:
01432 break;
01433 }
01434 }
01435
01436
01437
01438
01439
01440
01441
01442
01443 void Geom::
01444 combine_primitives(GeomPrimitive *a_prim, const GeomPrimitive *b_prim,
01445 Thread *current_thread) {
01446 nassertv(a_prim != b_prim);
01447 nassertv(a_prim->get_type() == b_prim->get_type());
01448
01449 CPT(GeomPrimitive) b_prim2 = b_prim;
01450
01451 if (a_prim->get_index_type() != b_prim2->get_index_type()) {
01452 GeomPrimitive::NumericType index_type = max(a_prim->get_index_type(), b_prim2->get_index_type());
01453 a_prim->set_index_type(index_type);
01454 if (b_prim2->get_index_type() != index_type) {
01455 PT(GeomPrimitive) b_prim_copy = b_prim2->make_copy();
01456 b_prim_copy->set_index_type(index_type);
01457 b_prim2 = b_prim_copy;
01458 }
01459 }
01460
01461 if (!b_prim2->is_indexed()) {
01462 PT(GeomPrimitive) b_prim_copy = b_prim2->make_copy();
01463 b_prim_copy->make_indexed();
01464 b_prim2 = b_prim_copy;
01465 }
01466
01467 PT(GeomVertexArrayData) a_vertices = a_prim->modify_vertices();
01468 CPT(GeomVertexArrayData) b_vertices = b_prim2->get_vertices();
01469
01470 if (a_prim->requires_unused_vertices()) {
01471 GeomVertexReader index(b_vertices, 0);
01472 int b_vertex = index.get_data1i();
01473 a_prim->append_unused_vertices(a_vertices, b_vertex);
01474 }
01475
01476 PT(GeomVertexArrayDataHandle) a_handle = a_vertices->modify_handle(current_thread);
01477 CPT(GeomVertexArrayDataHandle) b_handle = b_vertices->get_handle(current_thread);
01478
01479 size_t orig_a_vertices = a_handle->get_num_rows();
01480
01481 a_handle->copy_subdata_from(a_handle->get_data_size_bytes(), 0,
01482 b_handle, 0, b_handle->get_data_size_bytes());
01483 a_prim->clear_minmax();
01484 if (a_prim->is_composite()) {
01485
01486 PTA_int a_ends = a_prim->modify_ends();
01487 CPTA_int b_ends = b_prim2->get_ends();
01488 for (size_t i = 0; i < b_ends.size(); ++i) {
01489 a_ends.push_back(b_ends[i] + orig_a_vertices);
01490 }
01491 }
01492 }
01493
01494
01495
01496
01497
01498
01499
01500 void Geom::
01501 register_with_read_factory() {
01502 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
01503 }
01504
01505
01506
01507
01508
01509
01510
01511 void Geom::
01512 write_datagram(BamWriter *manager, Datagram &dg) {
01513 TypedWritable::write_datagram(manager, dg);
01514
01515 manager->write_cdata(dg, _cycler);
01516 }
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526 TypedWritable *Geom::
01527 make_from_bam(const FactoryParams ¶ms) {
01528 Geom *object = new Geom(NULL);
01529 DatagramIterator scan;
01530 BamReader *manager;
01531
01532 parse_params(params, scan, manager);
01533 object->fillin(scan, manager);
01534 manager->register_finalize(object);
01535
01536 return object;
01537 }
01538
01539
01540
01541
01542
01543
01544
01545
01546 void Geom::
01547 finalize(BamReader *manager) {
01548 CDWriter cdata(_cycler, true);
01549
01550
01551
01552
01553 if (!cdata->_data.is_null()) {
01554
01555
01556 cdata->_data.get_unsafe_pointer()->finalize(manager);
01557 }
01558
01559 reset_geom_rendering(cdata);
01560 }
01561
01562
01563
01564
01565
01566
01567
01568
01569 void Geom::
01570 fillin(DatagramIterator &scan, BamReader *manager) {
01571 TypedWritable::fillin(scan, manager);
01572
01573 manager->read_cdata(scan, _cycler);
01574 }
01575
01576
01577
01578
01579
01580
01581 Geom::CDataCache::
01582 ~CDataCache() {
01583 set_result(NULL, NULL);
01584 }
01585
01586
01587
01588
01589
01590
01591 CycleData *Geom::CDataCache::
01592 make_copy() const {
01593 return new CDataCache(*this);
01594 }
01595
01596
01597
01598
01599
01600
01601
01602 void Geom::CacheEntry::
01603 evict_callback() {
01604 LightMutexHolder holder(_source->_cache_lock);
01605 Cache::iterator ci = _source->_cache.find(&_key);
01606 nassertv(ci != _source->_cache.end());
01607 nassertv((*ci).second == this);
01608 _source->_cache.erase(ci);
01609 }
01610
01611
01612
01613
01614
01615
01616 void Geom::CacheEntry::
01617 output(ostream &out) const {
01618 out << "geom " << (void *)_source << ", "
01619 << (const void *)_key._modifier;
01620 }
01621
01622
01623
01624
01625
01626
01627
01628 CycleData *Geom::CData::
01629 make_copy() const {
01630 return new CData(*this);
01631 }
01632
01633
01634
01635
01636
01637
01638
01639 void Geom::CData::
01640 write_datagram(BamWriter *manager, Datagram &dg) const {
01641 manager->write_pointer(dg, _data.get_read_pointer());
01642
01643 dg.add_uint16(_primitives.size());
01644 Primitives::const_iterator pi;
01645 for (pi = _primitives.begin(); pi != _primitives.end(); ++pi) {
01646 manager->write_pointer(dg, (*pi).get_read_pointer());
01647 }
01648
01649 dg.add_uint8(_primitive_type);
01650 dg.add_uint8(_shade_model);
01651
01652
01653
01654 dg.add_uint16(_geom_rendering);
01655
01656 dg.add_uint8(_bounds_type);
01657 }
01658
01659
01660
01661
01662
01663
01664
01665
01666 int Geom::CData::
01667 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01668 int pi = CycleData::complete_pointers(p_list, manager);
01669
01670 _data = DCAST(GeomVertexData, p_list[pi++]);
01671
01672 Primitives::iterator pri;
01673 for (pri = _primitives.begin(); pri != _primitives.end(); ++pri) {
01674 (*pri) = DCAST(GeomPrimitive, p_list[pi++]);
01675 }
01676
01677 return pi;
01678 }
01679
01680
01681
01682
01683
01684
01685
01686
01687 void Geom::CData::
01688 fillin(DatagramIterator &scan, BamReader *manager) {
01689 manager->read_pointer(scan);
01690
01691 int num_primitives = scan.get_uint16();
01692 _primitives.reserve(num_primitives);
01693 for (int i = 0; i < num_primitives; ++i) {
01694 manager->read_pointer(scan);
01695 _primitives.push_back(NULL);
01696 }
01697
01698 _primitive_type = (PrimitiveType)scan.get_uint8();
01699 _shade_model = (ShadeModel)scan.get_uint8();
01700
01701
01702
01703 scan.get_uint16();
01704
01705 _got_usage_hint = false;
01706 _modified = Geom::get_next_modified();
01707
01708 _bounds_type = BoundingVolume::BT_default;
01709 if (manager->get_file_minor_ver() >= 19) {
01710 _bounds_type = (BoundingVolume::BoundsType)scan.get_uint8();
01711 }
01712 }
01713
01714
01715
01716
01717
01718
01719
01720 void GeomPipelineReader::
01721 check_usage_hint() const {
01722 if (!_cdata->_got_usage_hint) {
01723
01724
01725
01726 {
01727 #ifdef DO_PIPELINING
01728 unref_delete((CycleData *)_cdata);
01729 #endif
01730 Geom::CDWriter fresh_cdata(((Geom *)_object.p())->_cycler,
01731 false, _current_thread);
01732 ((GeomPipelineReader *)this)->_cdata = fresh_cdata;
01733 #ifdef DO_PIPELINING
01734 _cdata->ref();
01735 #endif
01736 if (!fresh_cdata->_got_usage_hint) {
01737
01738
01739 ((Geom *)_object.p())->reset_usage_hint(fresh_cdata);
01740 nassertv(fresh_cdata->_got_usage_hint);
01741 }
01742
01743
01744
01745
01746 }
01747 }
01748
01749 nassertv(_cdata->_got_usage_hint);
01750 }
01751
01752
01753
01754
01755
01756
01757 bool GeomPipelineReader::
01758 check_valid(const GeomVertexDataPipelineReader *data_reader) const {
01759 Geom::Primitives::const_iterator pi;
01760 for (pi = _cdata->_primitives.begin();
01761 pi != _cdata->_primitives.end();
01762 ++pi) {
01763 CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
01764 GeomPrimitivePipelineReader reader(primitive, _current_thread);
01765 reader.check_minmax();
01766 if (!reader.check_valid(data_reader)) {
01767 return false;
01768 }
01769 }
01770
01771 return true;
01772 }
01773
01774
01775
01776
01777
01778
01779 bool GeomPipelineReader::
01780 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
01781 const GeomVertexDataPipelineReader *data_reader, bool force) const {
01782 PStatTimer timer(Geom::_draw_primitive_setup_pcollector);
01783 bool all_ok = gsg->begin_draw_primitives(this, munger, data_reader, force);
01784 if (all_ok) {
01785 Geom::Primitives::const_iterator pi;
01786 for (pi = _cdata->_primitives.begin();
01787 pi != _cdata->_primitives.end();
01788 ++pi) {
01789 CPT(GeomPrimitive) primitive = (*pi).get_read_pointer();
01790 GeomPrimitivePipelineReader reader(primitive, _current_thread);
01791 if (reader.get_num_vertices() != 0) {
01792 reader.check_minmax();
01793 nassertr(reader.check_valid(data_reader), false);
01794 if (!primitive->draw(gsg, &reader, force)) {
01795 all_ok = false;
01796 }
01797 }
01798 }
01799 gsg->end_draw_primitives();
01800 }
01801
01802 return all_ok;
01803 }