render vertices in addition to edges
This commit is contained in:
@ -6,11 +6,12 @@
|
|||||||
constexpr int WIDTH = 800;
|
constexpr int WIDTH = 800;
|
||||||
constexpr int HEIGHT = 800;
|
constexpr int HEIGHT = 800;
|
||||||
|
|
||||||
constexpr float VERTEX_SIZE = 5.0;
|
constexpr float VERTEX_SIZE = 50.0;
|
||||||
constexpr Color VERTEX_COLOR = {27, 188, 104, 255};
|
constexpr Color VERTEX_COLOR = {27, 188, 104, 255};
|
||||||
constexpr Color EDGE_COLOR = {20, 133, 38, 255};
|
constexpr Color EDGE_COLOR = {20, 133, 38, 255};
|
||||||
|
|
||||||
constexpr float SIM_SPEED = 4.0;
|
constexpr float SIM_SPEED = 4.0;
|
||||||
|
constexpr float ROTATION_SPEED = 1.0;
|
||||||
constexpr float CAMERA_DISTANCE = 2.2;
|
constexpr float CAMERA_DISTANCE = 2.2;
|
||||||
|
|
||||||
constexpr float DEFAULT_SPRING_CONSTANT = 1.5;
|
constexpr float DEFAULT_SPRING_CONSTANT = 1.5;
|
||||||
|
|||||||
@ -115,9 +115,7 @@ public:
|
|||||||
|
|
||||||
auto CalculateSpringForces() -> void;
|
auto CalculateSpringForces() -> void;
|
||||||
|
|
||||||
auto IntegrateVelocities(const float delta_time) -> void;
|
auto EulerUpdate(const float delta_time) -> void;
|
||||||
|
|
||||||
auto IntegratePositions(const float delta_time) -> void;
|
|
||||||
|
|
||||||
auto VerletUpdate(const float delta_time) -> void;
|
auto VerletUpdate(const float delta_time) -> void;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,8 +8,11 @@
|
|||||||
|
|
||||||
#include "mass_springs.hpp"
|
#include "mass_springs.hpp"
|
||||||
|
|
||||||
using Edge2Set = std::vector<std::pair<Vector2, Vector2>>;
|
|
||||||
using Edge3Set = std::vector<std::pair<Vector3, Vector3>>;
|
using Edge3Set = std::vector<std::pair<Vector3, Vector3>>;
|
||||||
|
using Edge2Set = std::vector<std::pair<Vector2, Vector2>>;
|
||||||
|
using Vertex2Set =
|
||||||
|
std::vector<Vector3>; // Vertex2Set uses Vector3 to retain the z-coordinate
|
||||||
|
// for circle size adaptation
|
||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
private:
|
private:
|
||||||
@ -40,10 +43,12 @@ private:
|
|||||||
auto Map(const Vector2 &a) -> Vector2;
|
auto Map(const Vector2 &a) -> Vector2;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
auto Transform(Edge2Set &edges, const MassSpringSystem &mass_springs,
|
auto Transform(Edge2Set &edges, Vertex2Set &vertices,
|
||||||
const float angle, const float distance) -> void;
|
const MassSpringSystem &mass_springs, const float angle,
|
||||||
|
const float distance) -> void;
|
||||||
|
|
||||||
auto Draw(const Edge2Set &edges) -> void;
|
auto DrawMassSprings(const Edge2Set &edges, const Vertex2Set &vertices)
|
||||||
|
-> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
30
src/main.cpp
30
src/main.cpp
@ -23,9 +23,6 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
|
|
||||||
InitWindow(WIDTH, HEIGHT, "MassSprings");
|
InitWindow(WIDTH, HEIGHT, "MassSprings");
|
||||||
|
|
||||||
Edge3Set edges;
|
|
||||||
Edge2Set viewport;
|
|
||||||
viewport.reserve(edges.size());
|
|
||||||
|
|
||||||
MassSpringSystem mass_springs;
|
MassSpringSystem mass_springs;
|
||||||
mass_springs.AddMass(1.0, Vector3(-0.5, 0.5, 0.0), true);
|
mass_springs.AddMass(1.0, Vector3(-0.5, 0.5, 0.0), true);
|
||||||
@ -37,6 +34,10 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
DEFAULT_DAMPENING_CONSTANT, DEFAULT_REST_LENGTH);
|
DEFAULT_DAMPENING_CONSTANT, DEFAULT_REST_LENGTH);
|
||||||
|
|
||||||
Renderer renderer(WIDTH, HEIGHT);
|
Renderer renderer(WIDTH, HEIGHT);
|
||||||
|
Edge2Set edges;
|
||||||
|
edges.reserve(mass_springs.springs.size());
|
||||||
|
Vertex2Set vertices;
|
||||||
|
vertices.reserve(mass_springs.masses.size());
|
||||||
|
|
||||||
float frametime;
|
float frametime;
|
||||||
float abstime = 0.0;
|
float abstime = 0.0;
|
||||||
@ -48,28 +49,15 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
#ifdef VERLET_UPDATE
|
#ifdef VERLET_UPDATE
|
||||||
mass_springs.VerletUpdate(frametime * SIM_SPEED);
|
mass_springs.VerletUpdate(frametime * SIM_SPEED);
|
||||||
#else
|
#else
|
||||||
mass_springs.IntegrateVelocities(frametime * SIM_SPEED);
|
mass_springs.EulerUpdate(frametime * SIM_SPEED);
|
||||||
mass_springs.IntegratePositions(frametime * SIM_SPEED);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// std::cout << "Calculating Spring Forces: A: (" << massA.force.x << ", "
|
renderer.Transform(edges, vertices, mass_springs, abstime * ROTATION_SPEED,
|
||||||
// << massA.force.y << ", " << massA.force.z << ") B: ("
|
CAMERA_DISTANCE);
|
||||||
// << massB.force.x << ", " << massB.force.y << ", " <<
|
renderer.DrawMassSprings(edges, vertices);
|
||||||
// massB.force.z
|
|
||||||
// << ")" << std::endl;
|
|
||||||
// std::cout << "Calculating Velocities: A: (" << massA.velocity.x << ", "
|
|
||||||
// << massA.velocity.y << ", " << massA.velocity.z << ") B: ("
|
|
||||||
// << massB.velocity.x << ", " << massB.velocity.y << ", "
|
|
||||||
// << massB.velocity.z << ")" << std::endl;
|
|
||||||
// std::cout << "Calculating Positions: A: (" << massA.position.x << ", "
|
|
||||||
// << massA.position.y << ", " << massA.position.z << ") B: ("
|
|
||||||
// << massB.position.x << ", " << massB.position.y << ", "
|
|
||||||
// << massB.position.z << ")" << std::endl;
|
|
||||||
|
|
||||||
renderer.Transform(viewport, mass_springs, 0.0, CAMERA_DISTANCE);
|
|
||||||
renderer.Draw(viewport);
|
renderer.Draw(viewport);
|
||||||
|
abstime += frametime;
|
||||||
abstime += frametime * SIM_SPEED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
|
|||||||
@ -104,14 +104,9 @@ auto MassSpringSystem::CalculateSpringForces() -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MassSpringSystem::IntegrateVelocities(const float delta_time) -> void {
|
auto MassSpringSystem::EulerUpdate(const float delta_time) -> void {
|
||||||
for (auto &mass : masses) {
|
for (auto &mass : masses) {
|
||||||
mass.CalculateVelocity(delta_time);
|
mass.CalculateVelocity(delta_time);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto MassSpringSystem::IntegratePositions(const float delta_time) -> void {
|
|
||||||
for (auto &mass : masses) {
|
|
||||||
mass.CalculatePosition(delta_time);
|
mass.CalculatePosition(delta_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,31 +21,47 @@ auto Renderer::Map(const Vector2 &a) -> Vector2 {
|
|||||||
return Vector2((1.0 + a.x) / 2.0 * width, (1.0 - a.y) * height / 2.0);
|
return Vector2((1.0 + a.x) / 2.0 * width, (1.0 - a.y) * height / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Renderer::Transform(Edge2Set &edges, const MassSpringSystem &mass_springs,
|
auto Renderer::Transform(Edge2Set &edges, Vertex2Set &vertices,
|
||||||
|
const MassSpringSystem &mass_springs,
|
||||||
const float angle, const float distance) -> void {
|
const float angle, const float distance) -> void {
|
||||||
edges.clear();
|
|
||||||
|
|
||||||
const float cos_angle = cos(angle);
|
const float cos_angle = cos(angle);
|
||||||
const float sin_angle = sin(angle);
|
const float sin_angle = sin(angle);
|
||||||
|
|
||||||
|
edges.clear();
|
||||||
for (const auto &spring : mass_springs.springs) {
|
for (const auto &spring : mass_springs.springs) {
|
||||||
Vector2 at = Map(Project(Translate(
|
Vector2 a = Map(Project(Translate(
|
||||||
Rotate(spring.massA.position, cos_angle, sin_angle), distance)));
|
Rotate(spring.massA.position, cos_angle, sin_angle), distance)));
|
||||||
Vector2 bt = Map(Project(Translate(
|
Vector2 b = Map(Project(Translate(
|
||||||
Rotate(spring.massB.position, cos_angle, sin_angle), distance)));
|
Rotate(spring.massB.position, cos_angle, sin_angle), distance)));
|
||||||
|
|
||||||
edges.emplace_back(at, bt);
|
edges.emplace_back(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is duplicated work, but easy to read
|
||||||
|
vertices.clear();
|
||||||
|
for (const auto &mass : mass_springs.masses) {
|
||||||
|
Vector3 a =
|
||||||
|
Translate(Rotate(mass.position, cos_angle, sin_angle), distance);
|
||||||
|
Vector2 b = Map(Project(a));
|
||||||
|
|
||||||
|
vertices.emplace_back(b.x, b.y, a.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Renderer::Draw(const Edge2Set &edges) -> void {
|
auto Renderer::DrawMassSprings(const Edge2Set &edges,
|
||||||
|
const Vertex2Set &vertices) -> void {
|
||||||
BeginTextureMode(render_target);
|
BeginTextureMode(render_target);
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
for (const auto &[a, b] : edges) {
|
for (const auto &[a, b] : edges) {
|
||||||
DrawLine(a.x, a.y, b.x, b.y, EDGE_COLOR);
|
DrawLine(a.x, a.y, b.x, b.y, EDGE_COLOR);
|
||||||
DrawCircle(a.x, a.y, VERTEX_SIZE, VERTEX_COLOR);
|
|
||||||
DrawCircle(b.x, b.y, VERTEX_SIZE, VERTEX_COLOR);
|
|
||||||
}
|
}
|
||||||
|
for (const auto &a : vertices) {
|
||||||
|
// Increase the perspective perception by squaring the z-coordinate
|
||||||
|
const float size = VERTEX_SIZE / (a.z * a.z);
|
||||||
|
|
||||||
|
DrawRectangle(a.x - size / 2.0, a.y - size / 2.0, size, size, VERTEX_COLOR);
|
||||||
|
}
|
||||||
|
DrawLine(0, 0, 0, height, BLACK);
|
||||||
EndTextureMode();
|
EndTextureMode();
|
||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
|
|||||||
Reference in New Issue
Block a user