feat: bounds-based mesh reloading
This commit is contained in:
parent
953e4abe5b
commit
226c821454
7 changed files with 93 additions and 38 deletions
|
|
@ -78,6 +78,7 @@ void Terrain::construct_chunk_grid() {
|
|||
this->meshes.clear();
|
||||
size_t const chunks_per_side{ this->side_length / this->chunk_size };
|
||||
Vector3 const origin{ (float)this->chunk_size / 2.f, 0.f, (float)this->chunk_size / 2.f };
|
||||
this->workload_lock.lock();
|
||||
for (size_t y{ 0 }; y < chunks_per_side; ++y) {
|
||||
for (size_t x{ 0 }; x < chunks_per_side; ++x) {
|
||||
TerrainChunkMesh *chunk{ memnew(TerrainChunkMesh) };
|
||||
|
|
@ -88,8 +89,10 @@ void Terrain::construct_chunk_grid() {
|
|||
add_child(chunk);
|
||||
chunk->set_owner(this);
|
||||
this->meshes.push_back(chunk);
|
||||
this->workload.push_back(chunk);
|
||||
}
|
||||
}
|
||||
this->workload_lock.unlock();
|
||||
}
|
||||
|
||||
float Terrain::height_at(Vector2 world_coordinate) {
|
||||
|
|
@ -103,6 +106,16 @@ float Terrain::height_at(Vector2 world_coordinate) {
|
|||
return height;
|
||||
}
|
||||
|
||||
void Terrain::push_changed(Rect2 area) {
|
||||
for (TerrainChunkMesh *mesh : this->meshes) {
|
||||
this->workload_lock.lock();
|
||||
if (area.intersects(mesh->get_bounds()) && !this->workload.has(mesh)) {
|
||||
workload.push_back(mesh);
|
||||
}
|
||||
this->workload_lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::set_side_length(size_t length) {
|
||||
this->side_length = length;
|
||||
if (is_inside_tree()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/math/rect2.h"
|
||||
#include "core/os/mutex.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "core/templates/vector.h"
|
||||
|
|
@ -18,8 +19,8 @@ protected:
|
|||
|
||||
public:
|
||||
void construct_chunk_grid();
|
||||
void area_dirty(Vector2 from, Vector2 to);
|
||||
float height_at(Vector2 world_coordinate);
|
||||
void push_changed(Rect2 area);
|
||||
|
||||
private:
|
||||
Vector<TerrainChunkMesh *> workload{};
|
||||
|
|
|
|||
|
|
@ -60,8 +60,10 @@ void TerrainChunkMesh::_notification(int what) {
|
|||
default:
|
||||
return;
|
||||
case NOTIFICATION_READY:
|
||||
set_process_thread_group(ProcessThreadGroup::PROCESS_THREAD_GROUP_SUB_THREAD);
|
||||
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 };
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/math/rect2.h"
|
||||
#include "macros.h"
|
||||
#include "scene/3d/mesh_instance_3d.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
|
|
@ -28,8 +29,10 @@ private:
|
|||
Terrain *terrain{ nullptr };
|
||||
size_t detail{ 1 };
|
||||
size_t size{ 1 };
|
||||
Rect2 bounds{};
|
||||
|
||||
public:
|
||||
GET_SET_FNS(Rect2, bounds);
|
||||
GET_SET_FNS(Terrain *, terrain);
|
||||
GET_SET_FNS(size_t, detail);
|
||||
GET_SET_FNS(size_t, size);
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
#include "core/config/engine.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "macros.h"
|
||||
#include "terrain/terrain.h"
|
||||
#include <algorithm>
|
||||
|
||||
void TerrainModifier::_bind_methods() {
|
||||
BIND_HPROPERTY(Variant::INT, blend_mode, PROPERTY_HINT_ENUM, BlendMode_hint());
|
||||
BIND_PROPERTY(Variant::FLOAT, blend_distance);
|
||||
ADD_SIGNAL(MethodInfo(sig_changed));
|
||||
}
|
||||
|
||||
void TerrainModifier::_notification(int what) {
|
||||
|
|
@ -20,9 +20,6 @@ void TerrainModifier::_notification(int what) {
|
|||
}
|
||||
this->thread_safe_global_position = get_global_position();
|
||||
case NOTIFICATION_TRANSFORM_CHANGED:
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
emit_signal(sig_changed);
|
||||
}
|
||||
this->thread_safe_global_position = get_global_position();
|
||||
return;
|
||||
}
|
||||
|
|
@ -56,13 +53,10 @@ float TerrainModifier::blend(float under, float over) {
|
|||
}
|
||||
}
|
||||
|
||||
void TerrainModifier::changed() {
|
||||
this->dirty = true;
|
||||
emit_signal(sig_changed);
|
||||
}
|
||||
|
||||
void TerrainModifier::changed_deferred() {
|
||||
callable_mp(this, &self_type::changed).call_deferred();
|
||||
void TerrainModifier::push_changed(Rect2 area) {
|
||||
if (this->terrain) {
|
||||
this->terrain->push_changed(area);
|
||||
}
|
||||
}
|
||||
|
||||
float TerrainModifier::evaluate_at(Vector2 world_coordinate, float before) {
|
||||
|
|
@ -77,7 +71,6 @@ Vector3 TerrainModifier::get_thread_safe_global_position() const {
|
|||
|
||||
void TerrainModifier::set_blend_distance(float value) {
|
||||
this->blend_distance = value;
|
||||
emit_signal(sig_changed);
|
||||
}
|
||||
|
||||
float TerrainModifier::get_blend_distance() const {
|
||||
|
|
@ -86,15 +79,12 @@ float TerrainModifier::get_blend_distance() const {
|
|||
|
||||
void TerrainModifier::set_blend_mode(BlendMode mode) {
|
||||
this->blend_mode = mode;
|
||||
emit_signal(sig_changed);
|
||||
}
|
||||
|
||||
TerrainModifier::BlendMode TerrainModifier::get_blend_mode() const {
|
||||
return this->blend_mode;
|
||||
}
|
||||
|
||||
String const TerrainModifier::sig_changed{ "changed" };
|
||||
|
||||
void SharedMutex::lock_shared() {
|
||||
this->lock.lock();
|
||||
this->shared_count++;
|
||||
|
|
@ -127,15 +117,60 @@ void TerrainModifierDistance::_bind_methods() {
|
|||
}
|
||||
|
||||
void TerrainModifierDistance::curves_changed() {
|
||||
this->lock.lock_shared();
|
||||
this->lock.lock_exclusive();
|
||||
if (this->distance_height_curve.is_valid()) {
|
||||
this->distance_height_curve->bake();
|
||||
}
|
||||
if (this->distance_weight_curve.is_valid()) {
|
||||
this->distance_weight_curve->bake();
|
||||
}
|
||||
this->lock.unlock_exclusive();
|
||||
if (!update_bounds()) {
|
||||
push_changed(get_bounds());
|
||||
}
|
||||
}
|
||||
|
||||
bool TerrainModifierDistance::update_bounds() {
|
||||
Rect2 const before{ get_bounds() };
|
||||
Rect2 bounds{};
|
||||
Vector3 position{ get_thread_safe_global_position() };
|
||||
bounds.position = { position.x, position.z };
|
||||
bounds.size = { 0, 0 };
|
||||
this->lock.lock_shared();
|
||||
if (this->distance_weight_curve.is_valid()) {
|
||||
float const max_radius{ this->distance_weight_curve->get_max_domain() };
|
||||
float const max_diameter{ 2.f * max_radius };
|
||||
bounds.size = { max_diameter, max_diameter };
|
||||
bounds.position -= { max_radius, max_radius };
|
||||
}
|
||||
this->lock.unlock_shared();
|
||||
changed();
|
||||
this->lock.lock_exclusive();
|
||||
bool const changed{ before != bounds };
|
||||
if (changed) {
|
||||
set_bounds(bounds);
|
||||
push_changed(before);
|
||||
push_changed(bounds);
|
||||
}
|
||||
this->lock.unlock_exclusive();
|
||||
return changed;
|
||||
}
|
||||
|
||||
void TerrainModifierDistance::_notification(int what) {
|
||||
switch (what) {
|
||||
default:
|
||||
return;
|
||||
case NOTIFICATION_READY:
|
||||
update_bounds();
|
||||
set_notify_transform(true);
|
||||
return;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED:
|
||||
if (is_inside_tree()) {
|
||||
if (!update_bounds()) {
|
||||
push_changed(get_bounds());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float TerrainModifierDistance::distance_at(Vector2 const &world_coordinate) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "macros.h"
|
||||
#include "scene/3d/marker_3d.h"
|
||||
#include "scene/resources/curve.h"
|
||||
#include <cmath>
|
||||
class Terrain;
|
||||
|
||||
class TerrainModifier : public Marker3D {
|
||||
|
|
@ -16,9 +17,8 @@ public:
|
|||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
void changed();
|
||||
void changed_deferred();
|
||||
float blend(float under, float over);
|
||||
void push_changed(Rect2 bounds);
|
||||
|
||||
public:
|
||||
virtual float evaluate_at(Vector2 world_coordinate, float before);
|
||||
|
|
@ -27,8 +27,11 @@ private:
|
|||
float blend_distance{ 10.0 };
|
||||
BlendMode blend_mode{ Add };
|
||||
Vector3 thread_safe_global_position{};
|
||||
bool dirty{ false };
|
||||
Terrain *terrain{ nullptr };
|
||||
Rect2 bounds{ { -INFINITY, -INFINITY }, { INFINITY, INFINITY } };
|
||||
|
||||
protected:
|
||||
GET_SET_FNS(Rect2, bounds);
|
||||
|
||||
public:
|
||||
Vector3 get_thread_safe_global_position() const;
|
||||
|
|
@ -36,10 +39,7 @@ public:
|
|||
float get_blend_distance() const;
|
||||
void set_blend_mode(BlendMode mode);
|
||||
BlendMode get_blend_mode() const;
|
||||
GET_SET_FNS(bool, dirty);
|
||||
GET_SET_FNS(Terrain *, terrain);
|
||||
|
||||
static String const sig_changed;
|
||||
};
|
||||
|
||||
MAKE_TYPE_INFO(TerrainModifier::BlendMode, Variant::INT);
|
||||
|
|
@ -59,8 +59,10 @@ class TerrainModifierDistance : public TerrainModifier {
|
|||
GDCLASS(TerrainModifierDistance, TerrainModifier);
|
||||
static void _bind_methods();
|
||||
void curves_changed();
|
||||
bool update_bounds();
|
||||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
virtual float distance_at(Vector2 const &world_coordinate);
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -13,16 +13,16 @@ background_mode = 2
|
|||
sky = SubResource("Sky_w3uoq")
|
||||
|
||||
[sub_resource type="Curve" id="Curve_kbmr5"]
|
||||
_limits = [0.0, 1.0, 0.0, 200.0]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(123.87009, 0.38367254), -0.016318396, -0.016318396, 0, 0, Vector2(200, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 3
|
||||
_limits = [0.0, 1.0, 0.0, 500.0]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(76.609314, 0.6878389), -0.006221681, -0.006221681, 0, 0, Vector2(238.22075, 0.107827306), -0.0011518027, -0.0011518027, 0, 0, Vector2(500, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 4
|
||||
|
||||
[sub_resource type="Curve" id="Curve_w3uoq"]
|
||||
|
||||
[sub_resource type="Curve" id="Curve_chm2y"]
|
||||
_limits = [0.0, 1.0, 0.0, 200.0]
|
||||
_data = [Vector2(0, 1), 0.0, -0.010352392, 0, 0, Vector2(200, 0), 0.00017739221, -0.05797184, 0, 0]
|
||||
point_count = 2
|
||||
_limits = [0.0, 1.0, 0.0, 300.0]
|
||||
_data = [Vector2(0, 1), 0.0, -0.0043322877, 0, 0, Vector2(92.849304, 0.5972115), -0.0058290004, -0.0058290004, 0, 0, Vector2(300, 0), 0.00017739221, -0.05797184, 0, 0]
|
||||
point_count = 3
|
||||
|
||||
[sub_resource type="Curve" id="Curve_o3i6r"]
|
||||
_limits = [-30.0, 0.0, 0.0, 100.0]
|
||||
|
|
@ -30,8 +30,8 @@ _data = [Vector2(0, 0), 0.0, -0.56894803, 0, 0]
|
|||
point_count = 1
|
||||
|
||||
[sub_resource type="Curve" id="Curve_nonsf"]
|
||||
_limits = [0.0, 1.0, 0.0, 200.0]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(91.651596, 0.37567776), -0.0118739465, -0.0118739465, 0, 0, Vector2(200, 0), 0.0, 0.0, 0, 0]
|
||||
_limits = [0.0, 1.0, 0.0, 500.0]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(101.02984, 0.7462511), -0.0056187166, -0.0056187166, 0, 0, Vector2(500, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 3
|
||||
|
||||
[sub_resource type="Curve" id="Curve_4kj3c"]
|
||||
|
|
@ -48,23 +48,22 @@ environment = SubResource("Environment_o3i6r")
|
|||
|
||||
[node name="Terrain" type="Terrain" parent="." unique_id=1169843565]
|
||||
side_length = 1000
|
||||
chunk_size = 100
|
||||
thread_count = 4
|
||||
thread_count = 2
|
||||
|
||||
[node name="TerrainModifierDistance" type="TerrainModifierDistance" parent="Terrain" unique_id=1885116624]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 701.1817, 109.88881, 615.8812)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 544.8632, 188.56836, 713.1275)
|
||||
blend_distance = 4.0
|
||||
distance_weight_curve = SubResource("Curve_kbmr5")
|
||||
distance_height_curve = SubResource("Curve_w3uoq")
|
||||
|
||||
[node name="TerrainModifierDistance3" type="TerrainModifierDistance" parent="Terrain" unique_id=1846439541]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 138.05537, 108.75946, 327.30096)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 534.7505, 273.91986, 453.44415)
|
||||
blend_distance = 4.0
|
||||
distance_weight_curve = SubResource("Curve_chm2y")
|
||||
distance_height_curve = SubResource("Curve_o3i6r")
|
||||
|
||||
[node name="TerrainModifierDistance2" type="TerrainModifierDistance" parent="Terrain" unique_id=2110821264]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 183.81352, -28.866524, 195.71535)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 788.26746, -122.60801, 675.6073)
|
||||
blend_mode = 1
|
||||
distance_weight_curve = SubResource("Curve_nonsf")
|
||||
distance_height_curve = SubResource("Curve_4kj3c")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue