Преглед на файлове

Optimize Convex Collision

Implements the Gauss Mapping optimization to SAT convex collision test.

* Described [here](https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2013/slides/822403Gregorius_Dirk_TheSeparatingAxisTest.pdf) by Dirk Gregorius.
* Requires adding of face information to edges in MeshData
* Took the chance to convert MeshData to LocalVector for performance.
Juan Linietsky преди 2 години
родител
ревизия
71d2e38cb5

+ 49 - 5
core/math/convex_hull.cpp

@@ -62,6 +62,7 @@ subject to the following restrictions:
 #include "core/math/aabb.h"
 #include "core/math/math_defs.h"
 #include "core/os/memory.h"
+#include "core/templates/oa_hash_map.h"
 #include "core/templates/paged_allocator.h"
 
 #include <string.h>
@@ -2252,19 +2253,62 @@ Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3
 
 	r_mesh.vertices = ch.vertices;
 
+	// Tag which face each edge belongs to
+	LocalVector<int32_t> edge_faces;
+	edge_faces.resize(ch.edges.size());
+
+	for (uint32_t i = 0; i < ch.edges.size(); i++) {
+		edge_faces[i] = -1;
+	}
+
+	for (uint32_t i = 0; i < ch.faces.size(); i++) {
+		const Edge *e_start = &ch.edges[ch.faces[i]];
+		const Edge *e = e_start;
+		do {
+			int64_t ofs = e - ch.edges.ptr();
+			edge_faces[ofs] = i;
+
+			e = e->get_next_edge_of_face();
+		} while (e != e_start);
+	}
+
 	// Copy the edges over. There's two "half-edges" for every edge, so we pick only one of them.
 	r_mesh.edges.resize(ch.edges.size() / 2);
+	OAHashMap<uint64_t, int32_t> edge_map;
+	edge_map.reserve(ch.edges.size() * 4); // The higher the capacity, the faster the insert
+
 	uint32_t edges_copied = 0;
 	for (uint32_t i = 0; i < ch.edges.size(); i++) {
+		ERR_CONTINUE(edge_faces[i] == -1); // Sanity check
+
 		uint32_t a = (&ch.edges[i])->get_source_vertex();
 		uint32_t b = (&ch.edges[i])->get_target_vertex();
 		if (a < b) { // Copy only the "canonical" edge. For the reverse edge, this will be false.
 			ERR_BREAK(edges_copied >= (uint32_t)r_mesh.edges.size());
-			r_mesh.edges.write[edges_copied].a = a;
-			r_mesh.edges.write[edges_copied].b = b;
+			r_mesh.edges[edges_copied].vertex_a = a;
+			r_mesh.edges[edges_copied].vertex_b = b;
+			r_mesh.edges[edges_copied].face_a = edge_faces[i];
+			r_mesh.edges[edges_copied].face_b = -1;
+
+			uint64_t key = a;
+			key <<= 32;
+			key |= b;
+			edge_map.insert(key, edges_copied);
+
 			edges_copied++;
+		} else {
+			uint64_t key = b;
+			key <<= 32;
+			key |= a;
+			int32_t index;
+			if (!edge_map.lookup(key, index)) {
+				ERR_PRINT("Invalid edge");
+			} else {
+				r_mesh.edges[index].face_b = edge_faces[i];
+			}
 		}
 	}
+
 	if (edges_copied != (uint32_t)r_mesh.edges.size()) {
 		ERR_PRINT("Invalid edge count.");
 	}
