diff --git a/src/terrain_3d_editor.cpp b/src/terrain_3d_editor.cpp index 93097d7f..72d41a1b 100644 --- a/src/terrain_3d_editor.cpp +++ b/src/terrain_3d_editor.cpp @@ -5,6 +5,7 @@ #include "logger.h" #include "terrain_3d_editor.h" +#include "util.h" /////////////////////////// // Subclass Functions @@ -54,6 +55,7 @@ void Terrain3DEditor::_operate_region(Vector3 p_global_position) { } } +uint64_t counter = 0; void Terrain3DEditor::_operate_map(Vector3 p_global_position, real_t p_camera_direction) { Ref storage = _terrain->get_storage(); int region_size = storage->get_region_size(); @@ -109,6 +111,12 @@ void Terrain3DEditor::_operate_map(Vector3 p_global_position, real_t p_camera_di } Object::cast_to(_terrain->get_plugin()->get("ui"))->call("set_decal_rotation", rot); + _range_buffer = MIN(_range_buffer + opacity * .01f, real_t(.115f)); + + if (counter++ % 30 == 0) { + LOG(WARN, "index: ", index, ", opacity: ", vformat("%.2f", opacity), ", range_buffer: ", vformat("%.2f", _range_buffer)); + } + for (int x = 0; x < brush_size; x++) { for (int y = 0; y < brush_size; y++) { Vector2i brush_offset = Vector2i(x, y) - (Vector2i(brush_size, brush_size) / 2); @@ -189,33 +197,97 @@ void Terrain3DEditor::_operate_map(Vector3 p_global_position, real_t p_camera_di } dest = Color(destf, 0.0f, 0.0f, 1.0f); storage->update_heights(destf); + map->set_pixelv(map_pixel_position, dest); } else if (map_type == Terrain3DStorage::TYPE_CONTROL) { real_t alpha_clip = (brush_alpha < 0.1f) ? 0.0f : 1.0f; - int index_base = int(src.r * 255.0f); - int index_overlay = int(src.g * 255.0f); - int dest_index = 0; + + // Get bit field from pixel + uint32_t bits; + *(real_t *)&bits = src.r; + uint32_t base_index = bits >> 27u & 0x1Fu; + uint32_t overlay_index = bits >> 22u & 0x1Fu; + uint32_t blend_index = bits >> 19u & 0x7u; + real_t blend = Terrain3DStorage::RANGE[blend_index]; + uint32_t dest_index = 0; switch (_operation) { + case Terrain3DEditor::REPLACE: + // Base Paint + //dest_index = uint32_t(Math::lerp(base_index, index, alpha_clip)); + //base_index = real_t(dest_index) / 255.0f; + //blend = Math::lerp(blend, real_t(0.0f), alpha_clip * opacity + _range_buffer); + + //dest_index = int(Math::lerp(index_base, index, brush_alpha > 0.1f)); + //dest.r = dest_index / 255.0f; + //dest.b = Math::lerp(real_t(src.b), real_t(0.0f), alpha_clip * opacity); + + //dest_index = (brush_alpha < 0.1f) ? base_index : index; + dest_index = int(Math::lerp(base_index, index, alpha_clip)); + base_index = dest_index; + overlay_index = dest_index; + blend = Math::lerp(blend, real_t(0.0f), alpha_clip * opacity + _range_buffer); + + //if (brush_alpha > 0.1f) { + // base_index = index; + // overlay_index = index; + // blend = 0.0f; + //} + break; case Terrain3DEditor::ADD: // Spray Overlay - dest_index = int(Math::lerp(index_overlay, index, alpha_clip)); - if (dest_index == index_base) { - dest.b = Math::lerp(real_t(src.b), real_t(0.0f), alpha_clip * opacity * real_t(0.5f)); + //dest_index = uint32_t(Math::lerp(overlay_index, index, alpha_clip)); + //dest_index = uint32_t(Math::lerp(overlay_index, index, alpha_clip)); + //if (dest_index == base_index) { + // blend = Math::lerp(blend, real_t(0.0f), alpha_clip * opacity * real_t(0.5f)+_range_buffer); + //} else { + // overlay_index = real_t(dest_index) / 255.0f; + // blend = Math::lerp(blend, CLAMP(blend + brush_alpha, real_t(0.0f), real_t(1.0f)), brush_alpha * opacity * real_t(0.5f)+_range_buffer); + //} + + //dest_index = int(Math::lerp(index_overlay, index, alpha_clip)); + //if (dest_index == index_base) { + // dest.b = Math::lerp(real_t(src.b), real_t(0.0f), alpha_clip * opacity * real_t(0.5f)); + //} else { + // dest.g = dest_index / 255.0f; + // dest.b = Math::lerp(real_t(src.b), CLAMP(src.b + brush_alpha, real_t(0.0f), real_t(1.0f)), brush_alpha * opacity * real_t(0.5f)); + //} + + //dest_index = (brush_alpha < 0.1f) ? overlay_index : index; + dest_index = int(Math::lerp(overlay_index, index, alpha_clip)); + if (dest_index == base_index) { + // why not brush_alpha? + real_t factor = CLAMP(alpha_clip * opacity * real_t(0.5f) + _range_buffer, real_t(0.f), real_t(1.f)); + blend = Math::lerp(blend, real_t(0.0f), factor); } else { - dest.g = dest_index / 255.0f; - dest.b = Math::lerp(real_t(src.b), CLAMP(src.b + brush_alpha, real_t(0.0f), real_t(1.0f)), brush_alpha * opacity * real_t(0.5f)); + overlay_index = dest_index; + real_t b = CLAMP(blend + brush_alpha, real_t(0.0f), real_t(1.0f)); + real_t factor = CLAMP(brush_alpha * opacity * real_t(0.5f) + _range_buffer, real_t(0.f), real_t(1.f)); + blend = Math::lerp(blend, b, factor); } - break; - case Terrain3DEditor::REPLACE: - // Base Paint - dest_index = int(Math::lerp(index_base, index, alpha_clip)); - dest.r = dest_index / 255.0f; - dest.b = Math::lerp(real_t(src.b), real_t(0.0f), alpha_clip * opacity); + + //if (brush_alpha > 0.0f) { + // overlay_index = index; + // real_t b = CLAMP(blend + brush_alpha, real_t(0.0f), real_t(1.0f)); + // real_t factor = CLAMP(brush_alpha * opacity * real_t(0.5f) + _range_buffer, real_t(0.f), real_t(1.f)); + // blend = Math::lerp(blend, b, factor); + //} break; default: break; } + + // Convert back to bit field + uint32_t base = (base_index & 0x1F) << 27; // 5 bits 32-28 + uint32_t over = (overlay_index & 0x1F) << 22; // 5 bits 27-23 + blend_index = Util::closest_index(blend, Terrain3DStorage::RANGE, 8); + blend_index <<= 19; // 3 bits 22-20 + bits = base | over | blend_index; + + // Write back to pixel in FORMAT_RF + src.r = *(real_t *)&bits; + map->set_pixelv(map_pixel_position, Color(src.r, 0.f, 0.f, 1.0f)); + } else if (map_type == Terrain3DStorage::TYPE_COLOR) { switch (_tool) { case COLOR: @@ -230,14 +302,13 @@ void Terrain3DEditor::_operate_map(Vector3 p_global_position, real_t p_camera_di * We round the final amount in tool_settings.gd:_on_picked(). * Tip: One can round to 2 decimal places like so: 0.01*round(100.0*a) */ - dest.a = Math::lerp(real_t(src.a), real_t(.5f + .5f *.01f) * roughness, brush_alpha * opacity); + dest.a = Math::lerp(real_t(src.a), real_t(.5f + .5f * .01f) * roughness, brush_alpha * opacity); break; default: break; } + map->set_pixelv(map_pixel_position, dest); } - - map->set_pixelv(map_pixel_position, dest); } } }