// File: /workspace/github_c_makefile_star2_O2/FredTheDino[P]Fog/src/engine/logic/block_physics.cpp
// Function: Physics::add_shape(unsigned int, Vec2*)
ShapeID add_shape(u32 points_length, Vec2 *points) {
    // Assumes the shape is convex.
    ASSERT(points_length != 0, "Invalid list!");
    Shape shape = {};
    shape.points = create_list<Vec2>(points_length);

    // Check for non-convex polygons.
    // We can do this while looping over
    // the points checking for the center, but I don't
    // think performance will be an issue here.
    // -- Ed
    u32 positiv_cross = 0;
    u32 negative_cross = 0;
    for (u32 i = 0; i < points_length; i++) {
        Vec2 a = points[(i - 1) % points_length];
        Vec2 b = points[(i + 0) % points_length];
        Vec2 c = points[(i + 1) % points_length];
        Vec2 ab = b - a;
        Vec2 bc = c - b;
        auto winding_is_positive = [](Vec2 a, Vec2 b) -> b8 {
            return (a.x * b.y - a.y * b.x) > 0;
        };
        if (winding_is_positive(ab, bc))
            positiv_cross += 1;
        else
            negative_cross += 1;

        if (positiv_cross != 0 && negative_cross != 0) {
            char *shape_dump = Util::format_int("\t%.5f, %.5f\n",
                                            points[0].x, points[1].y);
            for (u32 a = 1; a < points_length; a++) {
                shape_dump = Util::format_int("%s\t%.5f, %.5f\n",
                                          shape_dump, points[a].x, points[a].y);
            }
            ERR("Invalid shape, a given shape is not convex. The shape was:\n %s",
                shape_dump);
            ASSERT(false, "Invalid shape.");
        }
    }


    // We need the center to lay inside the shapes
    // for the SAT algorithm to work.
    Vec2 center = V2(0, 0);
    for (u32 i = 0; i < points_length; i++) center = center + points[i];
    center /= (real) points_length;
    shape.center = center;

    for (u32 i = 0; i < points_length; i++)
        shape.points[i] = points[i] - center;
    shape.points.length = points_length;  // Change the length to match.
    // Allocate worstcase memory.
    // This is a tad wastefull but it shouldn't be much
    // since most shapes should be fairly simple in their
    // design, and they are reusable.
    shape.normals = create_list<Vec2>(points_length);
    for (u32 i = 0; i < points_length; i++) {
        Vec2 v = shape.points[i];
        Vec2 u = shape.points[(i + 1) % shape.points.length];

        Vec2 relative = normalize(v - u);
        Vec2 normal = {-relative.y, relative.x};

        // If they share the same axis with something else.
        // Sure it's slow to check now, but it does save time
        // in the long run since it can cut the checks in half
        // on a symetric shape. It's cool.
        for (u32 j = 0; j < shape.normals.length; j++) {
            if (ABS(dot(normal, shape.normals[j])) >= 0.98f) {
                goto _CONTINUE_OUTER_REG_SHAPE;
            }
        }

        shape.normals.append(normal);
    _CONTINUE_OUTER_REG_SHAPE:
        continue;
    }

    shape.id = global_shape_list.length;
    global_shape_list.append(shape);
    return shape.id;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movq %rsi, %r12
movl %edi, %r14d
xorl %ecx, %ecx
testl %edi, %edi
setne %cl
leaq 0xa54f(%rip), %rdi      # 0x2c9e3
leaq 0xa56b(%rip), %rdx      # 0x2ca06
pushq $0x14
popq %rsi
callq 0x6903
leaq -0x90(%rbp), %rax
andl $0x0, -0x10(%rax)
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movb $0x0, 0x10(%rax)
leaq -0x78(%rbp), %rbx
movl %r14d, %edi
callq 0x2ad85
movl %r14d, -0x50(%rbp)
movl %r14d, %esi
movq %rsi, (%rbx)
movq %rax, 0x8(%rbx)
movb $0x1, 0x10(%rbx)
leaq -0x1(%rsi), %r15
xorps %xmm5, %xmm5
leaq 0xa544(%rip), %r13      # 0x2ca28
xorl %r14d, %r14d
xorl %edi, %edi
xorl %r8d, %r8d
movq %rsi, -0x30(%rbp)
cmpq %rsi, %r14
je 0x2260e
leal -0x1(%r14), %eax
xorl %edx, %edx
divl -0x50(%rbp)
movsd (%r12,%rdx,8), %xmm0
movsd (%r12,%r14,8), %xmm1
incq %r14
cmpq %rsi, %r14
movl %r14d, %eax
movl $0x0, %ecx
cmovneq %rax, %rcx
movss (%r12,%rcx,8), %xmm2
movss 0x4(%r12,%rcx,8), %xmm3
movaps %xmm1, %xmm4
subps %xmm0, %xmm4
subss %xmm1, %xmm2
shufps $0x55, %xmm1, %xmm1     # xmm1 = xmm1[1,1,1,1]
subss %xmm1, %xmm3
mulss %xmm4, %xmm3
shufps $0x55, %xmm4, %xmm4     # xmm4 = xmm4[1,1,1,1]
mulss %xmm4, %xmm2
subss %xmm2, %xmm3
xorl %eax, %eax
xorl %ecx, %ecx
ucomiss %xmm5, %xmm3
seta %al
setbe %cl
addl %ecx, %edi
addl %eax, %r8d
je 0x224f0
testl %edi, %edi
je 0x224f0
movl %r8d, -0x60(%rbp)
movl %edi, -0x40(%rbp)
cvtss2sd (%r12), %xmm0
cvtss2sd 0xc(%r12), %xmm1
leaq 0xa4a8(%rip), %rdi      # 0x2ca2a
movb $0x2, %al
callq 0x9642
xorl %ebx, %ebx
cmpq %rbx, %r15
je 0x225b0
cvtss2sd 0x8(%r12,%rbx,8), %xmm0
cvtss2sd 0xc(%r12,%rbx,8), %xmm1
movq %r13, %rdi
movq %rax, %rsi
movb $0x2, %al
callq 0x9642
incq %rbx
jmp 0x2258b
movq 0x27a19(%rip), %rcx     # 0x49fd0
movq (%rcx), %rsi
movq %rax, (%rsp)
leaq 0x96b2(%rip), %rdi      # 0x2bc77
leaq 0xa417(%rip), %rbx      # 0x2c9e3
movq %rbx, %rdx
pushq $0x35
popq %rcx
leaq 0xa45e(%rip), %r8       # 0x2ca37
leaq 0xa461(%rip), %r9       # 0x2ca41
xorl %eax, %eax
callq 0x683a
movq %rbx, %rdi
pushq $0x36
popq %rsi
leaq 0xa48c(%rip), %rdx      # 0x2ca80
xorl %ecx, %ecx
callq 0x6903
movq -0x30(%rbp), %rsi
xorps %xmm5, %xmm5
movl -0x40(%rbp), %edi
movl -0x60(%rbp), %r8d
jmp 0x224f0
xorps %xmm2, %xmm2
xorl %eax, %eax
leaq -0x90(%rbp), %rbx
leaq -0x78(%rbp), %r14
cmpq %rax, %rsi
je 0x22631
movsd (%r12,%rax,8), %xmm0
addps %xmm0, %xmm2
incq %rax
jmp 0x2261e
cvtsi2ss %rsi, %xmm0
movss 0x89c6(%rip), %xmm1     # 0x2b004
divss %xmm0, %xmm1
movaps %xmm1, %xmm0
mulss %xmm2, %xmm0
shufps $0x55, %xmm2, %xmm2     # xmm2 = xmm2[1,1,1,1]
mulss %xmm1, %xmm2
movaps %xmm0, -0xb0(%rbp)
movaps %xmm2, -0x60(%rbp)
unpcklps %xmm2, %xmm0            # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
movlps %xmm0, -0x9c(%rbp)
xorl %r13d, %r13d
cmpq %r13, %rsi
je 0x226aa
movss (%r12,%r13,8), %xmm1
movss 0x4(%r12,%r13,8), %xmm0
subss -0xb0(%rbp), %xmm1
subss -0x60(%rbp), %xmm0
unpcklps %xmm0, %xmm1            # xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
movaps %xmm1, -0x40(%rbp)
movq %r14, %rdi
movl %r13d, %esi
callq 0x2a6a8
movaps -0x40(%rbp), %xmm0
movlps %xmm0, (%rax)
incq %r13
movq -0x30(%rbp), %rsi
jmp 0x22669
movl -0x50(%rbp), %edi
movl %edi, -0x74(%rbp)
callq 0x2ad85
movq -0x30(%rbp), %rcx
movq %rcx, -0x90(%rbp)
movq %rax, -0x88(%rbp)
movb $0x1, -0x80(%rbp)
xorl %r15d, %r15d
cmpl %ecx, %r15d
je 0x227ed
movq %r14, %rdi
movl %r15d, %esi
callq 0x2a6a8
movss (%rax), %xmm0
movaps %xmm0, -0x50(%rbp)
movss 0x4(%rax), %xmm0
movaps %xmm0, -0x40(%rbp)
incl %r15d
xorl %r12d, %r12d
movl %r15d, %eax
xorl %edx, %edx
divl -0x74(%rbp)
movq %r14, %rdi
movl %edx, %esi
callq 0x2a6a8
movsd (%rax), %xmm0
movaps -0x50(%rbp), %xmm1
subss %xmm0, %xmm1
shufps $0x55, %xmm0, %xmm0     # xmm0 = xmm0[1,1,1,1]
movaps -0x40(%rbp), %xmm2
subss %xmm0, %xmm2
unpcklps %xmm2, %xmm1            # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movaps %xmm1, %xmm0
callq 0x6a2a
movaps %xmm0, %xmm1
shufps $0x55, %xmm0, %xmm1     # xmm1 = xmm1[1,1],xmm0[1,1]
xorps 0x8904(%rip), %xmm1     # 0x2b040
movaps %xmm1, -0x50(%rbp)
movaps %xmm0, -0x40(%rbp)
unpcklps %xmm0, %xmm1            # xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
movaps %xmm1, -0xb0(%rbp)
cmpl -0x8c(%rbp), %r12d
jae 0x227d5
movq %rbx, %rdi
movl %r12d, %esi
callq 0x2a6a8
movsd (%rax), %xmm1
movaps %xmm1, %xmm0
shufps $0x55, %xmm1, %xmm0     # xmm0 = xmm0[1,1],xmm1[1,1]
mulss -0x40(%rbp), %xmm0
mulss -0x50(%rbp), %xmm1
addss %xmm0, %xmm1
movaps %xmm1, -0x60(%rbp)
movq %rbx, %rdi
movl %r12d, %esi
callq 0x2a6a8
movsd (%rax), %xmm0
movaps %xmm0, %xmm1
shufps $0x55, %xmm0, %xmm1     # xmm1 = xmm1[1,1],xmm0[1,1]
mulss -0x40(%rbp), %xmm1
mulss -0x50(%rbp), %xmm0
addss %xmm1, %xmm0
movaps -0x60(%rbp), %xmm2
cmpltss 0x8a7c(%rip), %xmm2     # 0x2b22c
movaps %xmm2, %xmm1
andnps %xmm0, %xmm1
xorps 0x8883(%rip), %xmm0     # 0x2b040
andps %xmm2, %xmm0
orps %xmm1, %xmm0
incl %r12d
ucomiss 0x8a7f(%rip), %xmm0     # 0x2b24c
jb 0x2274e
jmp 0x227e4
movq %rbx, %rdi
movaps -0xb0(%rbp), %xmm0
callq 0x2a6e2
movq -0x30(%rbp), %rcx
jmp 0x226ce
leaq 0x3d15c(%rip), %rdi     # 0x5f950
movl 0x4(%rdi), %eax
movl %eax, -0xa0(%rbp)
movups -0xa0(%rbp), %xmm0
movups -0x90(%rbp), %xmm1
movups -0x80(%rbp), %xmm2
movups -0x70(%rbp), %xmm3
movups %xmm3, 0x30(%rsp)
movups %xmm2, 0x20(%rsp)
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
callq 0x2a744
movl -0xa0(%rbp), %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq