diff --git a/godot b/godot index 3ca8003..d65f066 160000 --- a/godot +++ b/godot @@ -1 +1 @@ -Subproject commit 3ca80031995c8f4d312fcb4c955b83163d30b656 +Subproject commit d65f06652e9b22a2cc065313e8c6ab98c05f032a diff --git a/modules/voxel b/modules/voxel index fcca722..6cd143d 160000 --- a/modules/voxel +++ b/modules/voxel @@ -1 +1 @@ -Subproject commit fcca722d52c1be5e4555cfe28e42da227b183fd0 +Subproject commit 6cd143d392382612db51d51b46729a3da995847c diff --git a/modules/world/characters.cpp b/modules/world/characters.cpp index 9440970..6b9a736 100644 --- a/modules/world/characters.cpp +++ b/modules/world/characters.cpp @@ -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(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(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(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,7 +551,8 @@ void Characters_::_notification(int p_what) debug->set_color(Color(1, 0, 0, 1)); } for (e = char_node_list.front(); e; e = e->next()) { - debug->set_color(Color(1, 0, 0, 1)); + if (debug) + debug->set_color(Color(1, 0, 0, 1)); Node *ch = e->get(); if (!ch->has_meta("animation_tree")) continue; @@ -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(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 points; Vector flags; - 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; + 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(); } 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 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 mat; mat.instance(); diff --git a/modules/world/characters.h b/modules/world/characters.h index 69de15b..8e1fd3d 100644 --- a/modules/world/characters.h +++ b/modules/world/characters.h @@ -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; }; diff --git a/modules/world/road_grid.cpp b/modules/world/road_grid.cpp index 1934529..96542ca 100644 --- a/modules/world/road_grid.cpp +++ b/modules/world/road_grid.cpp @@ -1,7 +1,10 @@ #include #include +#include +#include #include #include +#include #include #include #include @@ -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 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 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 &RoadDiagram::get_clusters() const +{ + return clusters; +} +const Vector &RoadDiagram::get_map_sites() const +{ + return map_sites; +} +const Vector &RoadDiagram::get_diagram_vertices() const +{ + return diagram_vertices; +} +const Vector &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 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, Ref 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 &cl = rd.get_clusters(); + const List::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, Ref 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 &sort_data) sorter.sort(sort_data.ptrw(), sort_data.size()); } -void RoadGrid::generate_3d_vertices() +void RoadGrid::generate_3d_vertices(Ref curve, Ref noise) { - int i; + int i, j; + Vector 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 +static Array avar2str(const Vector &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(); + } +} + + diff --git a/modules/world/road_grid.h b/modules/world/road_grid.h index a35ce0f..a781131 100644 --- a/modules/world/road_grid.h +++ b/modules/world/road_grid.h @@ -32,25 +32,15 @@ class CanvasItem; * - Implement 3D positions and geometry generation */ -class RoadGrid: public Reference { - GDCLASS(RoadGrid, Object) -protected: - Ref rnd; - struct cluster { - Vector2i c; - float r; - }; - List clusters; - Dictionary build_diagram(int npatches, int center_count, int center_step, - int spread, int dim); - HashMap class_sizes; - struct half_edge; - Rect2 bounds; - void set_class_size(int cl, int sz) - { - class_sizes[cl] = sz; - } - static void _bind_methods(); +struct cluster { + Vector2i c; + float r; +}; +struct graphedge { + int a, b; + int edge; +}; +struct map_site { enum { SITE_UNASSIGNED = 0, SITE_FOREST, @@ -59,36 +49,33 @@ 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 graphedges; - Vector vertices; - Vector polygon; - Vector vertices_ind; - Vector polygon_ind; - int site_type; - int cluster; - Vector hedges; - Vector2 building_positions; - Rect2i rect; - float avg_height; - }; - void index_site(struct map_site *site); - Vector diagram_vertices; - Vector diagram_vertex_heights; + int index; + Vector2 pos; + Vector graphedges; + Vector vertices; + Vector polygon; + Vector vertices_ind; + Vector polygon_ind; + int site_type; + int cluster; + Vector hedges; + Vector2 building_positions; + Rect2i rect; + float avg_height; +}; +struct half_edge { + int a, b; + int site; + float depth; + float length; +}; +class RoadDiagram { +protected: + List clusters; Vector map_sites; + Vector diagram_vertices; Vector map_hedges; + HashMap 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 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 &get_clusters() const; + const Vector &get_map_sites() const; + const Vector &get_diagram_vertices() const; + const Vector &get_map_hedges() const; + void build(Ref rnd, + int npatches, int center_count, int center_step, + int spread, int dim); +}; + +class RoadGrid: public Reference { + GDCLASS(RoadGrid, Object) +protected: + Ref rnd; + int keep_seed; + List 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 diagram_vertices; + Vector map_sites; + Vector map_hedges; + PoolVector vertices; + PoolVector 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; } + inline void insert_hedge_to_grid_cell(int x, int y, struct half_edge *hedge) + { + static int count = 0; + count++; + set(x, y, hedge); + printf("count: %d\n", count); + } }; 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); - printf("count: %d\n", count); - } 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 vertices; -public: - struct vshape { - AABB area; - int instance; - int e1, e2; - int site; - Vector3 p1, p2, p3; - }; -protected: - PoolVector vshapes; void sort_angle(Vector &sort_data); public: void build(Ref curve, Ref noise); @@ -252,17 +271,17 @@ public: { return map_hedges.size(); } - void generate_3d_vertices(); + void generate_3d_vertices(Ref curve, Ref 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(); int count = 0, i; int psize = map_sites[site].polygon_ind.size(); PoolVector polygon; @@ -298,6 +319,8 @@ public: { if (polygon_cache_3d.has(site)) return polygon_cache_3d[site]; + if (map_sites.size() <= site) + return PoolVector(); int count = 0, i; int psize = map_sites[site].polygon_ind.size(); PoolVector polygon; @@ -329,5 +352,6 @@ public: } return ret; } + void save_json(const String &path); }; #endif diff --git a/modules/world/roads.cpp b/modules/world/roads.cpp index c562662..e9e5d6b 100644 --- a/modules/world/roads.cpp +++ b/modules/world/roads.cpp @@ -172,17 +172,20 @@ Ref Roads::build_curve(Vector3 p1, Vector3 p2, Vector3 p3, float total_ return curve3; } -Array Roads::curve_mesh(PoolVector points, float width, int flags, float sidewalk_sidth) +Array Roads::curve_mesh(PoolVector 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 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 curve3 = build_curve(points[0], points[1], points[2], total_width); + PoolVector 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 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 curve3 = build_curve(points[0], points[1], points[2], total_width2); l = curve3->get_baked_length(); assert(l > 0.0f); PoolVector new_verts, new_normals; @@ -193,9 +196,9 @@ Array Roads::curve_mesh(PoolVector 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 verts = data[Mesh::ARRAY_VERTEX]; PoolVector normals = data[Mesh::ARRAY_NORMAL]; @@ -226,7 +229,7 @@ Array Roads::curve_mesh(PoolVector 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 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 points, float width, int flags, floa static Ref create_concave_polygon_shape(Vector surfaces) { PoolVector 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 create_concave_polygon_shape(Vector 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 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(); } @@ -287,6 +293,10 @@ static Ref create_concave_polygon_shape(Vector surfa PoolVector positions = surface_arrays[Mesh::ARRAY_VERTEX]; PoolVector 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()); ERR_FAIL_COND_V(indices.size() < 3, Ref()); ERR_FAIL_COND_V(indices.size() % 3 != 0, Ref()); @@ -312,7 +322,7 @@ static Ref create_concave_polygon_shape(Vector surfa } int Roads::make_vmesh(Node *root, Ref mat, Ref 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 mat, Ref 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 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, Refget_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 active_vshapes; const PoolVector &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::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 noise) { diff --git a/modules/world/roads.h b/modules/world/roads.h index a8bb09d..7f18276 100644 --- a/modules/world/roads.h +++ b/modules/world/roads.h @@ -70,9 +70,9 @@ public: void all_offsets(); PoolVector build_item_list(float width, int flags, float sidewalk_width) const; Ref build_curve(Vector3 p1, Vector3 p2, Vector3 p3, float total_width) const; - Array curve_mesh(PoolVector points, float width, int flags, float sidewalk_width); + Array curve_mesh(PoolVector points, float width1, float width2, int flags, float sidewalk_width); int make_vmesh(Node *root, Ref mat, Ref 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 shape); }; @@ -104,5 +104,9 @@ public: { return rg->get_site_avg_height(site); } + inline void save_json(const String &path) + { + rg->save_json(path); + } };