From cbeaa4d2bb6ab4b14f34c9401349dcbcd779115a Mon Sep 17 00:00:00 2001 From: maelstrom Date: Fri, 29 Aug 2025 01:59:00 +0200 Subject: [PATCH] feat(physics): added wedges and cylinders --- core/src/enum/part.h | 1 + core/src/objects/part/part.cpp | 11 +++- core/src/objects/part/wedgepart.cpp | 87 +---------------------------- core/src/objects/part/wedgepart.h | 6 +- core/src/physics/world.cpp | 66 +++++++++++++++------- core/src/rendering/renderer.cpp | 6 ++ 6 files changed, 65 insertions(+), 112 deletions(-) diff --git a/core/src/enum/part.h b/core/src/enum/part.h index ec27a88..c7d4fb3 100644 --- a/core/src/enum/part.h +++ b/core/src/enum/part.h @@ -7,6 +7,7 @@ enum class DEF_ENUM PartType { Ball = 0, Block = 1, + Cylinder = 2, }; namespace EnumType { diff --git a/core/src/objects/part/part.cpp b/core/src/objects/part/part.cpp index 0b4839f..7c68509 100644 --- a/core/src/objects/part/part.cpp +++ b/core/src/objects/part/part.cpp @@ -9,5 +9,14 @@ Part::Part(PartConstructParams params): BasePart(&TYPE, params) { } Vector3 Part::GetEffectiveSize() { - return shape == PartType::Ball ? (Vector3)glm::vec3(glm::min(size.X(), size.Y(), size.Z())) : size; + float diameter; + switch (shape) { + case PartType::Ball: + return (Vector3)glm::vec3(glm::min(size.X(), size.Y(), size.Z())); + case PartType::Cylinder: + diameter = glm::min(size.Y(), size.Z()); + return Vector3(size.X(), diameter, diameter); + default: + return size; + } } \ No newline at end of file diff --git a/core/src/objects/part/wedgepart.cpp b/core/src/objects/part/wedgepart.cpp index 5795e1b..b510559 100644 --- a/core/src/objects/part/wedgepart.cpp +++ b/core/src/objects/part/wedgepart.cpp @@ -1,91 +1,6 @@ #include "wedgepart.h" -// #include -// #include - -// rp::ConvexMesh* wedgePhysMesh; WedgePart::WedgePart(): BasePart(&TYPE) { } -WedgePart::WedgePart(PartConstructParams params): BasePart(&TYPE, params) { - -} - -// void WedgePart::updateCollider(rp::PhysicsCommon* common) { -// Logger::fatalError("Wedges are currently disabled! Please do not use them or your editor may crash\n"); -// rp::ConvexMeshShape* shape = common->createConvexMeshShape(wedgePhysMesh, glmToRp(size * glm::vec3(0.5f))); - -// // Recreate the rigidbody if the shape changes -// if (rigidBody->getNbColliders() > 0 -// && dynamic_cast(rigidBody->getCollider(0)->getCollisionShape())->getScale() != shape->getScale()) { -// // TODO: This causes Touched to get called twice. Fix this. -// rigidBody->removeCollider(rigidBody->getCollider(0)); -// rigidBody->addCollider(shape, rp::Transform()); -// } - -// if (rigidBody->getNbColliders() == 0) -// rigidBody->addCollider(shape, rp::Transform()); -// } - -// void WedgePart::createWedgeShape(rp::PhysicsCommon* common) { -// // https://www.reactphysics3d.com/documentation/index.html#creatingbody -// float vertices[] = { -// // X Y Z -// /*0*/ -1, 1, 1, // 0 -// /*1*/ -1, -1, 1, // | -// /*2*/ -1, -1, -1, // 1---2 - -// /*3*/ 1, 1, 1, -// /*4*/ 1, -1, 1, -// /*5*/ 1, -1, -1, -// }; - -// // -x +x -// // +z 1----------4 -// // | bottom | -// // -z 2----------5 - -// // -x +x -// // +y 0----------3 -// // | front | -// // -y 1----------4 - -// // -x +x -// // +yz 0----------3 -// // | slope | -// // -yz 2----------5 - -// int indices[] = { -// // Base -// 1, 2, 5, 4, - -// // Back-face -// 0, 1, 4, 3, -// // 4, 1, 0, 3, - -// // Slope -// 0, 2, 5, 3, -// // 3, 5, 2, 0, - -// // Sides -// 0, 1, 2, -// 3, 4, 5, -// }; - -// // Description of the six faces of the convex mesh -// rp::PolygonVertexArray::PolygonFace* polygonFaces = new rp::PolygonVertexArray::PolygonFace[5]; -// polygonFaces[0] = { 4, 0 }; // Bottom -// polygonFaces[1] = { 4, 4 }; // Front -// polygonFaces[2] = { 4, 8 }; // Slope -// polygonFaces[3] = { 3, 12 }; // Side -// polygonFaces[4] = { 3, 15 }; // Side - -// // Create the polygon vertex array -// rp::PolygonVertexArray polygonVertexArray(6, vertices, 3 * sizeof(float), indices, sizeof(int), 5, polygonFaces, -// rp::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE, -// rp::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE); - -// // Create the convex mesh -// std::vector messages; -// // wedgePhysMesh = common->createConvexMesh(polygonVertexArray, messages); -// } \ No newline at end of file +WedgePart::WedgePart(PartConstructParams params): BasePart(&TYPE, params) {} \ No newline at end of file diff --git a/core/src/objects/part/wedgepart.h b/core/src/objects/part/wedgepart.h index 1c66cf9..10c77e5 100644 --- a/core/src/objects/part/wedgepart.h +++ b/core/src/objects/part/wedgepart.h @@ -3,13 +3,9 @@ #include "basepart.h" #include "objects/annotation.h" -class DEF_INST_(hidden) WedgePart : public BasePart { +class DEF_INST WedgePart : public BasePart { AUTOGEN_PREAMBLE -protected: - // static void createWedgeShape(rp::PhysicsCommon* common); - - friend Workspace; public: WedgePart(); WedgePart(PartConstructParams params); diff --git a/core/src/physics/world.cpp b/core/src/physics/world.cpp index 8d949f5..494e8ef 100644 --- a/core/src/physics/world.cpp +++ b/core/src/physics/world.cpp @@ -4,6 +4,7 @@ #include "logger.h" #include "objects/part/basepart.h" #include "objects/part/part.h" +#include "objects/part/wedgepart.h" #include "objects/service/workspace.h" #include "physics/convert.h" #include "timeutil.h" @@ -21,6 +22,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -36,12 +41,11 @@ static JPH::TempAllocator* allocator; static JPH::JobSystem* jobSystem; - namespace Layers { static constexpr JPH::ObjectLayer DYNAMIC = 0; static constexpr JPH::ObjectLayer ANCHORED = 1; - static constexpr JPH::ObjectLayer NUM_LAYERS = 2; + // static constexpr JPH::ObjectLayer NUM_LAYERS = 2; }; namespace BPLayers @@ -51,6 +55,37 @@ namespace BPLayers static constexpr uint NUM_LAYERS(2); }; +static JPH::Ref wedgeShape; + +void physicsInit() { + JPH::RegisterDefaultAllocator(); + JPH::Factory::sInstance = new JPH::Factory(); + JPH::RegisterTypes(); + + allocator = new JPH::TempAllocatorImpl(10 * 1024 * 1024); + jobSystem = new JPH::JobSystemThreadPool(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, std::thread::hardware_concurrency() - 1); + + // Create special shapes + JPH::Array wedgeVerts; + wedgeVerts.push_back({-1, -1, -1}); + wedgeVerts.push_back({ 1, -1, -1}); + wedgeVerts.push_back({-1, -1, 1}); + wedgeVerts.push_back({ 1, -1, 1}); + wedgeVerts.push_back({ 1, 1, 1}); + wedgeVerts.push_back({-1, 1, 1}); + // // Invisible bevel to avoid phasing + // wedgeVerts.push_back({1, 1, 0.9}); + // wedgeVerts.push_back({0, 1, 0.9}); + + wedgeShape = JPH::ConvexHullShapeSettings(wedgeVerts).Create().Get(); +} + +void physicsDeinit() { + JPH::UnregisterTypes(); + delete JPH::Factory::sInstance; + JPH::Factory::sInstance = nullptr; +} + PhysWorld::PhysWorld() { worldImpl.Init(4096, 0, 4096, 4096, broadPhaseLayerInterface, objectBroadPhasefilter, objectLayerPairFilter); worldImpl.SetGravity(JPH::Vec3(0, -196, 0)); @@ -79,8 +114,11 @@ JPH::Shape* makeShape(std::shared_ptr basePart) { return new JPH::BoxShape(convert(part->size / 2.f), JPH::cDefaultConvexRadius); case PartType::Ball: return new JPH::SphereShape(glm::min(part->size.X(), part->size.Y(), part->size.Z()) / 2.f); - break; + case PartType::Cylinder: + return new JPH::RotatedTranslatedShape(JPH::Vec3(), JPH::Quat::sEulerAngles(JPH::Vec3(0, 0, JPH::JPH_PI * 0.5)), new JPH::CylinderShape(part->size.X() / 2.f, glm::min(part->size.Z(), part->size.Y()) / 2.f)); } + } else if (std::shared_ptr part = std::dynamic_pointer_cast(basePart)) { + return new JPH::ScaledShape(wedgeShape, convert(part->size / 2.f)); } return nullptr; } @@ -123,21 +161,9 @@ void PhysWorld::syncBodyProperties(std::shared_ptr part) { interface.SetMotionType(body->GetID(), motionType, activationMode); interface.SetPositionRotationAndVelocity(body->GetID(), convert(part->position()), convert((glm::quat)part->cframe.RotMatrix()), convert(part->velocity), /* Angular velocity is NYI: */ body->GetAngularVelocity()); } -} -void physicsInit() { - JPH::RegisterDefaultAllocator(); - JPH::Factory::sInstance = new JPH::Factory(); - JPH::RegisterTypes(); - - allocator = new JPH::TempAllocatorImpl(10 * 1024 * 1024); - jobSystem = new JPH::JobSystemThreadPool(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, std::thread::hardware_concurrency() - 1); -} - -void physicsDeinit() { - JPH::UnregisterTypes(); - delete JPH::Factory::sInstance; - JPH::Factory::sInstance = nullptr; + part->rigidBody._lastSize = part->size; + if (std::shared_ptr part2 = std::dynamic_pointer_cast(part)) part->rigidBody._lastShape = part2->shape; } tu_time_t physTime; @@ -168,15 +194,15 @@ PhysJoint PhysWorld::createJoint(PhysJointInfo& type, std::shared_ptr ) { Logger::fatalError("Failed to create joint between two parts due to the call being invalid"); panic(); }; JPH::TwoBodyConstraint* constraint; - if (PhysJointGlueInfo* info = dynamic_cast(&type)) { + if (PhysJointGlueInfo* _ = dynamic_cast(&type)) { JPH::FixedConstraintSettings settings; settings.mAutoDetectPoint = true; // TODO: Replace this with anchor point constraint = settings.Create(*part0->rigidBody.bodyImpl, *part1->rigidBody.bodyImpl); - } else if (PhysJointWeldInfo* info = dynamic_cast(&type)) { + } else if (PhysJointWeldInfo* _ = dynamic_cast(&type)) { JPH::FixedConstraintSettings settings; settings.mAutoDetectPoint = true; // TODO: Replace this with anchor point constraint = settings.Create(*part0->rigidBody.bodyImpl, *part1->rigidBody.bodyImpl); - } else if (PhysJointSnapInfo* info = dynamic_cast(&type)) { + } else if (PhysJointSnapInfo* _ = dynamic_cast(&type)) { JPH::FixedConstraintSettings settings; settings.mAutoDetectPoint = true; // TODO: Replace this with anchor point constraint = settings.Create(*part0->rigidBody.bodyImpl, *part1->rigidBody.bodyImpl); diff --git a/core/src/rendering/renderer.cpp b/core/src/rendering/renderer.cpp index 35f94d8..7c0dcc5 100644 --- a/core/src/rendering/renderer.cpp +++ b/core/src/rendering/renderer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -127,6 +128,7 @@ static void renderPart(std::shared_ptr part) { glm::mat4 model = part->cframe; Vector3 size = part->GetEffectiveSize(); model = glm::scale(model, (glm::vec3)size); + if (std::shared_ptr part2 = std::dynamic_pointer_cast(part)) if (part2->shape == PartType::Cylinder) model = glm::rotate(model, glm::pi() * 0.5f, glm::vec3(0, 1, 0)); // Lazy hack shader->set("model", model); shader->set("material", Material { .diffuse = part->color, @@ -157,6 +159,10 @@ static void renderPart(std::shared_ptr part) { glFrontFace(GL_CW); CUBE_MESH->bind(); glDrawArrays(GL_TRIANGLES, 0, CUBE_MESH->vertexCount); + } else if (shape == PartType::Cylinder) { + glFrontFace(GL_CW); + CYLINDER_MESH->bind(); + glDrawArrays(GL_TRIANGLES, 0, CYLINDER_MESH->vertexCount); } }