Index: ps/trunk/source/lib/tex/tex.h =================================================================== --- ps/trunk/source/lib/tex/tex.h +++ ps/trunk/source/lib/tex/tex.h @@ -333,6 +333,14 @@ u8* get_data(); /** + * return a pointer to the mip level image data (pixels). + * + * @param level which level's data should be returned. + * @return pointer to the data. + **/ + u8* GetMipLevelData(const u32 level); + + /** * return the ARGB value of the 1x1 mipmap level of the texture. * * @return ARGB value (or 0 if texture does not have mipmaps) Index: ps/trunk/source/lib/tex/tex.cpp =================================================================== --- ps/trunk/source/lib/tex/tex.cpp +++ ps/trunk/source/lib/tex/tex.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -20,24 +20,19 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * support routines for 2d texture access/writing. - */ - #include "precompiled.h" -#include "tex.h" -#include -#include -#include +#include "tex.h" -#include "lib/timer.h" -#include "lib/bits.h" #include "lib/allocators/shared_ptr.h" +#include "lib/bits.h" #include "lib/sysdep/cpu.h" +#include "lib/tex/tex_codec.h" +#include "lib/timer.h" -#include "tex_codec.h" - +#include +#include +#include static const StatusDefinition texStatusDefinitions[] = { { ERR::TEX_FMT_INVALID, L"Invalid/unsupported texture format" }, @@ -633,10 +628,35 @@ u8* p = m_Data.get(); if(!p) - return 0; + return nullptr; return p + m_Ofs; } +u8* Tex::GetMipLevelData(const u32 level) +{ + // (can't use normal CHECK_TEX due to u8* return value) + WARN_IF_ERR(validate()); + + u8* levelData = m_Data.get(); + if (!levelData) + return nullptr; + levelData += m_Ofs; + const size_t dataPadding = (m_Flags & TEX_DXT) != 0 ? 4 : 1; + size_t levelWidth = m_Width, levelHeight = m_Height; + for (u32 currentLevel = 0; levelWidth > 1 || levelHeight > 1; ++currentLevel) + { + if (currentLevel == level) + return levelData; + + const size_t levelDataSize = round_up(levelWidth, dataPadding) * round_up(levelHeight, dataPadding) * m_Bpp / 8; + levelData += levelDataSize; + + levelWidth = std::max(levelWidth / 2, 1); + levelHeight = std::max(levelHeight / 2, 1); + } + return nullptr; +} + // returns color of 1x1 mipmap level u32 Tex::get_average_color() const { Index: ps/trunk/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp =================================================================== --- ps/trunk/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp +++ ps/trunk/source/tools/atlas/GameInterface/Handlers/TerrainHandlers.cpp @@ -86,7 +86,7 @@ // Check that we can fit the texture into the preview size before any transform. texture.m_Width >= width && texture.m_Height >= height && // Transform to a single format that we can process. - texture.transform_to((texture.m_Flags) & ~(TEX_DXT | TEX_MIPMAPS | TEX_GREY | TEX_BGR)) == INFO::OK && + texture.transform_to((texture.m_Flags | TEX_MIPMAPS) & ~(TEX_DXT | TEX_GREY | TEX_BGR)) == INFO::OK && (texture.m_Bpp == 24 || texture.m_Bpp == 32); if (canUsePreview) { @@ -95,14 +95,17 @@ ++level; // Extract the middle section (as a representative preview), // and copy into buffer. - u8* data = texture.get_data(); - const size_t dataShiftX = ((texture.m_Width - width) / 2) >> level; - const size_t dataShiftY = ((texture.m_Height - height) / 2) >> level; + u8* data = texture.GetMipLevelData(level); + ENSURE(data); + const size_t levelWidth = texture.m_Width >> level; + const size_t levelHeight = texture.m_Height >> level; + const size_t dataShiftX = (levelWidth - width) / 2; + const size_t dataShiftY = (levelHeight - height) / 2; for (size_t y = 0; y < height; ++y) for (size_t x = 0; x < width; ++x) { const size_t bufferOffset = (y * width + x) * previewBPP; - const size_t dataOffset = (((y << level) + dataShiftY) * texture.m_Width + (x << level) + dataShiftX) * texture.m_Bpp / 8; + const size_t dataOffset = ((y + dataShiftY) * levelWidth + x + dataShiftX) * texture.m_Bpp / 8; buffer[bufferOffset + 0] = data[dataOffset + 0]; buffer[bufferOffset + 1] = data[dataOffset + 1]; buffer[bufferOffset + 2] = data[dataOffset + 2];