// File: /workspace/github_cpp_makefile_star2_O1/YiweiMao[P]tessDX/src/tessellator.cpp
// Function: CHWTessellator::TriGenerateConnectivity(CHWTessellator::PROCESSED_TESS_FACTORS_TRI const&)
void CHWTessellator::TriGenerateConnectivity( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors )
{
    // Generate primitives for all the concentric rings, one side at a time for each ring
    static const int startRing = 1;
    int numRings = ((processedTessFactors.numPointsForInsideTessFactor+1) >> 1); // +1 is so even tess includes the center point, which we want to now
    const TESS_FACTOR_CONTEXT* outsideTessFactorCtx[TRI_EDGES] = {&processedTessFactors.outsideTessFactorCtx[Ueq0],
                                            &processedTessFactors.outsideTessFactorCtx[Veq0],
                                            &processedTessFactors.outsideTessFactorCtx[Weq0]};
    TESSELLATOR_PARITY outsideTessFactorParity[TRI_EDGES] = {processedTessFactors.outsideTessFactorParity[Ueq0],
                                            processedTessFactors.outsideTessFactorParity[Veq0],
                                            processedTessFactors.outsideTessFactorParity[Weq0]};
    int numPointsForOutsideEdge[TRI_EDGES] = {processedTessFactors.numPointsForOutsideEdge[Ueq0],
                                              processedTessFactors.numPointsForOutsideEdge[Veq0],
                                              processedTessFactors.numPointsForOutsideEdge[Weq0]};

    int insideEdgePointBaseOffset = processedTessFactors.insideEdgePointBaseOffset;
    int outsideEdgePointBaseOffset = 0;
    int edge;
    for(int ring = startRing; ring < numRings; ring++)
    {
        int numPointsForInsideEdge = processedTessFactors.numPointsForInsideTessFactor - 2*ring;
        int edge0InsidePointBaseOffset = insideEdgePointBaseOffset;
        int edge0OutsidePointBaseOffset = outsideEdgePointBaseOffset;
        for(edge = 0; edge < TRI_EDGES; edge++ )
        {
            int numTriangles = numPointsForInsideEdge + numPointsForOutsideEdge[edge] - 2;

            int insideBaseOffset;
            int outsideBaseOffset;
            if( edge == 2 )
            {
                m_IndexPatchContext.insidePointIndexDeltaToRealValue    = insideEdgePointBaseOffset;
                m_IndexPatchContext.insidePointIndexBadValue            = numPointsForInsideEdge - 1;
                m_IndexPatchContext.insidePointIndexReplacementValue    = edge0InsidePointBaseOffset;
                m_IndexPatchContext.outsidePointIndexPatchBase          = m_IndexPatchContext.insidePointIndexBadValue+1; // past inside patched index range
                m_IndexPatchContext.outsidePointIndexDeltaToRealValue   = outsideEdgePointBaseOffset 
                                                                            - m_IndexPatchContext.outsidePointIndexPatchBase;
                m_IndexPatchContext.outsidePointIndexBadValue           = m_IndexPatchContext.outsidePointIndexPatchBase
                                                                            + numPointsForOutsideEdge[edge] - 1;
                m_IndexPatchContext.outsidePointIndexReplacementValue   = edge0OutsidePointBaseOffset;
                SetUsingPatchedIndices(true);
                insideBaseOffset = 0;
                outsideBaseOffset = m_IndexPatchContext.outsidePointIndexPatchBase;
            }
            else
            {
                insideBaseOffset = insideEdgePointBaseOffset;
                outsideBaseOffset = outsideEdgePointBaseOffset;
            }
            if( ring == startRing )
            {
                StitchTransition(/*baseIndexOffset: */m_NumIndices, 
                               insideBaseOffset,processedTessFactors.insideTessFactorCtx.numHalfTessFactorPoints,processedTessFactors.insideTessFactorParity,
                               outsideBaseOffset,outsideTessFactorCtx[edge]->numHalfTessFactorPoints,outsideTessFactorParity[edge]);
            }
            else
            {
                StitchRegular(/*bTrapezoid*/true, DIAGONALS_MIRRORED,
                              /*baseIndexOffset: */m_NumIndices,
                              numPointsForInsideEdge,
                              insideBaseOffset,outsideBaseOffset);
            }
            if( 2 == edge )
            {
                SetUsingPatchedIndices(false);
            }
            m_NumIndices += numTriangles*3;
            outsideEdgePointBaseOffset += numPointsForOutsideEdge[edge] - 1;
            insideEdgePointBaseOffset += numPointsForInsideEdge - 1;
            numPointsForOutsideEdge[edge] = numPointsForInsideEdge;
        }
        if( startRing == ring )
        {
            for(edge = 0; edge < TRI_EDGES; edge++ )
            {
                outsideTessFactorCtx[edge] = &processedTessFactors.insideTessFactorCtx;
                outsideTessFactorParity[edge] = processedTessFactors.insideTessFactorParity;
            }
        }
    }
    if( Odd() )
    {
        // Triangulate center (a single triangle)
        DefineClockwiseTriangle(outsideEdgePointBaseOffset, outsideEdgePointBaseOffset+1, outsideEdgePointBaseOffset+2, 
                       m_NumIndices);
        m_NumIndices += 3;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rdi, %rbx
movl 0x80(%rsi), %ecx
incl %ecx
sarl %ecx
leaq 0x20(%rsi), %rax
movq %rax, 0x60(%rsp)
leaq 0x34(%rsi), %rax
movq %rax, 0x68(%rsp)
leaq 0x48(%rsi), %rax
movq %rax, 0x70(%rsp)
movl 0x10(%rsi), %eax
movl %eax, 0x34(%rsp)
movl 0x14(%rsi), %eax
movl %eax, 0x38(%rsp)
movl 0x18(%rsi), %eax
movl %eax, 0x3c(%rsp)
movl 0x74(%rsi), %eax
movl %eax, 0x28(%rsp)
movl 0x78(%rsi), %eax
movl %eax, 0x2c(%rsp)
movq %rsi, 0x8(%rsp)
movl 0x7c(%rsi), %eax
movl %eax, 0x30(%rsp)
xorl %r15d, %r15d
movl %ecx, 0x14(%rsp)
cmpl $0x2, %ecx
jl 0x4041e0
movq 0x8(%rsp), %rax
movl 0x84(%rax), %r13d
leaq 0x5c(%rax), %rdx
movl $0x1, %esi
xorl %r15d, %r15d
movl $0xfffffffd, %ecx       # imm = 0xFFFFFFFD
movq %rdx, 0x40(%rsp)
movl %r13d, 0x20(%rsp)
movq 0x8(%rsp), %rax
movl 0x80(%rax), %edi
leal (%rsi,%rsi), %eax
movl %edi, %r12d
subl %eax, %r12d
negl %eax
addl %edi, %eax
decl %eax
movl %eax, 0x1c(%rsp)
movl %ecx, 0x18(%rsp)
addl %ecx, %edi
movq %rdi, 0x48(%rsp)
xorl %ebp, %ebp
movl %r15d, 0x24(%rsp)
movq %rsi, 0x50(%rsp)
movl 0x28(%rsp,%rbp), %ecx
movq %rcx, 0x58(%rsp)
leal (%rcx,%r12), %r14d
movl %r13d, %r9d
movl %r15d, %eax
cmpq $0x8, %rbp
jne 0x40410f
movl %r13d, 0x34(%rbx)
movl 0x1c(%rsp), %eax
movl %eax, 0x38(%rbx)
movl 0x20(%rsp), %eax
movl %eax, 0x3c(%rbx)
movl %r12d, 0x40(%rbx)
movl %r15d, %eax
subl %r12d, %eax
movl %eax, 0x44(%rbx)
leal -0x1(%r14), %eax
movl %eax, 0x48(%rbx)
movl 0x24(%rsp), %eax
movl %eax, 0x4c(%rbx)
movb $0x1, 0x31(%rbx)
xorl %r9d, %r9d
movl %r12d, %eax
cmpl $0x1, %esi
jne 0x404145
movl 0x2c(%rbx), %esi
movq 0x8(%rsp), %rcx
movl 0x1c(%rcx), %r8d
movl 0x68(%rcx), %ecx
movq 0x60(%rsp,%rbp,2), %rdx
movl 0xc(%rdx), %r10d
movl 0x34(%rsp,%rbp), %r11d
movq %rbx, %rdi
movl %r9d, %edx
movl %eax, %r9d
pushq %r11
pushq %r10
callq 0x403248
jmp 0x404162
movl 0x2c(%rbx), %ecx
subq $0x8, %rsp
movq %rbx, %rdi
movl $0x1, %esi
movl $0x2, %edx
movl %r12d, %r8d
pushq %rax
callq 0x40353c
addq $0x10, %rsp
cmpq $0x8, %rbp
jne 0x404170
movb $0x0, 0x31(%rbx)
leal (%r14,%r14,2), %eax
movl 0x2c(%rbx), %ecx
addl %ecx, %eax
addl $-0x6, %eax
movl %eax, 0x2c(%rbx)
movq 0x58(%rsp), %rax
addl %eax, %r15d
decl %r15d
movl %r12d, 0x28(%rsp,%rbp)
addq $0x4, %rbp
addl 0x48(%rsp), %r13d
cmpq $0xc, %rbp
movq 0x50(%rsp), %rsi
jne 0x4040bf
cmpl $0x1, %esi
movq 0x40(%rsp), %rdx
jne 0x4041cd
movq 0x8(%rsp), %rax
movl 0x1c(%rax), %eax
xorl %ecx, %ecx
movq %rdx, 0x60(%rsp,%rcx,8)
movl %eax, 0x34(%rsp,%rcx,4)
incq %rcx
cmpq $0x3, %rcx
jne 0x4041bb
incl %esi
movl 0x18(%rsp), %ecx
addl $-0x2, %ecx
cmpl 0x14(%rsp), %esi
jne 0x404085
cmpl $0x1, 0x4(%rbx)
jne 0x404201
leal 0x1(%r15), %edx
leal 0x2(%r15), %ecx
movl 0x2c(%rbx), %r8d
movq %rbx, %rdi
movl %r15d, %esi
callq 0x40266a
addl $0x3, 0x2c(%rbx)
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq