Skip to content

Commit 39aead5

Browse files
committed
add transparency lookup tables for particle effects
1 parent 1594cb8 commit 39aead5

6 files changed

Lines changed: 90 additions & 0 deletions

File tree

‎src/Resource/ResourcePack.cpp‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,9 @@ Sound *ResourcePack::getSoundByDepth(unsigned int depth, unsigned int sound) con
277277
return getSound("BATTLE2.CAT", sound);
278278
}
279279

280+
const std::vector<std::vector<Uint8> > *ResourcePack::getLUTs() const
281+
{
282+
return &_transparencyLUTs;
283+
}
284+
280285
}

‎src/Resource/ResourcePack.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class ResourcePack
5858
std::map<std::string, SoundSet*> _sounds;
5959
std::map<std::string, Music*> _musics;
6060
std::vector<Uint16> _voxelData;
61+
std::vector<std::vector<Uint8> > _transparencyLUTs;
6162
public:
6263
static int DOOR_OPEN;
6364
static int SLIDING_DOOR_OPEN;
@@ -106,6 +107,8 @@ class ResourcePack
106107
std::vector<Uint16> *getVoxelData();
107108
/// Returns a specific sound from either the land or underwater resource set.
108109
Sound *getSoundByDepth(unsigned int depth, unsigned int sound) const;
110+
const std::vector<std::vector<Uint8> > *getLUTs() const;
111+
109112
};
110113

111114
}

‎src/Resource/XcomResourcePack.cpp‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "../Ruleset/ExtraSprites.h"
4545
#include "../Ruleset/ExtraSounds.h"
4646
#include "../Engine/AdlibMusic.h"
47+
#include "../fmath.h"
4748

4849
namespace OpenXcom
4950
{
@@ -76,6 +77,7 @@ struct HairBleach
7677
*/
7778
XcomResourcePack::XcomResourcePack(Ruleset *rules) : ResourcePack()
7879
{
80+
_ruleset = rules;
7981
// Load palettes
8082
const char *pal[] = {"PAL_GEOSCAPE", "PAL_BASESCAPE", "PAL_GRAPHS", "PAL_UFOPAEDIA", "PAL_BATTLEPEDIA"};
8183
for (size_t i = 0; i < sizeof(pal) / sizeof(pal[0]); ++i)
@@ -835,6 +837,7 @@ void XcomResourcePack::loadBattlescapeResources()
835837
SDL_Color *colors = tempSurface->getPalette();
836838
colors[255] = backPal[i];
837839
_palettes[pals[i]]->setColors(colors, 256);
840+
createTransparencyLUT(_palettes[pals[i]]);
838841
delete tempSurface;
839842
}
840843
}
@@ -1048,4 +1051,56 @@ Music *XcomResourcePack::loadMusic(MusicFormat fmt, const std::string &file, int
10481051
return music;
10491052
}
10501053

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+
10511106
}

‎src/Resource/XcomResourcePack.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ class Ruleset;
2929
class CatFile;
3030
class GMCatFile;
3131
class Music;
32+
class Palette;
3233

3334
/**
3435
* Resource pack for the X-Com: UFO Defense game.
3536
*/
3637
class XcomResourcePack : public ResourcePack
3738
{
39+
private:
40+
Ruleset *_ruleset;
3841
public:
3942
/// Creates the X-Com ruleset.
4043
XcomResourcePack(Ruleset *rules);
@@ -46,6 +49,8 @@ class XcomResourcePack : public ResourcePack
4649
bool isImageFile(std::string extension);
4750
/// Loads a specified music file.
4851
Music *loadMusic(MusicFormat fmt, const std::string &file, int track, float volume, CatFile *adlibcat, CatFile *aintrocat, GMCatFile *gmcat);
52+
/// Creates a transparency lookup table for a given palette.
53+
void createTransparencyLUT(Palette *pal);
4954
};
5055

5156
}

‎src/Ruleset/Ruleset.cpp‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,19 @@ void Ruleset::loadFile(const std::string &filename)
566566
ResourcePack::INTERCEPTOR_HIT = (*i)["intterceptorHit"].as<int>(ResourcePack::INTERCEPTOR_HIT);
567567
ResourcePack::INTERCEPTOR_EXPLODE = (*i)["interceptorExplode"].as<int>(ResourcePack::INTERCEPTOR_EXPLODE);
568568
}
569+
for (YAML::const_iterator i = doc["transparencyLUTs"].begin(); i != doc["transparencyLUTs"].end(); ++i)
570+
{
571+
for (YAML::const_iterator j = (*i)["colors"].begin(); j != (*i)["colors"].end(); ++j)
572+
{
573+
SDL_Color color;
574+
color.r = (*j)[0].as<int>(0);
575+
color.g = (*j)[1].as<int>(0);
576+
color.b = (*j)[2].as<int>(0);
577+
color.unused = (*j)[3].as<int>(2);;
578+
_transparencies.push_back(color);
579+
}
580+
}
581+
569582
// refresh _psiRequirements for psiStrengthEval
570583
for (std::vector<std::string>::const_iterator i = _facilitiesIndex.begin(); i != _facilitiesIndex.end(); ++i)
571584
{
@@ -1510,4 +1523,9 @@ const std::map<std::string, SoundDefinition *> *Ruleset::getSoundDefinitions() c
15101523
return &_soundDefs;
15111524
}
15121525

1526+
const std::vector<SDL_Color> *Ruleset::getTransparencies() const
1527+
{
1528+
return &_transparencies;
1529+
}
1530+
15131531
}

‎src/Ruleset/Ruleset.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <string>
2525
#include <yaml-cpp/yaml.h>
2626
#include "../Savegame/GameTime.h"
27+
#include <SDL.h>
2728

2829
namespace OpenXcom
2930
{
@@ -109,6 +110,7 @@ class Ruleset
109110
std::vector<std::string> _aliensIndex, _deploymentsIndex, _armorsIndex, _ufopaediaIndex, _researchIndex, _manufactureIndex, _MCDPatchesIndex;
110111
std::vector<std::string> _alienMissionsIndex, _terrainIndex, _extraSpritesIndex, _extraSoundsIndex, _extraStringsIndex;
111112
std::vector<std::vector<int> > _alienItemLevels;
113+
std::vector<SDL_Color> _transparencies;
112114
int _modIndex, _facilityListOrder, _craftListOrder, _itemListOrder, _researchListOrder, _manufactureListOrder, _ufopaediaListOrder, _invListOrder;
113115
std::vector<std::string> _psiRequirements; // it's a cache for psiStrengthEval
114116
/// Loads a ruleset from a YAML file.
@@ -245,6 +247,8 @@ class Ruleset
245247
RuleGlobe *getGlobe() const;
246248
/// Gets the list of selective files for insertion into our cat files.
247249
const std::map<std::string, SoundDefinition *> *getSoundDefinitions() const;
250+
/// Gets the list of transparency colors,
251+
const std::vector<SDL_Color> *getTransparencies() const;
248252
};
249253

250254
}

0 commit comments

Comments
 (0)