|
44 | 44 | #include "../Ruleset/ExtraSprites.h" |
45 | 45 | #include "../Ruleset/ExtraSounds.h" |
46 | 46 | #include "../Engine/AdlibMusic.h" |
| 47 | +#include "../fmath.h" |
47 | 48 |
|
48 | 49 | namespace OpenXcom |
49 | 50 | { |
@@ -76,6 +77,7 @@ struct HairBleach |
76 | 77 | */ |
77 | 78 | XcomResourcePack::XcomResourcePack(Ruleset *rules) : ResourcePack() |
78 | 79 | { |
| 80 | + _ruleset = rules; |
79 | 81 | // Load palettes |
80 | 82 | const char *pal[] = {"PAL_GEOSCAPE", "PAL_BASESCAPE", "PAL_GRAPHS", "PAL_UFOPAEDIA", "PAL_BATTLEPEDIA"}; |
81 | 83 | for (size_t i = 0; i < sizeof(pal) / sizeof(pal[0]); ++i) |
@@ -835,6 +837,7 @@ void XcomResourcePack::loadBattlescapeResources() |
835 | 837 | SDL_Color *colors = tempSurface->getPalette(); |
836 | 838 | colors[255] = backPal[i]; |
837 | 839 | _palettes[pals[i]]->setColors(colors, 256); |
| 840 | + createTransparencyLUT(_palettes[pals[i]]); |
838 | 841 | delete tempSurface; |
839 | 842 | } |
840 | 843 | } |
@@ -1048,4 +1051,56 @@ Music *XcomResourcePack::loadMusic(MusicFormat fmt, const std::string &file, int |
1048 | 1051 | return music; |
1049 | 1052 | } |
1050 | 1053 |
|
| 1054 | +/** |
| 1055 | + * Preamble: |
| 1056 | + * this is the most horrible function i've ever written, and it makes me sad. |
| 1057 | + * this is, however, a necessary evil, in order to save massive amounts of time in the draw function. |
| 1058 | + * when used with the default TFTD ruleset, this function loops 4,194,304 times |
| 1059 | + * (4 palettes, 4 tints, 4 levels of opacity, 256 colors, 256 comparisons per) |
| 1060 | + * each additional tint in the rulesets will result in over a million iterations more. |
| 1061 | + * @param pal the palette to base the lookup table on. |
| 1062 | + */ |
| 1063 | +void XcomResourcePack::createTransparencyLUT(Palette *pal) |
| 1064 | +{ |
| 1065 | + SDL_Color desiredColor; |
| 1066 | + std::vector<Uint8> lookUpTable; |
| 1067 | + // start with the color sets |
| 1068 | + for (std::vector<SDL_Color>::const_iterator tint = _ruleset->getTransparencies()->begin(); tint != _ruleset->getTransparencies()->end(); ++tint) |
| 1069 | + { |
| 1070 | + // then the opacity levels, using the alpha channel as the step |
| 1071 | + for (int opacity = 1; opacity < 1 + tint->unused * 4; opacity += tint->unused) |
| 1072 | + { |
| 1073 | + // then the palette itself |
| 1074 | + for (int currentColor = 0; currentColor < 256; ++currentColor) |
| 1075 | + { |
| 1076 | + // add the RGB values from the ruleset to those of the colors contained in the palette |
| 1077 | + // in order to determine the desired color |
| 1078 | + // yes all this casting and clamping is required, we're dealing with Uint8s here, and there's |
| 1079 | + // a lot of potential for values to wrap around, which would be very bad indeed. |
| 1080 | + desiredColor.r = std::min(255, (int)(pal->getColors(currentColor)->r) + (tint->r * opacity)); |
| 1081 | + desiredColor.g = std::min(255, (int)(pal->getColors(currentColor)->g) + (tint->g * opacity)); |
| 1082 | + desiredColor.b = std::min(255, (int)(pal->getColors(currentColor)->b) + (tint->b * opacity)); |
| 1083 | + |
| 1084 | + Uint8 closest = 0; |
| 1085 | + int lowestDifference = INT_MAX; |
| 1086 | + // now compare each color in the palette to find the closest match to our desired one |
| 1087 | + for (int comparator = 0; comparator < 256; ++comparator) |
| 1088 | + { |
| 1089 | + int currentDifference = Sqr(desiredColor.r - pal->getColors(comparator)->r) + |
| 1090 | + Sqr(desiredColor.g-pal->getColors(comparator)->g) + |
| 1091 | + Sqr(desiredColor.b-pal->getColors(comparator)->b); |
| 1092 | + |
| 1093 | + if (currentDifference < lowestDifference) |
| 1094 | + { |
| 1095 | + closest = comparator; |
| 1096 | + lowestDifference = currentDifference; |
| 1097 | + } |
| 1098 | + } |
| 1099 | + lookUpTable.push_back(closest); |
| 1100 | + } |
| 1101 | + } |
| 1102 | + } |
| 1103 | + _transparencyLUTs.push_back(lookUpTable); |
| 1104 | +} |
| 1105 | + |
1051 | 1106 | } |
0 commit comments