// File: /workspace/github_c_makefile_star2_O3/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 $0xd8, %rsp
movq %rsi, %r14
movl %edi, %ebx
xorl %ecx, %ecx
testl %edi, %edi
setne %cl
leaq 0xd3e0(%rip), %rdi      # 0x31a0b
leaq 0xd3fc(%rip), %rdx      # 0x31a2e
movl $0x14, %esi
callq 0x729c
movl $0x0, -0x90(%rbp)
movl %ebx, %edi
callq 0x2f363
movq %rax, %r12
movl %ebx, %r15d
movq %r15, -0x68(%rbp)
movq %rax, -0x60(%rbp)
movb $0x1, -0x58(%rbp)
xorps %xmm2, %xmm2
movl %ebx, -0x40(%rbp)
testl %ebx, %ebx
movq %r15, -0xa8(%rbp)
je 0x247f9
movq %r12, -0xc0(%rbp)
leaq -0x1(%r15), %rbx
xorps %xmm5, %xmm5
leaq 0xd3c7(%rip), %r12      # 0x31a50
xorl %r8d, %r8d
xorl %eax, %eax
xorl %r13d, %r13d
movl %r13d, %esi
movl %eax, %ecx
leal -0x1(%r8), %eax
xorl %edx, %edx
divl -0x40(%rbp)
movsd (%r14,%rdx,8), %xmm0
movsd (%r14,%r8,8), %xmm1
incq %r8
cmpq %r15, %r8
movl %r8d, %eax
movl $0x0, %edx
cmovneq %rax, %rdx
movss (%r14,%rdx,8), %xmm2
movss 0x4(%r14,%rdx,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 %r13d, %r13d
ucomiss %xmm5, %xmm3
seta %al
setbe %r13b
addl %esi, %r13d
addl %ecx, %eax
je 0x247cd
testl %r13d, %r13d
je 0x247cd
movl %eax, -0xa0(%rbp)
movq %r8, -0x50(%rbp)
xorps %xmm0, %xmm0
cvtss2sd (%r14), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0xc(%r14), %xmm1
leaq 0xd321(%rip), %rdi      # 0x31a52
movb $0x2, %al
callq 0xa899
cmpl $0x1, -0x40(%rbp)
je 0x2476a
xorl %r15d, %r15d
xorps %xmm0, %xmm0
cvtss2sd 0x8(%r14,%r15,8), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0xc(%r14,%r15,8), %xmm1
movq %r12, %rdi
movq %rax, %rsi
movb $0x2, %al
callq 0xa899
incq %r15
cmpq %r15, %rbx
jne 0x24741
movq 0x2a85f(%rip), %rcx     # 0x4efd0
movq (%rcx), %rsi
movq %rax, (%rsp)
leaq 0xc520(%rip), %rdi      # 0x30c9f
leaq 0xd285(%rip), %r15      # 0x31a0b
movq %r15, %rdx
movl $0x35, %ecx
leaq 0xd2ca(%rip), %r8       # 0x31a5f
leaq 0xd2cd(%rip), %r9       # 0x31a69
xorl %eax, %eax
callq 0x718c
movq %r15, %rdi
movl $0x36, %esi
leaq 0xd2f6(%rip), %rdx      # 0x31aa8
xorl %ecx, %ecx
callq 0x729c
movq -0xa8(%rbp), %r15
xorps %xmm5, %xmm5
movq -0x50(%rbp), %r8
movl -0xa0(%rbp), %eax
cmpq %r15, %r8
jne 0x24691
cmpl $0x0, -0x40(%rbp)
movq -0xc0(%rbp), %r12
xorps %xmm2, %xmm2
je 0x247f9
xorl %ecx, %ecx
movsd (%r14,%rcx,8), %xmm0
addps %xmm0, %xmm2
incq %rcx
cmpq %rcx, %r15
jne 0x247e8
xorps %xmm0, %xmm0
cvtsi2ss %r15, %xmm0
movss 0xb7fb(%rip), %xmm1     # 0x30004
divss %xmm0, %xmm1
movaps %xmm1, %xmm3
mulss %xmm2, %xmm3
shufps $0x55, %xmm2, %xmm2     # xmm2 = xmm2[1,1,1,1]
mulss %xmm1, %xmm2
movaps %xmm3, %xmm0
unpcklps %xmm2, %xmm0            # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
movlps %xmm0, -0x8c(%rbp)
cmpl $0x0, -0x40(%rbp)
je 0x2489a
xorl %ebx, %ebx
leaq 0x21173(%rip), %r13     # 0x459ab
movaps %xmm2, -0xa0(%rbp)
movaps %xmm3, -0xc0(%rbp)
movss (%r14,%rbx,8), %xmm1
movss 0x4(%r14,%rbx,8), %xmm0
subss %xmm3, %xmm1
subss %xmm2, %xmm0
unpcklps %xmm0, %xmm1            # xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
movaps %xmm1, -0x50(%rbp)
leaq 0x21125(%rip), %rdi     # 0x4598e
movl $0x21, %esi
movq %r13, %rdx
movl $0x1, %ecx
callq 0x729c
movaps -0xc0(%rbp), %xmm3
movaps -0xa0(%rbp), %xmm2
movaps -0x50(%rbp), %xmm0
movlps %xmm0, (%r12,%rbx,8)
incq %rbx
cmpq %rbx, %r15
jne 0x24846
movl -0x40(%rbp), %ebx
movl %ebx, -0x64(%rbp)
movl %ebx, %edi
callq 0x2f363
movq %r15, -0x80(%rbp)
movq %rax, -0x78(%rbp)
movb $0x1, -0x70(%rbp)
testl %ebx, %ebx
je 0x24a59
xorl %r14d, %r14d
leaq 0x210c9(%rip), %r15     # 0x4598e
leaq 0x210df(%rip), %r12     # 0x459ab
xorl %ecx, %ecx
cmpb $0x0, -0x58(%rbp)
setne %cl
movq %r15, %rdi
movl $0x21, %esi
movq %r12, %rdx
callq 0x729c
movq -0x60(%rbp), %rax
movss (%rax,%r14,8), %xmm0
movaps %xmm0, -0x40(%rbp)
movss 0x4(%rax,%r14,8), %xmm0
movaps %xmm0, -0x50(%rbp)
incq %r14
movl %r14d, %eax
xorl %edx, %edx
divl -0x64(%rbp)
movl %edx, %r13d
xorl %ecx, %ecx
cmpb $0x0, -0x58(%rbp)
setne %cl
movq %r15, %rdi
movl $0x21, %esi
movq %r12, %rdx
callq 0x729c
movq -0x60(%rbp), %rax
movsd (%rax,%r13,8), %xmm0
movaps -0x40(%rbp), %xmm3
subss %xmm0, %xmm3
shufps $0x55, %xmm0, %xmm0     # xmm0 = xmm0[1,1,1,1]
movaps -0x50(%rbp), %xmm2
subss %xmm0, %xmm2
movaps %xmm2, %xmm0
mulss %xmm2, %xmm0
movaps %xmm3, %xmm1
mulss %xmm3, %xmm1
addss %xmm0, %xmm1
xorps %xmm0, %xmm0
sqrtss %xmm1, %xmm0
movss 0xb6a0(%rip), %xmm1     # 0x30004
divss %xmm0, %xmm1
mulss %xmm1, %xmm3
movaps %xmm3, -0x40(%rbp)
xorps 0xb6c9(%rip), %xmm2     # 0x30040
mulss %xmm1, %xmm2
movaps %xmm2, -0x50(%rbp)
cmpl $0x0, -0x7c(%rbp)
je 0x24a3b
xorl %ebx, %ebx
xorl %ecx, %ecx
cmpb $0x0, -0x70(%rbp)
setne %cl
movq %r15, %rdi
movl $0x21, %esi
movq %r12, %rdx
callq 0x729c
movq -0x78(%rbp), %rax
movsd (%rax,%rbx,8), %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, -0xa0(%rbp)
xorl %ecx, %ecx
cmpb $0x0, -0x70(%rbp)
setne %cl
movq %r15, %rdi
movl $0x21, %esi
movq %r12, %rdx
callq 0x729c
movq -0x78(%rbp), %rax
movsd (%rax,%rbx,8), %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 -0xa0(%rbp), %xmm2
cmpltss 0xb828(%rip), %xmm2     # 0x30238
movaps %xmm2, %xmm1
andnps %xmm0, %xmm1
xorps 0xb623(%rip), %xmm0     # 0x30040
andps %xmm2, %xmm0
orps %xmm1, %xmm0
ucomiss 0xb826(%rip), %xmm0     # 0x30250
jae 0x24a4c
incq %rbx
movl -0x7c(%rbp), %eax
cmpq %rax, %rbx
jb 0x2498b
movaps -0x50(%rbp), %xmm0
unpcklps -0x40(%rbp), %xmm0      # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
leaq -0x80(%rbp), %rdi
callq 0x2ebfe
cmpq -0xa8(%rbp), %r14
jne 0x248cc
leaq 0x3fee0(%rip), %rdi     # 0x64940
movl 0x4(%rdi), %eax
movl %eax, -0x90(%rbp)
movups -0x90(%rbp), %xmm0
movups -0x80(%rbp), %xmm1
movups -0x70(%rbp), %xmm2
movups -0x60(%rbp), %xmm3
movups %xmm3, 0x30(%rsp)
movups %xmm2, 0x20(%rsp)
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
callq 0x2ec62
movl -0x90(%rbp), %eax
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq