Browse Source

Finally some physics

master
Gitea 3 years ago
parent
commit
7c68b04c11
  1. 19
      src/app.cpp
  2. 2
      src/app.hpp
  3. 77
      src/cloth.cpp
  4. 17
      src/cloth.hpp
  5. 11
      src/main.cpp
  6. 13
      src/point.hpp

19
src/app.cpp

@ -1,6 +1,7 @@
#include "app.hpp"
#include "cloth.hpp"
#include "window.hpp"
#include "vec.hpp"
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_keycode.h>
#include <SDL2/SDL_render.h>
@ -16,10 +17,20 @@ App* app_init(App_config conf) {
if (conf.window_dimensions.y <= 0) {
conf.window_dimensions.y = 500;
}
if (conf.efficiency_factor < 0 || conf.efficiency_factor > 1) {
conf.efficiency_factor = 0.6;
}
app->conf = conf;
app->window = new_window(conf.win_name, conf.window_dimensions);
app->cloth = new_cloth(conf.cloth_startpos, conf.cloth_dimensions, conf.cloth_spacing);
app->cloth = new_cloth(
conf.cloth_startpos,
conf.cloth_dimensions,
conf.cloth_spacing,
conf.efficiency_factor,
conf.friction_factor,
Vec2{0, 0}, Vec2{app->window->dimensions.x-5, app->window->dimensions.y-5}
);
if (app->window == NULL || app->cloth == NULL) {
return NULL;
@ -73,8 +84,10 @@ void app_update(App* app) {
SDL_GetWindowSize(app->window->sdl_win, &updated_window_w, &updated_window_h);
app->window->dimensions = Vec2{(unsigned int) updated_window_w, (unsigned int) updated_window_h};
compute_cloth_forces(app->cloth, app->conf.gravity);
satisfy_cloth_constraints(app->cloth, Vec2{0, 0}, Vec2{app->window->dimensions.x-5, app->window->dimensions.y-5});
app->cloth->constraint_bottom_right.x = app->window->dimensions.x;
app->cloth->constraint_bottom_right.y = app->window->dimensions.y-5;
cloth_step(app->cloth, app->conf.gravity, 1);
satisfy_cloth_constraints(app->cloth);
}
void destroy_app(App* app) {

2
src/app.hpp

@ -11,6 +11,8 @@ struct App_config {
Vec2 cloth_dimensions;
unsigned int cloth_spacing;
Vec2f gravity;
float efficiency_factor;
float friction_factor;
RGB background_color;
RGB point_color;
RGB point_selected_color;

77
src/cloth.cpp

@ -4,27 +4,37 @@
#include <cstdio>
#include <vector>
Cloth* new_cloth(Vec2 startpos, Vec2 dimensions, unsigned int spacing) {
Cloth* new_cloth(
Vec2 startpos,
Vec2 dimensions,
unsigned int spacing,
float efficiency_factor,
float friction_factor,
Vec2 constraint_top_left, Vec2 constraint_bottom_right
) {
Cloth* new_cloth = new Cloth;
new_cloth->efficiency_factor = efficiency_factor;
new_cloth->friction_factor = friction_factor;
new_cloth->startpos = startpos;
new_cloth->dimensions = dimensions;
new_cloth->constraint_top_left = constraint_top_left;
new_cloth->constraint_bottom_right = constraint_bottom_right;
new_cloth->points = std::vector<Point*>();
new_cloth->connections = std::vector<Connection*>();
bool frozen_point = false;
for (unsigned int y = 0; y < dimensions.y; y += spacing) {
if (y == 0) {
frozen_point = true;
} else {
frozen_point = false;
}
for (unsigned int y = 0; y < dimensions.y; y += spacing) {
for (unsigned int x = 0; x < dimensions.x; x += spacing) {
// if (y == 0 && x == new_cloth->dimensions.x/2) {
// frozen_point = true;
// } else {
// frozen_point = false;
// }
Point* new_point = new Point{
.x = static_cast<float>(startpos.x + x),
.y = static_cast<float>(startpos.y + y),
.prev_x = static_cast<float>(startpos.x + x),
.prev_y = static_cast<float>(startpos.y + y),
.mass = 10.0f,
.frozen = frozen_point,
.selected = false,
@ -68,37 +78,58 @@ void destroy_cloth(Cloth* cloth) {
delete cloth;
}
void compute_cloth_forces(Cloth* cloth, Vec2f gravity_vec) {
// calculate forces and actually MOVE points
void cloth_step(Cloth* cloth, Vec2f gravity_vec, float timedelta) {
for (Point* p : cloth->points) {
if (p->frozen) {
continue;
}
p->x += gravity_vec.x;
p->y += gravity_vec.y;
// calculate velocity
if (p->y == cloth->constraint_bottom_right.y) {
// if this point's x velocity is too small -> just stop it
// else -> handle friction
if (p->velocity.x <= 0.5) {
p->velocity.x = 0;
} else {
p->velocity.x = p->velocity.x*cloth->friction_factor * timedelta;
}
} else {
p->velocity.x = p->velocity.x+(gravity_vec.x/p->mass) * timedelta;
p->velocity.y = p->velocity.y+(gravity_vec.y/p->mass) * timedelta;
}
// move point
p->x += p->velocity.x;
p->y += p->velocity.y;
}
}
void satisfy_cloth_constraints(Cloth* cloth, Vec2 top_left, Vec2 bottom_right) {
// handle constraints, bounces
void satisfy_cloth_constraints(Cloth* cloth) {
for (Point* p : cloth->points) {
// bottom
if (p->y > bottom_right.y) {
p->y = bottom_right.y;
if (p->y > cloth->constraint_bottom_right.y) {
p->y = cloth->constraint_bottom_right.y;
p->velocity.y = -p->velocity.y*cloth->efficiency_factor;
}
// right
if (p->x > bottom_right.x) {
p->x = bottom_right.x;
if (p->x > cloth->constraint_bottom_right.x) {
p->x = cloth->constraint_bottom_right.x;
p->velocity.x = -p->velocity.x*cloth->efficiency_factor;
}
// left
if (p->x < top_left.x) {
p->x = top_left.x;
if (p->x < cloth->constraint_top_left.x) {
p->x = cloth->constraint_top_left.x;
p->velocity.x = -p->velocity.x*cloth->efficiency_factor;
}
// up
if (p->y < top_left.y) {
p->y = top_left.y;
if (p->y < cloth->constraint_top_left.y) {
p->y = cloth->constraint_top_left.y;
p->velocity.y = -p->velocity.y*cloth->efficiency_factor;
}
}
}

17
src/cloth.hpp

@ -6,13 +6,24 @@
#include <vector>
struct Cloth {
float efficiency_factor;
float friction_factor;
Vec2 startpos;
Vec2 dimensions;
Vec2 constraint_top_left;
Vec2 constraint_bottom_right;
std::vector<Point*> points;
std::vector<Connection*> connections;
};
Cloth* new_cloth(Vec2 startpos, Vec2 dimensions, unsigned int spacing);
Cloth* new_cloth(
Vec2 startpos,
Vec2 dimensions,
unsigned int spacing,
float efficiency_factor,
float friction_factor,
Vec2 constraint_top_left, Vec2 constraint_bottom_right
);
void destroy_cloth(Cloth* cloth);
void compute_cloth_forces(Cloth* cloth, Vec2f gravity_vec);
void satisfy_cloth_constraints(Cloth* cloth, Vec2 top_left, Vec2 bottom_right);
void cloth_step(Cloth* cloth, Vec2f gravity_vec, float timedelta);
void satisfy_cloth_constraints(Cloth* cloth);

11
src/main.cpp

@ -64,15 +64,16 @@ int main(const int argc, char** argv) {
App_config config = {
.win_name = window_name.c_str(),
.window_dimensions = Vec2{500, 500},
.window_dimensions = Vec2{800, 700},
.cloth_startpos = Vec2{50, 50},
.cloth_dimensions = Vec2{400, 400},
.cloth_spacing = 20,
.gravity = Vec2f{0.0f, 1.5f},
.background_color = RGB{80, 100, 255},
.point_color = RGB{10, 10, 10},
.gravity = Vec2f{0.65f, 0.45f},
.efficiency_factor = 0.25f,
.background_color = RGB{205, 222, 242},
.point_color = RGB{2, 10, 1},
.point_selected_color = RGB{200, 40, 12},
.connection_color = RGB{100, 100, 100},
.connection_color = RGB{48, 142, 31},
};
App* app = app_init(config);

13
src/point.hpp

@ -1,20 +1,13 @@
#pragma once
// struct Point {
// unsigned int x;
// unsigned int y;
// unsigned int prev_x;
// unsigned int prev_y;
// unsigned int mass;
// bool selected;
// };
#include "vec.hpp"
struct Point {
float x;
float y;
float prev_x;
float prev_y;
float mass;
bool frozen;
bool selected;
Vec2f velocity;
};
Loading…
Cancel
Save