From f71e77b7e3a66bf68cf88d6756c75f9dcbeb9035 Mon Sep 17 00:00:00 2001 From: Relintai Date: Wed, 21 Apr 2021 09:51:00 +0200 Subject: [PATCH] Lod margin corners. --- meshers/blocky/terra_mesher_blocky.cpp | 155 ++++++++++++++++++++++++- meshers/blocky/terra_mesher_blocky.h | 2 + 2 files changed, 152 insertions(+), 5 deletions(-) diff --git a/meshers/blocky/terra_mesher_blocky.cpp b/meshers/blocky/terra_mesher_blocky.cpp index b82cea7..4342567 100644 --- a/meshers/blocky/terra_mesher_blocky.cpp +++ b/meshers/blocky/terra_mesher_blocky.cpp @@ -211,6 +211,7 @@ void TerraMesherBlocky::add_chunk_lod(Ref chunk) { create_margin_zmax(chunk); create_margin_xmin(chunk); create_margin_xmax(chunk); + create_margin_corners(chunk); int x_size = chunk->get_size_x(); int z_size = chunk->get_size_z(); @@ -413,7 +414,7 @@ void TerraMesherBlocky::create_margin_zmin(Ref chunk) { for (int x = margin_start + 1; x < x_size + margin_start - 1; ++x) { - int prev_main_x = x - (x % lod_skip) ; + int prev_main_x = x - (x % lod_skip); int next_main_x = prev_main_x + lod_skip; next_main_x = CLAMP(next_main_x, 0, x_data_size); @@ -575,7 +576,7 @@ void TerraMesherBlocky::create_margin_zmax(Ref chunk) { for (int x = margin_start + 1; x < x_size + margin_start - 1; ++x) { - int prev_main_x = x - (x % lod_skip) ; + int prev_main_x = x - (x % lod_skip); int next_main_x = prev_main_x + lod_skip; next_main_x = CLAMP(next_main_x, 0, x_data_size); @@ -737,7 +738,7 @@ void TerraMesherBlocky::create_margin_xmin(Ref chunk) { for (int z = margin_start + 1; z < z_size + margin_start - 1; ++z) { - int prev_main_z = z - (z % lod_skip) ; + int prev_main_z = z - (z % lod_skip); int next_main_z = prev_main_z + lod_skip; next_main_z = CLAMP(next_main_z, 0, z_data_size); @@ -842,7 +843,7 @@ void TerraMesherBlocky::create_margin_xmin(Ref chunk) { } void TerraMesherBlocky::create_margin_xmax(Ref chunk) { - //if ((get_build_flags() & TerraChunkDefault::BUILD_FLAG_GENERATE_AO) != 0) + //if ((get_build_flags() & TerraChunkDefault::BUILD_FLAG_GENERATE_AO) != 0) // if (!chunk->get_channel(TerraChunkDefault::DEFAULT_CHANNEL_AO)) // chunk->generate_ao(); @@ -896,7 +897,7 @@ void TerraMesherBlocky::create_margin_xmax(Ref chunk) { for (int z = margin_start + 1; z < z_size + margin_start - 1; ++z) { - int prev_main_z = z - (z % lod_skip) ; + int prev_main_z = z - (z % lod_skip); int next_main_z = prev_main_z + lod_skip; next_main_z = CLAMP(next_main_z, 0, z_data_size); @@ -1000,6 +1001,150 @@ void TerraMesherBlocky::create_margin_xmax(Ref chunk) { } } +void TerraMesherBlocky::create_margin_corners(Ref chunk) { + create_face(chunk, 1, 2, 1, 2); + create_face(chunk, 1, 2, chunk->get_size_z() + chunk->get_margin_start() - 1, chunk->get_size_z() + chunk->get_margin_start()); + create_face(chunk, chunk->get_size_x() + chunk->get_margin_start() - 1, chunk->get_size_x() + chunk->get_margin_start(), 1, 2); + create_face(chunk, chunk->get_size_x() + chunk->get_margin_start() - 1, chunk->get_size_x() + chunk->get_margin_start(), chunk->get_size_z() + chunk->get_margin_start() - 1, chunk->get_size_z() + chunk->get_margin_start()); +} + +void TerraMesherBlocky::create_face(Ref chunk, int dataxmin, int dataxmax, int datazmin, int datazmax) { + //if ((get_build_flags() & TerraChunkDefault::BUILD_FLAG_GENERATE_AO) != 0) + // if (!chunk->get_channel(TerraChunkDefault::DEFAULT_CHANNEL_AO)) + // chunk->generate_ao(); + + float world_height = chunk->get_world_height(); + + float voxel_scale = get_voxel_scale(); + + uint8_t *channel_type = chunk->channel_get(_channel_index_type); + + if (!channel_type) + return; + + uint8_t *channel_isolevel = chunk->channel_get(_channel_index_isolevel); + + if (!channel_isolevel) + return; + + uint8_t *channel_color_r = NULL; + uint8_t *channel_color_g = NULL; + uint8_t *channel_color_b = NULL; + uint8_t *channel_ao = NULL; + uint8_t *channel_rao = NULL; + + Color base_light(_base_light_value, _base_light_value, _base_light_value); + Color light[4]{ Color(1, 1, 1), Color(1, 1, 1), Color(1, 1, 1), Color(1, 1, 1) }; + + bool use_lighting = (get_build_flags() & TerraChunkDefault::BUILD_FLAG_USE_LIGHTING) != 0; + bool use_ao = (get_build_flags() & TerraChunkDefault::BUILD_FLAG_USE_AO) != 0; + bool use_rao = (get_build_flags() & TerraChunkDefault::BUILD_FLAG_USE_RAO) != 0; + + if (use_lighting) { + channel_color_r = chunk->channel_get_valid(TerraChunkDefault::DEFAULT_CHANNEL_LIGHT_COLOR_R); + channel_color_g = chunk->channel_get_valid(TerraChunkDefault::DEFAULT_CHANNEL_LIGHT_COLOR_G); + channel_color_b = chunk->channel_get_valid(TerraChunkDefault::DEFAULT_CHANNEL_LIGHT_COLOR_B); + + if (use_ao) + channel_ao = chunk->channel_get_valid(TerraChunkDefault::DEFAULT_CHANNEL_AO); + + if (use_rao) + channel_rao = chunk->channel_get_valid(TerraChunkDefault::DEFAULT_CHANNEL_RANDOM_AO); + } + + int indexes[4] = { + chunk->get_data_index(dataxmax, datazmin), //x + 1 + chunk->get_data_index(dataxmin, datazmin), //x + chunk->get_data_index(dataxmin, datazmax), + chunk->get_data_index(dataxmax, datazmax), + }; + + uint8_t type = channel_type[indexes[0]]; + + if (type == 0) + return; + + Ref surface = _library->voxel_surface_get(type - 1); + + if (!surface.is_valid()) + return; + + uint8_t isolevels[] = { + channel_isolevel[indexes[0]], + channel_isolevel[indexes[1]], + channel_isolevel[indexes[2]], + channel_isolevel[indexes[3]], + }; + + if (use_lighting) { + for (int i = 0; i < 4; ++i) { + int indx = indexes[i]; + + light[i] = Color(channel_color_r[indx] / 255.0, + channel_color_g[indx] / 255.0, + channel_color_b[indx] / 255.0); + + float ao = 0; + + if (use_ao) + ao = channel_ao[indx] / 255.0; + + if (use_rao) { + float rao = channel_rao[indx] / 255.0; + ao += rao; + } + + light[i] += base_light; + + if (ao > 0) + light[i] -= Color(ao, ao, ao) * _ao_strength; + + light[i].r = CLAMP(light[i].r, 0, 1.0); + light[i].g = CLAMP(light[i].g, 0, 1.0); + light[i].b = CLAMP(light[i].b, 0, 1.0); + } + } + + int vc = get_vertex_count(); + add_indices(vc + 2); + add_indices(vc + 1); + add_indices(vc + 0); + add_indices(vc + 3); + add_indices(vc + 2); + add_indices(vc + 0); + + Vector2 uvs[] = { + surface->transform_uv_scaled(TerraSurface::TERRA_SIDE_TOP, Vector2(1, 0), dataxmin % get_texture_scale(), datazmin % get_texture_scale(), get_texture_scale()), + surface->transform_uv_scaled(TerraSurface::TERRA_SIDE_TOP, Vector2(0, 0), dataxmin % get_texture_scale(), datazmin % get_texture_scale(), get_texture_scale()), + surface->transform_uv_scaled(TerraSurface::TERRA_SIDE_TOP, Vector2(0, 1), dataxmin % get_texture_scale(), datazmin % get_texture_scale(), get_texture_scale()), + surface->transform_uv_scaled(TerraSurface::TERRA_SIDE_TOP, Vector2(1, 1), dataxmin % get_texture_scale(), datazmin % get_texture_scale(), get_texture_scale()) + }; + + Vector3 verts[] = { + Vector3(dataxmax, isolevels[0] / 255.0 * world_height, datazmin) * voxel_scale, + Vector3(dataxmin, isolevels[1] / 255.0 * world_height, datazmin) * voxel_scale, + Vector3(dataxmin, isolevels[2] / 255.0 * world_height, datazmax) * voxel_scale, + Vector3(dataxmax, isolevels[3] / 255.0 * world_height, datazmax) * voxel_scale + }; + + Vector3 normals[] = { + (verts[0] - verts[1]).cross(verts[0] - verts[2]).normalized(), + (verts[0] - verts[1]).cross(verts[1] - verts[2]).normalized(), + (verts[1] - verts[2]).cross(verts[2] - verts[0]).normalized(), + (verts[2] - verts[3]).cross(verts[3] - verts[0]).normalized(), + }; + + for (int i = 0; i < 4; ++i) { + add_normal(normals[i]); + + if (use_lighting || _always_add_colors) + add_color(light[i]); + + add_uv(uvs[i]); + add_vertex(verts[i]); + } +} + TerraMesherBlocky::TerraMesherBlocky() { _always_add_colors = false; _lod_index = 0; diff --git a/meshers/blocky/terra_mesher_blocky.h b/meshers/blocky/terra_mesher_blocky.h index 0d7b8e9..af32445 100644 --- a/meshers/blocky/terra_mesher_blocky.h +++ b/meshers/blocky/terra_mesher_blocky.h @@ -56,6 +56,8 @@ public: void create_margin_zmax(Ref chunk); void create_margin_xmin(Ref chunk); void create_margin_xmax(Ref chunk); + void create_margin_corners(Ref chunk); + void create_face(Ref chunk, int dataxmin, int dataxmax, int datazmin, int datazmax); TerraMesherBlocky(); ~TerraMesherBlocky();