Disable backface collision with ConcavePolygonShape by default
Helps a lot with soft bodies and generally useful to avoid shapes to go through the ground in certain cases. Added an option in ConcavePolygonShape to re-enable backface collision on specific bodies if needed.
This commit is contained in:
parent
c097ce0c18
commit
7bbd545432
8 changed files with 223 additions and 79 deletions
|
@ -28,6 +28,11 @@
|
|||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="backface_collision" type="bool" setter="set_backface_collision_enabled" getter="is_backface_collision_enabled" default="false">
|
||||
If set to [code]true[/code], collisions occur on both sides of the concave shape faces. Otherwise they occur only along the face normals.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -375,11 +375,17 @@ ConcavePolygonShapeBullet::~ConcavePolygonShapeBullet() {
|
|||
}
|
||||
|
||||
void ConcavePolygonShapeBullet::set_data(const Variant &p_data) {
|
||||
setup(p_data);
|
||||
Dictionary d = p_data;
|
||||
ERR_FAIL_COND(!d.has("faces"));
|
||||
|
||||
setup(d["faces"]);
|
||||
}
|
||||
|
||||
Variant ConcavePolygonShapeBullet::get_data() const {
|
||||
return faces;
|
||||
Dictionary d;
|
||||
d["faces"] = faces;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
PhysicsServer3D::ShapeType ConcavePolygonShapeBullet::get_type() const {
|
||||
|
|
|
@ -35,13 +35,12 @@
|
|||
Vector<Vector3> ConcavePolygonShape3D::get_debug_mesh_lines() const {
|
||||
Set<DrawEdge> edges;
|
||||
|
||||
Vector<Vector3> data = get_faces();
|
||||
int datalen = data.size();
|
||||
ERR_FAIL_COND_V((datalen % 3) != 0, Vector<Vector3>());
|
||||
int index_count = faces.size();
|
||||
ERR_FAIL_COND_V((index_count % 3) != 0, Vector<Vector3>());
|
||||
|
||||
const Vector3 *r = data.ptr();
|
||||
const Vector3 *r = faces.ptr();
|
||||
|
||||
for (int i = 0; i < datalen; i += 3) {
|
||||
for (int i = 0; i < index_count; i += 3) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
DrawEdge de(r[i + j], r[i + ((j + 1) % 3)]);
|
||||
edges.insert(de);
|
||||
|
@ -71,22 +70,46 @@ real_t ConcavePolygonShape3D::get_enclosing_radius() const {
|
|||
}
|
||||
|
||||
void ConcavePolygonShape3D::_update_shape() {
|
||||
Dictionary d;
|
||||
d["faces"] = faces;
|
||||
d["backface_collision"] = backface_collision;
|
||||
PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d);
|
||||
|
||||
Shape3D::_update_shape();
|
||||
}
|
||||
|
||||
void ConcavePolygonShape3D::set_faces(const Vector<Vector3> &p_faces) {
|
||||
PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), p_faces);
|
||||
faces = p_faces;
|
||||
_update_shape();
|
||||
notify_change_to_owners();
|
||||
}
|
||||
|
||||
Vector<Vector3> ConcavePolygonShape3D::get_faces() const {
|
||||
return PhysicsServer3D::get_singleton()->shape_get_data(get_shape());
|
||||
return faces;
|
||||
}
|
||||
|
||||
void ConcavePolygonShape3D::set_backface_collision_enabled(bool p_enabled) {
|
||||
backface_collision = p_enabled;
|
||||
|
||||
if (!faces.is_empty()) {
|
||||
_update_shape();
|
||||
notify_change_to_owners();
|
||||
}
|
||||
}
|
||||
|
||||
bool ConcavePolygonShape3D::is_backface_collision_enabled() const {
|
||||
return backface_collision;
|
||||
}
|
||||
|
||||
void ConcavePolygonShape3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_faces", "faces"), &ConcavePolygonShape3D::set_faces);
|
||||
ClassDB::bind_method(D_METHOD("get_faces"), &ConcavePolygonShape3D::get_faces);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_backface_collision_enabled", "enabled"), &ConcavePolygonShape3D::set_backface_collision_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_backface_collision_enabled"), &ConcavePolygonShape3D::is_backface_collision_enabled);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "backface_collision"), "set_backface_collision_enabled", "is_backface_collision_enabled");
|
||||
}
|
||||
|
||||
ConcavePolygonShape3D::ConcavePolygonShape3D() :
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
class ConcavePolygonShape3D : public Shape3D {
|
||||
GDCLASS(ConcavePolygonShape3D, Shape3D);
|
||||
|
||||
Vector<Vector3> faces;
|
||||
bool backface_collision = false;
|
||||
|
||||
struct DrawEdge {
|
||||
Vector3 a;
|
||||
Vector3 b;
|
||||
|
@ -65,6 +68,9 @@ public:
|
|||
void set_faces(const Vector<Vector3> &p_faces);
|
||||
Vector<Vector3> get_faces() const;
|
||||
|
||||
void set_backface_collision_enabled(bool p_enabled);
|
||||
bool is_backface_collision_enabled() const;
|
||||
|
||||
virtual Vector<Vector3> get_debug_mesh_lines() const override;
|
||||
virtual real_t get_enclosing_radius() const override;
|
||||
|
||||
|
|
|
@ -626,7 +626,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) {
|
||||
_FORCE_INLINE_ bool test_axis(const Vector3 &p_axis, bool p_directional = false) {
|
||||
Vector3 axis = p_axis;
|
||||
|
||||
if (Math::abs(axis.x) < CMP_EPSILON &&
|
||||
|
@ -662,7 +662,12 @@ public:
|
|||
//use the smallest depth
|
||||
|
||||
if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0
|
||||
min_B = -min_B;
|
||||
if (p_directional) {
|
||||
min_B = max_B;
|
||||
axis = -axis;
|
||||
} else {
|
||||
min_B = -min_B;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_B < min_B) {
|
||||
|
@ -1006,23 +1011,31 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform &p_tran
|
|||
p_transform_b.xform(face_B->vertex[2]),
|
||||
};
|
||||
|
||||
if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
|
||||
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
|
||||
|
||||
if (!separator.test_axis(normal, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// edges and points of B
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Vector3 n1 = vertex[i] - p_transform_a.origin;
|
||||
if (n1.dot(normal) < 0.0) {
|
||||
n1 *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(n1.normalized())) {
|
||||
if (!separator.test_axis(n1.normalized(), !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 n2 = vertex[(i + 1) % 3] - vertex[i];
|
||||
|
||||
Vector3 axis = n1.cross(n2).cross(n2).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis)) {
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1467,15 +1480,20 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
|
|||
p_transform_b.xform(face_B->vertex[2]),
|
||||
};
|
||||
|
||||
if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
|
||||
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
|
||||
|
||||
if (!separator.test_axis(normal, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// faces of A
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Vector3 axis = p_transform_a.basis.get_axis(i).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis)) {
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1486,9 +1504,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
|
|||
Vector3 e = vertex[i] - vertex[(i + 1) % 3];
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
Vector3 axis = p_transform_a.basis.get_axis(j);
|
||||
Vector3 axis = e.cross(p_transform_a.basis.get_axis(j)).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(e.cross(axis).normalized())) {
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1508,8 +1529,11 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
|
|||
(cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z));
|
||||
|
||||
Vector3 axis_ab = support_a - vertex[v];
|
||||
if (axis_ab.dot(normal) < 0.0) {
|
||||
axis_ab *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis_ab.normalized())) {
|
||||
if (!separator.test_axis(axis_ab.normalized(), !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1519,7 +1543,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
|
|||
//a ->b
|
||||
Vector3 axis_a = p_transform_a.basis.get_axis(i);
|
||||
|
||||
if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) {
|
||||
Vector3 axis = axis_ab.cross(axis_a).cross(axis_a).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1544,7 +1573,12 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transfo
|
|||
|
||||
Vector3 n = (p2 - p1);
|
||||
|
||||
if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) {
|
||||
Vector3 axis = (point - p2).cross(n).cross(n).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1759,7 +1793,9 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra
|
|||
p_transform_b.xform(face_B->vertex[2]),
|
||||
};
|
||||
|
||||
if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
|
||||
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
|
||||
|
||||
if (!separator.test_axis(normal, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1770,13 +1806,22 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra
|
|||
for (int i = 0; i < 3; i++) {
|
||||
// edge-cylinder
|
||||
Vector3 edge_axis = vertex[i] - vertex[(i + 1) % 3];
|
||||
Vector3 axis = edge_axis.cross(capsule_axis).normalized();
|
||||
|
||||
if (!separator.test_axis(axis)) {
|
||||
Vector3 axis = edge_axis.cross(capsule_axis).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!separator.test_axis((p_transform_a.origin - vertex[i]).cross(capsule_axis).cross(capsule_axis).normalized())) {
|
||||
Vector3 dir_axis = (p_transform_a.origin - vertex[i]).cross(capsule_axis).cross(capsule_axis).normalized();
|
||||
if (dir_axis.dot(normal) < 0.0) {
|
||||
dir_axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(dir_axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1785,16 +1830,22 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_tra
|
|||
Vector3 sphere_pos = p_transform_a.origin + ((j == 0) ? capsule_axis : -capsule_axis);
|
||||
|
||||
Vector3 n1 = sphere_pos - vertex[i];
|
||||
if (n1.dot(normal) < 0.0) {
|
||||
n1 *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(n1.normalized())) {
|
||||
if (!separator.test_axis(n1.normalized(), !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 n2 = edge_axis;
|
||||
|
||||
axis = n1.cross(n2).cross(n2);
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis.normalized())) {
|
||||
if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1891,18 +1942,21 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr
|
|||
p_transform_b.xform(face_B->vertex[2]),
|
||||
};
|
||||
|
||||
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
|
||||
|
||||
// Face B normal.
|
||||
if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
|
||||
if (!separator.test_axis(normal, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 cyl_axis = p_transform_a.basis.get_axis(1).normalized();
|
||||
if (cyl_axis.dot(normal) < 0.0) {
|
||||
cyl_axis *= -1.0;
|
||||
}
|
||||
|
||||
// Cylinder end caps.
|
||||
{
|
||||
if (!separator.test_axis(cyl_axis)) {
|
||||
return;
|
||||
}
|
||||
if (!separator.test_axis(cyl_axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Edges of B, cylinder lateral surface.
|
||||
|
@ -1913,7 +1967,11 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis.normalized())) {
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1922,8 +1980,11 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr
|
|||
for (int i = 0; i < 3; i++) {
|
||||
const Vector3 &point = vertex[i];
|
||||
Vector3 axis = Plane(cyl_axis, 0).project(point).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis)) {
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1956,8 +2017,11 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_tr
|
|||
|
||||
// Axis is orthogonal both to tangent and edge direction.
|
||||
Vector3 axis = tangent.cross(edge_dir);
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis.normalized())) {
|
||||
if (!separator.test_axis(axis.normalized(), !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2097,7 +2161,9 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
|
|||
p_transform_b.xform(face_B->vertex[2]),
|
||||
};
|
||||
|
||||
if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) {
|
||||
Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized();
|
||||
|
||||
if (!separator.test_axis(normal, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2105,8 +2171,11 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
|
|||
for (int i = 0; i < face_count; i++) {
|
||||
//Vector3 axis = p_transform_a.xform( faces[i].plane ).normal;
|
||||
Vector3 axis = p_transform_a.basis.xform(faces[i].plane.normal).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis)) {
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2119,8 +2188,11 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
|
|||
Vector3 e2 = vertex[j] - vertex[(j + 1) % 3];
|
||||
|
||||
Vector3 axis = e1.cross(e2).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis)) {
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2132,7 +2204,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
|
|||
Vector3 va = p_transform_a.xform(vertices[i]);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (!separator.test_axis((va - vertex[j]).normalized())) {
|
||||
Vector3 axis = (va - vertex[j]).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2147,7 +2224,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
|
|||
for (int j = 0; j < 3; j++) {
|
||||
Vector3 e3 = vertex[j];
|
||||
|
||||
if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) {
|
||||
Vector3 axis = (e1 - e3).cross(n).cross(n).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2161,7 +2243,12 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform
|
|||
for (int j = 0; j < vertex_count; j++) {
|
||||
Vector3 e3 = p_transform_a.xform(vertices[j]);
|
||||
|
||||
if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) {
|
||||
Vector3 axis = (e1 - e3).cross(n).cross(n).normalized();
|
||||
if (axis.dot(normal) < 0.0) {
|
||||
axis *= -1.0;
|
||||
}
|
||||
|
||||
if (!separator.test_axis(axis, !face_B->backface_collision)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1134,7 +1134,7 @@ void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_
|
|||
Vector3 n = p_normal;
|
||||
|
||||
/** TEST FACE AS SUPPORT **/
|
||||
if (normal.dot(n) > _FACE_IS_VALID_SUPPORT_THRESHOLD) {
|
||||
if (Math::abs(normal.dot(n)) > _FACE_IS_VALID_SUPPORT_THRESHOLD) {
|
||||
r_amount = 3;
|
||||
r_type = FEATURE_FACE;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
@ -1187,7 +1187,11 @@ bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_e
|
|||
if (c) {
|
||||
r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal;
|
||||
if (r_normal.dot(p_end - p_begin) > 0) {
|
||||
r_normal = -r_normal;
|
||||
if (backface_collision) {
|
||||
r_normal = -r_normal;
|
||||
} else {
|
||||
c = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1285,30 +1289,24 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par
|
|||
}
|
||||
|
||||
if (bvh->face_index >= 0) {
|
||||
Vector3 res;
|
||||
Vector3 vertices[3] = {
|
||||
p_params->vertices[p_params->faces[bvh->face_index].indices[0]],
|
||||
p_params->vertices[p_params->faces[bvh->face_index].indices[1]],
|
||||
p_params->vertices[p_params->faces[bvh->face_index].indices[2]]
|
||||
};
|
||||
const Face *f = &p_params->faces[bvh->face_index];
|
||||
FaceShape3DSW *face = p_params->face;
|
||||
face->normal = f->normal;
|
||||
face->vertex[0] = p_params->vertices[f->indices[0]];
|
||||
face->vertex[1] = p_params->vertices[f->indices[1]];
|
||||
face->vertex[2] = p_params->vertices[f->indices[2]];
|
||||
|
||||
if (Geometry3D::segment_intersects_triangle(
|
||||
p_params->from,
|
||||
p_params->to,
|
||||
vertices[0],
|
||||
vertices[1],
|
||||
vertices[2],
|
||||
&res)) {
|
||||
Vector3 res;
|
||||
Vector3 normal;
|
||||
if (face->intersect_segment(p_params->from, p_params->to, res, normal)) {
|
||||
real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from);
|
||||
//TODO, seems segmen/triangle intersection is broken :(
|
||||
if (d > 0 && d < p_params->min_d) {
|
||||
if ((d > 0) && (d < p_params->min_d)) {
|
||||
p_params->min_d = d;
|
||||
p_params->result = res;
|
||||
p_params->normal = Plane(vertices[0], vertices[1], vertices[2]).normal;
|
||||
p_params->normal = normal;
|
||||
p_params->collisions++;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (bvh->left >= 0) {
|
||||
_cull_segment(bvh->left, p_params);
|
||||
|
@ -1329,17 +1327,20 @@ bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Ve
|
|||
const Vector3 *vr = vertices.ptr();
|
||||
const BVH *br = bvh.ptr();
|
||||
|
||||
FaceShape3DSW face;
|
||||
face.backface_collision = backface_collision;
|
||||
|
||||
_SegmentCullParams params;
|
||||
params.from = p_begin;
|
||||
params.to = p_end;
|
||||
params.collisions = 0;
|
||||
params.dir = (p_end - p_begin).normalized();
|
||||
|
||||
params.faces = fr;
|
||||
params.vertices = vr;
|
||||
params.bvh = br;
|
||||
|
||||
params.min_d = 1e20;
|
||||
params.face = &face;
|
||||
|
||||
// cull
|
||||
_cull_segment(0, ¶ms);
|
||||
|
||||
|
@ -1401,6 +1402,7 @@ void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, Callback p_callback
|
|||
const BVH *br = bvh.ptr();
|
||||
|
||||
FaceShape3DSW face; // use this to send in the callback
|
||||
face.backface_collision = backface_collision;
|
||||
|
||||
_CullParams params;
|
||||
params.aabb = local_aabb;
|
||||
|
@ -1532,7 +1534,7 @@ void ConcavePolygonShape3DSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_ar
|
|||
memdelete(p_bvh_tree);
|
||||
}
|
||||
|
||||
void ConcavePolygonShape3DSW::_setup(Vector<Vector3> p_faces) {
|
||||
void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_backface_collision) {
|
||||
int src_face_count = p_faces.size();
|
||||
if (src_face_count == 0) {
|
||||
configure(AABB());
|
||||
|
@ -1587,15 +1589,24 @@ void ConcavePolygonShape3DSW::_setup(Vector<Vector3> p_faces) {
|
|||
int idx = 0;
|
||||
_fill_bvh(bvh_tree, bvh_arrayw2, idx);
|
||||
|
||||
backface_collision = p_backface_collision;
|
||||
|
||||
configure(_aabb); // this type of shape has no margin
|
||||
}
|
||||
|
||||
void ConcavePolygonShape3DSW::set_data(const Variant &p_data) {
|
||||
_setup(p_data);
|
||||
Dictionary d = p_data;
|
||||
ERR_FAIL_COND(!d.has("faces"));
|
||||
|
||||
_setup(d["faces"], d["backface_collision"]);
|
||||
}
|
||||
|
||||
Variant ConcavePolygonShape3DSW::get_data() const {
|
||||
return get_faces();
|
||||
Dictionary d;
|
||||
d["faces"] = get_faces();
|
||||
d["backface_collision"] = backface_collision;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
ConcavePolygonShape3DSW::ConcavePolygonShape3DSW() {
|
||||
|
|
|
@ -334,34 +334,37 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW {
|
|||
|
||||
struct _CullParams {
|
||||
AABB aabb;
|
||||
Callback callback;
|
||||
void *userdata;
|
||||
const Face *faces;
|
||||
const Vector3 *vertices;
|
||||
const BVH *bvh;
|
||||
FaceShape3DSW *face;
|
||||
Callback callback = nullptr;
|
||||
void *userdata = nullptr;
|
||||
const Face *faces = nullptr;
|
||||
const Vector3 *vertices = nullptr;
|
||||
const BVH *bvh = nullptr;
|
||||
FaceShape3DSW *face = nullptr;
|
||||
};
|
||||
|
||||
struct _SegmentCullParams {
|
||||
Vector3 from;
|
||||
Vector3 to;
|
||||
const Face *faces;
|
||||
const Vector3 *vertices;
|
||||
const BVH *bvh;
|
||||
Vector3 dir;
|
||||
const Face *faces = nullptr;
|
||||
const Vector3 *vertices = nullptr;
|
||||
const BVH *bvh = nullptr;
|
||||
FaceShape3DSW *face = nullptr;
|
||||
|
||||
Vector3 result;
|
||||
Vector3 normal;
|
||||
real_t min_d;
|
||||
int collisions;
|
||||
real_t min_d = 1e20;
|
||||
int collisions = 0;
|
||||
};
|
||||
|
||||
bool backface_collision = false;
|
||||
|
||||
void _cull_segment(int p_idx, _SegmentCullParams *p_params) const;
|
||||
void _cull(int p_idx, _CullParams *p_params) const;
|
||||
|
||||
void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx);
|
||||
|
||||
void _setup(Vector<Vector3> p_faces);
|
||||
void _setup(const Vector<Vector3> &p_faces, bool p_backface_collision);
|
||||
|
||||
public:
|
||||
Vector<Vector3> get_faces() const;
|
||||
|
@ -424,6 +427,7 @@ public:
|
|||
struct FaceShape3DSW : public Shape3DSW {
|
||||
Vector3 normal; //cache
|
||||
Vector3 vertex[3];
|
||||
bool backface_collision = false;
|
||||
|
||||
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; }
|
||||
|
||||
|
|
|
@ -187,8 +187,10 @@ protected:
|
|||
RenderingServer *vs = RenderingServer::get_singleton();
|
||||
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
|
||||
RID trimesh_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON);
|
||||
ps->shape_set_data(trimesh_shape, p_faces);
|
||||
p_faces = ps->shape_get_data(trimesh_shape); // optimized one
|
||||
Dictionary trimesh_params;
|
||||
trimesh_params["faces"] = p_faces;
|
||||
trimesh_params["backface_collision"] = false;
|
||||
ps->shape_set_data(trimesh_shape, trimesh_params);
|
||||
Vector<Vector3> normals; // for drawing
|
||||
for (int i = 0; i < p_faces.size() / 3; i++) {
|
||||
Plane p(p_faces[i * 3 + 0], p_faces[i * 3 + 1], p_faces[i * 3 + 2]);
|
||||
|
|
Loading…
Reference in a new issue