@@ -2273,7 +2317,7 @@ Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3
 	for (uint32_t i = 0; i < ch.faces.size(); i++) {
 		const Edge *e_start = &ch.edges[ch.faces[i]];
 		const Edge *e = e_start;
-		Geometry3D::MeshData::Face &face = r_mesh.faces.write[i];
+		Geometry3D::MeshData::Face &face = r_mesh.faces[i];
 
 		do {
 			face.indices.push_back(e->get_target_vertex());
@@ -2284,8 +2328,8 @@ Error ConvexHullComputer::convex_hull(const Vector<Vector3> &p_points, Geometry3
 		// reverse indices: Godot wants clockwise, but this is counter-clockwise
 		if (face.indices.size() > 2) {
 			// reverse all but the first index.
-			int *indices = face.indices.ptrw();
-			for (int c = 0; c < (face.indices.size() - 1) / 2; c++) {
+			int *indices = face.indices.ptr();
+			for (uint32_t c = 0; c < (face.indices.size() - 1) / 2; c++) {
 				SWAP(indices[c + 1], indices[face.indices.size() - 1 - c]);
 			}
 		}

+ 5 - 1
core/math/convex_hull.h

@@ -62,6 +62,10 @@ public:
 		friend class ConvexHullComputer;
 
 	public:
+		int32_t get_next_relative() const {
+			return next;
+		}
+
 		int32_t get_source_vertex() const {
 			return (this + reverse)->target_vertex;
 		}
@@ -86,7 +90,7 @@ public:
 	};
 
 	// Vertices of the output hull
-	Vector<Vector3> vertices;
+	LocalVector<Vector3> vertices;
 
 	// Edges of the output hull
 	LocalVector<Edge> edges;

+ 28 - 22
core/math/geometry_3d.cpp

@@ -141,21 +141,21 @@ real_t Geometry3D::get_closest_distance_between_segments(const Vector3 &p_p0, co
 void Geometry3D::MeshData::optimize_vertices() {
 	HashMap<int, int> vtx_remap;
 
-	for (int i = 0; i < faces.size(); i++) {
-		for (int j = 0; j < faces[i].indices.size(); j++) {
+	for (uint32_t i = 0; i < faces.size(); i++) {
+		for (uint32_t j = 0; j < faces[i].indices.size(); j++) {
 			int idx = faces[i].indices[j];
 			if (!vtx_remap.has(idx)) {
 				int ni = vtx_remap.size();
 				vtx_remap[idx] = ni;
 			}
 
-			faces.write[i].indices.write[j] = vtx_remap[idx];
+			faces[i].indices[j] = vtx_remap[idx];
 		}
 	}
 
-	for (int i = 0; i < edges.size(); i++) {
-		int a = edges[i].a;
-		int b = edges[i].b;
+	for (uint32_t i = 0; i < edges.size(); i++) {
+		int a = edges[i].vertex_a;
+		int b = edges[i].vertex_b;
 
 		if (!vtx_remap.has(a)) {
 			int ni = vtx_remap.size();
@@ -166,16 +166,16 @@ void Geometry3D::MeshData::optimize_vertices() {
 			vtx_remap[b] = ni;
 		}
 
-		edges.write[i].a = vtx_remap[a];
-		edges.write[i].b = vtx_remap[b];
+		edges[i].vertex_a = vtx_remap[a];
+		edges[i].vertex_b = vtx_remap[b];
 	}
 
-	Vector<Vector3> new_vertices;
+	LocalVector<Vector3> new_vertices;
 	new_vertices.resize(vtx_remap.size());
 
-	for (int i = 0; i < vertices.size(); i++) {
+	for (uint32_t i = 0; i < vertices.size(); i++) {
 		if (vtx_remap.has(i)) {
-			new_vertices.write[vtx_remap[i]] = vertices[i];
+			new_vertices[vtx_remap[i]] = vertices[i];
 		}
 	}
 	vertices = new_vertices;
@@ -751,7 +751,7 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
 		Vector3 center = p.center();
 
 		// make a quad clockwise
-		Vector<Vector3> vertices = {
+		LocalVector<Vector3> vertices = {
 			center - up * subplane_size + right * subplane_size,
 			center - up * subplane_size - right * subplane_size,
 			center + up * subplane_size - right * subplane_size,
@@ -763,7 +763,7 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
 				continue;
 			}
 
-			Vector<Vector3> new_vertices;
+			LocalVector<Vector3> new_vertices;
 			Plane clip = p_planes[j];
 
 			if (clip.normal.dot(p.normal) > 0.95f) {
@@ -774,7 +774,7 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
 				break;
 			}
 
-			for (int k = 0; k < vertices.size(); k++) {
+			for (uint32_t k = 0; k < vertices.size(); k++) {
 				int k_n = (k + 1) % vertices.size();
 
 				Vector3 edge0_A = vertices[k];
@@ -816,9 +816,9 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
 		MeshData::Face face;
 
 		// Add face indices.
-		for (int j = 0; j < vertices.size(); j++) {
+		for (uint32_t j = 0; j < vertices.size(); j++) {
 			int idx = -1;
-			for (int k = 0; k < mesh.vertices.size(); k++) {
+			for (uint32_t k = 0; k < mesh.vertices.size(); k++) {
 				if (mesh.vertices[k].distance_to(vertices[j]) < 0.001f) {
 					idx = k;
 					break;
@@ -837,28 +837,34 @@ Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes
 
 		// Add edge.
 
-		for (int j = 0; j < face.indices.size(); j++) {
+		for (uint32_t j = 0; j < face.indices.size(); j++) {
 			int a = face.indices[j];
 			int b = face.indices[(j + 1) % face.indices.size()];
 
 			bool found = false;
-			for (int k = 0; k < mesh.edges.size(); k++) {
-				if (mesh.edges[k].a == a && mesh.edges[k].b == b) {
+			int found_idx = -1;
+			for (uint32_t k = 0; k < mesh.edges.size(); k++) {
+				if (mesh.edges[k].vertex_a == a && mesh.edges[k].vertex_b == b) {
 					found = true;
+					found_idx = k;
 					break;
 				}
-				if (mesh.edges[k].b == a && mesh.edges[k].a == b) {
+				if (mesh.edges[k].vertex_b == a && mesh.edges[k].vertex_a == b) {
 					found = true;
+					found_idx = k;
 					break;
 				}
 			}
 
 			if (found) {
+				mesh.edges[found_idx].face_b = j;
 				continue;
 			}
 			MeshData::Edge edge;
-			edge.a = a;
-			edge.b = b;
+			edge.vertex_a = a;
+			edge.vertex_b = b;
+			edge.face_a = j;
+			edge.face_b = -1;
 			mesh.edges.push_back(edge);
 		}
 	}

+ 7 - 5
core/math/geometry_3d.h

@@ -33,6 +33,7 @@
 
 #include "core/math/face3.h"
 #include "core/object/object.h"
+#include "core/templates/local_vector.h"
 #include "core/templates/vector.h"
 
 class Geometry3D {
@@ -539,18 +540,19 @@ public:
 	struct MeshData {
 		struct Face {
 			Plane plane;
-			Vector<int> indices;
+			LocalVector<int> indices;
 		};
 
-		Vector<Face> faces;
+		LocalVector<Face> faces;
 
 		struct Edge {
-			int a, b;
+			int vertex_a, vertex_b;
+			int face_a, face_b;
 		};
 
-		Vector<Edge> edges;
+		LocalVector<Edge> edges;
 
-		Vector<Vector3> vertices;
+		LocalVector<Vector3> vertices;
 
 		void optimize_vertices();
 	};

+ 13 - 6
core/math/quick_hull.cpp

@@ -369,7 +369,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
 	for (List<Geometry3D::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) {
 		Geometry3D::MeshData::Face &f = E->get();
 
-		for (int i = 0; i < f.indices.size(); i++) {
+		for (uint32_t i = 0; i < f.indices.size(); i++) {
 			int a = E->get().indices[i];
 			int b = E->get().indices[(i + 1) % f.indices.size()];
 			Edge e(a, b);
@@ -436,17 +436,24 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
 	r_mesh.faces.clear();
 	r_mesh.faces.resize(ret_faces.size());
 
+	HashMap<List<Geometry3D::MeshData::Face>::Element *, int> face_indices;
+
 	int idx = 0;
-	for (const Geometry3D::MeshData::Face &E : ret_faces) {
-		r_mesh.faces.write[idx++] = E;
+	for (List<Geometry3D::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) {
+		face_indices[E] = idx;
+		r_mesh.faces[idx++] = E->get();
 	}
 	r_mesh.edges.resize(ret_edges.size());
 	idx = 0;
 	for (const KeyValue<Edge, RetFaceConnect> &E : ret_edges) {
 		Geometry3D::MeshData::Edge e;
-		e.a = E.key.vertices[0];
-		e.b = E.key.vertices[1];
-		r_mesh.edges.write[idx++] = e;
+		e.vertex_a = E.key.vertices[0];
+		e.vertex_b = E.key.vertices[1];
+		ERR_CONTINUE(!face_indices.has(E.value.left));
+		ERR_CONTINUE(!face_indices.has(E.value.right));
+		e.face_a = face_indices[E.value.left];
+		e.face_b = face_indices[E.value.right];
+		r_mesh.edges[idx++] = e;
 	}
 
 	r_mesh.vertices = p_points;

+ 3 - 3
editor/plugins/node_3d_editor_gizmos.cpp

@@ -4751,9 +4751,9 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			if (err == OK) {
 				Vector<Vector3> points2;
 				points2.resize(md.edges.size() * 2);
-				for (int i = 0; i < md.edges.size(); i++) {
-					points2.write[i * 2 + 0] = md.vertices[md.edges[i].a];
-					points2.write[i * 2 + 1] = md.vertices[md.edges[i].b];
+				for (uint32_t i = 0; i < md.edges.size(); i++) {
+					points2.write[i * 2 + 0] = md.vertices[md.edges[i].vertex_a];
+					points2.write[i * 2 + 1] = md.vertices[md.edges[i].vertex_b];
 				}
 
 				p_gizmo->add_lines(points2, material);

+ 6 - 6
modules/navigation/navigation_mesh_generator.cpp

@@ -266,10 +266,10 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
 						if (err == OK) {
 							PackedVector3Array faces;
 
-							for (int j = 0; j < md.faces.size(); ++j) {
-								Geometry3D::MeshData::Face face = md.faces[j];
+							for (uint32_t j = 0; j < md.faces.size(); ++j) {
+								const Geometry3D::MeshData::Face &face = md.faces[j];
 
-								for (int k = 2; k < face.indices.size(); ++k) {
+								for (uint32_t k = 2; k < face.indices.size(); ++k) {
 									faces.push_back(md.vertices[face.indices[0]]);
 									faces.push_back(md.vertices[face.indices[k - 1]]);
 									faces.push_back(md.vertices[face.indices[k]]);
@@ -392,10 +392,10 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
 						if (err == OK) {
 							PackedVector3Array faces;
 
-							for (int j = 0; j < md.faces.size(); ++j) {
-								Geometry3D::MeshData::Face face = md.faces[j];
+							for (uint32_t j = 0; j < md.faces.size(); ++j) {
+								const Geometry3D::MeshData::Face &face = md.faces[j];
 
-								for (int k = 2; k < face.indices.size(); ++k) {
+								for (uint32_t k = 2; k < face.indices.size(); ++k) {
 									faces.push_back(md.vertices[face.indices[0]]);
 									faces.push_back(md.vertices[face.indices[k - 1]]);
 									faces.push_back(md.vertices[face.indices[k]]);

+ 3 - 3
scene/resources/convex_polygon_shape_3d.cpp

@@ -42,9 +42,9 @@ Vector<Vector3> ConvexPolygonShape3D::get_debug_mesh_lines() const {
 		if (err == OK) {
 			Vector<Vector3> lines;
 			lines.resize(md.edges.size() * 2);
-			for (int i = 0; i < md.edges.size(); i++) {
-				lines.write[i * 2 + 0] = md.vertices[md.edges[i].a];
-				lines.write[i * 2 + 1] = md.vertices[md.edges[i].b];
+			for (uint32_t i = 0; i < md.edges.size(); i++) {
+				lines.write[i * 2 + 0] = md.vertices[md.edges[i].vertex_a];
+				lines.write[i * 2 + 1] = md.vertices[md.edges[i].vertex_b];
 			}
 			return lines;
 		}

+ 41 - 20
servers/physics_3d/godot_collision_solver_3d_sat.cpp

@@ -964,8 +964,8 @@ static void _collision_sphere_convex_polygon(const GodotShape3D *p_a, const Tran
 
 	// edges of B
 	for (int i = 0; i < edge_count; i++) {
-		Vector3 v1 = p_transform_b.xform(vertices[edges[i].a]);
-		Vector3 v2 = p_transform_b.xform(vertices[edges[i].b]);
+		Vector3 v1 = p_transform_b.xform(vertices[edges[i].vertex_a]);
+		Vector3 v2 = p_transform_b.xform(vertices[edges[i].vertex_b]);
 		Vector3 v3 = p_transform_a.origin;
 
 		Vector3 n1 = v2 - v1;
@@ -1404,7 +1404,7 @@ static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transfo
 		Vector3 e1 = p_transform_a.basis.get_column(i);
 
 		for (int j = 0; j < edge_count; j++) {
-			Vector3 e2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]);
+			Vector3 e2 = p_transform_b.basis.xform(vertices[edges[j].vertex_a]) - p_transform_b.basis.xform(vertices[edges[j].vertex_b]);
 
 			Vector3 axis = e1.cross(e2).normalized();
 
@@ -1460,8 +1460,8 @@ static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transfo
 					}
 
 					for (int e = 0; e < edge_count; e++) {
-						Vector3 p1 = p_transform_b.xform(vertices[edges[e].a]);
-						Vector3 p2 = p_transform_b.xform(vertices[edges[e].b]);
+						Vector3 p1 = p_transform_b.xform(vertices[edges[e].vertex_a]);
+						Vector3 p2 = p_transform_b.xform(vertices[edges[e].vertex_b]);
 						Vector3 n = (p2 - p1);
 
 						if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) {
@@ -1771,7 +1771,7 @@ static void _collision_capsule_convex_polygon(const GodotShape3D *p_a, const Tra
 
 	for (int i = 0; i < edge_count; i++) {
 		// cylinder
-		Vector3 edge_axis = p_transform_b.basis.xform(vertices[edges[i].a]) - p_transform_b.basis.xform(vertices[edges[i].b]);
+		Vector3 edge_axis = p_transform_b.basis.xform(vertices[edges[i].vertex_a]) - p_transform_b.basis.xform(vertices[edges[i].vertex_b]);
 		Vector3 axis = edge_axis.cross(p_transform_a.basis.get_column(1)).normalized();
 
 		if (!separator.test_axis(axis)) {
@@ -1789,8 +1789,8 @@ static void _collision_capsule_convex_polygon(const GodotShape3D *p_a, const Tra
 		Vector3 sphere_pos = p_transform_a.origin + ((i == 0) ? capsule_axis : -capsule_axis);
 
 		for (int j = 0; j < edge_count; j++) {
-			Vector3 n1 = sphere_pos - p_transform_b.xform(vertices[edges[j].a]);
-			Vector3 n2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]);
+			Vector3 n1 = sphere_pos - p_transform_b.xform(vertices[edges[j].vertex_a]);
+			Vector3 n2 = p_transform_b.basis.xform(vertices[edges[j].vertex_a]) - p_transform_b.basis.xform(vertices[edges[j].vertex_b]);
 
 			Vector3 axis = n1.cross(n2).cross(n2).normalized();
 
@@ -2075,6 +2075,16 @@ static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D
 	separator.generate_contacts();
 }
 
+static _FORCE_INLINE_ bool is_minkowski_face(const Vector3 &A, const Vector3 &B, const Vector3 &B_x_A, const Vector3 &C, const Vector3 &D, const Vector3 &D_x_C) {
+	// Test if arcs AB and CD intersect on the unit sphere
+	real_t CBA = C.dot(B_x_A);
+	real_t DBA = D.dot(B_x_A);
+	real_t ADC = A.dot(D_x_C);
+	real_t BDC = B.dot(D_x_C);
+
+	return (CBA * DBA < 0.0f) && (ADC * BDC < 0.0f) && (CBA * BDC > 0.0f);
+}
+
 template <bool withMargin>
 static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
 	const GodotConvexPolygonShape3D *convex_polygon_A = static_cast<const GodotConvexPolygonShape3D *>(p_a);
@@ -2129,16 +2139,27 @@ static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, co
 	}
 
 	// A<->B edges
+
 	for (int i = 0; i < edge_count_A; i++) {
-		Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].a]) - p_transform_a.basis.xform(vertices_A[edges_A[i].b]);
+		Vector3 p1 = p_transform_a.xform(vertices_A[edges_A[i].vertex_a]);
+		Vector3 q1 = p_transform_a.xform(vertices_A[edges_A[i].vertex_b]);
+		Vector3 e1 = q1 - p1;
+		Vector3 u1 = p_transform_a.basis.xform(faces_A[edges_A[i].face_a].plane.normal).normalized();
+		Vector3 v1 = p_transform_a.basis.xform(faces_A[edges_A[i].face_b].plane.normal).normalized();
 
 		for (int j = 0; j < edge_count_B; j++) {
-			Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[j].a]) - p_transform_b.basis.xform(vertices_B[edges_B[j].b]);
+			Vector3 p2 = p_transform_b.xform(vertices_B[edges_B[j].vertex_a]);
+			Vector3 q2 = p_transform_b.xform(vertices_B[edges_B[j].vertex_b]);
+			Vector3 e2 = q2 - p2;
+			Vector3 u2 = p_transform_b.basis.xform(faces_B[edges_B[j].face_a].plane.normal).normalized();
+			Vector3 v2 = p_transform_b.basis.xform(faces_B[edges_B[j].face_b].plane.normal).normalized();
 
-			Vector3 axis = e1.cross(e2).normalized();
+			if (is_minkowski_face(u1, v1, -e1, -u2, -v2, -e2)) {
+				Vector3 axis = e1.cross(e2).normalized();
 
-			if (!separator.test_axis(axis)) {
-				return;
+				if (!separator.test_axis(axis)) {
+					return;
+				}
 			}
 		}
 	}
@@ -2157,8 +2178,8 @@ static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, co
 		//edge-vertex (shell)
 
 		for (int i = 0; i < edge_count_A; i++) {
-			Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].a]);
-			Vector3 e2 = p_transform_a.basis.xform(vertices_A[edges_A[i].b]);
+			Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].vertex_a]);
+			Vector3 e2 = p_transform_a.basis.xform(vertices_A[edges_A[i].vertex_b]);
 			Vector3 n = (e2 - e1);
 
 			for (int j = 0; j < vertex_count_B; j++) {
@@ -2171,8 +2192,8 @@ static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, co
 		}
 
 		for (int i = 0; i < edge_count_B; i++) {
-			Vector3 e1 = p_transform_b.basis.xform(vertices_B[edges_B[i].a]);
-			Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[i].b]);
+			Vector3 e1 = p_transform_b.basis.xform(vertices_B[edges_B[i].vertex_a]);
+			Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[i].vertex_b]);
 			Vector3 n = (e2 - e1);
 
 			for (int j = 0; j < vertex_count_A; j++) {
@@ -2231,7 +2252,7 @@ static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transf
 
 	// A<->B edges
 	for (int i = 0; i < edge_count; i++) {
-		Vector3 e1 = p_transform_a.xform(vertices[edges[i].a]) - p_transform_a.xform(vertices[edges[i].b]);
+		Vector3 e1 = p_transform_a.xform(vertices[edges[i].vertex_a]) - p_transform_a.xform(vertices[edges[i].vertex_b]);
 
 		for (int j = 0; j < 3; j++) {
 			Vector3 e2 = vertex[j] - vertex[(j + 1) % 3];
@@ -2266,8 +2287,8 @@ static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transf
 		//edge-vertex (shell)
 
 		for (int i = 0; i < edge_count; i++) {
-			Vector3 e1 = p_transform_a.basis.xform(vertices[edges[i].a]);
-			Vector3 e2 = p_transform_a.basis.xform(vertices[edges[i].b]);
+			Vector3 e1 = p_transform_a.basis.xform(vertices[edges[i].vertex_a]);
+			Vector3 e2 = p_transform_a.basis.xform(vertices[edges[i].vertex_b]);
 			Vector3 n = (e2 - e1);
 
 			for (int j = 0; j < 3; j++) {

+ 13 - 8
servers/physics_3d/godot_shape_3d.cpp

@@ -915,13 +915,13 @@ void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max,
 	}
 
 	for (int i = 0; i < ec; i++) {
-		real_t dot = (vertices[edges[i].a] - vertices[edges[i].b]).normalized().dot(p_normal);
+		real_t dot = (vertices[edges[i].vertex_a] - vertices[edges[i].vertex_b]).normalized().dot(p_normal);
 		dot = ABS(dot);
-		if (dot < edge_support_threshold && (edges[i].a == vtx || edges[i].b == vtx)) {
+		if (dot < edge_support_threshold && (edges[i].vertex_a == vtx || edges[i].vertex_b == vtx)) {
 			r_amount = 2;
 			r_type = FEATURE_EDGE;
-			r_supports[0] = vertices[edges[i].a];
-			r_supports[1] = vertices[edges[i].b];
+			r_supports[0] = vertices[edges[i].vertex_a];
+			r_supports[1] = vertices[edges[i].vertex_b];
 			return;
 		}
 	}
@@ -1025,8 +1025,8 @@ Vector3 GodotConvexPolygonShape3D::get_closest_point_to(const Vector3 &p_point)
 	int ec = mesh.edges.size();
 	for (int i = 0; i < ec; i++) {
 		Vector3 s[2] = {
-			vertices[edges[i].a],
-			vertices[edges[i].b]
+			vertices[edges[i].vertex_a],
+			vertices[edges[i].vertex_b]
 		};
 
 		Vector3 closest = Geometry3D::get_closest_point_to_segment(p_point, s);
@@ -1058,7 +1058,7 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) {
 
 	AABB _aabb;
 
-	for (int i = 0; i < mesh.vertices.size(); i++) {
+	for (uint32_t i = 0; i < mesh.vertices.size(); i++) {
 		if (i == 0) {
 			_aabb.position = mesh.vertices[i];
 		} else {
@@ -1074,7 +1074,12 @@ void GodotConvexPolygonShape3D::set_data(const Variant &p_data) {
 }
 
 Variant GodotConvexPolygonShape3D::get_data() const {
-	return mesh.vertices;
+	Vector<Vector3> vertices;
+	vertices.resize(mesh.vertices.size());
+	for (uint32_t i = 0; i < mesh.vertices.size(); i++) {
+		vertices.write[i] = mesh.vertices[i];
+	}
+	return vertices;
 }
 
 GodotConvexPolygonShape3D::GodotConvexPolygonShape3D() {

+ 2 - 2
servers/rendering_server.cpp

@@ -2791,10 +2791,10 @@ void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry
 	Vector<Vector3> vertices;
 	Vector<Vector3> normals;
 
-	for (int i = 0; i < p_mesh_data.faces.size(); i++) {
+	for (uint32_t i = 0; i < p_mesh_data.faces.size(); i++) {
 		const Geometry3D::MeshData::Face &f = p_mesh_data.faces[i];
 
-		for (int j = 2; j < f.indices.size(); j++) {
+		for (uint32_t j = 2; j < f.indices.size(); j++) {
 			vertices.push_back(p_mesh_data.vertices[f.indices[0]]);
 			normals.push_back(f.plane.normal);