Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
cs3-19sp
project05
Commits
ba9f8584
Commit
ba9f8584
authored
5 years ago
by
Caleb C. Sander
Browse files
Options
Download
Email Patches
Plain Diff
Rename types to _t
parent
1c7777b4
master
No related merge requests found
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
include/body.h
+24
-21
include/body.h
include/collision.h
+1
-2
include/collision.h
include/forces.h
+14
-8
include/forces.h
include/scene.h
+18
-12
include/scene.h
tests/test_suite_body.c
+90
-87
tests/test_suite_body.c
tests/test_suite_forces.c
+39
-39
tests/test_suite_forces.c
tests/test_suite_scene.c
+64
-68
tests/test_suite_scene.c
with
250 additions
and
237 deletions
+250
-237
include/body.h
View file @
ba9f8584
...
...
@@ -2,7 +2,6 @@
#define __BODY_H__
#include <stdbool.h>
#include "color.h"
#include "list.h"
#include "vector.h"
...
...
@@ -13,13 +12,13 @@
* Bodies can accumulate forces and impulses during each tick.
* Angular physics (i.e. torques) are not currently implemented.
*/
typedef
struct
body
B
ody
;
typedef
struct
body
b
ody
_t
;
/**
* Initializes a body without any info.
* Acts like body_init_with_info() where info and info_freer are NULL.
*/
B
ody
*
body_init
(
L
ist
*
shape
,
double
mass
,
RGBC
olor
color
);
b
ody
_t
*
body_init
(
l
ist
_t
*
shape
,
double
mass
,
rgb_c
olor
_t
color
);
/**
* Allocates memory for a body with the given parameters.
...
...
@@ -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.
*
* @param shape a list of vectors describing the initial shape of the body
* @param mass the mass of the body (if INFINITY,
prevent
s the body from moving)
* @param mass the mass of the body (if INFINITY,
stop
s the body from moving)
* @param color the color of the body, used to draw it on the screen
* @param info additional information to associate with the body,
* 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
* @return a pointer to the newly allocated body
*/
Body
*
body_init_with_info
(
List
*
shape
,
double
mass
,
RGBColor
color
,
void
*
info
,
FreeFunc
info_freer
body_t
*
body_init_with_info
(
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(
*
* @param body a pointer to a body returned from body_init()
*/
void
body_free
(
B
ody
*
body
);
void
body_free
(
b
ody
_t
*
body
);
/**
* Gets the current shape of a body.
...
...
@@ -52,7 +55,7 @@ void body_free(Body *body);
* @param body a pointer to a body returned from body_init()
* @return the polygon describing the body's current position
*/
L
ist
*
body_get_shape
(
B
ody
*
body
);
l
ist
_t
*
body_get_shape
(
b
ody
_t
*
body
);
/**
* Gets the current center of mass of a body.
...
...
@@ -63,7 +66,7 @@ List *body_get_shape(Body *body);
* @param body a pointer to a body returned from body_init()
* @return the body's center of mass
*/
V
ector
body_get_centroid
(
B
ody
*
body
);
v
ector
_t
body_get_centroid
(
b
ody
_t
*
body
);
/**
* Gets the current velocity of a body.
...
...
@@ -71,7 +74,7 @@ Vector body_get_centroid(Body *body);
* @param body a pointer to a body returned from body_init()
* @return the body's velocity vector
*/
V
ector
body_get_velocity
(
B
ody
*
body
);
v
ector
_t
body_get_velocity
(
b
ody
_t
*
body
);
/**
* Gets the mass of a body.
...
...
@@ -79,7 +82,7 @@ Vector body_get_velocity(Body *body);
* @param body a pointer to a body returned from body_init()
* @return the mass passed to body_init(), which must be greater than 0
*/
double
body_get_mass
(
B
ody
*
body
);
double
body_get_mass
(
b
ody
_t
*
body
);
/**
* Gets the display color of a body.
...
...
@@ -87,7 +90,7 @@ double body_get_mass(Body *body);
* @param body a pointer to a body returned from body_init()
* @return the color passed to body_init(), as an (R, G, B) tuple
*/
RGBC
olor
body_get_color
(
B
ody
*
body
);
rgb_c
olor
_t
body_get_color
(
b
ody
_t
*
body
);
/**
* Gets the information associated with a body.
...
...
@@ -95,7 +98,7 @@ RGBColor body_get_color(Body *body);
* @param body a pointer to a body returned from body_init()
* @return the info passed to body_init()
*/
void
*
body_get_info
(
B
ody
*
body
);
void
*
body_get_info
(
b
ody
_t
*
body
);
/**
* Translates a body to a new position.
...
...
@@ -104,7 +107,7 @@ void *body_get_info(Body *body);
* @param body a pointer to a body returned from body_init()
* @param x the body's new centroid
*/
void
body_set_centroid
(
B
ody
*
body
,
V
ector
x
);
void
body_set_centroid
(
b
ody
_t
*
body
,
v
ector
_t
x
);
/**
* Changes a body's velocity (the time-derivative of its position).
...
...
@@ -112,7 +115,7 @@ void body_set_centroid(Body *body, Vector x);
* @param body a pointer to a body returned from body_init()
* @param v the body's new velocity
*/
void
body_set_velocity
(
B
ody
*
body
,
V
ector
v
);
void
body_set_velocity
(
b
ody
_t
*
body
,
v
ector
_t
v
);
/**
* Changes a body's orientation in the plane.
...
...
@@ -122,7 +125,7 @@ void body_set_velocity(Body *body, Vector v);
* @param body a pointer to a body returned from body_init()
* @param angle the body's new angle in radians. Positive is counterclockwise.
*/
void
body_set_rotation
(
B
ody
*
body
,
double
angle
);
void
body_set_rotation
(
b
ody
_t
*
body
,
double
angle
);
/**
* Applies a force to a body over the current tick.
...
...
@@ -132,7 +135,7 @@ void body_set_rotation(Body *body, double angle);
* @param body a pointer to a body returned from body_init()
* @param force the force vector to apply
*/
void
body_add_force
(
B
ody
*
body
,
V
ector
force
);
void
body_add_force
(
b
ody
_t
*
body
,
v
ector
_t
force
);
/**
* Applies an impulse to a body.
...
...
@@ -144,7 +147,7 @@ void body_add_force(Body *body, Vector force);
* @param body a pointer to a body returned from body_init()
* @param impulse the impulse vector to apply
*/
void
body_add_impulse
(
B
ody
*
body
,
V
ector
impulse
);
void
body_add_impulse
(
b
ody
_t
*
body
,
v
ector
_t
impulse
);
/**
* Updates the body after a given time interval has elapsed.
...
...
@@ -157,7 +160,7 @@ void body_add_impulse(Body *body, Vector impulse);
* @param body the body to tick
* @param dt the number of seconds elapsed since the last tick
*/
void
body_tick
(
B
ody
*
body
,
double
dt
);
void
body_tick
(
b
ody
_t
*
body
,
double
dt
);
/**
* 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);
*
* @param body the body to mark for removal
*/
void
body_remove
(
B
ody
*
body
);
void
body_remove
(
b
ody
_t
*
body
);
/**
* Returns whether a body has been marked for removal.
...
...
@@ -176,6 +179,6 @@ void body_remove(Body *body);
* @param body the body to check
* @return whether body_remove() has been called on the body
*/
bool
body_is_removed
(
B
ody
*
body
);
bool
body_is_removed
(
b
ody
_t
*
body
);
#endif // #ifndef __BODY_H__
This diff is collapsed.
Click to expand it.
include/collision.h
View file @
ba9f8584
...
...
@@ -3,7 +3,6 @@
#include <stdbool.h>
#include "list.h"
#include "vector.h"
/**
* Determines whether two convex polygons intersect.
...
...
@@ -15,6 +14,6 @@
* @param shape2 the second shape
* @return whether the shapes are colliding
*/
bool
find_collision
(
L
ist
*
shape1
,
L
ist
*
shape2
);
bool
find_collision
(
l
ist
_t
*
shape1
,
l
ist
_t
*
shape2
);
#endif // #ifndef __COLLISION_H__
This diff is collapsed.
Click to expand it.
include/forces.h
View file @
ba9f8584
...
...
@@ -4,7 +4,9 @@
#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.
* 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.
...
...
@@ -14,10 +16,12 @@
* @param body1 the first body
* @param body2 the second body
*/
void
create_newtonian_gravity
(
S
cene
*
scene
,
double
G
,
B
ody
*
body1
,
B
ody
*
body2
);
void
create_newtonian_gravity
(
s
cene
_t
*
scene
,
double
G
,
b
ody
_t
*
body1
,
b
ody
_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.
*
* @param scene the scene containing the bodies
...
...
@@ -25,10 +29,12 @@ void create_newtonian_gravity(Scene *scene, double G, Body *body1, Body *body2);
* @param body1 the first body
* @param body2 the second body
*/
void
create_spring
(
S
cene
*
scene
,
double
k
,
B
ody
*
body1
,
B
ody
*
body2
);
void
create_spring
(
s
cene
_t
*
scene
,
double
k
,
b
ody
_t
*
body1
,
b
ody
_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.
*
* @param scene the scene containing the bodies
...
...
@@ -36,16 +42,16 @@ void create_spring(Scene *scene, double k, Body *body1, Body *body2);
* (higher gamma means more drag)
* @param body the body to slow down
*/
void
create_drag
(
S
cene
*
scene
,
double
gamma
,
B
ody
*
body
);
void
create_drag
(
s
cene
_t
*
scene
,
double
gamma
,
b
ody
_t
*
body
);
/**
* Adds a
F
orce
C
reator to a scene that destroys two bodies when they collide.
* Adds a
f
orce
c
reator to a scene that destroys two bodies when they collide.
* The bodies should be destroyed by calling body_remove().
*
* @param scene the scene containing the bodies
* @param body1 the first body
* @param body2 the second body
*/
void
create_destructive_collision
(
S
cene
*
scene
,
B
ody
*
body1
,
B
ody
*
body2
);
void
create_destructive_collision
(
s
cene
_t
*
scene
,
b
ody
_t
*
body1
,
b
ody
_t
*
body2
);
#endif // #ifndef __FORCES_H__
This diff is collapsed.
Click to expand it.
include/scene.h
View file @
ba9f8584
#ifndef __SCENE_H__
#define __SCENE_H__
#include <stdbool.h>
#include "body.h"
#include "list.h"
...
...
@@ -10,14 +9,14 @@
* The scene automatically resizes to store
* arbitrarily many bodies and force creators.
*/
typedef
struct
scene
S
cene
;
typedef
struct
scene
s
cene
_t
;
/**
* A function which adds some forces or impulses to bodies,
* e.g. from collisions, gravity, or spring forces.
* Takes in an auxiliary value that can store parameters or state.
*/
typedef
void
(
*
F
orce
C
reator
)(
void
*
aux
);
typedef
void
(
*
f
orce
_c
reator
_t
)(
void
*
aux
);
/**
* Allocates memory for an empty scene.
...
...
@@ -26,7 +25,7 @@ typedef void (*ForceCreator)(void *aux);
*
* @return the new scene
*/
S
cene
*
scene_init
(
void
);
s
cene
_t
*
scene_init
(
void
);
/**
* Releases memory allocated for a given scene
...
...
@@ -34,7 +33,7 @@ Scene *scene_init(void);
*
* @param scene a pointer to a scene returned from scene_init()
*/
void
scene_free
(
S
cene
*
scene
);
void
scene_free
(
s
cene
_t
*
scene
);
/**
* Gets the number of bodies in a given scene.
...
...
@@ -42,7 +41,7 @@ void scene_free(Scene *scene);
* @param scene a pointer to a scene returned from scene_init()
* @return the number of bodies added with scene_add_body()
*/
size_t
scene_bodies
(
S
cene
*
scene
);
size_t
scene_bodies
(
s
cene
_t
*
scene
);
/**
* Gets the body at a given index in a scene.
...
...
@@ -52,7 +51,7 @@ size_t scene_bodies(Scene *scene);
* @param index the index of the body in the scene (starting at 0)
* @return a pointer to the body at the given index
*/
B
ody
*
scene_get_body
(
S
cene
*
scene
,
size_t
index
);
b
ody
_t
*
scene_get_body
(
s
cene
_t
*
scene
,
size_t
index
);
/**
* Adds a body to a scene.
...
...
@@ -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 body a pointer to the body to add to the scene
*/
void
scene_add_body
(
S
cene
*
scene
,
B
ody
*
body
);
void
scene_add_body
(
s
cene
_t
*
scene
,
b
ody
_t
*
body
);
/**
* @deprecated Use body_remove() instead
...
...
@@ -71,14 +70,17 @@ void scene_add_body(Scene *scene, Body *body);
* @param scene a pointer to a scene returned from scene_init()
* @param index the index of the body in the scene (starting at 0)
*/
void
scene_remove_body
(
S
cene
*
scene
,
size_t
index
);
void
scene_remove_body
(
s
cene
_t
*
scene
,
size_t
index
);
/**
* @deprecated Use scene_add_bodies_force_creator() instead
* so the scene knows which bodies the force creator depends on
*/
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(
* @param freer if non-NULL, a function to call in order to free aux
*/
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(
* @param scene a pointer to a scene returned from scene_init()
* @param dt the time elapsed since the last tick, in seconds
*/
void
scene_tick
(
S
cene
*
scene
,
double
dt
);
void
scene_tick
(
s
cene
_t
*
scene
,
double
dt
);
#endif // #ifndef __SCENE_H__
This diff is collapsed.
Click to expand it.
tests/test_suite_body.c
View file @
ba9f8584
...
...
@@ -5,23 +5,23 @@
#include <stdlib.h>
void
test_body_init
()
{
V
ector
v
[]
=
{{
1
,
1
},
{
2
,
1
},
{
2
,
2
},
{
1
,
2
}};
v
ector
_t
v
[]
=
{{
1
,
1
},
{
2
,
1
},
{
2
,
2
},
{
1
,
2
}};
const
size_t
VERTICES
=
sizeof
(
v
)
/
sizeof
(
*
v
);
L
ist
*
shape
=
list_init
(
0
,
free
);
l
ist
_t
*
shape
=
list_init
(
0
,
free
);
for
(
size_t
i
=
0
;
i
<
VERTICES
;
i
++
)
{
V
ector
*
list_v
=
malloc
(
sizeof
(
*
list_v
));
v
ector
_t
*
list_v
=
malloc
(
sizeof
(
*
list_v
));
*
list_v
=
v
[
i
];
list_add
(
shape
,
list_v
);
}
RGBC
olor
color
=
{
0
,
0
.
5
,
1
};
B
ody
*
body
=
body_init
(
shape
,
3
,
color
);
L
ist
*
shape2
=
body_get_shape
(
body
);
rgb_c
olor
_t
color
=
{
0
,
0
.
5
,
1
};
b
ody
_t
*
body
=
body_init
(
shape
,
3
,
color
);
l
ist
_t
*
shape2
=
body_get_shape
(
body
);
assert
(
list_size
(
shape2
)
==
VERTICES
);
for
(
size_t
i
=
0
;
i
<
VERTICES
;
i
++
)
{
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape2
,
i
),
v
[
i
]));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape2
,
i
),
v
[
i
]));
}
list_free
(
shape2
);
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
V
ector
)
{
1
.
5
,
1
.
5
}));
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
v
ector
_t
)
{
1
.
5
,
1
.
5
}));
assert
(
vec_equal
(
body_get_velocity
(
body
),
VEC_ZERO
));
assert
(
body_get_color
(
body
).
r
==
color
.
r
);
assert
(
body_get_color
(
body
).
g
==
color
.
g
);
...
...
@@ -31,65 +31,65 @@ void test_body_init() {
}
void
test_body_setters
()
{
L
ist
*
shape
=
list_init
(
3
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
0
};
l
ist
_t
*
shape
=
list_init
(
3
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
v
ector
_t
)
{
+
1
,
0
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
0
,
+
1
};
*
v
=
(
v
ector
_t
)
{
0
,
+
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
0
};
*
v
=
(
v
ector
_t
)
{
-
1
,
0
};
list_add
(
shape
,
v
);
B
ody
*
body
=
body_init
(
shape
,
1
,
(
RGBC
olor
)
{
0
,
0
,
0
});
body_set_velocity
(
body
,
(
V
ector
)
{
+
5
,
-
5
});
assert
(
vec_equal
(
body_get_velocity
(
body
),
(
V
ector
)
{
+
5
,
-
5
}));
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
V
ector
)
{
0
,
1
.
0
/
3
.
0
}));
body_set_centroid
(
body
,
(
V
ector
)
{
1
,
2
});
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
V
ector
)
{
1
,
2
}));
b
ody
_t
*
body
=
body_init
(
shape
,
1
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
body_set_velocity
(
body
,
(
v
ector
_t
)
{
+
5
,
-
5
});
assert
(
vec_equal
(
body_get_velocity
(
body
),
(
v
ector
_t
)
{
+
5
,
-
5
}));
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
v
ector
_t
)
{
0
,
1
.
0
/
3
.
0
}));
body_set_centroid
(
body
,
(
v
ector
_t
)
{
1
,
2
});
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
v
ector
_t
)
{
1
,
2
}));
shape
=
body_get_shape
(
body
);
assert
(
list_size
(
shape
)
==
3
);
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
0
),
(
V
ector
)
{
2
,
5
.
0
/
3
.
0
}));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
1
),
(
V
ector
)
{
1
,
8
.
0
/
3
.
0
}));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
2
),
(
V
ector
)
{
0
,
5
.
0
/
3
.
0
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
0
),
(
v
ector
_t
)
{
2
,
5
.
0
/
3
.
0
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
1
),
(
v
ector
_t
)
{
1
,
8
.
0
/
3
.
0
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
2
),
(
v
ector
_t
)
{
0
,
5
.
0
/
3
.
0
}));
list_free
(
shape
);
body_set_rotation
(
body
,
M_PI
/
2
);
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
V
ector
)
{
1
,
2
}));
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
v
ector
_t
)
{
1
,
2
}));
shape
=
body_get_shape
(
body
);
assert
(
list_size
(
shape
)
==
3
);
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
0
),
(
V
ector
)
{
4
.
0
/
3
.
0
,
3
}));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
1
),
(
V
ector
)
{
1
.
0
/
3
.
0
,
2
}));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
2
),
(
V
ector
)
{
4
.
0
/
3
.
0
,
1
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
0
),
(
v
ector
_t
)
{
4
.
0
/
3
.
0
,
3
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
1
),
(
v
ector
_t
)
{
1
.
0
/
3
.
0
,
2
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
2
),
(
v
ector
_t
)
{
4
.
0
/
3
.
0
,
1
}));
list_free
(
shape
);
body_set_centroid
(
body
,
(
V
ector
)
{
3
,
4
});
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
V
ector
)
{
3
,
4
}));
body_set_centroid
(
body
,
(
v
ector
_t
)
{
3
,
4
});
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
v
ector
_t
)
{
3
,
4
}));
shape
=
body_get_shape
(
body
);
assert
(
list_size
(
shape
)
==
3
);
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
0
),
(
V
ector
)
{
10
.
0
/
3
.
0
,
5
}));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
1
),
(
V
ector
)
{
7
.
0
/
3
.
0
,
4
}));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
2
),
(
V
ector
)
{
10
.
0
/
3
.
0
,
3
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
0
),
(
v
ector
_t
)
{
10
.
0
/
3
.
0
,
5
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
1
),
(
v
ector
_t
)
{
7
.
0
/
3
.
0
,
4
}));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
2
),
(
v
ector
_t
)
{
10
.
0
/
3
.
0
,
3
}));
list_free
(
shape
);
body_free
(
body
);
}
void
test_body_tick
()
{
const
V
ector
A
=
{
1
,
2
};
const
v
ector
_t
A
=
{
1
,
2
};
const
double
DT
=
1e-6
;
const
int
STEPS
=
1000000
;
L
ist
*
shape
=
list_init
(
4
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
l
ist
_t
*
shape
=
list_init
(
4
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
v
->
x
=
v
->
y
=
-
1
;
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
-
1
};
*
v
=
(
v
ector
_t
)
{
+
1
,
-
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
v
->
x
=
v
->
y
=
+
1
;
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
+
1
};
*
v
=
(
v
ector
_t
)
{
-
1
,
+
1
};
list_add
(
shape
,
v
);
B
ody
*
body
=
body_init
(
shape
,
1
,
(
RGBC
olor
)
{
0
,
0
,
0
});
b
ody
_t
*
body
=
body_init
(
shape
,
1
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
// Apply constant acceleration and ensure position is (a / 2) * t ** 2
for
(
int
i
=
0
;
i
<
STEPS
;
i
++
)
{
...
...
@@ -99,66 +99,66 @@ void test_body_tick() {
body_tick
(
body
,
DT
);
}
double
t
=
STEPS
*
DT
;
V
ector
new_x
=
vec_multiply
(
t
*
t
/
2
,
A
);
v
ector
_t
new_x
=
vec_multiply
(
t
*
t
/
2
,
A
);
shape
=
body_get_shape
(
body
);
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
0
),
vec_add
((
V
ector
)
{
-
1
,
-
1
},
new_x
)));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
1
),
vec_add
((
V
ector
)
{
+
1
,
-
1
},
new_x
)));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
2
),
vec_add
((
V
ector
)
{
+
1
,
+
1
},
new_x
)));
assert
(
vec_isclose
(
*
(
V
ector
*
)
list_get
(
shape
,
3
),
vec_add
((
V
ector
)
{
-
1
,
+
1
},
new_x
)));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
0
),
vec_add
((
v
ector
_t
)
{
-
1
,
-
1
},
new_x
)));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
1
),
vec_add
((
v
ector
_t
)
{
+
1
,
-
1
},
new_x
)));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
2
),
vec_add
((
v
ector
_t
)
{
+
1
,
+
1
},
new_x
)));
assert
(
vec_isclose
(
*
(
v
ector
_t
*
)
list_get
(
shape
,
3
),
vec_add
((
v
ector
_t
)
{
-
1
,
+
1
},
new_x
)));
list_free
(
shape
);
body_free
(
body
);
}
void
test_infinite_mass
()
{
L
ist
*
shape
=
list_init
(
10
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
l
ist
_t
*
shape
=
list_init
(
10
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
VEC_ZERO
;
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
0
};
*
v
=
(
v
ector
_t
)
{
+
1
,
0
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
+
1
};
*
v
=
(
v
ector
_t
)
{
+
1
,
+
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
0
,
+
1
};
*
v
=
(
v
ector
_t
)
{
0
,
+
1
};
list_add
(
shape
,
v
);
B
ody
*
body
=
body_init
(
shape
,
INFINITY
,
(
RGBC
olor
)
{
0
,
0
,
0
});
body_set_velocity
(
body
,
(
V
ector
)
{
2
,
3
});
b
ody
_t
*
body
=
body_init
(
shape
,
INFINITY
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
body_set_velocity
(
body
,
(
v
ector
_t
)
{
2
,
3
});
assert
(
body_get_mass
(
body
)
==
INFINITY
);
body_add_force
(
body
,
(
V
ector
)
{
1
,
1
});
body_add_force
(
body
,
(
v
ector
_t
)
{
1
,
1
});
body_tick
(
body
,
1
.
0
);
assert
(
vec_equal
(
body_get_velocity
(
body
),
(
V
ector
)
{
2
,
3
}));
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
V
ector
)
{
2
.
5
,
3
.
5
}));
assert
(
vec_equal
(
body_get_velocity
(
body
),
(
v
ector
_t
)
{
2
,
3
}));
assert
(
vec_isclose
(
body_get_centroid
(
body
),
(
v
ector
_t
)
{
2
.
5
,
3
.
5
}));
body_free
(
body
);
}
void
test_forces
()
{
const
double
MASS
=
10
;
const
double
DT
=
0
.
1
;
L
ist
*
shape
=
list_init
(
3
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
0
};
l
ist
_t
*
shape
=
list_init
(
3
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
v
ector
_t
)
{
+
1
,
0
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
0
,
+
1
};
*
v
=
(
v
ector
_t
)
{
0
,
+
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
0
};
*
v
=
(
v
ector
_t
)
{
-
1
,
0
};
list_add
(
shape
,
v
);
B
ody
*
body
=
body_init
(
shape
,
MASS
,
(
RGBC
olor
)
{
0
,
0
,
0
});
b
ody
_t
*
body
=
body_init
(
shape
,
MASS
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
body_set_centroid
(
body
,
VEC_ZERO
);
V
ector
old_velocity
=
{
1
,
-
2
};
v
ector
_t
old_velocity
=
{
1
,
-
2
};
body_set_velocity
(
body
,
old_velocity
);
body_add_force
(
body
,
(
V
ector
)
{
MASS
*
3
,
MASS
*
4
});
body_add_impulse
(
body
,
(
V
ector
)
{
MASS
*
10
,
MASS
*
5
});
body_add_force
(
body
,
(
V
ector
)
{
MASS
*
3
,
MASS
*
4
});
body_add_force
(
body
,
(
v
ector
_t
)
{
MASS
*
3
,
MASS
*
4
});
body_add_impulse
(
body
,
(
v
ector
_t
)
{
MASS
*
10
,
MASS
*
5
});
body_add_force
(
body
,
(
v
ector
_t
)
{
MASS
*
3
,
MASS
*
4
});
body_tick
(
body
,
DT
);
V
ector
new_velocity
=
vec_add
(
old_velocity
,
(
V
ector
)
{
10
+
6
*
DT
,
5
+
8
*
DT
});
v
ector
_t
new_velocity
=
vec_add
(
old_velocity
,
(
v
ector
_t
)
{
10
+
6
*
DT
,
5
+
8
*
DT
});
assert
(
vec_isclose
(
body_get_velocity
(
body
),
new_velocity
));
V
ector
new_centroid
=
vec_multiply
(
DT
/
2
.
0
,
vec_add
(
old_velocity
,
new_velocity
));
v
ector
_t
new_centroid
=
vec_multiply
(
DT
/
2
,
vec_add
(
old_velocity
,
new_velocity
));
assert
(
vec_isclose
(
body_get_centroid
(
body
),
new_centroid
));
body_tick
(
body
,
DT
);
assert
(
vec_isclose
(
...
...
@@ -169,17 +169,17 @@ void test_forces() {
}
void
test_body_remove
()
{
L
ist
*
shape
=
list_init
(
3
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
0
};
l
ist
_t
*
shape
=
list_init
(
3
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
v
ector
_t
)
{
+
1
,
0
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
0
,
+
1
};
*
v
=
(
v
ector
_t
)
{
0
,
+
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
0
};
*
v
=
(
v
ector
_t
)
{
-
1
,
0
};
list_add
(
shape
,
v
);
B
ody
*
body
=
body_init
(
shape
,
1
,
(
RGBC
olor
)
{
0
,
0
,
0
});
b
ody
_t
*
body
=
body_init
(
shape
,
1
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
assert
(
!
body_is_removed
(
body
));
body_remove
(
body
);
assert
(
body_is_removed
(
body
));
...
...
@@ -189,36 +189,36 @@ void test_body_remove() {
}
void
test_body_info
()
{
L
ist
*
shape
=
list_init
(
3
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
0
};
l
ist
_t
*
shape
=
list_init
(
3
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
v
ector
_t
)
{
+
1
,
0
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
0
,
+
1
};
*
v
=
(
v
ector
_t
)
{
0
,
+
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
0
};
*
v
=
(
v
ector
_t
)
{
-
1
,
0
};
list_add
(
shape
,
v
);
int
*
info
=
malloc
(
sizeof
(
*
info
));
*
info
=
123
;
B
ody
*
body
=
body_init_with_info
(
shape
,
1
,
(
RGBC
olor
)
{
0
,
0
,
0
},
info
,
NULL
);
b
ody
_t
*
body
=
body_init_with_info
(
shape
,
1
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
},
info
,
NULL
);
assert
(
*
(
int
*
)
body_get_info
(
body
)
==
123
);
body_free
(
body
);
free
(
info
);
}
void
test_body_info_freer
()
{
L
ist
*
shape
=
list_init
(
3
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
0
};
l
ist
_t
*
shape
=
list_init
(
3
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
v
ector
_t
)
{
+
1
,
0
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
0
,
+
1
};
*
v
=
(
v
ector
_t
)
{
0
,
+
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
0
};
*
v
=
(
v
ector
_t
)
{
-
1
,
0
};
list_add
(
shape
,
v
);
L
ist
*
info
=
list_init
(
3
,
free
);
l
ist
_t
*
info
=
list_init
(
3
,
free
);
int
*
info_elem
=
malloc
(
sizeof
(
*
info_elem
));
*
info_elem
=
10
;
list_add
(
info
,
info_elem
);
...
...
@@ -228,8 +228,12 @@ void test_body_info_freer() {
info_elem
=
malloc
(
sizeof
(
*
info_elem
));
*
info_elem
=
30
;
list_add
(
info
,
info_elem
);
Body
*
body
=
body_init_with_info
(
shape
,
1
,
(
RGBColor
)
{
0
,
0
,
0
},
info
,
(
FreeFunc
)
list_free
body_t
*
body
=
body_init_with_info
(
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
),
1
)
==
20
);
...
...
@@ -256,5 +260,4 @@ int main(int argc, char *argv[]) {
DO_TEST
(
test_body_info_freer
)
puts
(
"body_test PASS"
);
return
0
;
}
This diff is collapsed.
Click to expand it.
tests/test_suite_forces.c
View file @
ba9f8584
...
...
@@ -4,19 +4,19 @@
#include <math.h>
#include <stdlib.h>
L
ist
*
make_shape
()
{
L
ist
*
shape
=
list_init
(
4
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
-
1
};
l
ist
_t
*
make_shape
()
{
l
ist
_t
*
shape
=
list_init
(
4
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
v
ector
_t
)
{
-
1
,
-
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
-
1
};
*
v
=
(
v
ector
_t
)
{
+
1
,
-
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
+
1
};
*
v
=
(
v
ector
_t
)
{
+
1
,
+
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
+
1
};
*
v
=
(
v
ector
_t
)
{
-
1
,
+
1
};
list_add
(
shape
,
v
);
return
shape
;
}
...
...
@@ -28,29 +28,30 @@ void test_spring_sinusoid() {
const
double
A
=
3
;
const
double
DT
=
1e-6
;
const
int
STEPS
=
1000000
;
S
cene
*
scene
=
scene_init
();
B
ody
*
mass
=
body_init
(
make_shape
(),
M
,
(
RGBC
olor
)
{
0
,
0
,
0
});
body_set_centroid
(
mass
,
(
V
ector
)
{
A
,
0
});
s
cene
_t
*
scene
=
scene_init
();
b
ody
_t
*
mass
=
body_init
(
make_shape
(),
M
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
body_set_centroid
(
mass
,
(
v
ector
_t
)
{
A
,
0
});
scene_add_body
(
scene
,
mass
);
B
ody
*
anchor
=
body_init
(
make_shape
(),
INFINITY
,
(
RGBC
olor
)
{
0
,
0
,
0
});
b
ody
_t
*
anchor
=
body_init
(
make_shape
(),
INFINITY
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
scene_add_body
(
scene
,
anchor
);
create_spring
(
scene
,
K
,
mass
,
anchor
);
for
(
int
i
=
0
;
i
<
STEPS
;
i
++
)
{
assert
(
vec_isclose
(
body_get_centroid
(
mass
),
(
V
ector
)
{
A
*
cos
(
sqrt
(
K
/
M
)
*
i
*
DT
),
0
}
(
v
ector
_t
)
{
A
*
cos
(
sqrt
(
K
/
M
)
*
i
*
DT
),
0
}
));
assert
(
vec_equal
(
body_get_centroid
(
anchor
),
VEC_ZERO
));
scene_tick
(
scene
,
DT
);
}
scene_free
(
scene
);
}
double
gravity_potential
(
double
G
,
B
ody
*
body1
,
B
ody
*
body2
)
{
V
ector
r
=
vec_subtract
(
body_get_centroid
(
body2
),
body_get_centroid
(
body1
));
double
gravity_potential
(
double
G
,
b
ody
_t
*
body1
,
b
ody
_t
*
body2
)
{
v
ector
_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
));
}
double
kinetic_energy
(
B
ody
*
body
)
{
V
ector
v
=
body_get_velocity
(
body
);
double
kinetic_energy
(
b
ody
_t
*
body
)
{
v
ector
_t
v
=
body_get_velocity
(
body
);
return
body_get_mass
(
body
)
*
vec_dot
(
v
,
v
)
/
2
;
}
...
...
@@ -60,11 +61,11 @@ void test_energy_conservation() {
const
double
G
=
1e3
;
const
double
DT
=
1e-6
;
const
int
STEPS
=
1000000
;
S
cene
*
scene
=
scene_init
();
B
ody
*
mass1
=
body_init
(
make_shape
(),
M1
,
(
RGBC
olor
)
{
0
,
0
,
0
});
s
cene
_t
*
scene
=
scene_init
();
b
ody
_t
*
mass1
=
body_init
(
make_shape
(),
M1
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
scene_add_body
(
scene
,
mass1
);
B
ody
*
mass2
=
body_init
(
make_shape
(),
M2
,
(
RGBC
olor
)
{
0
,
0
,
0
});
body_set_centroid
(
mass2
,
(
V
ector
)
{
10
,
20
});
b
ody
_t
*
mass2
=
body_init
(
make_shape
(),
M2
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
body_set_centroid
(
mass2
,
(
v
ector
_t
)
{
10
,
20
});
scene_add_body
(
scene
,
mass2
);
create_newtonian_gravity
(
scene
,
G
,
mass1
,
mass2
);
double
initial_energy
=
gravity_potential
(
G
,
mass1
,
mass2
);
...
...
@@ -72,24 +73,24 @@ void test_energy_conservation() {
assert
(
body_get_centroid
(
mass1
).
x
<
body_get_centroid
(
mass2
).
x
);
double
energy
=
gravity_potential
(
G
,
mass1
,
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_free
(
scene
);
}
B
ody
*
make_triangle_body
()
{
L
ist
*
shape
=
list_init
(
3
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
1
,
0
};
b
ody
_t
*
make_triangle_body
()
{
l
ist
_t
*
shape
=
list_init
(
3
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
v
ector
_t
)
{
1
,
0
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
0
.
5
,
+
sqrt
(
3
)
/
2
};
*
v
=
(
v
ector
_t
)
{
-
0
.
5
,
+
sqrt
(
3
)
/
2
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
0
.
5
,
-
sqrt
(
3
)
/
2
};
*
v
=
(
v
ector
_t
)
{
-
0
.
5
,
-
sqrt
(
3
)
/
2
};
list_add
(
shape
,
v
);
return
body_init
(
shape
,
1
,
(
RGBC
olor
)
{
0
,
0
,
0
});
return
body_init
(
shape
,
1
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
}
// Tests that destructive collisions remove bodies from the scene
...
...
@@ -99,19 +100,19 @@ void test_collisions() {
const
double
SEPARATION_AT_COLLISION
=
1
.
5
;
const
int
TICKS_TO_COLLISION
=
10
;
S
cene
*
scene
=
scene_init
();
B
ody
*
body1
=
make_triangle_body
();
V
ector
initial_separation
=
s
cene
_t
*
scene
=
scene_init
();
b
ody
_t
*
body1
=
make_triangle_body
();
v
ector
_t
initial_separation
=
{
SEPARATION_AT_COLLISION
+
V
*
DT
*
(
TICKS_TO_COLLISION
-
0
.
5
),
0
};
body_set_centroid
(
body1
,
vec_negate
(
initial_separation
));
body_set_velocity
(
body1
,
(
V
ector
)
{
+
V
,
0
});
body_set_velocity
(
body1
,
(
v
ector
_t
)
{
+
V
,
0
});
scene_add_body
(
scene
,
body1
);
B
ody
*
body2
=
make_triangle_body
();
b
ody
_t
*
body2
=
make_triangle_body
();
scene_add_body
(
scene
,
body2
);
B
ody
*
body3
=
make_triangle_body
();
body_set_velocity
(
body3
,
(
V
ector
)
{
-
V
,
0
});
b
ody
_t
*
body3
=
make_triangle_body
();
body_set_velocity
(
body3
,
(
v
ector
_t
)
{
-
V
,
0
});
body_set_centroid
(
body3
,
initial_separation
);
scene_add_body
(
scene
,
body3
);
...
...
@@ -134,10 +135,10 @@ void test_collisions() {
// Tests that force creators properly register their list of affected bodies.
// If they don't, asan will report a heap-use-after-free failure.
void
test_forces_removed
()
{
S
cene
*
scene
=
scene_init
();
s
cene
_t
*
scene
=
scene_init
();
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
B
ody
*
body
=
body_init
(
make_shape
(),
1
,
(
RGBC
olor
)
{
0
,
0
,
0
});
body_set_centroid
(
body
,
(
V
ector
)
{
i
,
i
});
b
ody
_t
*
body
=
body_init
(
make_shape
(),
1
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
body_set_centroid
(
body
,
(
v
ector
_t
)
{
i
,
i
});
scene_add_body
(
scene
,
body
);
for
(
int
j
=
0
;
j
<
i
;
j
++
)
{
create_newtonian_gravity
(
scene
,
1
,
body
,
scene_get_body
(
scene
,
j
));
...
...
@@ -167,5 +168,4 @@ int main(int argc, char *argv[]) {
DO_TEST
(
test_forces_removed
)
puts
(
"forces_test PASS"
);
return
0
;
}
This diff is collapsed.
Click to expand it.
tests/test_suite_scene.c
View file @
ba9f8584
...
...
@@ -5,14 +5,14 @@
#include <stdlib.h>
void
scene_get_first
(
void
*
scene
)
{
scene_get_body
(
(
Scene
*
)
scene
,
0
);
scene_get_body
(
scene
,
0
);
}
void
scene_remove_first
(
void
*
scene
)
{
scene_remove_body
(
(
Scene
*
)
scene
,
0
);
scene_remove_body
(
scene
,
0
);
}
void
test_empty_scene
()
{
S
cene
*
scene
=
scene_init
();
s
cene
_t
*
scene
=
scene_init
();
assert
(
scene_bodies
(
scene
)
==
0
);
for
(
int
i
=
0
;
i
<
10
;
i
++
)
scene_tick
(
scene
,
1
);
assert
(
test_assert_fail
(
scene_get_first
,
scene
));
...
...
@@ -20,37 +20,37 @@ void test_empty_scene() {
scene_free
(
scene
);
}
L
ist
*
make_shape
()
{
L
ist
*
shape
=
list_init
(
4
,
free
);
V
ector
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
-
1
};
l
ist
_t
*
make_shape
()
{
l
ist
_t
*
shape
=
list_init
(
4
,
free
);
v
ector
_t
*
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
v
ector
_t
)
{
-
1
,
-
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
-
1
};
*
v
=
(
v
ector
_t
)
{
+
1
,
-
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
+
1
,
+
1
};
*
v
=
(
v
ector
_t
)
{
+
1
,
+
1
};
list_add
(
shape
,
v
);
v
=
malloc
(
sizeof
(
*
v
));
*
v
=
(
V
ector
)
{
-
1
,
+
1
};
*
v
=
(
v
ector
_t
)
{
-
1
,
+
1
};
list_add
(
shape
,
v
);
return
shape
;
}
void
test_scene
()
{
// Build a scene with 3 bodies
S
cene
*
scene
=
scene_init
();
s
cene
_t
*
scene
=
scene_init
();
assert
(
scene_bodies
(
scene
)
==
0
);
B
ody
*
body1
=
body_init
(
make_shape
(),
1
,
(
RGBC
olor
)
{
1
,
1
,
1
});
b
ody
_t
*
body1
=
body_init
(
make_shape
(),
1
,
(
rgb_c
olor
_t
)
{
1
,
1
,
1
});
scene_add_body
(
scene
,
body1
);
assert
(
scene_bodies
(
scene
)
==
1
);
assert
(
scene_get_body
(
scene
,
0
)
==
body1
);
B
ody
*
body2
=
body_init
(
make_shape
(),
2
,
(
RGBC
olor
)
{
1
,
1
,
1
});
b
ody
_t
*
body2
=
body_init
(
make_shape
(),
2
,
(
rgb_c
olor
_t
)
{
1
,
1
,
1
});
scene_add_body
(
scene
,
body2
);
assert
(
scene_bodies
(
scene
)
==
2
);
assert
(
scene_get_body
(
scene
,
0
)
==
body1
);
assert
(
scene_get_body
(
scene
,
1
)
==
body2
);
B
ody
*
body3
=
body_init
(
make_shape
(),
3
,
(
RGBC
olor
)
{
1
,
1
,
1
});
b
ody
_t
*
body3
=
body_init
(
make_shape
(),
3
,
(
rgb_c
olor
_t
)
{
1
,
1
,
1
});
scene_add_body
(
scene
,
body3
);
assert
(
scene_bodies
(
scene
)
==
3
);
assert
(
scene_get_body
(
scene
,
0
)
==
body1
);
...
...
@@ -58,20 +58,20 @@ void test_scene() {
assert
(
scene_get_body
(
scene
,
2
)
==
body3
);
// Set the bodies' positions with no velocity and ensure they match
body_set_centroid
(
body1
,
(
V
ector
)
{
1
,
1
});
body_set_centroid
(
body2
,
(
V
ector
)
{
2
,
2
});
body_set_centroid
(
body3
,
(
V
ector
)
{
3
,
3
});
body_set_centroid
(
body1
,
(
v
ector
_t
)
{
1
,
1
});
body_set_centroid
(
body2
,
(
v
ector
_t
)
{
2
,
2
});
body_set_centroid
(
body3
,
(
v
ector
_t
)
{
3
,
3
});
scene_tick
(
scene
,
1
);
assert
(
vec_isclose
(
body_get_centroid
(
body1
),
(
V
ector
)
{
1
,
1
}));
assert
(
vec_isclose
(
body_get_centroid
(
body2
),
(
V
ector
)
{
2
,
2
}));
assert
(
vec_isclose
(
body_get_centroid
(
body3
),
(
V
ector
)
{
3
,
3
}));
body_set_velocity
(
body1
,
(
V
ector
)
{
+
1
,
0
});
body_set_velocity
(
body2
,
(
V
ector
)
{
-
1
,
0
});
body_set_velocity
(
body3
,
(
V
ector
)
{
0
,
+
1
});
assert
(
vec_isclose
(
body_get_centroid
(
body1
),
(
v
ector
_t
)
{
1
,
1
}));
assert
(
vec_isclose
(
body_get_centroid
(
body2
),
(
v
ector
_t
)
{
2
,
2
}));
assert
(
vec_isclose
(
body_get_centroid
(
body3
),
(
v
ector
_t
)
{
3
,
3
}));
body_set_velocity
(
body1
,
(
v
ector
_t
)
{
+
1
,
0
});
body_set_velocity
(
body2
,
(
v
ector
_t
)
{
-
1
,
0
});
body_set_velocity
(
body3
,
(
v
ector
_t
)
{
0
,
+
1
});
scene_tick
(
scene
,
1
);
assert
(
vec_isclose
(
body_get_centroid
(
body1
),
(
V
ector
)
{
2
,
1
}));
assert
(
vec_isclose
(
body_get_centroid
(
body2
),
(
V
ector
)
{
1
,
2
}));
assert
(
vec_isclose
(
body_get_centroid
(
body3
),
(
V
ector
)
{
3
,
4
}));
assert
(
vec_isclose
(
body_get_centroid
(
body1
),
(
v
ector
_t
)
{
2
,
1
}));
assert
(
vec_isclose
(
body_get_centroid
(
body2
),
(
v
ector
_t
)
{
1
,
2
}));
assert
(
vec_isclose
(
body_get_centroid
(
body3
),
(
v
ector
_t
)
{
3
,
4
}));
// Try removing the second body
scene_remove_body
(
scene
,
1
);
...
...
@@ -83,19 +83,19 @@ void test_scene() {
// Tick the remaining bodies
scene_tick
(
scene
,
1
);
assert
(
vec_isclose
(
body_get_centroid
(
body1
),
(
V
ector
)
{
3
,
1
}));
assert
(
vec_isclose
(
body_get_centroid
(
body3
),
(
V
ector
)
{
3
,
5
}));
assert
(
vec_isclose
(
body_get_centroid
(
body1
),
(
v
ector
_t
)
{
3
,
1
}));
assert
(
vec_isclose
(
body_get_centroid
(
body3
),
(
v
ector
_t
)
{
3
,
5
}));
scene_free
(
scene
);
}
// A force creator that moves a body in uniform circular motion about the origin
void
centripetal_force
(
void
*
aux
)
{
B
ody
*
body
=
(
Body
*
)
aux
;
V
ector
v
=
body_get_velocity
(
body
);
V
ector
r
=
body_get_centroid
(
body
);
b
ody
_t
*
body
=
aux
;
v
ector
_t
v
=
body_get_velocity
(
body
);
v
ector
_t
r
=
body_get_centroid
(
body
);
assert
(
isclose
(
vec_dot
(
v
,
r
),
0
));
V
ector
force
=
v
ector
_t
force
=
vec_multiply
(
-
body_get_mass
(
body
)
*
vec_dot
(
v
,
v
)
/
vec_dot
(
r
,
r
),
r
);
body_add_force
(
body
,
force
);
}
...
...
@@ -105,14 +105,15 @@ void test_force_creator() {
const
double
R
=
2
;
const
double
DT
=
1e-6
;
const
int
STEPS
=
1000000
;
Scene
*
scene
=
scene_init
();
Body
*
body
=
body_init
(
make_shape
(),
123
,
(
RGBColor
)
{
0
,
0
,
0
});
body_set_centroid
(
body
,
(
Vector
)
{
R
,
0
});
body_set_velocity
(
body
,
(
Vector
)
{
0
,
OMEGA
*
R
});
scene_t
*
scene
=
scene_init
();
body_t
*
body
=
body_init
(
make_shape
(),
123
,
(
rgb_color_t
)
{
0
,
0
,
0
});
vector_t
radius
=
{
R
,
0
};
body_set_centroid
(
body
,
radius
);
body_set_velocity
(
body
,
(
vector_t
)
{
0
,
OMEGA
*
R
});
scene_add_body
(
scene
,
body
);
scene_add_force_creator
(
scene
,
centripetal_force
,
body
,
NULL
);
for
(
int
i
=
0
;
i
<
STEPS
;
i
++
)
{
V
ector
expected_x
=
vec_rotate
(
(
Vector
)
{
R
,
0
}
,
OMEGA
*
i
*
DT
);
v
ector
_t
expected_x
=
vec_rotate
(
radius
,
OMEGA
*
i
*
DT
);
assert
(
vec_within
(
1e-4
,
body_get_centroid
(
body
),
expected_x
));
scene_tick
(
scene
,
DT
);
}
...
...
@@ -120,29 +121,29 @@ void test_force_creator() {
}
typedef
struct
{
S
cene
*
scene
;
s
cene
_t
*
scene
;
double
coefficient
;
}
F
orce
Aux
;
}
f
orce
_aux_t
;
// A force creator that applies constant downwards gravity to all bodies in a scene
void
constant_gravity
(
void
*
aux
)
{
F
orce
Aux
*
gravity_aux
=
(
ForceAux
*
)
aux
;
f
orce
_aux_t
*
gravity_aux
=
aux
;
size_t
body_count
=
scene_bodies
(
gravity_aux
->
scene
);
for
(
size_t
i
=
0
;
i
<
body_count
;
i
++
)
{
B
ody
*
body
=
scene_get_body
(
gravity_aux
->
scene
,
i
);
V
ector
force
=
{
0
,
-
gravity_aux
->
coefficient
*
body_get_mass
(
body
)};
b
ody
_t
*
body
=
scene_get_body
(
gravity_aux
->
scene
,
i
);
v
ector
_t
force
=
{
0
,
-
gravity_aux
->
coefficient
*
body_get_mass
(
body
)};
body_add_force
(
body
,
force
);
}
}
// A force creator that applies drag proportional to v ** 2 to all bodies in a scene
void
air_drag
(
void
*
aux
)
{
F
orce
Aux
*
drag_aux
=
(
ForceAux
*
)
aux
;
f
orce
_aux_t
*
drag_aux
=
aux
;
size_t
body_count
=
scene_bodies
(
drag_aux
->
scene
);
for
(
size_t
i
=
0
;
i
<
body_count
;
i
++
)
{
B
ody
*
body
=
scene_get_body
(
drag_aux
->
scene
,
i
);
V
ector
v
=
body_get_velocity
(
body
);
V
ector
force
=
b
ody
_t
*
body
=
scene_get_body
(
drag_aux
->
scene
,
i
);
v
ector
_t
v
=
body_get_velocity
(
body
);
v
ector
_t
force
=
vec_multiply
(
-
drag_aux
->
coefficient
*
sqrt
(
vec_dot
(
v
,
v
)),
v
);
body_add_force
(
body
,
force
);
}
...
...
@@ -153,27 +154,27 @@ void test_force_creator_aux() {
const
double
GRAVITY
=
9
.
8
,
DRAG
=
3
;
const
double
DT
=
1e-3
;
const
int
STEPS
=
100000
;
S
cene
*
scene
=
scene_init
();
B
ody
*
light
=
body_init
(
make_shape
(),
LIGHT_MASS
,
(
RGBC
olor
)
{
0
,
0
,
0
});
s
cene
_t
*
scene
=
scene_init
();
b
ody
_t
*
light
=
body_init
(
make_shape
(),
LIGHT_MASS
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
scene_add_body
(
scene
,
light
);
B
ody
*
heavy
=
body_init
(
make_shape
(),
HEAVY_MASS
,
(
RGBC
olor
)
{
0
,
0
,
0
});
b
ody
_t
*
heavy
=
body_init
(
make_shape
(),
HEAVY_MASS
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
});
scene_add_body
(
scene
,
heavy
);
F
orce
Aux
*
gravity_aux
=
malloc
(
sizeof
(
*
gravity_aux
));
f
orce
_aux_t
*
gravity_aux
=
malloc
(
sizeof
(
*
gravity_aux
));
gravity_aux
->
scene
=
scene
;
gravity_aux
->
coefficient
=
GRAVITY
;
scene_add_force_creator
(
scene
,
constant_gravity
,
gravity_aux
,
free
);
F
orce
Aux
*
drag_aux
=
malloc
(
sizeof
(
*
drag_aux
));
f
orce
_aux_t
*
drag_aux
=
malloc
(
sizeof
(
*
drag_aux
));
drag_aux
->
scene
=
scene
;
drag_aux
->
coefficient
=
DRAG
;
scene_add_force_creator
(
scene
,
air_drag
,
drag_aux
,
free
);
for
(
int
i
=
0
;
i
<
STEPS
;
i
++
)
scene_tick
(
scene
,
DT
);
assert
(
vec_isclose
(
body_get_velocity
(
light
),
(
V
ector
)
{
0
,
-
sqrt
(
GRAVITY
*
LIGHT_MASS
/
DRAG
)
(
v
ector
_t
)
{
0
,
-
sqrt
(
GRAVITY
*
LIGHT_MASS
/
DRAG
)
}));
assert
(
vec_isclose
(
body_get_velocity
(
heavy
),
(
V
ector
)
{
0
,
-
sqrt
(
GRAVITY
*
HEAVY_MASS
/
DRAG
)
(
v
ector
_t
)
{
0
,
-
sqrt
(
GRAVITY
*
HEAVY_MASS
/
DRAG
)
}));
scene_free
(
scene
);
}
...
...
@@ -187,7 +188,7 @@ void test_force_creator_aux() {
so it should only be called during the first two ticks.
*/
void
remove_body
(
void
*
aux
)
{
S
cene
*
scene
=
(
Scene
*
)
aux
;
s
cene
_t
*
scene
=
aux
;
size_t
body_count
=
scene_bodies
(
scene
);
if
(
body_count
>
0
)
{
body_remove
(
scene_get_body
(
scene
,
body_count
-
1
));
...
...
@@ -195,10 +196,10 @@ void remove_body(void *aux) {
}
typedef
struct
{
int
count
;
S
cene
*
scene
;
}
C
ount
Aux
;
s
cene
_t
*
scene
;
}
c
ount
_aux_t
;
void
count_calls
(
void
*
aux
)
{
C
ount
Aux
*
count_aux
=
(
CountAux
*
)
aux
;
c
ount
_aux_t
*
count_aux
=
aux
;
// Every time count_calls() is called, the body count should decrease by 1
assert
(
scene_bodies
(
count_aux
->
scene
)
==
3
-
count_aux
->
count
);
// Record that count_calls() was called an additional time
...
...
@@ -206,23 +207,19 @@ void count_calls(void *aux) {
}
void
test_reaping
()
{
S
cene
*
scene
=
scene_init
();
s
cene
_t
*
scene
=
scene_init
();
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
scene_add_body
(
scene
,
body_init
(
make_shape
(),
1
,
(
RGBC
olor
)
{
0
,
0
,
0
}));
scene_add_body
(
scene
,
body_init
(
make_shape
(),
1
,
(
rgb_c
olor
_t
)
{
0
,
0
,
0
}));
}
scene_add_bodies_force_creator
(
scene
,
remove_body
,
scene
,
list_init
(
0
,
NULL
),
NULL
);
scene_add_bodies_force_creator
(
scene
,
remove_body
,
scene
,
list_init
(
0
,
NULL
),
NULL
);
C
ount
Aux
*
count_aux
=
malloc
(
sizeof
(
*
count_aux
));
c
ount
_aux_t
*
count_aux
=
malloc
(
sizeof
(
*
count_aux
));
count_aux
->
count
=
0
;
count_aux
->
scene
=
scene
;
L
ist
*
required_bodies
=
list_init
(
2
,
NULL
);
l
ist
_t
*
required_bodies
=
list_init
(
2
,
NULL
);
list_add
(
required_bodies
,
scene_get_body
(
scene
,
0
));
list_add
(
required_bodies
,
scene_get_body
(
scene
,
1
));
scene_add_bodies_force_creator
(
scene
,
count_calls
,
count_aux
,
required_bodies
,
NULL
);
scene_add_bodies_force_creator
(
scene
,
count_calls
,
count_aux
,
required_bodies
,
NULL
);
while
(
scene_bodies
(
scene
)
>
0
)
{
scene_tick
(
scene
,
1
);
...
...
@@ -249,5 +246,4 @@ int main(int argc, char *argv[]) {
DO_TEST
(
test_reaping
)
puts
(
"scene_test PASS"
);
return
0
;
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help