shape now uses list
This commit is contained in:
parent
f373fada26
commit
919aa8406b
10
src/list.c
10
src/list.c
|
@ -24,6 +24,16 @@ List list_init(size_t element_size) {
|
|||
return self;
|
||||
}
|
||||
|
||||
List list_copy(const List* source) {
|
||||
List self = list_init(source->element_size);
|
||||
list_reserve(&self, source->cap);
|
||||
if(self.cap > 0) {
|
||||
memcpy(self.data, source->data, source->element_size * source->len);
|
||||
self.len = source->len;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void list_empty(List* self) {
|
||||
if(self->data == NULL || self->cap == 0)
|
||||
return;
|
||||
|
|
|
@ -13,6 +13,7 @@ struct List {
|
|||
};
|
||||
|
||||
extern List list_init(size_t element_size);
|
||||
extern List list_copy(const List* source);
|
||||
extern void list_empty(List* list);
|
||||
|
||||
extern void list_reserve(List* self, size_t at_least);
|
||||
|
@ -27,5 +28,8 @@ extern void* list_iterator_end(List* self);
|
|||
|
||||
#define list_from_type(T) list_init(sizeof(T))
|
||||
#define list_foreach(T, iter, list) for(T* iter = list_iterator_begin(list); iter != (T*)list_iterator_end(list); ++iter)
|
||||
#define list_at_as(T, __list, __i) ((T*)(list_at(__list, __i)))
|
||||
|
||||
#define list_iterator_begin_as(T, __list) ((T*)(list_iterator_begin(__list)))
|
||||
|
||||
#endif // !_fencer_list_h
|
||||
|
|
89
src/shape.c
89
src/shape.c
|
@ -2,12 +2,12 @@
|
|||
#include "camera.h"
|
||||
#include "debug.h"
|
||||
#include "render.h"
|
||||
#include "list.h"
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct Shape {
|
||||
Vector* points;
|
||||
size_t points_len;
|
||||
List points;
|
||||
|
||||
Vector mean;
|
||||
int is_convex;
|
||||
|
@ -17,12 +17,11 @@ static
|
|||
Vector* _shape_get_furthest_in_direction(Shape* self, Vector direction) {
|
||||
// ensure direction is normalized
|
||||
direction = vnormalizedf(direction);
|
||||
Vector* end = self->points + self->points_len;
|
||||
float furthest_dot = vdotf(direction, vsubf(self->points[0], self->mean));
|
||||
Vector* furthest = self->points;
|
||||
float furthest_dot = vdotf(direction, vsubf(*list_at_as(Vector, &self->points, 0), self->mean));
|
||||
Vector* furthest = list_at(&self->points, 0);
|
||||
|
||||
float dot;
|
||||
for(Vector* point = self->points; point < end; ++point) {
|
||||
list_foreach(Vector, point, &self->points) {
|
||||
dot = vdotf(direction, vsubf(*point, self->mean));
|
||||
if(dot > furthest_dot) {
|
||||
furthest = point;
|
||||
|
@ -38,10 +37,9 @@ Vector* _shape_get_furthest_in_direction(Shape* self, Vector direction) {
|
|||
// measured from the median.
|
||||
static
|
||||
int _shape_calculate_is_convex(Shape* self) {
|
||||
Vector* end = self->points + self->points_len;
|
||||
// point relative to mean
|
||||
Vector relative;
|
||||
for(Vector* point = self->points; point < end; ++point) {
|
||||
list_foreach(Vector, point, &self->points) {
|
||||
relative = vsubf(*point, self->mean);
|
||||
if(point != _shape_get_furthest_in_direction(self, relative)) {
|
||||
return 0;
|
||||
|
@ -53,10 +51,9 @@ int _shape_calculate_is_convex(Shape* self) {
|
|||
|
||||
static
|
||||
Vector _shape_calculate_mean(Shape* self) {
|
||||
Vector* const end = self->points + self->points_len;
|
||||
Vector avg = ZeroVector;
|
||||
size_t count = 0;
|
||||
for(Vector* point = self->points; point < end; ++point) {
|
||||
list_foreach(Vector, point, &self->points) {
|
||||
++count;
|
||||
avg = vaddf(avg, vmulff(*point, 1.0/count));
|
||||
}
|
||||
|
@ -69,15 +66,11 @@ Shape* shape_new(const Vector* points, size_t points_len) {
|
|||
Shape* self = malloc(sizeof(Shape));
|
||||
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate enough space for a shape object.");
|
||||
|
||||
self->points = malloc(points_len * sizeof(Vector));
|
||||
if(self->points == NULL) {
|
||||
free(self);
|
||||
RETURN_ERROR(NULL, "Failed to allocate enough space for %zu points", points_len);
|
||||
}
|
||||
self->points = list_from_type(Vector);
|
||||
list_reserve(&self->points, points_len);
|
||||
|
||||
// initialize data based on function arguments
|
||||
self->points_len = points_len;
|
||||
memcpy(self->points, points, points_len * sizeof(Vector));
|
||||
memcpy(list_iterator_begin_as(Vector, &self->points), points, points_len * sizeof(Vector));
|
||||
self->points.len = points_len;
|
||||
|
||||
// derive metadata
|
||||
self->mean = _shape_calculate_mean(self);
|
||||
|
@ -99,12 +92,9 @@ Shape* shape_clone(const Shape* source) {
|
|||
Shape* self = malloc(sizeof(Shape));
|
||||
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for shape object.");
|
||||
|
||||
self->points = malloc(source->points_len * sizeof(Vector));
|
||||
ASSERT_RETURN(self->points != NULL, NULL, "Failed to allocate space for shape object.");
|
||||
self->points = list_copy(&source->points);
|
||||
|
||||
// copy data from source
|
||||
self->points_len = source->points_len;
|
||||
memcpy(self->points, source->points, source->points_len * sizeof(Vector));
|
||||
self->mean = source->mean;
|
||||
self->is_convex = source->is_convex;
|
||||
|
||||
|
@ -112,69 +102,48 @@ Shape* shape_clone(const Shape* source) {
|
|||
}
|
||||
|
||||
void shape_destroy(Shape* self) {
|
||||
free(self->points);
|
||||
list_empty(&self->points);
|
||||
free(self);
|
||||
}
|
||||
|
||||
Vector* shape_get_start(Shape* self) {
|
||||
return self->points;
|
||||
return list_iterator_begin(&self->points);
|
||||
}
|
||||
|
||||
Vector* shape_get_end(Shape* self) {
|
||||
return self->points + self->points_len;
|
||||
return list_iterator_end(&self->points);
|
||||
}
|
||||
|
||||
size_t shape_get_points_count(const Shape* self) {
|
||||
return self->points_len;
|
||||
return self->points.len;
|
||||
}
|
||||
|
||||
Vector shape_get_point(const Shape* self, size_t at) {
|
||||
ASSERT_RETURN(at < self->points_len, self->mean, "Point index %zu out of bounds for shape", at);
|
||||
return self->points[at];
|
||||
Vector shape_get_point(Shape* self, size_t at) {
|
||||
ASSERT_RETURN(at < self->points.len, self->mean, "Point index %zu out of bounds for shape", at);
|
||||
return *list_at_as(Vector, &self->points, at);
|
||||
}
|
||||
|
||||
Vector shape_get_point_transformed(const Shape* self, size_t at, Transform transform) {
|
||||
Vector shape_get_point_transformed(Shape* self, size_t at, Transform transform) {
|
||||
return transform_point(&transform, shape_get_point(self, at));
|
||||
}
|
||||
|
||||
void shape_set_point(Shape* self, size_t at, Vector point) {
|
||||
ASSERT_RETURN(at < self->points_len,, "Point index %zu out of bounds for shape", at);
|
||||
self->points[at] = point;
|
||||
ASSERT_RETURN(at < self->points.len,, "Point index %zu out of bounds for shape", at);
|
||||
*list_at_as(Vector, &self->points, at) = point;
|
||||
}
|
||||
|
||||
void shape_add_point(Shape* self, Vector point) {
|
||||
Vector* new = realloc(self->points, (self->points_len + 1) * sizeof(Vector));
|
||||
ASSERT_RETURN(new != NULL,, "Failed to allocate space for new point in shape");
|
||||
|
||||
new[self->points_len] = point;
|
||||
++self->points_len;
|
||||
self->points = new;
|
||||
list_add(&self->points, &point);
|
||||
}
|
||||
|
||||
void shape_insert_point(Shape* self, size_t at, Vector point) {
|
||||
ASSERT_RETURN(at < self->points_len + 1,, "Point index %zu out of bounds for shape", at);
|
||||
Vector* new = realloc(self->points, (self->points_len + 1) * sizeof(Vector));
|
||||
ASSERT_RETURN(new != NULL,, "Failed to allocate space to insert new point in shape");
|
||||
|
||||
size_t after_at = at + 1;
|
||||
// both should add one
|
||||
// (len increased and we want to measure the difference starting offset by one from at)
|
||||
// which cancels out
|
||||
size_t dif = self->points_len - after_at;
|
||||
memmove(new + at, new + at + 1, dif);
|
||||
new[at] = point;
|
||||
self->points = new;
|
||||
++self->points_len;
|
||||
ASSERT_RETURN(at < self->points.len + 1,, "Point index %zu out of bounds for shape", at);
|
||||
list_insert(&self->points, &point, at);
|
||||
}
|
||||
|
||||
Vector shape_remove_point(Shape* self, size_t at) {
|
||||
ASSERT_RETURN(at < self->points_len, ZeroVector, "Point index %zu out of bounds for shape", at);
|
||||
Vector point = self->points[at];
|
||||
memmove(self->points + at, self->points + at + 1, (self->points_len - (at + 1)) * sizeof(Vector));
|
||||
Vector* new = realloc(self->points, (self->points_len - 1) * sizeof(Vector));
|
||||
ASSERT_RETURN(new != NULL, point, "Failed to shrink points array to %zu", self->points_len - 1);
|
||||
self->points = new;
|
||||
--self->points_len;
|
||||
Vector point = *list_at_as(Vector, &self->points, at);
|
||||
list_erase(&self->points, at);
|
||||
return point;
|
||||
}
|
||||
|
||||
|
@ -188,9 +157,9 @@ int shape_is_convex(Shape* self) {
|
|||
|
||||
void shape_draw(Shape* self, Transform transform) {
|
||||
Vector lhs, rhs, normal;
|
||||
for(size_t i = 0; i < self->points_len; ++i) {
|
||||
for(size_t i = 0; i < self->points.len; ++i) {
|
||||
lhs = shape_get_point_transformed(self, i, transform);
|
||||
rhs = shape_get_point_transformed(self, (i + 1) % self->points_len, transform);
|
||||
rhs = shape_get_point_transformed(self, (i + 1) % self->points.len, transform);
|
||||
normal = vnormalizedf(vperpendicularf(vsubf(rhs, lhs)));
|
||||
lhs = camera_world_to_pixel_point(&g_camera, lhs);
|
||||
rhs = camera_world_to_pixel_point(&g_camera, rhs);
|
||||
|
|
|
@ -15,8 +15,8 @@ extern Vector* shape_get_start(Shape* self);
|
|||
extern Vector* shape_get_end(Shape* self);
|
||||
|
||||
extern size_t shape_get_points_count(const Shape* self);
|
||||
extern Vector shape_get_point(const Shape* self, size_t at);
|
||||
extern Vector shape_get_point_transformed(const Shape* self, size_t at, Transform transform);
|
||||
extern Vector shape_get_point(Shape* self, size_t at);
|
||||
extern Vector shape_get_point_transformed(Shape* self, size_t at, Transform transform);
|
||||
|
||||
extern void shape_set_point(Shape* self, size_t at, Vector point);
|
||||
extern void shape_add_point(Shape* self, Vector point);
|
||||
|
|
Loading…
Reference in a new issue