Skip to content

Commit

Permalink
Merge pull request #45854 from nekomatata/cylinder-support
Browse files Browse the repository at this point in the history
Cylinder support in Godot Physics 3D
  • Loading branch information
akien-mga authored Feb 10, 2021
2 parents 1808f1d + 333f184 commit 3c39aa8
Show file tree
Hide file tree
Showing 8 changed files with 1,078 additions and 83 deletions.
5 changes: 5 additions & 0 deletions COPYRIGHT.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ Copyright: 2008-2016, The Android Open Source Project
2002, Google, Inc.
License: Apache-2.0

Files: ./servers/physics_3d/collision_solver_3d_sat.cpp
Comment: Open Dynamics Engine
Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
License: BSD-3-clause

Files: ./servers/physics_3d/gjk_epa.cpp
./servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
./servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
Expand Down
33 changes: 21 additions & 12 deletions core/math/geometry_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,27 +252,34 @@ class Geometry3D {
return true;
}

static inline bool segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, real_t p_height, real_t p_radius, Vector3 *r_res = nullptr, Vector3 *r_norm = nullptr) {
static inline bool segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, real_t p_height, real_t p_radius, Vector3 *r_res = nullptr, Vector3 *r_norm = nullptr, int p_cylinder_axis = 2) {
Vector3 rel = (p_to - p_from);
real_t rel_l = rel.length();
if (rel_l < CMP_EPSILON) {
return false; // Both points are the same.
}

ERR_FAIL_COND_V(p_cylinder_axis < 0, false);
ERR_FAIL_COND_V(p_cylinder_axis > 2, false);
Vector3 cylinder_axis;
cylinder_axis[p_cylinder_axis] = 1.0;

// First check if they are parallel.
Vector3 normal = (rel / rel_l);
Vector3 crs = normal.cross(Vector3(0, 0, 1));
Vector3 crs = normal.cross(cylinder_axis);
real_t crs_l = crs.length();

Vector3 z_dir;
Vector3 axis_dir;

if (crs_l < CMP_EPSILON) {
z_dir = Vector3(1, 0, 0); // Any x/y vector OK.
Vector3 side_axis;
side_axis[(p_cylinder_axis + 1) % 3] = 1.0; // Any side axis OK.
axis_dir = side_axis;
} else {
z_dir = crs / crs_l;
axis_dir = crs / crs_l;
}

real_t dist = z_dir.dot(p_from);
real_t dist = axis_dir.dot(p_from);

if (dist >= p_radius) {
return false; // Too far away.
Expand All @@ -285,10 +292,10 @@ class Geometry3D {
}
Size2 size(Math::sqrt(w2), p_height * 0.5);

Vector3 x_dir = z_dir.cross(Vector3(0, 0, 1)).normalized();
Vector3 side_dir = axis_dir.cross(cylinder_axis).normalized();

Vector2 from2D(x_dir.dot(p_from), p_from.z);
Vector2 to2D(x_dir.dot(p_to), p_to.z);
Vector2 from2D(side_dir.dot(p_from), p_from[p_cylinder_axis]);
Vector2 to2D(side_dir.dot(p_to), p_to[p_cylinder_axis]);

real_t min = 0, max = 1;

Expand Down Expand Up @@ -335,10 +342,12 @@ class Geometry3D {
Vector3 res_normal = result;

if (axis == 0) {
res_normal.z = 0;
res_normal[p_cylinder_axis] = 0;
} else {
res_normal.x = 0;
res_normal.y = 0;
int axis_side = (p_cylinder_axis + 1) % 3;
res_normal[axis_side] = 0;
axis_side = (axis_side + 1) % 3;
res_normal[axis_side] = 0;
}

res_normal.normalize();
Expand Down
Loading

0 comments on commit 3c39aa8

Please sign in to comment.