实现弹簧
parent
588bfecd65
commit
5bd6647d14
|
@ -31,6 +31,7 @@
|
|||
<ClInclude Include="src\Mesh.h" />
|
||||
<ClInclude Include="src\Model.h" />
|
||||
<ClInclude Include="src\Particle.h" />
|
||||
<ClInclude Include="src\PhysicsManager.h" />
|
||||
<ClInclude Include="src\RenderPass.h" />
|
||||
<ClInclude Include="src\RenderPassContext.h" />
|
||||
<ClInclude Include="src\Shader.h" />
|
||||
|
@ -51,6 +52,7 @@
|
|||
<ClCompile Include="src\Mesh.cpp" />
|
||||
<ClCompile Include="src\Model.cpp" />
|
||||
<ClCompile Include="src\Particle.cpp" />
|
||||
<ClCompile Include="src\PhysicsManager.cpp" />
|
||||
<ClCompile Include="src\RenderPass.cpp" />
|
||||
<ClCompile Include="src\Shader.cpp" />
|
||||
<ClCompile Include="src\World.cpp" />
|
||||
|
|
|
@ -22,12 +22,26 @@ DemoWorld::DemoWorld()
|
|||
sponza->setScale(glm::vec3(2));
|
||||
|
||||
auto particle = std::make_shared<Particle>(10);
|
||||
particle->setSpeed(glm::vec3(-1, 0, 0));
|
||||
particle->setPosition({ 4, 5, 0 });
|
||||
particle->addForce(std::make_shared<Force>(glm::vec3(0.f, -particle->getMass() * 9.8f, 0.f)));
|
||||
//particle->addForce(std::make_shared<Force>(glm::vec3(0.f, -particle->getMass() * 9.8f, 0.f)));
|
||||
auto particle2 = std::make_shared<Particle>(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<Particle>(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);
|
||||
}
|
||||
|
|
|
@ -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> force)
|
||||
{
|
||||
forces.insert(force);
|
||||
resultantForce += force->value;
|
||||
}
|
||||
|
||||
void Particle::removeForce(std::shared_ptr<Force> 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;
|
||||
}
|
||||
|
|
|
@ -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> force);
|
||||
void removeForce(std::shared_ptr<Force> force);
|
||||
float getMass();
|
||||
glm::vec3 getSpeed();
|
||||
void setSpeed(const glm::vec3& speed);
|
||||
private:
|
||||
float mass;
|
||||
glm::vec3 speed = glm::vec3(0.f);
|
||||
|
|
|
@ -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<Particle> p1, std::shared_ptr<Particle> p2, float length, float ks, float kd)
|
||||
{
|
||||
auto f1 = std::make_shared<Force>(glm::vec3(0));
|
||||
auto f2 = std::make_shared<Force>(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);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
#include "Particle.h"
|
||||
|
||||
struct BinaryConstraint
|
||||
{
|
||||
std::weak_ptr<Particle> p1;
|
||||
std::weak_ptr<Particle> p2;
|
||||
std::function<glm::vec3(Particle& p1, Particle& p2)> solver; /// f1
|
||||
std::shared_ptr<Force> f1;
|
||||
std::shared_ptr<Force> f2;
|
||||
};
|
||||
|
||||
class PhysicsManager
|
||||
{
|
||||
public:
|
||||
void tick(float deltaTime);
|
||||
void addSpring(std::shared_ptr<Particle> p1, std::shared_ptr<Particle> p2, float length, float ks, float kd);
|
||||
|
||||
private:
|
||||
std::vector<BinaryConstraint> constraints;
|
||||
};
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
void World::logicalTick(float deltaTime)
|
||||
{
|
||||
physicsManager.tick(deltaTime);
|
||||
for (auto& actor : actors)
|
||||
actor->logicalTick(deltaTime);
|
||||
}
|
||||
|
|
|
@ -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> actor);
|
||||
std::pair<glm::vec3, glm::vec3> getAABB();
|
||||
protected:
|
||||
PhysicsManager physicsManager;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue