mirror of
https://github.com/godotengine/godot.git
synced 2024-11-10 14:12:51 +00:00
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:
parent
99bc4905cb
commit
71d2e38cb5
@ -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]);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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]]);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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++) {
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user