From 5889ad3e9b5c3b7ef1ee919d1201d5e137de0d0d Mon Sep 17 00:00:00 2001 From: Relintai Date: Wed, 21 Apr 2021 09:18:02 +0200 Subject: [PATCH] zmax lod seam. --- meshers/blocky/terra_mesher_blocky.cpp | 156 +++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/meshers/blocky/terra_mesher_blocky.cpp b/meshers/blocky/terra_mesher_blocky.cpp index 10fa941..b82cea7 100644 --- a/meshers/blocky/terra_mesher_blocky.cpp +++ b/meshers/blocky/terra_mesher_blocky.cpp @@ -842,6 +842,162 @@ 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 (!chunk->get_channel(TerraChunkDefault::DEFAULT_CHANNEL_AO)) + // chunk->generate_ao(); + + int z_size = chunk->get_size_x(); + int z_data_size = chunk->get_data_size_x(); + 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 margin_start = chunk->get_margin_start(); + + int lod_skip = _lod_index * 2; + //z_size + margin_start is fine, x, and z are in data space. + int x = chunk->get_size_x(); + float oolod = 1.0 / static_cast(lod_skip); + + for (int z = margin_start + 1; z < z_size + margin_start - 1; ++z) { + + 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); + + int indexes[4] = { + chunk->get_data_index(x + 1, z), //x + 1 + chunk->get_data_index(x, prev_main_z), //x + chunk->get_data_index(x, next_main_z), + chunk->get_data_index(x + 1, z + 1), + }; + + uint8_t type = channel_type[indexes[0]]; + + if (type == 0) + continue; + + Ref surface = _library->voxel_surface_get(type - 1); + + if (!surface.is_valid()) + continue; + + uint8_t isolevels[] = { + channel_isolevel[indexes[0]], + channel_isolevel[indexes[1]], + channel_isolevel[indexes[2]], + channel_isolevel[indexes[3]], + }; + + float z_interp = oolod * (z - prev_main_z); + float zp1_interp = 1.0 - (oolod * (next_main_z - (z + 1))); + + 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), x % get_texture_scale(), z % get_texture_scale(), get_texture_scale()), + surface->transform_uv_scaled(TerraSurface::TERRA_SIDE_TOP, Vector2(0, 0), x % get_texture_scale(), z % get_texture_scale(), get_texture_scale()), + surface->transform_uv_scaled(TerraSurface::TERRA_SIDE_TOP, Vector2(0, 1), x % get_texture_scale(), z % get_texture_scale(), get_texture_scale()), + surface->transform_uv_scaled(TerraSurface::TERRA_SIDE_TOP, Vector2(1, 1), x % get_texture_scale(), z % get_texture_scale(), get_texture_scale()) + }; + + float vi0 = Math::lerp(isolevels[1], isolevels[2], z_interp); + float vi1 = Math::lerp(isolevels[1], isolevels[2], zp1_interp); + + Vector3 verts[] = { + Vector3(x + 1, isolevels[0] / 255.0 * world_height, z) * voxel_scale, + Vector3(x, vi0 / 255.0 * world_height, z) * voxel_scale, + Vector3(x, vi1 / 255.0 * world_height, z + 1) * voxel_scale, + Vector3(x + 1, isolevels[3] / 255.0 * world_height, z + 1) * 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() {