feat: implemented terrain editor plumbing
This commit is contained in:
parent
76dd9fbc62
commit
81ac67c623
2
.dir-locals.el
Normal file
2
.dir-locals.el
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
((cpp-mode . ((mode . clang-format-on-save))))
|
||||||
|
((c-mode . ((mode . c++))))
|
||||||
|
|
@ -17,4 +17,12 @@
|
||||||
ADD_PROPERTY(PropertyInfo(m_type, #m_property), "set_" #m_property, \
|
ADD_PROPERTY(PropertyInfo(m_type, #m_property), "set_" #m_property, \
|
||||||
"get_" #m_property)
|
"get_" #m_property)
|
||||||
|
|
||||||
|
#define __VA_ARGS__STRING(...) String(#__VA_ARGS__)
|
||||||
|
|
||||||
|
#define GDENUM(M_Name, ...) \
|
||||||
|
enum M_Name { __VA_ARGS__ }; \
|
||||||
|
static String M_Name##_hint() { \
|
||||||
|
return __VA_ARGS__STRING(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !GODOT_EXTRA_MACROS_H
|
#endif // !GODOT_EXTRA_MACROS_H
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,19 @@
|
||||||
#include "register_types.h"
|
#include "register_types.h"
|
||||||
|
|
||||||
#include "core/object/class_db.h"
|
#include "core/object/class_db.h"
|
||||||
|
#include "terrain_editor/terrain_mesh_generator.h"
|
||||||
|
#include "terrain_editor/terrain_primitive.h"
|
||||||
|
|
||||||
void initialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
void initialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
||||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ClassDB::register_class<TerrainMeshGenerator>();
|
||||||
|
ClassDB::register_abstract_class<TerrainPrimitive>();
|
||||||
|
ClassDB::register_class<PlanePrimitive>();
|
||||||
|
ClassDB::register_class<PointPrimitive>();
|
||||||
|
ClassDB::register_class<NoisePrimitive>();
|
||||||
|
ClassDB::register_class<ExpressionPrimitive>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void uninitialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
void uninitialize_terrain_editor_module(ModuleInitializationLevel p_level) {
|
||||||
|
|
|
||||||
150
modules/terrain_editor/terrain_mesh_generator.cpp
Normal file
150
modules/terrain_editor/terrain_mesh_generator.cpp
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
#include "terrain_mesh_generator.h"
|
||||||
|
#include "core/io/resource_saver.h"
|
||||||
|
#include "core/math/math_funcs.h"
|
||||||
|
#include "core/math/rect2.h"
|
||||||
|
#include "core/object/class_db.h"
|
||||||
|
#include "core/templates/local_vector.h"
|
||||||
|
#include "scene/resources/surface_tool.h"
|
||||||
|
#include "terrain_editor/macros.h"
|
||||||
|
#include "terrain_editor/terrain_primitive.h"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
String const TerrainMeshGenerator::sig_primitives_changed{ "primitives_changed" };
|
||||||
|
|
||||||
|
void TerrainMeshGenerator::_bind_methods() {
|
||||||
|
BIND_HPROPERTY(Variant::ARRAY, primitives, PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:TerrainPrimitive", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE));
|
||||||
|
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);
|
||||||
|
ADD_SIGNAL(MethodInfo(sig_primitives_changed));
|
||||||
|
ClassDB::bind_method(D_METHOD("generate_grid", "area", "out_mesh", "side_points"), &self_type::generate_grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainMeshGenerator::on_configuration_changed() {
|
||||||
|
emit_signal(sig_primitives_changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
? this->vertex_color_gradient->get_color_at_offset(mapped)
|
||||||
|
: Color{ mapped, mapped, mapped, 1.f };
|
||||||
|
}
|
||||||
|
|
||||||
|
float TerrainMeshGenerator::evaluate_point(Vector2 at) const {
|
||||||
|
float height{ -std::numeric_limits<float>::infinity() };
|
||||||
|
for (Ref<TerrainPrimitive> primitive : this->primitives) {
|
||||||
|
if (primitive.is_valid()) {
|
||||||
|
primitive->evaluate(at, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void face_from(Ref<SurfaceTool> surface, size_t tl, size_t side_points) {
|
||||||
|
LocalVector<SurfaceTool::Vertex> &vertices{ surface->get_vertex_array() };
|
||||||
|
float d1{ vertices[tl].vertex.distance_to(vertices[tl + side_points + 1].vertex) };
|
||||||
|
float d2{ vertices[tl + 1].vertex.distance_to(vertices[tl + side_points].vertex) };
|
||||||
|
if (d1 < d2) {
|
||||||
|
surface->add_index(tl);
|
||||||
|
surface->add_index(tl + side_points + 1);
|
||||||
|
surface->add_index(tl + 1);
|
||||||
|
|
||||||
|
surface->add_index(tl);
|
||||||
|
surface->add_index(tl + side_points);
|
||||||
|
surface->add_index(tl + side_points + 1);
|
||||||
|
} else {
|
||||||
|
surface->add_index(tl + side_points);
|
||||||
|
surface->add_index(tl + side_points + 1);
|
||||||
|
surface->add_index(tl + 1);
|
||||||
|
|
||||||
|
surface->add_index(tl + 1);
|
||||||
|
surface->add_index(tl);
|
||||||
|
surface->add_index(tl + side_points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainMeshGenerator::generate_grid(Rect2 area, Ref<ArrayMesh> mesh, size_t side_points) {
|
||||||
|
mesh->clear_surfaces();
|
||||||
|
surface->clear();
|
||||||
|
Vector2 point_distance{ area.size / (float)side_points };
|
||||||
|
Vector2 at{ area.position };
|
||||||
|
surface->begin(Mesh::PRIMITIVE_TRIANGLES);
|
||||||
|
for (size_t xpoint{ 0 }; xpoint < side_points; ++xpoint) {
|
||||||
|
for (size_t ypoint{ 0 }; ypoint < side_points; ++ypoint) {
|
||||||
|
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 });
|
||||||
|
at.y += point_distance.y;
|
||||||
|
}
|
||||||
|
at.y = area.position.y;
|
||||||
|
at.x += point_distance.x;
|
||||||
|
}
|
||||||
|
for (size_t xface{ 0 }; xface < side_points - 1; ++xface) {
|
||||||
|
for (size_t yface{ 0 }; yface < side_points - 1; ++yface) {
|
||||||
|
face_from(surface, xface + yface * (size_t)side_points, side_points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
surface->generate_normals();
|
||||||
|
surface->generate_tangents();
|
||||||
|
surface->commit(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainMeshGenerator::set_primitives(Array primitives) {
|
||||||
|
for (Ref<TerrainPrimitive> primitive : this->primitives) {
|
||||||
|
if (primitive.is_valid()) {
|
||||||
|
primitive->disconnect_changed(this->generation_changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->primitives.clear();
|
||||||
|
for (Variant var : primitives) {
|
||||||
|
Ref<TerrainPrimitive> primitive{ var };
|
||||||
|
this->primitives.push_back(primitive);
|
||||||
|
if (primitive.is_valid()) {
|
||||||
|
primitive->connect_changed(this->generation_changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on_configuration_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Array TerrainMeshGenerator::get_primitives() const {
|
||||||
|
Array a;
|
||||||
|
for (Ref<TerrainPrimitive> primitive : this->primitives) {
|
||||||
|
a.push_back(primitive);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainMeshGenerator::set_vertex_color_gradient(Ref<Gradient> gradient) {
|
||||||
|
if (this->vertex_color_gradient.is_valid()) {
|
||||||
|
this->vertex_color_gradient->disconnect_changed(this->generation_changed);
|
||||||
|
}
|
||||||
|
this->vertex_color_gradient = gradient;
|
||||||
|
if (gradient.is_valid()) {
|
||||||
|
this->vertex_color_gradient->connect_changed(this->generation_changed);
|
||||||
|
}
|
||||||
|
on_configuration_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Gradient> TerrainMeshGenerator::get_vertex_color_gradient() const {
|
||||||
|
return this->vertex_color_gradient;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainMeshGenerator::set_color_gradient_start_height(float value) {
|
||||||
|
this->color_gradient_start_height = value;
|
||||||
|
on_configuration_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
float TerrainMeshGenerator::get_color_gradient_start_height() const {
|
||||||
|
return this->color_gradient_start_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainMeshGenerator::set_color_gradient_end_height(float value) {
|
||||||
|
this->color_gradient_end_height = value;
|
||||||
|
on_configuration_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
float TerrainMeshGenerator::get_color_gradient_end_height() const {
|
||||||
|
return this->color_gradient_end_height;
|
||||||
|
}
|
||||||
42
modules/terrain_editor/terrain_mesh_generator.h
Normal file
42
modules/terrain_editor/terrain_mesh_generator.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/math/color.h"
|
||||||
|
#include "core/object/object.h"
|
||||||
|
#include "core/variant/callable.h"
|
||||||
|
#include "scene/main/node.h"
|
||||||
|
#include "scene/resources/gradient.h"
|
||||||
|
#include "scene/resources/mesh.h"
|
||||||
|
#include "scene/resources/surface_tool.h"
|
||||||
|
#include "terrain_editor/terrain_primitive.h"
|
||||||
|
|
||||||
|
class TerrainMeshGenerator : public Node {
|
||||||
|
GDCLASS(TerrainMeshGenerator, Node);
|
||||||
|
static void _bind_methods();
|
||||||
|
void on_configuration_changed();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Color color_at_height(float height) const;
|
||||||
|
float evaluate_point(Vector2 at) const;
|
||||||
|
void generate_grid(Rect2 area, Ref<ArrayMesh> mesh, size_t side_points);
|
||||||
|
void set_primitives(Array array);
|
||||||
|
Array get_primitives() const;
|
||||||
|
void set_vertex_color_gradient(Ref<Gradient> gradient);
|
||||||
|
Ref<Gradient> get_vertex_color_gradient() const;
|
||||||
|
void set_color_gradient_start_height(float value);
|
||||||
|
float get_color_gradient_start_height() const;
|
||||||
|
void set_color_gradient_end_height(float value);
|
||||||
|
float get_color_gradient_end_height() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<Ref<TerrainPrimitive>> primitives{};
|
||||||
|
Ref<SurfaceTool> surface{ memnew(SurfaceTool) };
|
||||||
|
Ref<Gradient> vertex_color_gradient{};
|
||||||
|
float color_gradient_start_height{ 0.f };
|
||||||
|
float color_gradient_end_height{ 10.f };
|
||||||
|
|
||||||
|
private:
|
||||||
|
Callable generation_changed{ callable_mp(this, &self_type::on_configuration_changed) };
|
||||||
|
|
||||||
|
public:
|
||||||
|
static String const sig_primitives_changed;
|
||||||
|
};
|
||||||
188
modules/terrain_editor/terrain_primitive.cpp
Normal file
188
modules/terrain_editor/terrain_primitive.cpp
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
#include "terrain_primitive.h"
|
||||||
|
#include "core/error/error_list.h"
|
||||||
|
#include "core/math/expression.h"
|
||||||
|
#include "core/math/math_funcs.h"
|
||||||
|
#include "terrain_editor/macros.h"
|
||||||
|
|
||||||
|
void TerrainPrimitive::_bind_methods() {
|
||||||
|
BIND_HPROPERTY(Variant::INT, blend_mode, PROPERTY_HINT_ENUM, BlendMode_hint());
|
||||||
|
BIND_PROPERTY(Variant::FLOAT, blend_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
// by default does not modify height
|
||||||
|
void TerrainPrimitive::evaluate(Vector2, float &) const {}
|
||||||
|
|
||||||
|
float TerrainPrimitive::blend(float under, float over) const {
|
||||||
|
float const difference{ under - over };
|
||||||
|
float const distance{ Math::abs(difference) };
|
||||||
|
// .25 because we need half of each half of the blend range to be used
|
||||||
|
float const center_distance{ this->blend_range == 0.f ? 0.f : this->blend_range * 0.25f - distance / this->blend_range };
|
||||||
|
if (center_distance < 0.f) {
|
||||||
|
if (this->blend_mode == Both) {
|
||||||
|
return over;
|
||||||
|
} else if (this->blend_mode == Peak) {
|
||||||
|
return under > over ? under : over;
|
||||||
|
} else {
|
||||||
|
return under > over ? over : under;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float const smooth_center_distance{ center_distance * center_distance };
|
||||||
|
if (this->blend_mode == Both) {
|
||||||
|
return over + smooth_center_distance;
|
||||||
|
} else {
|
||||||
|
return (this->blend_mode == Peak
|
||||||
|
? (under >= over ? under : over) + smooth_center_distance
|
||||||
|
: (under >= over ? over : under) - smooth_center_distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainPrimitive::set_blend_mode(BlendMode mode) {
|
||||||
|
this->blend_mode = mode;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
TerrainPrimitive::BlendMode TerrainPrimitive::get_blend_mode() const {
|
||||||
|
return this->blend_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainPrimitive::set_blend_range(float value) {
|
||||||
|
this->blend_range = value;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
float TerrainPrimitive::get_blend_range() const {
|
||||||
|
return this->blend_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlanePrimitive::_bind_methods() {
|
||||||
|
BIND_PROPERTY(Variant::FLOAT, baseline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlanePrimitive::evaluate(Vector2, float &io_height) const {
|
||||||
|
io_height = blend(io_height, this->baseline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlanePrimitive::set_baseline(float value) {
|
||||||
|
this->baseline = value;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
float PlanePrimitive::get_baseline() const {
|
||||||
|
return this->baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointPrimitive::_bind_methods() {
|
||||||
|
BIND_PROPERTY(Variant::VECTOR2, center);
|
||||||
|
BIND_PROPERTY(Variant::FLOAT, slope);
|
||||||
|
BIND_PROPERTY(Variant::FLOAT, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointPrimitive::evaluate(Vector2 at, float &io_height) const {
|
||||||
|
float distance{ at.distance_to(this->center) };
|
||||||
|
io_height = blend(io_height, this->height + distance * this->slope);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointPrimitive::set_center(Vector2 center) {
|
||||||
|
this->center = center;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 PointPrimitive::get_center() const {
|
||||||
|
return this->center;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointPrimitive::set_slope(float radius) {
|
||||||
|
this->slope = radius;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
float PointPrimitive::get_slope() const {
|
||||||
|
return this->slope;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointPrimitive::set_height(float height) {
|
||||||
|
this->height = height;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
float PointPrimitive::get_height() const {
|
||||||
|
return this->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NoisePrimitive::_bind_methods() {
|
||||||
|
BIND_HPROPERTY(Variant::OBJECT, noise, PROPERTY_HINT_RESOURCE_TYPE, "Noise");
|
||||||
|
BIND_PROPERTY(Variant::FLOAT, noise_scale);
|
||||||
|
BIND_PROPERTY(Variant::FLOAT, noise_amplitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NoisePrimitive::evaluate(Vector2 at, float &io_height) const {
|
||||||
|
if (this->noise.is_valid()) {
|
||||||
|
float noise_sample{ this->noise->get_noise_2dv(at / this->noise_scale) };
|
||||||
|
switch (this->get_blend_mode()) {
|
||||||
|
case Peak:
|
||||||
|
noise_sample = Math::remap(noise_sample, -1.f, 1.f, 0.f, this->noise_amplitude);
|
||||||
|
break;
|
||||||
|
case Valley:
|
||||||
|
noise_sample = Math::remap(noise_sample, -1.f, 1.f, -this->noise_amplitude, 0.f);
|
||||||
|
break;
|
||||||
|
case Both:
|
||||||
|
noise_sample *= this->noise_amplitude;
|
||||||
|
}
|
||||||
|
io_height = blend(io_height, io_height + noise_sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NoisePrimitive::set_noise(Ref<Noise> noise) {
|
||||||
|
this->noise = noise;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Noise> NoisePrimitive::get_noise() const {
|
||||||
|
return this->noise;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NoisePrimitive::set_noise_scale(float value) {
|
||||||
|
this->noise_scale = value;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
float NoisePrimitive::get_noise_scale() const {
|
||||||
|
return this->noise_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NoisePrimitive::set_noise_amplitude(float value) {
|
||||||
|
this->noise_amplitude = value;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
float NoisePrimitive::get_noise_amplitude() const {
|
||||||
|
return this->noise_amplitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpressionPrimitive::_bind_methods() {
|
||||||
|
BIND_HPROPERTY(Variant::STRING, expression, PROPERTY_HINT_EXPRESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpressionPrimitive::evaluate(Vector2 at, float &io_height) const {
|
||||||
|
if (!this->valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Variant result{ this->expression->execute({ io_height, at }, nullptr, false, true) };
|
||||||
|
if (!this->expression->has_execute_failed()) {
|
||||||
|
io_height = blend(io_height, float(result.get(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpressionPrimitive::set_expression(String expression) {
|
||||||
|
this->expression_string = expression;
|
||||||
|
this->expression.unref();
|
||||||
|
this->expression = memnew(Expression);
|
||||||
|
Error error{ this->expression->parse(this->expression_string, { "height", "at" }) };
|
||||||
|
if ((this->valid = error == OK)) {
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String ExpressionPrimitive::get_expression() const {
|
||||||
|
return this->expression_string;
|
||||||
|
}
|
||||||
102
modules/terrain_editor/terrain_primitive.h
Normal file
102
modules/terrain_editor/terrain_primitive.h
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/io/resource.h"
|
||||||
|
#include "core/math/expression.h"
|
||||||
|
#include "core/object/object.h"
|
||||||
|
#include "modules/noise/noise.h"
|
||||||
|
#include "terrain_editor/macros.h"
|
||||||
|
|
||||||
|
class TerrainPrimitive : public Resource {
|
||||||
|
GDCLASS(TerrainPrimitive, Resource);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
GDENUM(BlendMode,
|
||||||
|
Peak,
|
||||||
|
Valley,
|
||||||
|
Both)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float blend(float under, float over) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// evaluate the height of this primitive at point, returns the weight of the effect, out_height will be set to the closest point on the primitive
|
||||||
|
virtual void evaluate(Vector2 at, float &io_height) const;
|
||||||
|
|
||||||
|
void set_blend_mode(BlendMode mode);
|
||||||
|
BlendMode get_blend_mode() const;
|
||||||
|
void set_blend_range(float blend_range);
|
||||||
|
float get_blend_range() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float blend_range{ 4.f };
|
||||||
|
BlendMode blend_mode{ Peak };
|
||||||
|
};
|
||||||
|
|
||||||
|
MAKE_TYPE_INFO(TerrainPrimitive::BlendMode, Variant::INT);
|
||||||
|
|
||||||
|
class PlanePrimitive : public TerrainPrimitive {
|
||||||
|
GDCLASS(PlanePrimitive, TerrainPrimitive);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void evaluate(Vector2 at, float &io_height) const override;
|
||||||
|
void set_baseline(float value);
|
||||||
|
float get_baseline() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float baseline{ 1.f };
|
||||||
|
};
|
||||||
|
|
||||||
|
class PointPrimitive : public TerrainPrimitive {
|
||||||
|
GDCLASS(PointPrimitive, TerrainPrimitive);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void evaluate(Vector2 at, float &io_height) const override;
|
||||||
|
void set_center(Vector2 center);
|
||||||
|
Vector2 get_center() const;
|
||||||
|
void set_slope(float radius);
|
||||||
|
float get_slope() const;
|
||||||
|
void set_height(float height);
|
||||||
|
float get_height() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector2 center{ 0.f, 0.f };
|
||||||
|
float slope{ -1.f };
|
||||||
|
float height{ 10.f };
|
||||||
|
};
|
||||||
|
|
||||||
|
class NoisePrimitive : public TerrainPrimitive {
|
||||||
|
GDCLASS(NoisePrimitive, TerrainPrimitive);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void evaluate(Vector2 at, float &io_height) const override;
|
||||||
|
void set_noise(Ref<Noise> noise);
|
||||||
|
Ref<Noise> get_noise() const;
|
||||||
|
void set_noise_scale(float pixels_per_meter);
|
||||||
|
float get_noise_scale() const;
|
||||||
|
void set_noise_amplitude(float height);
|
||||||
|
float get_noise_amplitude() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ref<Noise> noise{};
|
||||||
|
float noise_scale{ 1.f };
|
||||||
|
float noise_amplitude{ 1.f };
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExpressionPrimitive : public TerrainPrimitive {
|
||||||
|
GDCLASS(ExpressionPrimitive, TerrainPrimitive);
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void evaluate(Vector2 at, float &io_height) const override;
|
||||||
|
void set_expression(String expression);
|
||||||
|
String get_expression() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ref<Expression> expression{ memnew(Expression) };
|
||||||
|
String expression_string{ "height" };
|
||||||
|
bool valid{ false };
|
||||||
|
};
|
||||||
137
project/scenes/editor.tscn
Normal file
137
project/scenes/editor.tscn
Normal file
File diff suppressed because one or more lines are too long
9
project/terrain.gdshader
Normal file
9
project/terrain.gdshader
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
shader_type spatial;
|
||||||
|
|
||||||
|
void vertex() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//void fragment() {
|
||||||
|
// Called for every pixel the material is visible on.
|
||||||
|
//}
|
||||||
1
project/terrain.gdshader.uid
Normal file
1
project/terrain.gdshader.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://dsbxpdveoilep
|
||||||
Loading…
Reference in a new issue