Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions src/terrain_3d_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -692,18 +692,18 @@ Vector3 Terrain3DData::get_normal(const Vector3 &p_global_position) const {
return normal;
}

bool Terrain3DData::is_in_slope(const Vector3 &p_global_position, const Vector2 &p_slope_range, const bool p_invert) const {
real_t Terrain3DData::is_in_slope(const Vector3 &p_global_position, const Vector2 &p_slope_range, const bool p_invert) const {
// If slope is full range, it's disabled
const Vector2 slope_range = CLAMP(p_slope_range, V2_ZERO, Vector2(90.f, 90.f));
if (slope_range.y - slope_range.x > 89.99f) {
return true;
return real_t(1.f);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Casting float literals isn't necessary. Nor for the float math in the returns below. They'll be converted automatically for free. It's only necessary for some templates like Lerp or MIN/MAX because the linter is particular about the exact type.

}

// Adapted from get_normal to work with holes
Vector3 slope_normal;
{
if (get_region_idp(p_global_position) < 0) {
return false;
return real_t(0.f);
}
// Adapted from get_height() to work with holes
auto get_height = [&](Vector3 pos) -> real_t {
Expand All @@ -723,10 +723,22 @@ bool Terrain3DData::is_in_slope(const Vector3 &p_global_position, const Vector2
}

const real_t slope_angle = Math::acos(slope_normal.dot(Vector3(0.f, 1.f, 0.f)));
const real_t slope_angle_degrees = Math::rad_to_deg(slope_angle);
const real_t slope_angle_degrees = CLAMP(Math::rad_to_deg(slope_angle), 0.f, 90.f);

// XOR: If invert return !a || !b else return a && b
return p_invert ^ ((slope_range.x <= slope_angle_degrees) && (slope_angle_degrees <= slope_range.y));
if (p_invert ^ ((slope_range.x <= slope_angle_degrees) && (slope_angle_degrees <= slope_range.y))) {
return real_t(1.f);
}
// 1.0 -> 0.0 -> 1.0 inside range
if (p_invert) {
return real_t(ABS(2.f * (slope_angle_degrees - slope_range.x) / (slope_range.y - slope_range.x) - 1.f));
}
// 0.0 > 1.0 below range
if (slope_angle_degrees < slope_range.x) {
return real_t(slope_angle_degrees / slope_range.x);
}
// 1.0 -> 0.0 above above
return real_t((90.f - slope_angle_degrees) / (90.f - slope_range.y));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/terrain_3d_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ class Terrain3DData : public Object {
bool get_control_auto(const Vector3 &p_global_position) const;

Vector3 get_normal(const Vector3 &p_global_position) const;
bool is_in_slope(const Vector3 &p_global_position, const Vector2 &p_slope_range, const bool p_invert = false) const;
real_t is_in_slope(const Vector3 &p_global_position, const Vector2 &p_slope_range, const bool p_invert = false) const;
Vector3 get_texture_id(const Vector3 &p_global_position) const;
Vector3 get_mesh_vertex(const int32_t p_lod, const HeightFilter p_filter, const Vector3 &p_global_position) const;

Expand Down
20 changes: 8 additions & 12 deletions src/terrain_3d_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,13 +338,11 @@ void Terrain3DEditor::_operate_map(const Vector3 &p_global_position, const real_

switch (_tool) {
case TEXTURE: {
if (!data->is_in_slope(brush_global_position, slope_range, modifier_alt)) {
continue;
}
real_t slope_factor = pow(data->is_in_slope(brush_global_position, slope_range, modifier_alt), 8.f);
switch (_operation) {
// Base Paint
case REPLACE: {
if (brush_alpha > 0.5f) {
if (brush_alpha > 0.5f && slope_factor > 0.999f) {
if (enable_texture) {
// Set base & overlay texture
base_id = asset_id;
Expand Down Expand Up @@ -376,7 +374,7 @@ void Terrain3DEditor::_operate_map(const Vector3 &p_global_position, const real_
// Add asset id, and increase weighting
case ADD: {
real_t spray_strength = CLAMP(strength * 0.05f, 0.004f, .25f);
real_t brush_value = CLAMP(brush_alpha * spray_strength, 0.f, 1.f);
real_t brush_value = CLAMP(brush_alpha * spray_strength * slope_factor, 0.f, 1.f);
if (enable_texture && brush_alpha * strength * 11.f > 0.1f) {
// Pick lowest weighted id, and lower to zero before setting new asset id.
if (asset_id != base_id && asset_id != overlay_id) {
Expand Down Expand Up @@ -430,7 +428,7 @@ void Terrain3DEditor::_operate_map(const Vector3 &p_global_position, const real_
// Lower weight of current asset id
case SUBTRACT: {
real_t spray_strength = CLAMP(strength * 0.05f, 0.004f, .25f);
real_t brush_value = CLAMP(brush_alpha * spray_strength, 0.f, 1.f);
real_t brush_value = CLAMP(brush_alpha * spray_strength * slope_factor, 0.f, 1.f);
if (base_id == asset_id) {
blend = CLAMP(blend + brush_value, 0.f, 1.f);
}
Expand Down Expand Up @@ -494,12 +492,10 @@ void Terrain3DEditor::_operate_map(const Vector3 &p_global_position, const real_
continue;
}
}
if (!data->is_in_slope(brush_global_position, slope_range, modifier_alt)) {
continue;
}
real_t slope_factor = pow(data->is_in_slope(brush_global_position, slope_range, modifier_alt), 8.f);
switch (_tool) {
case COLOR:
dest = src.lerp((_operation == ADD) ? color : COLOR_WHITE, brush_alpha * strength);
dest = src.lerp((_operation == ADD) ? color : COLOR_WHITE, brush_alpha * strength * slope_factor);
dest.a = src.a;
break;
case ROUGHNESS:
Expand All @@ -511,10 +507,10 @@ void Terrain3DEditor::_operate_map(const Vector3 &p_global_position, const real_
*/
if (_operation == ADD) {
real_t target = .5f + .5f * roughness;
dest.a = Math::lerp(real_t(src.a), target, brush_alpha * strength);
dest.a = Math::lerp(real_t(src.a), target, brush_alpha * strength * slope_factor);
dest.a = float(int(dest.a * 255.f)) / 255.f; // Quantize explicitly so picked values match painted values
} else {
dest.a = Math::lerp(real_t(src.a), real_t(.5f), brush_alpha * strength);
dest.a = Math::lerp(real_t(src.a), real_t(.5f), brush_alpha * strength * slope_factor);
dest.a = float(int(dest.a * 255.f)) / 255.f;
}
break;
Expand Down
4 changes: 2 additions & 2 deletions src/terrain_3d_instancer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ Array Terrain3DInstancer::_get_usable_height(const Vector3 &p_global_position, c
height = raycast_height;
}
// No hole or collision, use height if in slope or quit
else if (!data->is_in_slope(p_global_position, p_slope_range, p_invert)) {
else if (!(data->is_in_slope(p_global_position, p_slope_range, p_invert) >= 0.999f)) {
return Array();
}
Array triple;
Expand Down Expand Up @@ -715,7 +715,7 @@ void Terrain3DInstancer::remove_instances(const Vector3 &p_global_position, cons
Vector3 height_offset = t.basis.get_column(1) * mesh_height_offset;
if (radial_distance < radius &&
UtilityFunctions::randf() < CLAMP(0.175f * strength, 0.005f, 10.f) &&
data->is_in_slope(t.origin + global_local_offset - height_offset, slope_range, invert)) {
data->is_in_slope(t.origin + global_local_offset - height_offset, slope_range, invert) > 0.9999f) {
_backup_region(region);
continue;
} else {
Expand Down
Loading