33 shape_border_x.clear();
34 shape_border_y.clear();
36 shape_pixnum.reserve(128);
44 if (!group.
LoadEntry(filename, &png_data))
return false;
47 assert(base_tex_wdt > 0);
48 int32_t zoom = png.
iWdt / base_tex_wdt;
49 if (base_tex_wdt * zoom !=
static_cast<int32_t
>(png.
iWdt) || base_tex_hgt * zoom !=
static_cast<int32_t
>(png.
iHgt))
51 LogF(
"ERROR: Material shape texture %s size (%d,%d) not a multiple of associated texture size (%d,%d). Not loading.", filename,
int(png.
iWdt),
int(png.
iHgt),
int(base_tex_wdt),
int(base_tex_hgt));
55 shape_border_x.resize(255,
false);
56 shape_border_y.resize(255,
false);
58 std::map<uint32_t, uint8_t> clr2shape;
59 std::vector<int32_t> first_px_pos_x(255), first_px_pos_y(255);
60 if (!data.
Create(base_tex_wdt, base_tex_hgt))
return false;
61 for (int32_t y = 0; y < data.
Hgt; ++y)
63 for (int32_t x = 0; x < data.
Wdt; ++x)
65 uint32_t px = png.
GetPix(x * zoom, y * zoom);
67 if ((px & 0xff000000u) == 0u)
76 auto shape_idx = clr2shape.find(px);
77 if (shape_idx == clr2shape.end())
81 clr2shape[px] = num_shapes;
82 shape_pixnum.push_back(1);
83 first_px_pos_x[num_shapes] = x;
84 first_px_pos_y[num_shapes] = y;
86 if (num_shapes >= 255)
88 LogF(
"Material shape texture %s invalid: Too many shape colors (>=255).", filename);
96 px_data = shape_idx->second;
97 ++shape_pixnum[px_data];
100 if (!x || x == data.
Wdt - 1) shape_border_x[px_data] =
true;
101 if (!y || y == data.
Hgt - 1) shape_border_y[px_data] =
true;
109 LogF(
"Shape texture summary for %s (%d x %d downscaled to %d x %d):", filename, (
int)png.
iWdt, (
int)png.
iHgt, (
int)base_tex_wdt, (
int)base_tex_wdt);
110 for (
auto iter : clr2shape)
112 unsigned int clr = iter.first;
114 LogF(
" Color 0x%08x: %d pixels. First seen pos: %d/%d", clr,
int(shape_pixnum[i]),
int(first_px_pos_x[i]),
int(first_px_pos_y[i]));
126 std::vector<int32_t> activation;
127 std::vector<uint8_t> back_pix;
128 int32_t block_x0, block_y0;
129 int32_t n_blocks_x, n_blocks_y;
133 int32_t Idx(int32_t block_x, int32_t block_y, int32_t shape_idx, int32_t xpart, int32_t ypart)
const;
136 C4TextureShapeActivationMap(int32_t block_x0, int32_t block_y0, int32_t n_blocks_x, int32_t n_blocks_y, int32_t num_shapes) : block_x0(block_x0), block_y0(block_y0), n_blocks_x(n_blocks_x), n_blocks_y(n_blocks_y), num_shapes(num_shapes)
138 activation.resize(n_blocks_x * n_blocks_y * num_shapes * 4, 0);
139 back_pix.resize(n_blocks_x * n_blocks_y * num_shapes * 4, 0u);
142 int32_t
Get(int32_t block_x, int32_t block_y, int32_t shape_idx, int32_t xpart, int32_t ypart, uint8_t *bg_pix)
const;
143 void Add(int32_t block_x, int32_t block_y, int32_t shape_idx, int32_t xpart, int32_t ypart, uint8_t back_pix);
146 int32_t C4TextureShapeActivationMap::Idx(int32_t block_x, int32_t block_y, int32_t shape_idx, int32_t xpart, int32_t ypart)
const
149 block_x -= block_x0; block_y -= block_y0;
150 if (!
Inside(block_x, 0, n_blocks_x - 1) || !
Inside(block_y, 0, n_blocks_y - 1))
return -1;
151 return ypart + 2 * (xpart + 2 * (shape_idx + num_shapes * (block_x + n_blocks_x * block_y)));
157 int32_t idx = Idx(block_x, block_y, shape_idx, xpart, ypart);
159 if (idx < 0)
return 0;
160 *bg_pix = back_pix[idx];
161 return activation[idx];
167 int32_t idx = Idx(block_x, block_y, shape_idx, xpart, ypart);
174 back_pix[idx] = bg_pix;
178 void C4TextureShape::Draw(
const CSurface8 &sfcMap,
const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY, int32_t MapZoom, int32_t min_overlap_ratio)
181 if (!num_shapes)
return;
184 int32_t x0 = std::max<int32_t>(0, iMapX*MapZoom + iOffX -
GetMaxPolyWidth()),
190 int32_t rblock_x0 = x0 / data.
Wdt;
191 int32_t rblock_y0 = y0 / data.
Hgt;
192 int32_t rblock_x1 = (x1 - 1) / data.
Wdt + 1;
193 int32_t rblock_y1 = (y1 - 1) / data.
Hgt + 1;
194 int32_t n_blocks_x = rblock_x1 - rblock_x0 + 1;
195 int32_t n_blocks_y = rblock_y1 - rblock_y0 + 1;
201 for (int32_t map_y = iMapY; map_y < iMapY + iMapHgt; ++map_y)
203 for (int32_t map_x = iMapX; map_x < iMapX + iMapWdt; ++map_x)
205 if (sfcMap.
GetPix(map_x, map_y) == iTexture)
209 const BYTE pixBkg = sfcMapBkg.
GetPix(map_x, map_y);
211 int32_t px_check_rate = 1;
212 for (int32_t pxo_y = 0; pxo_y < MapZoom; pxo_y += px_check_rate)
214 int32_t px_y = map_y * MapZoom + pxo_y + iOffY;
215 int32_t spx_y = px_y % data.
Hgt;
216 int32_t block_y = px_y / data.
Hgt;
217 for (int32_t pxo_x = 0; pxo_x < MapZoom; pxo_x += px_check_rate)
219 int32_t px_x = map_x * MapZoom + pxo_x + iOffX;
220 int32_t spx_x = px_x % data.
Wdt;
221 int32_t block_x = px_x / data.
Wdt;
224 if (shape_idx == Shape_None)
continue;
226 int32_t block_x1 = block_x, block_x2 = block_x;
228 if (shape_border_x[shape_idx])
231 if (spx_x < data.
Wdt / 2)
243 int32_t block_y1 = block_y, block_y2 = block_y;
244 if (shape_border_y[shape_idx]) {
if (spx_y < data.
Hgt / 2) --block_y2;
else ++block_y1; }
250 activation.
Add(block_x1, block_y1, shape_idx, 0, 0, pixBkg);
251 activation.
Add(block_x2, block_y1, shape_idx, 1, 0, pixBkg);
252 activation.
Add(block_x1, block_y2, shape_idx, 0, 1, pixBkg);
253 activation.
Add(block_x2, block_y2, shape_idx, 1, 1, pixBkg);
261 for (int32_t y = y0; y < y1; ++y)
263 int32_t block_y = y / data.
Hgt;
264 int32_t blockpos_y = y % data.
Hgt;
265 int32_t subblock_y = (blockpos_y >= data.
Hgt / 2) ? 1 : 0;
266 for (int32_t x = x0; x < x1; ++x)
268 int32_t block_x = x / data.
Wdt;
269 int32_t blockpos_x = x % data.
Wdt;
270 int32_t subblock_x = (blockpos_x >= data.
Wdt / 2) ? 1 : 0;
271 int32_t shape_idx = data.
_GetPix(blockpos_x, blockpos_y);
272 if (shape_idx == Shape_None)
continue;
274 int32_t act = activation.
Get(block_x, block_y, shape_idx, subblock_x, subblock_y, &pixBg);
275 if (!act || act < shape_pixnum[shape_idx] * min_overlap_ratio / 100)
continue;
bool LogF(const char *strMessage,...)
bool Inside(T ival, U lbound, V rbound)
int32_t DebugShapeTextures
C4ConfigDeveloper Developer
bool LoadEntry(const char *entry_name, char **buffer, size_t *size_info=nullptr, int zeros_to_append=0)
bool _SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix)
int32_t GetHeight() const
void Add(int32_t block_x, int32_t block_y, int32_t shape_idx, int32_t xpart, int32_t ypart, uint8_t back_pix)
C4TextureShapeActivationMap(int32_t block_x0, int32_t block_y0, int32_t n_blocks_x, int32_t n_blocks_y, int32_t num_shapes)
int32_t Get(int32_t block_x, int32_t block_y, int32_t shape_idx, int32_t xpart, int32_t ypart, uint8_t *bg_pix) const
void Draw(const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY, int32_t MapZoom, int32_t min_overlap_ratio)
bool Load(C4Group &group, const char *filename, int32_t base_tex_wdt, int32_t base_tex_hgt)
int32_t GetMaxPolyHeight() const
int32_t GetMaxPolyWidth() const
bool Load(BYTE *pFile, int iSize)
DWORD GetPix(int iX, int iY)
BYTE _GetPix(int x, int y) const
BYTE GetPix(int iX, int iY) const
bool Create(int iWdt, int iHgt)
void _SetPix(int iX, int iY, BYTE byCol)