// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/apps/conf2img/conf2img.cpp
// Function: RenderMesh(gaps::R3Mesh const&, int, gaps::R3Point const&, gaps::R3Vector const&, gaps::R3Vector const&)
static void
RenderMesh(const R3Mesh& mesh, int rendering_scheme,
  const R3Point& viewpoint, const R3Vector& towards, const R3Vector& up)
{
  // Clear window
  glViewport(0, 0, width, height);
  glClearColor(0, 0, 0, 0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glEnable(GL_DEPTH_TEST);
  RNLoadRgb(1.0, 1.0, 1.0);

  // Get world to camera matrix
  R3CoordSystem cs(viewpoint, R3Triad(towards, up));
  R4Matrix world_to_camera = cs.InverseMatrix();

  // Draw mesh
  RNGrfxBegin(RN_GRFX_TRIANGLES);
  for (int i = 0; i < mesh.NFaces(); i++) {
    R3MeshFace *face = mesh.Face(i);
    if (skip_removed_faces) {
      // This is a hack to skip faces marked for removal in the matterport dataset
      int category_index = mesh.FaceCategory(face);
      if (category_index == 9) continue;
      if (category_index == 64) continue;
    }
    if ((rendering_scheme >= CAMERA_PX_RENDERING) && (rendering_scheme <= WORLD_PZ_RENDERING)) {
      // Set color per vertex
      for (int j = 0; j < 3; j++) {
        R3MeshVertex *vertex = mesh.VertexOnFace(face, j);
        RNScalar position_coordinate = 0;
        const R3Point& world_position = mesh.VertexPosition(vertex);
        R3Point camera_position = world_to_camera * world_position;
        if (rendering_scheme == CAMERA_PX_RENDERING) position_coordinate = camera_position.X();
        else if (rendering_scheme == CAMERA_PY_RENDERING) position_coordinate = camera_position.Y();
        else if (rendering_scheme == CAMERA_PZ_RENDERING) position_coordinate = camera_position.Z();
        else if (rendering_scheme == WORLD_PX_RENDERING) position_coordinate = world_position.X() - viewpoint.X();
        else if (rendering_scheme == WORLD_PY_RENDERING) position_coordinate = world_position.Y() - viewpoint.Y();
        else if (rendering_scheme == WORLD_PZ_RENDERING) position_coordinate = world_position.Z() - viewpoint.Z();
        int position_value = png_distance_scale * position_coordinate + 32768;
        if (position_value < 0) position_value = 0;
        else if (position_value > 65535) position_value = 65535;
        LoadInteger(position_value);
        R3LoadPoint(world_position);
      }
    }
    else if (((rendering_scheme >= CAMERA_NX_RENDERING) && (rendering_scheme <= CAMERA_NZ_RENDERING)) ||
             ((rendering_scheme >= WORLD_NX_RENDERING) && (rendering_scheme <= WORLD_NZ_RENDERING))) {
      // Set color per face based on normal
      RNScalar normal_coordinate = 0;
      R3Vector world_normal = mesh.FaceNormal(face);
      R3Vector camera_normal = world_to_camera * world_normal; camera_normal.Normalize();
      if (rendering_scheme == CAMERA_NX_RENDERING) normal_coordinate = camera_normal.X();
      else if (rendering_scheme == CAMERA_NY_RENDERING) normal_coordinate = camera_normal.Y();
      else if (rendering_scheme == CAMERA_NZ_RENDERING) normal_coordinate = camera_normal.Z();
      else if (rendering_scheme == WORLD_NX_RENDERING) normal_coordinate = world_normal.X();
      else if (rendering_scheme == WORLD_NY_RENDERING) normal_coordinate = world_normal.Y();
      else if (rendering_scheme == WORLD_NZ_RENDERING) normal_coordinate = world_normal.Z();
      int normal_value = 32768 * (normal_coordinate + 1.0);
      if (normal_value < 0) normal_value = 0;
      else if (normal_value > 65535) normal_value = 65535;
      LoadInteger(normal_value);
      for (int j = 0; j < 3; j++) {
        R3MeshVertex *vertex = mesh.VertexOnFace(face, j);
        const R3Point& position = mesh.VertexPosition(vertex);
        R3LoadPoint(position);
      }
    }
    else if ((rendering_scheme == CAMERA_ND_RENDERING) || (rendering_scheme == WORLD_ND_RENDERING)) {
      RNScalar offset_coordinate = 0;
      R3Vector world_normal = mesh.FaceNormal(face);
      R3Point world_position = mesh.FaceCentroid(face);
      if (rendering_scheme == CAMERA_ND_RENDERING) {
        R3Point camera_position = world_to_camera * world_position;
        R3Vector camera_normal = world_to_camera * world_normal; camera_normal.Normalize();
        offset_coordinate = -camera_position.X()*camera_normal.X() - camera_position.Y()*camera_normal.Y() - camera_position.Z()*camera_normal.Z();
      }
      else if (rendering_scheme == WORLD_ND_RENDERING) {
        offset_coordinate = -world_position.X()*world_normal.X() - world_position.Y()*world_normal.Y() - world_position.Z()*world_normal.Z();
      }
      int offset_value = png_distance_scale * offset_coordinate + 32768;
      if (offset_value < 0) offset_value = 0;
      else if (offset_value > 65535) offset_value = 65535;
      LoadInteger(offset_value);
      for (int j = 0; j < 3; j++) {
        R3MeshVertex *vertex = mesh.VertexOnFace(face, j);
        const R3Point& position = mesh.VertexPosition(vertex);
        R3LoadPoint(position);
      }
    }
    else if (rendering_scheme == NDOTV_RENDERING) {
      // Set color per vertex
      for (int j = 0; j < 3; j++) {
        R3MeshVertex *vertex = mesh.VertexOnFace(face, j);
        const R3Point& world_position = mesh.VertexPosition(vertex);
        R3Vector n = mesh.FaceNormal(face);
        R3Vector v = viewpoint - world_position; v.Normalize();
        RNScalar ndotv = n.Dot(v);
        int ndotv_value = 32768 * (ndotv + 1.0);
        if (ndotv_value < 0) ndotv_value = 0;
        else if (ndotv_value > 65535) ndotv_value = 65535;
        LoadInteger(ndotv_value);
        R3LoadPoint(world_position);
      }
    }
    else if ((rendering_scheme >= FACE_INDEX_RENDERING) && (rendering_scheme <= FACE_CATEGORY_RENDERING)) {
      // Set color per face based on face attributes
      if (rendering_scheme == FACE_INDEX_RENDERING) LoadInteger(mesh.FaceID(face)+1);
      else if (rendering_scheme == FACE_MATERIAL_RENDERING) LoadInteger((mesh.FaceMaterial(face)+1) % 65536);
      else if (rendering_scheme == FACE_SEGMENT_RENDERING) LoadInteger((mesh.FaceSegment(face)+1) % 65536);
      else if (rendering_scheme == FACE_CATEGORY_RENDERING) LoadInteger((mesh.FaceCategory(face)+1) % 65536);
      for (int j = 0; j < 3; j++) {
        R3MeshVertex *vertex = mesh.VertexOnFace(face, j);
        const R3Point& position = mesh.VertexPosition(vertex);
        R3LoadPoint(position);
      }
    }
    else if (rendering_scheme >= COLOR_RENDERING){
      for (int j = 0; j < 3; j++) {
        R3MeshVertex *vertex = mesh.VertexOnFace(face, j);
        const R3Point& position = mesh.VertexPosition(vertex);
        const RNRgb& color = mesh.VertexColor(vertex);
        RNLoadRgb(color);
        R3LoadPoint(position);
      }
    }
    else {
      LoadInteger(0);
      for (int j = 0; j < 3; j++) {
        R3MeshVertex *vertex = mesh.VertexOnFace(face, j);
        const R3Point& position = mesh.VertexPosition(vertex);
        R3LoadPoint(position);
      }
    }
  }
  RNGrfxEnd();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x168, %rsp            # imm = 0x168
movq %rcx, %r14
movq %rdx, %r12
movq %rsi, %rbx
movl %edi, %r15d
movl 0x13ec58(%rip), %edx    # 0x168a80
movl 0x13ec56(%rip), %ecx    # 0x168a84
xorl %edi, %edi
xorl %esi, %esi
callq 0x23210
xorps %xmm0, %xmm0
xorps %xmm1, %xmm1
xorps %xmm2, %xmm2
xorps %xmm3, %xmm3
callq 0x23e50
movl $0x4100, %edi           # imm = 0x4100
callq 0x231f0
movl $0xb71, %edi            # imm = 0xB71
callq 0x23830
movsd 0xc31c4(%rip), %xmm0    # 0xed028
movapd %xmm0, %xmm1
movapd %xmm0, %xmm2
callq 0x23ea0
leaq 0x88(%rsp), %r13
movq %r13, %rdi
movq %r12, %rsi
movq %r14, %rdx
callq 0x82ea8
leaq 0x108(%rsp), %r14
movq %r14, %rdi
movq %rbx, 0x8(%rsp)
movq %rbx, %rsi
movq %r13, %rdx
callq 0x82a46
leaq 0x88(%rsp), %rdi
movq %r14, %rsi
callq 0x82ad0
pushq $0x4
popq %rdi
callq 0x23180
leal -0x6(%r15), %ebp
movq %r15, 0x48(%rsp)
leal -0x2(%r15), %eax
movl %eax, 0x2c(%rsp)
leaq 0xc31ea(%rip), %rbx     # 0xed0bc
xorl %ecx, %ecx
movslq 0x13ea69(%rip), %rax    # 0x168944
cmpq %rax, %rcx
jge 0x2a3ad
movq 0x13ea4d(%rip), %rax    # 0x168938
movq %rcx, 0x50(%rsp)
movq (%rax,%rcx,8), %r13
cmpb $0x1, 0x13eb7d(%rip)    # 0x168a78
jne 0x29f18
movl 0xa0(%r13), %eax
cmpl $0x9, %eax
je 0x29f0e
cmpl $0x40, %eax
jne 0x29f18
movq 0x50(%rsp), %rcx
incq %rcx
jmp 0x29ed4
cmpl $0x5, %ebp
ja 0x29fe7
pushq $0x1
popq %r15
cmpq $0x4, %r15
je 0x29f0e
movq (%r13,%r15,8), %r12
leaq 0x18(%r12), %r14
leaq 0x10(%rsp), %rdi
leaq 0x88(%rsp), %rsi
movq %r14, %rdx
callq 0x85e4f
cmpl $0x5, %ebp
ja 0x29fa6
movslq (%rbx,%rbp,4), %rax
addq %rbx, %rax
jmpq *%rax
movsd 0x10(%rsp), %xmm0
jmp 0x29faa
movsd 0x20(%r12), %xmm0
movq 0x8(%rsp), %rax
subsd 0x8(%rax), %xmm0
jmp 0x29faa
movsd 0x20(%rsp), %xmm0
jmp 0x29faa
movsd (%r14), %xmm0
movq 0x8(%rsp), %rax
subsd (%rax), %xmm0
jmp 0x29faa
movsd 0x18(%rsp), %xmm0
jmp 0x29faa
movsd 0x28(%r12), %xmm0
movq 0x8(%rsp), %rax
subsd 0x10(%rax), %xmm0
jmp 0x29faa
xorpd %xmm0, %xmm0
mulsd 0x139a0e(%rip), %xmm0   # 0x1639c0
addsd 0xc3076(%rip), %xmm0    # 0xed030
cvttsd2si %xmm0, %edi
movl $0xffff, %eax           # imm = 0xFFFF
cmpl %eax, %edi
jl 0x29fcc
movl $0xffff, %edi           # imm = 0xFFFF
testl %edi, %edi
jg 0x29fd2
xorl %edi, %edi
callq 0x2a961
movq %r14, %rdi
callq 0x231a0
incq %r15
jmp 0x29f25
movq 0x48(%rsp), %rax
cmpl $0x14, %eax
ja 0x2a1df
movl $0x77000, %ecx          # imm = 0x77000
btl %eax, %ecx
jae 0x2a06d
leaq 0x13e90a(%rip), %rdi    # 0x168910
movq %r13, %rsi
movq %rax, %r14
callq 0x2a9e6
leaq 0x10(%rsp), %r15
movq %r15, %rdi
movq %rax, %rsi
callq 0x87b54
leaq 0x30(%rsp), %r12
movq %r12, %rdi
leaq 0x88(%rsp), %rsi
movq %r15, %rdx
callq 0x85dd7
movq %r12, %rdi
callq 0x87e46
xorpd %xmm0, %xmm0
leal -0xc(%r14), %eax
cmpl $0x6, %eax
ja 0x2a239
leaq 0xc3047(%rip), %rcx     # 0xed0a0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movsd 0x30(%rsp), %xmm0
jmp 0x2a239
movl $0x88000, %ecx          # imm = 0x88000
btl %eax, %ecx
jae 0x2a134
leaq 0x13e88e(%rip), %r14    # 0x168910
movq %r14, %rdi
movq %r13, %rsi
callq 0x2a9e6
leaq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x87b54
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x66c76
movq 0x48(%rsp), %rax
cmpl $0x13, %eax
je 0x2a287
xorpd %xmm0, %xmm0
cmpl $0xf, %eax
jne 0x2a2bb
leaq 0x70(%rsp), %rdi
leaq 0x88(%rsp), %r14
movq %r14, %rsi
leaq 0x30(%rsp), %rdx
callq 0x85e4f
leaq 0x58(%rsp), %r15
movq %r15, %rdi
movq %r14, %rsi
leaq 0x10(%rsp), %rdx
callq 0x85dd7
movq %r15, %rdi
callq 0x87e46
movsd 0x70(%rsp), %xmm0
movsd 0x60(%rsp), %xmm1
mulsd 0x78(%rsp), %xmm1
xorpd 0xc2f6a(%rip), %xmm0    # 0xed080
mulsd 0x58(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd 0x80(%rsp), %xmm1
mulsd 0x68(%rsp), %xmm1
jmp 0x2a2b7
cmpl $0x14, %eax
jne 0x2a1df
pushq $0x1
popq %r15
cmpq $0x4, %r15
je 0x29f0e
movq (%r13,%r15,8), %r14
addq $0x18, %r14
leaq 0x13e7b5(%rip), %rdi    # 0x168910
movq %r13, %rsi
callq 0x2a9e6
leaq 0x10(%rsp), %r12
movq %r12, %rdi
movq %rax, %rsi
callq 0x87b54
leaq 0x30(%rsp), %rbx
movq %rbx, %rdi
movq 0x8(%rsp), %rsi
movq %r14, %rdx
callq 0x87561
movq %rbx, %rdi
callq 0x87e46
movq %r12, %rdi
movq %rbx, %rsi
callq 0x87dbe
addsd 0xc2e85(%rip), %xmm0    # 0xed028
mulsd 0xc2e85(%rip), %xmm0    # 0xed030
cvttsd2si %xmm0, %edi
movl $0xffff, %eax           # imm = 0xFFFF
cmpl %eax, %edi
jl 0x2a1bd
movl $0xffff, %edi           # imm = 0xFFFF
testl %edi, %edi
jg 0x2a1c3
xorl %edi, %edi
callq 0x2a961
movq %r14, %rdi
callq 0x231a0
incq %r15
leaq 0xc2ee2(%rip), %rbx     # 0xed0bc
jmp 0x2a141
cmpl $0x3, 0x2c(%rsp)
ja 0x2a309
cmpl $0x4, %eax
je 0x2a36b
cmpl $0x3, %eax
je 0x2a362
cmpl $0x2, %eax
jne 0x2a374
movl 0xa4(%r13), %edi
incl %edi
jmp 0x2a387
movsd 0x40(%rsp), %xmm0
jmp 0x2a239
movsd 0x20(%rsp), %xmm0
jmp 0x2a239
movsd 0x38(%rsp), %xmm0
jmp 0x2a239
movsd 0x10(%rsp), %xmm0
jmp 0x2a239
movsd 0x18(%rsp), %xmm0
addsd 0xc2de7(%rip), %xmm0    # 0xed028
mulsd 0xc2de7(%rip), %xmm0    # 0xed030
cvttsd2si %xmm0, %edi
movl $0xffff, %eax           # imm = 0xFFFF
cmpl %eax, %edi
cmovgel %eax, %edi
testl %edi, %edi
movl $0x0, %eax
cmovlel %eax, %edi
callq 0x2a961
pushq $0x1
popq %r14
cmpq $0x4, %r14
je 0x29f0e
movq (%r13,%r14,8), %rdi
addq $0x18, %rdi
callq 0x231a0
incq %r14
jmp 0x2a26a
movsd 0x30(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
mulsd 0x38(%rsp), %xmm1
xorpd 0xc2ddf(%rip), %xmm0    # 0xed080
mulsd 0x10(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd 0x40(%rsp), %xmm1
mulsd 0x20(%rsp), %xmm1
subsd %xmm1, %xmm0
mulsd 0x1396fd(%rip), %xmm0   # 0x1639c0
addsd 0xc2d65(%rip), %xmm0    # 0xed030
cvttsd2si %xmm0, %edi
movl $0xffff, %eax           # imm = 0xFFFF
cmpl %eax, %edi
cmovgel %eax, %edi
testl %edi, %edi
movl $0x0, %eax
cmovlel %eax, %edi
callq 0x2a961
pushq $0x1
popq %r14
cmpq $0x4, %r14
je 0x29f0e
movq (%r13,%r14,8), %rdi
addq $0x18, %rdi
callq 0x231a0
incq %r14
jmp 0x2a2ec
testl %eax, %eax
jle 0x2a33a
pushq $0x1
popq %r15
cmpq $0x4, %r15
je 0x29f0e
movq (%r13,%r15,8), %rdi
leaq 0x18(%rdi), %r14
addq $0x58, %rdi
callq 0x2a9d3
movq %r14, %rdi
callq 0x231a0
incq %r15
jmp 0x2a311
xorl %edi, %edi
callq 0x2a961
pushq $0x1
popq %r14
cmpq $0x4, %r14
je 0x29f0e
movq (%r13,%r14,8), %rdi
addq $0x18, %rdi
callq 0x231a0
incq %r14
jmp 0x2a345
movl 0x98(%r13), %eax
jmp 0x2a37b
movl 0x9c(%r13), %eax
jmp 0x2a37b
movl 0xa0(%r13), %eax
incl %eax
cltd
movl $0x10000, %ecx          # imm = 0x10000
idivl %ecx
movl %edx, %edi
callq 0x2a961
pushq $0x1
popq %r14
cmpq $0x4, %r14
je 0x29f0e
movq (%r13,%r14,8), %rdi
addq $0x18, %rdi
callq 0x231a0
incq %r14
jmp 0x2a390
callq 0x23c70
addq $0x168, %rsp            # imm = 0x168
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq