00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "texGenAttrib.h"
00016 #include "texturePool.h"
00017 #include "graphicsStateGuardianBase.h"
00018 #include "bamReader.h"
00019 #include "bamWriter.h"
00020 #include "datagram.h"
00021 #include "datagramIterator.h"
00022 #include "dcast.h"
00023
00024 CPT(RenderAttrib) TexGenAttrib::_empty_attrib;
00025 TypeHandle TexGenAttrib::_type_handle;
00026 int TexGenAttrib::_attrib_slot;
00027
00028
00029
00030
00031
00032
00033 TexGenAttrib::
00034 ~TexGenAttrib() {
00035 }
00036
00037
00038
00039
00040
00041
00042
00043 CPT(RenderAttrib) TexGenAttrib::
00044 make() {
00045
00046
00047 if (_empty_attrib == (RenderAttrib *)NULL) {
00048 _empty_attrib = return_new(new TexGenAttrib);
00049 }
00050
00051 return _empty_attrib;
00052 }
00053
00054
00055
00056
00057
00058
00059
00060 CPT(RenderAttrib) TexGenAttrib::
00061 make(TextureStage *stage, TexGenAttrib::Mode mode) {
00062 return DCAST(TexGenAttrib, make())->add_stage(stage, mode);
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072 CPT(RenderAttrib) TexGenAttrib::
00073 make_default() {
00074 return return_new(new TexGenAttrib);
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 CPT(RenderAttrib) TexGenAttrib::
00086 add_stage(TextureStage *stage, TexGenAttrib::Mode mode) const {
00087 nassertr(mode != M_light_vector && mode != M_constant, this);
00088
00089 CPT(RenderAttrib) removed = remove_stage(stage);
00090 TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed));
00091
00092 ModeDef &mode_def = attrib->_stages[stage];
00093 mode_def._mode = mode;
00094 attrib->record_stage(stage, mode_def);
00095
00096 return return_new(attrib);
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 CPT(RenderAttrib) TexGenAttrib::
00111 add_stage(TextureStage *stage, TexGenAttrib::Mode mode,
00112 const string &source_name, const NodePath &light) const {
00113 nassertr(mode == M_light_vector, this);
00114
00115 CPT(RenderAttrib) removed = remove_stage(stage);
00116 TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed));
00117
00118 ModeDef &mode_def = attrib->_stages[stage];
00119 mode_def._mode = mode;
00120 mode_def._source_name = source_name;
00121 mode_def._light = light;
00122 attrib->record_stage(stage, mode_def);
00123
00124 return return_new(attrib);
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 CPT(RenderAttrib) TexGenAttrib::
00139 add_stage(TextureStage *stage, TexGenAttrib::Mode mode,
00140 const LTexCoord3 &constant_value) const {
00141 nassertr(mode == M_constant, this);
00142
00143 CPT(RenderAttrib) removed = remove_stage(stage);
00144 TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed));
00145
00146 ModeDef &mode_def = attrib->_stages[stage];
00147 mode_def._mode = mode;
00148 mode_def._constant_value = constant_value;
00149 attrib->record_stage(stage, mode_def);
00150
00151 return return_new(attrib);
00152 }
00153
00154
00155
00156
00157
00158
00159
00160 CPT(RenderAttrib) TexGenAttrib::
00161 remove_stage(TextureStage *stage) const {
00162 Stages::const_iterator si;
00163 si = _stages.find(stage);
00164 if (si == _stages.end()) {
00165 return this;
00166 }
00167
00168 Mode mode = (*si).second._mode;
00169 TexGenAttrib *attrib = new TexGenAttrib(*this);
00170 attrib->_stages.erase(stage);
00171 attrib->_no_texcoords.erase(stage);
00172 if (mode == M_point_sprite) {
00173 attrib->_num_point_sprites--;
00174 if (attrib->_num_point_sprites == 0) {
00175 attrib->_point_geom_rendering &= ~Geom::GR_point_sprite;
00176 }
00177 } else if (mode == M_light_vector) {
00178 attrib->_light_vectors.erase(stage);
00179 attrib->_num_light_vectors--;
00180 if (attrib->_num_light_vectors == 0) {
00181 attrib->_geom_rendering &= ~Geom::GR_texcoord_light_vector;
00182 }
00183 }
00184 return return_new(attrib);
00185 }
00186
00187
00188
00189
00190
00191
00192
00193 bool TexGenAttrib::
00194 is_empty() const {
00195 return _stages.empty();
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205 bool TexGenAttrib::
00206 has_stage(TextureStage *stage) const {
00207 Stages::const_iterator mi = _stages.find(stage);
00208 return (mi != _stages.end());
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218 TexGenAttrib::Mode TexGenAttrib::
00219 get_mode(TextureStage *stage) const {
00220 Stages::const_iterator mi = _stages.find(stage);
00221 if (mi != _stages.end()) {
00222 return (*mi).second._mode;
00223 }
00224 return M_off;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 bool TexGenAttrib::
00236 has_gen_texcoord_stage(TextureStage *stage) const {
00237 NoTexCoordStages::const_iterator mi = _no_texcoords.find(stage);
00238 return (mi != _no_texcoords.end());
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 string TexGenAttrib::
00253 get_source_name(TextureStage *stage) const {
00254 Stages::const_iterator mi = _stages.find(stage);
00255 if (mi != _stages.end()) {
00256 return (*mi).second._source_name;
00257 }
00258 return string();
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 NodePath TexGenAttrib::
00270 get_light(TextureStage *stage) const {
00271 Stages::const_iterator mi = _stages.find(stage);
00272 if (mi != _stages.end()) {
00273 return (*mi).second._light;
00274 }
00275 return NodePath();
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285 const LTexCoord3 &TexGenAttrib::
00286 get_constant_value(TextureStage *stage) const {
00287 Stages::const_iterator mi = _stages.find(stage);
00288 if (mi != _stages.end()) {
00289 return (*mi).second._constant_value;
00290 }
00291 return LTexCoord3::zero();
00292 }
00293
00294
00295
00296
00297
00298
00299 void TexGenAttrib::
00300 output(ostream &out) const {
00301 out << get_type() << ":";
00302
00303 Stages::const_iterator mi;
00304 for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
00305 TextureStage *stage = (*mi).first;
00306 const ModeDef &mode_def = (*mi).second;
00307 out << " " << stage->get_name() << "(";
00308 switch (mode_def._mode) {
00309 case M_off:
00310 out << "off";
00311 break;
00312
00313 case M_eye_sphere_map:
00314 out << "eye_sphere_map";
00315 break;
00316
00317 case M_world_cube_map:
00318 out << "world_cube_map";
00319 break;
00320 case M_eye_cube_map:
00321 out << "eye_cube_map";
00322 break;
00323
00324 case M_world_normal:
00325 out << "world_normal";
00326 break;
00327 case M_eye_normal:
00328 out << "eye_normal";
00329 break;
00330
00331 case M_world_position:
00332 out << "world_position";
00333 break;
00334 case M_eye_position:
00335 out << "eye_position";
00336 break;
00337
00338 case M_point_sprite:
00339 out << "point_sprite";
00340 break;
00341
00342 case M_light_vector:
00343 out << "light_vector: \"" << mode_def._source_name << "\", "
00344 << mode_def._light;
00345 break;
00346
00347 case M_constant:
00348 out << "constant: " << mode_def._constant_value;
00349 break;
00350
00351 case M_unused:
00352 break;
00353 }
00354 out << ")";
00355 }
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 int TexGenAttrib::
00374 compare_to_impl(const RenderAttrib *other) const {
00375 const TexGenAttrib *ta;
00376 DCAST_INTO_R(ta, other, 0);
00377
00378 Stages::const_iterator ai, bi;
00379 ai = _stages.begin();
00380 bi = ta->_stages.begin();
00381 while (ai != _stages.end() && bi != ta->_stages.end()) {
00382 if ((*ai).first < (*bi).first) {
00383
00384 return -1;
00385
00386 } else if ((*bi).first < (*ai).first) {
00387
00388 return 1;
00389
00390 } else {
00391
00392 int compare = (*ai).second.compare_to((*bi).second);
00393 if (compare != 0) {
00394 return compare;
00395 }
00396 ++ai;
00397 ++bi;
00398 }
00399 }
00400
00401 if (bi != ta->_stages.end()) {
00402
00403 return -1;
00404 }
00405
00406 if (ai != _stages.end()) {
00407
00408 return 1;
00409 }
00410
00411 return 0;
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 size_t TexGenAttrib::
00425 get_hash_impl() const {
00426 size_t hash = 0;
00427 Stages::const_iterator ri;
00428 for (ri = _stages.begin(); ri != _stages.end(); ++ri) {
00429 const TextureStage *stage = (*ri).first;
00430 const ModeDef &mode_def = (*ri).second;
00431
00432 hash = pointer_hash::add_hash(hash, stage);
00433 hash = int_hash::add_hash(hash, (int)mode_def._mode);
00434 hash = string_hash::add_hash(hash, mode_def._source_name);
00435 hash = mode_def._light.add_hash(hash);
00436 hash = mode_def._constant_value.add_hash(hash);
00437 }
00438
00439 return hash;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 CPT(RenderAttrib) TexGenAttrib::
00460 compose_impl(const RenderAttrib *other) const {
00461 const TexGenAttrib *ta;
00462 DCAST_INTO_R(ta, other, 0);
00463
00464
00465
00466
00467 TexGenAttrib *attrib = new TexGenAttrib;
00468
00469 Stages::const_iterator ai, bi;
00470 ai = _stages.begin();
00471 bi = ta->_stages.begin();
00472 while (ai != _stages.end() && bi != ta->_stages.end()) {
00473 if ((*ai).first < (*bi).first) {
00474
00475 attrib->_stages.insert(attrib->_stages.end(), *ai);
00476 ++ai;
00477
00478 } else if ((*bi).first < (*ai).first) {
00479
00480 attrib->_stages.insert(attrib->_stages.end(), *bi);
00481 ++bi;
00482
00483 } else {
00484
00485 attrib->_stages.insert(attrib->_stages.end(), *bi);
00486 ++bi;
00487 ++ai;
00488 }
00489 }
00490
00491 while (ai != _stages.end()) {
00492
00493 attrib->_stages.insert(attrib->_stages.end(), *ai);
00494 ++ai;
00495 }
00496
00497 while (bi != ta->_stages.end()) {
00498
00499 attrib->_stages.insert(attrib->_stages.end(), *bi);
00500 ++bi;
00501 }
00502
00503 attrib->filled_stages();
00504
00505 return return_new(attrib);
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 CPT(RenderAttrib) TexGenAttrib::
00518 invert_compose_impl(const RenderAttrib *other) const {
00519 const TexGenAttrib *ta;
00520 DCAST_INTO_R(ta, other, 0);
00521
00522
00523
00524
00525 TexGenAttrib *attrib = new TexGenAttrib;
00526
00527 Stages::const_iterator ai, bi;
00528 ai = _stages.begin();
00529 bi = ta->_stages.begin();
00530 while (ai != _stages.end() && bi != ta->_stages.end()) {
00531 if ((*ai).first < (*bi).first) {
00532
00533 attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, ModeDef()));
00534 ++ai;
00535
00536 } else if ((*bi).first < (*ai).first) {
00537
00538 attrib->_stages.insert(attrib->_stages.end(), *bi);
00539 ++bi;
00540
00541 } else {
00542
00543 attrib->_stages.insert(attrib->_stages.end(), *bi);
00544 ++bi;
00545 ++ai;
00546 }
00547 }
00548
00549 while (ai != _stages.end()) {
00550
00551 attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, ModeDef()));
00552 ++ai;
00553 }
00554
00555 while (bi != ta->_stages.end()) {
00556
00557 attrib->_stages.insert(attrib->_stages.end(), *bi);
00558 ++bi;
00559 }
00560
00561 attrib->filled_stages();
00562
00563 return return_new(attrib);
00564 }
00565
00566
00567
00568
00569
00570
00571 CPT(RenderAttrib) TexGenAttrib::
00572 get_auto_shader_attrib_impl(const RenderState *state) const {
00573 return this;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 void TexGenAttrib::
00586 filled_stages() {
00587 Stages::iterator ri;
00588 for (ri = _stages.begin(); ri != _stages.end(); ++ri) {
00589 TextureStage *stage = (*ri).first;
00590 ModeDef &mode_def = (*ri).second;
00591 record_stage(stage, mode_def);
00592 }
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602 void TexGenAttrib::
00603 record_stage(TextureStage *stage, TexGenAttrib::ModeDef &mode_def) {
00604 switch (mode_def._mode) {
00605 case M_point_sprite:
00606 _no_texcoords.insert(stage);
00607 _point_geom_rendering |= Geom::GR_point_sprite;
00608 _num_point_sprites++;
00609 break;
00610
00611 case M_light_vector:
00612 {
00613 if (!mode_def._light.is_empty()) {
00614 Light *light_obj = mode_def._light.node()->as_light();
00615 if (light_obj == (Light *)NULL) {
00616 #ifndef NDEBUG
00617 ostringstream strm;
00618 strm << "Not a light: " << mode_def._light;
00619 nassert_raise(strm.str());
00620 #endif
00621 mode_def._light = NodePath();
00622 }
00623 }
00624
00625 _light_vectors.insert(stage);
00626 _geom_rendering |= Geom::GR_texcoord_light_vector;
00627 _num_light_vectors++;
00628 }
00629 break;
00630
00631 case M_off:
00632 break;
00633
00634 default:
00635 _no_texcoords.insert(stage);
00636 }
00637 }
00638
00639
00640
00641
00642
00643
00644
00645 void TexGenAttrib::
00646 register_with_read_factory() {
00647 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00648 }
00649
00650
00651
00652
00653
00654
00655
00656 void TexGenAttrib::
00657 write_datagram(BamWriter *manager, Datagram &dg) {
00658 RenderAttrib::write_datagram(manager, dg);
00659
00660 dg.add_uint16(_stages.size());
00661
00662 Stages::const_iterator si;
00663 for (si = _stages.begin(); si != _stages.end(); ++si) {
00664 TextureStage *stage = (*si).first;
00665 Mode mode = (*si).second._mode;
00666
00667 manager->write_pointer(dg, stage);
00668 dg.add_uint8((unsigned int)mode);
00669 }
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679 int TexGenAttrib::
00680 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00681 int pi = RenderAttrib::complete_pointers(p_list, manager);
00682
00683 pvector<Mode>::const_iterator mi;
00684 for (mi = _read_modes.begin(); mi != _read_modes.end(); ++mi) {
00685 Mode mode = (*mi);
00686
00687 TextureStage *stage = DCAST(TextureStage, p_list[pi++]);
00688 _stages[stage]._mode = mode;
00689 }
00690
00691 filled_stages();
00692
00693 return pi;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 TypedWritable *TexGenAttrib::
00705 make_from_bam(const FactoryParams ¶ms) {
00706 TexGenAttrib *attrib = new TexGenAttrib;
00707 DatagramIterator scan;
00708 BamReader *manager;
00709
00710 parse_params(params, scan, manager);
00711 attrib->fillin(scan, manager);
00712
00713 return attrib;
00714 }
00715
00716
00717
00718
00719
00720
00721
00722
00723 void TexGenAttrib::
00724 fillin(DatagramIterator &scan, BamReader *manager) {
00725 RenderAttrib::fillin(scan, manager);
00726
00727 size_t num_stages = scan.get_uint16();
00728
00729
00730
00731
00732
00733 _read_modes.clear();
00734 _read_modes.reserve(num_stages);
00735 for (size_t i = 0; i < num_stages; i++) {
00736 manager->read_pointer(scan);
00737 Mode mode = (Mode)scan.get_uint8();
00738 _read_modes.push_back(mode);
00739 }
00740 }