// File: /workspace/github_cpp_makefile_star2_O2/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 %rdi, %rbx
movq 0x78(%rdi), %r15
movq %r15, %rbp
andq %rsi, %rbp
cmpq $0x402, %rbp            # imm = 0x402
je 0x3ba2c
cmpq $0x22, %rbp
je 0x3b8c7
cmpq $0x32, %rbp
je 0x3b9a2
cmpq $0x122, %rbp            # imm = 0x122
je 0x3b95f
cmpq $0x132, %rbp            # imm = 0x132
je 0x3b782
cmpq $0x232, %rbp            # imm = 0x232
je 0x3b87b
cmpq $0x332, %rbp            # imm = 0x332
je 0x3b81e
cmpq $0x2, %rbp
jne 0x3b8ec
callq 0x21c40
jmp 0x3b8d5
leaq 0x20(%rbx), %rdi
callq 0x38490
movl %eax, %ecx
leal 0x1(%rcx), %eax
pushq $0x3
popq %rsi
cltd
idivl %esi
movl %edx, %ebp
addl $0x2, %ecx
movl %ecx, %eax
cltd
idivl %esi
movl %edx, %r14d
callq 0x21c40
movq 0x8(%rbx), %rax
movslq %ebp, %r15
movsd (%rax,%r15,8), %xmm0
movslq %r14d, %r14
movsd (%rax,%r14,8), %xmm1
callq 0xe900
movq 0x8(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6e0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rax
movsd (%rax,%r15,8), %xmm0
movsd (%rax,%r14,8), %xmm1
callq 0xe900
movq 0x10(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6e0
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rax
movsd (%rax,%r15,8), %xmm0
movsd (%rax,%r14,8), %xmm1
callq 0xe900
jmp 0x3b990
callq 0x21c40
movq 0x8(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
movq 0x8(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6e0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
movq 0x10(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6e0
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rdi
addq $0x48, %rdi
callq 0xe120
jmp 0x3b990
callq 0x21c40
leaq 0x20(%rbx), %rdi
callq 0xe6e0
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 0x3ba6a
callq 0x21c40
leaq 0x20(%rbx), %rdi
callq 0xe6e0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
callq 0xe130
jmp 0x3ba6a
testb $0x2, %bpl
je 0x3bb73
movq %rsi, %r14
callq 0x21c40
movl %ebp, %eax
andl $0x120, %eax            # imm = 0x120
cmpl $0x20, %eax
jne 0x3b913
leaq 0x20(%rbx), %rdi
callq 0xe6e0
btl $0x9, %r14d
setae %al
movl %r15d, %ecx
shrl $0x9, %ecx
andl $0x1, %ecx
orb %al, %cl
jne 0x3ba86
leaq 0x20(%rbx), %rdi
callq 0x38490
movl %eax, %ecx
leal 0x1(%rcx), %eax
pushq $0x3
popq %rdi
cltd
idivl %edi
movl %edx, %esi
addl $0x2, %ecx
movl %ecx, %eax
cltd
idivl %edi
movslq %esi, %rax
movq %rax, 0x10(%rsp)
movslq %edx, %rax
movq %rax, 0x18(%rsp)
jmp 0x3ba98
callq 0x21c40
movq 0x8(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6e0
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6e0
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rdi
addq $0x18, %rdi
callq 0xe6e0
jmp 0x3ba6a
leaq 0x20(%rbx), %r14
movq %r14, %rdi
callq 0x38490
movl %eax, %ecx
leal 0x1(%rcx), %eax
pushq $0x3
popq %rsi
cltd
idivl %esi
movl %edx, %ebp
addl $0x2, %ecx
movl %ecx, %eax
cltd
idivl %esi
movl %edx, %r15d
callq 0x21c40
movq %r14, %rdi
callq 0xe6e0
movq 0x8(%rbx), %rax
movslq %ebp, %r14
movsd (%rax,%r14,8), %xmm0
movslq %r15d, %r15
movsd (%rax,%r15,8), %xmm1
callq 0xe900
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rax
movsd (%rax,%r14,8), %xmm0
movsd (%rax,%r15,8), %xmm1
callq 0xe900
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rax
movsd (%rax,%r14,8), %xmm0
movsd (%rax,%r15,8), %xmm1
callq 0xe900
jmp 0x3ba6a
callq 0x21c40
movq 0x8(%rbx), %rdi
addq $0x30, %rdi
callq 0x3cc7b
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
addq $0x30, %rdi
callq 0x3cc7b
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rdi
addq $0x30, %rdi
callq 0x3cc7b
movq 0x18(%rbx), %rdi
callq 0xe130
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xe5f0
movq $0x0, 0x18(%rsp)
movq $0x0, 0x10(%rsp)
leaq 0x20(%rbx), %rax
movq %rax, 0x8(%rsp)
pushq $0x1
popq %r12
cmpq $0x4, %r12
je 0x3bb6e
btl $0xa, %ebp
jae 0x3bac2
movq (%rbx,%r12,8), %rdi
addq $0x30, %rdi
callq 0x3cc7b
btl $0x8, %ebp
jae 0x3bb27
movq (%rbx,%r12,8), %rax
btl $0x8, 0x58(%rax)
movq 0x8(%rsp), %r13
jae 0x3badf
addq $0x18, %rax
movq %rax, %r13
movq %r13, %rdi
movq 0x8(%rsp), %rsi
callq 0x38586
ucomisd 0x5826c(%rip), %xmm0    # 0x93d60
jbe 0x3bafb
movq %r13, %rdi
jmp 0x3bb22
movsd 0x5e33d(%rip), %xmm1    # 0x99e40
ucomisd %xmm0, %xmm1
jbe 0x3bb1d
leaq 0x20(%rsp), %rdi
movq %r13, %rsi
callq 0x38c72
leaq 0x20(%rsp), %rdi
jmp 0x3bb22
movq 0x8(%rsp), %rdi
callq 0xe6e0
btl $0x9, %r14d
jae 0x3bb5d
btl $0x9, %r15d
movq (%rbx,%r12,8), %rdi
jb 0x3bb54
movq 0x10(%rsp), %rax
movsd (%rdi,%rax,8), %xmm0
movq 0x18(%rsp), %rax
movsd (%rdi,%rax,8), %xmm1
callq 0xe900
jmp 0x3bb5d
addq $0x48, %rdi
callq 0xe120
movq (%rbx,%r12,8), %rdi
callq 0xe130
incq %r12
jmp 0x3baa5
callq 0xe5f0
testb $0x1, %bpl
je 0x3bb9e
callq 0x3cc8e
movq 0x8(%rbx), %rdi
callq 0xe130
movq 0x10(%rbx), %rdi
callq 0xe130
movq 0x18(%rbx), %rdi
callq 0xe130
callq 0xe5f0
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop