diff --git a/modules/terrain/terrain.cpp b/modules/terrain/terrain.cpp index f8d4eada..e09b054e 100644 --- a/modules/terrain/terrain.cpp +++ b/modules/terrain/terrain.cpp @@ -55,6 +55,32 @@ void Terrain::update_threads() { } } +void Terrain::synchronous_generate_terrain() { + this->workload_lock.lock(); + this->threads_stop = false; + this->workload.clear(); + this->workload.append_array(this->meshes); + for (Thread &thread : this->threads) { + if (!thread.is_started()) { + thread.start(&Terrain::generate_meshes_thread, this); + } + } + do { + this->workload_lock.unlock(); + Thread::yield(); + this->workload_lock.lock(); + } while (!this->workload.is_empty()); + this->threads_stop = true; + this->workload_lock.unlock(); + for (Thread &thread : this->threads) { + thread.wait_to_finish(); + } + for (TerrainChunkMesh *mesh : this->dirty_meshes) { + mesh->apply_new_mesh(); + } + this->dirty_meshes.clear(); +} + void Terrain::_notification(int what) { switch (what) { default: @@ -66,6 +92,7 @@ void Terrain::_notification(int what) { return; case NOTIFICATION_READY: construct_chunk_grid(); + synchronous_generate_terrain(); return; case NOTIFICATION_PROCESS: update_meshes(); diff --git a/modules/terrain/terrain.h b/modules/terrain/terrain.h index 64b79a06..7062fc26 100644 --- a/modules/terrain/terrain.h +++ b/modules/terrain/terrain.h @@ -15,6 +15,7 @@ class Terrain : public Node { void child_order_changed(); void update_meshes(); void update_threads(); + void synchronous_generate_terrain(); protected: void _notification(int what); diff --git a/modules/terrain/terrain_chunk.cpp b/modules/terrain/terrain_chunk.cpp index 1a5777eb..ab09e534 100644 --- a/modules/terrain/terrain_chunk.cpp +++ b/modules/terrain/terrain_chunk.cpp @@ -1,22 +1,54 @@ #include "terrain_chunk.h" +#include "core/math/math_defs.h" +#include "core/math/math_funcs.h" #include "core/variant/variant.h" +#include "scene/3d/physics/collision_shape_3d.h" +#include "scene/3d/physics/static_body_3d.h" +#include "scene/resources/3d/height_map_shape_3d.h" #include "scene/resources/surface_tool.h" #include "terrain/terrain.h" void TerrainChunkMesh::_bind_methods() {} +void TerrainChunkMesh::ready() { + this->position_buffer = get_global_position(); + float const sizef{ (float)get_size() }; + this->bounds.position = { this->position_buffer.x - sizef / 2.f, this->position_buffer.z - sizef / 2.f }; + this->bounds.size = { sizef, sizef }; + + add_child(this->body = memnew(StaticBody3D)); + ERR_FAIL_COND_EDMSG(this->body == nullptr, "Failed to instantiate StaticBody3D"); + this->body->add_child(this->collider = memnew(CollisionShape3D)); + this->body->set_owner(this); + ERR_FAIL_COND_EDMSG(this->collider == nullptr, "Failed to instantiate CollisionShape3D"); + this->collider->set_owner(this); + this->shape = memnew(HeightMapShape3D); + ERR_FAIL_COND_EDMSG(!this->shape.is_valid(), "Failed to instantiate HeightMapShape3D"); + this->collider->set_shape(this->shape); + this->shape->set_map_depth(heightmap_side_length()); + this->shape->set_map_width(heightmap_side_length()); +} + void TerrainChunkMesh::generate_vertices() { ERR_FAIL_COND_EDMSG(this->terrain == nullptr, "TerrainChunkMesh::generate_vertices: no terrain assigned"); ERR_FAIL_COND_EDMSG(this->size <= 0.f, "TerrainChunkMesh::generate_vertices: size <= 0"); ERR_FAIL_COND_EDMSG(points_per_side() <= 0, "TerrainChunkMesh::generate_vertices: points per side <= 0"); float const half_extent{ (float)this->size / 2.f }; float const point_distance{ (float)this->size / ((float)points_per_side() - 1) }; - Vector3 origin{ this->safe_position - Vector3{ half_extent, 0, half_extent } }; + Vector3 origin{ this->position_buffer - Vector3{ half_extent, 0, half_extent } }; for (size_t x{ 0 }; x < points_per_side(); ++x) { for (size_t y{ 0 }; y < points_per_side(); ++y) { Vector2 const coordinate{ origin.x + point_distance * x, origin.z + point_distance * y }; this->surface->set_uv({ (float)x / (float)points_per_side(), (float)y / (float)points_per_side() }); - this->surface->add_vertex({ coordinate.x - this->safe_position.x, this->terrain->height_at(coordinate), coordinate.y - this->safe_position.z }); + float height{ this->terrain->height_at(coordinate) }; + this->surface->add_vertex({ coordinate.x - this->position_buffer.x, height, coordinate.y - this->position_buffer.z }); + } + } + this->heightmap.resize_initialized(heightmap_side_length() * heightmap_side_length()); + for (size_t x{ 0 }; x < heightmap_side_length(); x++) { + for (size_t y{ 0 }; y < heightmap_side_length(); y++) { + Vector2 coordinate{ origin.x + x, origin.z + y }; + this->heightmap.set(x + y * heightmap_side_length(), this->terrain->height_at(coordinate)); } } } @@ -54,10 +86,7 @@ void TerrainChunkMesh::_notification(int what) { default: return; case NOTIFICATION_READY: - this->safe_position = get_global_position(); - float const sizef{ (float)get_size() }; - this->bounds.position = { this->safe_position.x - sizef / 2.f, this->safe_position.z - sizef / 2.f }; - this->bounds.size = { sizef, sizef }; + ready(); return; } } @@ -65,6 +94,11 @@ void TerrainChunkMesh::_notification(int what) { void TerrainChunkMesh::apply_new_mesh() { this->lock.lock(); set_mesh(this->new_mesh); + if (this->shape->get_map_depth() != heightmap_side_length() || this->shape->get_map_width() != heightmap_side_length()) { + this->shape->set_map_depth(heightmap_side_length()); + this->shape->set_map_width(heightmap_side_length()); + } + this->shape->set_map_data(heightmap); this->lock.unlock(); } @@ -87,3 +121,7 @@ void TerrainChunkMesh::update_mesh() { size_t TerrainChunkMesh::points_per_side() const { return this->size * this->detail; } + +int TerrainChunkMesh::heightmap_side_length() const { + return get_size() + 1; +} diff --git a/modules/terrain/terrain_chunk.h b/modules/terrain/terrain_chunk.h index 2e9ea49e..64b59218 100644 --- a/modules/terrain/terrain_chunk.h +++ b/modules/terrain/terrain_chunk.h @@ -3,6 +3,9 @@ #include "core/math/rect2.h" #include "macros.h" #include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/physics/collision_shape_3d.h" +#include "scene/3d/physics/static_body_3d.h" +#include "scene/resources/3d/height_map_shape_3d.h" #include "scene/resources/mesh.h" #include "scene/resources/surface_tool.h" class Terrain; @@ -10,6 +13,7 @@ class Terrain; class TerrainChunkMesh : public MeshInstance3D { GDCLASS(TerrainChunkMesh, MeshInstance3D); static void _bind_methods(); + void ready(); void generate_vertices(); void generate_faces(); @@ -20,10 +24,11 @@ public: void apply_new_mesh(); void update_mesh(); size_t points_per_side() const; + int heightmap_side_length() const; private: Mutex lock{}; - Vector3 safe_position{}; + Vector3 position_buffer{}; Ref surface{}; Ref new_mesh{}; Terrain *terrain{ nullptr }; @@ -31,6 +36,11 @@ private: size_t size{ 1 }; Rect2 bounds{}; + Ref shape{}; + StaticBody3D *body{ nullptr }; + CollisionShape3D *collider{ nullptr }; + Vector heightmap{}; + public: GET_SET_FNS(Rect2, bounds); GET_SET_FNS(Terrain *, terrain); diff --git a/project/assets/style/terrain_material.tres b/project/assets/style/terrain_material.tres index e915de60..b0badd89 100644 --- a/project/assets/style/terrain_material.tres +++ b/project/assets/style/terrain_material.tres @@ -48,8 +48,8 @@ shader_parameter/floor_3_tiling = 500.0 shader_parameter/floor_3_specular = 0.5 shader_parameter/floor_3_metallic = 0.5 shader_parameter/region_blending = 1.0 -shader_parameter/slope_threshold = 0.355 -shader_parameter/slope_blend_distance = 0.028 +shader_parameter/slope_threshold = 0.3 +shader_parameter/slope_blend_distance = 0.0 shader_parameter/slope_albedo = SubResource("NoiseTexture2D_pkl7k") shader_parameter/slope_tiling = 0.106 shader_parameter/slope_roughness = 0.7 diff --git a/project/assets/style/terrain_outline_material.tres b/project/assets/style/terrain_outline_material.tres index 37edd7e5..012ec7f0 100644 --- a/project/assets/style/terrain_outline_material.tres +++ b/project/assets/style/terrain_outline_material.tres @@ -2,9 +2,7 @@ [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_e6s0j"] render_priority = 1 -transparency = 2 -alpha_scissor_threshold = 1.0 -alpha_antialiasing_mode = 0 +transparency = 1 shading_mode = 0 albedo_color = Color(0, 0, 0, 1) grow = true diff --git a/project/scenes/terrain_test.tscn b/project/scenes/terrain_test.tscn index 35d59ae8..6ceebdd9 100644 --- a/project/scenes/terrain_test.tscn +++ b/project/scenes/terrain_test.tscn @@ -45,7 +45,7 @@ point_count = 2 [sub_resource type="Curve" id="Curve_4kj3c"] _limits = [0.0, 1.0, 0.0, 4.0] -_data = [Vector2(0.78173465, 1), 0.0, 0.0, 0, 0, Vector2(3.0802917, 0), 0.0, 0.0, 0, 0] +_data = [Vector2(1.1431929, 1), 0.0, 0.0, 0, 0, Vector2(3.4741035, 0), 0.0, 0.0, 0, 0] point_count = 2 [sub_resource type="BoxMesh" id="BoxMesh_kbmr5"] @@ -96,8 +96,8 @@ dof_blur_amount = 0.15 [sub_resource type="SphereMesh" id="SphereMesh_o3i6r"] flip_faces = true -radius = 1000.0 -height = 2000.0 +radius = 750.0 +height = 1500.0 [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_chm2y"] shading_mode = 0 @@ -106,7 +106,7 @@ specular_mode = 2 disable_ambient_light = true disable_fog = true disable_specular_occlusion = true -albedo_color = Color(0.3, 0.42, 0.6, 1) +albedo_color = Color(0.055481255, 0.09639085, 0.15917248, 1) [node name="Node3D" type="Node3D" unique_id=289500437] @@ -376,7 +376,7 @@ transform = Transform3D(1.0000001, 0, 0, 0, 1, 0, 0, 0, 1.0000001, -9.991547, -6 gizmo_extents = 5.0 [node name="TerrainModifierPathPoint23" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath16" unique_id=1120921338] -transform = Transform3D(1.0000004, 0, 0, 0, 1, 0, 0, 0, 1.0000004, -14.902985, -4.79982, -20.752014) +transform = Transform3D(1.0000007, 0, 0, 0, 1, 0, 0, 0, 1.0000007, -14.680634, -6.0471573, -22.171997) gizmo_extents = 5.0 [node name="TerrainModifierPath19" type="TerrainModifierPath" parent="Terrain" unique_id=1676642694] @@ -451,11 +451,8 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.441101, 0.8837204, 19.30413 [node name="TerrainModifierPathPoint21" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=1607100253] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.441101, 2.210205, 14.580994) -[node name="TerrainModifierPathPoint5" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=1820799746] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.534241, 5.0986557, 4.118469) - -[node name="TerrainModifierPathPoint6" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=2116612387] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6.9170227, 8.299988, -11.543091) +[node name="TerrainModifierPathPoint23" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=2000472843] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9.022736, 6.2285767, -4.9683228) [node name="TerrainModifierPathPoint7" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=1272225499] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.5455017, 10.130386, -23.116821) @@ -470,7 +467,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.5961, 11.085152, -18.563782 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13.502441, 12.257561, -3.0429688) [node name="TerrainModifierPathPoint11" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=43577796] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13.093262, 12.385696, 10.487976) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12.110291, 13.22065, 16.20935) [node name="TerrainModifierPathPoint12" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=1921440501] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 11.920105, 13.9776535, 22.744324) @@ -479,35 +476,26 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 11.920105, 13.9776535, 22.744 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15.705017, 14.232437, 23.40039) [node name="TerrainModifierPathPoint14" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=22432767] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 17.276093, 16.732018, 12.025452) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16.127441, 15.883354, 15.772705) [node name="TerrainModifierPathPoint16" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=159801860] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 17.724762, 18.037773, 3.9212646) -[node name="TerrainModifierPathPoint15" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=2059353099] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 17.2388, 19.639542, -3.52417) - [node name="TerrainModifierPathPoint17" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=1928936301] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16.626587, 21.457283, -9.916443) - -[node name="TerrainModifierPathPoint18" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=2071609159] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15.835022, 22.994705, -16.712402) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 16.948792, 21.457283, -11.136475) [node name="TerrainModifierPathPoint19" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=2055368136] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14.000671, 24.554016, -23.884766) - -[node name="TerrainModifierPathPoint20" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=1567587602] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18.630096, 24.856354, -23.92749) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14.000671, 24.39434, -23.884766) [node name="TerrainModifierPathPoint22" type="TerrainModifierPathPoint" parent="Terrain/TerrainModifierPath17" unique_id=1457562552] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 24.136475, 25.229156, -20.645813) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 26.076569, 24.770523, -26.303467) [node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1089775425] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 430.6339, 81.57795, 686.2748) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 415.88525, 69.94918, 697.9054) mesh = SubResource("BoxMesh_kbmr5") [node name="PlayerVehicle" parent="." unique_id=2037675333 instance=ExtResource("2_o3i6r")] -transform = Transform3D(-0.1691032, -0.0145671945, -0.9854907, -0.0020476654, 0.99989396, -0.014428737, 0.9855962, -0.00042199076, -0.16911517, 542.1524, 107.626686, 693.53375) +transform = Transform3D(-0.9999769, -0.002140658, -0.006432563, -0.0020476652, 0.9998938, -0.014428736, 0.006462857, -0.014415228, -0.99987507, 433.92926, 89.578415, 688.07916) [node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1509403058] environment = SubResource("Environment_1b7vx") @@ -515,6 +503,9 @@ camera_attributes = SubResource("CameraAttributesPractical_7eqww") compositor = SubResource("Compositor_n0ica") [node name="SkySphere" type="MeshInstance3D" parent="." unique_id=56834935] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 482.60254, 3.9775167, 432.92352) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 543.9732, 3.9775777, 555.09717) mesh = SubResource("SphereMesh_o3i6r") surface_material_override/0 = SubResource("StandardMaterial3D_chm2y") + +[node name="Camera3D" type="Camera3D" parent="." unique_id=241002743] +transform = Transform3D(-0.13388503, 0.50896627, -0.8503106, 0.0791636, 0.86078644, 0.5027721, 0.9878299, 0, -0.15553802, 388.02707, 99.978836, 697.3086)