cc: speedup terrain generation

This commit is contained in:
Crypto City 2020-08-07 02:35:50 +00:00
parent 1e9af40f21
commit 68f9accc79

View File

@ -39,6 +39,7 @@ static const int m_cellularDistanceIndex1 = 1;
#define MAX_TERRAIN_TILES 20
#define TERRAIN_TILE_SIZE 1024
#define HILLS_STEP 16
#define ATTENUATION_RANGE 4096
namespace cc
{
@ -1071,34 +1072,58 @@ static const std::shared_ptr<terrain_tile_t> require_terrain(const cc::cc_potent
uint16_t *data = generate_terrain(state->terrain_config, x0, y0);
const bool origin_close = state->ox + ATTENUATION_RANGE + TERRAIN_TILE_SIZE >= x0 && state->ox - ATTENUATION_RANGE + TERRAIN_TILE_SIZE <= x1 && state->oy + ATTENUATION_RANGE + TERRAIN_TILE_SIZE >= y0 && state->oy - ATTENUATION_RANGE + TERRAIN_TILE_SIZE <= y1;
Y = fixed_t(y0 - state->oy);
uint16_t *dptr = data;
for (uint32_t y = y0; y <= y1; ++y, Y += ONE)
static_assert(TERRAIN_TILE_SIZE % HILLS_STEP == 0, "HILLS_STEP must be a divisor of TERRAIN_TILE_SIZE");
const fixed_t FIXED_HILLS_STEP(HILLS_STEP);
for (uint32_t y = y0; y <= y1; y += HILLS_STEP, Y += FIXED_HILLS_STEP)
{
const uint32_t hy0 = (y - y0) / HILLS_STEP;
const uint32_t hdy = hy0 == TERRAIN_TILE_SIZE / HILLS_STEP - 1 ? 0 : 1;
fixed_t X = fixed_t(x0 - state->ox);
for (uint32_t x = x0; x <= x1; ++x, X += ONE)
for (uint32_t x = x0; x <= x1; x += HILLS_STEP, X += FIXED_HILLS_STEP)
{
const uint32_t hx0 = (x - x0) / HILLS_STEP;
const uint32_t hy0 = (y - y0) / HILLS_STEP;
const uint32_t hdx = hx0 == TERRAIN_TILE_SIZE / HILLS_STEP - 1 ? 0 : 1;
const uint32_t hdy = hy0 == TERRAIN_TILE_SIZE / HILLS_STEP - 1 ? 0 : 1;
const fixed_t c00(hills[hy0 * (TERRAIN_TILE_SIZE / HILLS_STEP) + hx0]);
const fixed_t c10(hills[hy0 * (TERRAIN_TILE_SIZE / HILLS_STEP) + hx0 + hdx]);
const fixed_t c01(hills[(hy0 + hdy) * (TERRAIN_TILE_SIZE / HILLS_STEP) + hx0]);
const fixed_t c11(hills[(hy0 + hdy) * (TERRAIN_TILE_SIZE / HILLS_STEP) + hx0 + hdx]);
const fixed_t xfrac = fixed_t((x - x0) % HILLS_STEP) / HILLS_STEP;
const fixed_t yfrac = fixed_t((y - y0) % HILLS_STEP) / HILLS_STEP;
int32_t p_hills = (c00 * (ONE - xfrac) * (ONE - yfrac) + c10 * xfrac * (ONE - yfrac) + c01 * (ONE - xfrac) * yfrac + c11 * xfrac * yfrac).get_int32_t();
if (p_hills > 0xffff) p_hills = 0xffff; else if (p_hills < 0) p_hills = 0;
const fixed_t f_dhills_left = (c01 - c00) / HILLS_STEP;
const fixed_t f_dhills_right = (c11 - c10) / HILLS_STEP;
fixed_t f_hills_left = c00;
fixed_t f_hills_right = c10;
for (uint32_t dy = 0; dy < HILLS_STEP; ++dy, f_hills_left += f_dhills_left, f_hills_right += f_dhills_right)
{
const fixed_t f_dhills = (f_hills_right - f_hills_left) / HILLS_STEP;
fixed_t f_hills = f_hills_left;
dptr = data + (y + dy - y0) * TERRAIN_TILE_SIZE + x - x0;
for (uint32_t dx = 0; dx < HILLS_STEP; ++dx, f_hills += f_dhills)
{
int32_t p_hills = f_hills.get_int32_t();
if (p_hills > 0xffff) p_hills = 0xffff; else if (p_hills < 0) p_hills = 0;
const uint32_t origin_dx = x < state->ox ? state->ox - x : x - state->ox;
const uint32_t origin_dy = y < state->oy ? state->oy - y : y - state->oy;
const uint32_t origin_d = std::max(origin_dx, origin_dy);
const uint32_t attenuation = std::min<uint32_t>(4096, origin_d);
if (origin_close)
{
const uint32_t origin_dx = x+dx < state->ox ? state->ox - (x+dx) : (x+dx) - state->ox;
const uint32_t origin_dy = y+dy < state->oy ? state->oy - (y+dy) : (y+dy) - state->oy;
const uint32_t origin_d = std::max(origin_dx, origin_dy);
const uint32_t attenuation = std::min<uint32_t>(ATTENUATION_RANGE, origin_d);
const uint16_t terrain = *dptr;
const uint32_t p = WITHOUT_TERRAIN_TYPE(terrain + (p_hills) * attenuation / 4096) | TERRAIN_TYPE(terrain);
*dptr++ = p > 0xffff ? 0xffff : p;
const uint16_t terrain = *dptr;
const uint32_t p = WITHOUT_TERRAIN_TYPE(terrain + (p_hills) * attenuation / ATTENUATION_RANGE) | TERRAIN_TYPE(terrain);
*dptr++ = p > 0xffff ? 0xffff : p;
}
else
{
const uint16_t terrain = *dptr;
const uint32_t p = WITHOUT_TERRAIN_TYPE(terrain + (p_hills)) | TERRAIN_TYPE(terrain);
*dptr++ = p > 0xffff ? 0xffff : p;
}
}
}
}
}