|
|
|
@ -170,7 +170,7 @@ static void analyze_texture(unsigned char* texBytes, int numBytes, const Color p |
|
|
|
desaturate(outTexture.dominantColor.channel, outTexture.dominantColor.channel); |
|
|
|
} |
|
|
|
|
|
|
|
bool process_textures(const world_t* world, TextureList& outTextures) // TODO: return TextureDescriptor structs, including average texture color
|
|
|
|
bool process_textures(const world_t* world, TextureList& outTextures) |
|
|
|
{ |
|
|
|
using spaces_type = rectpack2D::empty_spaces<false>; |
|
|
|
using rect_type = rectpack2D::output_rect_t<spaces_type>; |
|
|
|
@ -259,6 +259,8 @@ bool process_textures(const world_t* world, TextureList& outTextures) // TODO: r |
|
|
|
|
|
|
|
printf("Constructing texture atlas...\n"); |
|
|
|
|
|
|
|
std::unordered_map<std::string, std::unordered_map<int, int>> animationFrames; |
|
|
|
|
|
|
|
// Try to construct the texture atlas, see what we get
|
|
|
|
for (int texNum = 0; texNum < world->mipheader.numtex; ++texNum) |
|
|
|
{ |
|
|
|
@ -269,10 +271,6 @@ bool process_textures(const world_t* world, TextureList& outTextures) // TODO: r |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
char* outName = miptex->name; |
|
|
|
if (*outName == '*' || *outName == '+') |
|
|
|
outName++; |
|
|
|
|
|
|
|
TextureDescriptor tex = { 0 }; |
|
|
|
|
|
|
|
for (int mipLevel = 0; mipLevel < 4; ++mipLevel) |
|
|
|
@ -290,14 +288,33 @@ bool process_textures(const world_t* world, TextureList& outTextures) // TODO: r |
|
|
|
|
|
|
|
tex.w = (u_char)rectangle.w; |
|
|
|
tex.h = (u_char)rectangle.h; |
|
|
|
|
|
|
|
|
|
|
|
u_short x = (rectangle.x / 2) + outTim.imgXoffs; // Divide by 2 to get the coordinate in 16-bit pixel units
|
|
|
|
u_short y = rectangle.y + outTim.imgYoffs; |
|
|
|
|
|
|
|
tex.ps1tex.tpage = getTPage(outTim.format, 0, x, y); |
|
|
|
tex.uoffs = (u_char)((x % 64) << (2 - outTim.format)); |
|
|
|
tex.voffs = (u_char)(y & 0xFF); |
|
|
|
// TODO: animated textures
|
|
|
|
|
|
|
|
if (miptex->name[0] == '+') |
|
|
|
{ |
|
|
|
// Animated texture
|
|
|
|
int frameNum = miptex->name[1] - '0'; |
|
|
|
if (frameNum >= 0 && frameNum <= 9) |
|
|
|
{ |
|
|
|
std::string animName = &miptex->name[2]; |
|
|
|
animationFrames[animName][frameNum] = texNum; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
frameNum = miptex->name[1] - 'a'; |
|
|
|
if (frameNum >= 0 && frameNum <= 9) |
|
|
|
{ |
|
|
|
std::string animName = std::string(&miptex->name[2]) + "_alt"; |
|
|
|
animationFrames[animName][frameNum] = texNum; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -307,6 +324,24 @@ bool process_textures(const world_t* world, TextureList& outTextures) // TODO: r |
|
|
|
outTextures.push_back(tex); |
|
|
|
} |
|
|
|
|
|
|
|
// Link animated texture frames together
|
|
|
|
for (auto animIter = animationFrames.cbegin(); animIter != animationFrames.cend(); ++animIter) |
|
|
|
{ |
|
|
|
const auto& frames = animIter->second; |
|
|
|
for (auto frameIter = frames.cbegin(); frameIter != frames.cend(); ++frameIter) |
|
|
|
{ |
|
|
|
int frameNum = frameIter->first; |
|
|
|
int texNum = frameIter->second; |
|
|
|
auto& texture = outTextures[texNum]; |
|
|
|
|
|
|
|
const auto& nextFrameIter = frames.find(frameNum + 1); |
|
|
|
if (nextFrameIter != frames.cend()) |
|
|
|
texture.ps1tex.nextframe = nextFrameIter->second; |
|
|
|
else |
|
|
|
texture.ps1tex.nextframe = frames.find(0)->second; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
sprintf_s(path, _MAX_PATH, "atlas-%s.tim", world->name); |
|
|
|
tim::ExportFile(path, &outTim); |
|
|
|
|
|
|
|
|