// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Draw.cpp
// Function: gaps::R3Triangle::Draw(gaps::RNFlags) const
void R3Triangle::
Draw(const R3DrawFlags draw_flags) const
{
    // Ammend draw flags
    R3DrawFlags flags(Flags() & draw_flags);
    RNDimension dim = 0, dim1 = 0, dim2 = 0;

    // Unroll flags/loops for efficiency 
    switch (flags) {
    case R3_SURFACES_DRAW_FLAG:
      // No shading
      R3BeginPolygon();
      R3LoadPoint(v[0]->Position());
      R3LoadPoint(v[1]->Position());
      R3LoadPoint(v[2]->Position());
      R3EndPolygon();
      break;

    case R3_SURFACES_DRAW_FLAG | R3_SURFACE_NORMALS_DRAW_FLAG:
      // Flat shading
      R3BeginPolygon();
      R3LoadNormal(Normal());
      R3LoadPoint(v[0]->Position());
      R3LoadPoint(v[1]->Position());
      R3LoadPoint(v[2]->Position());
      R3EndPolygon();
      break;

    case R3_SURFACES_DRAW_FLAG | R3_VERTEX_COLORS_DRAW_FLAG:
      // Color interpolation
      R3BeginPolygon();
      RNLoadRgb(v[0]->Color());
      R3LoadPoint(v[0]->Position());
      RNLoadRgb(v[1]->Color());
      R3LoadPoint(v[1]->Position());
      RNLoadRgb(v[2]->Color());
      R3LoadPoint(v[2]->Position());
      R3EndPolygon();
      break;

    case R3_SURFACES_DRAW_FLAG | R3_SURFACE_NORMALS_DRAW_FLAG | R3_VERTEX_NORMALS_DRAW_FLAG:
      // Gouraud shading
      R3BeginPolygon();
      R3LoadNormal(v[0]->Normal());
      R3LoadPoint(v[0]->Position());
      R3LoadNormal(v[1]->Normal());
      R3LoadPoint(v[1]->Position());
      R3LoadNormal(v[2]->Normal());
      R3LoadPoint(v[2]->Position());
      R3EndPolygon();
      break;

    case R3_SURFACES_DRAW_FLAG | R3_SURFACE_NORMALS_DRAW_FLAG | 
         R3_SURFACE_TEXTURE_DRAW_FLAG | R3_VERTEX_TEXTURE_COORDS_DRAW_FLAG: 
      // Flat shading with texture coordinates
      R3BeginPolygon();
      R3LoadNormal(Normal());
      R3LoadTextureCoords(v[0]->TextureCoords());
      R3LoadPoint(v[0]->Position());
      R3LoadTextureCoords(v[1]->TextureCoords());
      R3LoadPoint(v[1]->Position());
      R3LoadTextureCoords(v[2]->TextureCoords());
      R3LoadPoint(v[2]->Position());
      R3EndPolygon();
      break;

    case R3_SURFACES_DRAW_FLAG | R3_SURFACE_NORMALS_DRAW_FLAG | 
         R3_SURFACE_TEXTURE_DRAW_FLAG: 
      // Flat shading with texture coordinate generation
      dim = Normal().MaxDimension();
      dim1 = (dim + 1) % 3;
      dim2 = (dim + 2) % 3;
      R3BeginPolygon();
      R3LoadNormal(Normal());
      R3LoadTextureCoords(v[0]->Position()[dim1], v[0]->Position()[dim2]);
      R3LoadPoint(v[0]->Position());
      R3LoadTextureCoords(v[1]->Position()[dim1], v[1]->Position()[dim2]);
      R3LoadPoint(v[1]->Position());
      R3LoadTextureCoords(v[2]->Position()[dim1], v[2]->Position()[dim2]);
      R3LoadPoint(v[2]->Position());
      R3EndPolygon();
      break;

    case R3_SURFACES_DRAW_FLAG | R3_SURFACE_NORMALS_DRAW_FLAG | R3_VERTEX_NORMALS_DRAW_FLAG | 
         R3_SURFACE_TEXTURE_DRAW_FLAG | R3_VERTEX_TEXTURE_COORDS_DRAW_FLAG: 
      // Gouraud shading with texture coordinates
      R3BeginPolygon();
      R3LoadTextureCoords(v[0]->TextureCoords());
      R3LoadNormal(v[0]->Normal());
      R3LoadPoint(v[0]->Position());
      R3LoadTextureCoords(v[1]->TextureCoords());
      R3LoadNormal(v[1]->Normal());
      R3LoadPoint(v[1]->Position());
      R3LoadTextureCoords(v[2]->TextureCoords());
      R3LoadNormal(v[2]->Normal());
      R3LoadPoint(v[2]->Position());
      R3EndPolygon();
      break;

    case R3_SURFACES_DRAW_FLAG | R3_SURFACE_NORMALS_DRAW_FLAG | R3_VERTEX_NORMALS_DRAW_FLAG | 
         R3_SURFACE_TEXTURE_DRAW_FLAG: 
      // Gouraud shading with texture coordinate generation
      dim = Normal().MaxDimension();
      dim1 = (dim + 1) % 3;
      dim2 = (dim + 2) % 3;
      R3BeginPolygon();
      R3LoadTextureCoords(v[0]->Position()[dim1], v[0]->Position()[dim2]);
      R3LoadNormal(v[0]->Normal());
      R3LoadPoint(v[0]->Position());
      R3LoadTextureCoords(v[1]->Position()[dim1], v[1]->Position()[dim2]);
      R3LoadNormal(v[1]->Normal());
      R3LoadPoint(v[1]->Position());
      R3LoadTextureCoords(v[2]->Position()[dim1], v[2]->Position()[dim2]);
      R3LoadNormal(v[2]->Normal());
      R3LoadPoint(v[2]->Position());
      R3EndPolygon();
      break;

    default:
        // Draw surface
        if (flags[R3_SURFACES_DRAW_FLAG]) {
	    // Begin polygon
	    R3BeginPolygon();

            // Load polygon normal
	    if ((flags[R3_SURFACE_NORMALS_DRAW_FLAG]) &&
		(!flags[R3_VERTEX_NORMALS_DRAW_FLAG]))
	        R3LoadNormal(Normal());

	    // Compute stuff for texture coordinates
	    if ((draw_flags[R3_VERTEX_TEXTURE_COORDS_DRAW_FLAG]) &&
		(!flags[R3_VERTEX_TEXTURE_COORDS_DRAW_FLAG])) {
	        dim = Normal().MaxDimension();
		dim1 = (dim + 1) % 3;
		dim2 = (dim + 2) % 3;
	    }

	    // Load triangle vertices
	    for (int i = 0; i < 3; i++) {
		// Load vertex color
  		if (flags[R3_VERTEX_COLORS_DRAW_FLAG]) {
                    RNLoadRgb(v[i]->Color());
 		}

		// Load vertex normal
		if (flags[R3_VERTEX_NORMALS_DRAW_FLAG]) {
                  const R3Vector& normal = (v[i]->HasNormal()) ? v[i]->Normal() : Normal();
                  RNScalar dot = normal.Dot(Normal());
                  if (dot > 0.25) R3LoadNormal(normal);
                  else if (dot < -0.25) R3LoadNormal(-normal);
                  else R3LoadNormal(Normal());
                }

		// Load vertex texture coordinates 
		if (draw_flags[R3_VERTEX_TEXTURE_COORDS_DRAW_FLAG]) {
		    if (flags[R3_VERTEX_TEXTURE_COORDS_DRAW_FLAG]) R3LoadTextureCoords(v[i]->TextureCoords());
		    else R3LoadTextureCoords(v[i]->Position()[dim1], v[i]->Position()[dim2]);
		}

		// Load vertex
		R3LoadPoint(v[i]->Position());
	    }

	    // End polygon 
	    R3EndPolygon();
	}
	
	// Draw edges
	if (flags[R3_EDGES_DRAW_FLAG]) {
	    R3BeginLoop();
            R3LoadPoint(v[0]->Position());
            R3LoadPoint(v[1]->Position());
            R3LoadPoint(v[2]->Position());
	    R3EndLoop();
	}
	break;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, %r15
movq %rdi, %rbx
movq 0x78(%rdi), %r13
movq %r13, %rbp
andq %rsi, %rbp
cmpq $0x131, %rbp            # imm = 0x131
jg 0x40843
cmpq $0x31, %rbp
jg 0x408bb
cmpq $0x2, %rbp
je 0x40990
cmpq $0x22, %rbp
jne 0x40bd1
movl $0x9, %edi
callq 0xe110
leaq 0x20(%rbx), %rdi
callq 0xe6b0
jmp 0x4099a
cmpq $0x331, %rbp            # imm = 0x331
jg 0x4090d
cmpq $0x132, %rbp            # imm = 0x132
je 0x409b1
cmpq $0x232, %rbp            # imm = 0x232
jne 0x40bd1
movl $0x9, %edi
callq 0xe110
leaq 0x20(%rbx), %rdi
callq 0xe6b0
movq 0x8(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
jmp 0x40bb5
cmpq $0x32, %rbp
je 0x40a87
cmpq $0x122, %rbp            # imm = 0x122
jne 0x40bd1
movl $0x9, %edi
callq 0xe110
movq 0x8(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6b0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6b0
movq 0x10(%rbx), %rdi
callq 0xe130
jmp 0x40ba8
cmpq $0x332, %rbp            # imm = 0x332
je 0x40b4b
cmpq $0x402, %rbp            # imm = 0x402
jne 0x40bd1
movl $0x9, %edi
callq 0xe110
movq 0x8(%rbx), %rax
movsd 0x30(%rax), %xmm0
movsd 0x38(%rax), %xmm1
movsd 0x40(%rax), %xmm2
callq 0xe6e0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rax
movsd 0x30(%rax), %xmm0
movsd 0x38(%rax), %xmm1
movsd 0x40(%rax), %xmm2
callq 0xe6e0
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rax
movsd 0x30(%rax), %xmm0
movsd 0x38(%rax), %xmm1
movsd 0x40(%rax), %xmm2
callq 0xe6e0
jmp 0x40bb5
movl $0x9, %edi
callq 0xe110
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
callq 0xe130
jmp 0x40bb5
leaq 0x20(%rbx), %rdi
callq 0x3d14e
leal 0x1(%rax), %ecx
movslq %ecx, %rcx
imulq $0x55555556, %rcx, %rcx # imm = 0x55555556
movq %rcx, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rcx
addl %edx, %ecx
leal (%rcx,%rcx,2), %ecx
negl %ecx
leal (%rax,%rcx), %ebp
incl %ebp
movl %eax, %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
imulq $0x55555556, %rcx, %rcx # imm = 0x55555556
movq %rcx, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rcx
addl %edx, %ecx
leal (%rcx,%rcx,2), %ecx
negl %ecx
leal (%rax,%rcx), %r15d
addl $0x2, %r15d
movl $0x9, %edi
callq 0xe110
movq 0x8(%rbx), %rax
movslq %ebp, %r14
movsd (%rax,%r14,8), %xmm0
movslq %r15d, %r15
movsd (%rax,%r15,8), %xmm1
callq 0xe8d0
movq 0x8(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6b0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rax
movsd (%rax,%r14,8), %xmm0
movsd (%rax,%r15,8), %xmm1
callq 0xe8d0
movq 0x10(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6b0
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rax
movsd (%rax,%r14,8), %xmm0
movsd (%rax,%r15,8), %xmm1
callq 0xe8d0
jmp 0x40ba8
leaq 0x20(%rbx), %r14
movq %r14, %rdi
callq 0x3d14e
leal 0x1(%rax), %ecx
movslq %ecx, %rcx
imulq $0x55555556, %rcx, %rcx # imm = 0x55555556
movq %rcx, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rcx
addl %edx, %ecx
leal (%rcx,%rcx,2), %ecx
negl %ecx
leal (%rax,%rcx), %ebp
incl %ebp
movl %eax, %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
imulq $0x55555556, %rcx, %rcx # imm = 0x55555556
movq %rcx, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rcx
addl %edx, %ecx
leal (%rcx,%rcx,2), %ecx
negl %ecx
leal (%rax,%rcx), %r15d
addl $0x2, %r15d
movl $0x9, %edi
callq 0xe110
movq %r14, %rdi
callq 0xe6b0
movq 0x8(%rbx), %rax
movslq %ebp, %r14
movsd (%rax,%r14,8), %xmm0
movslq %r15d, %r15
movsd (%rax,%r15,8), %xmm1
callq 0xe8d0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rax
movsd (%rax,%r14,8), %xmm0
movsd (%rax,%r15,8), %xmm1
callq 0xe8d0
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rax
movsd (%rax,%r14,8), %xmm0
movsd (%rax,%r15,8), %xmm1
callq 0xe8d0
jmp 0x40bb5
movl $0x9, %edi
callq 0xe110
movq 0x8(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
movq 0x8(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6b0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
movq 0x10(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6b0
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
movq 0x18(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6b0
movq 0x18(%rbx), %rdi
callq 0xe130
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xe5d0
testb $0x2, %bpl
je 0x40d6d
movl $0x9, %edi
callq 0xe110
movl %ebp, %eax
andl $0x120, %eax            # imm = 0x120
cmpl $0x20, %eax
jne 0x40bfa
leaq 0x20(%rbx), %rdi
callq 0xe6b0
btl $0x9, %r15d
setae %al
movl %r13d, %ecx
shrl $0x9, %ecx
andl $0x1, %ecx
orb %al, %cl
jne 0x40c72
leaq 0x20(%rbx), %rdi
callq 0x3d14e
leal 0x1(%rax), %ecx
movslq %ecx, %rcx
imulq $0x55555556, %rcx, %rcx # imm = 0x55555556
movq %rcx, %rdx
shrq $0x3f, %rdx
shrq $0x20, %rcx
addl %edx, %ecx
leal (%rcx,%rcx,2), %ecx
negl %ecx
addl %eax, %ecx
incl %ecx
movl %eax, %edx
addl $0x2, %edx
movslq %edx, %rdx
imulq $0x55555556, %rdx, %rdx # imm = 0x55555556
movq %rdx, %rsi
shrq $0x3f, %rsi
shrq $0x20, %rdx
addl %esi, %edx
leal (%rdx,%rdx,2), %edx
negl %edx
addl %edx, %eax
addl $0x2, %eax
movslq %ecx, %rcx
movq %rcx, 0x10(%rsp)
cltq
movq %rax, 0x18(%rsp)
jmp 0x40c84
movq $0x0, 0x18(%rsp)
movq $0x0, 0x10(%rsp)
leaq 0x20(%rbx), %rax
movq %rax, 0x8(%rsp)
movl $0x1, %r12d
btl $0xa, %ebp
jae 0x40cb1
movq (%rbx,%r12,8), %rax
movsd 0x30(%rax), %xmm0
movsd 0x38(%rax), %xmm1
movsd 0x40(%rax), %xmm2
callq 0xe6e0
btl $0x8, %ebp
jae 0x40d1c
movq %r13, %r14
movq (%rbx,%r12,8), %rax
btl $0x8, 0x58(%rax)
movq 0x8(%rsp), %r13
jae 0x40cd1
addq $0x18, %rax
movq %rax, %r13
movq %r13, %rdi
movq 0x8(%rsp), %rsi
callq 0x3d252
ucomisd 0x620ca(%rip), %xmm0    # 0xa2db0
jbe 0x40ced
movq %r13, %rdi
jmp 0x40d14
movsd 0x6819b(%rip), %xmm1    # 0xa8e90
ucomisd %xmm0, %xmm1
jbe 0x40d0f
leaq 0x20(%rsp), %rdi
movq %r13, %rsi
callq 0x3dc00
leaq 0x20(%rsp), %rdi
jmp 0x40d14
movq 0x8(%rsp), %rdi
callq 0xe6b0
movq %r14, %r13
btl $0x9, %r15d
jae 0x40d52
btl $0x9, %r13d
movq (%rbx,%r12,8), %rdi
jb 0x40d49
movq 0x10(%rsp), %rax
movsd (%rdi,%rax,8), %xmm0
movq 0x18(%rsp), %rax
movsd (%rdi,%rax,8), %xmm1
callq 0xe8d0
jmp 0x40d52
addq $0x48, %rdi
callq 0xe120
movq (%rbx,%r12,8), %rdi
callq 0xe130
incq %r12
cmpq $0x4, %r12
jne 0x40c93
callq 0xe5d0
testb $0x1, %bpl
je 0x40d9d
movl $0x2, %edi
callq 0xe110
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rdi
callq 0xe130
callq 0xe5d0
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq