Update; refactor of initial code

This commit is contained in:
Segey Lapin
2021-10-22 15:43:37 +03:00
parent da73a164a0
commit 2945dd1904
8 changed files with 397 additions and 151 deletions

2
godot

Submodule godot updated: 3ca8003199...d65f06652e

View File

@@ -18,6 +18,7 @@ Characters_::Characters_() : query(memnew(DetourNavigationQuery)),
crowd(NULL)
{
smm = NULL;
no_navmesh = true;
}
AnimationTree *Characters_::get_animation_tree(const Node *npc) const
{
@@ -173,6 +174,8 @@ void Characters_::rotate_to_agent(Spatial *obj)
}
void Characters_::speed_to_agent(Spatial *obj)
{
if (!crowd)
return;
float delta = get_physics_process_delta_time();
float cur_speed = get_walk_speed(obj);
float new_speed;
@@ -269,6 +272,8 @@ void Characters_::speed_to_agent(Spatial *obj)
}
bool Characters_::has_arrived(Object *obj)
{
if (!crowd)
return false;
Spatial *sp = Object::cast_to<Spatial>(obj);
if (!obj->has_meta("agent_id"))
return false;
@@ -287,6 +292,8 @@ bool Characters_::has_arrived(Object *obj)
}
void Characters_::update_arrived(Object *obj)
{
if (!crowd)
return;
Spatial *sp = Object::cast_to<Spatial>(obj);
int agent_id = obj->get_meta("agent_id");
if (obj->has_meta("climb"))
@@ -331,6 +338,7 @@ void Characters_::character_physics(Object *obj)
orientation = obj->get_meta("orientation");
root_motion = animtree->get_root_motion_transform();
root_motion.origin = root_motion_mod.xform(root_motion.origin);
orientation *= root_motion;
h_velocity = orientation.origin / delta;
velocity = h_velocity;
@@ -350,7 +358,7 @@ void Characters_::character_physics(Object *obj)
velocity = kb->move_and_slide(velocity, Vector3(0.0f, 1.0f, 0.0f), true, 4, 0.785f, false);
}
orientation.origin = Vector3();
orientation = orientation.orthonormalized();
orientation.orthonormalize();
obj->set_meta("orientation", orientation);
Spatial *sp = Object::cast_to<Spatial>(obj);
if (sp) {
@@ -513,7 +521,8 @@ void Characters_::walkto_agent_node(Node *ch, const Node *target)
}
void Characters_::walkto_agent(Node *ch, const Vector3 &target)
{
assert(crowd);
if (!crowd)
return;
if (ch->has_meta("_target")) {
Vector3 otarget = ch->get_meta("_target");
if (otarget == target)
@@ -542,6 +551,7 @@ void Characters_::_notification(int p_what)
debug->set_color(Color(1, 0, 0, 1));
}
for (e = char_node_list.front(); e; e = e->next()) {
if (debug)
debug->set_color(Color(1, 0, 0, 1));
Node *ch = e->get();
if (!ch->has_meta("animation_tree"))
@@ -595,9 +605,10 @@ void Characters_::_notification(int p_what)
continue;
if (!ch->has_meta("orientation"))
continue;
printf("running physics for %p\n", ch);
character_physics(ch);
Spatial *sp = Object::cast_to<Spatial>(ch);
Vector3 direction = -sp->get_global_transform().basis[2];
Vector3 direction = sp->get_global_transform().xform(Vector3(0, 0, -1));
ch->set_meta("direction", direction);
}
#if 0
@@ -630,9 +641,20 @@ void Characters_::_bind_methods()
ClassDB::bind_method(D_METHOD("walkto_agent", "ch", "target"), &Characters_::walkto_agent);
ClassDB::bind_method(D_METHOD("walkto_agent_node", "ch", "target"), &Characters_::walkto_agent_node);
ClassDB::bind_method(D_METHOD("character_physics", "obj"), &Characters_::character_physics);
ClassDB::bind_method(D_METHOD("set_root_motion_mod", "xform"), &Characters_::set_root_motion_mod);
ClassDB::bind_method(D_METHOD("get_root_motion_mod"), &Characters_::get_root_motion_mod);
ADD_SIGNAL(MethodInfo("arrived", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::VECTOR3, "where")));
}
void Characters_::set_root_motion_mod(const Transform &xform)
{
root_motion_mod = xform;
}
Transform Characters_::get_root_motion_mod() const
{
return root_motion_mod;
}
void Characters_::process_frozen_character(Node *npc, const Vector3 &tposition)
{
float delta = npc->get_process_delta_time();
@@ -691,11 +713,14 @@ void Characters_::process_character(Node *node, bool frozen)
if (!paths.has(id)) {
Vector<Vector3> points;
Vector<int> flags;
if (!no_navmesh) {
Vector3 start = query->nearest_point(position, Vector3(1, 1, 1), filter);
Vector3 end = query->nearest_point(target, Vector3(1, 1, 1), filter);
query->find_path_array(start, end, Vector3(1, 1, 1), filter, points, flags);
assert(points.size() > 0);
paths[id] = points;
} else
paths[id] = Vector<Vector3>();
}
if (debug)
for (i = 0; i < paths[id].size() - 1; i++) {
@@ -753,10 +778,16 @@ void Characters_::walkto_node(const Node *ch, const Node *target)
void Characters_::set_navmesh(Ref<DetourNavigationMesh> mesh, const Transform &xform)
{
if (mesh.is_null()) {
no_navmesh = true;
initialized = true;
return;
}
query->init(mesh, xform);
filter.instance();
debug = memnew(ImmediateGeometry);
add_child(debug);
no_navmesh = false;
initialized = true;
Ref<SpatialMaterial> mat;
mat.instance();

View File

@@ -39,6 +39,8 @@ public:
Object *get_crowd_();
bool has_arrived(Object *obj);
void agent_walk_stop(Object *obj);
void set_root_motion_mod(const Transform &xform);
Transform get_root_motion_mod() const;
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -56,5 +58,7 @@ protected:
ImmediateGeometry *debug;
DetourCrowdManager *crowd;
float arrive_precision;
Transform root_motion_mod;
bool no_navmesh;
};

View File

@@ -1,7 +1,10 @@
#include <cassert>
#include <cmath>
#include <core/os/file_access.h>
#include <core/io/json.h>
#include <core/math/geometry.h>
#include <core/resource.h>
#include <core/variant_parser.h>
#include <scene/2d/canvas_item.h>
#include <modules/voronoi/voronoi.h>
#include <modules/opensimplex/open_simplex_noise.h>
@@ -11,11 +14,6 @@ RoadGrid::RoadGrid()
{
grid_width = 16;
grid_height = 16;
class_sizes[SITE_EMPTY] = 10000;
class_sizes[SITE_TOWN] = 100000;
class_sizes[SITE_FARM] = 500000;
class_sizes[SITE_FOREST] = 1000000;
class_sizes[SITE_UNASSIGNED] = 2000000;
}
RoadGrid::~RoadGrid()
@@ -23,7 +21,7 @@ RoadGrid::~RoadGrid()
}
/* TODO: constants, configuration */
Dictionary RoadGrid::build_diagram(int npatches, int center_count, int center_step, int spread, int dim)
Dictionary RoadDiagram::build_diagram(Ref<RandomNumberGenerator> rnd, int npatches, int center_count, int center_step, int spread, int dim)
{
printf("build_diagram %d %d %d %d %d\n", npatches, center_count, center_step, spread, dim);
Vector<Vector2i> centers;
@@ -72,6 +70,22 @@ Dictionary RoadGrid::build_diagram(int npatches, int center_count, int center_st
Dictionary diagram = Voronoi::get_singleton()->generate_diagram(cpoints, 11);
return diagram;
}
const List<struct cluster> &RoadDiagram::get_clusters() const
{
return clusters;
}
const Vector<struct map_site> &RoadDiagram::get_map_sites() const
{
return map_sites;
}
const Vector<Vector2> &RoadDiagram::get_diagram_vertices() const
{
return diagram_vertices;
}
const Vector<struct half_edge *> &RoadDiagram::get_map_hedges() const
{
return map_hedges;
}
bool RoadGrid::segment_intersects_rect(const Vector2 &a, const Vector2 &b, const Rect2 &rect)
{
real_t min = 0, max = 1;
@@ -165,7 +179,7 @@ void RoadGrid::draw_debug(Node *drawable, int size_x, int size_y) const
}
}
void RoadGrid::index_site(struct map_site *site)
void RoadDiagram::index_site(struct map_site *site)
{
int i;
site->vertices_ind.resize(site->vertices.size());
@@ -203,14 +217,21 @@ void RoadGrid::index_site(struct map_site *site)
he.b = idx2;
he.site = site->index;
/* use length to decide */
he.depth = 6.0f;
he.length = diagram_vertices[idx1].distance_to(diagram_vertices[idx2]);
if (he.length < 50.0f)
he.depth = 3.0f;
else if (he.length < 100.0f)
he.depth = 6.0f;
else if (he.length < 200.0f)
he.depth = 12.0f;
else
he.depth = 24.0f;
site->hedges.write[count++] = he;
}
site->hedges.resize(count);
}
void RoadGrid::process_diagram(const Dictionary &diagram)
void RoadDiagram::process_diagram(const Dictionary &diagram)
{
const Array &sites = diagram["sites"];
int i, j;
@@ -237,7 +258,7 @@ void RoadGrid::process_diagram(const Dictionary &diagram)
site.pos = site_data["pos"];
site.polygon = site_data["polygon"];
site.vertices = site_data["vertices"];
site.site_type = SITE_UNASSIGNED;
site.site_type = map_site::SITE_UNASSIGNED;
site.cluster = -1;
index_site(&site);
hedge_count += site.hedges.size();
@@ -253,7 +274,6 @@ void RoadGrid::process_diagram(const Dictionary &diagram)
/* bad bad constness */
struct half_edge *hedge = &map_sites.write[i].hedges.write[j];
map_hedges.write[hedge_idx] = hedge;
add_hedge_to_grid(hedge);
hedge_idx++;
}
}
@@ -261,49 +281,48 @@ void RoadGrid::process_diagram(const Dictionary &diagram)
classify_sites();
printf("processing done, sites count: %d\n", map_sites.size());
}
RoadDiagram::RoadDiagram()
{
class_sizes[map_site::SITE_EMPTY] = 10000;
class_sizes[map_site::SITE_TOWN] = 100000;
class_sizes[map_site::SITE_FARM] = 500000;
class_sizes[map_site::SITE_FOREST] = 1000000;
class_sizes[map_site::SITE_UNASSIGNED] = 2000000;
}
void RoadDiagram::build(Ref<RandomNumberGenerator> rnd,
int npatches, int center_count, int center_step,
int spread, int dim)
{
Dictionary diagram = build_diagram(rnd, npatches, center_count, center_step,
spread, dim);
process_diagram(diagram);
}
void RoadGrid::build(Ref<Curve> curve, Ref<FastNoiseLite> noise)
{
int i, j;
RoadDiagram rd;
rnd.instance();
rnd->randomize();
printf("build_diagram\n");
// Dictionary diagram = build_diagram(8, 2 + (rnd->randi() % 2), 100, 100, 50);
Dictionary diagram = build_diagram(8, 2, 100, 100, 500);
rd.build(rnd, 8, 2, 100, 100, 500);
printf("build_diagram done\n");
printf("process_diagram\n");
process_diagram(diagram);
printf("process_diagram done\n");
const List<struct cluster> &cl = rd.get_clusters();
const List<struct cluster>::Element *e = cl.front();
for (e = cl.front(); e; e = e->next())
clusters.push_back(e->get());
map_sites.append_array(rd.get_map_sites());
diagram_vertices.append_array(rd.get_diagram_vertices());
map_hedges.append_array(rd.get_map_hedges());
for (i = 0; i < map_hedges.size(); i++) {
struct half_edge *hedge = map_hedges.write[i];
add_hedge_to_grid(hedge);
}
printf("%d %d\n", curve.is_valid(), noise.is_valid());
assert(curve.is_valid() && noise.is_valid());
int i, j;
if (curve.is_valid() && noise.is_valid()) {
printf("building 3rd dimention\n");
diagram_vertex_heights.resize(diagram_vertices.size());
for (i = 0; i < diagram_vertices.size(); i++) {
const Vector2 &v = diagram_vertices[i];
float n = noise->get_noise_2d(v.x, v.y);
float t = (n + 1.0f) * 0.5f;
float d = MAX(1.0f, curve->interpolate_baked(t));
d = CLAMP(d, 1.0f, 30.0f);
diagram_vertex_heights.write[i] = d;
}
for (j = 0; j < 3; j++) {
for (i = 0; i < map_hedges.size(); i++) {
int x1 = map_hedges[i]->a;
int x2 = map_hedges[i]->b;
float xd = map_hedges[i]->length;
float dh = fabsf(diagram_vertex_heights[x2] - diagram_vertex_heights[x1]);
if (fabsf(dh / xd) > 0.01f)
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
}
generate_3d_vertices();
generate_3d_vertices(curve, noise);
for (i = 0; i < map_sites.size(); i++) {
float max_height = -10000.0f;
float min_height = 10000.0f;
@@ -319,6 +338,7 @@ void RoadGrid::build(Ref<Curve> curve, Ref<FastNoiseLite> noise)
generate_building_positions();
printf("building 3rd dimention done\n");
}
keep_seed = rnd->get_state();
}
Vector2 RoadGrid::get_influence(int x, int y, float radius) const
@@ -345,13 +365,13 @@ Vector2 RoadGrid::get_influence(int x, int y, float radius) const
Vector2 seg[] = {a, b};
Vector2 pt = Geometry::get_closest_point_to_segment_2d(p, seg);
float d = pt.distance_squared_to(p);
if (d < radius * radius) {
if (d < radius * radius + he->depth * he->depth) {
Vector2 ret;
ret.x = 1.0f;
assert(diagram_vertex_heights.size() > he->a);
assert(diagram_vertex_heights.size() > he->b);
float h1 = diagram_vertex_heights[he->a];
float h2 = diagram_vertex_heights[he->b];
assert(vertices.size() > he->a);
assert(vertices.size() > he->b);
float h1 = vertices[he->a].y;
float h2 = vertices[he->b].y;
float l = he->length;
assert(l > 0.0f);
float m1 = pt.distance_to(a) / l;
@@ -409,6 +429,8 @@ void RoadGrid::setup_vshapes()
v.area.expand_to(vertices[b1] + Vector3(0, 1, 0));
v.area.expand_to(vertices[b2] + Vector3(0, -1, 0));
v.instance = -1;
v.depth1 = map_hedges[v.e1]->depth;
v.depth2 = map_hedges[v.e2]->depth;
Vector3 p1 = vertices[map_hedges[v.e1]->a];
Vector3 p2 = vertices[map_hedges[v.e1]->b];
Vector3 p3 = vertices[map_hedges[v.e2]->b];
@@ -492,9 +514,29 @@ void RoadGrid::sort_angle(Vector<int> &sort_data)
sorter.sort(sort_data.ptrw(), sort_data.size());
}
void RoadGrid::generate_3d_vertices()
void RoadGrid::generate_3d_vertices(Ref<Curve> curve, Ref<FastNoiseLite> noise)
{
int i;
int i, j;
Vector<float> diagram_vertex_heights;
diagram_vertex_heights.resize(diagram_vertices.size());
for (i = 0; i < diagram_vertices.size(); i++) {
const Vector2 &v = diagram_vertices[i];
float n = noise->get_noise_2d(v.x, v.y);
float t = (n + 1.0f) * 0.5f;
float d = MAX(1.0f, curve->interpolate_baked(t));
d = CLAMP(d, 1.0f, 30.0f);
diagram_vertex_heights.write[i] = d;
}
for (j = 0; j < 3; j++) {
for (i = 0; i < map_hedges.size(); i++) {
int x1 = map_hedges[i]->a;
int x2 = map_hedges[i]->b;
float xd = map_hedges[i]->length;
float dh = fabsf(diagram_vertex_heights[x2] - diagram_vertex_heights[x1]);
if (fabsf(dh / xd) > 0.01f)
diagram_vertex_heights.write[x2] = diagram_vertex_heights[x1] + dh / fabsf(dh) * 0.01f * xd;
}
}
vertices.resize(get_diagram_vertex_count());
for (i = 0; i < vertices.size(); i++) {
vertices.write()[i].x = diagram_vertices[i].x;
@@ -525,3 +567,117 @@ int RoadGrid::get_site_from_point(int x, int z)
return -1;
}
static String var2str(const Variant &data)
{
String s;
VariantWriter::write_to_string(data, s);
return s;
}
template <class T>
static Array avar2str(const Vector<T> &data)
{
Array pdata;
int i;
pdata.resize(data.size());
for (i = 0; i < data.size(); i++)
pdata[i] = var2str(data[i]);
return pdata;
}
static Dictionary half_edge2dict(const struct half_edge *he)
{
Dictionary ret;
ret["a"] = he->a;
ret["b"] = he->b;
ret["site"] = he->site;
ret["depth"] = he->depth;
ret["length"] = he->length;
return ret;
}
static Array rect2i_array(const Rect2i &rect)
{
Array tmp;
tmp.resize(4);
tmp[0] = rect.position[0];
tmp[1] = rect.position[1];
tmp[2] = rect.size[0];
tmp[3] = rect.size[1];
return tmp;
}
static Dictionary map_site2dict(const struct map_site *ms)
{
int i;
Dictionary ret;
Array hedges;
ret["index"] = ms->index;
ret["pos"] = var2str(ms->pos);
ret["vertices"] = avar2str(ms->vertices);
ret["polygon"] = avar2str(ms->polygon);
ret["vertices_ind"] = avar2str(ms->vertices_ind);
ret["polygon_ind"] = avar2str(ms->polygon_ind);
ret["site_type"] = ms->site_type;
ret["cluster"] = ms->cluster;
hedges.resize(ms->hedges.size());
for (i = 0; i < ms->hedges.size(); i++)
hedges[i] = half_edge2dict(&ms->hedges[i]);
ret["hedges"] = hedges;
ret["rect"] = rect2i_array(ms->rect);
ret["avg_height"] = ms->avg_height;
return ret;
}
static Dictionary vshape2dict(const struct RoadGrid::vshape *v)
{
Dictionary ret;
ret["area"] = var2str(v->area);
ret["instance"] = v->instance;
ret["e1"] = v->e1;
ret["e2"] = v->e2;
ret["site"] = v->site;
ret["p1"] = var2str(v->p1);
ret["p2"] = var2str(v->p2);
ret["p3"] = var2str(v->p3);
ret["depth1"] = v->depth1;
ret["depth2"] = v->depth2;
return ret;
}
void RoadGrid::save_json(const String &path)
{
int i;
String vars;
FileAccess *f;
Dictionary to_json;
/* Clusters */
Array save_clusters;
/* save clusters */
save_clusters.resize(clusters.size());
for (i = 0; i < clusters.size(); i++) {
Dictionary cluster;
cluster["pos_x"] = clusters[i].c.x;
cluster["pos_y"] = clusters[i].c.y;
cluster["radius"] = clusters[i].r;
save_clusters[i] = cluster;
}
to_json["clusters"] = save_clusters;
to_json["bounds"] = var2str(bounds);
to_json["diagram_vertices"] = avar2str(diagram_vertices);
Array msites, mvshapes;
msites.resize(map_sites.size());
for (i = 0; i < map_sites.size(); i++)
msites[i] = map_site2dict(&map_sites[i]);
to_json["map_sites"] = msites;
to_json["vertices"] = var2str(vertices);
mvshapes.resize(vshapes.size());
for (i = 0; i < vshapes.size(); i++) {
const struct vshape *v = &(vshapes.read()[i]);
mvshapes[i] = vshape2dict(v);
}
to_json["vshapes"] = mvshapes;
String json = JSON::print(to_json, "\t");
f = FileAccess::open(path, FileAccess::WRITE);
if (f) {
f->store_string(json);
f->close();
}
}

View File

@@ -32,25 +32,15 @@ class CanvasItem;
* - Implement 3D positions and geometry generation
*/
class RoadGrid: public Reference {
GDCLASS(RoadGrid, Object)
protected:
Ref<RandomNumberGenerator> rnd;
struct cluster {
Vector2i c;
float r;
};
List<struct cluster> clusters;
Dictionary build_diagram(int npatches, int center_count, int center_step,
int spread, int dim);
HashMap<int, int> class_sizes;
struct half_edge;
Rect2 bounds;
void set_class_size(int cl, int sz)
{
class_sizes[cl] = sz;
}
static void _bind_methods();
struct graphedge {
int a, b;
int edge;
};
struct map_site {
enum {
SITE_UNASSIGNED = 0,
SITE_FOREST,
@@ -59,17 +49,6 @@ protected:
SITE_EMPTY,
SITE_MAX
};
struct graphedge {
int a, b;
int edge;
};
struct half_edge {
int a, b;
int site;
float depth;
float length;
};
struct map_site {
int index;
Vector2 pos;
Vector<struct graphedge> graphedges;
@@ -84,11 +63,19 @@ protected:
Rect2i rect;
float avg_height;
};
void index_site(struct map_site *site);
Vector<Vector2> diagram_vertices;
Vector<float> diagram_vertex_heights;
struct half_edge {
int a, b;
int site;
float depth;
float length;
};
class RoadDiagram {
protected:
List<struct cluster> clusters;
Vector<struct map_site> map_sites;
Vector<Vector2> diagram_vertices;
Vector<struct half_edge *> map_hedges;
HashMap<int, int> class_sizes;
void classify_sites()
{
int i, j;
@@ -103,7 +90,7 @@ protected:
}
}
int cl_area = (int)(r.get_area() + 1.0f);
for (i = 0; i < SITE_MAX; i++) {
for (i = 0; i < map_site::SITE_MAX; i++) {
if (class_sizes.has(i))
if (cl_area <= class_sizes[i]) {
map_sites.write[j].site_type = i;
@@ -113,9 +100,52 @@ protected:
/* for now the starting town is at 0 */
printf("area: %d class: %d\n", cl_area, map_sites[j].site_type);
}
map_sites.write[0].site_type = SITE_TOWN;
map_sites.write[0].site_type = map_site::SITE_TOWN;
}
void index_site(struct map_site *site);
Dictionary build_diagram(Ref<RandomNumberGenerator> rnd,
int npatches, int center_count, int center_step,
int spread, int dim);
void process_diagram(const Dictionary &diagram);
public:
RoadDiagram();
void set_class_size(int cl, int sz)
{
class_sizes[cl] = sz;
}
const List<struct cluster> &get_clusters() const;
const Vector<struct map_site> &get_map_sites() const;
const Vector<Vector2> &get_diagram_vertices() const;
const Vector<struct half_edge *> &get_map_hedges() const;
void build(Ref<RandomNumberGenerator> rnd,
int npatches, int center_count, int center_step,
int spread, int dim);
};
class RoadGrid: public Reference {
GDCLASS(RoadGrid, Object)
protected:
Ref<RandomNumberGenerator> rnd;
int keep_seed;
List<struct cluster> clusters;
protected:
Rect2 bounds;
static void _bind_methods();
public:
struct vshape {
AABB area;
int instance;
int e1, e2;
int site;
Vector3 p1, p2, p3;
float depth1, depth2;
};
protected:
Vector<Vector2> diagram_vertices;
Vector<struct map_site> map_sites;
Vector<struct half_edge *> map_hedges;
PoolVector<Vector3> vertices;
PoolVector<struct vshape> vshapes;
bool segment_intersects_rect(const Vector2 &a, const Vector2 &b, const Rect2 &rect);
inline bool segment_in_grid_rect(const Vector2 &a, const Vector2 &b, int x, int y)
{
@@ -170,15 +200,15 @@ protected:
items.write[items.size() - 1] = hedge;
hedge_grid[x][y] = items;
}
};
class hg hedge_grid;
inline void insert_hedge_to_grid_cell(int x, int y, struct half_edge *hedge)
{
static int count = 0;
count++;
hedge_grid.set(x, y, hedge);
set(x, y, hedge);
printf("count: %d\n", count);
}
};
class hg hedge_grid;
inline void add_hedge_to_grid(struct half_edge *hedge)
{
Vector2 a = diagram_vertices[hedge->a];
@@ -201,7 +231,7 @@ protected:
int py = rgrid.position.y + y;
Rect2 xr = get_grid_rect(px, py).grow(16.0f);
if (segment_intersects_rect(a, b, xr))
insert_hedge_to_grid_cell(px, py, hedge);
hedge_grid.insert_hedge_to_grid_cell(px, py, hedge);
}
}
}
@@ -214,17 +244,6 @@ protected:
return (int)(y / grid_height);
}
float grid_width, grid_height;
PoolVector<Vector3> vertices;
public:
struct vshape {
AABB area;
int instance;
int e1, e2;
int site;
Vector3 p1, p2, p3;
};
protected:
PoolVector<struct vshape> vshapes;
void sort_angle(Vector<int> &sort_data);
public:
void build(Ref<Curve> curve, Ref<FastNoiseLite> noise);
@@ -252,17 +271,17 @@ public:
{
return map_hedges.size();
}
void generate_3d_vertices();
void generate_3d_vertices(Ref<Curve> curve, Ref<FastNoiseLite> noise);
void generate_building_positions();
void generate_site_building_positions(const struct map_site *site);
int get_site_from_point(int x, int z);
inline bool site_is_town(int site)
{
return map_sites[site].site_type == SITE_TOWN;
return map_sites[site].site_type == map_site::SITE_TOWN;
}
inline bool site_is_farm(int site)
{
return map_sites[site].site_type == SITE_FARM;
return map_sites[site].site_type == map_site::SITE_FARM;
}
inline float get_site_avg_height(int site)
{
@@ -277,6 +296,8 @@ public:
{
if (polygon_cache_2d.has(site))
return polygon_cache_2d[site];
if (map_sites.size() <= site)
return PoolVector<Vector2>();
int count = 0, i;
int psize = map_sites[site].polygon_ind.size();
PoolVector<Vector2> polygon;
@@ -298,6 +319,8 @@ public:
{
if (polygon_cache_3d.has(site))
return polygon_cache_3d[site];
if (map_sites.size() <= site)
return PoolVector<Vector3>();
int count = 0, i;
int psize = map_sites[site].polygon_ind.size();
PoolVector<Vector3> polygon;
@@ -329,5 +352,6 @@ public:
}
return ret;
}
void save_json(const String &path);
};
#endif

View File

@@ -172,17 +172,20 @@ Ref<Curve3D> Roads::build_curve(Vector3 p1, Vector3 p2, Vector3 p3, float total_
return curve3;
}
Array Roads::curve_mesh(PoolVector<Vector3> points, float width, int flags, float sidewalk_sidth)
Array Roads::curve_mesh(PoolVector<Vector3> points, float width1, float width2, int flags, float sidewalk_width)
{
float tx = 0.0f, total_width = 0.0f, t = 0.0f, l;
float tx = 0.0f, total_width1 = 0.0f, total_width2 = 0.0f, t = 0.0f, l;
int i;
Array ret;
all_offsets();
PoolVector<String> parts_list = build_item_list(width, flags, sidewalk_sidth);
for (i = 0; i < parts_list.size(); i++)
total_width += offsets[parts_list[i]].x;
assert(total_width >= 3.0f);
Ref<Curve3D> curve3 = build_curve(points[0], points[1], points[2], total_width);
PoolVector<String> parts_list1 = build_item_list(width1, flags, sidewalk_width);
for (i = 0; i < parts_list1.size(); i++)
total_width1 += offsets[parts_list1[i]].x;
PoolVector<String> parts_list2 = build_item_list(width2, flags, sidewalk_width);
for (i = 0; i < parts_list2.size(); i++)
total_width2 += offsets[parts_list2[i]].x;
assert(total_width1 >= 3.0f && total_width2 >= 3.0f);
Ref<Curve3D> curve3 = build_curve(points[0], points[1], points[2], total_width2);
l = curve3->get_baked_length();
assert(l > 0.0f);
PoolVector<Vector3> new_verts, new_normals;
@@ -193,9 +196,9 @@ Array Roads::curve_mesh(PoolVector<Vector3> points, float width, int flags, floa
while (t <= l) {
tx = 0.0f;
int part = 0;
while (tx < total_width) {
while (tx < total_width2) {
int k;
Array data = mesh_data[parts_list[part]];
Array data = mesh_data[parts_list2[part]];
int b = new_verts.size();
PoolVector<Vector3> verts = data[Mesh::ARRAY_VERTEX];
PoolVector<Vector3> normals = data[Mesh::ARRAY_NORMAL];
@@ -226,7 +229,7 @@ Array Roads::curve_mesh(PoolVector<Vector3> points, float width, int flags, floa
Vector3 n = xform.xform(normals[k]);
if (right < 0.15f &&
((flags & FLAGS_INTERSECTION) != 0) &&
nvert.distance_squared_to(points[1]) < total_width * total_width * 2.5f) {
nvert.distance_squared_to(points[1]) < total_width2 * total_width2 * 2.5f) {
new_verts.write()[b + k] = points[1];
new_normals.write()[b + k] = Vector3(0.0f, 1.0f, 0.0f);
} else {
@@ -240,9 +243,9 @@ Array Roads::curve_mesh(PoolVector<Vector3> points, float width, int flags, floa
new_index.resize(idx + index.size());
for (k = 0; k < index.size(); k++)
new_index.write()[idx + k] = index[k] + b;
tx += offsets[parts_list[part]].x;
tx += offsets[parts_list2[part]].x;
part += 1;
if (part >= parts_list.size())
if (part >= parts_list2.size())
break;
}
t += 2.0f;
@@ -258,6 +261,7 @@ Array Roads::curve_mesh(PoolVector<Vector3> points, float width, int flags, floa
static Ref<ConcavePolygonShape> create_concave_polygon_shape(Vector<Array> surfaces) {
PoolVector<Vector3> face_points;
int face_points_size = 0;
assert(surfaces.size() > 0);
//find the correct size for face_points
for (int i = 0; i < surfaces.size(); i++) {
@@ -268,12 +272,14 @@ static Ref<ConcavePolygonShape> create_concave_polygon_shape(Vector<Array> surfa
}
// If the surface is not empty then it must have an expected amount of data arrays
ERR_CONTINUE(surface_arrays.size() != Mesh::ARRAY_MAX);
assert(surface_arrays.size() == Mesh::ARRAY_MAX);
PoolVector<int> indices = surface_arrays[Mesh::ARRAY_INDEX];
face_points_size += indices.size();
}
face_points.resize(face_points_size);
if (face_points_size < 3) {
assert(0);
return Ref<ConcavePolygonShape>();
}
@@ -287,6 +293,10 @@ static Ref<ConcavePolygonShape> create_concave_polygon_shape(Vector<Array> surfa
PoolVector<Vector3> positions = surface_arrays[Mesh::ARRAY_VERTEX];
PoolVector<int> indices = surface_arrays[Mesh::ARRAY_INDEX];
assert(positions.size() >= 3);
assert(indices.size() >= 3);
assert(indices.size() % 3 == 0);
ERR_FAIL_COND_V(positions.size() < 3, Ref<ConcavePolygonShape>());
ERR_FAIL_COND_V(indices.size() < 3, Ref<ConcavePolygonShape>());
ERR_FAIL_COND_V(indices.size() % 3 != 0, Ref<ConcavePolygonShape>());
@@ -312,7 +322,7 @@ static Ref<ConcavePolygonShape> create_concave_polygon_shape(Vector<Array> surfa
}
int Roads::make_vmesh(Node *root, Ref<Material> mat, Ref<ArrayMesh> mesh, MeshInstance *xmi, Vector3 p1, Vector3 p2,
Vector3 p3, float width, int flags, float sidewalk_width)
Vector3 p3, float width1, float width2, int flags, float sidewalk_width)
{
Vector3 m1 = p1 - p2;
Vector3 m2 = Vector3();
@@ -329,7 +339,7 @@ int Roads::make_vmesh(Node *root, Ref<Material> mat, Ref<ArrayMesh> mesh, MeshIn
points.resize(3);
for (i = 0; i < 3; i++)
points.write()[i] = pts[i].snapped(Vector3(4.0f, 0.1f, 4.0f));
Array rdata = curve_mesh(points, width, flags, sidewalk_width);
Array rdata = curve_mesh(points, width1, width2, flags, sidewalk_width);
Ref<ArrayMesh> mdata = mesh;
assert(mdata.is_valid());
mdata->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, rdata);
@@ -352,9 +362,25 @@ void Roads::add_scene_element(Node *root, Node *xnode, const Vector3 &p2, Ref<Co
Transform xform(Basis(), p2);
assert(xmi->get_mesh().is_valid() && xmi->get_mesh()->get_surface_count() > 0);
xmi->set_global_transform(xform);
printf("trimesh collision\n");
#if 0
Node *c = xmi->create_trimesh_collision();
assert(c);
add_child(c);
#if 0
CollisionShape *cs = memnew(CollisionShape);
cs->set_shape(shape);
body->add_child(cs);
#endif
#endif
StaticBody *sb = memnew(StaticBody);
CollisionShape *cs = memnew(CollisionShape);
assert(sb);
assert(cs);
sb->add_child(cs);
assert(!shape.is_null());
cs->set_shape(shape);
xmi->call_deferred("add_child", sb);
}
void Roads::process_vshapes()
@@ -368,7 +394,6 @@ void Roads::process_vshapes()
int i;
List<int> active_vshapes;
const PoolVector<struct RoadGrid::vshape> &vshapes = rg->get_vshapes();
printf("camera %f %f %f\n", cam_xform.origin.x, cam_xform.origin.y, cam_xform.origin.z);
for (i = 0; i < vshapes.size(); i++) {
if (active_vshapes.size() > 32)
break;
@@ -387,7 +412,6 @@ void Roads::process_vshapes()
active_vshapes.push_back(i);
#endif
}
printf("active vshapes %d\n", active_vshapes.size());
List<int>::Element *e;
for (e = active_vshapes.front(); e; e = e->next()) {
i = e->get();
@@ -438,8 +462,10 @@ void Roads::generate_threaded(void *p_userdata)
Vector3 p1 = vshapes[data->vshape].p1;
Vector3 p2 = vshapes[data->vshape].p2;
Vector3 p3 = vshapes[data->vshape].p3;
float width1 = vshapes[data->vshape].depth1;
float width2 = vshapes[data->vshape].depth2;
obj->mutex.unlock();
int instance = obj->make_vmesh(obj, data->mat, data->mesh, data->xmi, p1, p2, p3, data->width, data->flags, data->sidewalk_width);
int instance = obj->make_vmesh(obj, data->mat, data->mesh, data->xmi, p1, p2, p3, width1, width2, data->flags, data->sidewalk_width);
assert(instance >= 0);
obj->mutex.lock();
rg->get_vshapes().write()[data->vshape].instance = instance;
@@ -484,6 +510,7 @@ void RoadsData::_bind_methods()
ClassDB::bind_method(D_METHOD("get_site_polygon_3d", "site"), &RoadsData::get_site_polygon_3d);
ClassDB::bind_method(D_METHOD("get_here_sites", "site"), &RoadsData::get_here_sites);
ClassDB::bind_method(D_METHOD("get_site_avg_height", "site"), &RoadsData::get_site_avg_height);
ClassDB::bind_method(D_METHOD("save_json", "path"), &RoadsData::save_json);
}
void RoadsData::set_noise(Ref<FastNoiseLite> noise)
{

View File

@@ -70,9 +70,9 @@ public:
void all_offsets();
PoolVector<String> build_item_list(float width, int flags, float sidewalk_width) const;
Ref<Curve3D> build_curve(Vector3 p1, Vector3 p2, Vector3 p3, float total_width) const;
Array curve_mesh(PoolVector<Vector3> points, float width, int flags, float sidewalk_width);
Array curve_mesh(PoolVector<Vector3> points, float width1, float width2, int flags, float sidewalk_width);
int make_vmesh(Node *root, Ref<Material> mat, Ref<ArrayMesh> mesh, MeshInstance *xmi, Vector3 p1, Vector3 p2,
Vector3 p3, float width, int flags, float sidewalk_width);
Vector3 p3, float width1, float width2, int flags, float sidewalk_width);
void process_vshapes();
void add_scene_element(Node *root, Node *xnode, const Vector3 &p2, Ref<ConcavePolygonShape> shape);
};
@@ -104,5 +104,9 @@ public:
{
return rg->get_site_avg_height(site);
}
inline void save_json(const String &path)
{
rg->save_json(path);
}
};