#include #include #include #include "maths.cpp" struct Shrinkwrap { v2f* points; int count; v2f p0; Shrinkwrap(v2f* src, int src_count): count(0), p0(INFINITY, INFINITY) { int i, top = 0; int stack_size = src_count; v2f* stack = (v2f*)malloc(stack_size * sizeof *stack); points = (v2f*)malloc(src_count * sizeof *points); auto push = [&](v2f p) { assert(top < stack_size); stack[top++] = p; }; auto pop = [&]() { assert(top > 0); return stack[--top]; }; auto peek = [&](int i) { assert(top - 1 - i >= 0); return stack[top - 1 - i]; }; auto ccw = [](v2f a, v2f b, v2f c) { float angle = (b.y - a.y) * (c.x - b.x) - (b.x - a.x) * (c.y - b.y); return angle > -0.00001f; }; for (i = 0; i < src_count; i++) { v2f p = src[i]; if (p.y < p0.y || (fabsf(p.y - p0.y) < 0.0001f && p.x < p0.x)) p0 = p; } std::sort( src, src + src_count, [this](const v2f& f, const v2f& s) { float a = (f.y - p0.y) * (s.x - f.x) - (f.x - p0.x) * (s.y - f.y); bool colinear = fabsf(a - 0.0f) < 0.001f; if (colinear) return v2f::mag(p0 - s) >= v2f::mag(p0 - f); return a < 0.0f; } ); for (i = 0; i < src_count; i++) { v2f p = src[i]; while (top > 1 && ccw(peek(1), peek(0), p)) pop(); push(p); } while (top) points[count++] = pop(); free(stack); } }; int main(int argc, const char** argv) { int r = 1; float rot = 3.5f; SDL_Window* window; SDL_Renderer* ren; SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); SDL_CreateWindowAndRenderer( 800, 800, 0, &window, &ren ); v2f points[] = { { 129.0f, 148.0f }, { 178.0f, 178.0f }, { 146.0f, 146.0f }, { 163.0f, 172.0f }, { 129.0f, 159.0f }, { 102.0f, 151.0f }, { 167.0f, 122.0f } }; float rots[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, }; constexpr int point_count = sizeof points / sizeof *points; v2f points2[point_count]; while (r) { int i; SDL_Event e; while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_QUIT: r = 0; break; } } for (i = 0; i < point_count; i++) { v2f p = points[i]; points2[i] = v2f( p.x * 2 + (sinf(rot * rots[i]) * p.x - cosf(rot * rots[i]) * p.y), p.y * 2 + (sinf(rot * rots[i]) * p.x + cosf(rot * rots[i]) * p.y) ); } Shrinkwrap s(points2, point_count); SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0x00); SDL_RenderClear(ren); for (int i = 0; i < s.count; i++) { v2f a = s.points[i]; v2f b = s.points[(i + 1) % s.count]; v2f e = a - b; v2f h = e * 0.5f; v2f n = v2f(e.y, -e.x); n = v2f::normalised(n); SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0xff, 0xff); SDL_RenderDrawLine(ren, (int)a.x, (int)a.y, (int)b.x, (int)b.y); SDL_SetRenderDrawColor(ren, 0xff, 0x00, 0xff, 0xff); SDL_RenderDrawLine( ren, (int)(a.x - h.x), (int)(a.y - h.y), (int)((a.x - h.x) + n.x * 32.0f), (int)((a.y - h.y) + n.y * 32.0f) ); } SDL_SetRenderDrawColor(ren, 0xff, 0x00, 0x00, 0xff); for (i = 0; i < point_count; i++) { v2f p = points2[i]; SDL_RenderDrawPoint(ren, (int)p.x, (int)p.y); } SDL_SetRenderDrawColor(ren, 0x00, 0xff, 0x00, 0xff); SDL_RenderDrawPoint(ren, (int)s.p0.x, (int)s.p0.y); SDL_RenderPresent(ren); free(s.points); rot += 0.0003f; } SDL_DestroyRenderer(ren); SDL_DestroyWindow(window); SDL_Quit(); return 0; }