// File: FreeSlave[P]vhlt/hlvis/flow.cpp
// Function: ChopWinding(winding_t*, pstack_s*, plane_t const*)
inline winding_t*      ChopWinding(winding_t* const in, pstack_t* const stack, const plane_t* const split)
{
    vec_t           dists[128];
    int             sides[128];
    int             counts[3];
    vec_t           dot;
    int             i;
    vec3_t          mid;
    winding_t*      neww;

    counts[0] = counts[1] = counts[2] = 0;

    if (in->numpoints > (sizeof(sides) / sizeof(*sides)))
    {
        Error("Winding with too many sides!");
    }

    // determine sides for each point
    for (i = 0; i < in->numpoints; i++)
    {
        dot = DotProduct(in->points[i], split->normal);
        dot -= split->dist;
        dists[i] = dot;
        if (dot > ON_EPSILON)
        {
            sides[i] = SIDE_FRONT;
        }
        else if (dot < -ON_EPSILON)
        {
            sides[i] = SIDE_BACK;
        }
        else
        {
            sides[i] = SIDE_ON;
        }
        counts[sides[i]]++;
    }

    if (!counts[1])
    {
        return in;                                         // completely on front side
    }

    if (!counts[0])
    {
        FreeStackWinding(in, stack);
        return NULL;
    }

    sides[i] = sides[0];
    dists[i] = dists[0];

    neww = AllocStackWinding(stack);

    neww->numpoints = 0;

    for (i = 0; i < in->numpoints; i++)
    {
        vec_t* p1 = in->points[i];

        if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
        {
            Warning("ChopWinding : rejected(1) due to too many points\n");
            FreeStackWinding(neww, stack);
            return in;                                     // can't chop -- fall back to original
        }

        if (sides[i] == SIDE_ON)
        {
            VectorCopy(p1, neww->points[neww->numpoints]);
            neww->numpoints++;
            continue;
        }
        else if (sides[i] == SIDE_FRONT)
        {
            VectorCopy(p1, neww->points[neww->numpoints]);
            neww->numpoints++;
        }

        if ((sides[i + 1] == SIDE_ON) | (sides[i + 1] == sides[i])) // | instead of || for branch optimization
        {
            continue;
        }

        if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
        {
            Warning("ChopWinding : rejected(2) due to too many points\n");
            FreeStackWinding(neww, stack);
            return in;                                     // can't chop -- fall back to original
        }

        // generate a split point
        {
            unsigned tmp = i + 1;
            if (tmp >= in->numpoints)
            {
                tmp = 0;
            }
            const vec_t* p2 = in->points[tmp];

            dot = dists[i] / (dists[i] - dists[i + 1]);

            const vec_t* normal = split->normal;
            const vec_t dist = split->dist;
            unsigned int j;
            for (j = 0; j < 3; j++)
            {                                                  // avoid round off error when possible
                if (normal[j] < (1.0 - NORMAL_EPSILON))
                {
                    if (normal[j] > (-1.0 + NORMAL_EPSILON))
                    {
                        mid[j] = p1[j] + dot * (p2[j] - p1[j]);
                    }
                    else
                    {
                        mid[j] = -dist;
                    }
                }
                else
                {
                    mid[j] = dist;
                }
            }
        }

        VectorCopy(mid, neww->points[neww->numpoints]);
        neww->numpoints++;
    }

    // free the original winding
    FreeStackWinding(in, stack);

    return neww;
}

// Assembly:
subq $0x478, %rsp            # imm = 0x478
movq %rdi, 0x468(%rsp)
movq %rsi, 0x460(%rsp)
movq %rdx, 0x458(%rsp)
movl $0x0, 0x4c(%rsp)
movl $0x0, 0x48(%rsp)
movl $0x0, 0x44(%rsp)
movq 0x468(%rsp), %rax
movslq 0x4(%rax), %rax
cmpq $0x80, %rax
jbe 0x14d39
leaq 0x7961(%rip), %rdi      # 0x1c693
movb $0x0, %al
callq 0xa380
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
movq 0x468(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x14e9b
movq 0x468(%rsp), %rax
addq $0x8, %rax
movslq 0x3c(%rsp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss (%rax), %xmm1
movq 0x458(%rsp), %rax
movss (%rax), %xmm2
movq 0x468(%rsp), %rax
addq $0x8, %rax
movslq 0x3c(%rsp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss 0x4(%rax), %xmm0
movq 0x458(%rsp), %rax
mulss 0x4(%rax), %xmm0
mulss %xmm2, %xmm1
addss %xmm0, %xmm1
movq 0x468(%rsp), %rax
addq $0x8, %rax
movslq 0x3c(%rsp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss 0x8(%rax), %xmm0
movq 0x458(%rsp), %rax
movss 0x8(%rax), %xmm2
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, 0x40(%rsp)
movq 0x458(%rsp), %rax
movss 0xc(%rax), %xmm1
movss 0x40(%rsp), %xmm0
subss %xmm1, %xmm0
movss %xmm0, 0x40(%rsp)
movss 0x40(%rsp), %xmm0
movslq 0x3c(%rsp), %rax
movss %xmm0, 0x250(%rsp,%rax,4)
movss 0x40(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x7805(%rip), %xmm1     # 0x1c630
ucomisd %xmm1, %xmm0
jbe 0x14e40
movslq 0x3c(%rsp), %rax
movl $0x0, 0x50(%rsp,%rax,4)
jmp 0x14e76
movss 0x40(%rsp), %xmm0
cvtss2sd %xmm0, %xmm1
movsd 0x77e6(%rip), %xmm0     # 0x1c638
ucomisd %xmm1, %xmm0
jbe 0x14e67
movslq 0x3c(%rsp), %rax
movl $0x1, 0x50(%rsp,%rax,4)
jmp 0x14e74
movslq 0x3c(%rsp), %rax
movl $0x2, 0x50(%rsp,%rax,4)
jmp 0x14e76
movslq 0x3c(%rsp), %rax
movslq 0x50(%rsp,%rax,4), %rax
movl 0x44(%rsp,%rax,4), %ecx
addl $0x1, %ecx
movl %ecx, 0x44(%rsp,%rax,4)
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x14d41
cmpl $0x0, 0x48(%rsp)
jne 0x14eb7
movq 0x468(%rsp), %rax
movq %rax, 0x470(%rsp)
jmp 0x15360
cmpl $0x0, 0x44(%rsp)
jne 0x14ee4
movq 0x468(%rsp), %rdi
movq 0x460(%rsp), %rsi
callq 0x14a50
movq $0x0, 0x470(%rsp)
jmp 0x15360
movl 0x50(%rsp), %ecx
movslq 0x3c(%rsp), %rax
movl %ecx, 0x50(%rsp,%rax,4)
movss 0x250(%rsp), %xmm0
movslq 0x3c(%rsp), %rax
movss %xmm0, 0x250(%rsp,%rax,4)
movq 0x460(%rsp), %rdi
callq 0x14ad0
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rax
movl $0x0, 0x4(%rax)
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
movq 0x468(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jge 0x1533e
movq 0x468(%rsp), %rax
addq $0x8, %rax
movslq 0x3c(%rsp), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x28(%rsp), %rax
cmpl $0x20, 0x4(%rax)
jne 0x14fa0
leaq 0x773e(%rip), %rdi      # 0x1c6b0
movb $0x0, %al
callq 0xa7f0
movq 0x28(%rsp), %rdi
movq 0x460(%rsp), %rsi
callq 0x14a50
movq 0x468(%rsp), %rax
movq %rax, 0x470(%rsp)
jmp 0x15360
movslq 0x3c(%rsp), %rax
cmpl $0x2, 0x50(%rsp,%rax,4)
jne 0x15039
movq 0x20(%rsp), %rax
movss (%rax), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, (%rax)
movq 0x20(%rsp), %rax
movss 0x4(%rax), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, 0x4(%rax)
movq 0x20(%rsp), %rax
movss 0x8(%rax), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, 0x8(%rax)
movq 0x28(%rsp), %rax
movl 0x4(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x4(%rax)
jmp 0x1532e
movslq 0x3c(%rsp), %rax
cmpl $0x0, 0x50(%rsp,%rax,4)
jne 0x150cd
movq 0x20(%rsp), %rax
movss (%rax), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, (%rax)
movq 0x20(%rsp), %rax
movss 0x4(%rax), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, 0x4(%rax)
movq 0x20(%rsp), %rax
movss 0x8(%rax), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, 0x8(%rax)
movq 0x28(%rsp), %rax
movl 0x4(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x4(%rax)
jmp 0x150cf
movl 0x3c(%rsp), %eax
addl $0x1, %eax
cltq
cmpl $0x2, 0x50(%rsp,%rax,4)
sete %al
andb $0x1, %al
movzbl %al, %eax
movl 0x3c(%rsp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movl 0x50(%rsp,%rcx,4), %ecx
movslq 0x3c(%rsp), %rdx
cmpl 0x50(%rsp,%rdx,4), %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %ecx
orl %ecx, %eax
cmpl $0x0, %eax
je 0x15111
jmp 0x1532e
movq 0x28(%rsp), %rax
cmpl $0x20, 0x4(%rax)
jne 0x15151
leaq 0x75bf(%rip), %rdi      # 0x1c6e2
movb $0x0, %al
callq 0xa7f0
movq 0x28(%rsp), %rdi
movq 0x460(%rsp), %rsi
callq 0x14a50
movq 0x468(%rsp), %rax
movq %rax, 0x470(%rsp)
jmp 0x15360
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
movq 0x468(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jb 0x15175
movl $0x0, 0x1c(%rsp)
movq 0x468(%rsp), %rax
addq $0x8, %rax
movl 0x1c(%rsp), %ecx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x10(%rsp)
movslq 0x3c(%rsp), %rax
movss 0x250(%rsp,%rax,4), %xmm0
movslq 0x3c(%rsp), %rax
movss 0x250(%rsp,%rax,4), %xmm1
movl 0x3c(%rsp), %eax
addl $0x1, %eax
cltq
subss 0x250(%rsp,%rax,4), %xmm1
divss %xmm1, %xmm0
movss %xmm0, 0x40(%rsp)
movq 0x458(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x458(%rsp), %rax
movss 0xc(%rax), %xmm0
movss %xmm0, 0x4(%rsp)
movl $0x0, (%rsp)
cmpl $0x3, (%rsp)
jae 0x152b5
movq 0x8(%rsp), %rax
movl (%rsp), %ecx
movss (%rax,%rcx,4), %xmm0
cvtss2sd %xmm0, %xmm1
movsd 0x743d(%rip), %xmm0     # 0x1c650
ucomisd %xmm1, %xmm0
jbe 0x15296
movq 0x8(%rsp), %rax
movl (%rsp), %ecx
movss (%rax,%rcx,4), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x3e3e(%rip), %xmm1     # 0x19070
ucomisd %xmm1, %xmm0
jbe 0x15278
movq 0x20(%rsp), %rax
movl (%rsp), %ecx
movss (%rax,%rcx,4), %xmm1
movss 0x40(%rsp), %xmm0
movq 0x10(%rsp), %rax
movl (%rsp), %ecx
movss (%rax,%rcx,4), %xmm2
movq 0x20(%rsp), %rax
movl (%rsp), %ecx
subss (%rax,%rcx,4), %xmm2
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movl (%rsp), %eax
movss %xmm0, 0x30(%rsp,%rax,4)
jmp 0x15294
movss 0x4(%rsp), %xmm0
movd %xmm0, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm0
movl (%rsp), %eax
movss %xmm0, 0x30(%rsp,%rax,4)
jmp 0x152a5
movss 0x4(%rsp), %xmm0
movl (%rsp), %eax
movss %xmm0, 0x30(%rsp,%rax,4)
jmp 0x152a7
movl (%rsp), %eax
addl $0x1, %eax
movl %eax, (%rsp)
jmp 0x151f0
movss 0x30(%rsp), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, (%rax)
movss 0x34(%rsp), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, 0x4(%rax)
movss 0x38(%rsp), %xmm0
movq 0x28(%rsp), %rax
addq $0x8, %rax
movq 0x28(%rsp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
movss %xmm0, 0x8(%rax)
movq 0x28(%rsp), %rax
movl 0x4(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x4(%rax)
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x14f2e
movq 0x468(%rsp), %rdi
movq 0x460(%rsp), %rsi
callq 0x14a50
movq 0x28(%rsp), %rax
movq %rax, 0x470(%rsp)
movq 0x470(%rsp), %rax
addq $0x478, %rsp            # imm = 0x478
retq