00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "geomPrimitive.h"
00016 #include "geom.h"
00017 #include "geomVertexData.h"
00018 #include "geomVertexArrayFormat.h"
00019 #include "geomVertexColumn.h"
00020 #include "geomVertexReader.h"
00021 #include "geomVertexWriter.h"
00022 #include "geomVertexRewriter.h"
00023 #include "geomPoints.h"
00024 #include "preparedGraphicsObjects.h"
00025 #include "internalName.h"
00026 #include "bamReader.h"
00027 #include "bamWriter.h"
00028 #include "ioPtaDatagramInt.h"
00029 #include "indent.h"
00030 #include "pStatTimer.h"
00031
00032 TypeHandle GeomPrimitive::_type_handle;
00033 TypeHandle GeomPrimitive::CData::_type_handle;
00034 TypeHandle GeomPrimitivePipelineReader::_type_handle;
00035
00036 PStatCollector GeomPrimitive::_decompose_pcollector("*:Munge:Decompose");
00037 PStatCollector GeomPrimitive::_doubleside_pcollector("*:Munge:Doubleside");
00038 PStatCollector GeomPrimitive::_reverse_pcollector("*:Munge:Reverse");
00039 PStatCollector GeomPrimitive::_rotate_pcollector("*:Munge:Rotate");
00040
00041
00042
00043
00044
00045
00046
00047 GeomPrimitive::
00048 GeomPrimitive() {
00049 }
00050
00051
00052
00053
00054
00055
00056 PT(CopyOnWriteObject) GeomPrimitive::
00057 make_cow_copy() {
00058 return make_copy().p();
00059 }
00060
00061
00062
00063
00064
00065
00066 GeomPrimitive::
00067 GeomPrimitive(GeomPrimitive::UsageHint usage_hint) {
00068 CDWriter cdata(_cycler, true);
00069 cdata->_usage_hint = usage_hint;
00070 }
00071
00072
00073
00074
00075
00076
00077 GeomPrimitive::
00078 GeomPrimitive(const GeomPrimitive ©) :
00079 CopyOnWriteObject(copy),
00080 _cycler(copy._cycler)
00081 {
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 void GeomPrimitive::
00093 operator = (const GeomPrimitive ©) {
00094 CopyOnWriteObject::operator = (copy);
00095 _cycler = copy._cycler;
00096 }
00097
00098
00099
00100
00101
00102
00103 GeomPrimitive::
00104 ~GeomPrimitive() {
00105 release_all();
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115 int GeomPrimitive::
00116 get_geom_rendering() const {
00117 if (is_indexed()) {
00118 return GR_indexed_other;
00119 } else {
00120 return 0;
00121 }
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 void GeomPrimitive::
00135 set_usage_hint(GeomPrimitive::UsageHint usage_hint) {
00136 CDWriter cdata(_cycler, true);
00137 cdata->_usage_hint = usage_hint;
00138
00139 if (!cdata->_vertices.is_null()) {
00140 cdata->_modified = Geom::get_next_modified();
00141 cdata->_usage_hint = usage_hint;
00142 }
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 void GeomPrimitive::
00164 set_index_type(GeomPrimitive::NumericType index_type) {
00165 nassertv(get_max_vertex() <= get_highest_index_value(index_type));
00166
00167 CDWriter cdata(_cycler, true);
00168 if (cdata->_index_type != index_type) {
00169 do_set_index_type(cdata, index_type);
00170 }
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 void GeomPrimitive::
00188 add_vertex(int vertex) {
00189 CDWriter cdata(_cycler, true);
00190
00191 if (gobj_cat.is_spam()) {
00192 gobj_cat.spam()
00193 << this << ".add_vertex(" << vertex << ")\n";
00194 }
00195
00196 consider_elevate_index_type(cdata, vertex);
00197
00198 int num_primitives = get_num_primitives();
00199 if (num_primitives > 0 &&
00200 requires_unused_vertices() &&
00201 get_num_vertices() == get_primitive_end(num_primitives - 1)) {
00202
00203
00204 if (cdata->_vertices.is_null()) {
00205 do_make_indexed(cdata);
00206 }
00207 append_unused_vertices(cdata->_vertices.get_write_pointer(), vertex);
00208 }
00209
00210 if (cdata->_vertices.is_null()) {
00211
00212
00213 nassertv(cdata->_num_vertices != -1);
00214 if (cdata->_num_vertices == 0) {
00215 cdata->_first_vertex = vertex;
00216 cdata->_num_vertices = 1;
00217 cdata->_modified = Geom::get_next_modified();
00218 cdata->_got_minmax = false;
00219 return;
00220
00221 } else if (vertex == cdata->_first_vertex + cdata->_num_vertices) {
00222 ++cdata->_num_vertices;
00223 cdata->_modified = Geom::get_next_modified();
00224 cdata->_got_minmax = false;
00225 return;
00226 }
00227
00228
00229 do_make_indexed(cdata);
00230 }
00231
00232 PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer();
00233 GeomVertexWriter index(array_obj, 0);
00234 index.set_row_unsafe(array_obj->get_num_rows());
00235
00236 index.add_data1i(vertex);
00237
00238 cdata->_modified = Geom::get_next_modified();
00239 cdata->_got_minmax = false;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 void GeomPrimitive::
00253 add_consecutive_vertices(int start, int num_vertices) {
00254 if (num_vertices == 0) {
00255 return;
00256 }
00257 int end = (start + num_vertices) - 1;
00258
00259 CDWriter cdata(_cycler, true);
00260
00261 consider_elevate_index_type(cdata, end);
00262
00263 int num_primitives = get_num_primitives();
00264 if (num_primitives > 0 &&
00265 get_num_vertices() == get_primitive_end(num_primitives - 1)) {
00266
00267
00268 if (cdata->_vertices.is_null()) {
00269 do_make_indexed(cdata);
00270 }
00271 append_unused_vertices(cdata->_vertices.get_write_pointer(), start);
00272 }
00273
00274 if (cdata->_vertices.is_null()) {
00275
00276
00277 nassertv(cdata->_num_vertices != -1);
00278 if (cdata->_num_vertices == 0) {
00279 cdata->_first_vertex = start;
00280 cdata->_num_vertices = num_vertices;
00281 cdata->_modified = Geom::get_next_modified();
00282 cdata->_got_minmax = false;
00283 return;
00284
00285 } else if (start == cdata->_first_vertex + cdata->_num_vertices) {
00286 cdata->_num_vertices += num_vertices;
00287 cdata->_modified = Geom::get_next_modified();
00288 cdata->_got_minmax = false;
00289 return;
00290 }
00291
00292
00293 do_make_indexed(cdata);
00294 }
00295
00296 PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer();
00297 GeomVertexWriter index(array_obj, 0);
00298 index.set_row_unsafe(array_obj->get_num_rows());
00299
00300 for (int v = start; v <= end; ++v) {
00301 index.add_data1i(v);
00302 }
00303
00304 cdata->_modified = Geom::get_next_modified();
00305 cdata->_got_minmax = false;
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 void GeomPrimitive::
00320 add_next_vertices(int num_vertices) {
00321 if (get_num_vertices() == 0) {
00322 add_consecutive_vertices(0, num_vertices);
00323 } else {
00324 add_consecutive_vertices(get_vertex(get_num_vertices() - 1) + 1, num_vertices);
00325 }
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 void GeomPrimitive::
00351 reserve_num_vertices(int num_vertices) {
00352 if (gobj_cat.is_debug()) {
00353 gobj_cat.debug()
00354 << this << ".reserve_num_vertices(" << num_vertices << ")\n";
00355 }
00356
00357 CDWriter cdata(_cycler, true);
00358 consider_elevate_index_type(cdata, num_vertices);
00359 do_make_indexed(cdata);
00360 PT(GeomVertexArrayData) array_obj = cdata->_vertices.get_write_pointer();
00361 array_obj->reserve_num_rows(num_vertices);
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 bool GeomPrimitive::
00377 close_primitive() {
00378 int num_vertices_per_primitive = get_num_vertices_per_primitive();
00379
00380 CDWriter cdata(_cycler, true);
00381 if (num_vertices_per_primitive == 0) {
00382
00383
00384 #ifndef NDEBUG
00385 int num_added;
00386 if (cdata->_ends.empty()) {
00387 num_added = get_num_vertices();
00388 } else {
00389 num_added = get_num_vertices() - cdata->_ends.back();
00390 num_added -= get_num_unused_vertices_per_primitive();
00391 }
00392 nassertr(num_added >= get_min_num_vertices_per_primitive(), false);
00393 #endif
00394 if (cdata->_ends.get_ref_count() > 1) {
00395 PTA_int new_ends;
00396 new_ends.v() = cdata->_ends.v();
00397 cdata->_ends = new_ends;
00398 }
00399 cdata->_ends.push_back(get_num_vertices());
00400
00401 } else {
00402 #ifndef NDEBUG
00403
00404
00405
00406 int num_vertices_per_primitive = get_num_vertices_per_primitive();
00407 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
00408
00409 int num_vertices = get_num_vertices();
00410 nassertr((num_vertices + num_unused_vertices_per_primitive) % (num_vertices_per_primitive + num_unused_vertices_per_primitive) == 0, false)
00411 #endif
00412 }
00413
00414 cdata->_modified = Geom::get_next_modified();
00415
00416 return true;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 void GeomPrimitive::
00430 clear_vertices() {
00431 CDWriter cdata(_cycler, true);
00432 cdata->_first_vertex = 0;
00433 cdata->_num_vertices = 0;
00434
00435
00436
00437
00438 cdata->_index_type = NT_uint16;
00439
00440 cdata->_vertices.clear();
00441 cdata->_ends.clear();
00442 cdata->_mins.clear();
00443 cdata->_maxs.clear();
00444 cdata->_modified = Geom::get_next_modified();
00445 cdata->_got_minmax = false;
00446 }
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 void GeomPrimitive::
00459 offset_vertices(int offset) {
00460 if (is_indexed()) {
00461 CDWriter cdata(_cycler, true);
00462
00463 if (!cdata->_got_minmax) {
00464 recompute_minmax(cdata);
00465 nassertv(cdata->_got_minmax);
00466 }
00467
00468 consider_elevate_index_type(cdata, cdata->_max_vertex + offset);
00469
00470 GeomVertexRewriter index(do_modify_vertices(cdata), 0);
00471 while (!index.is_at_end()) {
00472 index.set_data1i(index.get_data1i() + offset);
00473 }
00474
00475 } else {
00476 CDWriter cdata(_cycler, true);
00477
00478 cdata->_first_vertex += offset;
00479 cdata->_modified = Geom::get_next_modified();
00480 cdata->_got_minmax = false;
00481
00482 consider_elevate_index_type(cdata,
00483 cdata->_first_vertex + cdata->_num_vertices - 1);
00484 }
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494 void GeomPrimitive::
00495 make_nonindexed(GeomVertexData *dest, const GeomVertexData *source) {
00496 Thread *current_thread = Thread::get_current_thread();
00497 int num_vertices = get_num_vertices();
00498 int dest_start = dest->get_num_rows();
00499
00500 dest->set_num_rows(dest_start + num_vertices);
00501 for (int i = 0; i < num_vertices; ++i) {
00502 int v = get_vertex(i);
00503 dest->copy_row_from(dest_start + i, source, v, current_thread);
00504 }
00505
00506 set_nonindexed_vertices(dest_start, num_vertices);
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516 void GeomPrimitive::
00517 pack_vertices(GeomVertexData *dest, const GeomVertexData *source) {
00518 Thread *current_thread = Thread::get_current_thread();
00519 if (!is_indexed()) {
00520
00521
00522 make_nonindexed(dest, source);
00523
00524 } else {
00525
00526 CPT(GeomVertexArrayData) orig_vertices = get_vertices();
00527 PT(GeomVertexArrayData) new_vertices = make_index_data();
00528 GeomVertexWriter index(new_vertices, 0);
00529 typedef pmap<int, int> CopiedIndices;
00530 CopiedIndices copied_indices;
00531
00532 int num_vertices = get_num_vertices();
00533 int dest_start = dest->get_num_rows();
00534
00535 for (int i = 0; i < num_vertices; ++i) {
00536 int v = get_vertex(i);
00537
00538
00539
00540
00541 pair<CopiedIndices::iterator, bool> result =
00542 copied_indices.insert(CopiedIndices::value_type(v, (int)copied_indices.size()));
00543 int v2 = (*result.first).second + dest_start;
00544 index.add_data1i(v2);
00545
00546 if (result.second) {
00547
00548 dest->copy_row_from(v2, source, v, current_thread);
00549 }
00550 }
00551
00552 set_vertices(new_vertices);
00553 }
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 void GeomPrimitive::
00572 make_indexed() {
00573 CDWriter cdata(_cycler, true);
00574 do_make_indexed(cdata);
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 int GeomPrimitive::
00592 get_primitive_start(int n) const {
00593 int num_vertices_per_primitive = get_num_vertices_per_primitive();
00594 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
00595
00596 if (num_vertices_per_primitive == 0) {
00597
00598
00599 CDReader cdata(_cycler);
00600 nassertr(n >= 0 && n <= (int)cdata->_ends.size(), -1);
00601 if (n == 0) {
00602 return 0;
00603 } else {
00604 return cdata->_ends[n - 1] + num_unused_vertices_per_primitive;
00605 }
00606
00607 } else {
00608
00609
00610 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive);
00611 }
00612 }
00613
00614
00615
00616
00617
00618
00619
00620
00621 int GeomPrimitive::
00622 get_primitive_end(int n) const {
00623 int num_vertices_per_primitive = get_num_vertices_per_primitive();
00624
00625 if (num_vertices_per_primitive == 0) {
00626
00627
00628 CDReader cdata(_cycler);
00629 nassertr(n >= 0 && n < (int)cdata->_ends.size(), -1);
00630 return cdata->_ends[n];
00631
00632 } else {
00633
00634
00635 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
00636 return n * (num_vertices_per_primitive + num_unused_vertices_per_primitive) + num_vertices_per_primitive;
00637 }
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647 int GeomPrimitive::
00648 get_primitive_num_vertices(int n) const {
00649 int num_vertices_per_primitive = get_num_vertices_per_primitive();
00650
00651 if (num_vertices_per_primitive == 0) {
00652
00653
00654 CDReader cdata(_cycler);
00655 nassertr(n >= 0 && n < (int)cdata->_ends.size(), 0);
00656 if (n == 0) {
00657 return cdata->_ends[0];
00658 } else {
00659 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
00660 return cdata->_ends[n] - cdata->_ends[n - 1] - num_unused_vertices_per_primitive;
00661 }
00662
00663 } else {
00664
00665
00666 return num_vertices_per_primitive;
00667 }
00668 }
00669
00670
00671
00672
00673
00674
00675
00676 int GeomPrimitive::
00677 get_primitive_min_vertex(int n) const {
00678 if (is_indexed()) {
00679 CPT(GeomVertexArrayData) mins = get_mins();
00680 nassertr(n >= 0 && n < mins->get_num_rows(), -1);
00681
00682 GeomVertexReader index(mins, 0);
00683 index.set_row_unsafe(n);
00684 return index.get_data1i();
00685 } else {
00686 return get_primitive_start(n);
00687 }
00688 }
00689
00690
00691
00692
00693
00694
00695
00696 int GeomPrimitive::
00697 get_primitive_max_vertex(int n) const {
00698 if (is_indexed()) {
00699 CPT(GeomVertexArrayData) maxs = get_maxs();
00700 nassertr(n >= 0 && n < maxs->get_num_rows(), -1);
00701
00702 GeomVertexReader index(maxs, 0);
00703 index.set_row_unsafe(n);
00704 return index.get_data1i();
00705 } else {
00706 return get_primitive_end(n) - 1;
00707 }
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724 CPT(GeomPrimitive) GeomPrimitive::
00725 decompose() const {
00726 if (gobj_cat.is_debug()) {
00727 gobj_cat.debug()
00728 << "Decomposing " << get_type() << ": " << (void *)this << "\n";
00729 }
00730
00731 PStatTimer timer(_decompose_pcollector);
00732 return decompose_impl();
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 CPT(GeomPrimitive) GeomPrimitive::
00750 rotate() const {
00751 if (gobj_cat.is_debug()) {
00752 gobj_cat.debug()
00753 << "Rotating " << get_type() << ": " << (void *)this << "\n";
00754 }
00755
00756 PStatTimer timer(_rotate_pcollector);
00757 CPT(GeomVertexArrayData) rotated_vertices = rotate_impl();
00758
00759 if (rotated_vertices == (GeomVertexArrayData *)NULL) {
00760
00761 return this;
00762 }
00763
00764 PT(GeomPrimitive) new_prim = make_copy();
00765 new_prim->set_vertices(rotated_vertices);
00766
00767 switch (get_shade_model()) {
00768 case SM_flat_first_vertex:
00769 new_prim->set_shade_model(SM_flat_last_vertex);
00770 break;
00771
00772 case SM_flat_last_vertex:
00773 new_prim->set_shade_model(SM_flat_first_vertex);
00774 break;
00775
00776 default:
00777 break;
00778 }
00779
00780 return new_prim;
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 CPT(GeomPrimitive) GeomPrimitive::
00799 doubleside() const {
00800 if (gobj_cat.is_debug()) {
00801 gobj_cat.debug()
00802 << "Doublesiding " << get_type() << ": " << (void *)this << "\n";
00803 }
00804
00805 PStatTimer timer(_doubleside_pcollector);
00806 return doubleside_impl();
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 CPT(GeomPrimitive) GeomPrimitive::
00825 reverse() const {
00826 if (gobj_cat.is_debug()) {
00827 gobj_cat.debug()
00828 << "Reversing " << get_type() << ": " << (void *)this << "\n";
00829 }
00830
00831 PStatTimer timer(_reverse_pcollector);
00832 return reverse_impl();
00833 }
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 CPT(GeomPrimitive) GeomPrimitive::
00849 match_shade_model(GeomPrimitive::ShadeModel shade_model) const {
00850 ShadeModel this_shade_model = get_shade_model();
00851 if (this_shade_model == shade_model) {
00852
00853 return this;
00854 }
00855
00856 if (this_shade_model == SM_uniform || shade_model == SM_uniform) {
00857
00858 return this;
00859 }
00860
00861 if ((this_shade_model == SM_flat_first_vertex && shade_model == SM_flat_last_vertex) ||
00862 (this_shade_model == SM_flat_last_vertex && shade_model == SM_flat_first_vertex)) {
00863
00864 CPT(GeomPrimitive) rotated = rotate();
00865 if (rotated.p() == this) {
00866
00867 return NULL;
00868 }
00869 return rotated;
00870 }
00871
00872
00873 return NULL;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 CPT(GeomPrimitive) GeomPrimitive::
00886 make_points() const {
00887 if (is_exact_type(GeomPoints::get_class_type())) {
00888 return this;
00889 }
00890
00891
00892
00893 BitArray bits;
00894 int num_vertices = get_num_vertices();
00895 if (is_indexed()) {
00896 CPT(GeomVertexArrayData) vertices = get_vertices();
00897 GeomVertexReader index(vertices, 0);
00898 for (int vi = 0; vi < num_vertices; ++vi) {
00899 nassertr(!index.is_at_end(), NULL);
00900 bits.set_bit(index.get_data1i());
00901 }
00902 } else {
00903 int first_vertex = get_first_vertex();
00904 bits.set_range(first_vertex, num_vertices);
00905 }
00906
00907
00908 PT(GeomVertexArrayData) new_vertices = make_index_data();
00909 GeomVertexWriter new_index(new_vertices, 0);
00910 int p = bits.get_lowest_on_bit();
00911 while (p != -1) {
00912 while (bits.get_bit(p)) {
00913 new_index.add_data1i(p);
00914 ++p;
00915 }
00916 int q = bits.get_next_higher_different_bit(p);
00917 if (q == p) {
00918 break;
00919 }
00920 p = q;
00921 }
00922
00923 PT(GeomPrimitive) points = new GeomPoints(UH_dynamic);
00924 points->set_vertices(new_vertices);
00925
00926 return points;
00927 }
00928
00929
00930
00931
00932
00933
00934
00935 int GeomPrimitive::
00936 get_num_bytes() const {
00937 CDReader cdata(_cycler);
00938 int num_bytes = cdata->_ends.size() * sizeof(int) + sizeof(GeomPrimitive);
00939 if (!cdata->_vertices.is_null()) {
00940 num_bytes += cdata->_vertices.get_read_pointer()->get_data_size_bytes();
00941 }
00942
00943 return num_bytes;
00944 }
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 bool GeomPrimitive::
00955 request_resident() const {
00956 CDReader cdata(_cycler);
00957
00958 bool resident = true;
00959
00960 if (!cdata->_vertices.is_null() &&
00961 !cdata->_vertices.get_read_pointer()->request_resident()) {
00962 resident = false;
00963 }
00964
00965 if (is_composite() && cdata->_got_minmax) {
00966 if (!cdata->_mins.is_null() &&
00967 !cdata->_mins.get_read_pointer()->request_resident()) {
00968 resident = false;
00969 }
00970 if (!cdata->_maxs.is_null() &&
00971 !cdata->_maxs.get_read_pointer()->request_resident()) {
00972 resident = false;
00973 }
00974 }
00975
00976 return resident;
00977 }
00978
00979
00980
00981
00982
00983
00984 void GeomPrimitive::
00985 output(ostream &out) const {
00986 out << get_type() << ", " << get_num_primitives()
00987 << ", " << get_num_vertices();
00988 }
00989
00990
00991
00992
00993
00994
00995 void GeomPrimitive::
00996 write(ostream &out, int indent_level) const {
00997 indent(out, indent_level)
00998 << get_type();
00999 if (is_indexed()) {
01000 out << " (indexed)";
01001 } else {
01002 out << " (nonindexed)";
01003 }
01004 out << ":\n";
01005 int num_primitives = get_num_primitives();
01006 int num_vertices = get_num_vertices();
01007 int num_unused_vertices_per_primitive = get_num_unused_vertices_per_primitive();
01008 for (int i = 0; i < num_primitives; ++i) {
01009 indent(out, indent_level + 2)
01010 << "[";
01011 int begin = get_primitive_start(i);
01012 int end = get_primitive_end(i);
01013 for (int vi = begin; vi < end; vi++) {
01014 out << " " << get_vertex(vi);
01015 }
01016 out << " ]";
01017 if (end < num_vertices) {
01018 for (int ui = 0; ui < num_unused_vertices_per_primitive; ++ui) {
01019 if (end + ui < num_vertices) {
01020 out << " " << get_vertex(end + ui);
01021 } else {
01022 out << " ?";
01023 }
01024 }
01025 }
01026 out << "\n";
01027 }
01028 }
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055 PT(GeomVertexArrayData) GeomPrimitive::
01056 modify_vertices(int num_vertices) {
01057 CDWriter cdata(_cycler, true);
01058 PT(GeomVertexArrayData) vertices = do_modify_vertices(cdata);
01059 cdata->_num_vertices = num_vertices;
01060 return vertices;
01061 }
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 void GeomPrimitive::
01085 set_vertices(const GeomVertexArrayData *vertices, int num_vertices) {
01086 CDWriter cdata(_cycler, true);
01087 cdata->_vertices = (GeomVertexArrayData *)vertices;
01088 cdata->_num_vertices = num_vertices;
01089
01090 cdata->_modified = Geom::get_next_modified();
01091 cdata->_got_minmax = false;
01092 }
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109 void GeomPrimitive::
01110 set_nonindexed_vertices(int first_vertex, int num_vertices) {
01111 nassertv(num_vertices != -1);
01112 CDWriter cdata(_cycler, true);
01113 cdata->_vertices = (GeomVertexArrayData *)NULL;
01114 cdata->_first_vertex = first_vertex;
01115 cdata->_num_vertices = num_vertices;
01116
01117 cdata->_modified = Geom::get_next_modified();
01118 cdata->_got_minmax = false;
01119
01120
01121 recompute_minmax(cdata);
01122 }
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145 PTA_int GeomPrimitive::
01146 modify_ends() {
01147 CDWriter cdata(_cycler, true);
01148
01149 cdata->_modified = Geom::get_next_modified();
01150 cdata->_got_minmax = false;
01151
01152 if (cdata->_ends.get_ref_count() > 1) {
01153 PTA_int new_ends;
01154 new_ends.v() = cdata->_ends.v();
01155 cdata->_ends = new_ends;
01156 }
01157 return cdata->_ends;
01158 }
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 void GeomPrimitive::
01182 set_ends(CPTA_int ends) {
01183 CDWriter cdata(_cycler, true);
01184 cdata->_ends = (PTA_int &)ends;
01185
01186 cdata->_modified = Geom::get_next_modified();
01187 cdata->_got_minmax = false;
01188 }
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 void GeomPrimitive::
01212 set_minmax(int min_vertex, int max_vertex,
01213 GeomVertexArrayData *mins, GeomVertexArrayData *maxs) {
01214 CDWriter cdata(_cycler, true);
01215 cdata->_min_vertex = min_vertex;
01216 cdata->_max_vertex = max_vertex;
01217 cdata->_mins = mins;
01218 cdata->_maxs = maxs;
01219
01220 cdata->_modified = Geom::get_next_modified();
01221 cdata->_got_minmax = true;
01222 }
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236 void GeomPrimitive::
01237 clear_minmax() {
01238 CDWriter cdata(_cycler, true);
01239 cdata->_got_minmax = false;
01240 }
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258 int GeomPrimitive::
01259 get_num_vertices_per_primitive() const {
01260 return 0;
01261 }
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 int GeomPrimitive::
01275 get_min_num_vertices_per_primitive() const {
01276 return 3;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293 int GeomPrimitive::
01294 get_num_unused_vertices_per_primitive() const {
01295 return 0;
01296 }
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310 void GeomPrimitive::
01311 prepare(PreparedGraphicsObjects *prepared_objects) {
01312 if (is_indexed()) {
01313 prepared_objects->enqueue_index_buffer(this);
01314 }
01315 }
01316
01317
01318
01319
01320
01321
01322
01323
01324 bool GeomPrimitive::
01325 is_prepared(PreparedGraphicsObjects *prepared_objects) const {
01326 Contexts::const_iterator ci;
01327 ci = _contexts.find(prepared_objects);
01328 if (ci != _contexts.end()) {
01329 return true;
01330 }
01331 return prepared_objects->is_index_buffer_queued(this);
01332 }
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350 IndexBufferContext *GeomPrimitive::
01351 prepare_now(PreparedGraphicsObjects *prepared_objects,
01352 GraphicsStateGuardianBase *gsg) {
01353 nassertr(is_indexed(), NULL);
01354
01355 Contexts::const_iterator ci;
01356 ci = _contexts.find(prepared_objects);
01357 if (ci != _contexts.end()) {
01358 return (*ci).second;
01359 }
01360
01361 IndexBufferContext *ibc = prepared_objects->prepare_index_buffer_now(this, gsg);
01362 if (ibc != (IndexBufferContext *)NULL) {
01363 _contexts[prepared_objects] = ibc;
01364 }
01365 return ibc;
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375 bool GeomPrimitive::
01376 release(PreparedGraphicsObjects *prepared_objects) {
01377 Contexts::iterator ci;
01378 ci = _contexts.find(prepared_objects);
01379 if (ci != _contexts.end()) {
01380 IndexBufferContext *ibc = (*ci).second;
01381 prepared_objects->release_index_buffer(ibc);
01382 return true;
01383 }
01384
01385
01386 return prepared_objects->dequeue_index_buffer(this);
01387 }
01388
01389
01390
01391
01392
01393
01394
01395
01396 int GeomPrimitive::
01397 release_all() {
01398
01399
01400
01401
01402 Contexts temp = _contexts;
01403 int num_freed = (int)_contexts.size();
01404
01405 Contexts::const_iterator ci;
01406 for (ci = temp.begin(); ci != temp.end(); ++ci) {
01407 PreparedGraphicsObjects *prepared_objects = (*ci).first;
01408 IndexBufferContext *ibc = (*ci).second;
01409 prepared_objects->release_index_buffer(ibc);
01410 }
01411
01412
01413
01414 nassertr(_contexts.empty(), num_freed);
01415
01416 return num_freed;
01417 }
01418
01419
01420
01421
01422
01423
01424
01425 CPT(GeomVertexArrayFormat) GeomPrimitive::
01426 get_index_format() const {
01427 PT(GeomVertexArrayFormat) format = new GeomVertexArrayFormat;
01428
01429
01430
01431 format->add_column(InternalName::get_index(), 1, get_index_type(), C_index, 0, 1);
01432 return GeomVertexArrayFormat::register_format(format);
01433 }
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445 void GeomPrimitive::
01446 clear_prepared(PreparedGraphicsObjects *prepared_objects) {
01447 Contexts::iterator ci;
01448 ci = _contexts.find(prepared_objects);
01449 if (ci != _contexts.end()) {
01450 _contexts.erase(ci);
01451 } else {
01452
01453
01454 nassertv(false);
01455 }
01456 }
01457
01458
01459
01460
01461
01462
01463
01464 int GeomPrimitive::
01465 get_highest_index_value(NumericType index_type) {
01466 switch (index_type) {
01467 case NT_uint8:
01468 return 0xff;
01469
01470 case NT_uint16:
01471 return 0xffff;
01472
01473 case NT_uint32:
01474
01475
01476 return 0x7fffffff;
01477
01478 default:
01479 return 0;
01480 }
01481 }
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494 void GeomPrimitive::
01495 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
01496 bool &found_any,
01497 const GeomVertexData *vertex_data,
01498 bool got_mat, const LMatrix4 &mat,
01499 const InternalName *column_name,
01500 Thread *current_thread) const {
01501 GeomVertexReader reader(vertex_data, column_name, current_thread);
01502 if (!reader.has_column()) {
01503
01504 return;
01505 }
01506
01507 CDReader cdata(_cycler, current_thread);
01508
01509 if (cdata->_vertices.is_null()) {
01510
01511 nassertv(cdata->_num_vertices != -1);
01512 if (got_mat) {
01513 for (int i = 0; i < cdata->_num_vertices; i++) {
01514 reader.set_row_unsafe(cdata->_first_vertex + i);
01515 LPoint3 vertex = mat.xform_point(reader.get_data3());
01516
01517 if (found_any) {
01518 min_point.set(min(min_point[0], vertex[0]),
01519 min(min_point[1], vertex[1]),
01520 min(min_point[2], vertex[2]));
01521 max_point.set(max(max_point[0], vertex[0]),
01522 max(max_point[1], vertex[1]),
01523 max(max_point[2], vertex[2]));
01524 } else {
01525 min_point = vertex;
01526 max_point = vertex;
01527 found_any = true;
01528 }
01529 }
01530 } else {
01531 for (int i = 0; i < cdata->_num_vertices; i++) {
01532 reader.set_row_unsafe(cdata->_first_vertex + i);
01533 const LVecBase3 &vertex = reader.get_data3();
01534
01535 if (found_any) {
01536 min_point.set(min(min_point[0], vertex[0]),
01537 min(min_point[1], vertex[1]),
01538 min(min_point[2], vertex[2]));
01539 max_point.set(max(max_point[0], vertex[0]),
01540 max(max_point[1], vertex[1]),
01541 max(max_point[2], vertex[2]));
01542 } else {
01543 min_point = vertex;
01544 max_point = vertex;
01545 found_any = true;
01546 }
01547 }
01548 }
01549
01550 } else {
01551
01552 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0, current_thread);
01553
01554 if (got_mat) {
01555 while (!index.is_at_end()) {
01556 int ii = index.get_data1i();
01557 reader.set_row_unsafe(ii);
01558 LPoint3 vertex = mat.xform_point(reader.get_data3());
01559
01560 if (found_any) {
01561 min_point.set(min(min_point[0], vertex[0]),
01562 min(min_point[1], vertex[1]),
01563 min(min_point[2], vertex[2]));
01564 max_point.set(max(max_point[0], vertex[0]),
01565 max(max_point[1], vertex[1]),
01566 max(max_point[2], vertex[2]));
01567 } else {
01568 min_point = vertex;
01569 max_point = vertex;
01570 found_any = true;
01571 }
01572 }
01573 } else {
01574 while (!index.is_at_end()) {
01575 int ii = index.get_data1i();
01576 reader.set_row_unsafe(ii);
01577 const LVecBase3 &vertex = reader.get_data3();
01578
01579 if (found_any) {
01580 min_point.set(min(min_point[0], vertex[0]),
01581 min(min_point[1], vertex[1]),
01582 min(min_point[2], vertex[2]));
01583 max_point.set(max(max_point[0], vertex[0]),
01584 max(max_point[1], vertex[1]),
01585 max(max_point[2], vertex[2]));
01586 } else {
01587 min_point = vertex;
01588 max_point = vertex;
01589 found_any = true;
01590 }
01591 }
01592 }
01593 }
01594 }
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610 CPT(GeomPrimitive) GeomPrimitive::
01611 decompose_impl() const {
01612 return this;
01613 }
01614
01615
01616
01617
01618
01619
01620 CPT(GeomVertexArrayData) GeomPrimitive::
01621 rotate_impl() const {
01622
01623 nassertr(false, NULL);
01624 return NULL;
01625 }
01626
01627
01628
01629
01630
01631
01632 CPT(GeomPrimitive) GeomPrimitive::
01633 doubleside_impl() const {
01634 return this;
01635 }
01636
01637
01638
01639
01640
01641
01642 CPT(GeomPrimitive) GeomPrimitive::
01643 reverse_impl() const {
01644 return this;
01645 }
01646
01647
01648
01649
01650
01651
01652
01653 bool GeomPrimitive::
01654 requires_unused_vertices() const {
01655 return false;
01656 }
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670 void GeomPrimitive::
01671 append_unused_vertices(GeomVertexArrayData *, int) {
01672 }
01673
01674
01675
01676
01677
01678
01679
01680 void GeomPrimitive::
01681 recompute_minmax(GeomPrimitive::CData *cdata) {
01682 if (cdata->_vertices.is_null()) {
01683
01684
01685 nassertv(cdata->_num_vertices != -1);
01686 cdata->_min_vertex = cdata->_first_vertex;
01687 cdata->_max_vertex = cdata->_first_vertex + cdata->_num_vertices - 1;
01688 cdata->_mins.clear();
01689 cdata->_maxs.clear();
01690
01691 } else {
01692 int num_vertices = cdata->_vertices.get_read_pointer()->get_num_rows();
01693
01694 if (num_vertices == 0) {
01695
01696 cdata->_min_vertex = 0;
01697 cdata->_max_vertex = 0;
01698 cdata->_mins.clear();
01699 cdata->_maxs.clear();
01700
01701 } else if (get_num_vertices_per_primitive() == 0) {
01702
01703
01704 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0);
01705
01706 cdata->_mins = make_index_data();
01707 cdata->_maxs = make_index_data();
01708
01709 GeomVertexWriter mins(cdata->_mins.get_write_pointer(), 0);
01710 mins.reserve_num_rows(cdata->_ends.size());
01711 GeomVertexWriter maxs(cdata->_maxs.get_write_pointer(), 0);
01712 maxs.reserve_num_rows(cdata->_ends.size());
01713
01714 int pi = 0;
01715
01716 unsigned int vertex = index.get_data1i();
01717 cdata->_min_vertex = vertex;
01718 cdata->_max_vertex = vertex;
01719 unsigned int min_prim = vertex;
01720 unsigned int max_prim = vertex;
01721
01722 for (int vi = 1; vi < num_vertices; ++vi) {
01723 nassertv(!index.is_at_end());
01724 unsigned int vertex = index.get_data1i();
01725 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
01726 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
01727
01728 nassertv(pi < (int)cdata->_ends.size());
01729 if (vi == cdata->_ends[pi]) {
01730 mins.add_data1i(min_prim);
01731 maxs.add_data1i(max_prim);
01732 min_prim = vertex;
01733 max_prim = vertex;
01734 ++pi;
01735
01736 } else {
01737 min_prim = min(min_prim, vertex);
01738 max_prim = max(max_prim, vertex);
01739 }
01740 }
01741 mins.add_data1i(min_prim);
01742 maxs.add_data1i(max_prim);
01743 nassertv(mins.get_array_data()->get_num_rows() == (int)cdata->_ends.size());
01744
01745 } else {
01746
01747
01748 GeomVertexReader index(cdata->_vertices.get_read_pointer(), 0);
01749
01750 cdata->_mins.clear();
01751 cdata->_maxs.clear();
01752
01753 unsigned int vertex = index.get_data1i();
01754 cdata->_min_vertex = vertex;
01755 cdata->_max_vertex = vertex;
01756
01757 for (int vi = 1; vi < num_vertices; ++vi) {
01758 nassertv(!index.is_at_end());
01759 unsigned int vertex = index.get_data1i();
01760 cdata->_min_vertex = min(cdata->_min_vertex, vertex);
01761 cdata->_max_vertex = max(cdata->_max_vertex, vertex);
01762 }
01763 }
01764 }
01765
01766 cdata->_got_minmax = true;
01767 }
01768
01769
01770
01771
01772
01773
01774 void GeomPrimitive::
01775 do_make_indexed(CData *cdata) {
01776 if (cdata->_vertices.is_null()) {
01777 if (gobj_cat.is_debug()) {
01778 gobj_cat.debug()
01779 << this << ".make_indexed()\n";
01780 }
01781
01782 nassertv(cdata->_num_vertices != -1);
01783 cdata->_vertices = make_index_data();
01784 GeomVertexWriter index(cdata->_vertices.get_write_pointer(), 0);
01785 index.reserve_num_rows(cdata->_num_vertices);
01786 for (int i = 0; i < cdata->_num_vertices; ++i) {
01787 index.add_data1i(i + cdata->_first_vertex);
01788 }
01789 cdata->_num_vertices = -1;
01790 }
01791 }
01792
01793
01794
01795
01796
01797
01798
01799
01800 void GeomPrimitive::
01801 consider_elevate_index_type(CData *cdata, int vertex) {
01802 switch (cdata->_index_type) {
01803 case NT_uint8:
01804 if (vertex > 0xff) {
01805 do_set_index_type(cdata, NT_uint16);
01806 }
01807 break;
01808
01809 case NT_uint16:
01810 if (vertex > 0xffff) {
01811 do_set_index_type(cdata, NT_uint32);
01812 }
01813 break;
01814
01815 case NT_uint32:
01816
01817 nassertv(vertex <= 0x7fffffff);
01818 break;
01819
01820 default:
01821 break;
01822 }
01823 }
01824
01825
01826
01827
01828
01829
01830 void GeomPrimitive::
01831 do_set_index_type(CData *cdata, GeomPrimitive::NumericType index_type) {
01832 cdata->_index_type = index_type;
01833
01834 if (gobj_cat.is_debug()) {
01835 gobj_cat.debug()
01836 << this << ".set_index_type(" << index_type << ")\n";
01837 }
01838
01839 if (!cdata->_vertices.is_null()) {
01840 CPT(GeomVertexArrayFormat) new_format = get_index_format();
01841
01842 CPT(GeomVertexArrayData) array_obj = cdata->_vertices.get_read_pointer();
01843 if (array_obj->get_array_format() != new_format) {
01844 PT(GeomVertexArrayData) new_vertices = make_index_data();
01845 new_vertices->set_num_rows(array_obj->get_num_rows());
01846
01847 GeomVertexReader from(array_obj, 0);
01848 GeomVertexWriter to(new_vertices, 0);
01849
01850 while (!from.is_at_end()) {
01851 to.set_data1i(from.get_data1i());
01852 }
01853 cdata->_vertices = new_vertices;
01854 cdata->_got_minmax = false;
01855 }
01856 }
01857 }
01858
01859
01860
01861
01862
01863
01864 PT(GeomVertexArrayData) GeomPrimitive::
01865 do_modify_vertices(GeomPrimitive::CData *cdata) {
01866 if (cdata->_vertices.is_null()) {
01867 do_make_indexed(cdata);
01868 }
01869
01870 PT(GeomVertexArrayData) vertices = cdata->_vertices.get_write_pointer();
01871
01872 cdata->_modified = Geom::get_next_modified();
01873 cdata->_got_minmax = false;
01874 return vertices;
01875 }
01876
01877
01878
01879
01880
01881
01882
01883 void GeomPrimitive::
01884 write_datagram(BamWriter *manager, Datagram &dg) {
01885 TypedWritable::write_datagram(manager, dg);
01886
01887 manager->write_cdata(dg, _cycler);
01888 }
01889
01890
01891
01892
01893
01894
01895
01896
01897 void GeomPrimitive::
01898 finalize(BamReader *manager) {
01899 const GeomVertexArrayData *vertices = get_vertices();
01900 if (vertices != (GeomVertexArrayData *)NULL) {
01901 set_usage_hint(vertices->get_usage_hint());
01902 }
01903 }
01904
01905
01906
01907
01908
01909
01910
01911
01912 void GeomPrimitive::
01913 fillin(DatagramIterator &scan, BamReader *manager) {
01914 TypedWritable::fillin(scan, manager);
01915
01916 manager->read_cdata(scan, _cycler);
01917 manager->register_finalize(this);
01918 }
01919
01920
01921
01922
01923
01924
01925 CycleData *GeomPrimitive::CData::
01926 make_copy() const {
01927 return new CData(*this);
01928 }
01929
01930
01931
01932
01933
01934
01935
01936 void GeomPrimitive::CData::
01937 write_datagram(BamWriter *manager, Datagram &dg) const {
01938 dg.add_uint8(_shade_model);
01939 dg.add_int32(_first_vertex);
01940 dg.add_int32(_num_vertices);
01941 dg.add_uint8(_index_type);
01942 dg.add_uint8(_usage_hint);
01943
01944 manager->write_pointer(dg, _vertices.get_read_pointer());
01945 WRITE_PTA(manager, dg, IPD_int::write_datagram, _ends);
01946 }
01947
01948
01949
01950
01951
01952
01953
01954
01955 int GeomPrimitive::CData::
01956 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01957 int pi = CycleData::complete_pointers(p_list, manager);
01958
01959 _vertices = DCAST(GeomVertexArrayData, p_list[pi++]);
01960
01961 if (manager->get_file_minor_ver() < 6 && !_vertices.is_null()) {
01962
01963
01964
01965 _num_vertices = -1;
01966 }
01967
01968 return pi;
01969 }
01970
01971
01972
01973
01974
01975
01976
01977
01978 void GeomPrimitive::CData::
01979 fillin(DatagramIterator &scan, BamReader *manager) {
01980 _shade_model = (ShadeModel)scan.get_uint8();
01981 _first_vertex = scan.get_int32();
01982 _num_vertices = scan.get_int32();
01983 _index_type = (NumericType)scan.get_uint8();
01984 _usage_hint = (UsageHint)scan.get_uint8();
01985
01986 manager->read_pointer(scan);
01987 READ_PTA(manager, scan, IPD_int::read_datagram, _ends);
01988
01989 _modified = Geom::get_next_modified();
01990 _got_minmax = false;
01991 }
01992
01993
01994
01995
01996
01997
01998
01999 void GeomPrimitivePipelineReader::
02000 check_minmax() const {
02001 if (!_cdata->_got_minmax) {
02002
02003
02004
02005 {
02006 #ifdef DO_PIPELINING
02007 unref_delete((CycleData *)_cdata);
02008 #endif
02009 GeomPrimitive::CDWriter fresh_cdata(((GeomPrimitive *)_object.p())->_cycler,
02010 false, _current_thread);
02011 ((GeomPrimitivePipelineReader *)this)->_cdata = fresh_cdata;
02012 #ifdef DO_PIPELINING
02013 _cdata->ref();
02014 #endif
02015
02016 if (!fresh_cdata->_got_minmax) {
02017
02018
02019 ((GeomPrimitive *)_object.p())->recompute_minmax(fresh_cdata);
02020 nassertv(fresh_cdata->_got_minmax);
02021 }
02022
02023
02024
02025
02026 }
02027 }
02028
02029 nassertv(_cdata->_got_minmax);
02030 }
02031
02032
02033
02034
02035
02036
02037 int GeomPrimitivePipelineReader::
02038 get_first_vertex() const {
02039 if (_cdata->_vertices.is_null()) {
02040 return _cdata->_first_vertex;
02041 } else if (_vertices_reader->get_num_rows() == 0) {
02042 return 0;
02043 } else {
02044 GeomVertexReader index(_cdata->_vertices.get_read_pointer(), 0);
02045 return index.get_data1i();
02046 }
02047 }
02048
02049
02050
02051
02052
02053
02054 int GeomPrimitivePipelineReader::
02055 get_vertex(int i) const {
02056 if (!_cdata->_vertices.is_null()) {
02057
02058 nassertr(i >= 0 && i < _vertices_reader->get_num_rows(), -1);
02059
02060 GeomVertexReader index(_cdata->_vertices.get_read_pointer(), 0);
02061 index.set_row_unsafe(i);
02062 return index.get_data1i();
02063
02064 } else {
02065
02066 return _cdata->_first_vertex + i;
02067 }
02068 }
02069
02070
02071
02072
02073
02074
02075 int GeomPrimitivePipelineReader::
02076 get_num_primitives() const {
02077 int num_vertices_per_primitive = _object->get_num_vertices_per_primitive();
02078
02079 if (num_vertices_per_primitive == 0) {
02080
02081
02082 return _cdata->_ends.size();
02083
02084 } else {
02085
02086
02087 return (get_num_vertices() / num_vertices_per_primitive);
02088 }
02089 }
02090
02091
02092
02093
02094
02095
02096 bool GeomPrimitivePipelineReader::
02097 check_valid(const GeomVertexDataPipelineReader *data_reader) const {
02098 return get_num_vertices() == 0 ||
02099 get_max_vertex() < data_reader->get_num_rows();
02100 }