feat(physics): added collision detection with Touched/TouchEnded

This commit is contained in:
maelstrom 2025-05-21 21:58:15 +02:00
parent e0ac5398f3
commit cc87d08dad
6 changed files with 60 additions and 13 deletions

View file

@ -88,8 +88,6 @@ protected:
// NOTE: This value is not necessarily present if dataModel is present // NOTE: This value is not necessarily present if dataModel is present
// Objects under services other than workspace will NOT have this field set // Objects under services other than workspace will NOT have this field set
std::optional<std::shared_ptr<Workspace>> workspace(); std::optional<std::shared_ptr<Workspace>> workspace();
template <typename T> inline std::shared_ptr<T> shared() { return std::dynamic_pointer_cast<T>(this->shared_from_this()); }
public: public:
const static InstanceType TYPE; const static InstanceType TYPE;
std::string name; std::string name;
@ -108,6 +106,8 @@ public:
bool IsA(std::string className); bool IsA(std::string className);
template <typename T> bool IsA() { return IsA(T::TYPE.className); } template <typename T> bool IsA() { return IsA(T::TYPE.className); }
template <typename T> inline std::shared_ptr<T> shared() { return std::dynamic_pointer_cast<T>(this->shared_from_this()); }
DescendantsIterator GetDescendantsStart(); DescendantsIterator GetDescendantsStart();
DescendantsIterator GetDescendantsEnd(); DescendantsIterator GetDescendantsEnd();
// Utility functions // Utility functions

View file

@ -60,8 +60,6 @@ void Part::onUpdated(std::string property) {
// When position/rotation/size is manually edited, break all joints, they don't apply anymore // When position/rotation/size is manually edited, break all joints, they don't apply anymore
if (property != "Anchored") if (property != "Anchored")
BreakJoints(); BreakJoints();
OnParentUpdated->Fire();
} }
// Expands provided extents to fit point // Expands provided extents to fit point

View file

@ -92,7 +92,8 @@ public:
DEF_PROP float frontParamB = 0.5; DEF_PROP float frontParamB = 0.5;
DEF_PROP float backParamB = 0.5; DEF_PROP float backParamB = 0.5;
DEF_SIGNAL SignalSource OnParentUpdated; DEF_SIGNAL SignalSource Touched;
DEF_SIGNAL SignalSource TouchEnded;
rp::RigidBody* rigidBody = nullptr; rp::RigidBody* rigidBody = nullptr;

View file

