diff --git a/src/list.c b/src/list.c index 6676a39..acba56a 100644 --- a/src/list.c +++ b/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; diff --git a/src/list.h b/src/list.h index 4b2e37c..2a74735 100644 --- a/src/list.h +++ b/src/list.h @@ -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 diff --git a/src/shape.c b/src/shape.c index 3b94c60..a805284 100644 --- a/src/shape.c +++ b/src/shape.c @@ -2,12 +2,12 @@ #include "camera.h" #include "debug.h" #include "render.h" +#include "list.h" #include #include 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); diff --git a/src/shape.h b/src/shape.h index bf91607..f0ec98b 100644 --- a/src/shape.h +++ b/src/shape.h @@ -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);