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.
This commit is contained in:
Juan Linietsky 2022-09-23 12:37:40 +02:00
parent 99bc4905cb
commit 71d2e38cb5
11 changed files with 170 additions and 81 deletions

View file

@ -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]);
}
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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();
};

View file

@ -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;

View file

@ -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);

View file

@ -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]]);

View file

@ -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;
}

View file

@ -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++) {

View file

@ -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() {

View file

@ -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);