@ -15,9 +15,14 @@ int script_wait(lua_State*);
int script_delay(lua_State*); int script_delay(lua_State*);
Script::Script(): Instance(&TYPE) { Script::Script(): Instance(&TYPE) {
source = "workspace.Part.OnParentUpdated:Connect(function()\n\ source = "workspace.Part.Touched:Connect(function(otherPart)\n"
print(\"Yeux d'enfants\")\n\ " print(\"Touched by: \", otherPart.Name)\n"
end)"; "end)\n"
"\n"
"workspace.Part.TouchEnded:Connect(function(otherPart)\n"
" print(\"Touched ended with: \", otherPart.Name)\n"
"end)\n"
"\n";
} }
Script::~Script() { Script::~Script() {

View file

@ -1,4 +1,6 @@
#include "workspace.h" #include "workspace.h"
#include "datatypes/meta.h"
#include "datatypes/ref.h"
#include "datatypes/vector.h" #include "datatypes/vector.h"
#include "objects/base/instance.h" #include "objects/base/instance.h"
#include "objects/jointsservice.h" #include "objects/jointsservice.h"
@ -6,11 +8,12 @@
#include "objects/datamodel.h" #include "objects/datamodel.h"
#include "physics/util.h" #include "physics/util.h"
#include <memory> #include <memory>
#include <reactphysics3d/collision/CollisionCallback.h>
#include <reactphysics3d/engine/PhysicsCommon.h> #include <reactphysics3d/engine/PhysicsCommon.h>
rp::PhysicsCommon* Workspace::physicsCommon = new rp::PhysicsCommon; rp::PhysicsCommon* Workspace::physicsCommon = new rp::PhysicsCommon;
Workspace::Workspace(): Service(&TYPE) { Workspace::Workspace(): Service(&TYPE), physicsEventListener(this) {
} }
Workspace::~Workspace() { Workspace::~Workspace() {
@ -18,6 +21,27 @@ Workspace::~Workspace() {
physicsCommon->destroyPhysicsWorld(physicsWorld); physicsCommon->destroyPhysicsWorld(physicsWorld);
} }
PhysicsEventListener::PhysicsEventListener(Workspace* parent) : workspace(parent) {}
void PhysicsEventListener::onContact(const rp::CollisionCallback::CallbackData& data) {
for (int i = 0; i < data.getNbContactPairs(); i++) {
auto pair = data.getContactPair(i);
auto type = pair.getEventType();
if (type == rp::CollisionCallback::ContactPair::EventType::ContactStay) continue;
auto part0 = reinterpret_cast<Part*>(pair.getBody1()->getUserData())->shared<Part>();
auto part1 = reinterpret_cast<Part*>(pair.getBody2()->getUserData())->shared<Part>();
if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactStart) {
part0->Touched->Fire({ (Data::Variant)Data::InstanceRef(part1) });
part1->Touched->Fire({ (Data::Variant)Data::InstanceRef(part0) });
} else if (type == reactphysics3d::CollisionCallback::ContactPair::EventType::ContactExit) {
part0->TouchEnded->Fire({ (Data::Variant)Data::InstanceRef(part1) });
part1->TouchEnded->Fire({ (Data::Variant)Data::InstanceRef(part0) });
}
}
}
void Workspace::InitService() { void Workspace::InitService() {
if (initialized) return; if (initialized) return;
initialized = true; initialized = true;
@ -31,7 +55,7 @@ void Workspace::InitService() {
// physicsWorld->setSleepLinearVelocity(10); // physicsWorld->setSleepLinearVelocity(10);
// physicsWorld->setSleepAngularVelocity(5); // physicsWorld->setSleepAngularVelocity(5);
// physicsWorld->setEventListener(&eventListener); physicsWorld->setEventListener(&physicsEventListener);
// Sync all parts // Sync all parts
for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) { for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) {
@ -71,10 +95,17 @@ void Workspace::SyncPartPhysics(std::shared_ptr<Part> part) {
rp::BoxShape* shape = physicsCommon->createBoxShape(glmToRp(part->size * glm::vec3(0.5f))); rp::BoxShape* shape = physicsCommon->createBoxShape(glmToRp(part->size * glm::vec3(0.5f)));
if (part->rigidBody->getNbColliders() > 0) // Recreate the rigidbody if the shape changes
if (part->rigidBody->getNbColliders() > 0
&& dynamic_cast<rp::BoxShape*>(part->rigidBody->getCollider(0)->getCollisionShape())->getHalfExtents() != shape->getHalfExtents()) {
// TODO: This causes Touched to get called twice. Fix this.
part->rigidBody->removeCollider(part->rigidBody->getCollider(0)); part->rigidBody->removeCollider(part->rigidBody->getCollider(0));
part->rigidBody->addCollider(shape, rp::Transform());
}
if (part->rigidBody->getNbColliders() == 0)
part->rigidBody->addCollider(shape, rp::Transform());
part->rigidBody->addCollider(shape, rp::Transform());
part->rigidBody->setType(part->anchored ? rp::BodyType::STATIC : rp::BodyType::DYNAMIC); part->rigidBody->setType(part->anchored ? rp::BodyType::STATIC : rp::BodyType::DYNAMIC);
part->rigidBody->getCollider(0)->setCollisionCategoryBits(0b11); part->rigidBody->getCollider(0)->setCollisionCategoryBits(0b11);

View file

@ -5,6 +5,7 @@
#include <glm/ext/vector_float3.hpp> #include <glm/ext/vector_float3.hpp>
#include <memory> #include <memory>
#include <reactphysics3d/body/RigidBody.h> #include <reactphysics3d/body/RigidBody.h>
#include <reactphysics3d/engine/EventListener.h>
#include <reactphysics3d/engine/PhysicsCommon.h> #include <reactphysics3d/engine/PhysicsCommon.h>
#include <reactphysics3d/engine/PhysicsWorld.h> #include <reactphysics3d/engine/PhysicsWorld.h>
@ -35,11 +36,22 @@ class RotateV;
typedef std::function<FilterResult(std::shared_ptr<Part>)> RaycastFilter; typedef std::function<FilterResult(std::shared_ptr<Part>)> RaycastFilter;
class Workspace;
class PhysicsEventListener : public rp::EventListener {
friend Workspace;
Workspace* workspace;
PhysicsEventListener(Workspace*);
void onContact(const rp::CollisionCallback::CallbackData&) override;
};
class DEF_INST_SERVICE_(explorer_icon="workspace") Workspace : public Service { class DEF_INST_SERVICE_(explorer_icon="workspace") Workspace : public Service {
AUTOGEN_PREAMBLE AUTOGEN_PREAMBLE
rp::PhysicsWorld* physicsWorld = nullptr; rp::PhysicsWorld* physicsWorld = nullptr;
static rp::PhysicsCommon* physicsCommon; static rp::PhysicsCommon* physicsCommon;
PhysicsEventListener physicsEventListener;
friend Part; friend Part;
friend Snap; friend Snap;