// File: /workspace/github_cpp_makefile_star2_O2/YiweiMao[P]tessDX/src/tessellator.cpp
// Function: CHWTessellator::TriGeneratePoints(CHWTessellator::PROCESSED_TESS_FACTORS_TRI const&)
void CHWTessellator::TriGeneratePoints( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors )
{
    // Generate exterior ring edge points, clockwise starting from point V (VW, the U==0 edge)
    int pointOffset = 0;
    int edge;
    for(edge = 0; edge < TRI_EDGES; edge++ )
    {
        int parity = edge&0x1;
        int startPoint = 0;
        int endPoint = processedTessFactors.numPointsForOutsideEdge[edge] - 1;
        for(int p = startPoint; p < endPoint; p++, pointOffset++) // don't include end, since next edge starts with it.
        {
            FXP fxpParam;
            int q = (parity) ? p : endPoint - p; // whether to reverse point order given we are defining V or U (W implicit):
                                                 // edge0, VW, has V decreasing, so reverse 1D points below
                                                 // edge1, WU, has U increasing, so don't reverse 1D points  below
                                                 // edge2, UV, has U decreasing, so reverse 1D points below
            SetTessellationParity(processedTessFactors.outsideTessFactorParity[edge]);
            PlacePointIn1D(processedTessFactors.outsideTessFactorCtx[edge],q,fxpParam);
            if( edge == 0 )
            {
                DefinePoint(/*U*/0,
                            /*V*/fxpParam,
                            /*pointStorageOffset*/pointOffset);
            }
            else
            {
                DefinePoint(/*U*/fxpParam,
                            /*V*/(edge == 2) ? FXP_ONE - fxpParam : 0,
                            /*pointStorageOffset*/pointOffset);
            }
        }
    }

    // Generate interior ring points, clockwise spiralling in
    SetTessellationParity(processedTessFactors.insideTessFactorParity);
    static const int startRing = 1;
    int numRings = (processedTessFactors.numPointsForInsideTessFactor >> 1);
    for(int ring = startRing; ring < numRings; ring++)
    {
        int startPoint = ring;
        int endPoint = processedTessFactors.numPointsForInsideTessFactor - 1 - startPoint;

        for(edge = 0; edge < TRI_EDGES; edge++ )
        {
            int parity = edge&0x1;
            int perpendicularAxisPoint = startPoint;
            FXP fxpPerpParam;
            PlacePointIn1D(processedTessFactors.insideTessFactorCtx,perpendicularAxisPoint,fxpPerpParam);
            fxpPerpParam *= FXP_TWO_THIRDS; // Map location to the right size in barycentric space.
                                         // I (amarp) can draw a picture to explain.
                                         // We know this fixed point math won't over/underflow
            fxpPerpParam = (fxpPerpParam+FXP_ONE_HALF/*round*/)>>FXP_FRACTION_BITS; // get back to n.16
            for(int p = startPoint; p < endPoint; p++, pointOffset++) // don't include end: next edge starts with it. 
            {
                FXP fxpParam;
                int q = (parity) ? p : endPoint - (p - startPoint); // whether to reverse point given we are defining V or U (W implicit):
                                                         // edge0, VW, has V decreasing, so reverse 1D points below
                                                         // edge1, WU, has U increasing, so don't reverse 1D points  below
                                                         // edge2, UV, has U decreasing, so reverse 1D points below
                PlacePointIn1D(processedTessFactors.insideTessFactorCtx,q,fxpParam);
                // edge0 VW, has perpendicular parameter U constant
                // edge1 WU, has perpendicular parameter V constant
                // edge2 UV, has perpendicular parameter W constant 
                const unsigned int deriv = 2; // reciprocal is the rate of change of edge-parallel parameters as they are pushed into the triangle
                switch(edge)
                {
                case 0:
                    DefinePoint(/*U*/fxpPerpParam,
                                /*V*/fxpParam - (fxpPerpParam+1/*round*/)/deriv, // we know this fixed point math won't over/underflow
                                /*pointStorageOffset*/pointOffset);
                    break;
                case 1:
                    DefinePoint(/*U*/fxpParam - (fxpPerpParam+1/*round*/)/deriv,// we know this fixed point math won't over/underflow
                                /*V*/fxpPerpParam,
                                /*pointStorageOffset*/pointOffset);
                    break;
                case 2:
                    DefinePoint(/*U*/fxpParam - (fxpPerpParam+1/*round*/)/deriv,// we know this fixed point math won't over/underflow
                                /*V*/FXP_ONE - (fxpParam - (fxpPerpParam+1/*round*/)/deriv) - fxpPerpParam,// we know this fixed point math won't over/underflow
                                /*pointStorageOffset*/pointOffset);
                    break;
                }
            }
        }
    }
    if( !Odd() )
    {
        // Last point is the point at the center.
        DefinePoint(/*U*/FXP_ONE_THIRD,
                    /*V*/FXP_ONE_THIRD,
                    /*pointStorageOffset*/pointOffset);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdi, %r14
movq %rsi, 0x10(%rsp)
leaq 0x20(%rsi), %rax
movq %rax, 0x20(%rsp)
xorl %r12d, %r12d
xorl %ebp, %ebp
cmpq $0x3, %r12
je 0x403ad9
movq 0x10(%rsp), %rax
movl 0x74(%rax,%r12,4), %r13d
decl %r13d
imulq $0x14, %r12, %rax
addq 0x20(%rsp), %rax
movq %rax, 0x28(%rsp)
testl %r13d, %r13d
movl $0x0, %ebx
cmovgl %r13d, %ebx
movslq %ebp, %rax
movl %eax, %ecx
movq %rcx, 0x18(%rsp)
leaq 0x4(,%rax,8), %rax
movq %rax, 0x8(%rsp)
xorl %r15d, %r15d
cmpl %r15d, %ebx
je 0x403ace
testb $0x1, %r12b
movl %r15d, %edx
cmovel %r13d, %edx
movq 0x10(%rsp), %rax
movl 0x10(%rax,%r12,4), %eax
movl %eax, 0x4(%r14)
movq %r14, %rdi
movq 0x28(%rsp), %rsi
leaq 0x44(%rsp), %rcx
callq 0x402f08
movl 0x44(%rsp), %esi
testq %r12, %r12
je 0x403a92
movl $0x10000, %edx          # imm = 0x10000
subl %esi, %edx
cmpq $0x2, %r12
movl $0x0, %eax
cmovnel %eax, %edx
movq 0x18(%rsp), %rax
leal (%rax,%r15), %ecx
movq %r14, %rdi
callq 0x402558
jmp 0x403ac3
movq 0x18(%r14), %rax
addq 0x8(%rsp), %rax
andl $0x0, -0x4(%rax,%r15,8)
movl %esi, %ecx
shrl $0x10, %ecx
cvtsi2ss %ecx, %xmm0
movzwl %si, %ecx
cvtsi2ss %ecx, %xmm1
mulss 0xc1583(%rip), %xmm1    # 0x4c503c
addss %xmm0, %xmm1
movss %xmm1, (%rax,%r15,8)
incq %r15
decl %r13d
jmp 0x403a2f
addl %r15d, %ebp
incq %r12
jmp 0x4039e4
movq 0x10(%rsp), %rcx
movl 0x1c(%rcx), %eax
movl %eax, 0x4(%r14)
movl 0x80(%rcx), %eax
sarl %eax
movl %eax, 0x34(%rsp)
leaq 0x5c(%rcx), %rax
movq %rax, 0x18(%rsp)
pushq $0x1
popq %r12
pushq $-0x2
popq %rcx
cmpl 0x34(%rsp), %r12d
jge 0x403c0f
movq 0x10(%rsp), %rax
movl 0x80(%rax), %eax
movl %r12d, %edx
notl %edx
addl %eax, %edx
movl %edx, 0x28(%rsp)
movl %ecx, 0x38(%rsp)
addl %ecx, %eax
movl %eax, 0x3c(%rsp)
xorl %r13d, %r13d
movl %r12d, 0x20(%rsp)
cmpl $0x3, %r13d
je 0x403c01
movq %r14, %r15
movq %r14, %rdi
movq 0x18(%rsp), %rsi
movl %r12d, %edx
leaq 0x40(%rsp), %rcx
callq 0x402f08
imull $0xaaaa, 0x40(%rsp), %r14d # imm = 0xAAAA
addl $0x8000, %r14d          # imm = 0x8000
shrl $0x10, %r14d
leal 0x1(%r14), %eax
shrl %eax
movl %eax, 0x8(%rsp)
movl 0x3c(%rsp), %ebx
cmpl 0x28(%rsp), %r12d
jge 0x403bf1
testb $0x1, %r13b
movl %r12d, %edx
cmovel %ebx, %edx
movq %r15, %rdi
movq 0x18(%rsp), %rsi
leaq 0x4(%rsp), %rcx
callq 0x402f08
cmpl $0x2, %r13d
je 0x403bcc
cmpl $0x1, %r13d
je 0x403bbc
testl %r13d, %r13d
jne 0x403be8
movl 0x4(%rsp), %edx
subl 0x8(%rsp), %edx
movq %r15, %rdi
movl %r14d, %esi
jmp 0x403be1
movl 0x4(%rsp), %esi
subl 0x8(%rsp), %esi
movq %r15, %rdi
movl %r14d, %edx
jmp 0x403be1
movl 0x4(%rsp), %esi
subl 0x8(%rsp), %esi
movl $0x10000, %edx          # imm = 0x10000
subl %r14d, %edx
subl %esi, %edx
movq %r15, %rdi
movl %ebp, %ecx
callq 0x402558
incl %r12d
incl %ebp
decl %ebx
jmp 0x403b78
incl %r13d
movq %r15, %r14
movl 0x20(%rsp), %r12d
jmp 0x403b34
incl %r12d
movl 0x38(%rsp), %ecx
decl %ecx
jmp 0x403b01
cmpl $0x1, 0x4(%r14)
je 0x403c2a
movq 0x18(%r14), %rax
movslq %ebp, %rcx
movsd 0xc14bb(%rip), %xmm0    # 0x4c50e0
movsd %xmm0, (%rax,%rcx,8)
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop