00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "textureProperties.h"
00016 #include "palettizer.h"
00017 #include "pnmFileType.h"
00018 #include "datagram.h"
00019 #include "datagramIterator.h"
00020 #include "bamReader.h"
00021 #include "bamWriter.h"
00022 #include "string_utils.h"
00023
00024 TypeHandle TextureProperties::_type_handle;
00025
00026
00027
00028
00029
00030
00031 TextureProperties::
00032 TextureProperties() {
00033 _got_num_channels = false;
00034 _num_channels = 0;
00035 _effective_num_channels = 0;
00036 _format = EggTexture::F_unspecified;
00037 _force_format = false;
00038 _generic_format = false;
00039 _keep_format = false;
00040 _minfilter = EggTexture::FT_unspecified;
00041 _magfilter = EggTexture::FT_unspecified;
00042 _quality_level = EggTexture::QL_unspecified;
00043 _anisotropic_degree = 0;
00044 _color_type = (PNMFileType *)NULL;
00045 _alpha_type = (PNMFileType *)NULL;
00046 }
00047
00048
00049
00050
00051
00052
00053 TextureProperties::
00054 TextureProperties(const TextureProperties ©) :
00055 _format(copy._format),
00056 _force_format(copy._force_format),
00057 _generic_format(copy._generic_format),
00058 _keep_format(copy._keep_format),
00059 _minfilter(copy._minfilter),
00060 _magfilter(copy._magfilter),
00061 _quality_level(copy._quality_level),
00062 _anisotropic_degree(copy._anisotropic_degree),
00063 _color_type(copy._color_type),
00064 _alpha_type(copy._alpha_type),
00065 _got_num_channels(copy._got_num_channels),
00066 _num_channels(copy._num_channels),
00067 _effective_num_channels(copy._effective_num_channels)
00068 {
00069 }
00070
00071
00072
00073
00074
00075
00076 void TextureProperties::
00077 operator = (const TextureProperties ©) {
00078 _force_format = copy._force_format;
00079 _generic_format = copy._generic_format;
00080 _keep_format = copy._keep_format;
00081 _minfilter = copy._minfilter;
00082 _magfilter = copy._magfilter;
00083 _quality_level = copy._quality_level;
00084 _anisotropic_degree = copy._anisotropic_degree;
00085 _color_type = copy._color_type;
00086 _alpha_type = copy._alpha_type;
00087 _got_num_channels = copy._got_num_channels;
00088 _num_channels = copy._num_channels;
00089 _effective_num_channels = copy._effective_num_channels;
00090 _format = copy._format;
00091 }
00092
00093
00094
00095
00096
00097
00098
00099 void TextureProperties::
00100 clear_basic() {
00101 if (!_force_format) {
00102 _format = EggTexture::F_unspecified;
00103 }
00104
00105 _minfilter = EggTexture::FT_unspecified;
00106 _magfilter = EggTexture::FT_unspecified;
00107 _quality_level = EggTexture::QL_unspecified;
00108 _anisotropic_degree = 0;
00109 }
00110
00111
00112
00113
00114
00115
00116 bool TextureProperties::
00117 has_num_channels() const {
00118 return _got_num_channels;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128 int TextureProperties::
00129 get_num_channels() const {
00130 nassertr(_got_num_channels, 0);
00131 return _effective_num_channels;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141 void TextureProperties::
00142 set_num_channels(int num_channels) {
00143 _num_channels = num_channels;
00144 _effective_num_channels = num_channels;
00145 _got_num_channels = true;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155 void TextureProperties::
00156 force_grayscale() {
00157 nassertv(_got_num_channels && _num_channels >= 3);
00158 _num_channels -= 2;
00159 _effective_num_channels = _num_channels;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 void TextureProperties::
00171 force_nonalpha() {
00172 nassertv(_got_num_channels && (_num_channels == 2 || _num_channels == 4));
00173 _num_channels--;
00174 _effective_num_channels = _num_channels;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 bool TextureProperties::
00184 uses_alpha() const {
00185 switch (_format) {
00186 case EggTexture::F_rgba:
00187 case EggTexture::F_rgbm:
00188 case EggTexture::F_rgba12:
00189 case EggTexture::F_rgba8:
00190 case EggTexture::F_rgba4:
00191 case EggTexture::F_rgba5:
00192 case EggTexture::F_alpha:
00193 case EggTexture::F_luminance_alpha:
00194 case EggTexture::F_luminance_alphamask:
00195 return true;
00196
00197 default:
00198 return false;
00199 }
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 string TextureProperties::
00212 get_string() const {
00213 string result;
00214
00215 if (_got_num_channels) {
00216 ostringstream num;
00217 num << _effective_num_channels;
00218 result += num.str();
00219 }
00220
00221 result += get_format_string(_format);
00222 result += get_filter_string(_minfilter);
00223 result += get_filter_string(_magfilter);
00224 result += get_anisotropic_degree_string(_anisotropic_degree);
00225 result += get_type_string(_color_type, _alpha_type);
00226 result += get_quality_level_string(_quality_level);
00227 return result;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236 void TextureProperties::
00237 update_properties(const TextureProperties &other) {
00238 if (!_got_num_channels) {
00239 _got_num_channels = other._got_num_channels;
00240 _num_channels = other._num_channels;
00241 _effective_num_channels = _num_channels;
00242 }
00243 if (_force_format) {
00244
00245 } else if (other._force_format) {
00246 _format = other._format;
00247 } else {
00248 _format = union_format(_format, other._format);
00249 }
00250
00251 _minfilter = union_filter(_minfilter, other._minfilter);
00252 _magfilter = union_filter(_magfilter, other._magfilter);
00253 _quality_level = union_quality_level(_quality_level, other._quality_level);
00254
00255 _anisotropic_degree = other._anisotropic_degree;
00256
00257 if (_color_type == (PNMFileType *)NULL) {
00258 _color_type = other._color_type;
00259 _alpha_type = other._alpha_type;
00260 }
00261 }
00262
00263
00264
00265
00266
00267
00268
00269 void TextureProperties::
00270 fully_define() {
00271 if (!_got_num_channels || _force_format) {
00272 switch (_format) {
00273 case EggTexture::F_rgba:
00274 case EggTexture::F_rgbm:
00275 case EggTexture::F_rgba12:
00276 case EggTexture::F_rgba8:
00277 case EggTexture::F_rgba4:
00278 case EggTexture::F_rgba5:
00279 _num_channels = 4;
00280 break;
00281
00282 case EggTexture::F_unspecified:
00283 case EggTexture::F_rgb:
00284 case EggTexture::F_rgb12:
00285 case EggTexture::F_rgb8:
00286 case EggTexture::F_rgb5:
00287 case EggTexture::F_rgb332:
00288 _num_channels = 3;
00289 break;
00290
00291 case EggTexture::F_luminance_alpha:
00292 case EggTexture::F_luminance_alphamask:
00293 _num_channels = 2;
00294 break;
00295
00296 case EggTexture::F_red:
00297 case EggTexture::F_green:
00298 case EggTexture::F_blue:
00299 case EggTexture::F_alpha:
00300 case EggTexture::F_luminance:
00301 _num_channels = 1;
00302 break;
00303 }
00304 _got_num_channels = true;
00305 }
00306
00307 _effective_num_channels = _num_channels;
00308
00309
00310
00311
00312 if (_generic_format) {
00313 switch (_format) {
00314 case EggTexture::F_unspecified:
00315 case EggTexture::F_rgba:
00316 case EggTexture::F_rgbm:
00317 case EggTexture::F_rgb:
00318 case EggTexture::F_red:
00319 case EggTexture::F_green:
00320 case EggTexture::F_blue:
00321 case EggTexture::F_alpha:
00322 case EggTexture::F_luminance:
00323 case EggTexture::F_luminance_alpha:
00324 case EggTexture::F_luminance_alphamask:
00325 break;
00326
00327 case EggTexture::F_rgba12:
00328 case EggTexture::F_rgba8:
00329 case EggTexture::F_rgba4:
00330 case EggTexture::F_rgba5:
00331 _format = EggTexture::F_rgba;
00332 break;
00333
00334 case EggTexture::F_rgb12:
00335 case EggTexture::F_rgb8:
00336 case EggTexture::F_rgb5:
00337 case EggTexture::F_rgb332:
00338 _format = EggTexture::F_rgb;
00339 break;
00340 }
00341 }
00342
00343
00344
00345 if (!_force_format && !_keep_format) {
00346 switch (_num_channels) {
00347 case 1:
00348 switch (_format) {
00349 case EggTexture::F_red:
00350 case EggTexture::F_green:
00351 case EggTexture::F_blue:
00352 case EggTexture::F_alpha:
00353 case EggTexture::F_luminance:
00354 break;
00355
00356
00357
00358 case EggTexture::F_luminance_alpha:
00359 case EggTexture::F_luminance_alphamask:
00360 _format = EggTexture::F_luminance;
00361 break;
00362
00363 default:
00364 _format = EggTexture::F_luminance;
00365 }
00366 break;
00367
00368 case 2:
00369 switch (_format) {
00370 case EggTexture::F_luminance_alpha:
00371 case EggTexture::F_luminance_alphamask:
00372 break;
00373
00374
00375 case EggTexture::F_red:
00376 case EggTexture::F_green:
00377 case EggTexture::F_blue:
00378 case EggTexture::F_alpha:
00379 case EggTexture::F_luminance:
00380 break;
00381
00382 default:
00383 _format = EggTexture::F_luminance_alpha;
00384 }
00385 break;
00386
00387 case 3:
00388 switch (_format) {
00389 case EggTexture::F_rgb:
00390 case EggTexture::F_rgb12:
00391 case EggTexture::F_rgb8:
00392 case EggTexture::F_rgb5:
00393 case EggTexture::F_rgb332:
00394 break;
00395
00396
00397
00398 case EggTexture::F_rgba8:
00399 _format = EggTexture::F_rgb8;
00400 break;
00401
00402 case EggTexture::F_rgba5:
00403 case EggTexture::F_rgba4:
00404 _format = EggTexture::F_rgb5;
00405 break;
00406
00407
00408 case EggTexture::F_red:
00409 case EggTexture::F_green:
00410 case EggTexture::F_blue:
00411 case EggTexture::F_alpha:
00412 case EggTexture::F_luminance:
00413 break;
00414
00415 default:
00416 _format = EggTexture::F_rgb;
00417 }
00418 break;
00419
00420 case 4:
00421 switch (_format) {
00422 case EggTexture::F_rgba:
00423 case EggTexture::F_rgbm:
00424 case EggTexture::F_rgba12:
00425 case EggTexture::F_rgba8:
00426 case EggTexture::F_rgba4:
00427 case EggTexture::F_rgba5:
00428 break;
00429
00430
00431 case EggTexture::F_rgb:
00432 case EggTexture::F_rgb12:
00433 case EggTexture::F_rgb8:
00434 case EggTexture::F_rgb5:
00435 case EggTexture::F_rgb332:
00436 _effective_num_channels = 3;
00437 break;
00438
00439
00440 case EggTexture::F_luminance_alpha:
00441 case EggTexture::F_luminance_alphamask:
00442 _effective_num_channels = 2;
00443 break;
00444
00445
00446 case EggTexture::F_red:
00447 case EggTexture::F_green:
00448 case EggTexture::F_blue:
00449 case EggTexture::F_alpha:
00450 case EggTexture::F_luminance:
00451 _effective_num_channels = 1;
00452 break;
00453
00454 default:
00455 _format = EggTexture::F_rgba;
00456 }
00457 }
00458 }
00459
00460 switch (_minfilter) {
00461 case EggTexture::FT_unspecified:
00462 _minfilter = EggTexture::FT_linear;
00463 break;
00464
00465 default:
00466 break;
00467 }
00468
00469 switch (_magfilter) {
00470 case EggTexture::FT_unspecified:
00471 case EggTexture::FT_nearest_mipmap_nearest:
00472 case EggTexture::FT_linear_mipmap_nearest:
00473 case EggTexture::FT_nearest_mipmap_linear:
00474 case EggTexture::FT_linear_mipmap_linear:
00475 _magfilter = EggTexture::FT_linear;
00476 break;
00477
00478 default:
00479 break;
00480 }
00481
00482 if (_color_type == (PNMFileType *)NULL) {
00483 _color_type = pal->_color_type;
00484 _alpha_type = pal->_alpha_type;
00485 }
00486 }
00487
00488
00489
00490
00491
00492
00493
00494 void TextureProperties::
00495 update_egg_tex(EggTexture *egg_tex) const {
00496 egg_tex->set_format(_format);
00497 egg_tex->set_minfilter(_minfilter);
00498 egg_tex->set_magfilter(_minfilter);
00499 egg_tex->set_quality_level(_quality_level);
00500 egg_tex->set_anisotropic_degree(_anisotropic_degree);
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 bool TextureProperties::
00512 egg_properties_match(const TextureProperties &other) const {
00513 return (_format == other._format &&
00514 _minfilter == other._minfilter &&
00515 _magfilter == other._magfilter &&
00516 _quality_level == other._quality_level &&
00517 _anisotropic_degree == other._anisotropic_degree);
00518 }
00519
00520
00521
00522
00523
00524
00525 bool TextureProperties::
00526 operator < (const TextureProperties &other) const {
00527 if (_format != other._format) {
00528 return (int)_format < (int)other._format;
00529 }
00530 if (_minfilter != other._minfilter) {
00531 return (int)_minfilter < (int)other._minfilter;
00532 }
00533 if (_magfilter != other._magfilter) {
00534 return (int)_magfilter < (int)other._magfilter;
00535 }
00536 if (_quality_level != other._quality_level) {
00537 return (int)_quality_level < (int)other._quality_level;
00538 }
00539 if (_anisotropic_degree != other._anisotropic_degree) {
00540 return _anisotropic_degree < other._anisotropic_degree;
00541 }
00542 if (_color_type != other._color_type) {
00543 return _color_type < other._color_type;
00544 }
00545 if (_color_type != (PNMFileType *)NULL) {
00546 if (_alpha_type != other._alpha_type) {
00547 return _alpha_type < other._alpha_type;
00548 }
00549 }
00550 return false;
00551 }
00552
00553
00554
00555
00556
00557
00558 bool TextureProperties::
00559 operator == (const TextureProperties &other) const {
00560 return (_format == other._format &&
00561 _minfilter == other._minfilter &&
00562 _magfilter == other._magfilter &&
00563 _quality_level == other._quality_level &&
00564 _anisotropic_degree == other._anisotropic_degree &&
00565 _color_type == other._color_type &&
00566 (_color_type == (PNMFileType *)NULL ||
00567 _alpha_type == other._alpha_type));
00568 }
00569
00570
00571
00572
00573
00574
00575 bool TextureProperties::
00576 operator != (const TextureProperties &other) const {
00577 return !operator == (other);
00578 }
00579
00580
00581
00582
00583
00584
00585
00586 string TextureProperties::
00587 get_format_string(EggTexture::Format format) {
00588 switch (format) {
00589 case EggTexture::F_unspecified:
00590 return "u";
00591
00592 case EggTexture::F_rgba:
00593 return "a";
00594
00595 case EggTexture::F_rgbm:
00596 return "m";
00597
00598 case EggTexture::F_rgba12:
00599 return "a12";
00600
00601 case EggTexture::F_rgba8:
00602 return "a8";
00603
00604 case EggTexture::F_rgba4:
00605 return "a4";
00606
00607 case EggTexture::F_rgba5:
00608 return "a5";
00609
00610 case EggTexture::F_rgb:
00611 return "c";
00612
00613 case EggTexture::F_rgb12:
00614 return "c12";
00615
00616 case EggTexture::F_rgb8:
00617 return "c8";
00618
00619 case EggTexture::F_rgb5:
00620 return "c5";
00621
00622 case EggTexture::F_rgb332:
00623 return "c3";
00624
00625 case EggTexture::F_luminance_alpha:
00626 return "t";
00627
00628 case EggTexture::F_luminance_alphamask:
00629 return "t1";
00630
00631 case EggTexture::F_red:
00632 return "r";
00633
00634 case EggTexture::F_green:
00635 return "g";
00636
00637 case EggTexture::F_blue:
00638 return "b";
00639
00640 case EggTexture::F_alpha:
00641 return "a";
00642
00643 case EggTexture::F_luminance:
00644 return "l";
00645 }
00646
00647 return "x";
00648 }
00649
00650
00651
00652
00653
00654
00655
00656 string TextureProperties::
00657 get_filter_string(EggTexture::FilterType filter_type) {
00658 switch (filter_type) {
00659 case EggTexture::FT_unspecified:
00660 return "u";
00661
00662 case EggTexture::FT_nearest:
00663 return "n";
00664
00665 case EggTexture::FT_linear:
00666 return "l";
00667
00668 case EggTexture::FT_nearest_mipmap_nearest:
00669 return "m1";
00670
00671 case EggTexture::FT_linear_mipmap_nearest:
00672 return "m2";
00673
00674 case EggTexture::FT_nearest_mipmap_linear:
00675 return "m3";
00676
00677 case EggTexture::FT_linear_mipmap_linear:
00678 return "m";
00679 }
00680
00681 return "x";
00682 }
00683
00684
00685
00686
00687
00688
00689 string TextureProperties::
00690 get_anisotropic_degree_string(int aniso_degree) {
00691 if (aniso_degree <= 1) {
00692 return "";
00693 } else {
00694 return string("an") + format_string(aniso_degree);
00695 }
00696 }
00697
00698
00699
00700
00701
00702
00703 string TextureProperties::
00704 get_quality_level_string(EggTexture::QualityLevel quality_level) {
00705 switch (quality_level) {
00706 case EggTexture::QL_unspecified:
00707 case EggTexture::QL_default:
00708 return "";
00709
00710 case EggTexture::QL_fastest:
00711 return "f";
00712
00713 case EggTexture::QL_normal:
00714 return "n";
00715
00716 case EggTexture::QL_best:
00717 return "b";
00718 }
00719 return "";
00720 }
00721
00722
00723
00724
00725
00726
00727
00728 string TextureProperties::
00729 get_type_string(PNMFileType *color_type, PNMFileType *alpha_type) {
00730 if (color_type == (PNMFileType *)NULL) {
00731 return "";
00732 }
00733 if (alpha_type == (PNMFileType *)NULL) {
00734 return "c";
00735 }
00736 return "a";
00737 }
00738
00739
00740
00741
00742
00743
00744
00745 EggTexture::Format TextureProperties::
00746 union_format(EggTexture::Format a, EggTexture::Format b) {
00747 switch (a) {
00748 case EggTexture::F_unspecified:
00749 return b;
00750
00751 case EggTexture::F_rgba:
00752 switch (b) {
00753 case EggTexture::F_rgbm:
00754 case EggTexture::F_rgba12:
00755 case EggTexture::F_rgba8:
00756 case EggTexture::F_rgba4:
00757 case EggTexture::F_rgba5:
00758 case EggTexture::F_red:
00759 case EggTexture::F_green:
00760 case EggTexture::F_blue:
00761 case EggTexture::F_alpha:
00762 return b;
00763
00764 default:
00765 return a;
00766 };
00767
00768 case EggTexture::F_rgb:
00769 if (b != EggTexture::F_unspecified) {
00770 return b;
00771 }
00772 return a;
00773
00774 default:
00775 return a;
00776 }
00777 }
00778
00779
00780
00781
00782
00783
00784
00785 EggTexture::FilterType TextureProperties::
00786 union_filter(EggTexture::FilterType a, EggTexture::FilterType b) {
00787 if ((int)a < (int)b) {
00788 return b;
00789 } else {
00790 return a;
00791 }
00792 }
00793
00794
00795
00796
00797
00798
00799
00800 EggTexture::QualityLevel TextureProperties::
00801 union_quality_level(EggTexture::QualityLevel a, EggTexture::QualityLevel b) {
00802 if ((int)a < (int)b) {
00803 return b;
00804 } else {
00805 return a;
00806 }
00807 }
00808
00809
00810
00811
00812
00813
00814
00815 void TextureProperties::
00816 register_with_read_factory() {
00817 BamReader::get_factory()->
00818 register_factory(get_class_type(), make_TextureProperties);
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828 void TextureProperties::
00829 write_datagram(BamWriter *writer, Datagram &datagram) {
00830 TypedWritable::write_datagram(writer, datagram);
00831 datagram.add_bool(_got_num_channels);
00832 datagram.add_int32(_num_channels);
00833 datagram.add_int32(_effective_num_channels);
00834 datagram.add_int32((int)_format);
00835 datagram.add_bool(_force_format);
00836 datagram.add_bool(_generic_format);
00837 datagram.add_bool(_keep_format);
00838 datagram.add_int32((int)_minfilter);
00839 datagram.add_int32((int)_magfilter);
00840 datagram.add_int32((int)_quality_level);
00841 datagram.add_int32(_anisotropic_degree);
00842 writer->write_pointer(datagram, _color_type);
00843 writer->write_pointer(datagram, _alpha_type);
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 int TextureProperties::
00856 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00857 int index = TypedWritable::complete_pointers(p_list, manager);
00858
00859 if (p_list[index] != (TypedWritable *)NULL) {
00860 DCAST_INTO_R(_color_type, p_list[index], index);
00861 }
00862 index++;
00863
00864 if (p_list[index] != (TypedWritable *)NULL) {
00865 DCAST_INTO_R(_alpha_type, p_list[index], index);
00866 }
00867 index++;
00868
00869 return index;
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 TypedWritable* TextureProperties::
00881 make_TextureProperties(const FactoryParams ¶ms) {
00882 TextureProperties *me = new TextureProperties;
00883 DatagramIterator scan;
00884 BamReader *manager;
00885
00886 parse_params(params, scan, manager);
00887 me->fillin(scan, manager);
00888 return me;
00889 }
00890
00891
00892
00893
00894
00895
00896
00897
00898 void TextureProperties::
00899 fillin(DatagramIterator &scan, BamReader *manager) {
00900 TypedWritable::fillin(scan, manager);
00901 _got_num_channels = scan.get_bool();
00902 _num_channels = scan.get_int32();
00903 _effective_num_channels = _num_channels;
00904 if (Palettizer::_read_pi_version >= 9) {
00905 _effective_num_channels = scan.get_int32();
00906 }
00907 _format = (EggTexture::Format)scan.get_int32();
00908 _force_format = scan.get_bool();
00909 _generic_format = false;
00910 if (Palettizer::_read_pi_version >= 9) {
00911 _generic_format = scan.get_bool();
00912 }
00913 _keep_format = false;
00914 if (Palettizer::_read_pi_version >= 13) {
00915 _keep_format = scan.get_bool();
00916 }
00917 _minfilter = (EggTexture::FilterType)scan.get_int32();
00918 _magfilter = (EggTexture::FilterType)scan.get_int32();
00919 if (Palettizer::_read_pi_version >= 18) {
00920 _quality_level = (EggTexture::QualityLevel)scan.get_int32();
00921 }
00922 _anisotropic_degree = scan.get_int32();
00923
00924 manager->read_pointer(scan);
00925 manager->read_pointer(scan);
00926 }