feat: implemented chunking
This commit is contained in:
parent
823d70a93c
commit
f5a78e10c7
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "core/object/class_db.h"
|
||||
#include "terrain_editor/point_primitive_node.h"
|
||||
#include "terrain_editor/terrain_chunk.h"
|
||||
#include "terrain_editor/terrain_mesh_editor.h"
|
||||
#include "terrain_editor/terrain_mesh_generator.h"
|
||||
#include "terrain_editor/terrain_primitive.h"
|
||||
|
|
@ -19,6 +20,7 @@ void initialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
|||
ClassDB::register_class<PointPrimitiveNode>();
|
||||
ClassDB::register_class<TerrainMeshEditor>();
|
||||
ClassDB::register_class<SaveData>();
|
||||
ClassDB::register_class<TerrainChunk>();
|
||||
}
|
||||
|
||||
void uninitialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
||||
|
|
|
|||
50
modules/terrain_editor/terrain_chunk.cpp
Normal file
50
modules/terrain_editor/terrain_chunk.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include "terrain_chunk.h"
|
||||
#include "terrain_editor/terrain_mesh_generator.h"
|
||||
|
||||
void TerrainChunk::_bind_methods() {}
|
||||
|
||||
void TerrainChunk::ready() {
|
||||
if ((this->generator = cast_to<TerrainMeshGenerator>(get_parent()))) {
|
||||
this->generator->connect(TerrainMeshGenerator::sig_primitives_changed, callable_mp(this, &self_type::on_terrain_changed));
|
||||
} else {
|
||||
print_error(vformat("Chunk %s ready without generator.", get_path()));
|
||||
return;
|
||||
}
|
||||
this->set_mesh(this->lod1);
|
||||
on_terrain_changed();
|
||||
}
|
||||
|
||||
void TerrainChunk::on_terrain_changed() {
|
||||
if (this->generator) {
|
||||
Vector3 const position{ get_global_position() };
|
||||
this->generator->generate_grid({ { position.x, position.z }, { this->size, this->size } }, this->mesh, this->lod1_detail);
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainChunk::_notification(int what) {
|
||||
switch (what) {
|
||||
default:
|
||||
return;
|
||||
case NOTIFICATION_READY:
|
||||
ready();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainChunk::set_size(float size) {
|
||||
this->size = size;
|
||||
on_terrain_changed();
|
||||
}
|
||||
|
||||
float TerrainChunk::get_size() const {
|
||||
return this->size;
|
||||
}
|
||||
|
||||
void TerrainChunk::set_lod1_detail(int detail) {
|
||||
this->lod1_detail = detail;
|
||||
on_terrain_changed();
|
||||
}
|
||||
|
||||
int TerrainChunk::get_lod1_detail() const {
|
||||
return this->lod1_detail;
|
||||
}
|
||||
26
modules/terrain_editor/terrain_chunk.h
Normal file
26
modules/terrain_editor/terrain_chunk.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include "scene/3d/mesh_instance_3d.h"
|
||||
class TerrainMeshGenerator;
|
||||
|
||||
class TerrainChunk : public MeshInstance3D {
|
||||
GDCLASS(TerrainChunk, MeshInstance3D);
|
||||
static void _bind_methods();
|
||||
void ready();
|
||||
void on_terrain_changed();
|
||||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
|
||||
public:
|
||||
void set_size(float size);
|
||||
float get_size() const;
|
||||
void set_lod1_detail(int detail);
|
||||
int get_lod1_detail() const;
|
||||
|
||||
private:
|
||||
Ref<ArrayMesh> lod1{ memnew(ArrayMesh) };
|
||||
TerrainMeshGenerator *generator{ nullptr };
|
||||
int lod1_detail{ 100 };
|
||||
float size{ 50 };
|
||||
};
|
||||
|
|
@ -2,9 +2,11 @@
|
|||
#include "core/math/math_funcs.h"
|
||||
#include "core/math/rect2.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/object.h"
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
#include "terrain_editor/macros.h"
|
||||
#include "terrain_editor/terrain_chunk.h"
|
||||
#include "terrain_editor/terrain_primitive.h"
|
||||
#include <limits>
|
||||
|
||||
|
|
@ -16,15 +18,55 @@ void TerrainMeshGenerator::_bind_methods() {
|
|||
BIND_HPROPERTY(Variant::OBJECT, vertex_color_gradient, PROPERTY_HINT_RESOURCE_TYPE, "Gradient");
|
||||
BIND_PROPERTY(Variant::FLOAT, color_gradient_start_height);
|
||||
BIND_PROPERTY(Variant::FLOAT, color_gradient_end_height);
|
||||
BIND_PROPERTY(Variant::FLOAT, chunk_size);
|
||||
BIND_PROPERTY(Variant::INT, lod1_detail);
|
||||
BIND_PROPERTY(Variant::INT, chunk_count);
|
||||
BIND_HPROPERTY(Variant::OBJECT, material, PROPERTY_HINT_RESOURCE_TYPE, "Material");
|
||||
ADD_SIGNAL(MethodInfo(sig_primitives_changed));
|
||||
ADD_SIGNAL(MethodInfo(sig_primitive_list_changed, PropertyInfo(Variant::ARRAY, "array", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:TerrainPrimitive", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE))));
|
||||
ClassDB::bind_method(D_METHOD("generate_grid", "area", "out_mesh", "side_points"), &self_type::generate_grid);
|
||||
}
|
||||
|
||||
void TerrainMeshGenerator::ready() {
|
||||
if (this->chunks.is_empty()) {
|
||||
rebuild_chunks();
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainMeshGenerator::on_configuration_changed() {
|
||||
emit_signal(sig_primitives_changed);
|
||||
}
|
||||
|
||||
void TerrainMeshGenerator::_notification(int what) {
|
||||
switch (what) {
|
||||
default:
|
||||
return;
|
||||
case NOTIFICATION_READY:
|
||||
ready();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainMeshGenerator::rebuild_chunks() {
|
||||
for (TerrainChunk *chunk : this->chunks) {
|
||||
chunk->queue_free();
|
||||
}
|
||||
this->chunks.clear();
|
||||
Vector3 origin{ -Vector3{ (float)chunks_per_side, 0, (float)chunks_per_side } * this->chunk_size / 2 };
|
||||
for (size_t chunk_y{ 0 }; chunk_y < this->chunks_per_side; ++chunk_y) {
|
||||
for (size_t chunk_x{ 0 }; chunk_x < this->chunks_per_side; ++chunk_x) {
|
||||
TerrainChunk *chunk{ memnew(TerrainChunk) };
|
||||
chunk->set_size(this->chunk_size);
|
||||
chunk->set_lod1_detail(this->lod1_detail);
|
||||
chunk->set_material_override(this->material);
|
||||
this->chunks.push_back(chunk);
|
||||
Vector3 offset{ Vector3{ (float)chunk_x, 0.f, (float)chunk_y } * this->chunk_size };
|
||||
chunk->set_position(origin + offset);
|
||||
add_child(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Color TerrainMeshGenerator::color_at_height(float height) const {
|
||||
float const mapped{ Math::remap(height, this->color_gradient_start_height, this->color_gradient_end_height, 0.f, 1.f) };
|
||||
return this->vertex_color_gradient.is_valid()
|
||||
|
|
@ -69,6 +111,7 @@ void TerrainMeshGenerator::generate_grid(Rect2 area, Ref<ArrayMesh> mesh, size_t
|
|||
mesh->clear_surfaces();
|
||||
surface->clear();
|
||||
Vector2 point_distance{ area.size / (float)side_points };
|
||||
++side_points;
|
||||
Vector2 at{ area.position };
|
||||
surface->begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||
for (size_t xpoint{ 0 }; xpoint < side_points; ++xpoint) {
|
||||
|
|
@ -76,7 +119,7 @@ void TerrainMeshGenerator::generate_grid(Rect2 area, Ref<ArrayMesh> mesh, size_t
|
|||
float const height{ evaluate_point(at) };
|
||||
surface->set_color(color_at_height(height));
|
||||
surface->set_uv({ at / area.size });
|
||||
surface->add_vertex({ at.x, height, at.y });
|
||||
surface->add_vertex({ at.x - area.position.x, height, at.y - area.position.y });
|
||||
at.y += point_distance.y;
|
||||
}
|
||||
at.y = area.position.y;
|
||||
|
|
@ -150,3 +193,42 @@ void TerrainMeshGenerator::set_color_gradient_end_height(float value) {
|
|||
float TerrainMeshGenerator::get_color_gradient_end_height() const {
|
||||
return this->color_gradient_end_height;
|
||||
}
|
||||
|
||||
void TerrainMeshGenerator::set_chunk_size(float size) {
|
||||
this->chunk_size = size;
|
||||
rebuild_chunks();
|
||||
}
|
||||
float TerrainMeshGenerator::get_chunk_size() const {
|
||||
return this->chunk_size;
|
||||
}
|
||||
void TerrainMeshGenerator::set_lod1_detail(int detail) {
|
||||
if (detail != this->lod1_detail) {
|
||||
this->lod1_detail = detail;
|
||||
rebuild_chunks();
|
||||
}
|
||||
}
|
||||
int TerrainMeshGenerator::get_lod1_detail() const {
|
||||
return this->lod1_detail;
|
||||
}
|
||||
|
||||
void TerrainMeshGenerator::set_chunk_count(int num) {
|
||||
if (num != this->chunks_per_side) {
|
||||
this->chunks_per_side = num;
|
||||
rebuild_chunks();
|
||||
}
|
||||
}
|
||||
|
||||
int TerrainMeshGenerator::get_chunk_count() const {
|
||||
return this->chunks_per_side;
|
||||
}
|
||||
|
||||
void TerrainMeshGenerator::set_material(Ref<Material> material) {
|
||||
this->material = material;
|
||||
for (TerrainChunk *chunk : this->chunks) {
|
||||
chunk->set_material_override(material);
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Material> TerrainMeshGenerator::get_material() const {
|
||||
return this->material;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,15 +5,22 @@
|
|||
#include "core/variant/callable.h"
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/resources/gradient.h"
|
||||
#include "scene/resources/material.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
#include "terrain_editor/terrain_chunk.h"
|
||||
#include "terrain_editor/terrain_primitive.h"
|
||||
|
||||
class TerrainMeshGenerator : public Node {
|
||||
GDCLASS(TerrainMeshGenerator, Node);
|
||||
static void _bind_methods();
|
||||
void ready();
|
||||
void on_configuration_changed();
|
||||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
void rebuild_chunks();
|
||||
|
||||
public:
|
||||
Color color_at_height(float height) const;
|
||||
float evaluate_point(Vector2 at) const;
|
||||
|
|
@ -26,6 +33,14 @@ public:
|
|||
float get_color_gradient_start_height() const;
|
||||
void set_color_gradient_end_height(float value);
|
||||
float get_color_gradient_end_height() const;
|
||||
void set_chunk_size(float size);
|
||||
float get_chunk_size() const;
|
||||
void set_lod1_detail(int detail);
|
||||
int get_lod1_detail() const;
|
||||
void set_chunk_count(int num);
|
||||
int get_chunk_count() const;
|
||||
void set_material(Ref<Material> material);
|
||||
Ref<Material> get_material() const;
|
||||
|
||||
private:
|
||||
Vector<Ref<TerrainPrimitive>> primitives{};
|
||||
|
|
@ -33,6 +48,11 @@ private:
|
|||
Ref<Gradient> vertex_color_gradient{};
|
||||
float color_gradient_start_height{ 0.f };
|
||||
float color_gradient_end_height{ 10.f };
|
||||
float chunk_size{ 100.f };
|
||||
int lod1_detail{ 25 };
|
||||
int chunks_per_side{ 10 };
|
||||
Vector<TerrainChunk *> chunks{};
|
||||
Ref<Material> material{};
|
||||
|
||||
private:
|
||||
Callable generation_changed{ callable_mp(this, &self_type::on_configuration_changed) };
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue