From 5bd6647d145c3c40ffceeca814f4e274b6269cbc Mon Sep 17 00:00:00 2001 From: wuyize Date: Wed, 19 Apr 2023 20:38:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=BC=B9=E7=B0=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ToyEngine/ToyEngine.vcxproj | 2 ++ ToyEngine/src/DemoWorld.cpp | 16 ++++++++++++++- ToyEngine/src/Particle.cpp | 35 ++++++++++++++++++++++++-------- ToyEngine/src/Particle.h | 3 +++ ToyEngine/src/PhysicsManager.cpp | 30 +++++++++++++++++++++++++++ ToyEngine/src/PhysicsManager.h | 22 ++++++++++++++++++++ ToyEngine/src/World.cpp | 1 + ToyEngine/src/World.h | 3 +++ 8 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 ToyEngine/src/PhysicsManager.cpp create mode 100644 ToyEngine/src/PhysicsManager.h diff --git a/ToyEngine/ToyEngine.vcxproj b/ToyEngine/ToyEngine.vcxproj index a9ba45c..df6cbda 100644 --- a/ToyEngine/ToyEngine.vcxproj +++ b/ToyEngine/ToyEngine.vcxproj @@ -31,6 +31,7 @@ + @@ -51,6 +52,7 @@ + diff --git a/ToyEngine/src/DemoWorld.cpp b/ToyEngine/src/DemoWorld.cpp index 83766cd..085f3c8 100644 --- a/ToyEngine/src/DemoWorld.cpp +++ b/ToyEngine/src/DemoWorld.cpp @@ -22,12 +22,26 @@ DemoWorld::DemoWorld() sponza->setScale(glm::vec3(2)); auto particle = std::make_shared(10); + particle->setSpeed(glm::vec3(-1, 0, 0)); particle->setPosition({ 4, 5, 0 }); - particle->addForce(std::make_shared(glm::vec3(0.f, -particle->getMass() * 9.8f, 0.f))); + //particle->addForce(std::make_shared(glm::vec3(0.f, -particle->getMass() * 9.8f, 0.f))); + auto particle2 = std::make_shared(10, "Models/vampire/vampire.gltf"); + particle2->setSpeed(glm::vec3(1, 0, 0)); + particle2->setPosition({ 6, 5, 0 }); + particle2->setScale(glm::vec3{ 0.4 }); + + auto particle3 = std::make_shared(10); + particle3->setSpeed(glm::vec3(0, 1, 0)); + particle3->setPosition({ 6, 7, 0 }); + + physicsManager.addSpring(particle, particle2, 2, 10, 0); + physicsManager.addSpring(particle2, particle3, 2, 10, 0); addActor(actor); addActor(actor2); addActor(actor3); addActor(sponza); addActor(particle); + addActor(particle2); + addActor(particle3); } diff --git a/ToyEngine/src/Particle.cpp b/ToyEngine/src/Particle.cpp index 0dab9d8..99f2bae 100644 --- a/ToyEngine/src/Particle.cpp +++ b/ToyEngine/src/Particle.cpp @@ -7,17 +7,28 @@ Particle::Particle(float mass) , debugShader(gl, "Shaders/debug.vert", "Shaders/debug.frag") { model = Model::createSphere(gl); - setScale(glm::vec3(0.4)); + setScale(glm::vec3(0.2)); +} + +Particle::Particle(float mass, const std::string& path) + : Actor(path) + , mass(mass) + , debugShader(gl, "Shaders/debug.vert", "Shaders/debug.frag") +{ } void Particle::logicalTick(float deltaTime) { + resultantForce = glm::vec3(0); + for (auto& force : forces) + resultantForce += force->value; + auto pos = getPosition() + speed * deltaTime + 0.5f * resultantForce / mass * deltaTime * deltaTime; speed += resultantForce / mass * deltaTime; - if (speed.y < 0 && pos.y < 0.4) - { - speed.y = -speed.y; - } + //if (speed.y < 0 && pos.y < 0.4) + //{ + // speed.y = -speed.y; + //} setPosition(pos); } @@ -48,7 +59,7 @@ void Particle::draw(const RenderPassContext& context, Shader& shader) debugShader.use(); debugShader.setUniformValue("projection", *context.projection); debugShader.setUniformValue("view", *context.view); - glm::mat4 modelMatrix = glm::translate(glm::mat4(1), getPosition()) * glm::scale(glm::mat4(1), getScale()) * glm::mat4_cast(getRotation()); + glm::mat4 modelMatrix = glm::translate(glm::mat4(1), getPosition()) * glm::scale(glm::mat4(1), getScale()) * glm::mat4_cast(getRotation()) * glm::scale(glm::mat4(1), glm::vec3(glm::abs(resultantForce / mass))); gl->BindVertexArray(vao); for (auto& force : forces) { @@ -64,16 +75,24 @@ void Particle::draw(const RenderPassContext& context, Shader& shader) void Particle::addForce(std::shared_ptr force) { forces.insert(force); - resultantForce += force->value; } void Particle::removeForce(std::shared_ptr force) { forces.erase(force); - resultantForce -= force->value; } float Particle::getMass() { return mass; } + +glm::vec3 Particle::getSpeed() +{ + return speed; +} + +void Particle::setSpeed(const glm::vec3& speed) +{ + this->speed = speed; +} diff --git a/ToyEngine/src/Particle.h b/ToyEngine/src/Particle.h index 26604f9..2a05193 100644 --- a/ToyEngine/src/Particle.h +++ b/ToyEngine/src/Particle.h @@ -12,12 +12,15 @@ class Particle : public Actor { public: Particle(float mass); + Particle(float mass, const std::string& path); virtual ~Particle() = default; virtual void logicalTick(float deltaTime); virtual void draw(const RenderPassContext& context, Shader& shader); void addForce(std::shared_ptr force); void removeForce(std::shared_ptr force); float getMass(); + glm::vec3 getSpeed(); + void setSpeed(const glm::vec3& speed); private: float mass; glm::vec3 speed = glm::vec3(0.f); diff --git a/ToyEngine/src/PhysicsManager.cpp b/ToyEngine/src/PhysicsManager.cpp new file mode 100644 index 0000000..96af01c --- /dev/null +++ b/ToyEngine/src/PhysicsManager.cpp @@ -0,0 +1,30 @@ +#include "PhysicsManager.h" + +void PhysicsManager::tick(float deltaTime) +{ + for (auto iter = constraints.begin(); iter < constraints.end(); ) + { + if (iter->p1.expired() || iter->p2.expired()) + iter = constraints.erase(iter); + else + { + iter->f1->value = iter->solver(*iter->p1.lock(), *iter->p2.lock()); + iter->f2->value = -iter->f1->value; + iter++; + } + } +} + +void PhysicsManager::addSpring(std::shared_ptr p1, std::shared_ptr p2, float length, float ks, float kd) +{ + auto f1 = std::make_shared(glm::vec3(0)); + auto f2 = std::make_shared(glm::vec3(0)); + p1->addForce(f1); + p2->addForce(f2); + constraints.emplace_back(p1, p2, [length, ks, kd](Particle& p1, Particle& p2) { + auto d = glm::distance(p1.getPosition(), p2.getPosition()); + float dt = 1.f; + auto vd = glm::distance(p1.getPosition() + p1.getSpeed() * dt, p2.getPosition() + p2.getSpeed() * dt) / dt; + return -(ks * (d - length) + kd * vd) * (p1.getPosition() - p2.getPosition()) / d; + }, f1, f2); +} diff --git a/ToyEngine/src/PhysicsManager.h b/ToyEngine/src/PhysicsManager.h new file mode 100644 index 0000000..3190172 --- /dev/null +++ b/ToyEngine/src/PhysicsManager.h @@ -0,0 +1,22 @@ +#pragma once +#include "Particle.h" + +struct BinaryConstraint +{ + std::weak_ptr p1; + std::weak_ptr p2; + std::function solver; /// f1 + std::shared_ptr f1; + std::shared_ptr f2; +}; + +class PhysicsManager +{ +public: + void tick(float deltaTime); + void addSpring(std::shared_ptr p1, std::shared_ptr p2, float length, float ks, float kd); + +private: + std::vector constraints; +}; + diff --git a/ToyEngine/src/World.cpp b/ToyEngine/src/World.cpp index d54ed45..7d73ed7 100644 --- a/ToyEngine/src/World.cpp +++ b/ToyEngine/src/World.cpp @@ -2,6 +2,7 @@ void World::logicalTick(float deltaTime) { + physicsManager.tick(deltaTime); for (auto& actor : actors) actor->logicalTick(deltaTime); } diff --git a/ToyEngine/src/World.h b/ToyEngine/src/World.h index ca2b2df..03bbc92 100644 --- a/ToyEngine/src/World.h +++ b/ToyEngine/src/World.h @@ -1,6 +1,7 @@ #pragma once #include "Actor.h" #include "RenderPassContext.h" +#include "PhysicsManager.h" class World { @@ -11,5 +12,7 @@ public: void draw(const RenderPassContext& context, Shader& shader); void addActor(std::shared_ptr actor); std::pair getAABB(); +protected: + PhysicsManager physicsManager; };