Skip to content

Commit

Permalink
[Forest] Small plants will now rotate to match the surface normal
Browse files Browse the repository at this point in the history
  • Loading branch information
PanosK92 committed Oct 24, 2023
1 parent f344f7c commit 8e6d748
Showing 1 changed file with 22 additions and 14 deletions.
36 changes: 22 additions & 14 deletions runtime/World/Components/Terrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ namespace Spartan
const vector<uint32_t>& indices,
uint32_t tree_count,
float max_slope_radians,
bool rotate_to_match_surface_normal,
float water_level,
float terrain_offset
)
Expand Down Expand Up @@ -293,24 +294,29 @@ namespace Spartan
// generate barycentric coordinates
float u = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
float v = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);

if (u + v > 1.0f)
{
u = 1.0f - u;
v = 1.0f - v;
}

Vector3 position = v0 + (u * (v1 - v0) + terrain_offset) + v * (v2 - v0);
Quaternion rotation = Quaternion::FromEulerAngles(0.0f, get_random_float(0.0f, 360.0f), 0.0f);
Vector3 scale = Vector3(get_random_float(0.5f, 1.5f));
// scale is a random value between 0.5 and 1.5
Vector3 scale = Vector3(get_random_float(0.5f, 1.5f));

// position is the barycentric coordinates multiplied by the vertices of the triangle, plus a terrain_offset to avoid floating object
Vector3 position = v0 + (u * (v1 - v0) + terrain_offset) + v * (v2 - v0);

// rotation is a random rotation around the Y axis, and then rotated to match the normal of the triangle
Quaternion rotate_to_normal = rotate_to_match_surface_normal ? Quaternion::FromToRotation(Vector3::Up, normal) : Quaternion::Identity;
Quaternion rotation = rotate_to_normal * Quaternion::FromEulerAngles(0.0f, get_random_float(0.0f, 360.0f), 0.0f);

// we are mapping 4 vector4 (c++ side, see vulka_pipeline.cpp) to 1 matrix (HLSL side), and the matrix
// memory layout is column-major, so we need to transpose to get it as row-major
transforms.push_back(Matrix(position, rotation, scale).Transposed());
}
else
{
// if the slope is too steep, try again
// if the slope is too steep or the object is underwater, try again
--i;
}
}
Expand Down Expand Up @@ -432,19 +438,21 @@ namespace Spartan
ProgressTracker::GetProgress(ProgressType::Terrain).JobDone();

// compute tree positions
uint32_t tree_count = 5000;
float max_slope = 30.0f * Math::Helper::DEG_TO_RAD;
float terrain_offset = -0.2f;
m_trees = generate_transforms(vertices, indices, tree_count, max_slope, m_water_level, terrain_offset);
uint32_t tree_count = 5000;
float max_slope = 30.0f * Math::Helper::DEG_TO_RAD;
bool rotate_match_surface_normal = false; // trees tend to grow upwards (they go for the sun)
float terrain_offset = -0.2f;
m_trees = generate_transforms(vertices, indices, tree_count, max_slope, rotate_match_surface_normal, m_water_level, terrain_offset);

// compute plant 1 positions
uint32_t plant_count = 20000;
max_slope = 40.0f * Math::Helper::DEG_TO_RAD;
terrain_offset = 0.0f;
m_plants_1 = generate_transforms(vertices, indices, plant_count, max_slope, m_water_level, terrain_offset);
uint32_t plant_count = 20000;
max_slope = 40.0f * Math::Helper::DEG_TO_RAD;
rotate_match_surface_normal = true; // small plants tend to grow towards the sun but they can have some wonky angles due to low mass
terrain_offset = 0.0f;
m_plants_1 = generate_transforms(vertices, indices, plant_count, max_slope, rotate_match_surface_normal, m_water_level, terrain_offset);

// compute plant 2 positions
m_plants_2 = generate_transforms(vertices, indices, plant_count, max_slope, m_water_level, terrain_offset);
m_plants_2 = generate_transforms(vertices, indices, plant_count, max_slope, rotate_match_surface_normal, m_water_level, terrain_offset);

if (on_complete)
{
Expand Down

0 comments on commit 8e6d748

Please sign in to comment.