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