diff --git a/modules/world/roads.cpp b/modules/world/roads.cpp index e9e5d6b..b9c504e 100644 --- a/modules/world/roads.cpp +++ b/modules/world/roads.cpp @@ -9,9 +9,14 @@ #include #include "roads.h" +enum { + FLAGS_SIDEWALK = (1 << 0), + FLAGS_INTERSECTION = (1 << 1), + FLAGS_WALL = (1 << 2), +}; + void Roads::_bind_methods() { - ClassDB::bind_method(D_METHOD("curve_mesh", "points", "width", "flags", "sidewalk_width"), &Roads::curve_mesh); ClassDB::bind_method(D_METHOD("add_scene_element", "root", "surface", "p2", "shape"), &Roads::add_scene_element); } void Roads::_get_property_list(List *p_list) const @@ -171,21 +176,36 @@ Ref Roads::build_curve(Vector3 p1, Vector3 p2, Vector3 p3, float total_ assert(curve3->get_baked_length() > 0); return curve3; } +inline float Roads::get_total_width(float width, int flags, float sidewalk_width) +{ + int i; + float total_width = 0.0f; + PoolVector parts_list = rg->build_item_list(width, flags, sidewalk_width); + for (i = 0; i < parts_list.size(); i++) + total_width += offsets[parts_list[i]].x; + return total_width; +} -Array Roads::curve_mesh(PoolVector points, float width1, float width2, int flags, float sidewalk_width) +inline Ref Roads::get_curve(const PoolVector &points, float width, int flags, float sidewalk_width) +{ + float total_width = get_total_width(width, flags, sidewalk_width); + Ref curve = build_curve(points[0], points[1], points[2], total_width); + return curve; +} + +Array Roads::curve_mesh(const PoolVector &points, Ref curve3, float width1, float width2, int flags, float sidewalk_width) { float tx = 0.0f, total_width1 = 0.0f, total_width2 = 0.0f, t = 0.0f, l; int i; Array ret; all_offsets(); + total_width1 = get_total_width(width1, flags, sidewalk_width); + total_width2 = get_total_width(width2, flags, sidewalk_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); +// Ref curve3 = build_curve(points[0], points[1], points[2], total_width2); +// Ref curve3 = get_curve(points, width2, flags, sidewalk_width); l = curve3->get_baked_length(); assert(l > 0.0f); PoolVector new_verts, new_normals; @@ -321,9 +341,11 @@ static Ref create_concave_polygon_shape(Vector surfa return shape; } -int Roads::make_vmesh(Node *root, Ref mat, Ref mesh, MeshInstance *xmi, Vector3 p1, Vector3 p2, - Vector3 p3, float width1, float width2, int flags, float sidewalk_width) +static inline PoolVector make_points(const PoolVector &ipoints) { + Vector3 p1 = ipoints[0], + p2 = ipoints[1], + p3 = ipoints[2]; Vector3 m1 = p1 - p2; Vector3 m2 = Vector3(); Vector3 m3 = p3 - p2; @@ -339,7 +361,16 @@ 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, width1, width2, flags, sidewalk_width); + return points; +} + +int Roads::make_vmesh(Node *root, Ref mat, Ref mesh, MeshInstance *xmi, RoadMeshData *data) +{ + int i; + PoolVector points = make_points(data->points); + rg->all_offsets(); + Ref curve3 = get_curve(points, data->width2, data->flags, data->sidewalk_width); + Array rdata = curve_mesh(points, curve3, data->width1, data->width2, data->flags, data->sidewalk_width); Ref mdata = mesh; assert(mdata.is_valid()); mdata->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, rdata); @@ -349,7 +380,7 @@ int Roads::make_vmesh(Node *root, Ref mat, Ref mesh, MeshIn Ref shape = create_concave_polygon_shape(surfaces); mdata->surface_set_material(0, mat); xmi->set_mesh(mdata); - call_deferred("add_scene_element", root, xmi, p2, shape); + call_deferred("add_scene_element", root, xmi, data->points[1], shape); return xmi->get_instance_id(); } @@ -415,27 +446,39 @@ void Roads::process_vshapes() List::Element *e; for (e = active_vshapes.front(); e; e = e->next()) { i = e->get(); - const struct RoadGrid::vshape &v = vshapes[i]; + struct RoadGrid::vshape &v = rg->get_vshapes().write()[i]; assert(v.p1.distance_squared_to(v.p2) > 2.0f); assert(v.p2.distance_squared_to(v.p3) > 2.0f); assert(v.p1.distance_squared_to(v.p3) > 2.0f); + float sidewalk_width = 6.0f; if (vshapes[i].instance < 0) { if (thread.thread.is_started()) thread.thread.wait_to_finish(); thread.mat = mat; - thread.vshape = i; - thread.width = 6.0; - thread.sidewalk_width = 3.0; - thread.flags = FLAGS_SIDEWALK|FLAGS_INTERSECTION; thread.root = this; Ref mesh; mesh.instance(); thread.mesh = mesh; thread.xmi = memnew(MeshInstance); + create_data(&v, &thread.data, + FLAGS_SIDEWALK|FLAGS_INTERSECTION, + sidewalk_width); thread.thread.start(generate_threaded, &thread); } } } +void Roads::create_data(struct RoadGrid::vshape *v, struct RoadMeshData *data, int flags, float sidewalk_width) +{ + data->points.resize(3); + data->points.write()[0] = v->p1; + data->points.write()[1] = v->p2; + data->points.write()[2] = v->p3; + data->width1 = v->depth1; + data->width2 = v->depth2; + data->flags = flags; + data->sidewalk_width = sidewalk_width; + data->vshape = v; +} void Roads::_notification(int p_what) { @@ -456,19 +499,11 @@ void Roads::generate_threaded(void *p_userdata) { struct thread_data *data = (struct thread_data *)p_userdata; Roads *obj = Object::cast_to(data->root); - obj->mutex.lock(); - RoadGrid *rg = RoadsData::get_singleton()->get_road_grid(); - const PoolVector &vshapes = rg->get_vshapes(); - 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, width1, width2, data->flags, data->sidewalk_width); + int instance = obj->make_vmesh(obj, data->mat, data->mesh, data->xmi, &data->data); assert(instance >= 0); obj->mutex.lock(); - rg->get_vshapes().write()[data->vshape].instance = instance; + + data->data.vshape->instance = instance; obj->mutex.unlock(); } diff --git a/modules/world/roads.h b/modules/world/roads.h index 7f18276..2f5710e 100644 --- a/modules/world/roads.h +++ b/modules/world/roads.h @@ -6,6 +6,16 @@ #include class StaticBody; +struct RoadGrid::vshape; + +struct RoadMeshData { + PoolVector points; + float width1; + float width2; + int flags; + float sidewalk_width; + struct RoadGrid::vshape *vshape; +}; class Roads: public MeshInstance { GDCLASS(Roads, MeshInstance); @@ -25,13 +35,10 @@ protected: struct thread_data { Thread thread; Ref mat; - int vshape; - float width; - float sidewalk_width; - int flags; Node *root; Ref mesh; MeshInstance *xmi; + struct RoadMeshData data; }; struct thread_data thread; static void generate_threaded(void *p_userdata); @@ -70,11 +77,16 @@ 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 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 width1, float width2, int flags, float sidewalk_width); + // Array curve_mesh(PoolVector points, float width1, float width2, int flags, float sidewalk_width); + Array curve_mesh(const PoolVector &points, Ref curve3, float width1, float width2, int flags, float sidewalk_width); + int make_vmesh(Node *root, Ref mat, Ref mesh, MeshInstance *xmi, RoadMeshData *data); void process_vshapes(); + void create_data(struct RoadGrid::vshape *v, + struct RoadMeshData *data, + int flags, float sidewalk_width); void add_scene_element(Node *root, Node *xnode, const Vector3 &p2, Ref shape); + inline float get_total_width(float width, int flags, float sidewalk_width); + inline Ref get_curve(const PoolVector &points, float width, int flags, float sidewalk_width); }; class RoadsData: public Object {