Browse Source

Mouse, constraints in cloth step now

master
Gitea 3 years ago
parent
commit
52de904d10
  1. 50
      src/app.cpp
  2. 3
      src/app.hpp
  3. 78
      src/cloth.cpp
  4. 4
      src/cloth.hpp
  5. 3
      src/main.cpp
  6. 14
      src/mouse.cpp
  7. 13
      src/mouse.hpp
  8. 4
      src/point.hpp
  9. 24
      src/window.cpp

50
src/app.cpp

@ -1,9 +1,11 @@
#include "app.hpp"
#include "cloth.hpp"
#include "mouse.hpp"
#include "window.hpp"
#include "vec.hpp"
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_keycode.h>
#include <SDL2/SDL_mouse.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_video.h>
@ -22,6 +24,7 @@ App* app_init(App_config conf) {
}
app->conf = conf;
app->mouse = new_mouse(Vec2{0, 0}, 30);
app->window = new_window(conf.win_name, conf.window_dimensions);
app->cloth = new_cloth(
conf.cloth_startpos,
@ -61,12 +64,44 @@ void app_handle_input(App* app) {
case SDLK_SPACE:
toggle_pause(app);
break;
}
case SDLK_LEFT:
if (app->conf.timestep >= 0.25) {
app->conf.timestep -= 0.25;
}
break;
case SDLK_RIGHT:
app->conf.timestep += 0.25;
break;
}
case SDL_MOUSEMOTION:
app->mouse->last_pos = app->mouse->pos;
app->mouse->pos = Vec2{
static_cast<unsigned int>(event.motion.x),
static_cast<unsigned int>(event.motion.y)
};
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) {
app->mouse->left_button_clicked = true;
}
break;
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT) {
app->mouse->left_button_clicked = false;
}
break;
}
}
}
void app_render(App* app) {
void app_render(App* app) {
SDL_RenderClear(app->window->renderer);
fill_screen(app->window, app->conf.background_color);
draw_cloth(
app->window, app->cloth,
@ -83,16 +118,19 @@ void app_update(App* app) {
int updated_window_h;
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};
if (app->cloth->constraint_bottom_right.x != (unsigned int) updated_window_w || app->cloth->constraint_bottom_right.y != (unsigned int) updated_window_h) {
app->cloth->constraint_bottom_right.x = app->window->dimensions.x;
app->cloth->constraint_bottom_right.y = 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);
cloth_step(app->cloth, app->mouse, app->conf.gravity, app->conf.timestep);
}
void destroy_app(App* app) {
destroy_mouse(app->mouse);
destroy_cloth(app->cloth);
destroy_window(app->window);
app->mouse = NULL;
app->cloth = NULL;
app->window = NULL;
app->is_running = false;

3
src/app.hpp

@ -1,5 +1,6 @@
#pragma once
#include "mouse.hpp"
#include "window.hpp"
#include "cloth.hpp"
#include <SDL2/SDL_render.h>
@ -13,6 +14,7 @@ struct App_config {
Vec2f gravity;
float efficiency_factor;
float friction_factor;
float timestep;
RGB background_color;
RGB point_color;
RGB point_selected_color;
@ -23,6 +25,7 @@ struct App {
bool is_running;
bool paused;
App_config conf;
Mouse* mouse;
Window* window;
Cloth* cloth;
};

78
src/cloth.cpp

@ -1,5 +1,7 @@
#include "cloth.hpp"
#include "connection.hpp"
#include "mouse.hpp"
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <vector>
@ -26,18 +28,12 @@ Cloth* new_cloth(
bool 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),
.pos = Vec2f{static_cast<float>(startpos.x + x), static_cast<float>(startpos.y + y)},
.mass = 10.0f,
.frozen = frozen_point,
.selected = false,
.radius = 2.5,
};
new_cloth->points.push_back(new_point);
@ -78,58 +74,58 @@ void destroy_cloth(Cloth* cloth) {
delete cloth;
}
// calculate forces and actually MOVE points
void cloth_step(Cloth* cloth, Vec2f gravity_vec, float timedelta) {
// calculate forces, move points and satisfy constraints
void cloth_step(Cloth* cloth, Mouse* mouse, Vec2f gravity_vec, float timedelta) {
for (Point* p : cloth->points) {
if (p->frozen) {
continue;
}
// 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;
}
// handle mouse
// ((x0 - x1)^2 + (y0 - y1)^2)^0.5
float distance_to_point = std::sqrt(pow(p->pos.x - mouse->pos.x, 2.0f)+pow(p->pos.y - mouse->pos.y, 2.0f));
if (distance_to_point <= mouse->cursor_radius_size) {
p->selected = true;
} 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;
p->selected = false;
}
if (p->selected && mouse->left_button_clicked) {
p->pos = Vec2f{(float) mouse->pos.x, (float) mouse->pos.y};
}
// calculate velocity
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;
}
}
p->pos.x += p->velocity.x;
p->pos.y += p->velocity.y;
// handle constraints, bounces
void satisfy_cloth_constraints(Cloth* cloth) {
for (Point* p : cloth->points) {
// now handle constraints
// bottom
if (p->y > cloth->constraint_bottom_right.y) {
p->y = cloth->constraint_bottom_right.y;
p->velocity.y = -p->velocity.y*cloth->efficiency_factor;
if (p->pos.y >= cloth->constraint_bottom_right.y) {
p->pos.y = cloth->constraint_bottom_right.y;
p->velocity.x = (p->velocity.x * cloth->friction_factor);
p->velocity.y = -p->velocity.y * cloth->efficiency_factor;
}
// right
if (p->x > cloth->constraint_bottom_right.x) {
p->x = cloth->constraint_bottom_right.x;
p->velocity.x = -p->velocity.x*cloth->efficiency_factor;
if (p->pos.x >= cloth->constraint_bottom_right.x) {
p->pos.x = cloth->constraint_bottom_right.x;
p->velocity.x = -p->velocity.x * cloth->efficiency_factor;
}
// left
if (p->x < cloth->constraint_top_left.x) {
p->x = cloth->constraint_top_left.x;
p->velocity.x = -p->velocity.x*cloth->efficiency_factor;
if (p->pos.x <= cloth->constraint_top_left.x) {
p->pos.x = cloth->constraint_top_left.x;
p->velocity.x = -p->velocity.x * cloth->efficiency_factor;
}
// up
if (p->y < cloth->constraint_top_left.y) {
p->y = cloth->constraint_top_left.y;
p->velocity.y = -p->velocity.y*cloth->efficiency_factor;
if (p->pos.y <= cloth->constraint_top_left.y) {
p->pos.y = cloth->constraint_top_left.y;
p->velocity.y = -p->velocity.y * cloth->efficiency_factor;
}
}
}

4
src/cloth.hpp

@ -1,5 +1,6 @@
#pragma once
#include "mouse.hpp"
#include "point.hpp"
#include "connection.hpp"
#include "vec.hpp"
@ -25,5 +26,4 @@ Cloth* new_cloth(
Vec2 constraint_top_left, Vec2 constraint_bottom_right
);
void destroy_cloth(Cloth* cloth);
void cloth_step(Cloth* cloth, Vec2f gravity_vec, float timedelta);
void satisfy_cloth_constraints(Cloth* cloth);
void cloth_step(Cloth* cloth, Mouse* mouse, Vec2f gravity_vec, float timedelta);

3
src/main.cpp

@ -68,8 +68,9 @@ int main(const int argc, char** argv) {
.cloth_startpos = Vec2{50, 50},
.cloth_dimensions = Vec2{400, 400},
.cloth_spacing = 20,
.gravity = Vec2f{0.65f, 0.45f},
.gravity = Vec2f{0.5f, 0.75f},
.efficiency_factor = 0.25f,
.timestep = 1.0f,
.background_color = RGB{205, 222, 242},
.point_color = RGB{2, 10, 1},
.point_selected_color = RGB{200, 40, 12},

14
src/mouse.cpp

@ -0,0 +1,14 @@
#include "mouse.hpp"
Mouse* new_mouse(Vec2 position, float cursor_size) {
return new Mouse{
.left_button_clicked = false,
.cursor_radius_size = cursor_size,
.pos = position,
.last_pos = position,
};
}
void destroy_mouse(Mouse* mouse) {
delete mouse;
}

13
src/mouse.hpp

@ -0,0 +1,13 @@
#pragma once
#include "vec.hpp"
struct Mouse {
bool left_button_clicked;
float cursor_radius_size;
Vec2 pos;
Vec2 last_pos;
};
Mouse* new_mouse(Vec2 position, float cursor_size);
void destroy_mouse(Mouse* mouse);

4
src/point.hpp

@ -4,10 +4,10 @@
#include "vec.hpp"
struct Point {
float x;
float y;
Vec2f pos;
float mass;
bool frozen;
bool selected;
float radius;
Vec2f velocity;
};

24
src/window.cpp

@ -60,9 +60,15 @@ void fill_screen(Window* window, RGB color) {
}
void draw_point(Window* window, Point point, RGB color) {
if (window->renderer != NULL) {
if (window->renderer != NULL) {
SDL_SetRenderDrawColor(window->renderer, color.r, color.g, color.b, 255);
SDL_RenderDrawPoint(window->renderer, (int) point.x, (int) point.y);
for (float angle = 0.0f; angle <= 6.283f; angle+=1.0f/point.radius ) {
SDL_RenderDrawPoint(
window->renderer,
point.pos.x+point.radius*cos(angle),
point.pos.y+point.radius*sin(angle)
);
}
}
}
@ -71,10 +77,10 @@ void draw_connection(Window* window, Connection connection, RGB color) {
SDL_SetRenderDrawColor(window->renderer, color.r, color.g, color.b, 255);
SDL_RenderDrawLine(
window->renderer,
(int) connection.p0.x,
(int) connection.p0.y,
(int) connection.p1.x,
(int) connection.p1.y
(int) connection.p0.pos.x,
(int) connection.p0.pos.y,
(int) connection.p1.pos.x,
(int) connection.p1.pos.y
);
}
}
@ -85,6 +91,10 @@ void draw_cloth(Window* window, Cloth* cloth, RGB point_color, RGB connection_co
}
for (const Point* point : cloth->points) {
draw_point(window, *point, point_color);
if (point->selected) {
draw_point(window, *point, selected_p_color);
} else {
draw_point(window, *point, point_color);
}
}
}
Loading…
Cancel
Save