00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "geomVertexData.h"
00016 #include "geom.h"
00017 #include "geomVertexReader.h"
00018 #include "geomVertexWriter.h"
00019 #include "geomVertexRewriter.h"
00020 #include "pStatTimer.h"
00021 #include "bamReader.h"
00022 #include "bamWriter.h"
00023 #include "pset.h"
00024 #include "indent.h"
00025
00026 TypeHandle GeomVertexData::_type_handle;
00027 TypeHandle GeomVertexData::CDataCache::_type_handle;
00028 TypeHandle GeomVertexData::CacheEntry::_type_handle;
00029 TypeHandle GeomVertexData::CData::_type_handle;
00030 TypeHandle GeomVertexDataPipelineReader::_type_handle;
00031 TypeHandle GeomVertexDataPipelineWriter::_type_handle;
00032
00033 PStatCollector GeomVertexData::_convert_pcollector("*:Munge:Convert");
00034 PStatCollector GeomVertexData::_scale_color_pcollector("*:Munge:Scale color");
00035 PStatCollector GeomVertexData::_set_color_pcollector("*:Munge:Set color");
00036 PStatCollector GeomVertexData::_animation_pcollector("*:Animation");
00037
00038
00039
00040
00041
00042
00043
00044
00045 GeomVertexData::
00046 GeomVertexData() :
00047 _char_pcollector(_animation_pcollector, "unnamed"),
00048 _skinning_pcollector(_char_pcollector, "Skinning"),
00049 _morphs_pcollector(_char_pcollector, "Morphs"),
00050 _blends_pcollector(_char_pcollector, "Calc blends")
00051 {
00052 }
00053
00054
00055
00056
00057
00058
00059 PT(CopyOnWriteObject) GeomVertexData::
00060 make_cow_copy() {
00061 return new GeomVertexData(*this);
00062 }
00063
00064
00065
00066
00067
00068
00069 GeomVertexData::
00070 GeomVertexData(const string &name,
00071 const GeomVertexFormat *format,
00072 GeomVertexData::UsageHint usage_hint) :
00073 _name(name),
00074 _char_pcollector(PStatCollector(_animation_pcollector, name)),
00075 _skinning_pcollector(_char_pcollector, "Skinning"),
00076 _morphs_pcollector(_char_pcollector, "Morphs"),
00077 _blends_pcollector(_char_pcollector, "Calc blends")
00078 {
00079 nassertv(format->is_registered());
00080
00081
00082
00083 OPEN_ITERATE_ALL_STAGES(_cycler) {
00084 CDStageWriter cdata(_cycler, pipeline_stage);
00085 cdata->_format = format;
00086 cdata->_usage_hint = usage_hint;
00087 int num_arrays = format->get_num_arrays();
00088 for (int i = 0; i < num_arrays; i++) {
00089 PT(GeomVertexArrayData) array = new GeomVertexArrayData
00090 (format->get_array(i), usage_hint);
00091 cdata->_arrays.push_back(array.p());
00092 }
00093 }
00094 CLOSE_ITERATE_ALL_STAGES(_cycler);
00095 }
00096
00097
00098
00099
00100
00101
00102 GeomVertexData::
00103 GeomVertexData(const GeomVertexData ©) :
00104 CopyOnWriteObject(copy),
00105 _name(copy._name),
00106 _cycler(copy._cycler),
00107 _char_pcollector(copy._char_pcollector),
00108 _skinning_pcollector(copy._skinning_pcollector),
00109 _morphs_pcollector(copy._morphs_pcollector),
00110 _blends_pcollector(copy._blends_pcollector)
00111 {
00112 OPEN_ITERATE_ALL_STAGES(_cycler) {
00113 CDStageWriter cdata(_cycler, pipeline_stage);
00114
00115 cdata->_animated_vertices = NULL;
00116 cdata->_animated_vertices_modified = UpdateSeq();
00117 }
00118 CLOSE_ITERATE_ALL_STAGES(_cycler);
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 GeomVertexData::
00130 GeomVertexData(const GeomVertexData ©,
00131 const GeomVertexFormat *format) :
00132 CopyOnWriteObject(copy),
00133 _name(copy._name),
00134 _cycler(copy._cycler),
00135 _char_pcollector(copy._char_pcollector),
00136 _skinning_pcollector(copy._skinning_pcollector),
00137 _morphs_pcollector(copy._morphs_pcollector),
00138 _blends_pcollector(copy._blends_pcollector)
00139 {
00140 nassertv(format->is_registered());
00141
00142
00143 OPEN_ITERATE_ALL_STAGES(_cycler) {
00144 CDStageWriter cdata(_cycler, pipeline_stage);
00145
00146 UsageHint usage_hint = cdata->_usage_hint;
00147 cdata->_arrays.clear();
00148 cdata->_format = format;
00149 int num_arrays = format->get_num_arrays();
00150 for (int i = 0; i < num_arrays; i++) {
00151 PT(GeomVertexArrayData) array = new GeomVertexArrayData
00152 (format->get_array(i), usage_hint);
00153 cdata->_arrays.push_back(array.p());
00154 }
00155
00156
00157 cdata->_animated_vertices = NULL;
00158 cdata->_animated_vertices_modified = UpdateSeq();
00159 }
00160 CLOSE_ITERATE_ALL_STAGES(_cycler);
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 void GeomVertexData::
00172 operator = (const GeomVertexData ©) {
00173 CopyOnWriteObject::operator = (copy);
00174
00175 clear_cache();
00176
00177 _name = copy._name;
00178 _cycler = copy._cycler;
00179 _char_pcollector = copy._char_pcollector;
00180 _skinning_pcollector = copy._skinning_pcollector;
00181 _morphs_pcollector = copy._morphs_pcollector;
00182 _blends_pcollector = copy._blends_pcollector;
00183
00184 OPEN_ITERATE_ALL_STAGES(_cycler) {
00185 CDStageWriter cdata(_cycler, pipeline_stage);
00186 cdata->_modified = Geom::get_next_modified();
00187 cdata->_animated_vertices = NULL;
00188 cdata->_animated_vertices_modified = UpdateSeq();
00189 }
00190 CLOSE_ITERATE_ALL_STAGES(_cycler);
00191 }
00192
00193
00194
00195
00196
00197
00198 GeomVertexData::
00199 ~GeomVertexData() {
00200 clear_cache();
00201 }
00202
00203
00204
00205
00206
00207
00208
00209 int GeomVertexData::
00210 compare_to(const GeomVertexData &other) const {
00211 CDReader cdata(_cycler);
00212 CDReader other_cdata(other._cycler);
00213
00214 if (cdata->_usage_hint != other_cdata->_usage_hint) {
00215 return (int)cdata->_usage_hint - (int)other_cdata->_usage_hint;
00216 }
00217 if (cdata->_format != other_cdata->_format) {
00218 return cdata->_format < other_cdata->_format ? -1 : 1;
00219 }
00220 if (cdata->_transform_table != other_cdata->_transform_table) {
00221 return cdata->_transform_table < other_cdata->_transform_table ? -1 : 1;
00222 }
00223 if (cdata->_transform_blend_table != other_cdata->_transform_blend_table) {
00224 return cdata->_transform_blend_table < other_cdata->_transform_blend_table ? -1 : 1;
00225 }
00226 if (cdata->_slider_table != other_cdata->_slider_table) {
00227 return cdata->_slider_table < other_cdata->_slider_table ? -1 : 1;
00228 }
00229 if (cdata->_arrays.size() != other_cdata->_arrays.size()) {
00230 return (int)cdata->_arrays.size() - (int)other_cdata->_arrays.size();
00231 }
00232 for (size_t i = 0; i < cdata->_arrays.size(); ++i) {
00233 if (cdata->_arrays[i] != other_cdata->_arrays[i]) {
00234 return cdata->_arrays[i] < other_cdata->_arrays[i] ? -1 : 1;
00235 }
00236 }
00237
00238 return 0;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 void GeomVertexData::
00248 set_name(const string &name) {
00249 _name = name;
00250 _char_pcollector = PStatCollector(_animation_pcollector, name);
00251 _skinning_pcollector = PStatCollector(_char_pcollector, "Skinning");
00252 _morphs_pcollector = PStatCollector(_char_pcollector, "Morphs");
00253 _blends_pcollector = PStatCollector(_char_pcollector, "Calc blends");
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 void GeomVertexData::
00268 set_usage_hint(GeomVertexData::UsageHint usage_hint) {
00269 CDWriter cdata(_cycler, true);
00270 cdata->_usage_hint = usage_hint;
00271
00272 Arrays::iterator ai;
00273 for (ai = cdata->_arrays.begin();
00274 ai != cdata->_arrays.end();
00275 ++ai) {
00276 PT(GeomVertexArrayData) array_obj = (*ai).get_write_pointer();
00277 array_obj->set_usage_hint(usage_hint);
00278 }
00279 clear_cache_stage();
00280 cdata->_modified = Geom::get_next_modified();
00281 cdata->_animated_vertices_modified = UpdateSeq();
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 void GeomVertexData::
00296 set_format(const GeomVertexFormat *format) {
00297 Thread *current_thread = Thread::get_current_thread();
00298 nassertv(format->is_registered());
00299
00300 CDLockedReader cdata(_cycler, current_thread);
00301
00302 if (format == cdata->_format) {
00303
00304 return;
00305 }
00306
00307 CDWriter cdataw(_cycler, cdata, true);
00308
00309
00310 CPT(GeomVertexData) orig_data = new GeomVertexData(*this);
00311
00312
00313
00314 cdataw->_format = format;
00315
00316 UsageHint usage_hint = cdataw->_usage_hint;
00317 cdataw->_arrays.clear();
00318 int num_arrays = cdataw->_format->get_num_arrays();
00319 for (int i = 0; i < num_arrays; i++) {
00320 PT(GeomVertexArrayData) array = new GeomVertexArrayData
00321 (cdataw->_format->get_array(i), usage_hint);
00322 cdataw->_arrays.push_back(array.p());
00323 }
00324
00325
00326
00327 copy_from(orig_data, false, current_thread);
00328
00329 clear_cache_stage();
00330 cdataw->_modified = Geom::get_next_modified();
00331 cdataw->_animated_vertices.clear();
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 void GeomVertexData::
00346 clear_rows() {
00347 Thread *current_thread = Thread::get_current_thread();
00348 CDWriter cdata(_cycler, true, current_thread);
00349 nassertv(cdata->_format->get_num_arrays() == (int)cdata->_arrays.size());
00350
00351 Arrays::iterator ai;
00352 for (ai = cdata->_arrays.begin();
00353 ai != cdata->_arrays.end();
00354 ++ai) {
00355 PT(GeomVertexArrayData) array_obj = (*ai).get_write_pointer();
00356 array_obj->clear_rows();
00357 }
00358 clear_cache_stage();
00359 cdata->_modified = Geom::get_next_modified();
00360 cdata->_animated_vertices.clear();
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 void GeomVertexData::
00377 set_transform_table(const TransformTable *table) {
00378 Thread *current_thread = Thread::get_current_thread();
00379 nassertv(table == (TransformTable *)NULL || table->is_registered());
00380
00381 CDWriter cdata(_cycler, true, current_thread);
00382 cdata->_transform_table = (TransformTable *)table;
00383 clear_cache_stage();
00384 cdata->_modified = Geom::get_next_modified();
00385 cdata->_animated_vertices_modified = UpdateSeq();
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 PT(TransformBlendTable) GeomVertexData::
00401 modify_transform_blend_table() {
00402 CDWriter cdata(_cycler, true);
00403
00404 clear_cache_stage();
00405 cdata->_modified = Geom::get_next_modified();
00406 cdata->_animated_vertices_modified = UpdateSeq();
00407
00408 return cdata->_transform_blend_table.get_write_pointer();
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 void GeomVertexData::
00425 set_transform_blend_table(const TransformBlendTable *table) {
00426 CDWriter cdata(_cycler, true);
00427 cdata->_transform_blend_table = (TransformBlendTable *)table;
00428 clear_cache_stage();
00429 cdata->_modified = Geom::get_next_modified();
00430 cdata->_animated_vertices_modified = UpdateSeq();
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 void GeomVertexData::
00449 set_slider_table(const SliderTable *table) {
00450 nassertv(table == (SliderTable *)NULL || table->is_registered());
00451
00452 CDWriter cdata(_cycler, true);
00453 cdata->_slider_table = (SliderTable *)table;
00454 clear_cache_stage();
00455 cdata->_modified = Geom::get_next_modified();
00456 cdata->_animated_vertices_modified = UpdateSeq();
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466 bool GeomVertexData::
00467 request_resident() const {
00468 CDReader cdata(_cycler);
00469
00470 bool resident = true;
00471
00472 Arrays::const_iterator ai;
00473 for (ai = cdata->_arrays.begin();
00474 ai != cdata->_arrays.end();
00475 ++ai) {
00476 if (!(*ai).get_read_pointer()->request_resident()) {
00477 resident = false;
00478 }
00479 }
00480
00481 return resident;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 void GeomVertexData::
00505 copy_from(const GeomVertexData *source, bool keep_data_objects,
00506 Thread *current_thread) {
00507 const GeomVertexFormat *source_format = source->get_format();
00508 const GeomVertexFormat *dest_format = get_format();
00509
00510 int num_rows = source->get_num_rows();
00511 int num_arrays = source_format->get_num_arrays();
00512 int source_i;
00513
00514
00515
00516 pset<int> done_arrays;
00517
00518 for (source_i = 0; source_i < num_arrays; ++source_i) {
00519 const GeomVertexArrayFormat *source_array_format =
00520 source_format->get_array(source_i);
00521
00522 bool array_done = false;
00523
00524 int dest_num_arrays = dest_format->get_num_arrays();
00525 for (int dest_i = 0;
00526 dest_i < dest_num_arrays && !array_done;
00527 ++dest_i) {
00528 const GeomVertexArrayFormat *dest_array_format =
00529 dest_format->get_array(dest_i);
00530 if (dest_array_format->is_data_subset_of(*source_array_format)) {
00531
00532 if (keep_data_objects) {
00533
00534
00535 PT(GeomVertexArrayData) dest_data = modify_array(dest_i);
00536 CPT(GeomVertexArrayData) source_data = source->get_array(source_i);
00537 dest_data->modify_handle()->copy_data_from(source_data->get_handle());
00538 } else {
00539
00540 if (get_array(dest_i) != source->get_array(source_i)) {
00541 set_array(dest_i, source->get_array(source_i));
00542 }
00543 }
00544
00545 array_done = true;
00546 done_arrays.insert(dest_i);
00547 }
00548 }
00549 }
00550
00551
00552 reserve_num_rows(num_rows);
00553 set_num_rows(num_rows);
00554
00555
00556 for (source_i = 0; source_i < num_arrays; ++source_i) {
00557 CPT(GeomVertexArrayData) array_obj = source->get_array(source_i);
00558 CPT(GeomVertexArrayDataHandle) array_handle = array_obj->get_handle();
00559 const unsigned char *array_data = array_handle->get_read_pointer(true);
00560 const GeomVertexArrayFormat *source_array_format = source_format->get_array(source_i);
00561 int num_columns = source_array_format->get_num_columns();
00562 for (int di = 0; di < num_columns; ++di) {
00563 const GeomVertexColumn *source_column = source_array_format->get_column(di);
00564
00565 int dest_i = dest_format->get_array_with(source_column->get_name());
00566 if (dest_i >= 0 && done_arrays.count(dest_i) == 0) {
00567
00568 const GeomVertexArrayFormat *dest_array_format =
00569 dest_format->get_array(dest_i);
00570 const GeomVertexColumn *dest_column =
00571 dest_array_format->get_column(source_column->get_name());
00572 nassertv(dest_column != (const GeomVertexColumn *)NULL);
00573
00574 if (dest_column->is_bytewise_equivalent(*source_column)) {
00575
00576 PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
00577 PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
00578 unsigned char *dest_array_data = dest_handle->get_write_pointer();
00579
00580 bytewise_copy(dest_array_data + dest_column->get_start(),
00581 dest_array_format->get_stride(),
00582 array_data + source_column->get_start(), source_array_format->get_stride(),
00583 source_column, num_rows);
00584
00585 } else if (dest_column->is_packed_argb() &&
00586 source_column->is_uint8_rgba()) {
00587
00588 PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
00589 PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
00590 unsigned char *dest_array_data = dest_handle->get_write_pointer();
00591
00592 uint8_rgba_to_packed_argb
00593 (dest_array_data + dest_column->get_start(),
00594 dest_array_format->get_stride(),
00595 array_data + source_column->get_start(), source_array_format->get_stride(),
00596 num_rows);
00597
00598 } else if (dest_column->is_uint8_rgba() &&
00599 source_column->is_packed_argb()) {
00600
00601
00602 PT(GeomVertexArrayData) dest_array_obj = modify_array(dest_i);
00603 PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
00604 unsigned char *dest_array_data = dest_handle->get_write_pointer();
00605
00606 packed_argb_to_uint8_rgba
00607 (dest_array_data + dest_column->get_start(),
00608 dest_array_format->get_stride(),
00609 array_data + source_column->get_start(), source_array_format->get_stride(),
00610 num_rows);
00611
00612 } else {
00613
00614 if (gobj_cat.is_debug()) {
00615 gobj_cat.debug()
00616 << "generic copy " << *dest_column << " from "
00617 << *source_column << "\n";
00618 }
00619 GeomVertexWriter to(this);
00620 to.set_column(dest_i, dest_column);
00621 GeomVertexReader from(source);
00622 from.set_column(source_i, source_column);
00623
00624 while (!from.is_at_end()) {
00625 to.set_data4(from.get_data4());
00626 }
00627 }
00628 }
00629 }
00630 }
00631
00632
00633 const GeomVertexAnimationSpec &source_animation = source_format->get_animation();
00634 const GeomVertexAnimationSpec &dest_animation = dest_format->get_animation();
00635 if (source_animation != dest_animation) {
00636 if (dest_animation.get_animation_type() == AT_hardware) {
00637
00638
00639 CPT(TransformBlendTable) blend_table = source->get_transform_blend_table();
00640 if (blend_table != (TransformBlendTable *)NULL) {
00641 PT(TransformTable) transform_table = new TransformTable;
00642 TransformMap already_added;
00643
00644 if (dest_animation.get_indexed_transforms()) {
00645
00646
00647 GeomVertexWriter weight(this, InternalName::get_transform_weight());
00648 GeomVertexWriter index(this, InternalName::get_transform_index());
00649 GeomVertexReader from(source, InternalName::get_transform_blend());
00650
00651 while (!from.is_at_end()) {
00652 const TransformBlend &blend = blend_table->get_blend(from.get_data1i());
00653 LVecBase4 weights = LVecBase4::zero();
00654 int indices[4] = {0, 0, 0, 0};
00655 nassertv(blend.get_num_transforms() <= 4);
00656
00657 for (int i = 0; i < blend.get_num_transforms(); i++) {
00658 weights[i] = blend.get_weight(i);
00659 indices[i] = add_transform(transform_table, blend.get_transform(i),
00660 already_added);
00661 }
00662 if (weight.has_column()) {
00663 weight.set_data4(weights);
00664 }
00665 index.set_data4i(indices);
00666 }
00667 } else {
00668
00669
00670 GeomVertexWriter weight(this, InternalName::get_transform_weight());
00671 GeomVertexReader from(source, InternalName::get_transform_blend());
00672
00673 while (!from.is_at_end()) {
00674 const TransformBlend &blend = blend_table->get_blend(from.get_data1i());
00675 LVecBase4 weights = LVecBase4::zero();
00676
00677 for (int i = 0; i < blend.get_num_transforms(); i++) {
00678 int index = add_transform(transform_table, blend.get_transform(i),
00679 already_added);
00680 nassertv(index <= 4);
00681 weights[index] = blend.get_weight(i);
00682 }
00683 if (weight.has_column()) {
00684 weight.set_data4(weights);
00685 }
00686 }
00687 }
00688
00689 clear_transform_blend_table();
00690 set_transform_table(TransformTable::register_table(transform_table));
00691 }
00692 }
00693 }
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 void GeomVertexData::
00709 copy_row_from(int dest_row, const GeomVertexData *source,
00710 int source_row, Thread *current_thread) {
00711 const GeomVertexFormat *source_format = source->get_format();
00712 const GeomVertexFormat *dest_format = get_format();
00713 nassertv(source_format == dest_format);
00714 nassertv(source_row >= 0 && source_row < source->get_num_rows());
00715
00716 if (dest_row >= get_num_rows()) {
00717
00718 set_num_rows(dest_row + 1);
00719 }
00720
00721 int num_arrays = source_format->get_num_arrays();
00722
00723 for (int i = 0; i < num_arrays; ++i) {
00724 PT(GeomVertexArrayData) dest_array_obj = modify_array(i);
00725 PT(GeomVertexArrayDataHandle) dest_handle = dest_array_obj->modify_handle();
00726 unsigned char *dest_array_data = dest_handle->get_write_pointer();
00727
00728 CPT(GeomVertexArrayData) source_array_obj = source->get_array(i);
00729 CPT(GeomVertexArrayDataHandle) source_array_handle = source_array_obj->get_handle();
00730 const unsigned char *source_array_data = source_array_handle->get_read_pointer(true);
00731
00732 const GeomVertexArrayFormat *array_format = source_format->get_array(i);
00733 int stride = array_format->get_stride();
00734
00735 memcpy(dest_array_data + stride * dest_row,
00736 source_array_data + stride * source_row,
00737 stride);
00738 }
00739 }
00740
00741
00742
00743
00744
00745
00746
00747
00748 CPT(GeomVertexData) GeomVertexData::
00749 convert_to(const GeomVertexFormat *new_format) const {
00750 Thread *current_thread = Thread::get_current_thread();
00751
00752 if (new_format == get_format()) {
00753
00754 return this;
00755 }
00756
00757
00758
00759 PT(CacheEntry) entry;
00760
00761 CacheKey key(new_format);
00762
00763 _cache_lock.acquire();
00764 Cache::const_iterator ci = _cache.find(&key);
00765 if (ci == _cache.end()) {
00766 _cache_lock.release();
00767
00768 } else {
00769 entry = (*ci).second;
00770 _cache_lock.release();
00771 nassertr(entry->_source == this, NULL);
00772
00773
00774
00775
00776 entry->refresh(current_thread);
00777
00778 CDCacheReader cdata(entry->_cycler);
00779 if (cdata->_result != (GeomVertexData *)NULL) {
00780 return cdata->_result;
00781 }
00782
00783
00784
00785
00786
00787 }
00788
00789
00790 if (gobj_cat.is_debug()) {
00791 gobj_cat.debug()
00792 << "Converting " << get_num_rows() << " rows from " << *get_format()
00793 << " to " << *new_format << "\n";
00794 }
00795 PStatTimer timer(_convert_pcollector);
00796
00797 PT(GeomVertexData) new_data =
00798 new GeomVertexData(get_name(), new_format, get_usage_hint());
00799 new_data->set_transform_blend_table(get_transform_blend_table());
00800 new_data->set_slider_table(get_slider_table());
00801
00802 new_data->copy_from(this, false);
00803
00804
00805 if (entry == (CacheEntry *)NULL) {
00806
00807 entry = new CacheEntry((GeomVertexData *)this, new_format);
00808 {
00809 LightMutexHolder holder(_cache_lock);
00810 bool inserted = ((GeomVertexData *)this)->_cache.insert(Cache::value_type(&entry->_key, entry)).second;
00811 if (!inserted) {
00812
00813
00814 return new_data;
00815 }
00816 }
00817
00818
00819
00820
00821 entry->record(current_thread);
00822 }
00823
00824
00825 CDCacheWriter cdata(entry->_cycler, true, current_thread);
00826 cdata->_result = new_data;
00827
00828 return new_data;
00829 }
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 CPT(GeomVertexData) GeomVertexData::
00842 scale_color(const LVecBase4 &color_scale) const {
00843 const GeomVertexColumn *old_column =
00844 get_format()->get_column(InternalName::get_color());
00845 if (old_column == (GeomVertexColumn *)NULL) {
00846 return this;
00847 }
00848
00849 PT(GeomVertexData) new_data = new GeomVertexData(*this);
00850 GeomVertexRewriter data(new_data, InternalName::get_color());
00851 while (!data.is_at_end()) {
00852 LColor color = data.get_data4();
00853 data.set_data4(color[0] * color_scale[0],
00854 color[1] * color_scale[1],
00855 color[2] * color_scale[2],
00856 color[3] * color_scale[3]);
00857 }
00858
00859 return new_data;
00860 }
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 CPT(GeomVertexData) GeomVertexData::
00873 scale_color(const LVecBase4 &color_scale, int num_components,
00874 GeomVertexData::NumericType numeric_type,
00875 GeomVertexData::Contents contents) const {
00876 int old_color_array = get_format()->get_array_with(InternalName::get_color());
00877 if (old_color_array == -1) {
00878
00879 return set_color(color_scale, num_components, numeric_type, contents);
00880 }
00881
00882 int num_rows = get_num_rows();
00883
00884 if (gobj_cat.is_debug()) {
00885 gobj_cat.debug()
00886 << "Scaling color for " << num_rows << " vertices by "
00887 << color_scale << ".\n";
00888 }
00889 PStatTimer timer(_scale_color_pcollector);
00890
00891 PT(GeomVertexData) new_data = replace_column
00892 (InternalName::get_color(), num_components, numeric_type, contents);
00893
00894
00895 GeomVertexWriter to(new_data, InternalName::get_color());
00896 GeomVertexReader from(this, InternalName::get_color());
00897
00898 for (int i = 0; i < num_rows; i++) {
00899 LColor color = from.get_data4();
00900 to.set_data4(color[0] * color_scale[0],
00901 color[1] * color_scale[1],
00902 color[2] * color_scale[2],
00903 color[3] * color_scale[3]);
00904 }
00905
00906 return new_data;
00907 }
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918 CPT(GeomVertexData) GeomVertexData::
00919 set_color(const LColor &color) const {
00920 const GeomVertexColumn *old_column =
00921 get_format()->get_column(InternalName::get_color());
00922 if (old_column == (GeomVertexColumn *)NULL) {
00923 return this;
00924 }
00925
00926 PT(GeomVertexData) new_data = new GeomVertexData(*this);
00927 GeomVertexWriter to(new_data, InternalName::get_color());
00928 while (!to.is_at_end()) {
00929 to.set_data4(color);
00930 }
00931
00932 return new_data;
00933 }
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 CPT(GeomVertexData) GeomVertexData::
00946 set_color(const LColor &color, int num_components,
00947 GeomVertexData::NumericType numeric_type,
00948 GeomVertexData::Contents contents) const {
00949 if (gobj_cat.is_debug()) {
00950 gobj_cat.debug()
00951 << "Setting color for " << get_num_rows() << " vertices to "
00952 << color << ".\n";
00953 }
00954 PStatTimer timer(_set_color_pcollector);
00955
00956 PT(GeomVertexData) new_data = replace_column
00957 (InternalName::get_color(), num_components, numeric_type, contents);
00958
00959
00960 GeomVertexWriter to(new_data, InternalName::get_color());
00961 while (!to.is_at_end()) {
00962 to.set_data4(color);
00963 }
00964
00965 return new_data;
00966 }
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 CPT(GeomVertexData) GeomVertexData::
00980 reverse_normals() const {
00981 const GeomVertexColumn *old_column =
00982 get_format()->get_column(InternalName::get_normal());
00983 if (old_column == (GeomVertexColumn *)NULL) {
00984 return this;
00985 }
00986
00987 PT(GeomVertexData) new_data = new GeomVertexData(*this);
00988 GeomVertexRewriter to(new_data, InternalName::get_normal());
00989 while (!to.is_at_end()) {
00990 to.set_data3(-to.get_data3());
00991 }
00992
00993 return new_data;
00994 }
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 CPT(GeomVertexData) GeomVertexData::
01021 animate_vertices(bool force, Thread *current_thread) const {
01022 #ifdef DO_PIPELINING
01023 {
01024
01025
01026
01027 CDReader cdata(_cycler, current_thread);
01028 if (cdata->_format->get_animation().get_animation_type() != AT_panda) {
01029 return this;
01030 }
01031 }
01032 #endif // DO_PIPELINING
01033
01034 PStatTimer timer(((GeomVertexData *)this)->_char_pcollector, current_thread);
01035
01036
01037
01038
01039 CDLockedReader cdata(_cycler, current_thread);
01040 if (cdata->_format->get_animation().get_animation_type() != AT_panda) {
01041 return this;
01042 }
01043
01044 UpdateSeq modified;
01045 {
01046 PStatTimer timer2(((GeomVertexData *)this)->_blends_pcollector, current_thread);
01047 if (!cdata->_transform_blend_table.is_null()) {
01048 if (cdata->_slider_table != (SliderTable *)NULL) {
01049 modified =
01050 max(cdata->_transform_blend_table.get_read_pointer()->get_modified(current_thread),
01051 cdata->_slider_table->get_modified(current_thread));
01052 } else {
01053 modified = cdata->_transform_blend_table.get_read_pointer()->get_modified(current_thread);
01054 }
01055
01056 } else if (cdata->_slider_table != (SliderTable *)NULL) {
01057 modified = cdata->_slider_table->get_modified(current_thread);
01058
01059 } else {
01060
01061
01062 return this;
01063 }
01064 }
01065
01066 if (cdata->_animated_vertices_modified == modified &&
01067 cdata->_animated_vertices != (GeomVertexData *)NULL) {
01068
01069 return cdata->_animated_vertices;
01070 }
01071
01072 if (!force && !request_resident()) {
01073
01074
01075 if (cdata->_animated_vertices != (GeomVertexData *)NULL) {
01076 return cdata->_animated_vertices;
01077 }
01078 return this;
01079 }
01080
01081 CDWriter cdataw(((GeomVertexData *)this)->_cycler, cdata, false);
01082 cdataw->_animated_vertices_modified = modified;
01083 ((GeomVertexData *)this)->update_animated_vertices(cdataw, current_thread);
01084
01085 return cdataw->_animated_vertices;
01086 }
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 void GeomVertexData::
01098 clear_animated_vertices() {
01099 CDWriter cdata(_cycler, true);
01100 cdata->_animated_vertices_modified.clear();
01101 cdata->_animated_vertices.clear();
01102 }
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113 void GeomVertexData::
01114 transform_vertices(const LMatrix4 &mat) {
01115 transform_vertices(mat, 0, get_num_rows());
01116 }
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126 void GeomVertexData::
01127 transform_vertices(const LMatrix4 &mat, int begin_row, int end_row) {
01128 if (end_row <= begin_row) {
01129
01130 return;
01131 }
01132
01133 const GeomVertexFormat *format = get_format();
01134
01135 int ci;
01136 for (ci = 0; ci < format->get_num_points(); ci++) {
01137 GeomVertexRewriter data(this, format->get_point(ci));
01138 do_transform_point_column(format, data, mat, begin_row, end_row);
01139 }
01140
01141 for (ci = 0; ci < format->get_num_vectors(); ci++) {
01142 GeomVertexRewriter data(this, format->get_vector(ci));
01143 do_transform_vector_column(format, data, mat, begin_row, end_row);
01144 }
01145 }
01146
01147
01148
01149
01150
01151
01152 void GeomVertexData::
01153 bytewise_copy(unsigned char *to, int to_stride,
01154 const unsigned char *from, int from_stride,
01155 const GeomVertexColumn *from_type,
01156 int num_records) {
01157 if (gobj_cat.is_debug()) {
01158 gobj_cat.debug()
01159 << "bytewise_copy(" << (void *)to << ", " << to_stride
01160 << ", " << (const void *)from << ", " << from_stride
01161 << ", " << *from_type << ", " << num_records << ")\n";
01162 }
01163 if (to_stride == from_type->get_total_bytes() &&
01164 from_stride == from_type->get_total_bytes()) {
01165
01166
01167 memcpy(to, from, num_records * from_type->get_total_bytes());
01168
01169 } else {
01170
01171
01172 while (num_records > 0) {
01173 memcpy(to, from, from_type->get_total_bytes());
01174 to += to_stride;
01175 from += from_stride;
01176 num_records--;
01177 }
01178 }
01179 }
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195 PT(GeomVertexData) GeomVertexData::
01196 replace_column(InternalName *name, int num_components,
01197 GeomVertexData::NumericType numeric_type,
01198 GeomVertexData::Contents contents) const {
01199 CDReader cdata(_cycler);
01200 PT(GeomVertexFormat) new_format = new GeomVertexFormat(*cdata->_format);
01201
01202
01203 bool removed_type_array = false;
01204 int old_type_array = cdata->_format->get_array_with(name);
01205 if (old_type_array != -1) {
01206 GeomVertexArrayFormat *array_format = new_format->modify_array(old_type_array);
01207 if (array_format->get_num_columns() == 1) {
01208
01209
01210 new_format->remove_array(old_type_array);
01211 removed_type_array = true;
01212
01213 } else {
01214
01215
01216 array_format->remove_column(name);
01217 }
01218 }
01219
01220
01221 int new_type_array = -1;
01222 if (num_components != 0) {
01223 PT(GeomVertexArrayFormat) type_array_format =
01224 new GeomVertexArrayFormat(name, num_components, numeric_type, contents);
01225 new_type_array = new_format->add_array(type_array_format);
01226 }
01227
01228 CPT(GeomVertexFormat) format =
01229 GeomVertexFormat::register_format(new_format);
01230
01231 if (gobj_cat.is_debug()) {
01232 gobj_cat.debug()
01233 << "Replacing data type " << *name << "; converting "
01234 << get_num_rows() << " rows from "
01235 << *cdata->_format << " to " << *format << "\n";
01236 }
01237
01238 PT(GeomVertexData) new_data = new GeomVertexData(*this, format);
01239
01240 int j = 0;
01241 int num_arrays = get_num_arrays();
01242 for (int i = 0; i < num_arrays; ++i) {
01243 if (i == old_type_array) {
01244 if (!removed_type_array) {
01245
01246
01247 new_data->set_array(j, get_array(i));
01248 ++j;
01249 }
01250
01251 } else {
01252
01253 new_data->set_array(j, get_array(i));
01254 ++j;
01255 }
01256 }
01257
01258 if (new_type_array != -1) {
01259 nassertr(j == new_type_array, new_data);
01260
01261
01262
01263 PT(GeomVertexArrayData) new_array = new GeomVertexArrayData
01264 (format->get_array(j), get_usage_hint());
01265 new_array->set_num_rows(get_num_rows());
01266 new_data->set_array(j, new_array);
01267 }
01268
01269 return new_data;
01270 }
01271
01272
01273
01274
01275
01276
01277 void GeomVertexData::
01278 output(ostream &out) const {
01279 if (!get_name().empty()) {
01280 out << get_name() << " ";
01281 }
01282 out << get_num_rows() << " rows: " << *get_format();
01283 }
01284
01285
01286
01287
01288
01289
01290 void GeomVertexData::
01291 write(ostream &out, int indent_level) const {
01292 if (!get_name().empty()) {
01293 indent(out, indent_level) << get_name() << "\n";
01294 }
01295 get_format()->write_with_data(out, indent_level + 2, this);
01296 CPT(TransformBlendTable) table = get_transform_blend_table();
01297 if (table != (TransformBlendTable *)NULL) {
01298 indent(out, indent_level)
01299 << "Transform blend table:\n";
01300 table->write(out, indent_level + 2);
01301 }
01302 }
01303
01304
01305
01306
01307
01308
01309
01310 void GeomVertexData::
01311 describe_vertex(ostream &out, int row) const {
01312 nassertv_always(row >= 0 && row < get_num_rows());
01313
01314 out << "Vertex " << row << ":\n";
01315
01316 GeomVertexReader reader(this);
01317 reader.set_row_unsafe(row);
01318 const GeomVertexFormat *format = get_format();
01319
01320 const TransformBlendTable *tb_table = NULL;
01321 if (format->get_animation().get_animation_type() == AT_panda) {
01322 tb_table = get_transform_blend_table();
01323 }
01324
01325 int num_columns = format->get_num_columns();
01326 for (int ci = 0; ci < num_columns; ++ci) {
01327 int ai = format->get_array_with(ci);
01328 const GeomVertexColumn *column = format->get_column(ci);
01329 reader.set_column(ai, column);
01330
01331 int num_values = min(column->get_num_values(), 4);
01332 const LVecBase4 &d = reader.get_data4();
01333
01334 out << " " << *column->get_name();
01335 for (int v = 0; v < num_values; v++) {
01336 out << " " << d[v];
01337 }
01338 out << "\n";
01339
01340 if (column->get_name() == InternalName::get_transform_blend() &&
01341 tb_table != NULL) {
01342
01343
01344 reader.set_column(ai, column);
01345 int bi = reader.get_data1i();
01346 if (bi >= 0 && bi < tb_table->get_num_blends()) {
01347 const TransformBlend &blend = tb_table->get_blend(bi);
01348 out << " " << blend << "\n";
01349 }
01350 }
01351 }
01352
01353
01354 out << "\nraw data:\n";
01355 int num_arrays = format->get_num_arrays();
01356 for (int ai = 0; ai < num_arrays; ++ai) {
01357 const GeomVertexArrayData *array = get_array(ai);
01358 const GeomVertexArrayFormat *aformat = format->get_array(ai);
01359 nassertv(array != NULL && aformat != NULL);
01360 out << " " << *aformat << "\n";
01361 CPT(GeomVertexArrayDataHandle) handle = array->get_handle();
01362 nassertv(handle != (const GeomVertexArrayDataHandle *)NULL);
01363 const unsigned char *data = handle->get_read_pointer(true);
01364 nassertv(data != NULL);
01365 int stride = aformat->get_stride();
01366 int start = stride * row;
01367 if (data != NULL) {
01368 Datagram dg(data + start, stride);
01369 dg.dump_hex(out, 4);
01370 }
01371 }
01372 }
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 void GeomVertexData::
01386 clear_cache() {
01387 LightMutexHolder holder(_cache_lock);
01388 for (Cache::iterator ci = _cache.begin();
01389 ci != _cache.end();
01390 ++ci) {
01391 CacheEntry *entry = (*ci).second;
01392 entry->erase();
01393 }
01394 _cache.clear();
01395 }
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408 void GeomVertexData::
01409 clear_cache_stage() {
01410 LightMutexHolder holder(_cache_lock);
01411 for (Cache::iterator ci = _cache.begin();
01412 ci != _cache.end();
01413 ++ci) {
01414 CacheEntry *entry = (*ci).second;
01415 CDCacheWriter cdata(entry->_cycler);
01416 cdata->_result = NULL;
01417 }
01418 }
01419
01420
01421
01422
01423
01424
01425
01426 void GeomVertexData::
01427 packed_argb_to_uint8_rgba(unsigned char *to, int to_stride,
01428 const unsigned char *from, int from_stride,
01429 int num_records) {
01430 if (gobj_cat.is_debug()) {
01431 gobj_cat.debug()
01432 << "packed_argb_to_uint8_rgba(" << (void *)to << ", " << to_stride
01433 << ", " << (const void *)from << ", " << from_stride
01434 << ", " << num_records << ")\n";
01435 }
01436
01437 while (num_records > 0) {
01438 PN_uint32 dword = *(const PN_uint32 *)from;
01439 to[0] = unpack_abcd_b(dword);
01440 to[1] = unpack_abcd_c(dword);
01441 to[2] = unpack_abcd_d(dword);
01442 to[3] = unpack_abcd_a(dword);
01443
01444 to += to_stride;
01445 from += from_stride;
01446 num_records--;
01447 }
01448 }
01449
01450
01451
01452
01453
01454
01455
01456 void GeomVertexData::
01457 uint8_rgba_to_packed_argb(unsigned char *to, int to_stride,
01458 const unsigned char *from, int from_stride,
01459 int num_records) {
01460 if (gobj_cat.is_debug()) {
01461 gobj_cat.debug()
01462 << "uint8_rgba_to_packed_argb(" << (void *)to << ", " << to_stride
01463 << ", " << (const void *)from << ", " << from_stride
01464 << ", " << num_records << ")\n";
01465 }
01466
01467 while (num_records > 0) {
01468 *(PN_uint32 *)to = pack_abcd(from[3], from[0], from[1], from[2]);
01469
01470 to += to_stride;
01471 from += from_stride;
01472 num_records--;
01473 }
01474 }
01475
01476
01477
01478
01479
01480
01481
01482
01483 void GeomVertexData::
01484 update_animated_vertices(GeomVertexData::CData *cdata, Thread *current_thread) {
01485 PStatTimer timer(_char_pcollector, current_thread);
01486
01487 int num_rows = get_num_rows();
01488
01489 if (gobj_cat.is_debug()) {
01490 gobj_cat.debug()
01491 << "Animating " << num_rows << " vertices for " << get_name()
01492 << "\n";
01493 }
01494
01495 const GeomVertexFormat *orig_format = cdata->_format;
01496 CPT(GeomVertexFormat) new_format = orig_format;
01497
01498 if (cdata->_animated_vertices == (GeomVertexData *)NULL) {
01499 new_format = orig_format->get_post_animated_format();
01500 cdata->_animated_vertices =
01501 new GeomVertexData(get_name(), new_format,
01502 min(get_usage_hint(), UH_dynamic));
01503 }
01504 PT(GeomVertexData) new_data = cdata->_animated_vertices;
01505
01506
01507
01508
01509
01510
01511 new_data->copy_from(this, true);
01512
01513
01514 CPT(SliderTable) slider_table = cdata->_slider_table;
01515 if (slider_table != (SliderTable *)NULL) {
01516 PStatTimer timer2(_morphs_pcollector);
01517 int num_morphs = orig_format->get_num_morphs();
01518 for (int mi = 0; mi < num_morphs; mi++) {
01519 CPT(InternalName) slider_name = orig_format->get_morph_slider(mi);
01520
01521 const SparseArray &sliders = slider_table->find_sliders(slider_name);
01522 if (!sliders.is_zero()) {
01523 nassertv(!sliders.is_inverse());
01524 int num_slider_subranges = sliders.get_num_subranges();
01525 for (int sni = 0; sni < num_slider_subranges; ++sni) {
01526 int slider_begin = sliders.get_subrange_begin(sni);
01527 int slider_end = sliders.get_subrange_end(sni);
01528 for (int sn = slider_begin; sn < slider_end; ++sn) {
01529 const VertexSlider *slider = slider_table->get_slider(sn);
01530 const SparseArray &rows = slider_table->get_slider_rows(sn);
01531 nassertv(!rows.is_inverse());
01532
01533 PN_stdfloat slider_value = slider->get_slider();
01534 if (slider_value != 0.0f) {
01535 CPT(InternalName) base_name = orig_format->get_morph_base(mi);
01536 CPT(InternalName) delta_name = orig_format->get_morph_delta(mi);
01537
01538 GeomVertexRewriter data(new_data, base_name);
01539 GeomVertexReader delta(this, delta_name);
01540 int num_subranges = rows.get_num_subranges();
01541
01542 if (data.get_column()->get_num_values() == 4) {
01543 if (data.get_column()->has_homogeneous_coord()) {
01544
01545 for (int i = 0; i < num_subranges; ++i) {
01546 int begin = rows.get_subrange_begin(i);
01547 int end = rows.get_subrange_end(i);
01548 data.set_row_unsafe(begin);
01549 delta.set_row_unsafe(begin);
01550 for (int j = begin; j < end; ++j) {
01551 LPoint4 vertex = data.get_data4();
01552 LPoint3 d = delta.get_data3();
01553 d *= slider_value * vertex[3];
01554 data.set_data4(vertex[0] + d[0],
01555 vertex[1] + d[1],
01556 vertex[2] + d[2],
01557 vertex[3]);
01558 }
01559 }
01560 } else {
01561
01562 for (int i = 0; i < num_subranges; ++i) {
01563 int begin = rows.get_subrange_begin(i);
01564 int end = rows.get_subrange_end(i);
01565 data.set_row_unsafe(begin);
01566 delta.set_row_unsafe(begin);
01567 for (int j = begin; j < end; ++j) {
01568 const LPoint4 &vertex = data.get_data4();
01569 LPoint4 d = delta.get_data4();
01570 data.set_data4(vertex + d * slider_value);
01571 }
01572 }
01573 }
01574 } else {
01575
01576
01577 for (int i = 0; i < num_subranges; ++i) {
01578 int begin = rows.get_subrange_begin(i);
01579 int end = rows.get_subrange_end(i);
01580 data.set_row_unsafe(begin);
01581 delta.set_row_unsafe(begin);
01582 for (int j = begin; j < end; ++j) {
01583 const LPoint3 &vertex = data.get_data3();
01584 LPoint3 d = delta.get_data3();
01585 data.set_data3(vertex + d * slider_value);
01586 }
01587 }
01588 }
01589 }
01590 }
01591 }
01592 }
01593 }
01594 }
01595
01596
01597 CPT(TransformBlendTable) tb_table = cdata->_transform_blend_table.get_read_pointer();
01598 if (tb_table != (TransformBlendTable *)NULL) {
01599
01600
01601 {
01602 PStatTimer timer4(_blends_pcollector);
01603 int num_blends = tb_table->get_num_blends();
01604 for (int bi = 0; bi < num_blends; bi++) {
01605 tb_table->get_blend(bi).update_blend(current_thread);
01606 }
01607 }
01608
01609
01610 PStatTimer timer3(_skinning_pcollector);
01611
01612 const SparseArray &rows = tb_table->get_rows();
01613 int num_subranges = rows.get_num_subranges();
01614
01615 int blend_array_index = orig_format->get_array_with(InternalName::get_transform_blend());
01616 if (blend_array_index < 0) {
01617 gobj_cat.warning()
01618 << "Vertex data " << get_name()
01619 << " has a transform_blend_table, but no transform_blend data.\n";
01620 return;
01621 }
01622
01623 CPT(GeomVertexArrayFormat) blend_array_format = orig_format->get_array(blend_array_index);
01624
01625 if (blend_array_format->get_stride() == 2 &&
01626 blend_array_format->get_column(0)->get_component_bytes() == 2) {
01627
01628
01629 CPT(GeomVertexArrayDataHandle) blend_array_handle = cdata->_arrays[blend_array_index].get_read_pointer()->get_handle(current_thread);
01630 const unsigned short *blendt = (const unsigned short *)blend_array_handle->get_read_pointer(true);
01631
01632 int ci;
01633 for (ci = 0; ci < new_format->get_num_points(); ci++) {
01634 GeomVertexRewriter data(new_data, new_format->get_point(ci));
01635
01636 for (int i = 0; i < num_subranges; ++i) {
01637 int begin = rows.get_subrange_begin(i);
01638 int end = rows.get_subrange_end(i);
01639 nassertv(begin < end);
01640
01641 int first_vertex = begin;
01642 int first_bi = blendt[first_vertex];
01643
01644 while (first_vertex < end) {
01645
01646
01647
01648
01649
01650 int next_vertex = first_vertex;
01651 int next_bi = first_bi;
01652 ++next_vertex;
01653 while (next_vertex < end) {
01654 next_bi = blendt[next_vertex];
01655 if (next_bi != first_bi) {
01656 break;
01657 }
01658 ++next_vertex;
01659 }
01660
01661
01662
01663 LMatrix4 mat;
01664 tb_table->get_blend(first_bi).get_blend(mat, current_thread);
01665 new_data->do_transform_point_column(new_format, data, mat, first_vertex, next_vertex);
01666
01667 first_vertex = next_vertex;
01668 first_bi = next_bi;
01669 }
01670 }
01671 }
01672
01673 for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
01674 GeomVertexRewriter data(new_data, new_format->get_vector(ci));
01675
01676 for (int i = 0; i < num_subranges; ++i) {
01677 int begin = rows.get_subrange_begin(i);
01678 int end = rows.get_subrange_end(i);
01679 nassertv(begin < end);
01680
01681 int first_vertex = begin;
01682 int first_bi = blendt[first_vertex];
01683
01684 while (first_vertex < end) {
01685
01686
01687
01688
01689
01690 int next_vertex = first_vertex;
01691 int next_bi = first_bi;
01692 ++next_vertex;
01693 while (next_vertex < end) {
01694 next_bi = blendt[next_vertex];
01695 if (next_bi != first_bi) {
01696 break;
01697 }
01698 ++next_vertex;
01699 }
01700
01701
01702
01703 LMatrix4 mat;
01704 tb_table->get_blend(first_bi).get_blend(mat, current_thread);
01705 new_data->do_transform_vector_column(new_format, data, mat, first_vertex, next_vertex);
01706
01707 first_vertex = next_vertex;
01708 first_bi = next_bi;
01709 }
01710 }
01711 }
01712
01713 } else {
01714
01715
01716 GeomVertexReader blendi(this, InternalName::get_transform_blend());
01717 nassertv(blendi.has_column());
01718
01719 int ci;
01720 for (ci = 0; ci < new_format->get_num_points(); ci++) {
01721 GeomVertexRewriter data(new_data, new_format->get_point(ci));
01722
01723 for (int i = 0; i < num_subranges; ++i) {
01724 int begin = rows.get_subrange_begin(i);
01725 int end = rows.get_subrange_end(i);
01726 nassertv(begin < end);
01727 blendi.set_row_unsafe(begin);
01728
01729 int first_vertex = begin;
01730 int first_bi = blendi.get_data1i();
01731
01732 while (first_vertex < end) {
01733
01734
01735
01736
01737
01738 int next_vertex = first_vertex;
01739 int next_bi = first_bi;
01740 ++next_vertex;
01741 while (next_vertex < end) {
01742 next_bi = blendi.get_data1i();
01743 if (next_bi != first_bi) {
01744 break;
01745 }
01746 ++next_vertex;
01747 }
01748
01749
01750
01751 LMatrix4 mat;
01752 tb_table->get_blend(first_bi).get_blend(mat, current_thread);
01753 new_data->do_transform_point_column(new_format, data, mat, first_vertex, next_vertex);
01754
01755 first_vertex = next_vertex;
01756 first_bi = next_bi;
01757 }
01758 }
01759 }
01760
01761 for (ci = 0; ci < new_format->get_num_vectors(); ci++) {
01762 GeomVertexRewriter data(new_data, new_format->get_vector(ci));
01763
01764 for (int i = 0; i < num_subranges; ++i) {
01765 int begin = rows.get_subrange_begin(i);
01766 int end = rows.get_subrange_end(i);
01767 nassertv(begin != end);
01768 blendi.set_row_unsafe(begin);
01769
01770 int first_vertex = begin;
01771 int first_bi = blendi.get_data1i();
01772
01773 while (first_vertex < end) {
01774
01775
01776
01777
01778
01779 int next_vertex = first_vertex;
01780 int next_bi = first_bi;
01781 ++next_vertex;
01782 while (next_vertex < end) {
01783 next_bi = blendi.get_data1i();
01784 if (next_bi != first_bi) {
01785 break;
01786 }
01787 ++next_vertex;
01788 }
01789
01790
01791
01792 LMatrix4 mat;
01793 tb_table->get_blend(first_bi).get_blend(mat, current_thread);
01794 new_data->do_transform_vector_column(new_format, data, mat, first_vertex, next_vertex);
01795
01796 first_vertex = next_vertex;
01797 first_bi = next_bi;
01798 }
01799 }
01800 }
01801 }
01802 }
01803 }
01804
01805
01806
01807
01808
01809
01810
01811
01812 void GeomVertexData::
01813 do_transform_point_column(const GeomVertexFormat *format, GeomVertexRewriter &data,
01814 const LMatrix4 &mat, int begin_row, int end_row) {
01815 const GeomVertexColumn *data_column = data.get_column();
01816 int num_values = data_column->get_num_values();
01817
01818 if ((num_values == 3 || num_values == 4) &&
01819 data_column->get_numeric_type() == NT_float32) {
01820
01821
01822 GeomVertexArrayDataHandle *data_handle = data.get_array_handle();
01823
01824 size_t stride = data.get_stride();
01825 size_t num_rows = end_row - begin_row;
01826 unsigned char *datat = data_handle->get_write_pointer();
01827 datat += data_column->get_start() + begin_row * stride;
01828 LMatrix4f matf = LCAST(float, mat);
01829
01830 if (num_values == 3) {
01831 table_xform_point3f(datat, num_rows, stride, matf);
01832 } else {
01833 table_xform_vecbase4f(datat, num_rows, stride, matf);
01834 }
01835
01836 } else if (num_values == 4) {
01837
01838
01839
01840 data.set_row_unsafe(begin_row);
01841 for (int j = begin_row; j < end_row; ++j) {
01842 LPoint4 vertex = data.get_data4();
01843 data.set_data4(vertex * mat);
01844 }
01845
01846 } else {
01847
01848
01849
01850 data.set_row_unsafe(begin_row);
01851 for (int j = begin_row; j < end_row; ++j) {
01852 LPoint3 vertex = data.get_data3();
01853 data.set_data3(vertex * mat);
01854 }
01855 }
01856 }
01857
01858
01859
01860
01861
01862
01863
01864 void GeomVertexData::
01865 do_transform_vector_column(const GeomVertexFormat *format, GeomVertexRewriter &data,
01866 const LMatrix4 &mat, int begin_row, int end_row) {
01867 const GeomVertexColumn *data_column = data.get_column();
01868 int num_values = data_column->get_num_values();
01869
01870 if ((num_values == 3 || num_values == 4) &&
01871 data_column->get_numeric_type() == NT_float32) {
01872
01873
01874 GeomVertexArrayDataHandle *data_handle = data.get_array_handle();
01875
01876 size_t stride = data.get_stride();
01877 size_t num_rows = end_row - begin_row;
01878 unsigned char *datat = data_handle->get_write_pointer();
01879 datat += data_column->get_start() + begin_row * stride;
01880 LMatrix4f matf = LCAST(float, mat);
01881
01882 if (num_values == 3) {
01883 table_xform_vector3f(datat, num_rows, stride, matf);
01884 } else {
01885 table_xform_vecbase4f(datat, num_rows, stride, matf);
01886 }
01887
01888 } else {
01889
01890
01891 data.set_row_unsafe(begin_row);
01892 for (int j = begin_row; j < end_row; ++j) {
01893 LVector3 vertex = data.get_data3();
01894 data.set_data3(vertex * mat);
01895 }
01896 }
01897 }
01898
01899
01900
01901
01902
01903
01904
01905 void GeomVertexData::
01906 table_xform_point3f(unsigned char *datat, size_t num_rows, size_t stride,
01907 const LMatrix4f &matf) {
01908
01909
01910 for (size_t i = 0; i < num_rows; ++i) {
01911 LPoint3f &vertex = *(LPoint3f *)(&datat[i * stride]);
01912 vertex *= matf;
01913 }
01914 }
01915
01916
01917
01918
01919
01920
01921
01922 void GeomVertexData::
01923 table_xform_vector3f(unsigned char *datat, size_t num_rows, size_t stride,
01924 const LMatrix4f &matf) {
01925
01926
01927 for (size_t i = 0; i < num_rows; ++i) {
01928 LVector3f &vertex = *(LVector3f *)(&datat[i * stride]);
01929 vertex *= matf;
01930 }
01931 }
01932
01933
01934
01935
01936
01937
01938
01939 void GeomVertexData::
01940 table_xform_vecbase4f(unsigned char *datat, size_t num_rows, size_t stride,
01941 const LMatrix4f &matf) {
01942 #if defined(HAVE_EIGEN) && defined(LINMATH_ALIGN)
01943
01944
01945 if (((size_t)datat & 0xf) != 0 || (stride & 0xf) != 0) {
01946
01947
01948 Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, 4, Eigen::RowMajor>, Eigen::Unaligned, Eigen::OuterStride<> > table((float *)datat, num_rows, 4, Eigen::OuterStride<>(stride / sizeof(float)));
01949 for (size_t i = 0; i < num_rows; ++i) {
01950 table.row(i) *= matf._m;
01951 }
01952 return;
01953 }
01954 #endif // HAVE_EIGEN
01955
01956
01957
01958
01959 for (size_t i = 0; i < num_rows; ++i) {
01960 LVecBase4f &vertex = *(LVecBase4f *)(&datat[i * stride]);
01961 vertex *= matf;
01962 }
01963 }
01964
01965
01966
01967
01968
01969
01970
01971 void GeomVertexData::
01972 register_with_read_factory() {
01973 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
01974 }
01975
01976
01977
01978
01979
01980
01981
01982 void GeomVertexData::
01983 write_datagram(BamWriter *manager, Datagram &dg) {
01984 CopyOnWriteObject::write_datagram(manager, dg);
01985
01986 dg.add_string(_name);
01987 manager->write_cdata(dg, _cycler);
01988 }
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998 TypedWritable *GeomVertexData::
01999 make_from_bam(const FactoryParams ¶ms) {
02000 GeomVertexData *object = new GeomVertexData;
02001 DatagramIterator scan;
02002 BamReader *manager;
02003
02004 parse_params(params, scan, manager);
02005 object->fillin(scan, manager);
02006 manager->register_finalize(object);
02007
02008 return object;
02009 }
02010
02011
02012
02013
02014
02015
02016
02017
02018 int GeomVertexData::
02019 complete_pointers(TypedWritable **p_list, BamReader *manager) {
02020 int pi = CopyOnWriteObject::complete_pointers(p_list, manager);
02021 return pi;
02022 }
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034 bool GeomVertexData::
02035 require_fully_complete() const {
02036 return true;
02037 }
02038
02039
02040
02041
02042
02043
02044
02045
02046 void GeomVertexData::
02047 finalize(BamReader *manager) {
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062 CDWriter cdata(_cycler, true);
02063
02064 for (size_t i = 0; i < cdata->_arrays.size(); ++i) {
02065 CPT(GeomVertexFormat) new_format =
02066 GeomVertexFormat::register_format(cdata->_format);
02067 manager->change_pointer(cdata->_format, new_format);
02068 cdata->_format = new_format;
02069
02070 CPT(GeomVertexArrayFormat) new_array_format = new_format->get_array(i);
02071 PT(GeomVertexArrayData) array_obj = cdata->_arrays[i].get_unsafe_pointer();
02072 nassertv(new_array_format->is_data_subset_of(*array_obj->_array_format));
02073
02074 manager->change_pointer(array_obj->_array_format, new_array_format);
02075 array_obj->_array_format = new_array_format;
02076 }
02077
02078 if (cdata->_transform_table != (TransformTable *)NULL) {
02079 CPT(TransformTable) new_transform_table =
02080 TransformTable::register_table(cdata->_transform_table);
02081 manager->change_pointer(cdata->_transform_table, new_transform_table);
02082 cdata->_transform_table = new_transform_table;
02083 }
02084
02085 if (cdata->_slider_table != (SliderTable *)NULL) {
02086 CPT(SliderTable) new_slider_table =
02087 SliderTable::register_table(cdata->_slider_table);
02088 manager->change_pointer(cdata->_slider_table, new_slider_table);
02089 cdata->_slider_table = new_slider_table;
02090 }
02091 }
02092
02093
02094
02095
02096
02097
02098
02099
02100 void GeomVertexData::
02101 fillin(DatagramIterator &scan, BamReader *manager) {
02102 CopyOnWriteObject::fillin(scan, manager);
02103
02104 set_name(scan.get_string());
02105 manager->read_cdata(scan, _cycler);
02106 }
02107
02108
02109
02110
02111
02112
02113 CycleData *GeomVertexData::CDataCache::
02114 make_copy() const {
02115 return new CDataCache(*this);
02116 }
02117
02118
02119
02120
02121
02122
02123
02124 void GeomVertexData::CacheEntry::
02125 evict_callback() {
02126 LightMutexHolder holder(_source->_cache_lock);
02127 Cache::iterator ci = _source->_cache.find(&_key);
02128 nassertv(ci != _source->_cache.end());
02129 nassertv((*ci).second == this);
02130 _source->_cache.erase(ci);
02131 }
02132
02133
02134
02135
02136
02137
02138 void GeomVertexData::CacheEntry::
02139 output(ostream &out) const {
02140 out << "vertex data " << (void *)_source << " to "
02141 << *_key._modifier;
02142 }
02143
02144
02145
02146
02147
02148
02149 CycleData *GeomVertexData::CData::
02150 make_copy() const {
02151 return new CData(*this);
02152 }
02153
02154
02155
02156
02157
02158
02159
02160 void GeomVertexData::CData::
02161 write_datagram(BamWriter *manager, Datagram &dg) const {
02162 manager->write_pointer(dg, _format);
02163 dg.add_uint8(_usage_hint);
02164
02165 dg.add_uint16(_arrays.size());
02166 Arrays::const_iterator ai;
02167 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
02168 manager->write_pointer(dg, (*ai).get_read_pointer());
02169 }
02170
02171 manager->write_pointer(dg, _transform_table);
02172 manager->write_pointer(dg, _transform_blend_table.get_read_pointer());
02173 manager->write_pointer(dg, _slider_table);
02174 }
02175
02176
02177
02178
02179
02180
02181
02182
02183 int GeomVertexData::CData::
02184 complete_pointers(TypedWritable **p_list, BamReader *manager) {
02185 int pi = CycleData::complete_pointers(p_list, manager);
02186
02187 _format = DCAST(GeomVertexFormat, p_list[pi++]);
02188
02189 Arrays::iterator ai;
02190 for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
02191 (*ai) = DCAST(GeomVertexArrayData, p_list[pi++]);
02192 }
02193
02194 _transform_table = DCAST(TransformTable, p_list[pi++]);
02195 _transform_blend_table = DCAST(TransformBlendTable, p_list[pi++]);
02196 _slider_table = DCAST(SliderTable, p_list[pi++]);
02197
02198 _modified = Geom::get_next_modified();
02199
02200 if (!_arrays.empty() && manager->get_file_minor_ver() < 7) {
02201
02202
02203
02204
02205 SparseArray all_rows;
02206 CPT(GeomVertexArrayData) adata = _arrays[0].get_read_pointer();
02207 all_rows.set_range(0, adata->get_num_rows());
02208
02209 if (_slider_table != (SliderTable *)NULL) {
02210 int num_sliders = _slider_table->get_num_sliders();
02211 for (int i = 0; i < num_sliders; ++i) {
02212 ((SliderTable *)_slider_table.p())->set_slider_rows(i, all_rows);
02213 }
02214 }
02215 if (!_transform_blend_table.is_null()) {
02216 _transform_blend_table.get_unsafe_pointer()->set_rows(all_rows);
02217 }
02218 }
02219
02220 return pi;
02221 }
02222
02223
02224
02225
02226
02227
02228
02229
02230 void GeomVertexData::CData::
02231 fillin(DatagramIterator &scan, BamReader *manager) {
02232 manager->read_pointer(scan);
02233 _usage_hint = (UsageHint)scan.get_uint8();
02234
02235 size_t num_arrays = scan.get_uint16();
02236 _arrays.reserve(num_arrays);
02237 for (size_t i = 0; i < num_arrays; ++i) {
02238 manager->read_pointer(scan);
02239 _arrays.push_back(NULL);
02240 }
02241
02242 manager->read_pointer(scan);
02243 manager->read_pointer(scan);
02244 manager->read_pointer(scan);
02245 }
02246
02247
02248
02249
02250
02251
02252 int GeomVertexDataPipelineBase::
02253 get_num_bytes() const {
02254 int num_bytes = sizeof(GeomVertexData);
02255
02256 GeomVertexData::Arrays::const_iterator ai;
02257 for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
02258 num_bytes += (*ai).get_read_pointer()->get_data_size_bytes();
02259 }
02260
02261 return num_bytes;
02262 }
02263
02264
02265
02266
02267
02268
02269 int GeomVertexDataPipelineReader::
02270 get_num_rows() const {
02271 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(), 0);
02272 nassertr(_got_array_readers, 0);
02273
02274 if (_cdata->_format->get_num_arrays() == 0) {
02275
02276 return 0;
02277 }
02278
02279
02280 int stride = _cdata->_format->get_array(0)->get_stride();
02281 return _array_readers[0]->get_data_size_bytes() / stride;
02282 }
02283
02284
02285
02286
02287
02288
02289 bool GeomVertexDataPipelineReader::
02290 get_array_info(const InternalName *name,
02291 const GeomVertexArrayDataHandle *&array_reader,
02292 int &num_values,
02293 GeomVertexDataPipelineReader::NumericType &numeric_type,
02294 int &start, int &stride) const {
02295 nassertr(_got_array_readers, false);
02296 int array_index;
02297 const GeomVertexColumn *column;
02298 if (_cdata->_format->get_array_info(name, array_index, column)) {
02299 array_reader = _array_readers[array_index];
02300 num_values = column->get_num_values();
02301 numeric_type = column->get_numeric_type();
02302 start = column->get_start();
02303 stride = _cdata->_format->get_array(array_index)->get_stride();
02304 return true;
02305 }
02306 return false;
02307 }
02308
02309
02310
02311
02312
02313
02314 bool GeomVertexDataPipelineReader::
02315 get_vertex_info(const GeomVertexArrayDataHandle *&array_reader,
02316 int &num_values,
02317 GeomVertexDataPipelineReader::NumericType &numeric_type,
02318 int &start, int &stride) const {
02319 nassertr(_got_array_readers, false);
02320 int array_index = _cdata->_format->get_vertex_array_index();
02321 if (array_index >= 0) {
02322 const GeomVertexColumn *column = _cdata->_format->get_vertex_column();
02323
02324 array_reader = _array_readers[array_index];
02325 num_values = column->get_num_values();
02326 numeric_type = column->get_numeric_type();
02327 start = column->get_start();
02328 stride = _cdata->_format->get_array(array_index)->get_stride();
02329 return true;
02330 }
02331 return false;
02332 }
02333
02334
02335
02336
02337
02338
02339 bool GeomVertexDataPipelineReader::
02340 get_normal_info(const GeomVertexArrayDataHandle *&array_reader,
02341 GeomVertexDataPipelineReader::NumericType &numeric_type,
02342 int &start, int &stride) const {
02343 nassertr(_got_array_readers, false);
02344 int array_index = _cdata->_format->get_normal_array_index();
02345 if (array_index >= 0) {
02346 const GeomVertexColumn *column = _cdata->_format->get_normal_column();
02347
02348 array_reader = _array_readers[array_index];
02349 numeric_type = column->get_numeric_type();
02350 start = column->get_start();
02351 stride = _cdata->_format->get_array(array_index)->get_stride();
02352 return true;
02353 }
02354 return false;
02355 }
02356
02357
02358
02359
02360
02361
02362 bool GeomVertexDataPipelineReader::
02363 get_color_info(const GeomVertexArrayDataHandle *&array_reader,
02364 int &num_values,
02365 GeomVertexDataPipelineReader::NumericType &numeric_type,
02366 int &start, int &stride) const {
02367 nassertr(_got_array_readers, false);
02368 int array_index = _cdata->_format->get_color_array_index();
02369 if (array_index >= 0) {
02370 const GeomVertexColumn *column = _cdata->_format->get_color_column();
02371
02372 array_reader = _array_readers[array_index];
02373 num_values = column->get_num_values();
02374 numeric_type = column->get_numeric_type();
02375 start = column->get_start();
02376 stride = _cdata->_format->get_array(array_index)->get_stride();
02377 return true;
02378 }
02379 return false;
02380 }
02381
02382
02383
02384
02385
02386
02387 void GeomVertexDataPipelineReader::
02388 make_array_readers() {
02389 nassertv(!_got_array_readers);
02390
02391 _array_readers.reserve(_cdata->_arrays.size());
02392 GeomVertexData::Arrays::const_iterator ai;
02393 for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
02394 CPT(GeomVertexArrayData) array_obj = (*ai).get_read_pointer();
02395 _array_readers.push_back(array_obj->get_handle(_current_thread));
02396 }
02397
02398 _got_array_readers = true;
02399 }
02400
02401
02402
02403
02404
02405
02406 void GeomVertexDataPipelineReader::
02407 delete_array_readers() {
02408 nassertv(_got_array_readers);
02409
02410 _array_readers.clear();
02411 _got_array_readers = false;
02412 }
02413
02414
02415
02416
02417
02418
02419 int GeomVertexDataPipelineWriter::
02420 get_num_rows() const {
02421 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(), 0);
02422 nassertr(_got_array_writers, 0);
02423
02424 if (_cdata->_format->get_num_arrays() == 0) {
02425
02426 return 0;
02427 }
02428
02429
02430 int stride = _cdata->_format->get_array(0)->get_stride();
02431 return _array_writers[0]->get_data_size_bytes() / stride;
02432 }
02433
02434
02435
02436
02437
02438
02439 bool GeomVertexDataPipelineWriter::
02440 set_num_rows(int n) {
02441 nassertr(_got_array_writers, false);
02442 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(), false);
02443
02444 bool any_changed = false;
02445
02446 int color_array = -1;
02447 int orig_color_rows = -1;
02448
02449 for (size_t i = 0; i < _cdata->_arrays.size(); i++) {
02450 if (_array_writers[i]->get_num_rows() != n) {
02451 if (_array_writers[i]->get_object()->has_column(InternalName::get_color())) {
02452 color_array = i;
02453 orig_color_rows = _array_writers[i]->get_num_rows();
02454 }
02455 _array_writers[i]->set_num_rows(n);
02456 any_changed = true;
02457 }
02458 }
02459
02460 if (color_array >= 0 && orig_color_rows < n) {
02461
02462
02463 GeomVertexArrayDataHandle *array_writer = _array_writers[color_array];
02464 const GeomVertexArrayFormat *array_format = array_writer->get_array_format();
02465 const GeomVertexColumn *column =
02466 array_format->get_column(InternalName::get_color());
02467 int stride = array_format->get_stride();
02468 unsigned char *start =
02469 array_writer->get_write_pointer() + column->get_start();
02470 unsigned char *stop = start + array_writer->get_data_size_bytes();
02471 unsigned char *pointer = start + stride * orig_color_rows;
02472 int num_values = column->get_num_values();
02473
02474 switch (column->get_numeric_type()) {
02475 case NT_packed_dcba:
02476 case NT_packed_dabc:
02477 case NT_uint8:
02478 case NT_uint16:
02479 case NT_uint32:
02480 while (pointer < stop) {
02481 memset(pointer, 0xff, column->get_total_bytes());
02482 pointer += stride;
02483 }
02484 break;
02485
02486 case NT_float32:
02487 while (pointer < stop) {
02488 PN_float32 *pi = (PN_float32 *)pointer;
02489 for (int i = 0; i < num_values; i++) {
02490 pi[i] = 1.0f;
02491 }
02492 pointer += stride;
02493 }
02494 break;
02495
02496 case NT_float64:
02497 while (pointer < stop) {
02498 PN_float64 *pi = (PN_float64 *)pointer;
02499 for (int i = 0; i < num_values; i++) {
02500 pi[i] = 1.0f;
02501 }
02502 pointer += stride;
02503 }
02504 break;
02505
02506 case NT_stdfloat:
02507
02508 nassertr(false, false);
02509 }
02510 }
02511
02512 if (any_changed) {
02513 _object->clear_cache_stage();
02514 _cdata->_modified = Geom::get_next_modified();
02515 _cdata->_animated_vertices.clear();
02516 }
02517
02518 return any_changed;
02519 }
02520
02521
02522
02523
02524
02525
02526 bool GeomVertexDataPipelineWriter::
02527 unclean_set_num_rows(int n) {
02528 nassertr(_got_array_writers, false);
02529 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(), false);
02530
02531 bool any_changed = false;
02532
02533 for (size_t i = 0; i < _cdata->_arrays.size(); i++) {
02534 if (_array_writers[i]->get_num_rows() != n) {
02535 if (_array_writers[i]->unclean_set_num_rows(n)) {
02536 any_changed = true;
02537 }
02538 }
02539 }
02540
02541 if (any_changed) {
02542 _object->clear_cache_stage();
02543 _cdata->_modified = Geom::get_next_modified();
02544 _cdata->_animated_vertices.clear();
02545 }
02546
02547 return any_changed;
02548 }
02549
02550
02551
02552
02553
02554
02555 bool GeomVertexDataPipelineWriter::
02556 reserve_num_rows(int n) {
02557 nassertr(_got_array_writers, false);
02558 nassertr(_cdata->_format->get_num_arrays() == (int)_cdata->_arrays.size(), false);
02559
02560 bool any_changed = false;
02561
02562 for (size_t i = 0; i < _cdata->_arrays.size(); i++) {
02563 if (_array_writers[i]->reserve_num_rows(n)) {
02564 any_changed = true;
02565 }
02566 }
02567
02568 return any_changed;
02569 }
02570
02571
02572
02573
02574
02575
02576 PT(GeomVertexArrayData) GeomVertexDataPipelineWriter::
02577 modify_array(int i) {
02578 nassertr(i >= 0 && i < (int)_cdata->_arrays.size(), NULL);
02579
02580 PT(GeomVertexArrayData) new_data;
02581 if (_got_array_writers) {
02582 new_data = _array_writers[i]->get_object();
02583 } else {
02584 new_data = _cdata->_arrays[i].get_write_pointer();
02585 }
02586
02587 _object->clear_cache_stage();
02588 _cdata->_modified = Geom::get_next_modified();
02589 _cdata->_animated_vertices_modified = UpdateSeq();
02590
02591 return new_data;
02592 }
02593
02594
02595
02596
02597
02598
02599 void GeomVertexDataPipelineWriter::
02600 set_array(int i, const GeomVertexArrayData *array) {
02601 nassertv(i >= 0 && i < (int)_cdata->_arrays.size());
02602 _cdata->_arrays[i] = (GeomVertexArrayData *)array;
02603 _object->clear_cache_stage();
02604 _cdata->_modified = Geom::get_next_modified();
02605 _cdata->_animated_vertices_modified = UpdateSeq();
02606
02607 if (_got_array_writers) {
02608 _array_writers[i] = _cdata->_arrays[i].get_write_pointer()->modify_handle(_current_thread);
02609 }
02610 }
02611
02612
02613
02614
02615
02616
02617 void GeomVertexDataPipelineWriter::
02618 make_array_writers() {
02619 nassertv(!_got_array_writers);
02620
02621 _array_writers.reserve(_cdata->_arrays.size());
02622 GeomVertexData::Arrays::iterator ai;
02623 for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
02624 PT(GeomVertexArrayData) array_obj = (*ai).get_write_pointer();
02625 _array_writers.push_back(array_obj->modify_handle(_current_thread));
02626 }
02627
02628 _object->clear_cache_stage();
02629 _cdata->_modified = Geom::get_next_modified();
02630 _cdata->_animated_vertices_modified = UpdateSeq();
02631
02632 _got_array_writers = true;
02633 }
02634
02635
02636
02637
02638
02639
02640 void GeomVertexDataPipelineWriter::
02641 delete_array_writers() {
02642 nassertv(_got_array_writers);
02643
02644 _array_writers.clear();
02645 _got_array_writers = false;
02646 }