initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
/**************************************************************************/
/* jolt_box_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_box_shape_3d.h"
#include "../jolt_project_settings.h"
#include "../misc/jolt_type_conversions.h"
#include "Jolt/Physics/Collision/Shape/BoxShape.h"
JPH::ShapeRefC JoltBoxShape3D::_build() const {
const float min_half_extent = (float)half_extents[half_extents.min_axis_index()];
const float actual_margin = MIN(margin, min_half_extent * JoltProjectSettings::collision_margin_fraction);
const JPH::BoxShapeSettings shape_settings(to_jolt(half_extents), actual_margin);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics box shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return shape_result.Get();
}
Variant JoltBoxShape3D::get_data() const {
return half_extents;
}
void JoltBoxShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::VECTOR3);
const Vector3 new_half_extents = p_data;
if (unlikely(new_half_extents == half_extents)) {
return;
}
half_extents = new_half_extents;
destroy();
}
void JoltBoxShape3D::set_margin(float p_margin) {
if (unlikely(margin == p_margin)) {
return;
}
margin = p_margin;
destroy();
}
String JoltBoxShape3D::to_string() const {
return vformat("{half_extents=%v margin=%f}", half_extents, margin);
}
AABB JoltBoxShape3D::get_aabb() const {
return AABB(-half_extents, half_extents * 2.0f);
}

View File

@@ -0,0 +1,54 @@
/**************************************************************************/
/* jolt_box_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltBoxShape3D final : public JoltShape3D {
Vector3 half_extents;
float margin = 0.04f;
virtual JPH::ShapeRefC _build() const override;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_BOX; }
virtual bool is_convex() const override { return true; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return margin; }
virtual void set_margin(float p_margin) override;
virtual AABB get_aabb() const override;
String to_string() const;
};

View File

@@ -0,0 +1,90 @@
/**************************************************************************/
/* jolt_capsule_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_capsule_shape_3d.h"
#include "../misc/jolt_type_conversions.h"
#include "Jolt/Physics/Collision/Shape/CapsuleShape.h"
JPH::ShapeRefC JoltCapsuleShape3D::_build() const {
ERR_FAIL_COND_V_MSG(radius <= 0.0f, nullptr, vformat("Failed to build Jolt Physics capsule shape with %s. Its radius must be greater than 0. This shape belongs to %s.", to_string(), _owners_to_string()));
ERR_FAIL_COND_V_MSG(height <= 0.0f, nullptr, vformat("Failed to build Jolt Physics capsule shape with %s. Its height must be greater than 0. This shape belongs to %s.", to_string(), _owners_to_string()));
ERR_FAIL_COND_V_MSG(height < radius * 2.0f, nullptr, vformat("Failed to build Jolt Physics capsule shape with %s. Its height must be at least double that of its radius. This shape belongs to %s.", to_string(), _owners_to_string()));
const float half_height = height / 2.0f;
const float cylinder_height = half_height - radius;
const JPH::CapsuleShapeSettings shape_settings(cylinder_height, radius);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics capsule shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return shape_result.Get();
}
Variant JoltCapsuleShape3D::get_data() const {
Dictionary data;
data["height"] = height;
data["radius"] = radius;
return data;
}
void JoltCapsuleShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY);
const Dictionary data = p_data;
const Variant maybe_height = data.get("height", Variant());
ERR_FAIL_COND(maybe_height.get_type() != Variant::FLOAT);
const Variant maybe_radius = data.get("radius", Variant());
ERR_FAIL_COND(maybe_radius.get_type() != Variant::FLOAT);
const float new_height = maybe_height;
const float new_radius = maybe_radius;
if (unlikely(new_height == height && new_radius == radius)) {
return;
}
height = new_height;
radius = new_radius;
destroy();
}
AABB JoltCapsuleShape3D::get_aabb() const {
const Vector3 half_extents(radius, height / 2.0f, radius);
return AABB(-half_extents, half_extents * 2.0f);
}
String JoltCapsuleShape3D::to_string() const {
return vformat("{height=%f radius=%f}", height, radius);
}

View File

@@ -0,0 +1,54 @@
/**************************************************************************/
/* jolt_capsule_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltCapsuleShape3D final : public JoltShape3D {
float height = 0.0f;
float radius = 0.0f;
virtual JPH::ShapeRefC _build() const override;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_CAPSULE; }
virtual bool is_convex() const override { return true; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return 0.0f; }
virtual void set_margin(float p_margin) override {}
virtual AABB get_aabb() const override;
String to_string() const;
};

View File

@@ -0,0 +1,125 @@
/**************************************************************************/
/* jolt_concave_polygon_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_concave_polygon_shape_3d.h"
#include "../jolt_project_settings.h"
#include "../misc/jolt_type_conversions.h"
#include "Jolt/Physics/Collision/Shape/MeshShape.h"
JPH::ShapeRefC JoltConcavePolygonShape3D::_build() const {
const int vertex_count = (int)faces.size();
const int face_count = vertex_count / 3;
const int excess_vertex_count = vertex_count % 3;
if (unlikely(vertex_count == 0)) {
return nullptr;
}
ERR_FAIL_COND_V_MSG(vertex_count < 3, nullptr, vformat("Failed to build Jolt Physics concave polygon shape with %s. It must have a vertex count of at least 3. This shape belongs to %s.", to_string(), _owners_to_string()));
ERR_FAIL_COND_V_MSG(excess_vertex_count != 0, nullptr, vformat("Failed to build Jolt Physics concave polygon shape with %s. It must have a vertex count that is divisible by 3. This shape belongs to %s.", to_string(), _owners_to_string()));
JPH::TriangleList jolt_faces;
jolt_faces.reserve((size_t)face_count);
const Vector3 *faces_begin = &faces[0];
const Vector3 *faces_end = faces_begin + vertex_count;
JPH::uint32 triangle_index = 0;
for (const Vector3 *vertex = faces_begin; vertex != faces_end; vertex += 3) {
const Vector3 *v0 = vertex + 0;
const Vector3 *v1 = vertex + 1;
const Vector3 *v2 = vertex + 2;
// Jolt uses a different winding order, so we swizzle the vertices to account for that.
jolt_faces.emplace_back(
JPH::Float3((float)v2->x, (float)v2->y, (float)v2->z),
JPH::Float3((float)v1->x, (float)v1->y, (float)v1->z),
JPH::Float3((float)v0->x, (float)v0->y, (float)v0->z),
0,
triangle_index++);
}
JPH::MeshShapeSettings shape_settings(jolt_faces);
shape_settings.mActiveEdgeCosThresholdAngle = JoltProjectSettings::active_edge_threshold_cos;
shape_settings.mPerTriangleUserData = JoltProjectSettings::enable_ray_cast_face_index;
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics concave polygon shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return JoltShape3D::with_double_sided(shape_result.Get(), back_face_collision);
}
AABB JoltConcavePolygonShape3D::_calculate_aabb() const {
AABB result;
for (int i = 0; i < faces.size(); ++i) {
const Vector3 &vertex = faces[i];
if (i == 0) {
result.position = vertex;
} else {
result.expand_to(vertex);
}
}
return result;
}
Variant JoltConcavePolygonShape3D::get_data() const {
Dictionary data;
data["faces"] = faces;
data["backface_collision"] = back_face_collision;
return data;
}
void JoltConcavePolygonShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY);
const Dictionary data = p_data;
const Variant maybe_faces = data.get("faces", Variant());
ERR_FAIL_COND(maybe_faces.get_type() != Variant::PACKED_VECTOR3_ARRAY);
const Variant maybe_back_face_collision = data.get("backface_collision", Variant());
ERR_FAIL_COND(maybe_back_face_collision.get_type() != Variant::BOOL);
faces = maybe_faces;
back_face_collision = maybe_back_face_collision;
aabb = _calculate_aabb();
destroy();
}
String JoltConcavePolygonShape3D::to_string() const {
return vformat("{vertex_count=%d}", faces.size());
}

View File

@@ -0,0 +1,57 @@
/**************************************************************************/
/* jolt_concave_polygon_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltConcavePolygonShape3D final : public JoltShape3D {
AABB aabb;
PackedVector3Array faces;
bool back_face_collision = false;
virtual JPH::ShapeRefC _build() const override;
AABB _calculate_aabb() const;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_CONCAVE_POLYGON; }
virtual bool is_convex() const override { return false; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return 0.0f; }
virtual void set_margin(float p_margin) override {}
virtual AABB get_aabb() const override { return aabb; }
String to_string() const;
};

View File

@@ -0,0 +1,107 @@
/**************************************************************************/
/* jolt_convex_polygon_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_convex_polygon_shape_3d.h"
#include "../jolt_project_settings.h"
#include "../misc/jolt_type_conversions.h"
#include "Jolt/Physics/Collision/Shape/ConvexHullShape.h"
JPH::ShapeRefC JoltConvexPolygonShape3D::_build() const {
const int vertex_count = (int)vertices.size();
if (unlikely(vertex_count == 0)) {
return nullptr;
}
ERR_FAIL_COND_V_MSG(vertex_count < 3, nullptr, vformat("Failed to build Jolt Physics convex polygon shape with %s. It must have a vertex count of at least 3. This shape belongs to %s.", to_string(), _owners_to_string()));
JPH::Array<JPH::Vec3> jolt_vertices;
jolt_vertices.reserve((size_t)vertex_count);
const Vector3 *vertices_begin = &vertices[0];
const Vector3 *vertices_end = vertices_begin + vertex_count;
for (const Vector3 *vertex = vertices_begin; vertex != vertices_end; ++vertex) {
jolt_vertices.emplace_back((float)vertex->x, (float)vertex->y, (float)vertex->z);
}
const float min_half_extent = _calculate_aabb().get_shortest_axis_size() * 0.5f;
const float actual_margin = MIN(margin, min_half_extent * JoltProjectSettings::collision_margin_fraction);
const JPH::ConvexHullShapeSettings shape_settings(jolt_vertices, actual_margin);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics convex polygon shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return shape_result.Get();
}
AABB JoltConvexPolygonShape3D::_calculate_aabb() const {
AABB result;
for (int i = 0; i < vertices.size(); ++i) {
if (i == 0) {
result.position = vertices[i];
} else {
result.expand_to(vertices[i]);
}
}
return result;
}
Variant JoltConvexPolygonShape3D::get_data() const {
return vertices;
}
void JoltConvexPolygonShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR3_ARRAY);
vertices = p_data;
aabb = _calculate_aabb();
destroy();
}
void JoltConvexPolygonShape3D::set_margin(float p_margin) {
if (unlikely(margin == p_margin)) {
return;
}
margin = p_margin;
destroy();
}
String JoltConvexPolygonShape3D::to_string() const {
return vformat("{vertex_count=%d margin=%f}", vertices.size(), margin);
}

View File

@@ -0,0 +1,57 @@
/**************************************************************************/
/* jolt_convex_polygon_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltConvexPolygonShape3D final : public JoltShape3D {
AABB aabb;
PackedVector3Array vertices;
float margin = 0.04f;
virtual JPH::ShapeRefC _build() const override;
AABB _calculate_aabb() const;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_CONVEX_POLYGON; }
virtual bool is_convex() const override { return true; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return margin; }
virtual void set_margin(float p_margin) override;
virtual AABB get_aabb() const override { return aabb; }
String to_string() const;
};

View File

@@ -0,0 +1,92 @@
/**************************************************************************/
/* jolt_custom_decorated_shape.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_custom_shape_type.h"
#include "Jolt/Jolt.h"
#include "Jolt/Physics/Collision/Shape/DecoratedShape.h"
#include "Jolt/Physics/Collision/TransformedShape.h"
class JoltCustomDecoratedShapeSettings : public JPH::DecoratedShapeSettings {
public:
using JPH::DecoratedShapeSettings::DecoratedShapeSettings;
};
class JoltCustomDecoratedShape : public JPH::DecoratedShape {
public:
using JPH::DecoratedShape::DecoratedShape;
virtual JPH::AABox GetLocalBounds() const override { return mInnerShape->GetLocalBounds(); }
virtual JPH::AABox GetWorldSpaceBounds(JPH::Mat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale) const override { return mInnerShape->GetWorldSpaceBounds(p_center_of_mass_transform, p_scale); }
virtual float GetInnerRadius() const override { return mInnerShape->GetInnerRadius(); }
virtual JPH::MassProperties GetMassProperties() const override { return mInnerShape->GetMassProperties(); }
virtual JPH::Vec3 GetSurfaceNormal(const JPH::SubShapeID &p_sub_shape_id, JPH::Vec3Arg p_local_surface_position) const override { return mInnerShape->GetSurfaceNormal(p_sub_shape_id, p_local_surface_position); }
virtual JPH::uint64 GetSubShapeUserData(const JPH::SubShapeID &p_sub_shape_id) const override { return mInnerShape->GetSubShapeUserData(p_sub_shape_id); }
virtual JPH::TransformedShape GetSubShapeTransformedShape(const JPH::SubShapeID &p_sub_shape_id, JPH::Vec3Arg p_position_com, JPH::QuatArg p_rotation, JPH::Vec3Arg p_scale, JPH::SubShapeID &p_remainder) const override { return mInnerShape->GetSubShapeTransformedShape(p_sub_shape_id, p_position_com, p_rotation, p_scale, p_remainder); }
virtual void GetSubmergedVolume(JPH::Mat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, const JPH::Plane &p_surface, float &p_total_volume, float &p_submerged_volume, JPH::Vec3 &p_center_of_buoyancy JPH_IF_DEBUG_RENDERER(, JPH::RVec3Arg p_base_offset)) const override { mInnerShape->GetSubmergedVolume(p_center_of_mass_transform, p_scale, p_surface, p_total_volume, p_submerged_volume, p_center_of_buoyancy JPH_IF_DEBUG_RENDERER(, p_base_offset)); }
#ifdef JPH_DEBUG_RENDERER
virtual void Draw(JPH::DebugRenderer *p_renderer, JPH::RMat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, JPH::ColorArg p_color, bool p_use_material_colors, bool p_draw_wireframe) const override { mInnerShape->Draw(p_renderer, p_center_of_mass_transform, p_scale, p_color, p_use_material_colors, p_draw_wireframe); }
virtual void DrawGetSupportFunction(JPH::DebugRenderer *p_renderer, JPH::RMat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, JPH::ColorArg p_color, bool p_draw_support_direction) const override { mInnerShape->DrawGetSupportFunction(p_renderer, p_center_of_mass_transform, p_scale, p_color, p_draw_support_direction); }
virtual void DrawGetSupportingFace(JPH::DebugRenderer *p_renderer, JPH::RMat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale) const override { mInnerShape->DrawGetSupportingFace(p_renderer, p_center_of_mass_transform, p_scale); }
#endif
virtual bool CastRay(const JPH::RayCast &p_ray, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::RayCastResult &p_hit) const override { return mInnerShape->CastRay(p_ray, p_sub_shape_id_creator, p_hit); }
virtual void CastRay(const JPH::RayCast &p_ray, const JPH::RayCastSettings &p_ray_cast_settings, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::CastRayCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override { return mInnerShape->CastRay(p_ray, p_ray_cast_settings, p_sub_shape_id_creator, p_collector, p_shape_filter); }
virtual void CollidePoint(JPH::Vec3Arg p_point, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::CollidePointCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override { mInnerShape->CollidePoint(p_point, p_sub_shape_id_creator, p_collector, p_shape_filter); }
virtual void CollideSoftBodyVertices(JPH::Mat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, const JPH::CollideSoftBodyVertexIterator &p_vertices, JPH::uint p_num_vertices, int p_colliding_shape_index) const override { mInnerShape->CollideSoftBodyVertices(p_center_of_mass_transform, p_scale, p_vertices, p_num_vertices, p_colliding_shape_index); }
virtual void CollectTransformedShapes(const JPH::AABox &p_box, JPH::Vec3Arg p_position_com, JPH::QuatArg p_rotation, JPH::Vec3Arg p_scale, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::TransformedShapeCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override { mInnerShape->CollectTransformedShapes(p_box, p_position_com, p_rotation, p_scale, p_sub_shape_id_creator, p_collector, p_shape_filter); }
virtual void TransformShape(JPH::Mat44Arg p_center_of_mass_transform, JPH::TransformedShapeCollector &p_collector) const override { mInnerShape->TransformShape(p_center_of_mass_transform, p_collector); }
virtual void GetTrianglesStart(JPH::Shape::GetTrianglesContext &p_context, const JPH::AABox &p_box, JPH::Vec3Arg p_position_com, JPH::QuatArg p_rotation, JPH::Vec3Arg p_scale) const override { mInnerShape->GetTrianglesStart(p_context, p_box, p_position_com, p_rotation, p_scale); }
virtual int GetTrianglesNext(JPH::Shape::GetTrianglesContext &p_context, int p_max_triangles_requested, JPH::Float3 *p_triangle_vertices, const JPH::PhysicsMaterial **p_materials = nullptr) const override { return mInnerShape->GetTrianglesNext(p_context, p_max_triangles_requested, p_triangle_vertices, p_materials); }
virtual JPH::Shape::Stats GetStats() const override { return JPH::Shape::Stats(sizeof(*this), 0); }
virtual float GetVolume() const override { return mInnerShape->GetVolume(); }
};

View File

@@ -0,0 +1,118 @@
/**************************************************************************/
/* jolt_custom_double_sided_shape.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_custom_double_sided_shape.h"
#include "../jolt_project_settings.h"
#include "core/error/error_macros.h"
#include "Jolt/Physics/Collision/CollisionDispatch.h"
#include "Jolt/Physics/Collision/RayCast.h"
namespace {
JPH::Shape *construct_double_sided() {
return new JoltCustomDoubleSidedShape();
}
void collide_double_sided_vs_shape(const JPH::Shape *p_shape1, const JPH::Shape *p_shape2, JPH::Vec3Arg p_scale1, JPH::Vec3Arg p_scale2, JPH::Mat44Arg p_center_of_mass_transform1, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, const JPH::CollideShapeSettings &p_collide_shape_settings, JPH::CollideShapeCollector &p_collector, const JPH::ShapeFilter &p_shape_filter) {
ERR_FAIL_COND(p_shape1->GetSubType() != JoltCustomShapeSubType::DOUBLE_SIDED);
const JoltCustomDoubleSidedShape *shape1 = static_cast<const JoltCustomDoubleSidedShape *>(p_shape1);
JPH::CollideShapeSettings new_collide_shape_settings = p_collide_shape_settings;
if (shape1->should_collide_with_back_faces()) {
new_collide_shape_settings.mBackFaceMode = JPH::EBackFaceMode::CollideWithBackFaces;
}
JPH::CollisionDispatch::sCollideShapeVsShape(shape1->GetInnerShape(), p_shape2, p_scale1, p_scale2, p_center_of_mass_transform1, p_center_of_mass_transform2, p_sub_shape_id_creator1, p_sub_shape_id_creator2, new_collide_shape_settings, p_collector, p_shape_filter);
}
void collide_shape_vs_double_sided(const JPH::Shape *p_shape1, const JPH::Shape *p_shape2, JPH::Vec3Arg p_scale1, JPH::Vec3Arg p_scale2, JPH::Mat44Arg p_center_of_mass_transform1, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, const JPH::CollideShapeSettings &p_collide_shape_settings, JPH::CollideShapeCollector &p_collector, const JPH::ShapeFilter &p_shape_filter) {
ERR_FAIL_COND(p_shape2->GetSubType() != JoltCustomShapeSubType::DOUBLE_SIDED);
const JoltCustomDoubleSidedShape *shape2 = static_cast<const JoltCustomDoubleSidedShape *>(p_shape2);
JPH::CollideShapeSettings new_collide_shape_settings = p_collide_shape_settings;
if (shape2->should_collide_with_back_faces()) {
new_collide_shape_settings.mBackFaceMode = JPH::EBackFaceMode::CollideWithBackFaces;
}
JPH::CollisionDispatch::sCollideShapeVsShape(p_shape1, shape2->GetInnerShape(), p_scale1, p_scale2, p_center_of_mass_transform1, p_center_of_mass_transform2, p_sub_shape_id_creator1, p_sub_shape_id_creator2, new_collide_shape_settings, p_collector, p_shape_filter);
}
void cast_shape_vs_double_sided(const JPH::ShapeCast &p_shape_cast, const JPH::ShapeCastSettings &p_shape_cast_settings, const JPH::Shape *p_shape, JPH::Vec3Arg p_scale, const JPH::ShapeFilter &p_shape_filter, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, JPH::CastShapeCollector &p_collector) {
ERR_FAIL_COND(p_shape->GetSubType() != JoltCustomShapeSubType::DOUBLE_SIDED);
const JoltCustomDoubleSidedShape *shape = static_cast<const JoltCustomDoubleSidedShape *>(p_shape);
JPH::ShapeCastSettings new_shape_cast_settings = p_shape_cast_settings;
if (shape->should_collide_with_back_faces()) {
new_shape_cast_settings.mBackFaceModeTriangles = JPH::EBackFaceMode::CollideWithBackFaces;
}
JPH::CollisionDispatch::sCastShapeVsShapeLocalSpace(p_shape_cast, new_shape_cast_settings, shape->GetInnerShape(), p_scale, p_shape_filter, p_center_of_mass_transform2, p_sub_shape_id_creator1, p_sub_shape_id_creator2, p_collector);
}
} // namespace
JPH::ShapeSettings::ShapeResult JoltCustomDoubleSidedShapeSettings::Create() const {
if (mCachedResult.IsEmpty()) {
new JoltCustomDoubleSidedShape(*this, mCachedResult);
}
return mCachedResult;
}
void JoltCustomDoubleSidedShape::register_type() {
JPH::ShapeFunctions &shape_functions = JPH::ShapeFunctions::sGet(JoltCustomShapeSubType::DOUBLE_SIDED);
shape_functions.mConstruct = construct_double_sided;
shape_functions.mColor = JPH::Color::sPurple;
for (const JPH::EShapeSubType sub_type : JPH::sAllSubShapeTypes) {
JPH::CollisionDispatch::sRegisterCollideShape(JoltCustomShapeSubType::DOUBLE_SIDED, sub_type, collide_double_sided_vs_shape);
JPH::CollisionDispatch::sRegisterCollideShape(sub_type, JoltCustomShapeSubType::DOUBLE_SIDED, collide_shape_vs_double_sided);
}
for (const JPH::EShapeSubType sub_type : JPH::sConvexSubShapeTypes) {
JPH::CollisionDispatch::sRegisterCastShape(sub_type, JoltCustomShapeSubType::DOUBLE_SIDED, cast_shape_vs_double_sided);
}
}
void JoltCustomDoubleSidedShape::CastRay(const JPH::RayCast &p_ray, const JPH::RayCastSettings &p_ray_cast_settings, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::CastRayCollector &p_collector, const JPH::ShapeFilter &p_shape_filter) const {
JPH::RayCastSettings new_ray_cast_settings = p_ray_cast_settings;
if (!should_collide_with_back_faces()) {
new_ray_cast_settings.SetBackFaceMode(JPH::EBackFaceMode::IgnoreBackFaces);
}
return mInnerShape->CastRay(p_ray, new_ray_cast_settings, p_sub_shape_id_creator, p_collector, p_shape_filter);
}

View File

@@ -0,0 +1,73 @@
/**************************************************************************/
/* jolt_custom_double_sided_shape.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_custom_decorated_shape.h"
#include "jolt_custom_shape_type.h"
class JoltCustomDoubleSidedShapeSettings final : public JoltCustomDecoratedShapeSettings {
public:
bool back_face_collision = false;
JoltCustomDoubleSidedShapeSettings() = default;
JoltCustomDoubleSidedShapeSettings(const ShapeSettings *p_inner_settings, bool p_back_face_collision) :
JoltCustomDecoratedShapeSettings(p_inner_settings), back_face_collision(p_back_face_collision) {}
JoltCustomDoubleSidedShapeSettings(const JPH::Shape *p_inner_shape, bool p_back_face_collision) :
JoltCustomDecoratedShapeSettings(p_inner_shape), back_face_collision(p_back_face_collision) {}
virtual JPH::Shape::ShapeResult Create() const override;
};
class JoltCustomDoubleSidedShape final : public JoltCustomDecoratedShape {
bool back_face_collision = false;
public:
static void register_type();
JoltCustomDoubleSidedShape() :
JoltCustomDecoratedShape(JoltCustomShapeSubType::DOUBLE_SIDED) {}
JoltCustomDoubleSidedShape(const JoltCustomDoubleSidedShapeSettings &p_settings, JPH::Shape::ShapeResult &p_result) :
JoltCustomDecoratedShape(JoltCustomShapeSubType::DOUBLE_SIDED, p_settings, p_result), back_face_collision(p_settings.back_face_collision) {
if (!p_result.HasError()) {
p_result.Set(this);
}
}
JoltCustomDoubleSidedShape(const JPH::Shape *p_inner_shape, bool p_back_face_collision) :
JoltCustomDecoratedShape(JoltCustomShapeSubType::DOUBLE_SIDED, p_inner_shape), back_face_collision(p_back_face_collision) {}
virtual void CastRay(const JPH::RayCast &p_ray, const JPH::RayCastSettings &p_ray_cast_settings, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::CastRayCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override;
bool should_collide_with_back_faces() const { return back_face_collision; }
};

View File

@@ -0,0 +1,78 @@
/**************************************************************************/
/* jolt_custom_motion_shape.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_custom_motion_shape.h"
namespace {
class JoltMotionConvexSupport final : public JPH::ConvexShape::Support {
public:
JoltMotionConvexSupport(JPH::Vec3Arg p_motion, const JPH::ConvexShape::Support *p_inner_support) :
motion(p_motion),
inner_support(p_inner_support) {}
virtual JPH::Vec3 GetSupport(JPH::Vec3Arg p_direction) const override {
JPH::Vec3 support = inner_support->GetSupport(p_direction);
if (p_direction.Dot(motion) > 0) {
support += motion;
}
return support;
}
virtual float GetConvexRadius() const override { return inner_support->GetConvexRadius(); }
private:
JPH::Vec3 motion = JPH::Vec3::sZero();
const JPH::ConvexShape::Support *inner_support = nullptr;
};
} // namespace
JPH::AABox JoltCustomMotionShape::GetLocalBounds() const {
JPH::AABox aabb = inner_shape.GetLocalBounds();
JPH::AABox aabb_translated = aabb;
aabb_translated.Translate(motion);
aabb.Encapsulate(aabb_translated);
return aabb;
}
void JoltCustomMotionShape::GetSupportingFace(const JPH::SubShapeID &p_sub_shape_id, JPH::Vec3Arg p_direction, JPH::Vec3Arg p_scale, JPH::Mat44Arg p_center_of_mass_transform, JPH::Shape::SupportingFace &p_vertices) const {
// This is technically called when using the enhanced internal edge removal, but `JPH::InternalEdgeRemovingCollector` will
// only ever use the faces of the second shape in the collision pair, and this shape will always be the first in the pair, so
// we can safely skip this.
}
const JPH::ConvexShape::Support *JoltCustomMotionShape::GetSupportFunction(JPH::ConvexShape::ESupportMode p_mode, JPH::ConvexShape::SupportBuffer &p_buffer, JPH::Vec3Arg p_scale) const {
return new (&p_buffer) JoltMotionConvexSupport(motion, inner_shape.GetSupportFunction(p_mode, inner_support_buffer, p_scale));
}

View File

@@ -0,0 +1,114 @@
/**************************************************************************/
/* jolt_custom_motion_shape.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_custom_shape_type.h"
#include "core/error/error_macros.h"
#include "Jolt/Jolt.h"
#include "Jolt/Physics/Collision/Shape/ConvexShape.h"
#include "Jolt/Physics/Collision/TransformedShape.h"
class JoltCustomMotionShape final : public JPH::ConvexShape {
mutable JPH::ConvexShape::SupportBuffer inner_support_buffer;
JPH::Vec3 motion = JPH::Vec3::sZero();
const JPH::ConvexShape &inner_shape;
public:
explicit JoltCustomMotionShape(const JPH::ConvexShape &p_shape) :
JPH::ConvexShape(JoltCustomShapeSubType::MOTION), inner_shape(p_shape) {}
virtual bool MustBeStatic() const override { return false; }
virtual JPH::Vec3 GetCenterOfMass() const override { ERR_FAIL_V_MSG(JPH::Vec3::sZero(), "Not implemented."); }
virtual JPH::AABox GetLocalBounds() const override;
virtual JPH::uint GetSubShapeIDBitsRecursive() const override { ERR_FAIL_V_MSG(0, "Not implemented."); }
virtual JPH::AABox GetWorldSpaceBounds(JPH::Mat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale) const override { ERR_FAIL_V_MSG(JPH::AABox(), "Not implemented."); }
virtual float GetInnerRadius() const override { ERR_FAIL_V_MSG(0.0f, "Not implemented."); }
virtual JPH::MassProperties GetMassProperties() const override { ERR_FAIL_V_MSG(JPH::MassProperties(), "Not implemented."); }
virtual const JPH::PhysicsMaterial *GetMaterial(const JPH::SubShapeID &p_sub_shape_id) const override { ERR_FAIL_V_MSG(nullptr, "Not implemented."); }
virtual JPH::Vec3 GetSurfaceNormal(const JPH::SubShapeID &p_sub_shape_id, JPH::Vec3Arg p_local_surface_position) const override { ERR_FAIL_V_MSG(JPH::Vec3::sZero(), "Not implemented."); }
virtual void GetSupportingFace(const JPH::SubShapeID &p_sub_shape_id, JPH::Vec3Arg p_direction, JPH::Vec3Arg p_scale, JPH::Mat44Arg p_center_of_mass_transform, JPH::Shape::SupportingFace &p_vertices) const override;
virtual JPH::uint64 GetSubShapeUserData(const JPH::SubShapeID &p_sub_shape_id) const override { ERR_FAIL_V_MSG(0, "Not implemented."); }
virtual JPH::TransformedShape GetSubShapeTransformedShape(const JPH::SubShapeID &p_sub_shape_id, JPH::Vec3Arg p_position_com, JPH::QuatArg p_rotation, JPH::Vec3Arg p_scale, JPH::SubShapeID &p_remainder) const override { ERR_FAIL_V_MSG(JPH::TransformedShape(), "Not implemented."); }
virtual void GetSubmergedVolume(JPH::Mat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, const JPH::Plane &p_surface, float &p_total_volume, float &p_submerged_volume, JPH::Vec3 &p_center_of_buoyancy JPH_IF_DEBUG_RENDERER(, JPH::RVec3Arg p_base_offset)) const override { ERR_FAIL_MSG("Not implemented."); }
virtual const JPH::ConvexShape::Support *GetSupportFunction(JPH::ConvexShape::ESupportMode p_mode, JPH::ConvexShape::SupportBuffer &p_buffer, JPH::Vec3Arg p_scale) const override;
#ifdef JPH_DEBUG_RENDERER
virtual void Draw(JPH::DebugRenderer *p_renderer, JPH::RMat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, JPH::ColorArg p_color, bool p_use_material_colors, bool p_draw_wireframe) const override { ERR_FAIL_MSG("Not implemented."); }
virtual void DrawGetSupportFunction(JPH::DebugRenderer *p_renderer, JPH::RMat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, JPH::ColorArg p_color, bool p_draw_support_direction) const override { ERR_FAIL_MSG("Not implemented."); }
virtual void DrawGetSupportingFace(JPH::DebugRenderer *p_renderer, JPH::RMat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale) const override { ERR_FAIL_MSG("Not implemented."); }
#endif
virtual bool CastRay(const JPH::RayCast &p_ray, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::RayCastResult &p_hit) const override { ERR_FAIL_V_MSG(false, "Not implemented."); }
virtual void CastRay(const JPH::RayCast &p_ray, const JPH::RayCastSettings &p_ray_cast_settings, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::CastRayCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override { ERR_FAIL_MSG("Not implemented."); }
virtual void CollidePoint(JPH::Vec3Arg p_point, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::CollidePointCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override { ERR_FAIL_MSG("Not implemented."); }
virtual void CollideSoftBodyVertices(JPH::Mat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, const JPH::CollideSoftBodyVertexIterator &p_vertices, JPH::uint p_num_vertices, int p_colliding_shape_index) const override { ERR_FAIL_MSG("Not implemented."); }
virtual void CollectTransformedShapes(const JPH::AABox &p_box, JPH::Vec3Arg p_position_com, JPH::QuatArg p_rotation, JPH::Vec3Arg p_scale, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::TransformedShapeCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override { ERR_FAIL_MSG("Not implemented."); }
virtual void TransformShape(JPH::Mat44Arg p_center_of_mass_transform, JPH::TransformedShapeCollector &p_collector) const override { ERR_FAIL_MSG("Not implemented."); }
virtual void GetTrianglesStart(JPH::Shape::GetTrianglesContext &p_context, const JPH::AABox &p_box, JPH::Vec3Arg p_position_com, JPH::QuatArg p_rotation, JPH::Vec3Arg p_scale) const override { ERR_FAIL_MSG("Not implemented."); }
virtual int GetTrianglesNext(JPH::Shape::GetTrianglesContext &p_context, int p_max_triangles_requested, JPH::Float3 *p_triangle_vertices, const JPH::PhysicsMaterial **p_materials = nullptr) const override { ERR_FAIL_V_MSG(0, "Not implemented."); }
virtual JPH::Shape::Stats GetStats() const override { return JPH::Shape::Stats(sizeof(*this), 0); }
virtual float GetVolume() const override { ERR_FAIL_V_MSG(0.0f, "Not implemented."); }
virtual bool IsValidScale(JPH::Vec3Arg p_scale) const override { ERR_FAIL_V_MSG(false, "Not implemented."); }
const JPH::ConvexShape &get_inner_shape() const { return inner_shape; }
void set_motion(JPH::Vec3Arg p_motion) { motion = p_motion; }
};

View File

@@ -0,0 +1,232 @@
/**************************************************************************/
/* jolt_custom_ray_shape.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_custom_ray_shape.h"
#include "../spaces/jolt_query_collectors.h"
#include "Jolt/Physics/Collision/CastResult.h"
#include "Jolt/Physics/Collision/RayCast.h"
#include "Jolt/Physics/Collision/TransformedShape.h"
#ifdef JPH_DEBUG_RENDERER
#include "Jolt/Renderer/DebugRenderer.h"
#endif
namespace {
class JoltCustomRayShapeSupport final : public JPH::ConvexShape::Support {
public:
explicit JoltCustomRayShapeSupport(float p_length) :
length(p_length) {}
virtual JPH::Vec3 GetSupport(JPH::Vec3Arg p_direction) const override {
if (p_direction.GetZ() > 0.0f) {
return JPH::Vec3(0.0f, 0.0f, length);
} else {
return JPH::Vec3::sZero();
}
}
virtual float GetConvexRadius() const override { return 0.0f; }
private:
float length = 0.0f;
};
static_assert(sizeof(JoltCustomRayShapeSupport) <= sizeof(JPH::ConvexShape::SupportBuffer), "Size of SeparationRayShape3D support is larger than size of support buffer.");
JPH::Shape *construct_ray() {
return new JoltCustomRayShape();
}
void collide_ray_vs_shape(const JPH::Shape *p_shape1, const JPH::Shape *p_shape2, JPH::Vec3Arg p_scale1, JPH::Vec3Arg p_scale2, JPH::Mat44Arg p_center_of_mass_transform1, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, const JPH::CollideShapeSettings &p_collide_shape_settings, JPH::CollideShapeCollector &p_collector, const JPH::ShapeFilter &p_shape_filter) {
ERR_FAIL_COND(p_shape1->GetSubType() != JoltCustomShapeSubType::RAY);
const JoltCustomRayShape *shape1 = static_cast<const JoltCustomRayShape *>(p_shape1);
const float margin = p_collide_shape_settings.mMaxSeparationDistance;
const float ray_length = shape1->length;
const float ray_length_padded = ray_length + margin;
const JPH::Mat44 transform1 = p_center_of_mass_transform1 * JPH::Mat44::sScale(p_scale1);
const JPH::Mat44 transform2 = p_center_of_mass_transform2 * JPH::Mat44::sScale(p_scale2);
const JPH::Mat44 transform_inv2 = transform2.Inversed();
const JPH::Vec3 ray_start = transform1.GetTranslation();
const JPH::Vec3 ray_direction = transform1.GetAxisZ();
const JPH::Vec3 ray_vector = ray_direction * ray_length;
const JPH::Vec3 ray_vector_padded = ray_direction * ray_length_padded;
const JPH::Vec3 ray_start2 = transform_inv2 * ray_start;
const JPH::Vec3 ray_direction2 = transform_inv2.Multiply3x3(ray_direction);
const JPH::Vec3 ray_vector_padded2 = transform_inv2.Multiply3x3(ray_vector_padded);
const JPH::RayCast ray_cast(ray_start2, ray_vector_padded2);
JPH::RayCastSettings ray_cast_settings;
ray_cast_settings.mTreatConvexAsSolid = false;
ray_cast_settings.mBackFaceModeTriangles = p_collide_shape_settings.mBackFaceMode;
JoltQueryCollectorClosest<JPH::CastRayCollector> ray_collector;
p_shape2->CastRay(ray_cast, ray_cast_settings, p_sub_shape_id_creator2, ray_collector);
if (!ray_collector.had_hit()) {
return;
}
const JPH::RayCastResult &hit = ray_collector.get_hit();
const float hit_distance = ray_length_padded * hit.mFraction;
const float hit_depth = ray_length - hit_distance;
if (-hit_depth >= p_collector.GetEarlyOutFraction()) {
return;
}
// Since `hit.mSubShapeID2` could represent a path not only from `p_shape2` but also any
// compound shape that it's contained within, we need to split this path into something that
// `p_shape2` can actually understand.
JPH::SubShapeID local_sub_shape_id2;
hit.mSubShapeID2.PopID(p_sub_shape_id_creator2.GetNumBitsWritten(), local_sub_shape_id2);
const JPH::Vec3 hit_point2 = ray_cast.GetPointOnRay(hit.mFraction);
const JPH::Vec3 hit_point_on_1 = ray_start + ray_vector;
const JPH::Vec3 hit_point_on_2 = transform2 * hit_point2;
JPH::Vec3 hit_normal2 = JPH::Vec3::sZero();
if (shape1->slide_on_slope) {
hit_normal2 = p_shape2->GetSurfaceNormal(local_sub_shape_id2, hit_point2);
// If we got a back-face normal we need to flip it.
if (hit_normal2.Dot(ray_direction2) > 0) {
hit_normal2 = -hit_normal2;
}
} else {
hit_normal2 = -ray_direction2;
}
const JPH::Vec3 hit_normal = transform2.Multiply3x3(hit_normal2);
JPH::CollideShapeResult result(hit_point_on_1, hit_point_on_2, -hit_normal, hit_depth, p_sub_shape_id_creator1.GetID(), hit.mSubShapeID2, JPH::TransformedShape::sGetBodyID(p_collector.GetContext()));
if (p_collide_shape_settings.mCollectFacesMode == JPH::ECollectFacesMode::CollectFaces) {
p_shape2->GetSupportingFace(local_sub_shape_id2, ray_direction2, p_scale2, p_center_of_mass_transform2, result.mShape2Face);
}
p_collector.AddHit(result);
}
void collide_noop(const JPH::Shape *p_shape1, const JPH::Shape *p_shape2, JPH::Vec3Arg p_scale1, JPH::Vec3Arg p_scale2, JPH::Mat44Arg p_center_of_mass_transform1, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, const JPH::CollideShapeSettings &p_collide_shape_settings, JPH::CollideShapeCollector &p_collector, const JPH::ShapeFilter &p_shape_filter) {
}
void cast_noop(const JPH::ShapeCast &p_shape_cast, const JPH::ShapeCastSettings &p_shape_cast_settings, const JPH::Shape *p_shape, JPH::Vec3Arg p_scale, const JPH::ShapeFilter &p_shape_filter, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, JPH::CastShapeCollector &p_collector) {
}
} // namespace
JPH::ShapeSettings::ShapeResult JoltCustomRayShapeSettings::Create() const {
if (mCachedResult.IsEmpty()) {
new JoltCustomRayShape(*this, mCachedResult);
}
return mCachedResult;
}
void JoltCustomRayShape::register_type() {
JPH::ShapeFunctions &shape_functions = JPH::ShapeFunctions::sGet(JoltCustomShapeSubType::RAY);
shape_functions.mConstruct = construct_ray;
shape_functions.mColor = JPH::Color::sDarkRed;
static constexpr JPH::EShapeSubType concrete_sub_types[] = {
JPH::EShapeSubType::Sphere,
JPH::EShapeSubType::Box,
JPH::EShapeSubType::Triangle,
JPH::EShapeSubType::Capsule,
JPH::EShapeSubType::TaperedCapsule,
JPH::EShapeSubType::Cylinder,
JPH::EShapeSubType::ConvexHull,
JPH::EShapeSubType::Mesh,
JPH::EShapeSubType::HeightField,
JPH::EShapeSubType::Plane,
JPH::EShapeSubType::TaperedCylinder
};
for (const JPH::EShapeSubType concrete_sub_type : concrete_sub_types) {
JPH::CollisionDispatch::sRegisterCollideShape(JoltCustomShapeSubType::RAY, concrete_sub_type, collide_ray_vs_shape);
JPH::CollisionDispatch::sRegisterCollideShape(concrete_sub_type, JoltCustomShapeSubType::RAY, JPH::CollisionDispatch::sReversedCollideShape);
}
JPH::CollisionDispatch::sRegisterCollideShape(JoltCustomShapeSubType::RAY, JoltCustomShapeSubType::RAY, collide_noop);
for (const JPH::EShapeSubType sub_type : JPH::sAllSubShapeTypes) {
JPH::CollisionDispatch::sRegisterCastShape(JoltCustomShapeSubType::RAY, sub_type, cast_noop);
JPH::CollisionDispatch::sRegisterCastShape(sub_type, JoltCustomShapeSubType::RAY, cast_noop);
}
}
JPH::AABox JoltCustomRayShape::GetLocalBounds() const {
const float radius = GetInnerRadius();
return JPH::AABox(JPH::Vec3(-radius, -radius, 0.0f), JPH::Vec3(radius, radius, length));
}
float JoltCustomRayShape::GetInnerRadius() const {
// There is no sensible value here, since this shape is infinitely thin, so we pick something
// that's hopefully small enough to effectively be zero, but big enough to not cause any
// numerical issues.
return 0.0001f;
}
JPH::MassProperties JoltCustomRayShape::GetMassProperties() const {
JPH::MassProperties mass_properties;
// Since this shape has no volume we can't really give it a correct set of mass properties, so
// instead we just give it some arbitrary ones.
mass_properties.mMass = 1.0f;
mass_properties.mInertia = JPH::Mat44::sIdentity();
return mass_properties;
}
#ifdef JPH_DEBUG_RENDERER
void JoltCustomRayShape::Draw(JPH::DebugRenderer *p_renderer, JPH::RMat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, JPH::ColorArg p_color, bool p_use_material_colors, bool p_draw_wireframe) const {
p_renderer->DrawArrow(p_center_of_mass_transform.GetTranslation(), p_center_of_mass_transform * JPH::Vec3(0, 0, length * p_scale.GetZ()), p_use_material_colors ? GetMaterial()->GetDebugColor() : p_color, 0.1f);
}
#endif
const JPH::ConvexShape::Support *JoltCustomRayShape::GetSupportFunction(JPH::ConvexShape::ESupportMode p_mode, JPH::ConvexShape::SupportBuffer &p_buffer, JPH::Vec3Arg p_scale) const {
return new (&p_buffer) JoltCustomRayShapeSupport(p_scale.GetZ() * length);
}

View File

@@ -0,0 +1,104 @@
/**************************************************************************/
/* jolt_custom_ray_shape.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_custom_shape_type.h"
#include "Jolt/Jolt.h"
#include "Jolt/Physics/Collision/Shape/ConvexShape.h"
class JoltCustomRayShapeSettings final : public JPH::ConvexShapeSettings {
public:
JPH::RefConst<JPH::PhysicsMaterial> material;
float length = 1.0f;
bool slide_on_slope = false;
JoltCustomRayShapeSettings() = default;
JoltCustomRayShapeSettings(float p_length, bool p_slide_on_slope, const JPH::PhysicsMaterial *p_material = nullptr) :
material(p_material), length(p_length), slide_on_slope(p_slide_on_slope) {}
virtual JPH::ShapeSettings::ShapeResult Create() const override;
};
class JoltCustomRayShape final : public JPH::ConvexShape {
public:
JPH::RefConst<JPH::PhysicsMaterial> material;
float length = 0.0f;
bool slide_on_slope = false;
static void register_type();
JoltCustomRayShape() :
JPH::ConvexShape(JoltCustomShapeSubType::RAY) {}
JoltCustomRayShape(const JoltCustomRayShapeSettings &p_settings, JPH::Shape::ShapeResult &p_result) :
JPH::ConvexShape(JoltCustomShapeSubType::RAY, p_settings, p_result), material(p_settings.material), length(p_settings.length), slide_on_slope(p_settings.slide_on_slope) {
if (!p_result.HasError()) {
p_result.Set(this);
}
}
JoltCustomRayShape(float p_length, bool p_slide_on_slope, const JPH::PhysicsMaterial *p_material = nullptr) :
JPH::ConvexShape(JoltCustomShapeSubType::RAY), material(p_material), length(p_length), slide_on_slope(p_slide_on_slope) {}
virtual JPH::AABox GetLocalBounds() const override;
virtual float GetInnerRadius() const override;
virtual JPH::MassProperties GetMassProperties() const override;
virtual JPH::Vec3 GetSurfaceNormal(const JPH::SubShapeID &p_sub_shape_id, JPH::Vec3Arg p_local_surface_position) const override { return JPH::Vec3::sAxisZ(); }
virtual void GetSubmergedVolume(JPH::Mat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, const JPH::Plane &p_surface, float &p_total_volume, float &p_submerged_volume, JPH::Vec3 &p_center_of_buoyancy JPH_IF_DEBUG_RENDERER(, JPH::RVec3Arg p_base_offset)) const override {
p_total_volume = 0.0f;
p_submerged_volume = 0.0f;
p_center_of_buoyancy = JPH::Vec3::sZero();
}
#ifdef JPH_DEBUG_RENDERER
virtual void Draw(JPH::DebugRenderer *p_renderer, JPH::RMat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, JPH::ColorArg p_color, bool p_use_material_colors, bool p_draw_wireframe) const override;
#endif
virtual bool CastRay(const JPH::RayCast &p_ray, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::RayCastResult &p_hit) const override { return false; }
virtual void CastRay(const JPH::RayCast &p_ray, const JPH::RayCastSettings &p_ray_cast_settings, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::CastRayCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override {}
virtual void CollidePoint(JPH::Vec3Arg p_point, const JPH::SubShapeIDCreator &p_sub_shape_id_creator, JPH::CollidePointCollector &p_collector, const JPH::ShapeFilter &p_shape_filter = JPH::ShapeFilter()) const override {}
virtual void CollideSoftBodyVertices(JPH::Mat44Arg p_center_of_mass_transform, JPH::Vec3Arg p_scale, const JPH::CollideSoftBodyVertexIterator &p_vertices, JPH::uint p_num_vertices, int p_colliding_shape_index) const override {}
virtual JPH::Shape::Stats GetStats() const override { return JPH::Shape::Stats(sizeof(*this), 0); }
virtual float GetVolume() const override { return 0.0f; }
virtual const JPH::ConvexShape::Support *GetSupportFunction(JPH::ConvexShape::ESupportMode p_mode, JPH::ConvexShape::SupportBuffer &p_buffer, JPH::Vec3Arg p_scale) const override;
};

View File

@@ -0,0 +1,44 @@
/**************************************************************************/
/* jolt_custom_shape_type.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "Jolt/Jolt.h"
#include "Jolt/Physics/Collision/Shape/Shape.h"
namespace JoltCustomShapeSubType {
constexpr JPH::EShapeSubType OVERRIDE_USER_DATA = JPH::EShapeSubType::User1;
constexpr JPH::EShapeSubType DOUBLE_SIDED = JPH::EShapeSubType::User2;
constexpr JPH::EShapeSubType RAY = JPH::EShapeSubType::UserConvex1;
constexpr JPH::EShapeSubType MOTION = JPH::EShapeSubType::UserConvex2;
} // namespace JoltCustomShapeSubType

View File

@@ -0,0 +1,99 @@
/**************************************************************************/
/* jolt_custom_user_data_shape.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_custom_user_data_shape.h"
#include "core/error/error_macros.h"
#include "Jolt/Physics/Collision/CollisionDispatch.h"
#include "Jolt/Physics/Collision/ShapeCast.h"
namespace {
JPH::Shape *construct_override_user_data() {
return new JoltCustomUserDataShape();
}
void collide_override_user_data_vs_shape(const JPH::Shape *p_shape1, const JPH::Shape *p_shape2, JPH::Vec3Arg p_scale1, JPH::Vec3Arg p_scale2, JPH::Mat44Arg p_center_of_mass_transform1, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, const JPH::CollideShapeSettings &p_collide_shape_settings, JPH::CollideShapeCollector &p_collector, const JPH::ShapeFilter &p_shape_filter) {
ERR_FAIL_COND(p_shape1->GetSubType() != JoltCustomShapeSubType::OVERRIDE_USER_DATA);
const JoltCustomUserDataShape *shape1 = static_cast<const JoltCustomUserDataShape *>(p_shape1);
JPH::CollisionDispatch::sCollideShapeVsShape(shape1->GetInnerShape(), p_shape2, p_scale1, p_scale2, p_center_of_mass_transform1, p_center_of_mass_transform2, p_sub_shape_id_creator1, p_sub_shape_id_creator2, p_collide_shape_settings, p_collector, p_shape_filter);
}
void collide_shape_vs_override_user_data(const JPH::Shape *p_shape1, const JPH::Shape *p_shape2, JPH::Vec3Arg p_scale1, JPH::Vec3Arg p_scale2, JPH::Mat44Arg p_center_of_mass_transform1, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, const JPH::CollideShapeSettings &p_collide_shape_settings, JPH::CollideShapeCollector &p_collector, const JPH::ShapeFilter &p_shape_filter) {
ERR_FAIL_COND(p_shape2->GetSubType() != JoltCustomShapeSubType::OVERRIDE_USER_DATA);
const JoltCustomUserDataShape *shape2 = static_cast<const JoltCustomUserDataShape *>(p_shape2);
JPH::CollisionDispatch::sCollideShapeVsShape(p_shape1, shape2->GetInnerShape(), p_scale1, p_scale2, p_center_of_mass_transform1, p_center_of_mass_transform2, p_sub_shape_id_creator1, p_sub_shape_id_creator2, p_collide_shape_settings, p_collector, p_shape_filter);
}
void cast_override_user_data_vs_shape(const JPH::ShapeCast &p_shape_cast, const JPH::ShapeCastSettings &p_shape_cast_settings, const JPH::Shape *p_shape, JPH::Vec3Arg p_scale, const JPH::ShapeFilter &p_shape_filter, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, JPH::CastShapeCollector &p_collector) {
ERR_FAIL_COND(p_shape_cast.mShape->GetSubType() != JoltCustomShapeSubType::OVERRIDE_USER_DATA);
const JoltCustomUserDataShape *shape = static_cast<const JoltCustomUserDataShape *>(p_shape_cast.mShape);
const JPH::ShapeCast shape_cast(shape->GetInnerShape(), p_shape_cast.mScale, p_shape_cast.mCenterOfMassStart, p_shape_cast.mDirection);
JPH::CollisionDispatch::sCastShapeVsShapeLocalSpace(shape_cast, p_shape_cast_settings, p_shape, p_scale, p_shape_filter, p_center_of_mass_transform2, p_sub_shape_id_creator1, p_sub_shape_id_creator2, p_collector);
}
void cast_shape_vs_override_user_data(const JPH::ShapeCast &p_shape_cast, const JPH::ShapeCastSettings &p_shape_cast_settings, const JPH::Shape *p_shape, JPH::Vec3Arg p_scale, const JPH::ShapeFilter &p_shape_filter, JPH::Mat44Arg p_center_of_mass_transform2, const JPH::SubShapeIDCreator &p_sub_shape_id_creator1, const JPH::SubShapeIDCreator &p_sub_shape_id_creator2, JPH::CastShapeCollector &p_collector) {
ERR_FAIL_COND(p_shape->GetSubType() != JoltCustomShapeSubType::OVERRIDE_USER_DATA);
const JoltCustomUserDataShape *shape = static_cast<const JoltCustomUserDataShape *>(p_shape);
JPH::CollisionDispatch::sCastShapeVsShapeLocalSpace(p_shape_cast, p_shape_cast_settings, shape->GetInnerShape(), p_scale, p_shape_filter, p_center_of_mass_transform2, p_sub_shape_id_creator1, p_sub_shape_id_creator2, p_collector);
}
} // namespace
JPH::ShapeSettings::ShapeResult JoltCustomUserDataShapeSettings::Create() const {
if (mCachedResult.IsEmpty()) {
new JoltCustomUserDataShape(*this, mCachedResult);
}
return mCachedResult;
}
void JoltCustomUserDataShape::register_type() {
JPH::ShapeFunctions &shape_functions = JPH::ShapeFunctions::sGet(JoltCustomShapeSubType::OVERRIDE_USER_DATA);
shape_functions.mConstruct = construct_override_user_data;
shape_functions.mColor = JPH::Color::sCyan;
for (const JPH::EShapeSubType sub_type : JPH::sAllSubShapeTypes) {
JPH::CollisionDispatch::sRegisterCollideShape(JoltCustomShapeSubType::OVERRIDE_USER_DATA, sub_type, collide_override_user_data_vs_shape);
JPH::CollisionDispatch::sRegisterCollideShape(sub_type, JoltCustomShapeSubType::OVERRIDE_USER_DATA, collide_shape_vs_override_user_data);
JPH::CollisionDispatch::sRegisterCastShape(JoltCustomShapeSubType::OVERRIDE_USER_DATA, sub_type, cast_override_user_data_vs_shape);
JPH::CollisionDispatch::sRegisterCastShape(sub_type, JoltCustomShapeSubType::OVERRIDE_USER_DATA, cast_shape_vs_override_user_data);
}
}

View File

@@ -0,0 +1,58 @@
/**************************************************************************/
/* jolt_custom_user_data_shape.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_custom_decorated_shape.h"
#include "jolt_custom_shape_type.h"
class JoltCustomUserDataShapeSettings final : public JoltCustomDecoratedShapeSettings {
public:
using JoltCustomDecoratedShapeSettings::JoltCustomDecoratedShapeSettings;
virtual ShapeResult Create() const override;
};
class JoltCustomUserDataShape final : public JoltCustomDecoratedShape {
public:
static void register_type();
JoltCustomUserDataShape() :
JoltCustomDecoratedShape(JoltCustomShapeSubType::OVERRIDE_USER_DATA) {}
JoltCustomUserDataShape(const JoltCustomUserDataShapeSettings &p_settings, ShapeResult &p_result) :
JoltCustomDecoratedShape(JoltCustomShapeSubType::OVERRIDE_USER_DATA, p_settings, p_result) {
if (!p_result.HasError()) {
p_result.Set(this);
}
}
virtual JPH::uint64 GetSubShapeUserData(const JPH::SubShapeID &p_sub_shape_id) const override { return GetUserData(); }
};

View File

@@ -0,0 +1,98 @@
/**************************************************************************/
/* jolt_cylinder_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_cylinder_shape_3d.h"
#include "../jolt_project_settings.h"
#include "../misc/jolt_type_conversions.h"
#include "Jolt/Physics/Collision/Shape/CylinderShape.h"
JPH::ShapeRefC JoltCylinderShape3D::_build() const {
const float half_height = height / 2.0f;
const float min_half_extent = MIN(half_height, radius);
const float actual_margin = MIN(margin, min_half_extent * JoltProjectSettings::collision_margin_fraction);
const JPH::CylinderShapeSettings shape_settings(half_height, radius, actual_margin);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics cylinder shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return shape_result.Get();
}
Variant JoltCylinderShape3D::get_data() const {
Dictionary data;
data["height"] = height;
data["radius"] = radius;
return data;
}
void JoltCylinderShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY);
const Dictionary data = p_data;
const Variant maybe_height = data.get("height", Variant());
ERR_FAIL_COND(maybe_height.get_type() != Variant::FLOAT);
const Variant maybe_radius = data.get("radius", Variant());
ERR_FAIL_COND(maybe_radius.get_type() != Variant::FLOAT);
const float new_height = maybe_height;
const float new_radius = maybe_radius;
if (unlikely(new_height == height && new_radius == radius)) {
return;
}
height = new_height;
radius = new_radius;
destroy();
}
void JoltCylinderShape3D::set_margin(float p_margin) {
if (unlikely(margin == p_margin)) {
return;
}
margin = p_margin;
destroy();
}
AABB JoltCylinderShape3D::get_aabb() const {
const Vector3 half_extents(radius, height / 2.0f, radius);
return AABB(-half_extents, half_extents * 2.0f);
}
String JoltCylinderShape3D::to_string() const {
return vformat("{height=%f radius=%f margin=%f}", height, radius, margin);
}

View File

@@ -0,0 +1,55 @@
/**************************************************************************/
/* jolt_cylinder_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltCylinderShape3D final : public JoltShape3D {
float height = 0.0f;
float radius = 0.0f;
float margin = 0.04f;
virtual JPH::ShapeRefC _build() const override;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_CYLINDER; }
virtual bool is_convex() const override { return true; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return margin; }
virtual void set_margin(float p_margin) override;
virtual AABB get_aabb() const override;
String to_string() const;
};

View File

@@ -0,0 +1,233 @@
/**************************************************************************/
/* jolt_height_map_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_height_map_shape_3d.h"
#include "../jolt_project_settings.h"
#include "../misc/jolt_type_conversions.h"
#include "Jolt/Physics/Collision/Shape/HeightFieldShape.h"
#include "Jolt/Physics/Collision/Shape/MeshShape.h"
namespace {
bool _is_vertex_hole(const JPH::VertexList &p_vertices, int p_index) {
const float height = p_vertices[(size_t)p_index].y;
return height == FLT_MAX || Math::is_nan(height);
}
bool _is_triangle_hole(const JPH::VertexList &p_vertices, int p_index0, int p_index1, int p_index2) {
return _is_vertex_hole(p_vertices, p_index0) || _is_vertex_hole(p_vertices, p_index1) || _is_vertex_hole(p_vertices, p_index2);
}
} // namespace
JPH::ShapeRefC JoltHeightMapShape3D::_build() const {
const int height_count = (int)heights.size();
if (unlikely(height_count == 0)) {
return nullptr;
}
ERR_FAIL_COND_V_MSG(height_count != width * depth, nullptr, vformat("Failed to build Jolt Physics height map shape with %s. Height count must be the product of width and depth. This shape belongs to %s.", to_string(), _owners_to_string()));
ERR_FAIL_COND_V_MSG(width < 2 || depth < 2, nullptr, vformat("Failed to build Jolt Physics height map shape with %s. The height map must be at least 2x2. This shape belongs to %s.", to_string(), _owners_to_string()));
if (width != depth) {
return JoltShape3D::with_double_sided(_build_mesh(), true);
}
const int block_size = 2; // Default of JPH::HeightFieldShapeSettings::mBlockSize
const int block_count = width / block_size;
if (block_count < 2) {
return JoltShape3D::with_double_sided(_build_mesh(), true);
}
return JoltShape3D::with_double_sided(_build_height_field(), true);
}
JPH::ShapeRefC JoltHeightMapShape3D::_build_height_field() const {
const int quad_count_x = width - 1;
const int quad_count_y = depth - 1;
const float offset_x = (float)-quad_count_x / 2.0f;
const float offset_y = (float)-quad_count_y / 2.0f;
// Jolt triangulates the height map differently from how Godot Physics does it, so we mirror the shape along the
// Z-axis to get the desired triangulation and reverse the rows to undo the mirroring.
LocalVector<float> heights_rev;
heights_rev.resize(heights.size());
const real_t *heights_ptr = heights.ptr();
float *heights_rev_ptr = heights_rev.ptr();
for (int z = 0; z < depth; ++z) {
const int z_rev = (depth - 1) - z;
const real_t *row = heights_ptr + ptrdiff_t(z * width);
float *row_rev = heights_rev_ptr + ptrdiff_t(z_rev * width);
for (int x = 0; x < width; ++x) {
const real_t height = row[x];
// Godot has undocumented (accidental?) support for holes by passing NaN as the height value, whereas Jolt
// uses `FLT_MAX` instead, so we translate any NaN to `FLT_MAX` in order to be drop-in compatible.
row_rev[x] = Math::is_nan(height) ? FLT_MAX : (float)height;
}
}
JPH::HeightFieldShapeSettings shape_settings(heights_rev.ptr(), JPH::Vec3(offset_x, 0, offset_y), JPH::Vec3::sOne(), (JPH::uint32)width);
shape_settings.mBitsPerSample = shape_settings.CalculateBitsPerSampleForError(0.0f);
shape_settings.mActiveEdgeCosThresholdAngle = JoltProjectSettings::active_edge_threshold_cos;
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics height map shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return with_scale(shape_result.Get(), Vector3(1, 1, -1));
}
JPH::ShapeRefC JoltHeightMapShape3D::_build_mesh() const {
const int height_count = (int)heights.size();
const int quad_count_x = width - 1;
const int quad_count_z = depth - 1;
const int quad_count = quad_count_x * quad_count_z;
const int triangle_count = quad_count * 2;
JPH::VertexList vertices;
vertices.reserve((size_t)height_count);
JPH::IndexedTriangleList indices;
indices.reserve((size_t)triangle_count);
const float offset_x = (float)-quad_count_x / 2.0f;
const float offset_z = (float)-quad_count_z / 2.0f;
for (int z = 0; z < depth; ++z) {
for (int x = 0; x < width; ++x) {
const float vertex_x = offset_x + (float)x;
const float vertex_y = (float)heights[z * width + x];
const float vertex_z = offset_z + (float)z;
vertices.emplace_back(vertex_x, vertex_y, vertex_z);
}
}
for (int z = 0; z < quad_count_z; ++z) {
for (int x = 0; x < quad_count_x; ++x) {
const int index_lower_right = z * width + x;
const int index_lower_left = z * width + (x + 1);
const int index_upper_right = (z + 1) * width + x;
const int index_upper_left = (z + 1) * width + (x + 1);
if (!_is_triangle_hole(vertices, index_lower_right, index_upper_right, index_lower_left)) {
indices.emplace_back(index_lower_right, index_upper_right, index_lower_left);
}
if (!_is_triangle_hole(vertices, index_lower_left, index_upper_right, index_upper_left)) {
indices.emplace_back(index_lower_left, index_upper_right, index_upper_left);
}
}
}
JPH::MeshShapeSettings shape_settings(std::move(vertices), std::move(indices));
shape_settings.mActiveEdgeCosThresholdAngle = JoltProjectSettings::active_edge_threshold_cos;
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics height map shape (as polygon) with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return shape_result.Get();
}
AABB JoltHeightMapShape3D::_calculate_aabb() const {
AABB result;
const int quad_count_x = width - 1;
const int quad_count_z = depth - 1;
const float offset_x = (float)-quad_count_x / 2.0f;
const float offset_z = (float)-quad_count_z / 2.0f;
for (int z = 0; z < depth; ++z) {
for (int x = 0; x < width; ++x) {
const Vector3 vertex(offset_x + (float)x, (float)heights[z * width + x], offset_z + (float)z);
if (x == 0 && z == 0) {
result.position = vertex;
} else {
result.expand_to(vertex);
}
}
}
return result;
}
Variant JoltHeightMapShape3D::get_data() const {
Dictionary data;
data["width"] = width;
data["depth"] = depth;
data["heights"] = heights;
return data;
}
void JoltHeightMapShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY);
const Dictionary data = p_data;
const Variant maybe_heights = data.get("heights", Variant());
#ifdef REAL_T_IS_DOUBLE
ERR_FAIL_COND(maybe_heights.get_type() != Variant::PACKED_FLOAT64_ARRAY);
#else
ERR_FAIL_COND(maybe_heights.get_type() != Variant::PACKED_FLOAT32_ARRAY);
#endif
const Variant maybe_width = data.get("width", Variant());
ERR_FAIL_COND(maybe_width.get_type() != Variant::INT);
const Variant maybe_depth = data.get("depth", Variant());
ERR_FAIL_COND(maybe_depth.get_type() != Variant::INT);
heights = maybe_heights;
width = maybe_width;
depth = maybe_depth;
aabb = _calculate_aabb();
destroy();
}
String JoltHeightMapShape3D::to_string() const {
return vformat("{height_count=%d width=%d depth=%d}", heights.size(), width, depth);
}

View File

@@ -0,0 +1,66 @@
/**************************************************************************/
/* jolt_height_map_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltHeightMapShape3D final : public JoltShape3D {
AABB aabb;
#ifdef REAL_T_IS_DOUBLE
PackedFloat64Array heights;
#else
PackedFloat32Array heights;
#endif
int width = 0;
int depth = 0;
virtual JPH::ShapeRefC _build() const override;
JPH::ShapeRefC _build_height_field() const;
JPH::ShapeRefC _build_mesh() const;
AABB _calculate_aabb() const;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_HEIGHTMAP; }
virtual bool is_convex() const override { return false; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return 0.0f; }
virtual void set_margin(float p_margin) override {}
virtual AABB get_aabb() const override { return aabb; }
String to_string() const;
};

View File

@@ -0,0 +1,85 @@
/**************************************************************************/
/* jolt_separation_ray_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_separation_ray_shape_3d.h"
#include "../misc/jolt_type_conversions.h"
#include "jolt_custom_ray_shape.h"
JPH::ShapeRefC JoltSeparationRayShape3D::_build() const {
ERR_FAIL_COND_V_MSG(length <= 0.0f, nullptr, vformat("Failed to build Jolt Physics separation ray shape with %s. Its length must be greater than 0. This shape belongs to %s.", to_string(), _owners_to_string()));
const JoltCustomRayShapeSettings shape_settings(length, slide_on_slope);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics separation ray shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return shape_result.Get();
}
Variant JoltSeparationRayShape3D::get_data() const {
Dictionary data;
data["length"] = length;
data["slide_on_slope"] = slide_on_slope;
return data;
}
void JoltSeparationRayShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY);
const Dictionary data = p_data;
const Variant maybe_length = data.get("length", Variant());
ERR_FAIL_COND(maybe_length.get_type() != Variant::FLOAT);
const Variant maybe_slide_on_slope = data.get("slide_on_slope", Variant());
ERR_FAIL_COND(maybe_slide_on_slope.get_type() != Variant::BOOL);
const float new_length = maybe_length;
const bool new_slide_on_slope = maybe_slide_on_slope;
if (unlikely(new_length == length && new_slide_on_slope == slide_on_slope)) {
return;
}
length = new_length;
slide_on_slope = new_slide_on_slope;
destroy();
}
AABB JoltSeparationRayShape3D::get_aabb() const {
constexpr float size_xy = 0.1f;
constexpr float half_size_xy = size_xy / 2.0f;
return AABB(Vector3(-half_size_xy, -half_size_xy, 0.0f), Vector3(size_xy, size_xy, length));
}
String JoltSeparationRayShape3D::to_string() const {
return vformat("{length=%f slide_on_slope=%s}", length, slide_on_slope);
}

View File

@@ -0,0 +1,54 @@
/**************************************************************************/
/* jolt_separation_ray_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltSeparationRayShape3D final : public JoltShape3D {
float length = 0.0f;
bool slide_on_slope = false;
virtual JPH::ShapeRefC _build() const override;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_SEPARATION_RAY; }
virtual bool is_convex() const override { return true; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return 0.0f; }
virtual void set_margin(float p_margin) override {}
virtual AABB get_aabb() const override;
String to_string() const;
};

View File

@@ -0,0 +1,278 @@
/**************************************************************************/
/* jolt_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_shape_3d.h"
#include "../misc/jolt_type_conversions.h"
#include "../objects/jolt_shaped_object_3d.h"
#include "jolt_custom_double_sided_shape.h"
#include "jolt_custom_user_data_shape.h"
#include "Jolt/Physics/Collision/Shape/MutableCompoundShape.h"
#include "Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h"
#include "Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h"
#include "Jolt/Physics/Collision/Shape/ScaledShape.h"
#include "Jolt/Physics/Collision/Shape/SphereShape.h"
#include "Jolt/Physics/Collision/Shape/StaticCompoundShape.h"
namespace {
constexpr float DEFAULT_SOLVER_BIAS = 0.0;
} // namespace
String JoltShape3D::_owners_to_string() const {
const int owner_count = ref_counts_by_owner.size();
if (owner_count == 0) {
return "'<unknown>' and 0 other object(s)";
}
const JoltShapedObject3D &random_owner = *ref_counts_by_owner.begin()->key;
return vformat("'%s' and %d other object(s)", random_owner.to_string(), owner_count - 1);
}
JoltShape3D::~JoltShape3D() = default;
void JoltShape3D::add_owner(JoltShapedObject3D *p_owner) {
ref_counts_by_owner[p_owner]++;
}
void JoltShape3D::remove_owner(JoltShapedObject3D *p_owner) {
if (--ref_counts_by_owner[p_owner] <= 0) {
ref_counts_by_owner.erase(p_owner);
}
}
void JoltShape3D::remove_self() {
// `remove_owner` will be called when we `remove_shape`, so we need to copy the map since the
// iterator would be invalidated from underneath us.
const HashMap<JoltShapedObject3D *, int> ref_counts_by_owner_copy = ref_counts_by_owner;
for (const KeyValue<JoltShapedObject3D *, int> &E : ref_counts_by_owner_copy) {
E.key->remove_shape(this);
}
}
float JoltShape3D::get_solver_bias() const {
return DEFAULT_SOLVER_BIAS;
}
void JoltShape3D::set_solver_bias(float p_bias) {
if (!Math::is_equal_approx(p_bias, DEFAULT_SOLVER_BIAS)) {
WARN_PRINT(vformat("Custom solver bias for shapes is not supported when using Jolt Physics. Any such value will be ignored. This shape belongs to %s.", _owners_to_string()));
}
}
JPH::ShapeRefC JoltShape3D::try_build() {
jolt_ref_mutex.lock();
if (jolt_ref == nullptr) {
jolt_ref = _build();
}
jolt_ref_mutex.unlock();
return jolt_ref;
}
void JoltShape3D::destroy() {
jolt_ref_mutex.lock();
jolt_ref = nullptr;
jolt_ref_mutex.unlock();
for (const KeyValue<JoltShapedObject3D *, int> &E : ref_counts_by_owner) {
E.key->_shapes_changed();
}
}
JPH::ShapeRefC JoltShape3D::with_scale(const JPH::Shape *p_shape, const Vector3 &p_scale) {
ERR_FAIL_NULL_V(p_shape, nullptr);
const JPH::ScaledShapeSettings shape_settings(p_shape, to_jolt(p_scale));
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to scale shape with {scale=%v}. It returned the following error: '%s'.", p_scale, to_godot(shape_result.GetError())));
return shape_result.Get();
}
JPH::ShapeRefC JoltShape3D::with_basis_origin(const JPH::Shape *p_shape, const Basis &p_basis, const Vector3 &p_origin) {
ERR_FAIL_NULL_V(p_shape, nullptr);
const JPH::RotatedTranslatedShapeSettings shape_settings(to_jolt(p_origin), to_jolt(p_basis), p_shape);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to offset shape with {basis=%s origin=%v}. It returned the following error: '%s'.", p_basis, p_origin, to_godot(shape_result.GetError())));
return shape_result.Get();
}
JPH::ShapeRefC JoltShape3D::with_center_of_mass_offset(const JPH::Shape *p_shape, const Vector3 &p_offset) {
ERR_FAIL_NULL_V(p_shape, nullptr);
const JPH::OffsetCenterOfMassShapeSettings shape_settings(to_jolt(p_offset), p_shape);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to offset center of mass with {offset=%v}. It returned the following error: '%s'.", p_offset, to_godot(shape_result.GetError())));
return shape_result.Get();
}
JPH::ShapeRefC JoltShape3D::with_center_of_mass(const JPH::Shape *p_shape, const Vector3 &p_center_of_mass) {
ERR_FAIL_NULL_V(p_shape, nullptr);
const Vector3 center_of_mass_inner = to_godot(p_shape->GetCenterOfMass());
const Vector3 center_of_mass_offset = p_center_of_mass - center_of_mass_inner;
if (center_of_mass_offset == Vector3()) {
return p_shape;
}
return with_center_of_mass_offset(p_shape, center_of_mass_offset);
}
JPH::ShapeRefC JoltShape3D::with_user_data(const JPH::Shape *p_shape, uint64_t p_user_data) {
JoltCustomUserDataShapeSettings shape_settings(p_shape);
shape_settings.mUserData = (JPH::uint64)p_user_data;
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to override user data. It returned the following error: '%s'.", to_godot(shape_result.GetError())));
return shape_result.Get();
}
JPH::ShapeRefC JoltShape3D::with_double_sided(const JPH::Shape *p_shape, bool p_back_face_collision) {
ERR_FAIL_NULL_V(p_shape, nullptr);
const JoltCustomDoubleSidedShapeSettings shape_settings(p_shape, p_back_face_collision);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to make shape double-sided. It returned the following error: '%s'.", to_godot(shape_result.GetError())));
return shape_result.Get();
}
JPH::ShapeRefC JoltShape3D::without_custom_shapes(const JPH::Shape *p_shape) {
switch (p_shape->GetSubType()) {
case JoltCustomShapeSubType::RAY:
case JoltCustomShapeSubType::MOTION: {
// Replace unsupported shapes with a small sphere.
return new JPH::SphereShape(0.1f);
}
case JoltCustomShapeSubType::OVERRIDE_USER_DATA:
case JoltCustomShapeSubType::DOUBLE_SIDED: {
const JPH::DecoratedShape *shape = static_cast<const JPH::DecoratedShape *>(p_shape);
// Replace unsupported decorator shapes with the inner shape.
return without_custom_shapes(shape->GetInnerShape());
}
case JPH::EShapeSubType::StaticCompound: {
const JPH::StaticCompoundShape *shape = static_cast<const JPH::StaticCompoundShape *>(p_shape);
JPH::StaticCompoundShapeSettings settings;
for (const JPH::CompoundShape::SubShape &sub_shape : shape->GetSubShapes()) {
settings.AddShape(shape->GetCenterOfMass() + sub_shape.GetPositionCOM() - sub_shape.GetRotation() * sub_shape.mShape->GetCenterOfMass(), sub_shape.GetRotation(), without_custom_shapes(sub_shape.mShape));
}
const JPH::ShapeSettings::ShapeResult shape_result = settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to recreate static compound shape during filtering of custom shapes. It returned the following error: '%s'.", to_godot(shape_result.GetError())));
return shape_result.Get();
}
case JPH::EShapeSubType::MutableCompound: {
const JPH::MutableCompoundShape *shape = static_cast<const JPH::MutableCompoundShape *>(p_shape);
JPH::MutableCompoundShapeSettings settings;
for (const JPH::MutableCompoundShape::SubShape &sub_shape : shape->GetSubShapes()) {
settings.AddShape(shape->GetCenterOfMass() + sub_shape.GetPositionCOM() - sub_shape.GetRotation() * sub_shape.mShape->GetCenterOfMass(), sub_shape.GetRotation(), without_custom_shapes(sub_shape.mShape));
}
const JPH::ShapeSettings::ShapeResult shape_result = settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to recreate mutable compound shape during filtering of custom shapes. It returned the following error: '%s'.", to_godot(shape_result.GetError())));
return shape_result.Get();
}
case JPH::EShapeSubType::RotatedTranslated: {
const JPH::RotatedTranslatedShape *shape = static_cast<const JPH::RotatedTranslatedShape *>(p_shape);
const JPH::Shape *inner_shape = shape->GetInnerShape();
const JPH::ShapeRefC new_inner_shape = without_custom_shapes(inner_shape);
if (inner_shape == new_inner_shape) {
return p_shape;
}
return new JPH::RotatedTranslatedShape(shape->GetPosition(), shape->GetRotation(), new_inner_shape);
}
case JPH::EShapeSubType::Scaled: {
const JPH::ScaledShape *shape = static_cast<const JPH::ScaledShape *>(p_shape);
const JPH::Shape *inner_shape = shape->GetInnerShape();
const JPH::ShapeRefC new_inner_shape = without_custom_shapes(inner_shape);
if (inner_shape == new_inner_shape) {
return p_shape;
}
return new JPH::ScaledShape(new_inner_shape, shape->GetScale());
}
case JPH::EShapeSubType::OffsetCenterOfMass: {
const JPH::OffsetCenterOfMassShape *shape = static_cast<const JPH::OffsetCenterOfMassShape *>(p_shape);
const JPH::Shape *inner_shape = shape->GetInnerShape();
const JPH::ShapeRefC new_inner_shape = without_custom_shapes(inner_shape);
if (inner_shape == new_inner_shape) {
return p_shape;
}
return new JPH::OffsetCenterOfMassShape(new_inner_shape, shape->GetOffset());
}
default: {
return p_shape;
}
}
}
Vector3 JoltShape3D::make_scale_valid(const JPH::Shape *p_shape, const Vector3 &p_scale) {
return to_godot(p_shape->MakeScaleValid(to_jolt(p_scale)));
}
bool JoltShape3D::is_scale_valid(const Vector3 &p_scale, const Vector3 &p_valid_scale, real_t p_tolerance) {
return Math::is_equal_approx(p_scale.x, p_valid_scale.x, p_tolerance) && Math::is_equal_approx(p_scale.y, p_valid_scale.y, p_tolerance) && Math::is_equal_approx(p_scale.z, p_valid_scale.z, p_tolerance);
}

View File

@@ -0,0 +1,133 @@
/**************************************************************************/
/* jolt_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "servers/physics_server_3d.h"
#include "Jolt/Jolt.h"
#include "Jolt/Physics/Collision/Shape/Shape.h"
class JoltShapedObject3D;
class JoltShape3D {
protected:
HashMap<JoltShapedObject3D *, int> ref_counts_by_owner;
Mutex jolt_ref_mutex;
RID rid;
JPH::ShapeRefC jolt_ref;
virtual JPH::ShapeRefC _build() const = 0;
String _owners_to_string() const;
public:
typedef PhysicsServer3D::ShapeType ShapeType;
virtual ~JoltShape3D() = 0;
RID get_rid() const { return rid; }
void set_rid(const RID &p_rid) { rid = p_rid; }
void add_owner(JoltShapedObject3D *p_owner);
void remove_owner(JoltShapedObject3D *p_owner);
void remove_self();
virtual ShapeType get_type() const = 0;
virtual bool is_convex() const = 0;
virtual Variant get_data() const = 0;
virtual void set_data(const Variant &p_data) = 0;
virtual float get_margin() const = 0;
virtual void set_margin(float p_margin) = 0;
virtual AABB get_aabb() const = 0;
float get_solver_bias() const;
void set_solver_bias(float p_bias);
JPH::ShapeRefC try_build();
void destroy();
const JPH::Shape *get_jolt_ref() const { return jolt_ref; }
static JPH::ShapeRefC with_scale(const JPH::Shape *p_shape, const Vector3 &p_scale);
static JPH::ShapeRefC with_basis_origin(const JPH::Shape *p_shape, const Basis &p_basis, const Vector3 &p_origin);
static JPH::ShapeRefC with_center_of_mass_offset(const JPH::Shape *p_shape, const Vector3 &p_offset);
static JPH::ShapeRefC with_center_of_mass(const JPH::Shape *p_shape, const Vector3 &p_center_of_mass);
static JPH::ShapeRefC with_user_data(const JPH::Shape *p_shape, uint64_t p_user_data);
static JPH::ShapeRefC with_double_sided(const JPH::Shape *p_shape, bool p_back_face_collision);
static JPH::ShapeRefC without_custom_shapes(const JPH::Shape *p_shape);
static Vector3 make_scale_valid(const JPH::Shape *p_shape, const Vector3 &p_scale);
static bool is_scale_valid(const Vector3 &p_scale, const Vector3 &p_valid_scale, real_t p_tolerance = 0.01f);
};
#ifdef DEBUG_ENABLED
#define JOLT_ENSURE_SCALE_NOT_ZERO(m_transform, m_msg) \
if (unlikely((m_transform).basis.determinant() == 0.0f)) { \
WARN_PRINT(vformat("%s " \
"The basis of the transform was singular, which is not supported by Jolt Physics. " \
"This is likely caused by one or more axes having a scale of zero. " \
"The basis (and thus its scale) will be treated as identity.", \
m_msg)); \
\
(m_transform).basis = Basis(); \
} else \
((void)0)
#define ERR_PRINT_INVALID_SCALE_MSG(m_scale, m_valid_scale, m_msg) \
if (unlikely(!JoltShape3D::is_scale_valid(m_scale, valid_scale))) { \
ERR_PRINT(vformat("%s " \
"A scale of %v is not supported by Jolt Physics for this shape/body. " \
"The scale will instead be treated as %v.", \
m_msg, m_scale, valid_scale)); \
} else \
((void)0)
#else
#define JOLT_ENSURE_SCALE_NOT_ZERO(m_transform, m_msg)
#define ERR_PRINT_INVALID_SCALE_MSG(m_scale, m_valid_scale, m_msg)
#endif
#define JOLT_ENSURE_SCALE_VALID(m_shape, m_scale, m_msg) \
if (true) { \
const Vector3 valid_scale = JoltShape3D::make_scale_valid(m_shape, m_scale); \
ERR_PRINT_INVALID_SCALE_MSG(m_scale, valid_scale, m_msg); \
(m_scale) = valid_scale; \
} else \
((void)0)

View File

@@ -0,0 +1,99 @@
/**************************************************************************/
/* jolt_shape_instance_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_shape_instance_3d.h"
#include "jolt_shape_3d.h"
#include "Jolt/Physics/Collision/Shape/DecoratedShape.h"
JoltShapeInstance3D::ShapeReference::ShapeReference(JoltShapedObject3D *p_parent, JoltShape3D *p_shape) :
parent(p_parent),
shape(p_shape) {
if (shape != nullptr) {
shape->add_owner(parent);
}
}
JoltShapeInstance3D::ShapeReference::ShapeReference(ShapeReference &&p_other) :
parent(p_other.parent),
shape(p_other.shape) {
p_other.parent = nullptr;
p_other.shape = nullptr;
}
JoltShapeInstance3D::ShapeReference::~ShapeReference() {
if (shape != nullptr) {
shape->remove_owner(parent);
}
}
JoltShapeInstance3D::ShapeReference &JoltShapeInstance3D::ShapeReference::operator=(ShapeReference &&p_other) {
if (this != &p_other) {
SWAP(parent, p_other.parent);
SWAP(shape, p_other.shape);
}
return *this;
}
JoltShapeInstance3D::JoltShapeInstance3D(JoltShapedObject3D *p_parent, JoltShape3D *p_shape, const Transform3D &p_transform, const Vector3 &p_scale, bool p_disabled) :
transform(p_transform),
scale(p_scale),
shape(p_parent, p_shape),
disabled(p_disabled) {
}
AABB JoltShapeInstance3D::get_aabb() const {
return get_transform_scaled().xform(shape->get_aabb());
}
bool JoltShapeInstance3D::try_build() {
ERR_FAIL_COND_V(is_disabled(), false);
const JPH::ShapeRefC maybe_new_shape = shape->try_build();
if (maybe_new_shape == nullptr) {
jolt_ref = nullptr;
return false;
}
if (jolt_ref != nullptr) {
const JPH::DecoratedShape *outer_shape = static_cast<const JPH::DecoratedShape *>(jolt_ref.GetPtr());
if (outer_shape->GetInnerShape() == maybe_new_shape) {
return true;
}
}
jolt_ref = JoltShape3D::with_user_data(maybe_new_shape, (uint64_t)id);
return true;
}

View File

@@ -0,0 +1,99 @@
/**************************************************************************/
/* jolt_shape_instance_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/math/transform_3d.h"
#include "Jolt/Jolt.h"
#include "Jolt/Physics/Collision/Shape/Shape.h"
class JoltShapedObject3D;
class JoltShape3D;
class JoltShapeInstance3D {
// This RAII helper exists solely to avoid needing to maintain move construction/assignment in `JoltShapeInstance3D`.
struct ShapeReference {
JoltShapedObject3D *parent = nullptr;
JoltShape3D *shape = nullptr;
ShapeReference() = default;
ShapeReference(JoltShapedObject3D *p_parent, JoltShape3D *p_shape);
ShapeReference(const ShapeReference &p_other) = delete;
ShapeReference(ShapeReference &&p_other);
~ShapeReference();
ShapeReference &operator=(const ShapeReference &p_other) = delete;
ShapeReference &operator=(ShapeReference &&p_other);
JoltShape3D *operator*() const { return shape; }
JoltShape3D *operator->() const { return shape; }
operator JoltShape3D *() const { return shape; }
};
inline static uint32_t next_id = 1;
Transform3D transform;
Vector3 scale;
ShapeReference shape;
JPH::ShapeRefC jolt_ref;
uint32_t id = next_id++;
bool disabled = false;
public:
JoltShapeInstance3D() = default;
JoltShapeInstance3D(JoltShapedObject3D *p_parent, JoltShape3D *p_shape, const Transform3D &p_transform = Transform3D(), const Vector3 &p_scale = Vector3(1.0f, 1.0f, 1.0f), bool p_disabled = false);
uint32_t get_id() const { return id; }
JoltShape3D *get_shape() const { return shape; }
const JPH::Shape *get_jolt_ref() const { return jolt_ref; }
const Transform3D &get_transform_unscaled() const { return transform; }
Transform3D get_transform_scaled() const { return transform.scaled_local(scale); }
void set_transform(const Transform3D &p_transform) { transform = p_transform; }
const Vector3 &get_scale() const { return scale; }
void set_scale(const Vector3 &p_scale) { scale = p_scale; }
AABB get_aabb() const;
bool is_built() const { return jolt_ref != nullptr; }
bool is_enabled() const { return !disabled; }
bool is_disabled() const { return disabled; }
void enable() { disabled = false; }
void disable() { disabled = true; }
bool try_build();
};

View File

@@ -0,0 +1,71 @@
/**************************************************************************/
/* jolt_sphere_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_sphere_shape_3d.h"
#include "../misc/jolt_type_conversions.h"
#include "Jolt/Physics/Collision/Shape/SphereShape.h"
JPH::ShapeRefC JoltSphereShape3D::_build() const {
ERR_FAIL_COND_V_MSG(radius <= 0.0f, nullptr, vformat("Failed to build Jolt Physics sphere shape with %s. Its radius must be greater than 0. This shape belongs to %s.", to_string(), _owners_to_string()));
const JPH::SphereShapeSettings shape_settings(radius);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics sphere shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return shape_result.Get();
}
Variant JoltSphereShape3D::get_data() const {
return radius;
}
void JoltSphereShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::FLOAT);
const float new_radius = p_data;
if (unlikely(new_radius == radius)) {
return;
}
radius = new_radius;
destroy();
}
AABB JoltSphereShape3D::get_aabb() const {
const Vector3 half_extents(radius, radius, radius);
return AABB(-half_extents, half_extents * 2.0f);
}
String JoltSphereShape3D::to_string() const {
return vformat("{radius=%f}", radius);
}

View File

@@ -0,0 +1,53 @@
/**************************************************************************/
/* jolt_sphere_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltSphereShape3D final : public JoltShape3D {
float radius = 0.0f;
virtual JPH::ShapeRefC _build() const override;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_SPHERE; }
virtual bool is_convex() const override { return true; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return 0.0f; }
virtual void set_margin(float p_margin) override {}
virtual AABB get_aabb() const override;
String to_string() const;
};

View File

@@ -0,0 +1,75 @@
/**************************************************************************/
/* jolt_world_boundary_shape_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "jolt_world_boundary_shape_3d.h"
#include "../jolt_project_settings.h"
#include "../misc/jolt_type_conversions.h"
#include "Jolt/Physics/Collision/Shape/PlaneShape.h"
JPH::ShapeRefC JoltWorldBoundaryShape3D::_build() const {
const Plane normalized_plane = plane.normalized();
ERR_FAIL_COND_V_MSG(normalized_plane == Plane(), nullptr, vformat("Failed to build Jolt Physics world boundary shape with %s. The plane's normal must not be zero. This shape belongs to %s.", to_string(), _owners_to_string()));
const float half_size = JoltProjectSettings::world_boundary_shape_size / 2.0f;
const JPH::PlaneShapeSettings shape_settings(to_jolt(normalized_plane), nullptr, half_size);
const JPH::ShapeSettings::ShapeResult shape_result = shape_settings.Create();
ERR_FAIL_COND_V_MSG(shape_result.HasError(), nullptr, vformat("Failed to build Jolt Physics world boundary shape with %s. It returned the following error: '%s'. This shape belongs to %s.", to_string(), to_godot(shape_result.GetError()), _owners_to_string()));
return shape_result.Get();
}
Variant JoltWorldBoundaryShape3D::get_data() const {
return plane;
}
void JoltWorldBoundaryShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::PLANE);
const Plane new_plane = p_data;
if (unlikely(new_plane == plane)) {
return;
}
plane = p_data;
destroy();
}
AABB JoltWorldBoundaryShape3D::get_aabb() const {
const float size = JoltProjectSettings::world_boundary_shape_size;
const float half_size = size / 2.0f;
return AABB(Vector3(-half_size, -half_size, -half_size), Vector3(size, half_size, size));
}
String JoltWorldBoundaryShape3D::to_string() const {
return vformat("{plane=%s}", plane);
}

View File

@@ -0,0 +1,53 @@
/**************************************************************************/
/* jolt_world_boundary_shape_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "jolt_shape_3d.h"
class JoltWorldBoundaryShape3D final : public JoltShape3D {
Plane plane;
virtual JPH::ShapeRefC _build() const override;
public:
virtual ShapeType get_type() const override { return ShapeType::SHAPE_WORLD_BOUNDARY; }
virtual bool is_convex() const override { return false; }
virtual Variant get_data() const override;
virtual void set_data(const Variant &p_data) override;
virtual float get_margin() const override { return 0.0f; }
virtual void set_margin(float p_margin) override {}
virtual AABB get_aabb() const override;
String to_string() const;
};