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;
};