[Fix] Visible lighting seems between chunks.
Server now generates and sends an expanded 34x34 heightmap for each chunk, which includes a 1-vertex border containing height information from all adjacent chunks. Client ChunkMesh class updated to consume this extra data, allowing it to calcualte perfectly accurate normal vectors for all vertices, including those at the very edge of a chunk.
This commit is contained in:
parent
fa7159587d
commit
e35c4b5d61
@ -8,10 +8,14 @@ namespace Game {
|
|||||||
const int CHUNK_WIDTH = 32;
|
const int CHUNK_WIDTH = 32;
|
||||||
const int CHUNK_HEIGHT = 32;
|
const int CHUNK_HEIGHT = 32;
|
||||||
|
|
||||||
|
const int CHUNK_BORDER_SIZE = 1;
|
||||||
|
const int CHUNK_DATA_WIDTH = CHUNK_WIDTH + CHUNK_BORDER_SIZE * 2;
|
||||||
|
const int CHUNK_DATA_HEIGHT = CHUNK_HEIGHT + CHUNK_BORDER_SIZE * 2;
|
||||||
|
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
std::vector<float> heightmap;
|
std::vector<float> heightmap;
|
||||||
|
|
||||||
Chunk(void) : heightmap(CHUNK_WIDTH * CHUNK_HEIGHT) {}
|
Chunk(void) : heightmap(CHUNK_DATA_WIDTH * CHUNK_DATA_HEIGHT) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace Game. */
|
} /* namespace Game. */
|
||||||
|
|||||||
@ -21,7 +21,10 @@ inline float get_height_at(const BettolaLib::Game::Chunk& chunk, float local_x,
|
|||||||
if(local_x < 0 || local_x > max_coord || local_z < 0 || local_z > max_coord) {
|
if(local_x < 0 || local_x > max_coord || local_z < 0 || local_z > max_coord) {
|
||||||
int x = std::max(0, std::min((int)local_x, CHUNK_WIDTH - 1));
|
int x = std::max(0, std::min((int)local_x, CHUNK_WIDTH - 1));
|
||||||
int z = std::max(0, std::min((int)local_z, CHUNK_HEIGHT - 1));
|
int z = std::max(0, std::min((int)local_z, CHUNK_HEIGHT - 1));
|
||||||
return chunk.heightmap[z*CHUNK_WIDTH+x] * 5.0f; /* Apply height scaling. */
|
/* Adjust index for border. */
|
||||||
|
int data_x = x + CHUNK_BORDER_SIZE;
|
||||||
|
int data_z = z + CHUNK_BORDER_SIZE;
|
||||||
|
return chunk.heightmap[data_z*CHUNK_DATA_WIDTH+data_x] * 5.0f; /* Apply height scaling. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get integer and fracctional parts of the coords. */
|
/* Get integer and fracctional parts of the coords. */
|
||||||
@ -31,10 +34,14 @@ inline float get_height_at(const BettolaLib::Game::Chunk& chunk, float local_x,
|
|||||||
float z_frac = local_z - z_int;
|
float z_frac = local_z - z_int;
|
||||||
|
|
||||||
/* Get heights of the four corners of the grid cell. */
|
/* Get heights of the four corners of the grid cell. */
|
||||||
float h00 = chunk.heightmap[z_int * CHUNK_WIDTH+x_int];
|
/* Adjust indices for bordder. */
|
||||||
float h10 = chunk.heightmap[z_int * CHUNK_WIDTH+(x_int+1)];
|
int x0 = x_int + CHUNK_BORDER_SIZE;
|
||||||
float h01 = chunk.heightmap[(z_int+1) * CHUNK_WIDTH+x_int];
|
int z0 = z_int + CHUNK_BORDER_SIZE;
|
||||||
float h11 = chunk.heightmap[(z_int+1) * CHUNK_WIDTH+(x_int+1)];
|
|
||||||
|
float h00 = chunk.heightmap[z0 * CHUNK_DATA_WIDTH + x0];
|
||||||
|
float h10 = chunk.heightmap[z0 * CHUNK_DATA_WIDTH + (x0+1)];
|
||||||
|
float h01 = chunk.heightmap[(z0+1) * CHUNK_DATA_WIDTH + x0];
|
||||||
|
float h11 = chunk.heightmap[(z0+1) * CHUNK_DATA_WIDTH + (x0+1)];
|
||||||
|
|
||||||
/* Bilinear interpolation. */
|
/* Bilinear interpolation. */
|
||||||
float h_x0 = h00 * (1 - x_frac) + h10 * x_frac;
|
float h_x0 = h00 * (1 - x_frac) + h10 * x_frac;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ namespace Network {
|
|||||||
struct ChunkMessage {
|
struct ChunkMessage {
|
||||||
int chunk_x;
|
int chunk_x;
|
||||||
int chunk_z;
|
int chunk_z;
|
||||||
float heightmap[BettolaLib::Game::CHUNK_WIDTH * BettolaLib::Game::CHUNK_HEIGHT];
|
float heightmap[Game::CHUNK_DATA_WIDTH*Game::CHUNK_DATA_HEIGHT];
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace Network. */
|
} /* namespace Network. */
|
||||||
|
|||||||
@ -10,8 +10,13 @@ ChunkMesh::ChunkMesh(int chunk_x, int chunk_z, const BettolaLib::Game::Chunk& ch
|
|||||||
for(int z = 0; z < BettolaLib::Game::CHUNK_HEIGHT; ++z) {
|
for(int z = 0; z < BettolaLib::Game::CHUNK_HEIGHT; ++z) {
|
||||||
for(int x = 0; x < BettolaLib::Game::CHUNK_WIDTH; ++x) {
|
for(int x = 0; x < BettolaLib::Game::CHUNK_WIDTH; ++x) {
|
||||||
/* Vertex position. */
|
/* Vertex position. */
|
||||||
|
/* Index into the full 34x34 data array, offsetting by the border size. */
|
||||||
|
int data_x = x + BettolaLib::Game::CHUNK_BORDER_SIZE;
|
||||||
|
int data_z = z + BettolaLib::Game::CHUNK_BORDER_SIZE;
|
||||||
|
|
||||||
_vertices.push_back((float)(chunk_x * (BettolaLib::Game::CHUNK_WIDTH-1) + x));
|
_vertices.push_back((float)(chunk_x * (BettolaLib::Game::CHUNK_WIDTH-1) + x));
|
||||||
_vertices.push_back(chunk.heightmap[z * BettolaLib::Game::CHUNK_WIDTH+x] * 5.0f); /* 5x scale height */
|
/* 5x scale height */
|
||||||
|
_vertices.push_back(chunk.heightmap[data_z * BettolaLib::Game::CHUNK_DATA_WIDTH+data_x]*5.0f);
|
||||||
_vertices.push_back((float)(chunk_z * (BettolaLib::Game::CHUNK_HEIGHT-1) + z));
|
_vertices.push_back((float)(chunk_z * (BettolaLib::Game::CHUNK_HEIGHT-1) + z));
|
||||||
|
|
||||||
/* Vertex normal. */
|
/* Vertex normal. */
|
||||||
@ -47,12 +52,15 @@ ChunkMesh::ChunkMesh(int chunk_x, int chunk_z, const BettolaLib::Game::Chunk& ch
|
|||||||
|
|
||||||
BettolaMath::Vec3 ChunkMesh::_calculate_normal(int x, int z, const BettolaLib::Game::Chunk& chunk) {
|
BettolaMath::Vec3 ChunkMesh::_calculate_normal(int x, int z, const BettolaLib::Game::Chunk& chunk) {
|
||||||
/* Get heights of adjacent certices. */
|
/* Get heights of adjacent certices. */
|
||||||
float height_l = chunk.heightmap[z*BettolaLib::Game::CHUNK_WIDTH+(x>0?x-1 : x)] * 5.0f;
|
/* Index into the full 34x34 data array, offsetting by the border size. */
|
||||||
float height_r = chunk.heightmap[z*BettolaLib::Game::CHUNK_WIDTH+
|
int data_x = x + BettolaLib::Game::CHUNK_BORDER_SIZE;
|
||||||
(x<BettolaLib::Game::CHUNK_WIDTH-1?x+1 : x)]*5.0f;
|
int data_z = z + BettolaLib::Game::CHUNK_BORDER_SIZE;
|
||||||
float height_d = chunk.heightmap[(z>0?z-1 : z)*BettolaLib::Game::CHUNK_WIDTH+x]*5.0f;
|
|
||||||
float height_u = chunk.heightmap[(z<BettolaLib::Game::CHUNK_HEIGHT-1?z+1 : z)
|
/* Thanks for the border.. We can sample adjacent vertices without boundary checks now. */
|
||||||
* BettolaLib::Game::CHUNK_WIDTH+x]*5.0f;
|
float height_l = chunk.heightmap[data_z*BettolaLib::Game::CHUNK_DATA_WIDTH+(data_x-1)] * 5.0f;
|
||||||
|
float height_r = chunk.heightmap[data_z*BettolaLib::Game::CHUNK_DATA_WIDTH+(data_x+1)] * 5.0f;
|
||||||
|
float height_d = chunk.heightmap[(data_z-1)*BettolaLib::Game::CHUNK_DATA_WIDTH+data_x] * 5.0f;
|
||||||
|
float height_u = chunk.heightmap[(data_z+1)*BettolaLib::Game::CHUNK_DATA_WIDTH+data_x] * 5.0f;
|
||||||
|
|
||||||
BettolaMath::Vec3 normal = { height_l - height_r, 2.0f, height_d - height_u };
|
BettolaMath::Vec3 normal = { height_l - height_r, 2.0f, height_d - height_u };
|
||||||
|
|
||||||
|
|||||||
@ -21,14 +21,16 @@ BettolaLib::Game::Chunk& World::get_chunk(int x, int z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::_generate_chunk(BettolaLib::Game::Chunk& chunk, int chunk_x, int chunk_z) {
|
void World::_generate_chunk(BettolaLib::Game::Chunk& chunk, int chunk_x, int chunk_z) {
|
||||||
for(int z = 0; z < BettolaLib::Game::CHUNK_HEIGHT; ++z) {
|
for(int z = 0; z < BettolaLib::Game::CHUNK_DATA_HEIGHT; ++z) {
|
||||||
for(int x = 0; x < BettolaLib::Game::CHUNK_WIDTH; ++x) {
|
for(int x = 0; x < BettolaLib::Game::CHUNK_DATA_WIDTH; ++x) {
|
||||||
/* Calculate world coordinates. */
|
/* Calculate world coordinates. */
|
||||||
float world_x = (float)(chunk_x * (BettolaLib::Game::CHUNK_WIDTH - 1) + x);
|
float world_x = (float)(chunk_x * (BettolaLib::Game::CHUNK_WIDTH - 1)
|
||||||
float world_z = (float)(chunk_z * (BettolaLib::Game::CHUNK_HEIGHT - 1) + z);
|
+ (x - BettolaLib::Game::CHUNK_BORDER_SIZE));
|
||||||
|
float world_z = (float)(chunk_z * (BettolaLib::Game::CHUNK_HEIGHT - 1)
|
||||||
|
+ (z + BettolaLib::Game::CHUNK_BORDER_SIZE));
|
||||||
|
|
||||||
/* generate noise value. */
|
/* generate noise value. */
|
||||||
chunk.heightmap[z * BettolaLib::Game::CHUNK_WIDTH + x] = m_noise.GetNoise(world_x, world_z);
|
chunk.heightmap[z * BettolaLib::Game::CHUNK_DATA_WIDTH + x] = m_noise.GetNoise(world_x, world_z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user