Commit ba9f8584 authored by Caleb C. Sander's avatar Caleb C. Sander
Browse files

Rename types to _t

parent 1c7777b4
No related merge requests found
Showing with 250 additions and 237 deletions
+250 -237
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#define __BODY_H__ #define __BODY_H__
#include <stdbool.h> #include <stdbool.h>
#include "color.h" #include "color.h"
#include "list.h" #include "list.h"
#include "vector.h" #include "vector.h"
...@@ -13,13 +12,13 @@ ...@@ -13,13 +12,13 @@
* Bodies can accumulate forces and impulses during each tick. * Bodies can accumulate forces and impulses during each tick.
* Angular physics (i.e. torques) are not currently implemented. * Angular physics (i.e. torques) are not currently implemented.
*/ */
typedef struct body Body; typedef struct body body_t;
/** /**
* Initializes a body without any info. * Initializes a body without any info.
* Acts like body_init_with_info() where info and info_freer are NULL. * Acts like body_init_with_info() where info and info_freer are NULL.
*/ */
Body *body_init(List *shape, double mass, RGBColor color); body_t *body_init(list_t *shape, double mass, rgb_color_t color);
/** /**
* Allocates memory for a body with the given parameters. * Allocates memory for a body with the given parameters.
...@@ -27,15 +26,19 @@ Body *body_init(List *shape, double mass, RGBColor color); ...@@ -27,15 +26,19 @@ Body *body_init(List *shape, double mass, RGBColor color);
* Asserts that the mass is positive and that the required memory is allocated. * Asserts that the mass is positive and that the required memory is allocated.
* *
* @param shape a list of vectors describing the initial shape of the body * @param shape a list of vectors describing the initial shape of the body
* @param mass the mass of the body (if INFINITY, prevents the body from moving) * @param mass the mass of the body (if INFINITY, stops the body from moving)
* @param color the color of the body, used to draw it on the screen * @param color the color of the body, used to draw it on the screen
* @param info additional information to associate with the body, * @param info additional information to associate with the body,
* e.g. its type if the scene has multiple types of bodies * e.g. its type if the scene has multiple types of bodies
* @param info_freer if non-NULL, a function call on the info to free it * @param info_freer if non-NULL, a function call on the info to free it
* @return a pointer to the newly allocated body * @return a pointer to the newly allocated body
*/ */
Body *body_init_with_info( body_t *body_init_with_info(
List *shape, double mass, RGBColor color, void *info, FreeFunc info_freer list_t *shape,
double mass,
rgb_color_t color,
void *info,
free_func_t info_freer
); );
/** /**
...@@ -43,7 +46,7 @@ Body *body_init_with_info( ...@@ -43,7 +46,7 @@ Body *body_init_with_info(
* *
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
*/ */
void body_free(Body *body); void body_free(body_t *body);
/** /**
* Gets the current shape of a body. * Gets the current shape of a body.
...@@ -52,7 +55,7 @@ void body_free(Body *body); ...@@ -52,7 +55,7 @@ void body_free(Body *body);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @return the polygon describing the body's current position * @return the polygon describing the body's current position
*/ */
List *body_get_shape(Body *body); list_t *body_get_shape(body_t *body);
/** /**
* Gets the current center of mass of a body. * Gets the current center of mass of a body.
...@@ -63,7 +66,7 @@ List *body_get_shape(Body *body); ...@@ -63,7 +66,7 @@ List *body_get_shape(Body *body);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @return the body's center of mass * @return the body's center of mass
*/ */
Vector body_get_centroid(Body *body); vector_t body_get_centroid(body_t *body);
/** /**
* Gets the current velocity of a body. * Gets the current velocity of a body.
...@@ -71,7 +74,7 @@ Vector body_get_centroid(Body *body); ...@@ -71,7 +74,7 @@ Vector body_get_centroid(Body *body);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @return the body's velocity vector * @return the body's velocity vector
*/ */
Vector body_get_velocity(Body *body); vector_t body_get_velocity(body_t *body);
/** /**
* Gets the mass of a body. * Gets the mass of a body.
...@@ -79,7 +82,7 @@ Vector body_get_velocity(Body *body); ...@@ -79,7 +82,7 @@ Vector body_get_velocity(Body *body);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @return the mass passed to body_init(), which must be greater than 0 * @return the mass passed to body_init(), which must be greater than 0
*/ */
double body_get_mass(Body *body); double body_get_mass(body_t *body);
/** /**
* Gets the display color of a body. * Gets the display color of a body.
...@@ -87,7 +90,7 @@ double body_get_mass(Body *body); ...@@ -87,7 +90,7 @@ double body_get_mass(Body *body);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @return the color passed to body_init(), as an (R, G, B) tuple * @return the color passed to body_init(), as an (R, G, B) tuple
*/ */
RGBColor body_get_color(Body *body); rgb_color_t body_get_color(body_t *body);
/** /**
* Gets the information associated with a body. * Gets the information associated with a body.
...@@ -95,7 +98,7 @@ RGBColor body_get_color(Body *body); ...@@ -95,7 +98,7 @@ RGBColor body_get_color(Body *body);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @return the info passed to body_init() * @return the info passed to body_init()
*/ */
void *body_get_info(Body *body); void *body_get_info(body_t *body);
/** /**
* Translates a body to a new position. * Translates a body to a new position.
...@@ -104,7 +107,7 @@ void *body_get_info(Body *body); ...@@ -104,7 +107,7 @@ void *body_get_info(Body *body);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @param x the body's new centroid * @param x the body's new centroid
*/ */
void body_set_centroid(Body *body, Vector x); void body_set_centroid(body_t *body, vector_t x);
/** /**
* Changes a body's velocity (the time-derivative of its position). * Changes a body's velocity (the time-derivative of its position).
...@@ -112,7 +115,7 @@ void body_set_centroid(Body *body, Vector x); ...@@ -112,7 +115,7 @@ void body_set_centroid(Body *body, Vector x);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @param v the body's new velocity * @param v the body's new velocity
*/ */
void body_set_velocity(Body *body, Vector v); void body_set_velocity(body_t *body, vector_t v);
/** /**
* Changes a body's orientation in the plane. * Changes a body's orientation in the plane.
...@@ -122,7 +125,7 @@ void body_set_velocity(Body *body, Vector v); ...@@ -122,7 +125,7 @@ void body_set_velocity(Body *body, Vector v);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @param angle the body's new angle in radians. Positive is counterclockwise. * @param angle the body's new angle in radians. Positive is counterclockwise.
*/ */
void body_set_rotation(Body *body, double angle); void body_set_rotation(body_t *body, double angle);
/** /**
* Applies a force to a body over the current tick. * Applies a force to a body over the current tick.
...@@ -132,7 +135,7 @@ void body_set_rotation(Body *body, double angle); ...@@ -132,7 +135,7 @@ void body_set_rotation(Body *body, double angle);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @param force the force vector to apply * @param force the force vector to apply
*/ */
void body_add_force(Body *body, Vector force); void body_add_force(body_t *body, vector_t force);
/** /**
* Applies an impulse to a body. * Applies an impulse to a body.
...@@ -144,7 +147,7 @@ void body_add_force(Body *body, Vector force); ...@@ -144,7 +147,7 @@ void body_add_force(Body *body, Vector force);
* @param body a pointer to a body returned from body_init() * @param body a pointer to a body returned from body_init()
* @param impulse the impulse vector to apply * @param impulse the impulse vector to apply
*/ */
void body_add_impulse(Body *body, Vector impulse); void body_add_impulse(body_t *body, vector_t impulse);
/** /**
* Updates the body after a given time interval has elapsed. * Updates the body after a given time interval has elapsed.
...@@ -157,7 +160,7 @@ void body_add_impulse(Body *body, Vector impulse); ...@@ -157,7 +160,7 @@ void body_add_impulse(Body *body, Vector impulse);
* @param body the body to tick * @param body the body to tick
* @param dt the number of seconds elapsed since the last tick * @param dt the number of seconds elapsed since the last tick
*/ */
void body_tick(Body *body, double dt); void body_tick(body_t *body, double dt);
/** /**
* Marks a body for removal--future calls to body_is_removed() will return true. * Marks a body for removal--future calls to body_is_removed() will return true.
...@@ -166,7 +169,7 @@ void body_tick(Body *body, double dt); ...@@ -166,7 +169,7 @@ void body_tick(Body *body, double dt);
* *
* @param body the body to mark for removal * @param body the body to mark for removal
*/ */
void body_remove(Body *body); void body_remove(body_t *body);
/** /**
* Returns whether a body has been marked for removal. * Returns whether a body has been marked for removal.
...@@ -176,6 +179,6 @@ void body_remove(Body *body); ...@@ -176,6 +179,6 @@ void body_remove(Body *body);
* @param body the body to check * @param body the body to check
* @return whether body_remove() has been called on the body * @return whether body_remove() has been called on the body
*/ */
bool body_is_removed(Body *body); bool body_is_removed(body_t *body);
#endif // #ifndef __BODY_H__ #endif // #ifndef __BODY_H__
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include <stdbool.h> #include <stdbool.h>
#include "list.h" #include "list.h"
#include "vector.h"
/** /**
* Determines whether two convex polygons intersect. * Determines whether two convex polygons intersect.
...@@ -15,6 +14,6 @@ ...@@ -15,6 +14,6 @@
* @param shape2 the second shape * @param shape2 the second shape
* @return whether the shapes are colliding * @return whether the shapes are colliding
*/ */
bool find_collision(List *shape1, List *shape2); bool find_collision(list_t *shape1, list_t *shape2);
#endif // #ifndef __COLLISION_H__ #endif // #ifndef __COLLISION_H__
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
#include "scene.h" #include "scene.h"
/** /**
* Adds a Newtonian gravitational force between two bodies in a scene. * Adds a force creator to a scene that applies gravity between two bodies.
* The force creator will be called each tick
* to compute the Newtonian gravitational force between the bodies.
* See https://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation#Vector_form. * See https://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation#Vector_form.
* The force should not be applied when the bodies are very close, * The force should not be applied when the bodies are very close,
* because its magnitude blows up as the distance between the bodies goes to 0. * because its magnitude blows up as the distance between the bodies goes to 0.
...@@ -14,10 +16,12 @@ ...@@ -14,10 +16,12 @@
* @param body1 the first body * @param body1 the first body
* @param body2 the second body * @param body2 the second body
*/ */
void create_newtonian_gravity(Scene *scene, double G, Body *body1, Body *body2); void create_newtonian_gravity(scene_t *scene, double G, body_t *body1, body_t *body2);
/** /**
* Adds a Hooke's-Law spring force between two bodies in a scene. * Adds a force creator to a scene that acts like a spring between two bodies.
* The force creator will be called each tick
* to compute the Hooke's-Law spring force between the bodies.
* See https://en.wikipedia.org/wiki/Hooke%27s_law. * See https://en.wikipedia.org/wiki/Hooke%27s_law.
* *
* @param scene the scene containing the bodies * @param scene the scene containing the bodies
...@@ -25,10 +29,12 @@ void create_newtonian_gravity(Scene *scene, double G, Body *body1, Body *body2); ...@@ -25,10 +29,12 @@ void create_newtonian_gravity(Scene *scene, double G, Body *body1, Body *body2);
* @param body1 the first body * @param body1 the first body
* @param body2 the second body * @param body2 the second body
*/ */
void create_spring(Scene *scene, double k, Body *body1, Body *body2); void create_spring(scene_t *scene, double k, body_t *body1, body_t *body2);
/** /**
* Adds a drag force on a body proportional to its velocity. * Adds a force creator to a scene that applies a drag force on a body.
* The force creator will be called each tick
* to compute the drag force on the body proportional to its velocity.
* The force points opposite the body's velocity. * The force points opposite the body's velocity.
* *
* @param scene the scene containing the bodies * @param scene the scene containing the bodies
...@@ -36,16 +42,16 @@ void create_spring(Scene *scene, double k, Body *body1, Body *body2); ...@@ -36,16 +42,16 @@ void create_spring(Scene *scene, double k, Body *body1, Body *body2);
* (higher gamma means more drag) * (higher gamma means more drag)
* @param body the body to slow down * @param body the body to slow down
*/ */
void create_drag(Scene *scene, double gamma, Body *body); void create_drag(scene_t *scene, double gamma, body_t *body);
/** /**
* Adds a ForceCreator to a scene that destroys two bodies when they collide. * Adds a force creator to a scene that destroys two bodies when they collide.
* The bodies should be destroyed by calling body_remove(). * The bodies should be destroyed by calling body_remove().
* *
* @param scene the scene containing the bodies * @param scene the scene containing the bodies
* @param body1 the first body * @param body1 the first body
* @param body2 the second body * @param body2 the second body
*/ */
void create_destructive_collision(Scene *scene, Body *body1, Body *body2); void create_destructive_collision(scene_t *scene, body_t *body1, body_t *body2);
#endif // #ifndef __FORCES_H__ #endif // #ifndef __FORCES_H__
#ifndef __SCENE_H__ #ifndef __SCENE_H__
#define __SCENE_H__ #define __SCENE_H__
#include <stdbool.h>
#include "body.h" #include "body.h"
#include "list.h" #include "list.h"
...@@ -10,14 +9,14 @@ ...@@ -10,14 +9,14 @@
* The scene automatically resizes to store * The scene automatically resizes to store
* arbitrarily many bodies and force creators. * arbitrarily many bodies and force creators.
*/ */
typedef struct scene Scene; typedef struct scene scene_t;
/** /**
* A function which adds some forces or impulses to bodies, * A function which adds some forces or impulses to bodies,
* e.g. from collisions, gravity, or spring forces. * e.g. from collisions, gravity, or spring forces.
* Takes in an auxiliary value that can store parameters or state. * Takes in an auxiliary value that can store parameters or state.
*/ */
typedef void (*ForceCreator)(void *aux); typedef void (*force_creator_t)(void *aux);
/** /**
* Allocates memory for an empty scene. * Allocates memory for an empty scene.
...@@ -26,7 +25,7 @@ typedef void (*ForceCreator)(void *aux); ...@@ -26,7 +25,7 @@ typedef void (*ForceCreator)(void *aux);
* *
* @return the new scene * @return the new scene
*/ */
Scene *scene_init(void); scene_t *scene_init(void);
/** /**
* Releases memory allocated for a given scene * Releases memory allocated for a given scene
...@@ -34,7 +33,7 @@ Scene *scene_init(void); ...@@ -34,7 +33,7 @@ Scene *scene_init(void);
* *
* @param scene a pointer to a scene returned from scene_init() * @param scene a pointer to a scene returned from scene_init()
*/ */
void scene_free(Scene *scene); void scene_free(scene_t *scene);
/** /**
* Gets the number of bodies in a given scene. * Gets the number of bodies in a given scene.
...@@ -42,7 +41,7 @@ void scene_free(Scene *scene); ...@@ -42,7 +41,7 @@ void scene_free(Scene *scene);
* @param scene a pointer to a scene returned from scene_init() * @param scene a pointer to a scene returned from scene_init()
* @return the number of bodies added with scene_add_body() * @return the number of bodies added with scene_add_body()
*/ */
size_t scene_bodies(Scene *scene); size_t scene_bodies(scene_t *scene);
/** /**
* Gets the body at a given index in a scene. * Gets the body at a given index in a scene.
...@@ -52,7 +51,7 @@ size_t scene_bodies(Scene *scene); ...@@ -52,7 +51,7 @@ size_t scene_bodies(Scene *scene);
* @param index the index of the body in the scene (starting at 0) * @param index the index of the body in the scene (starting at 0)
* @return a pointer to the body at the given index * @return a pointer to the body at the given index
*/ */
Body *scene_get_body(Scene *scene, size_t index); body_t *scene_get_body(scene_t *scene, size_t index);
/** /**
* Adds a body to a scene. * Adds a body to a scene.
...@@ -60,7 +59,7 @@ Body *scene_get_body(Scene *scene, size_t index); ...@@ -60,7 +59,7 @@ Body *scene_get_body(Scene *scene, size_t index);
* @param scene a pointer to a scene returned from scene_init() * @param scene a pointer to a scene returned from scene_init()
* @param body a pointer to the body to add to the scene * @param body a pointer to the body to add to the scene
*/ */
void scene_add_body(Scene *scene, Body *body); void scene_add_body(scene_t *scene, body_t *body);
/** /**
* @deprecated Use body_remove() instead * @deprecated Use body_remove() instead
...@@ -71,14 +70,17 @@ void scene_add_body(Scene *scene, Body *body); ...@@ -71,14 +70,17 @@ void scene_add_body(Scene *scene, Body *body);
* @param scene a pointer to a scene returned from scene_init() * @param scene a pointer to a scene returned from scene_init()
* @param index the index of the body in the scene (starting at 0) * @param index the index of the body in the scene (starting at 0)
*/ */
void scene_remove_body(Scene *scene, size_t index); void scene_remove_body(scene_t *scene, size_t index);
/** /**
* @deprecated Use scene_add_bodies_force_creator() instead * @deprecated Use scene_add_bodies_force_creator() instead
* so the scene knows which bodies the force creator depends on * so the scene knows which bodies the force creator depends on
*/ */
void scene_add_force_creator( void scene_add_force_creator(
Scene *scene, ForceCreator forcer, void *aux, FreeFunc freer scene_t *scene,
force_creator_t forcer,
void *aux,
free_func_t freer
); );
/** /**
...@@ -97,7 +99,11 @@ void scene_add_force_creator( ...@@ -97,7 +99,11 @@ void scene_add_force_creator(
* @param freer if non-NULL, a function to call in order to free aux * @param freer if non-NULL, a function to call in order to free aux
*/ */
void scene_add_bodies_force_creator( void scene_add_bodies_force_creator(
Scene *scene, ForceCreator forcer, void *aux, List *bodies, FreeFunc freer scene_t *scene,
force_creator_t forcer,
void *aux,
list_t *bodies,
free_func_t freer
); );
/** /**
...@@ -110,6 +116,6 @@ void scene_add_bodies_force_creator( ...@@ -110,6 +116,6 @@ void scene_add_bodies_force_creator(
* @param scene a pointer to a scene returned from scene_init() * @param scene a pointer to a scene returned from scene_init()
* @param dt the time elapsed since the last tick, in seconds * @param dt the time elapsed since the last tick, in seconds
*/ */
void scene_tick(Scene *scene, double dt); void scene_tick(scene_t *scene, double dt);
#endif // #ifndef __SCENE_H__ #endif // #ifndef __SCENE_H__
...@@ -5,23 +5,23 @@ ...@@ -5,23 +5,23 @@
#include <stdlib.h> #include <stdlib.h>
void test_body_init() { void test_body_init() {
Vector v[] = {{1, 1}, {2, 1}, {2, 2}, {1, 2}}; vector_t v[] = {{1, 1}, {2, 1}, {2, 2}, {1, 2}};
const size_t VERTICES = sizeof(v) / sizeof(*v); const size_t VERTICES = sizeof(v) / sizeof(*v);
List *shape = list_init(0, free); list_t *shape = list_init(0, free);
for (size_t i = 0; i < VERTICES; i++) { for (size_t i = 0; i < VERTICES; i++) {
Vector *list_v = malloc(sizeof(*list_v)); vector_t *list_v = malloc(sizeof(*list_v));
*list_v = v[i]; *list_v = v[i];
list_add(shape, list_v); list_add(shape, list_v);
} }
RGBColor color = {0, 0.5, 1}; rgb_color_t color = {0, 0.5, 1};
Body *body = body_init(shape, 3, color); body_t *body = body_init(shape, 3, color);
List *shape2 = body_get_shape(body); list_t *shape2 = body_get_shape(body);
assert(list_size(shape2) == VERTICES); assert(list_size(shape2) == VERTICES);
for (size_t i = 0; i < VERTICES; i++) { for (size_t i = 0; i < VERTICES; i++) {
assert(vec_isclose(*(Vector *) list_get(shape2, i), v[i])); assert(vec_isclose(*(vector_t *) list_get(shape2, i), v[i]));
} }
list_free(shape2); list_free(shape2);
assert(vec_isclose(body_get_centroid(body), (Vector) {1.5, 1.5})); assert(vec_isclose(body_get_centroid(body), (vector_t) {1.5, 1.5}));
assert(vec_equal(body_get_velocity(body), VEC_ZERO)); assert(vec_equal(body_get_velocity(body), VEC_ZERO));
assert(body_get_color(body).r == color.r); assert(body_get_color(body).r == color.r);
assert(body_get_color(body).g == color.g); assert(body_get_color(body).g == color.g);
...@@ -31,65 +31,65 @@ void test_body_init() { ...@@ -31,65 +31,65 @@ void test_body_init() {
} }
void test_body_setters() { void test_body_setters() {
List *shape = list_init(3, free); list_t *shape = list_init(3, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = (Vector) {+1, 0}; *v = (vector_t) {+1, 0};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {0, +1}; *v = (vector_t) {0, +1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-1, 0}; *v = (vector_t) {-1, 0};
list_add(shape, v); list_add(shape, v);
Body *body = body_init(shape, 1, (RGBColor) {0, 0, 0}); body_t *body = body_init(shape, 1, (rgb_color_t) {0, 0, 0});
body_set_velocity(body, (Vector) {+5, -5}); body_set_velocity(body, (vector_t) {+5, -5});
assert(vec_equal(body_get_velocity(body), (Vector) {+5, -5})); assert(vec_equal(body_get_velocity(body), (vector_t) {+5, -5}));
assert(vec_isclose(body_get_centroid(body), (Vector) {0, 1.0 / 3.0})); assert(vec_isclose(body_get_centroid(body), (vector_t) {0, 1.0 / 3.0}));
body_set_centroid(body, (Vector) {1, 2}); body_set_centroid(body, (vector_t) {1, 2});
assert(vec_isclose(body_get_centroid(body), (Vector) {1, 2})); assert(vec_isclose(body_get_centroid(body), (vector_t) {1, 2}));
shape = body_get_shape(body); shape = body_get_shape(body);
assert(list_size(shape) == 3); assert(list_size(shape) == 3);
assert(vec_isclose(*(Vector *) list_get(shape, 0), (Vector) {2, 5.0 / 3.0})); assert(vec_isclose(*(vector_t *) list_get(shape, 0), (vector_t) {2, 5.0 / 3.0}));
assert(vec_isclose(*(Vector *) list_get(shape, 1), (Vector) {1, 8.0 / 3.0})); assert(vec_isclose(*(vector_t *) list_get(shape, 1), (vector_t) {1, 8.0 / 3.0}));
assert(vec_isclose(*(Vector *) list_get(shape, 2), (Vector) {0, 5.0 / 3.0})); assert(vec_isclose(*(vector_t *) list_get(shape, 2), (vector_t) {0, 5.0 / 3.0}));
list_free(shape); list_free(shape);
body_set_rotation(body, M_PI / 2); body_set_rotation(body, M_PI / 2);
assert(vec_isclose(body_get_centroid(body), (Vector) {1, 2})); assert(vec_isclose(body_get_centroid(body), (vector_t) {1, 2}));
shape = body_get_shape(body); shape = body_get_shape(body);
assert(list_size(shape) == 3); assert(list_size(shape) == 3);
assert(vec_isclose(*(Vector *) list_get(shape, 0), (Vector) {4.0 / 3.0, 3})); assert(vec_isclose(*(vector_t *) list_get(shape, 0), (vector_t) {4.0 / 3.0, 3}));
assert(vec_isclose(*(Vector *) list_get(shape, 1), (Vector) {1.0 / 3.0, 2})); assert(vec_isclose(*(vector_t *) list_get(shape, 1), (vector_t) {1.0 / 3.0, 2}));
assert(vec_isclose(*(Vector *) list_get(shape, 2), (Vector) {4.0 / 3.0, 1})); assert(vec_isclose(*(vector_t *) list_get(shape, 2), (vector_t) {4.0 / 3.0, 1}));
list_free(shape); list_free(shape);
body_set_centroid(body, (Vector) {3, 4}); body_set_centroid(body, (vector_t) {3, 4});
assert(vec_isclose(body_get_centroid(body), (Vector) {3, 4})); assert(vec_isclose(body_get_centroid(body), (vector_t) {3, 4}));
shape = body_get_shape(body); shape = body_get_shape(body);
assert(list_size(shape) == 3); assert(list_size(shape) == 3);
assert(vec_isclose(*(Vector *) list_get(shape, 0), (Vector) {10.0 / 3.0, 5})); assert(vec_isclose(*(vector_t *) list_get(shape, 0), (vector_t) {10.0 / 3.0, 5}));
assert(vec_isclose(*(Vector *) list_get(shape, 1), (Vector) {7.0 / 3.0, 4})); assert(vec_isclose(*(vector_t *) list_get(shape, 1), (vector_t) {7.0 / 3.0, 4}));
assert(vec_isclose(*(Vector *) list_get(shape, 2), (Vector) {10.0 / 3.0, 3})); assert(vec_isclose(*(vector_t *) list_get(shape, 2), (vector_t) {10.0 / 3.0, 3}));
list_free(shape); list_free(shape);
body_free(body); body_free(body);
} }
void test_body_tick() { void test_body_tick() {
const Vector A = {1, 2}; const vector_t A = {1, 2};
const double DT = 1e-6; const double DT = 1e-6;
const int STEPS = 1000000; const int STEPS = 1000000;
List *shape = list_init(4, free); list_t *shape = list_init(4, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
v->x = v->y = -1; v->x = v->y = -1;
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {+1, -1}; *v = (vector_t) {+1, -1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
v->x = v->y = +1; v->x = v->y = +1;
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-1, +1}; *v = (vector_t) {-1, +1};
list_add(shape, v); list_add(shape, v);
Body *body = body_init(shape, 1, (RGBColor) {0, 0, 0}); body_t *body = body_init(shape, 1, (rgb_color_t) {0, 0, 0});
// Apply constant acceleration and ensure position is (a / 2) * t ** 2 // Apply constant acceleration and ensure position is (a / 2) * t ** 2
for (int i = 0; i < STEPS; i++) { for (int i = 0; i < STEPS; i++) {
...@@ -99,66 +99,66 @@ void test_body_tick() { ...@@ -99,66 +99,66 @@ void test_body_tick() {
body_tick(body, DT); body_tick(body, DT);
} }
double t = STEPS * DT; double t = STEPS * DT;
Vector new_x = vec_multiply(t * t / 2, A); vector_t new_x = vec_multiply(t * t / 2, A);
shape = body_get_shape(body); shape = body_get_shape(body);
assert(vec_isclose(*(Vector *) list_get(shape, 0), vec_add((Vector) {-1, -1}, new_x))); assert(vec_isclose(*(vector_t *) list_get(shape, 0), vec_add((vector_t) {-1, -1}, new_x)));
assert(vec_isclose(*(Vector *) list_get(shape, 1), vec_add((Vector) {+1, -1}, new_x))); assert(vec_isclose(*(vector_t *) list_get(shape, 1), vec_add((vector_t) {+1, -1}, new_x)));
assert(vec_isclose(*(Vector *) list_get(shape, 2), vec_add((Vector) {+1, +1}, new_x))); assert(vec_isclose(*(vector_t *) list_get(shape, 2), vec_add((vector_t) {+1, +1}, new_x)));
assert(vec_isclose(*(Vector *) list_get(shape, 3), vec_add((Vector) {-1, +1}, new_x))); assert(vec_isclose(*(vector_t *) list_get(shape, 3), vec_add((vector_t) {-1, +1}, new_x)));
list_free(shape); list_free(shape);
body_free(body); body_free(body);
} }
void test_infinite_mass() { void test_infinite_mass() {
List *shape = list_init(10, free); list_t *shape = list_init(10, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = VEC_ZERO; *v = VEC_ZERO;
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {+1, 0}; *v = (vector_t) {+1, 0};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {+1, +1}; *v = (vector_t) {+1, +1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {0, +1}; *v = (vector_t) {0, +1};
list_add(shape, v); list_add(shape, v);
Body *body = body_init(shape, INFINITY, (RGBColor) {0, 0, 0}); body_t *body = body_init(shape, INFINITY, (rgb_color_t) {0, 0, 0});
body_set_velocity(body, (Vector) {2, 3}); body_set_velocity(body, (vector_t) {2, 3});
assert(body_get_mass(body) == INFINITY); assert(body_get_mass(body) == INFINITY);
body_add_force(body, (Vector) {1, 1}); body_add_force(body, (vector_t) {1, 1});
body_tick(body, 1.0); body_tick(body, 1.0);
assert(vec_equal(body_get_velocity(body), (Vector) {2, 3})); assert(vec_equal(body_get_velocity(body), (vector_t) {2, 3}));
assert(vec_isclose(body_get_centroid(body), (Vector) {2.5, 3.5})); assert(vec_isclose(body_get_centroid(body), (vector_t) {2.5, 3.5}));
body_free(body); body_free(body);
} }
void test_forces() { void test_forces() {
const double MASS = 10; const double MASS = 10;
const double DT = 0.1; const double DT = 0.1;
List *shape = list_init(3, free); list_t *shape = list_init(3, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = (Vector) {+1, 0}; *v = (vector_t) {+1, 0};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {0, +1}; *v = (vector_t) {0, +1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-1, 0}; *v = (vector_t) {-1, 0};
list_add(shape, v); list_add(shape, v);
Body *body = body_init(shape, MASS, (RGBColor) {0, 0, 0}); body_t *body = body_init(shape, MASS, (rgb_color_t) {0, 0, 0});
body_set_centroid(body, VEC_ZERO); body_set_centroid(body, VEC_ZERO);
Vector old_velocity = {1, -2}; vector_t old_velocity = {1, -2};
body_set_velocity(body, old_velocity); body_set_velocity(body, old_velocity);
body_add_force(body, (Vector) {MASS * 3, MASS * 4}); body_add_force(body, (vector_t) {MASS * 3, MASS * 4});
body_add_impulse(body, (Vector) {MASS * 10, MASS * 5}); body_add_impulse(body, (vector_t) {MASS * 10, MASS * 5});
body_add_force(body, (Vector) {MASS * 3, MASS * 4}); body_add_force(body, (vector_t) {MASS * 3, MASS * 4});
body_tick(body, DT); body_tick(body, DT);
Vector new_velocity = vector_t new_velocity =
vec_add(old_velocity, (Vector) {10 + 6 * DT, 5 + 8 * DT}); vec_add(old_velocity, (vector_t) {10 + 6 * DT, 5 + 8 * DT});
assert(vec_isclose(body_get_velocity(body), new_velocity)); assert(vec_isclose(body_get_velocity(body), new_velocity));
Vector new_centroid = vector_t new_centroid =
vec_multiply(DT / 2.0, vec_add(old_velocity, new_velocity)); vec_multiply(DT / 2, vec_add(old_velocity, new_velocity));
assert(vec_isclose(body_get_centroid(body), new_centroid)); assert(vec_isclose(body_get_centroid(body), new_centroid));
body_tick(body, DT); body_tick(body, DT);
assert(vec_isclose( assert(vec_isclose(
...@@ -169,17 +169,17 @@ void test_forces() { ...@@ -169,17 +169,17 @@ void test_forces() {
} }
void test_body_remove() { void test_body_remove() {
List *shape = list_init(3, free); list_t *shape = list_init(3, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = (Vector) {+1, 0}; *v = (vector_t) {+1, 0};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {0, +1}; *v = (vector_t) {0, +1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-1, 0}; *v = (vector_t) {-1, 0};
list_add(shape, v); list_add(shape, v);
Body *body = body_init(shape, 1, (RGBColor) {0, 0, 0}); body_t *body = body_init(shape, 1, (rgb_color_t) {0, 0, 0});
assert(!body_is_removed(body)); assert(!body_is_removed(body));
body_remove(body); body_remove(body);
assert(body_is_removed(body)); assert(body_is_removed(body));
...@@ -189,36 +189,36 @@ void test_body_remove() { ...@@ -189,36 +189,36 @@ void test_body_remove() {
} }
void test_body_info() { void test_body_info() {
List *shape = list_init(3, free); list_t *shape = list_init(3, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = (Vector) {+1, 0}; *v = (vector_t) {+1, 0};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {0, +1}; *v = (vector_t) {0, +1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-1, 0}; *v = (vector_t) {-1, 0};
list_add(shape, v); list_add(shape, v);
int *info = malloc(sizeof(*info)); int *info = malloc(sizeof(*info));
*info = 123; *info = 123;
Body *body = body_init_with_info(shape, 1, (RGBColor) {0, 0, 0}, info, NULL); body_t *body = body_init_with_info(shape, 1, (rgb_color_t) {0, 0, 0}, info, NULL);
assert(*(int *) body_get_info(body) == 123); assert(*(int *) body_get_info(body) == 123);
body_free(body); body_free(body);
free(info); free(info);
} }
void test_body_info_freer() { void test_body_info_freer() {
List *shape = list_init(3, free); list_t *shape = list_init(3, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = (Vector) {+1, 0}; *v = (vector_t) {+1, 0};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {0, +1}; *v = (vector_t) {0, +1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-1, 0}; *v = (vector_t) {-1, 0};
list_add(shape, v); list_add(shape, v);
List *info = list_init(3, free); list_t *info = list_init(3, free);
int *info_elem = malloc(sizeof(*info_elem)); int *info_elem = malloc(sizeof(*info_elem));
*info_elem = 10; *info_elem = 10;
list_add(info, info_elem); list_add(info, info_elem);
...@@ -228,8 +228,12 @@ void test_body_info_freer() { ...@@ -228,8 +228,12 @@ void test_body_info_freer() {
info_elem = malloc(sizeof(*info_elem)); info_elem = malloc(sizeof(*info_elem));
*info_elem = 30; *info_elem = 30;
list_add(info, info_elem); list_add(info, info_elem);
Body *body = body_init_with_info( body_t *body = body_init_with_info(
shape, 1, (RGBColor) {0, 0, 0}, info, (FreeFunc) list_free shape,
1,
(rgb_color_t) {0, 0, 0},
info,
(free_func_t) list_free
); );
assert(*(int *) list_get(body_get_info(body), 0) == 10); assert(*(int *) list_get(body_get_info(body), 0) == 10);
assert(*(int *) list_get(body_get_info(body), 1) == 20); assert(*(int *) list_get(body_get_info(body), 1) == 20);
...@@ -256,5 +260,4 @@ int main(int argc, char *argv[]) { ...@@ -256,5 +260,4 @@ int main(int argc, char *argv[]) {
DO_TEST(test_body_info_freer) DO_TEST(test_body_info_freer)
puts("body_test PASS"); puts("body_test PASS");
return 0;
} }
...@@ -4,19 +4,19 @@ ...@@ -4,19 +4,19 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
List *make_shape() { list_t *make_shape() {
List *shape = list_init(4, free); list_t *shape = list_init(4, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = (Vector) {-1, -1}; *v = (vector_t) {-1, -1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {+1, -1}; *v = (vector_t) {+1, -1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {+1, +1}; *v = (vector_t) {+1, +1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-1, +1}; *v = (vector_t) {-1, +1};
list_add(shape, v); list_add(shape, v);
return shape; return shape;
} }
...@@ -28,29 +28,30 @@ void test_spring_sinusoid() { ...@@ -28,29 +28,30 @@ void test_spring_sinusoid() {
const double A = 3; const double A = 3;
const double DT = 1e-6; const double DT = 1e-6;
const int STEPS = 1000000; const int STEPS = 1000000;
Scene *scene = scene_init(); scene_t *scene = scene_init();
Body *mass = body_init(make_shape(), M, (RGBColor) {0, 0, 0}); body_t *mass = body_init(make_shape(), M, (rgb_color_t) {0, 0, 0});
body_set_centroid(mass, (Vector) {A, 0}); body_set_centroid(mass, (vector_t) {A, 0});
scene_add_body(scene, mass); scene_add_body(scene, mass);
Body *anchor = body_init(make_shape(), INFINITY, (RGBColor) {0, 0, 0}); body_t *anchor = body_init(make_shape(), INFINITY, (rgb_color_t) {0, 0, 0});
scene_add_body(scene, anchor); scene_add_body(scene, anchor);
create_spring(scene, K, mass, anchor); create_spring(scene, K, mass, anchor);
for (int i = 0; i < STEPS; i++) { for (int i = 0; i < STEPS; i++) {
assert(vec_isclose( assert(vec_isclose(
body_get_centroid(mass), body_get_centroid(mass),
(Vector) {A * cos(sqrt(K / M) * i * DT), 0} (vector_t) {A * cos(sqrt(K / M) * i * DT), 0}
)); ));
assert(vec_equal(body_get_centroid(anchor), VEC_ZERO));
scene_tick(scene, DT); scene_tick(scene, DT);
} }
scene_free(scene); scene_free(scene);
} }
double gravity_potential(double G, Body *body1, Body *body2) { double gravity_potential(double G, body_t *body1, body_t *body2) {
Vector r = vec_subtract(body_get_centroid(body2), body_get_centroid(body1)); vector_t r = vec_subtract(body_get_centroid(body2), body_get_centroid(body1));
return -G * body_get_mass(body1) * body_get_mass(body2) / sqrt(vec_dot(r, r)); return -G * body_get_mass(body1) * body_get_mass(body2) / sqrt(vec_dot(r, r));
} }
double kinetic_energy(Body *body) { double kinetic_energy(body_t *body) {
Vector v = body_get_velocity(body); vector_t v = body_get_velocity(body);
return body_get_mass(body) * vec_dot(v, v) / 2; return body_get_mass(body) * vec_dot(v, v) / 2;
} }
...@@ -60,11 +61,11 @@ void test_energy_conservation() { ...@@ -60,11 +61,11 @@ void test_energy_conservation() {
const double G = 1e3; const double G = 1e3;
const double DT = 1e-6; const double DT = 1e-6;
const int STEPS = 1000000; const int STEPS = 1000000;
Scene *scene = scene_init(); scene_t *scene = scene_init();
Body *mass1 = body_init(make_shape(), M1, (RGBColor) {0, 0, 0}); body_t *mass1 = body_init(make_shape(), M1, (rgb_color_t) {0, 0, 0});
scene_add_body(scene, mass1); scene_add_body(scene, mass1);
Body *mass2 = body_init(make_shape(), M2, (RGBColor) {0, 0, 0}); body_t *mass2 = body_init(make_shape(), M2, (rgb_color_t) {0, 0, 0});
body_set_centroid(mass2, (Vector) {10, 20}); body_set_centroid(mass2, (vector_t) {10, 20});
scene_add_body(scene, mass2); scene_add_body(scene, mass2);
create_newtonian_gravity(scene, G, mass1, mass2); create_newtonian_gravity(scene, G, mass1, mass2);
double initial_energy = gravity_potential(G, mass1, mass2); double initial_energy = gravity_potential(G, mass1, mass2);
...@@ -72,24 +73,24 @@ void test_energy_conservation() { ...@@ -72,24 +73,24 @@ void test_energy_conservation() {
assert(body_get_centroid(mass1).x < body_get_centroid(mass2).x); assert(body_get_centroid(mass1).x < body_get_centroid(mass2).x);
double energy = gravity_potential(G, mass1, mass2) + double energy = gravity_potential(G, mass1, mass2) +
kinetic_energy(mass1) + kinetic_energy(mass2); kinetic_energy(mass1) + kinetic_energy(mass2);
assert(within(1e-5, energy / initial_energy, 1)); assert(within(1e-4, energy / initial_energy, 1));
scene_tick(scene, DT); scene_tick(scene, DT);
} }
scene_free(scene); scene_free(scene);
} }
Body *make_triangle_body() { body_t *make_triangle_body() {
List *shape = list_init(3, free); list_t *shape = list_init(3, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = (Vector) {1, 0}; *v = (vector_t) {1, 0};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-0.5, +sqrt(3) / 2}; *v = (vector_t) {-0.5, +sqrt(3) / 2};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-0.5, -sqrt(3) / 2}; *v = (vector_t) {-0.5, -sqrt(3) / 2};
list_add(shape, v); list_add(shape, v);
return body_init(shape, 1, (RGBColor) {0, 0, 0}); return body_init(shape, 1, (rgb_color_t) {0, 0, 0});
} }
// Tests that destructive collisions remove bodies from the scene // Tests that destructive collisions remove bodies from the scene
...@@ -99,19 +100,19 @@ void test_collisions() { ...@@ -99,19 +100,19 @@ void test_collisions() {
const double SEPARATION_AT_COLLISION = 1.5; const double SEPARATION_AT_COLLISION = 1.5;
const int TICKS_TO_COLLISION = 10; const int TICKS_TO_COLLISION = 10;
Scene *scene = scene_init(); scene_t *scene = scene_init();
Body *body1 = make_triangle_body(); body_t *body1 = make_triangle_body();
Vector initial_separation = vector_t initial_separation =
{SEPARATION_AT_COLLISION + V * DT * (TICKS_TO_COLLISION - 0.5), 0}; {SEPARATION_AT_COLLISION + V * DT * (TICKS_TO_COLLISION - 0.5), 0};
body_set_centroid(body1, vec_negate(initial_separation)); body_set_centroid(body1, vec_negate(initial_separation));
body_set_velocity(body1, (Vector) {+V, 0}); body_set_velocity(body1, (vector_t) {+V, 0});
scene_add_body(scene, body1); scene_add_body(scene, body1);
Body *body2 = make_triangle_body(); body_t *body2 = make_triangle_body();
scene_add_body(scene, body2); scene_add_body(scene, body2);
Body *body3 = make_triangle_body(); body_t *body3 = make_triangle_body();
body_set_velocity(body3, (Vector) {-V, 0}); body_set_velocity(body3, (vector_t) {-V, 0});
body_set_centroid(body3, initial_separation); body_set_centroid(body3, initial_separation);
scene_add_body(scene, body3); scene_add_body(scene, body3);
...@@ -134,10 +135,10 @@ void test_collisions() { ...@@ -134,10 +135,10 @@ void test_collisions() {
// Tests that force creators properly register their list of affected bodies. // Tests that force creators properly register their list of affected bodies.
// If they don't, asan will report a heap-use-after-free failure. // If they don't, asan will report a heap-use-after-free failure.
void test_forces_removed() { void test_forces_removed() {
Scene *scene = scene_init(); scene_t *scene = scene_init();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Body *body = body_init(make_shape(), 1, (RGBColor) {0, 0, 0}); body_t *body = body_init(make_shape(), 1, (rgb_color_t) {0, 0, 0});
body_set_centroid(body, (Vector) {i, i}); body_set_centroid(body, (vector_t) {i, i});
scene_add_body(scene, body); scene_add_body(scene, body);
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
create_newtonian_gravity(scene, 1, body, scene_get_body(scene, j)); create_newtonian_gravity(scene, 1, body, scene_get_body(scene, j));
...@@ -167,5 +168,4 @@ int main(int argc, char *argv[]) { ...@@ -167,5 +168,4 @@ int main(int argc, char *argv[]) {
DO_TEST(test_forces_removed) DO_TEST(test_forces_removed)
puts("forces_test PASS"); puts("forces_test PASS");
return 0;
} }
...@@ -5,14 +5,14 @@ ...@@ -5,14 +5,14 @@
#include <stdlib.h> #include <stdlib.h>
void scene_get_first(void *scene) { void scene_get_first(void *scene) {
scene_get_body((Scene *) scene, 0); scene_get_body(scene, 0);
} }
void scene_remove_first(void *scene) { void scene_remove_first(void *scene) {
scene_remove_body((Scene *) scene, 0); scene_remove_body(scene, 0);
} }
void test_empty_scene() { void test_empty_scene() {
Scene *scene = scene_init(); scene_t *scene = scene_init();
assert(scene_bodies(scene) == 0); assert(scene_bodies(scene) == 0);
for (int i = 0; i < 10; i++) scene_tick(scene, 1); for (int i = 0; i < 10; i++) scene_tick(scene, 1);
assert(test_assert_fail(scene_get_first, scene)); assert(test_assert_fail(scene_get_first, scene));
...@@ -20,37 +20,37 @@ void test_empty_scene() { ...@@ -20,37 +20,37 @@ void test_empty_scene() {
scene_free(scene); scene_free(scene);
} }
List *make_shape() { list_t *make_shape() {
List *shape = list_init(4, free); list_t *shape = list_init(4, free);
Vector *v = malloc(sizeof(*v)); vector_t *v = malloc(sizeof(*v));
*v = (Vector) {-1, -1}; *v = (vector_t) {-1, -1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {+1, -1}; *v = (vector_t) {+1, -1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {+1, +1}; *v = (vector_t) {+1, +1};
list_add(shape, v); list_add(shape, v);
v = malloc(sizeof(*v)); v = malloc(sizeof(*v));
*v = (Vector) {-1, +1}; *v = (vector_t) {-1, +1};
list_add(shape, v); list_add(shape, v);
return shape; return shape;
} }
void test_scene() { void test_scene() {
// Build a scene with 3 bodies // Build a scene with 3 bodies
Scene *scene = scene_init(); scene_t *scene = scene_init();
assert(scene_bodies(scene) == 0); assert(scene_bodies(scene) == 0);
Body *body1 = body_init(make_shape(), 1, (RGBColor) {1, 1, 1}); body_t *body1 = body_init(make_shape(), 1, (rgb_color_t) {1, 1, 1});
scene_add_body(scene, body1); scene_add_body(scene, body1);
assert(scene_bodies(scene) == 1); assert(scene_bodies(scene) == 1);
assert(scene_get_body(scene, 0) == body1); assert(scene_get_body(scene, 0) == body1);
Body *body2 = body_init(make_shape(), 2, (RGBColor) {1, 1, 1}); body_t *body2 = body_init(make_shape(), 2, (rgb_color_t) {1, 1, 1});
scene_add_body(scene, body2); scene_add_body(scene, body2);
assert(scene_bodies(scene) == 2); assert(scene_bodies(scene) == 2);
assert(scene_get_body(scene, 0) == body1); assert(scene_get_body(scene, 0) == body1);
assert(scene_get_body(scene, 1) == body2); assert(scene_get_body(scene, 1) == body2);
Body *body3 = body_init(make_shape(), 3, (RGBColor) {1, 1, 1}); body_t *body3 = body_init(make_shape(), 3, (rgb_color_t) {1, 1, 1});
scene_add_body(scene, body3); scene_add_body(scene, body3);
assert(scene_bodies(scene) == 3); assert(scene_bodies(scene) == 3);
assert(scene_get_body(scene, 0) == body1); assert(scene_get_body(scene, 0) == body1);
...@@ -58,20 +58,20 @@ void test_scene() { ...@@ -58,20 +58,20 @@ void test_scene() {
assert(scene_get_body(scene, 2) == body3); assert(scene_get_body(scene, 2) == body3);
// Set the bodies' positions with no velocity and ensure they match // Set the bodies' positions with no velocity and ensure they match
body_set_centroid(body1, (Vector) {1, 1}); body_set_centroid(body1, (vector_t) {1, 1});
body_set_centroid(body2, (Vector) {2, 2}); body_set_centroid(body2, (vector_t) {2, 2});
body_set_centroid(body3, (Vector) {3, 3}); body_set_centroid(body3, (vector_t) {3, 3});
scene_tick(scene, 1); scene_tick(scene, 1);
assert(vec_isclose(body_get_centroid(body1), (Vector) {1, 1})); assert(vec_isclose(body_get_centroid(body1), (vector_t) {1, 1}));
assert(vec_isclose(body_get_centroid(body2), (Vector) {2, 2})); assert(vec_isclose(body_get_centroid(body2), (vector_t) {2, 2}));
assert(vec_isclose(body_get_centroid(body3), (Vector) {3, 3})); assert(vec_isclose(body_get_centroid(body3), (vector_t) {3, 3}));
body_set_velocity(body1, (Vector) {+1, 0}); body_set_velocity(body1, (vector_t) {+1, 0});
body_set_velocity(body2, (Vector) {-1, 0}); body_set_velocity(body2, (vector_t) {-1, 0});
body_set_velocity(body3, (Vector) {0, +1}); body_set_velocity(body3, (vector_t) {0, +1});
scene_tick(scene, 1); scene_tick(scene, 1);
assert(vec_isclose(body_get_centroid(body1), (Vector) {2, 1})); assert(vec_isclose(body_get_centroid(body1), (vector_t) {2, 1}));
assert(vec_isclose(body_get_centroid(body2), (Vector) {1, 2})); assert(vec_isclose(body_get_centroid(body2), (vector_t) {1, 2}));
assert(vec_isclose(body_get_centroid(body3), (Vector) {3, 4})); assert(vec_isclose(body_get_centroid(body3), (vector_t) {3, 4}));
// Try removing the second body // Try removing the second body
scene_remove_body(scene, 1); scene_remove_body(scene, 1);
...@@ -83,19 +83,19 @@ void test_scene() { ...@@ -83,19 +83,19 @@ void test_scene() {
// Tick the remaining bodies // Tick the remaining bodies
scene_tick(scene, 1); scene_tick(scene, 1);
assert(vec_isclose(body_get_centroid(body1), (Vector) {3, 1})); assert(vec_isclose(body_get_centroid(body1), (vector_t) {3, 1}));
assert(vec_isclose(body_get_centroid(body3), (Vector) {3, 5})); assert(vec_isclose(body_get_centroid(body3), (vector_t) {3, 5}));
scene_free(scene); scene_free(scene);
} }
// A force creator that moves a body in uniform circular motion about the origin // A force creator that moves a body in uniform circular motion about the origin
void centripetal_force(void *aux) { void centripetal_force(void *aux) {
Body *body = (Body *) aux; body_t *body = aux;
Vector v = body_get_velocity(body); vector_t v = body_get_velocity(body);
Vector r = body_get_centroid(body); vector_t r = body_get_centroid(body);
assert(isclose(vec_dot(v, r), 0)); assert(isclose(vec_dot(v, r), 0));
Vector force = vector_t force =
vec_multiply(-body_get_mass(body) * vec_dot(v, v) / vec_dot(r, r), r); vec_multiply(-body_get_mass(body) * vec_dot(v, v) / vec_dot(r, r), r);
body_add_force(body, force); body_add_force(body, force);
} }
...@@ -105,14 +105,15 @@ void test_force_creator() { ...@@ -105,14 +105,15 @@ void test_force_creator() {
const double R = 2; const double R = 2;
const double DT = 1e-6; const double DT = 1e-6;
const int STEPS = 1000000; const int STEPS = 1000000;
Scene *scene = scene_init(); scene_t *scene = scene_init();
Body *body = body_init(make_shape(), 123, (RGBColor) {0, 0, 0}); body_t *body = body_init(make_shape(), 123, (rgb_color_t) {0, 0, 0});
body_set_centroid(body, (Vector) {R, 0}); vector_t radius = {R, 0};
body_set_velocity(body, (Vector) {0, OMEGA * R}); body_set_centroid(body, radius);
body_set_velocity(body, (vector_t) {0, OMEGA * R});
scene_add_body(scene, body); scene_add_body(scene, body);
scene_add_force_creator(scene, centripetal_force, body, NULL); scene_add_force_creator(scene, centripetal_force, body, NULL);
for (int i = 0; i < STEPS; i++) { for (int i = 0; i < STEPS; i++) {
Vector expected_x = vec_rotate((Vector) {R, 0}, OMEGA * i * DT); vector_t expected_x = vec_rotate(radius, OMEGA * i * DT);
assert(vec_within(1e-4, body_get_centroid(body), expected_x)); assert(vec_within(1e-4, body_get_centroid(body), expected_x));
scene_tick(scene, DT); scene_tick(scene, DT);
} }
...@@ -120,29 +121,29 @@ void test_force_creator() { ...@@ -120,29 +121,29 @@ void test_force_creator() {
} }
typedef struct { typedef struct {
Scene *scene; scene_t *scene;
double coefficient; double coefficient;
} ForceAux; } force_aux_t;
// A force creator that applies constant downwards gravity to all bodies in a scene // A force creator that applies constant downwards gravity to all bodies in a scene
void constant_gravity(void *aux) { void constant_gravity(void *aux) {
ForceAux *gravity_aux = (ForceAux *) aux; force_aux_t *gravity_aux = aux;
size_t body_count = scene_bodies(gravity_aux->scene); size_t body_count = scene_bodies(gravity_aux->scene);
for (size_t i = 0; i < body_count; i++) { for (size_t i = 0; i < body_count; i++) {
Body *body = scene_get_body(gravity_aux->scene, i); body_t *body = scene_get_body(gravity_aux->scene, i);
Vector force = {0, -gravity_aux->coefficient * body_get_mass(body)}; vector_t force = {0, -gravity_aux->coefficient * body_get_mass(body)};
body_add_force(body, force); body_add_force(body, force);
} }
} }
// A force creator that applies drag proportional to v ** 2 to all bodies in a scene // A force creator that applies drag proportional to v ** 2 to all bodies in a scene
void air_drag(void *aux) { void air_drag(void *aux) {
ForceAux *drag_aux = (ForceAux *) aux; force_aux_t *drag_aux = aux;
size_t body_count = scene_bodies(drag_aux->scene); size_t body_count = scene_bodies(drag_aux->scene);
for (size_t i = 0; i < body_count; i++) { for (size_t i = 0; i < body_count; i++) {
Body *body = scene_get_body(drag_aux->scene, i); body_t *body = scene_get_body(drag_aux->scene, i);
Vector v = body_get_velocity(body); vector_t v = body_get_velocity(body);
Vector force = vector_t force =
vec_multiply(-drag_aux->coefficient * sqrt(vec_dot(v, v)), v); vec_multiply(-drag_aux->coefficient * sqrt(vec_dot(v, v)), v);
body_add_force(body, force); body_add_force(body, force);
} }
...@@ -153,27 +154,27 @@ void test_force_creator_aux() { ...@@ -153,27 +154,27 @@ void test_force_creator_aux() {
const double GRAVITY = 9.8, DRAG = 3; const double GRAVITY = 9.8, DRAG = 3;
const double DT = 1e-3; const double DT = 1e-3;
const int STEPS = 100000; const int STEPS = 100000;
Scene *scene = scene_init(); scene_t *scene = scene_init();
Body *light = body_init(make_shape(), LIGHT_MASS, (RGBColor) {0, 0, 0}); body_t *light = body_init(make_shape(), LIGHT_MASS, (rgb_color_t) {0, 0, 0});
scene_add_body(scene, light); scene_add_body(scene, light);
Body *heavy = body_init(make_shape(), HEAVY_MASS, (RGBColor) {0, 0, 0}); body_t *heavy = body_init(make_shape(), HEAVY_MASS, (rgb_color_t) {0, 0, 0});
scene_add_body(scene, heavy); scene_add_body(scene, heavy);
ForceAux *gravity_aux = malloc(sizeof(*gravity_aux)); force_aux_t *gravity_aux = malloc(sizeof(*gravity_aux));
gravity_aux->scene = scene; gravity_aux->scene = scene;
gravity_aux->coefficient = GRAVITY; gravity_aux->coefficient = GRAVITY;
scene_add_force_creator(scene, constant_gravity, gravity_aux, free); scene_add_force_creator(scene, constant_gravity, gravity_aux, free);
ForceAux *drag_aux = malloc(sizeof(*drag_aux)); force_aux_t *drag_aux = malloc(sizeof(*drag_aux));
drag_aux->scene = scene; drag_aux->scene = scene;
drag_aux->coefficient = DRAG; drag_aux->coefficient = DRAG;
scene_add_force_creator(scene, air_drag, drag_aux, free); scene_add_force_creator(scene, air_drag, drag_aux, free);
for (int i = 0; i < STEPS; i++) scene_tick(scene, DT); for (int i = 0; i < STEPS; i++) scene_tick(scene, DT);
assert(vec_isclose( assert(vec_isclose(
body_get_velocity(light), body_get_velocity(light),
(Vector) {0, -sqrt(GRAVITY * LIGHT_MASS / DRAG) (vector_t) {0, -sqrt(GRAVITY * LIGHT_MASS / DRAG)
})); }));
assert(vec_isclose( assert(vec_isclose(
body_get_velocity(heavy), body_get_velocity(heavy),
(Vector) {0, -sqrt(GRAVITY * HEAVY_MASS / DRAG) (vector_t) {0, -sqrt(GRAVITY * HEAVY_MASS / DRAG)
})); }));
scene_free(scene); scene_free(scene);
} }
...@@ -187,7 +188,7 @@ void test_force_creator_aux() { ...@@ -187,7 +188,7 @@ void test_force_creator_aux() {
so it should only be called during the first two ticks. so it should only be called during the first two ticks.
*/ */
void remove_body(void *aux) { void remove_body(void *aux) {
Scene *scene = (Scene *) aux; scene_t *scene = aux;
size_t body_count = scene_bodies(scene); size_t body_count = scene_bodies(scene);
if (body_count > 0) { if (body_count > 0) {
body_remove(scene_get_body(scene, body_count - 1)); body_remove(scene_get_body(scene, body_count - 1));
...@@ -195,10 +196,10 @@ void remove_body(void *aux) { ...@@ -195,10 +196,10 @@ void remove_body(void *aux) {
} }
typedef struct { typedef struct {
int count; int count;
Scene *scene; scene_t *scene;
} CountAux; } count_aux_t;
void count_calls(void *aux) { void count_calls(void *aux) {
CountAux *count_aux = (CountAux *) aux; count_aux_t *count_aux = aux;
// Every time count_calls() is called, the body count should decrease by 1 // Every time count_calls() is called, the body count should decrease by 1
assert(scene_bodies(count_aux->scene) == 3 - count_aux->count); assert(scene_bodies(count_aux->scene) == 3 - count_aux->count);
// Record that count_calls() was called an additional time // Record that count_calls() was called an additional time
...@@ -206,23 +207,19 @@ void count_calls(void *aux) { ...@@ -206,23 +207,19 @@ void count_calls(void *aux) {
} }
void test_reaping() { void test_reaping() {
Scene *scene = scene_init(); scene_t *scene = scene_init();
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
scene_add_body(scene, body_init(make_shape(), 1, (RGBColor) {0, 0, 0})); scene_add_body(scene, body_init(make_shape(), 1, (rgb_color_t) {0, 0, 0}));
} }
scene_add_bodies_force_creator( scene_add_bodies_force_creator(scene, remove_body, scene, list_init(0, NULL), NULL);
scene, remove_body, scene, list_init(0, NULL), NULL
);
CountAux *count_aux = malloc(sizeof(*count_aux)); count_aux_t *count_aux = malloc(sizeof(*count_aux));
count_aux->count = 0; count_aux->count = 0;
count_aux->scene = scene; count_aux->scene = scene;
List *required_bodies = list_init(2, NULL); list_t *required_bodies = list_init(2, NULL);
list_add(required_bodies, scene_get_body(scene, 0)); list_add(required_bodies, scene_get_body(scene, 0));
list_add(required_bodies, scene_get_body(scene, 1)); list_add(required_bodies, scene_get_body(scene, 1));
scene_add_bodies_force_creator( scene_add_bodies_force_creator(scene, count_calls, count_aux, required_bodies, NULL);
scene, count_calls, count_aux, required_bodies, NULL
);
while (scene_bodies(scene) > 0) { while (scene_bodies(scene) > 0) {
scene_tick(scene, 1); scene_tick(scene, 1);
...@@ -249,5 +246,4 @@ int main(int argc, char *argv[]) { ...@@ -249,5 +246,4 @@ int main(int argc, char *argv[]) {
DO_TEST(test_reaping) DO_TEST(test_reaping)
puts("scene_test PASS"); puts("scene_test PASS");
return 0;
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment