Updated sdf code to work in C++
This commit is contained in:
@@ -170,25 +170,30 @@ void RoadGrid::index_site(struct map_site *site)
|
|||||||
site->polygon_ind.resize(site->polygon.size());
|
site->polygon_ind.resize(site->polygon.size());
|
||||||
/* slow as fuck */
|
/* slow as fuck */
|
||||||
for (i = 0; i < site->vertices.size(); i++) {
|
for (i = 0; i < site->vertices.size(); i++) {
|
||||||
int idx = diagram_vertices.find(site->vertices[i]);
|
Vector2 v = site->vertices[i].snapped(Vector2(2.0f, 2.0f));
|
||||||
|
int idx = diagram_vertices.find(v);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
idx = diagram_vertices.size();
|
idx = diagram_vertices.size();
|
||||||
diagram_vertices.push_back(site->vertices[i]);
|
diagram_vertices.push_back(v);
|
||||||
}
|
}
|
||||||
site->vertices_ind.write[i] = idx;
|
site->vertices_ind.write[i] = idx;
|
||||||
}
|
}
|
||||||
for (i = 0; i < site->polygon.size(); i++) {
|
for (i = 0; i < site->polygon.size(); i++) {
|
||||||
int idx = diagram_vertices.find(site->polygon[i]);
|
Vector2 v = site->polygon[i].snapped(Vector2(2.0f, 2.0f));
|
||||||
|
int idx = diagram_vertices.find(v);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
idx = diagram_vertices.size();
|
idx = diagram_vertices.size();
|
||||||
diagram_vertices.push_back(site->polygon[i]);
|
diagram_vertices.push_back(v);
|
||||||
}
|
}
|
||||||
site->polygon_ind.write[i] = idx;
|
site->polygon_ind.write[i] = idx;
|
||||||
}
|
}
|
||||||
site->hedges.resize(site->polygon.size());
|
site->hedges.resize(site->polygon.size());
|
||||||
|
int count = 0;
|
||||||
for (i = 0; i < site->polygon.size(); i++) {
|
for (i = 0; i < site->polygon.size(); i++) {
|
||||||
int idx1 = site->polygon_ind[i];
|
int idx1 = site->polygon_ind[i];
|
||||||
int idx2 = site->polygon_ind[(i + 1) % site->polygon.size()];
|
int idx2 = site->polygon_ind[(i + 1) % site->polygon.size()];
|
||||||
|
if (idx1 == idx2)
|
||||||
|
continue;
|
||||||
struct half_edge he;
|
struct half_edge he;
|
||||||
he.a = idx1;
|
he.a = idx1;
|
||||||
he.b = idx2;
|
he.b = idx2;
|
||||||
@@ -196,8 +201,9 @@ void RoadGrid::index_site(struct map_site *site)
|
|||||||
/* use length to decide */
|
/* use length to decide */
|
||||||
he.depth = 6.0f;
|
he.depth = 6.0f;
|
||||||
he.length = diagram_vertices[idx1].distance_to(diagram_vertices[idx2]);
|
he.length = diagram_vertices[idx1].distance_to(diagram_vertices[idx2]);
|
||||||
site->hedges.write[i] = he;
|
site->hedges.write[count++] = he;
|
||||||
}
|
}
|
||||||
|
site->hedges.resize(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadGrid::process_diagram(const Dictionary &diagram)
|
void RoadGrid::process_diagram(const Dictionary &diagram)
|
||||||
@@ -256,14 +262,14 @@ void RoadGrid::build(Ref<Curve> curve, Ref<OpenSimplexNoise> noise)
|
|||||||
rnd->randomize();
|
rnd->randomize();
|
||||||
printf("build_diagram\n");
|
printf("build_diagram\n");
|
||||||
// Dictionary diagram = build_diagram(8, 2 + (rnd->randi() % 2), 100, 100, 50);
|
// Dictionary diagram = build_diagram(8, 2 + (rnd->randi() % 2), 100, 100, 50);
|
||||||
Dictionary diagram = build_diagram(8, 2, 100, 100, 30);
|
Dictionary diagram = build_diagram(8, 2, 100, 100, 500);
|
||||||
printf("build_diagram done\n");
|
printf("build_diagram done\n");
|
||||||
printf("process_diagram\n");
|
printf("process_diagram\n");
|
||||||
process_diagram(diagram);
|
process_diagram(diagram);
|
||||||
printf("process_diagram done\n");
|
printf("process_diagram done\n");
|
||||||
printf("%d %d\n", curve.is_valid(), noise.is_valid());
|
printf("%d %d\n", curve.is_valid(), noise.is_valid());
|
||||||
assert(curve.is_valid() && noise.is_valid());
|
assert(curve.is_valid() && noise.is_valid());
|
||||||
int i;
|
int i, j;
|
||||||
if (curve.is_valid() && noise.is_valid()) {
|
if (curve.is_valid() && noise.is_valid()) {
|
||||||
printf("building 3rd dimention\n");
|
printf("building 3rd dimention\n");
|
||||||
diagram_vertex_heights.resize(diagram_vertices.size());
|
diagram_vertex_heights.resize(diagram_vertices.size());
|
||||||
@@ -271,30 +277,49 @@ void RoadGrid::build(Ref<Curve> curve, Ref<OpenSimplexNoise> noise)
|
|||||||
float n = noise->get_noise_2dv(diagram_vertices[i]);
|
float n = noise->get_noise_2dv(diagram_vertices[i]);
|
||||||
float t = (n + 1.0f) * 0.5f;
|
float t = (n + 1.0f) * 0.5f;
|
||||||
float d = MAX(1.0f, curve->interpolate_baked(t));
|
float d = MAX(1.0f, curve->interpolate_baked(t));
|
||||||
|
d = CLAMP(d, 1.0f, 30.0f);
|
||||||
diagram_vertex_heights.write[i] = d;
|
diagram_vertex_heights.write[i] = d;
|
||||||
}
|
}
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
for (i = 0; i < map_hedges.size(); i++) {
|
for (i = 0; i < map_hedges.size(); i++) {
|
||||||
int x1 = map_hedges[i]->a;
|
int x1 = map_hedges[i]->a;
|
||||||
int x2 = map_hedges[i]->b;
|
int x2 = map_hedges[i]->b;
|
||||||
float xd = diagram_vertices[x1].distance_squared_to(diagram_vertices[x2]);
|
float xd = map_hedges[i]->length;
|
||||||
float dh = fabsf(diagram_vertex_heights[x2] - diagram_vertex_heights[x1]);
|
float dh = fabsf(diagram_vertex_heights[x2] - diagram_vertex_heights[x1]);
|
||||||
if (fabsf(dh / xd) > 0.02f)
|
if (fabsf(dh / xd) > 0.01f)
|
||||||
diagram_vertex_heights.write[x2] = diagram_vertex_heights[x1] + dh / fabsf(dh) * 0.02f * xd;
|
diagram_vertex_heights.write[x2] = diagram_vertex_heights[x1] + dh / fabsf(dh) * 0.01f * xd;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
for (i = 0; i < diagram_vertices.size(); i++)
|
||||||
|
diagram_vertex_heights.write[i] = Math::stepify(diagram_vertex_heights.write[i], 4.0f);
|
||||||
|
for (i = 0; i < diagram_vertices.size(); i++)
|
||||||
|
diagram_vertex_heights.write[i] = 2.0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
printf("building 3rd dimention done\n");
|
printf("building 3rd dimention done\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 RoadGrid::get_influence(int x, int y) const
|
Vector2 RoadGrid::get_influence(int x, int y, float radius) const
|
||||||
{
|
{
|
||||||
static int mind = 1000000;
|
int rd = (int)(radius / grid_width) + 1;
|
||||||
static int maxd = 0;
|
|
||||||
List<struct half_edge *> hlist;
|
List<struct half_edge *> hlist;
|
||||||
if (hedge_grid.has(x / grid_width) && hedge_grid[x / grid_width].has(y / grid_height))
|
List<struct half_edge *>::Element *e;
|
||||||
hlist = hedge_grid[x / grid_width][y / grid_height];
|
int i = 0, j = 0;
|
||||||
|
for (i = -rd; i < rd + 1; i++)
|
||||||
|
for (j = -rd; j < rd + 1; j++) {
|
||||||
|
List<struct half_edge *> tmp;
|
||||||
|
if (hedge_grid.has(x / grid_width + i) && hedge_grid[x / grid_width + i].has(y / grid_height + j)) {
|
||||||
|
tmp = hedge_grid[x / grid_width + i][y / grid_height + j];
|
||||||
|
for (e = tmp.front(); e; e = e->next()) {
|
||||||
|
struct half_edge *d = e->get();
|
||||||
|
hlist.push_back(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if (hlist.size() == 0)
|
if (hlist.size() == 0)
|
||||||
return Vector2();
|
return Vector2();
|
||||||
List<struct half_edge *>::Element *e;
|
|
||||||
for (e = hlist.front(); e; e = e->next()) {
|
for (e = hlist.front(); e; e = e->next()) {
|
||||||
struct half_edge *he = e->get();
|
struct half_edge *he = e->get();
|
||||||
Vector2 a = diagram_vertices[he->a];
|
Vector2 a = diagram_vertices[he->a];
|
||||||
@@ -303,7 +328,7 @@ Vector2 RoadGrid::get_influence(int x, int y) const
|
|||||||
Vector2 seg[] = {a, b};
|
Vector2 seg[] = {a, b};
|
||||||
Vector2 pt = Geometry::get_closest_point_to_segment_2d(p, seg);
|
Vector2 pt = Geometry::get_closest_point_to_segment_2d(p, seg);
|
||||||
float d = pt.distance_squared_to(p);
|
float d = pt.distance_squared_to(p);
|
||||||
if (d < MAX(96.0f * 96.0f, he->depth * he->depth) + 96.0f * 96.0f) {
|
if (d < radius * radius) {
|
||||||
Vector2 ret;
|
Vector2 ret;
|
||||||
ret.x = 1.0f;
|
ret.x = 1.0f;
|
||||||
assert(diagram_vertex_heights.size() > he->a);
|
assert(diagram_vertex_heights.size() > he->a);
|
||||||
@@ -315,7 +340,7 @@ Vector2 RoadGrid::get_influence(int x, int y) const
|
|||||||
float m1 = pt.distance_to(a) / l;
|
float m1 = pt.distance_to(a) / l;
|
||||||
float m2 = CLAMP(1.0f - m1, 0.0f, 1.0f);
|
float m2 = CLAMP(1.0f - m1, 0.0f, 1.0f);
|
||||||
float h = h1 * (1.0f - m1) + h2 * (1.0f - m2);
|
float h = h1 * (1.0f - m1) + h2 * (1.0f - m2);
|
||||||
ret.y = h - 0.5f;
|
ret.y = h - 2.5f;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,7 +350,7 @@ Vector2 RoadGrid::get_influence(int x, int y) const
|
|||||||
void RoadGrid::_bind_methods()
|
void RoadGrid::_bind_methods()
|
||||||
{
|
{
|
||||||
ClassDB::bind_method(D_METHOD("draw_debug", "drawable", "size_x", "size_y"), &RoadGrid::draw_debug);
|
ClassDB::bind_method(D_METHOD("draw_debug", "drawable", "size_x", "size_y"), &RoadGrid::draw_debug);
|
||||||
ClassDB::bind_method(D_METHOD("get_influence", "x", "y"), &RoadGrid::get_influence);
|
ClassDB::bind_method(D_METHOD("get_influence", "x", "y", "radius"), &RoadGrid::get_influence);
|
||||||
ClassDB::bind_method(D_METHOD("build", "curve", "noise"), &RoadGrid::build);
|
ClassDB::bind_method(D_METHOD("build", "curve", "noise"), &RoadGrid::build);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
void build(Ref<Curve> curve, Ref<OpenSimplexNoise> noise);
|
void build(Ref<Curve> curve, Ref<OpenSimplexNoise> noise);
|
||||||
void draw_debug(Node *drawable, int size_x, int size_y) const;
|
void draw_debug(Node *drawable, int size_x, int size_y) const;
|
||||||
Vector2 get_influence(int x, int y) const;
|
Vector2 get_influence(int x, int y, float radius) const;
|
||||||
RoadGrid();
|
RoadGrid();
|
||||||
~RoadGrid();
|
~RoadGrid();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -614,10 +614,11 @@ float RoadsData::get_sdf(int x, int y, int z)
|
|||||||
if (!curve.is_valid() || !noise.is_valid())
|
if (!curve.is_valid() || !noise.is_valid())
|
||||||
return (float)y;
|
return (float)y;
|
||||||
float n = curve->interpolate_baked(0.5f + noise->get_noise_2d(x, z) * 0.5f);
|
float n = curve->interpolate_baked(0.5f + noise->get_noise_2d(x, z) * 0.5f);
|
||||||
Vector2 ifl = rg->get_influence(x, z);
|
n = CLAMP(n, -1000.0f, 1000.0f);
|
||||||
|
Vector2 ifl = rg->get_influence(x, z, 32.0f);
|
||||||
if (ifl.x > 0.0f) {
|
if (ifl.x > 0.0f) {
|
||||||
if (n <= ifl.y + 2.0f)
|
if (n <= ifl.y - 0.5f)
|
||||||
return (float)y - ifl.y;
|
return (float)y - ifl.y - 0.6f;
|
||||||
else
|
else
|
||||||
return (float)y - ifl.y;
|
return (float)y - ifl.y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,105 +1,24 @@
|
|||||||
#include <core/engine.h>
|
#include <core/engine.h>
|
||||||
|
#include <core/os/os.h>
|
||||||
|
#include "roads.h"
|
||||||
#include "world_map_data.h"
|
#include "world_map_data.h"
|
||||||
#include "world_generator.h"
|
#include "world_generator.h"
|
||||||
|
|
||||||
WorldGenerator::WorldGenerator() {
|
WorldGenerator::WorldGenerator() {
|
||||||
#ifdef TOOLS_ENABLED
|
|
||||||
if (Engine::get_singleton()->is_editor_hint()) {
|
|
||||||
// Have one by default in editor
|
|
||||||
_noise.instance();
|
|
||||||
_mount_noise.instance();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldGenerator::set_noise(Ref<OpenSimplexNoise> noise) {
|
|
||||||
_noise = noise;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<OpenSimplexNoise> WorldGenerator::get_noise() const {
|
|
||||||
return _noise;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldGenerator::set_mount_noise(Ref<OpenSimplexNoise> noise) {
|
|
||||||
_mount_noise = noise;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<OpenSimplexNoise> WorldGenerator::get_mount_noise() const {
|
|
||||||
return _mount_noise;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorldGenerator::height_func(int x, int y, int z)
|
float WorldGenerator::height_func(int x, int y, int z)
|
||||||
{
|
{
|
||||||
float mh = _noise->get_noise_2d((float)x * main_multiplier, (float)z * main_multiplier);
|
float sdf = RoadsData::get_singleton()->get_sdf(x, y, z);
|
||||||
float mth = _mount_noise->get_noise_2d((float)x * mount_multiplier, (float)z * mount_multiplier);
|
return sdf;
|
||||||
float dmt = 15.0f;
|
|
||||||
float d1 = initial_spawn_radius + 33.5f * mth;
|
|
||||||
float h1 = initial_spawn_height + 0.03f * mth;
|
|
||||||
float d2 = d1 + 20.0f + 0.05 * mth;
|
|
||||||
float h2 = _range.start + 0.15f * mth;
|
|
||||||
Vector3 pos((float)x, (float)y, (float)z);
|
|
||||||
float d = pos.distance_squared_to(initial_spawn);
|
|
||||||
float factor = (d1 * d1 + 1.0f) / (d + 1.0f);
|
|
||||||
float th = (d < d1 * d1) ? h1 : h1 * factor + h2 * (1.0f - factor);
|
|
||||||
float fh = th;
|
|
||||||
float iheight = CLAMP(fh, _range.start, initial_spawn_height) / _range.height;
|
|
||||||
float oheight = (mh + mth * 0.01 + 0.1 * mth * CLAMP(y - mount_offset, 0.0f, dmt) / dmt);
|
|
||||||
float rt = CLAMP(d2 * d2 / (d + 1.0f), 0.0f, 1.0f);
|
|
||||||
return 0.5f + 0.5f * (iheight * rt + oheight * (1.0f - rt));
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldGenerator::set_mount_offset(float offt)
|
|
||||||
{
|
|
||||||
mount_offset = offt;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorldGenerator::get_mount_offset() const
|
|
||||||
{
|
|
||||||
return mount_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldGenerator::set_main_multiplier(float mult)
|
|
||||||
{
|
|
||||||
main_multiplier = mult;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorldGenerator::get_main_multiplier() const
|
|
||||||
{
|
|
||||||
return main_multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldGenerator::set_initial_spawn_height(float height)
|
|
||||||
{
|
|
||||||
initial_spawn_height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorldGenerator::get_initial_spawn_height() const
|
|
||||||
{
|
|
||||||
return initial_spawn_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldGenerator::set_density_map(Ref<DensityMap> map)
|
|
||||||
{
|
|
||||||
density_map = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<DensityMap> WorldGenerator::get_density_map() const
|
|
||||||
{
|
|
||||||
return density_map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelGenerator::Result WorldGenerator::generate_block(VoxelBlockRequest &input) {
|
VoxelGenerator::Result WorldGenerator::generate_block(VoxelBlockRequest &input) {
|
||||||
|
|
||||||
ERR_FAIL_COND_V(_noise.is_null(), Result());
|
|
||||||
#ifdef WORLD_MAP_TESTS
|
|
||||||
WorldMapData *wmd = WorldMapData::get_singleton();
|
|
||||||
if (!wmd->tests_run) {
|
|
||||||
wmd->unit_test();
|
|
||||||
wmd->tests_run = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Result result;
|
Result result;
|
||||||
|
|
||||||
|
real_t time_before = OS::get_singleton()->get_ticks_usec(), total;
|
||||||
VoxelBufferInternal &out_buffer = input.voxel_buffer;
|
VoxelBufferInternal &out_buffer = input.voxel_buffer;
|
||||||
result = WorldGenerator::generate(
|
result = WorldGenerator::generate(
|
||||||
out_buffer,
|
out_buffer,
|
||||||
@@ -107,96 +26,19 @@ VoxelGenerator::Result WorldGenerator::generate_block(VoxelBlockRequest &input)
|
|||||||
input.origin_in_voxels, input.lod);
|
input.origin_in_voxels, input.lod);
|
||||||
|
|
||||||
out_buffer.compress_uniform_channels();
|
out_buffer.compress_uniform_channels();
|
||||||
|
total = OS::get_singleton()->get_ticks_usec() - time_before;
|
||||||
|
printf("generate_block: %f\n", total);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldGenerator::_bind_methods() {
|
void WorldGenerator::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &WorldGenerator::set_noise);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_noise"), &WorldGenerator::get_noise);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_mount_noise", "noise"), &WorldGenerator::set_mount_noise);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_mount_noise"), &WorldGenerator::get_mount_noise);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &WorldGenerator::set_channel);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_channel"), &WorldGenerator::get_channel);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_height_start", "start"), &WorldGenerator::set_height_start);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_height_start"), &WorldGenerator::get_height_start);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_mount_offset", "offt"), &WorldGenerator::set_mount_offset);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_mount_offset"), &WorldGenerator::get_mount_offset);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_main_multiplier", "mult"), &WorldGenerator::set_main_multiplier);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_main_multiplier"), &WorldGenerator::get_main_multiplier);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_initial_spawn_height", "height"), &WorldGenerator::set_initial_spawn_height);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_initial_spawn_height"), &WorldGenerator::get_initial_spawn_height);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_initial_spawn_radius", "radius"), &WorldGenerator::set_initial_spawn_radius);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_initial_spawn_radius"), &WorldGenerator::get_initial_spawn_radius);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_height_range", "range"), &WorldGenerator::set_height_range);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_height_range"), &WorldGenerator::get_height_range);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_iso_scale", "scale"), &WorldGenerator::set_iso_scale);
|
ClassDB::bind_method(D_METHOD("set_iso_scale", "scale"), &WorldGenerator::set_iso_scale);
|
||||||
ClassDB::bind_method(D_METHOD("get_iso_scale"), &WorldGenerator::get_iso_scale);
|
ClassDB::bind_method(D_METHOD("get_iso_scale"), &WorldGenerator::get_iso_scale);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_density_map", "density_map"), &WorldGenerator::set_density_map);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_density_map"), &WorldGenerator::get_density_map);
|
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mount_noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_mount_noise", "get_mount_noise");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "mount_offset"), "set_mount_offset", "get_mount_offset");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "main_multiplier"), "set_main_multiplier", "get_main_multiplier");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "initial_spawn_height"), "set_initial_spawn_height", "get_initial_spawn_height");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "initial_spawn_radius"), "set_initial_spawn_radius", "get_initial_spawn_radius");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, VoxelBuffer::CHANNEL_ID_HINT_STRING), "set_channel", "get_channel");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_start"), "set_height_start", "get_height_start");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "height_range"), "set_height_range", "get_height_range");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "density_map", PROPERTY_HINT_RESOURCE_TYPE, "DensityMap"), "set_density_map", "get_density_map");
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "iso_scale"), "set_iso_scale", "get_iso_scale");
|
ADD_PROPERTY(PropertyInfo(Variant::REAL, "iso_scale"), "set_iso_scale", "get_iso_scale");
|
||||||
}
|
}
|
||||||
void WorldGenerator::set_channel(VoxelBuffer::ChannelId channel) {
|
|
||||||
ERR_FAIL_INDEX(channel, VoxelBuffer::MAX_CHANNELS);
|
|
||||||
if (_channel != channel) {
|
|
||||||
_channel = channel;
|
|
||||||
emit_changed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VoxelBuffer::ChannelId WorldGenerator::get_channel() const {
|
|
||||||
return _channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WorldGenerator::get_used_channels_mask() const {
|
int WorldGenerator::get_used_channels_mask() const {
|
||||||
return (1 << _channel);
|
return (1 << VoxelBuffer::CHANNEL_SDF);
|
||||||
}
|
|
||||||
|
|
||||||
void WorldGenerator::set_height_start(float start) {
|
|
||||||
_range.start = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorldGenerator::get_height_start() const {
|
|
||||||
return _range.start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldGenerator::set_height_range(float range) {
|
|
||||||
_range.height = range;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorldGenerator::get_height_range() const {
|
|
||||||
return _range.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldGenerator::set_initial_spawn_radius(float radius)
|
|
||||||
{
|
|
||||||
initial_spawn_radius = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WorldGenerator::get_initial_spawn_radius() const
|
|
||||||
{
|
|
||||||
return initial_spawn_radius;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldGenerator::set_iso_scale(float iso_scale) {
|
void WorldGenerator::set_iso_scale(float iso_scale) {
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
#define VOXEL_GENERATOR_NOISE_2D_H
|
#define VOXEL_GENERATOR_NOISE_2D_H
|
||||||
|
|
||||||
#include <modules/voxel/generators/voxel_generator.h>
|
#include <modules/voxel/generators/voxel_generator.h>
|
||||||
#include <modules/opensimplex/open_simplex_noise.h>
|
|
||||||
|
|
||||||
#include "density_map.h"
|
|
||||||
|
|
||||||
class WorldGenerator : public VoxelGenerator {
|
class WorldGenerator : public VoxelGenerator {
|
||||||
GDCLASS(WorldGenerator, VoxelGenerator)
|
GDCLASS(WorldGenerator, VoxelGenerator)
|
||||||
@@ -12,38 +9,10 @@ class WorldGenerator : public VoxelGenerator {
|
|||||||
public:
|
public:
|
||||||
WorldGenerator();
|
WorldGenerator();
|
||||||
|
|
||||||
void set_noise(Ref<OpenSimplexNoise> noise);
|
|
||||||
Ref<OpenSimplexNoise> get_noise() const;
|
|
||||||
|
|
||||||
void set_mount_noise(Ref<OpenSimplexNoise> noise);
|
|
||||||
Ref<OpenSimplexNoise> get_mount_noise() const;
|
|
||||||
|
|
||||||
void set_channel(VoxelBuffer::ChannelId channel);
|
|
||||||
VoxelBuffer::ChannelId get_channel() const;
|
|
||||||
int get_used_channels_mask() const override;
|
int get_used_channels_mask() const override;
|
||||||
|
|
||||||
void set_height_start(float start);
|
|
||||||
float get_height_start() const;
|
|
||||||
|
|
||||||
void set_height_range(float range);
|
|
||||||
float get_height_range() const;
|
|
||||||
|
|
||||||
void set_mount_offset(float offt);
|
|
||||||
float get_mount_offset() const;
|
|
||||||
|
|
||||||
void set_main_multiplier(float mult);
|
|
||||||
float get_main_multiplier() const;
|
|
||||||
|
|
||||||
void set_initial_spawn_height(float height);
|
|
||||||
float get_initial_spawn_height() const;
|
|
||||||
|
|
||||||
void set_initial_spawn_radius(float radius);
|
|
||||||
float get_initial_spawn_radius() const;
|
|
||||||
|
|
||||||
void set_iso_scale(float iso_scale);
|
void set_iso_scale(float iso_scale);
|
||||||
float get_iso_scale() const;
|
float get_iso_scale() const;
|
||||||
void set_density_map(Ref<DensityMap> map);
|
|
||||||
Ref<DensityMap> get_density_map() const;
|
|
||||||
|
|
||||||
Result generate_block(VoxelBlockRequest &input) override;
|
Result generate_block(VoxelBlockRequest &input) override;
|
||||||
float height_func(int x, int y, int z);
|
float height_func(int x, int y, int z);
|
||||||
@@ -54,28 +23,25 @@ protected:
|
|||||||
template <typename Height_F>
|
template <typename Height_F>
|
||||||
Result generate(VoxelBufferInternal &out_buffer, Height_F height_func, Vector3i origin, int lod) {
|
Result generate(VoxelBufferInternal &out_buffer, Height_F height_func, Vector3i origin, int lod) {
|
||||||
|
|
||||||
const int channel = _channel;
|
const int channel = VoxelBuffer::CHANNEL_SDF;
|
||||||
const Vector3i bs = out_buffer.get_size();
|
const Vector3i bs = out_buffer.get_size();
|
||||||
bool use_sdf = channel == VoxelBuffer::CHANNEL_SDF;
|
|
||||||
|
|
||||||
if (origin.y > get_height_start() + get_height_range()) {
|
/* TODO: get via RoadsData */
|
||||||
|
if (origin.y > 300.0f) {
|
||||||
// The bottom of the block is above the highest ground can go (default is air)
|
// The bottom of the block is above the highest ground can go (default is air)
|
||||||
Result result;
|
Result result;
|
||||||
result.max_lod_hint = true;
|
result.max_lod_hint = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (origin.y + (bs.y << lod) < get_height_start()) {
|
if (origin.y + (bs.y << lod) < -1000.0f) {
|
||||||
// The top of the block is below the lowest ground can go
|
// The top of the block is below the lowest ground can go
|
||||||
out_buffer.clear_channel(_channel, use_sdf ? 0 : _matter_type);
|
out_buffer.clear_channel(channel, 0);
|
||||||
Result result;
|
Result result;
|
||||||
result.max_lod_hint = true;
|
result.max_lod_hint = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int stride = 1 << lod;
|
const int stride = 1 << lod;
|
||||||
|
|
||||||
if (use_sdf) {
|
|
||||||
|
|
||||||
int gz = origin.z;
|
int gz = origin.z;
|
||||||
for (int z = 0; z < bs.z; ++z, gz += stride) {
|
for (int z = 0; z < bs.z; ++z, gz += stride) {
|
||||||
|
|
||||||
@@ -84,64 +50,20 @@ protected:
|
|||||||
|
|
||||||
int gy = origin.y;
|
int gy = origin.y;
|
||||||
for (int y = 0; y < bs.y; ++y, gy += stride) {
|
for (int y = 0; y < bs.y; ++y, gy += stride) {
|
||||||
float h = _range.xform(height_func(gx, gy, gz));
|
float sdf = height_func(gx, gy, gz);
|
||||||
float sdf = _iso_scale * (gy - h);
|
out_buffer.set_voxel_f(sdf * _iso_scale, x, y, z, channel);
|
||||||
out_buffer.set_voxel_f(sdf, x, y, z, channel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // for x
|
} // for x
|
||||||
} // for z
|
} // for z
|
||||||
|
|
||||||
} else {
|
|
||||||
// Blocky
|
|
||||||
|
|
||||||
int gz = origin.z;
|
|
||||||
for (int z = 0; z < bs.z; ++z, gz += stride) {
|
|
||||||
|
|
||||||
int gx = origin.x;
|
|
||||||
for (int x = 0; x < bs.x; ++x, gx += stride) {
|
|
||||||
|
|
||||||
// Output is blocky, so we can go for just one sample
|
|
||||||
float h = _range.xform(height_func(gx, origin.y, gz));
|
|
||||||
h -= origin.y;
|
|
||||||
int ih = int(h);
|
|
||||||
if (ih > 0) {
|
|
||||||
if (ih > bs.y) {
|
|
||||||
ih = bs.y;
|
|
||||||
}
|
|
||||||
out_buffer.fill_area(_matter_type, Vector3i(x, 0, z), Vector3i(x + 1, ih, z + 1), channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // for x
|
|
||||||
} // for z
|
|
||||||
} // use_sdf
|
|
||||||
|
|
||||||
return Result();
|
return Result();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<OpenSimplexNoise> _noise, _mount_noise;
|
|
||||||
|
|
||||||
struct Range {
|
|
||||||
float start = -250;
|
|
||||||
float height = 500;
|
|
||||||
|
|
||||||
inline float xform(float x) const {
|
|
||||||
return x * height + start;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
float mount_offset = 50.0f;
|
|
||||||
float main_multiplier = 0.1f;
|
|
||||||
Vector3 initial_spawn;
|
|
||||||
float initial_spawn_radius = 150.0f;
|
|
||||||
float initial_spawn_height = 20.0f;
|
|
||||||
|
|
||||||
VoxelBuffer::ChannelId _channel = VoxelBuffer::CHANNEL_SDF;
|
|
||||||
int _matter_type = 1;
|
int _matter_type = 1;
|
||||||
Range _range;
|
|
||||||
float _iso_scale = 0.1;
|
float _iso_scale = 0.1;
|
||||||
float mount_multiplier = 1.5f;
|
|
||||||
Ref<DensityMap> density_map;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VOXEL_GENERATOR_NOISE_2D_H
|
#endif // VOXEL_GENERATOR_NOISE_2D_H
|
||||||
|
|||||||
Reference in New Issue
Block a user