// File: tomfunkhouser[P]gaps/apps/msh2msh/msh2msh.cpp
// Function: DeleteInteriorFaces(gaps::R3Mesh*)
static int
DeleteInteriorFaces(R3Mesh *mesh)
{
  // Start statistics
  RNTime start_time;
  start_time.Read();

  // Get convenient variables
  int resolution = 1024;
  R3Point c = mesh->BBox().Centroid();
  RNScalar r = mesh->BBox().DiagonalRadius();
  R2Box bbox2d(-r, -r, r, r);
  R2Grid face_image(bbox2d, r / resolution);
  R2Grid depth_image(face_image);
  RNScalar d = face_image.GridToWorldScaleFactor();
  RNArea pixel_area = d*d;
  const int nviews = 100;

  // Initialize face marks
  int *marks = new int [ mesh->NFaces() ];
  for (int i = 0; i < mesh->NFaces(); i++) marks[i] = 0;

  // Mark faces visible from any exterior view
  for (int k = 0; k < nviews; k++) {
    // Create transformation
    R3Affine transformation = R3identity_affine;
    transformation.Rotate(R3RandomDirection(), RN_TWO_PI * RNRandomScalar());
    transformation.Rotate(R3RandomDirection(), RN_TWO_PI * RNRandomScalar());
    transformation.Rotate(R3RandomDirection(), RN_TWO_PI * RNRandomScalar());
    transformation.Translate(-c.Vector());

    // Render image
    face_image.Clear(-1);
    depth_image.Clear(RN_INFINITY);
    for (int i = 0; i < mesh->NFaces(); i++) {
      R3MeshFace *face = mesh->Face(i);
      R3MeshVertex *v0 = mesh->VertexOnFace(face, 0);
      R3MeshVertex *v1 = mesh->VertexOnFace(face, 1);
      R3MeshVertex *v2 = mesh->VertexOnFace(face, 2);
      R3Point p0 = mesh->VertexPosition(v0);
      R3Point p1 = mesh->VertexPosition(v1);
      R3Point p2 = mesh->VertexPosition(v2);
      p0.Transform(transformation);
      p1.Transform(transformation);
      p2.Transform(transformation);
      face_image.RenderWorldTriangle(
        R2Point(p0.X(), p0.Y()),
        R2Point(p1.X(), p1.Y()),
        R2Point(p2.X(), p2.Y()),
        i, i, i,
        p0.Z(), p1.Z(), p2.Z(),
        depth_image);
    }

    // Mark visible faces
    for (int i = 0; i < face_image.NEntries(); i++) {
      RNScalar face_value = face_image.GridValue(i);
      if (face_value < 0) continue;
      int face_index = (int) (face_value + 0.5);
      if (face_index < 0) continue;
      if (face_index >= mesh->NFaces()) continue;
      marks[face_index]++;
    }
  }

  // Find unmarked faces
  RNArray<R3MeshFace *> unmarked_faces;
  for (int i = 0; i < mesh->NFaces(); i++) {
    R3MeshFace *face = mesh->Face(i);
    int possible_marks = nviews * mesh->FaceArea(face) / pixel_area;
    if (marks[i] > 1E-3*possible_marks) continue;
    unmarked_faces.Insert(face);
  }
  
  // Delete unmarked faces
  for (int i = 0; i < unmarked_faces.NEntries(); i++) {
    R3MeshFace *face = unmarked_faces.Kth(i);
    mesh->DeleteFace(face);
  }

  // Print debug statistics
  if (print_verbose) {
    printf("  Deleted interior faces ...\n");
    printf("    Time = %.2f seconds\n", start_time.Elapsed());
    printf("    # Deleted Faces = %d\n", unmarked_faces.NEntries());
    printf("    # Remaining Faces = %d\n", mesh->NFaces());
    fflush(stdout);
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x608, %rsp            # imm = 0x608
movq %rdi, 0x600(%rsp)
leaq 0x5f0(%rsp), %rdi
movq %rdi, 0x148(%rsp)
callq 0xc35d0
movq 0x148(%rsp), %rdi
callq 0x165f0
movl $0x400, 0x5ec(%rsp) # imm = 0x400
movq 0x600(%rsp), %rdi
callq 0x16660
movq %rax, %rsi
movq (%rsi), %rax
movq 0x68(%rax), %rax
leaq 0x5d0(%rsp), %rdi
callq *%rax
movq 0x600(%rsp), %rdi
callq 0x16660
movq %rax, %rdi
callq 0x16680
movsd %xmm0, 0x5c8(%rsp)
movsd 0x5c8(%rsp), %xmm3
movaps %xmm3, %xmm1
movaps 0x111ab2(%rip), %xmm0   # 0x126040
pxor %xmm0, %xmm1
leaq 0x5a0(%rsp), %rdi
movq %rdi, 0x150(%rsp)
movaps %xmm1, %xmm0
movaps %xmm3, %xmm2
callq 0xafed0
movq 0x150(%rsp), %rsi
movsd 0x5c8(%rsp), %xmm0
cvtsi2sdl 0x5ec(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x4d0(%rsp), %rdi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x995e0
jmp 0x145de
leaq 0x3f0(%rsp), %rdi
leaq 0x4d0(%rsp), %rsi
callq 0x99b40
jmp 0x145f5
leaq 0x4d0(%rsp), %rdi
callq 0x166a0
movsd %xmm0, 0x140(%rsp)
jmp 0x1460d
movsd 0x140(%rsp), %xmm0
movsd %xmm0, 0x3e8(%rsp)
movsd 0x3e8(%rsp), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, 0x3e0(%rsp)
movl $0x64, 0x3dc(%rsp)
movq 0x600(%rsp), %rdi
callq 0x164b0
movl %eax, 0x13c(%rsp)
jmp 0x14656
movl 0x13c(%rsp), %eax
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0xf030
movq %rax, 0x130(%rsp)
jmp 0x14684
movq 0x130(%rsp), %rax
movq %rax, 0x3d0(%rsp)
movl $0x0, 0x3cc(%rsp)
movl 0x3cc(%rsp), %eax
movl %eax, 0x128(%rsp)
movq 0x600(%rsp), %rdi
callq 0x164b0
movl %eax, 0x12c(%rsp)
jmp 0x146c3
movl 0x128(%rsp), %eax
movl 0x12c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x1474a
movq 0x3d0(%rsp), %rax
movslq 0x3cc(%rsp), %rcx
movl $0x0, (%rax,%rcx,4)
movl 0x3cc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3cc(%rsp)
jmp 0x1469f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4c8(%rsp)
movl %eax, 0x4c4(%rsp)
jmp 0x150be
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4c8(%rsp)
movl %eax, 0x4c4(%rsp)
jmp 0x150b1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4c8(%rsp)
movl %eax, 0x4c4(%rsp)
jmp 0x150a4
movl $0x0, 0x3c8(%rsp)
cmpl $0x64, 0x3c8(%rsp)
jge 0x14e03
leaq 0x14cca6(%rip), %rsi    # 0x161410
leaq 0x2b8(%rsp), %rdi
callq 0x16070
jmp 0x14779
leaq 0x2a0(%rsp), %rdi
callq 0x7ac00
jmp 0x14788
leaq 0x1140d1(%rip), %rax    # 0x128860
movsd (%rax), %xmm0
movsd %xmm0, 0x118(%rsp)
callq 0xc6fd0
movsd %xmm0, 0x120(%rsp)
jmp 0x147ac
movsd 0x120(%rsp), %xmm1
movsd 0x118(%rsp), %xmm0
mulsd %xmm1, %xmm0
leaq 0x2b8(%rsp), %rdi
leaq 0x2a0(%rsp), %rsi
callq 0x16700
jmp 0x147d9
leaq 0x288(%rsp), %rdi
callq 0x7ac00
jmp 0x147e8
leaq 0x114071(%rip), %rax    # 0x128860
movsd (%rax), %xmm0
movsd %xmm0, 0x108(%rsp)
callq 0xc6fd0
movsd %xmm0, 0x110(%rsp)
jmp 0x1480c
movsd 0x110(%rsp), %xmm1
movsd 0x108(%rsp), %xmm0
mulsd %xmm1, %xmm0
leaq 0x2b8(%rsp), %rdi
leaq 0x288(%rsp), %rsi
callq 0x16700
jmp 0x14839
leaq 0x270(%rsp), %rdi
callq 0x7ac00
jmp 0x14848
leaq 0x114011(%rip), %rax    # 0x128860
movsd (%rax), %xmm0
movsd %xmm0, 0xf8(%rsp)
callq 0xc6fd0
movsd %xmm0, 0x100(%rsp)
jmp 0x1486c
movsd 0x100(%rsp), %xmm1
movsd 0xf8(%rsp), %xmm0
mulsd %xmm1, %xmm0
leaq 0x2b8(%rsp), %rdi
leaq 0x270(%rsp), %rsi
callq 0x16700
jmp 0x14899
leaq 0x240(%rsp), %rdi
leaq 0x5d0(%rsp), %rsi
callq 0x16470
jmp 0x148b0
leaq 0x258(%rsp), %rdi
leaq 0x240(%rsp), %rsi
callq 0x7a950
jmp 0x148c7
leaq 0x2b8(%rsp), %rdi
leaq 0x258(%rsp), %rsi
callq 0x16430
jmp 0x148de
leaq 0x4d0(%rsp), %rdi
movsd 0x111742(%rip), %xmm0   # 0x126030
callq 0x9c4c0
jmp 0x148f5
leaq 0x14c384(%rip), %rax    # 0x160c80
movsd (%rax), %xmm0
leaq 0x3f0(%rsp), %rdi
callq 0x9c4c0
jmp 0x1490f
movl $0x0, 0x23c(%rsp)
movl 0x23c(%rsp), %eax
movl %eax, 0xf0(%rsp)
movq 0x600(%rsp), %rdi
callq 0x164b0
movl %eax, 0xf4(%rsp)
jmp 0x1493e
movl 0xf0(%rsp), %eax
movl 0xf4(%rsp), %ecx
cmpl %ecx, %eax
jge 0x14ce9
movq 0x600(%rsp), %rdi
movl 0x23c(%rsp), %esi
callq 0x164d0
movq %rax, 0xe8(%rsp)
jmp 0x14972
movq 0xe8(%rsp), %rax
movq %rax, 0x230(%rsp)
movq 0x600(%rsp), %rdi
movq 0x230(%rsp), %rsi
xorl %edx, %edx
callq 0x16750
movq %rax, 0xe0(%rsp)
jmp 0x149a3
movq 0xe0(%rsp), %rax
movq %rax, 0x228(%rsp)
movq 0x600(%rsp), %rdi
movq 0x230(%rsp), %rsi
movl $0x1, %edx
callq 0x16750
movq %rax, 0xd8(%rsp)
jmp 0x149d7
movq 0xd8(%rsp), %rax
movq %rax, 0x220(%rsp)
movq 0x600(%rsp), %rdi
movq 0x230(%rsp), %rsi
movl $0x2, %edx
callq 0x16750
movq %rax, 0xd0(%rsp)
jmp 0x14a0b
movq 0xd0(%rsp), %rax
movq %rax, 0x218(%rsp)
movq 0x600(%rsp), %rdi
movq 0x228(%rsp), %rsi
callq 0x16770
movq %rax, 0xc8(%rsp)
jmp 0x14a3a
movq 0xc8(%rsp), %rsi
leaq 0x200(%rsp), %rdi
callq 0x78540
jmp 0x14a51
movq 0x600(%rsp), %rdi
movq 0x220(%rsp), %rsi
callq 0x16770
movq %rax, 0xc0(%rsp)
jmp 0x14a70
movq 0xc0(%rsp), %rsi
leaq 0x1e8(%rsp), %rdi
callq 0x78540
jmp 0x14a87
movq 0x600(%rsp), %rdi
movq 0x218(%rsp), %rsi
callq 0x16770
movq %rax, 0xb8(%rsp)
jmp 0x14aa6
movq 0xb8(%rsp), %rsi
leaq 0x1d0(%rsp), %rdi
callq 0x78540
jmp 0x14abd
leaq 0x200(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x79170
jmp 0x14ad4
leaq 0x1e8(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x79170
jmp 0x14aeb
leaq 0x1d0(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x79170
jmp 0x14b02
leaq 0x200(%rsp), %rdi
callq 0x16880
movsd %xmm0, 0xb0(%rsp)
jmp 0x14b1a
leaq 0x200(%rsp), %rdi
callq 0x16890
movsd %xmm0, 0xa8(%rsp)
jmp 0x14b32
movsd 0xa8(%rsp), %xmm1
movsd 0xb0(%rsp), %xmm0
leaq 0x1c0(%rsp), %rdi
callq 0xb5a00
jmp 0x14b53
leaq 0x1e8(%rsp), %rdi
callq 0x16880
movsd %xmm0, 0xa0(%rsp)
jmp 0x14b6b
leaq 0x1e8(%rsp), %rdi
callq 0x16890
movsd %xmm0, 0x98(%rsp)
jmp 0x14b83
movsd 0x98(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm0
leaq 0x1b0(%rsp), %rdi
callq 0xb5a00
jmp 0x14ba4
leaq 0x1d0(%rsp), %rdi
callq 0x16880
movsd %xmm0, 0x90(%rsp)
jmp 0x14bbc
leaq 0x1d0(%rsp), %rdi
callq 0x16890
movsd %xmm0, 0x88(%rsp)
jmp 0x14bd4
movsd 0x88(%rsp), %xmm1
movsd 0x90(%rsp), %xmm0
leaq 0x1a0(%rsp), %rdi
callq 0xb5a00
jmp 0x14bf5
cvtsi2sdl 0x23c(%rsp), %xmm0
movsd %xmm0, 0x68(%rsp)
movaps %xmm0, %xmm1
movsd %xmm1, 0x70(%rsp)
movsd %xmm0, 0x78(%rsp)
leaq 0x200(%rsp), %rdi
callq 0x168a0
movsd %xmm0, 0x80(%rsp)
jmp 0x14c2b
leaq 0x1e8(%rsp), %rdi
callq 0x168a0
movsd %xmm0, 0x60(%rsp)
jmp 0x14c40
leaq 0x1d0(%rsp), %rdi
callq 0x168a0
movsd %xmm0, 0x58(%rsp)
jmp 0x14c55
movsd 0x58(%rsp), %xmm5
movsd 0x60(%rsp), %xmm4
movsd 0x80(%rsp), %xmm3
movsd 0x68(%rsp), %xmm2
movsd 0x78(%rsp), %xmm1
movsd 0x70(%rsp), %xmm0
leaq 0x4d0(%rsp), %rdi
leaq 0x1c0(%rsp), %rsi
leaq 0x1b0(%rsp), %rdx
leaq 0x1a0(%rsp), %rcx
leaq 0x3f0(%rsp), %r8
callq 0x16790
jmp 0x14cab
jmp 0x14cad
movl 0x23c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x23c(%rsp)
jmp 0x1491a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4c8(%rsp)
movl %eax, 0x4c4(%rsp)
leaq 0x2b8(%rsp), %rdi
callq 0x6d700
jmp 0x150a4
movl $0x0, 0x19c(%rsp)
movl 0x19c(%rsp), %eax
movl %eax, 0x50(%rsp)
leaq 0x4d0(%rsp), %rdi
callq 0x168b0
movl %eax, 0x54(%rsp)
jmp 0x14d12
movl 0x50(%rsp), %eax
movl 0x54(%rsp), %ecx
cmpl %ecx, %eax
jge 0x14de0
movl 0x19c(%rsp), %esi
leaq 0x4d0(%rsp), %rdi
callq 0x168d0
movsd %xmm0, 0x48(%rsp)
jmp 0x14d3e
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x190(%rsp)
xorps %xmm0, %xmm0
ucomisd 0x190(%rsp), %xmm0
jbe 0x14d5d
jmp 0x14dca
movsd 0x1112d3(%rip), %xmm0   # 0x126038
addsd 0x190(%rsp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x18c(%rsp)
cmpl $0x0, 0x18c(%rsp)
jge 0x14d85
jmp 0x14dca
movl 0x18c(%rsp), %eax
movl %eax, 0x40(%rsp)
movq 0x600(%rsp), %rdi
callq 0x164b0
movl %eax, 0x44(%rsp)
jmp 0x14da3
movl 0x40(%rsp), %eax
movl 0x44(%rsp), %ecx
cmpl %ecx, %eax
jl 0x14db1
jmp 0x14dca
movq 0x3d0(%rsp), %rax
movslq 0x18c(%rsp), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
movl 0x19c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x19c(%rsp)
jmp 0x14cf4
leaq 0x2b8(%rsp), %rdi
callq 0x6d700
movl 0x3c8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c8(%rsp)
jmp 0x14755
leaq 0x178(%rsp), %rdi
callq 0x168f0
jmp 0x14e12
movl $0x0, 0x174(%rsp)
movl 0x174(%rsp), %eax
movl %eax, 0x38(%rsp)
movq 0x600(%rsp), %rdi
callq 0x164b0
movl %eax, 0x3c(%rsp)
jmp 0x14e3b
movl 0x38(%rsp), %eax
movl 0x3c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x14f3d
movq 0x600(%rsp), %rdi
movl 0x174(%rsp), %esi
callq 0x164d0
movq %rax, 0x30(%rsp)
jmp 0x14e66
movq 0x30(%rsp), %rax
movq %rax, 0x168(%rsp)
movq 0x600(%rsp), %rdi
movq 0x168(%rsp), %rsi
callq 0x16900
movsd %xmm0, 0x28(%rsp)
jmp 0x14e90
movsd 0x28(%rsp), %xmm1
movsd 0x11118a(%rip), %xmm0   # 0x126028
mulsd %xmm1, %xmm0
divsd 0x3e0(%rsp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x164(%rsp)
movq 0x3d0(%rsp), %rax
movslq 0x174(%rsp), %rcx
cvtsi2sdl (%rax,%rcx,4), %xmm0
cvtsi2sdl 0x164(%rsp), %xmm2
movsd 0x111144(%rip), %xmm1   # 0x126020
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x14f0e
jmp 0x14f27
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x4c8(%rsp)
movl %eax, 0x4c4(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x169c0
jmp 0x150a4
movq 0x168(%rsp), %rsi
leaq 0x178(%rsp), %rdi
callq 0x16970
jmp 0x14f25
jmp 0x14f27
movl 0x174(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x174(%rsp)
jmp 0x14e1d
movl $0x0, 0x160(%rsp)
movl 0x160(%rsp), %eax
movl %eax, 0x24(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x16650
movl %eax, %ecx
movl 0x24(%rsp), %eax
cmpl %ecx, %eax
jge 0x14fc2
movl 0x160(%rsp), %esi
leaq 0x178(%rsp), %rdi
callq 0x169a0
movq %rax, 0x18(%rsp)
jmp 0x14f85
movq 0x18(%rsp), %rax
movq %rax, 0x158(%rsp)
movq 0x600(%rsp), %rdi
movq 0x158(%rsp), %rsi
movq (%rdi), %rax
movq 0x70(%rax), %rax
callq *%rax
jmp 0x14fad
jmp 0x14faf
movl 0x160(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x160(%rsp)
jmp 0x14f48
cmpl $0x0, 0x14becb(%rip)    # 0x160e94
je 0x15063
leaq 0x11131b(%rip), %rdi    # 0x1262f1
xorl %eax, %eax
callq 0xf070
jmp 0x14fdf
leaq 0x5f0(%rsp), %rdi
callq 0xc3690
movsd %xmm0, 0x10(%rsp)
jmp 0x14ff4
movsd 0x10(%rsp), %xmm0
leaq 0x11130e(%rip), %rdi    # 0x12630f
movb $0x1, %al
callq 0xf070
jmp 0x1500a
leaq 0x178(%rsp), %rdi
callq 0x16650
movl %eax, %esi
leaq 0x111308(%rip), %rdi    # 0x126328
xorl %eax, %eax
callq 0xf070
jmp 0x15029
movq 0x600(%rsp), %rdi
callq 0x164b0
movl %eax, 0xc(%rsp)
jmp 0x1503c
movl 0xc(%rsp), %esi
leaq 0x1112fb(%rip), %rdi    # 0x126342
xorl %eax, %eax
callq 0xf070
jmp 0x15050
movq 0x14af39(%rip), %rax    # 0x15ff90
movq (%rax), %rdi
callq 0xf5a0
jmp 0x15061
jmp 0x15063
leaq 0x178(%rsp), %rdi
callq 0x169c0
leaq 0x3f0(%rsp), %rdi
callq 0x99e30
leaq 0x4d0(%rsp), %rdi
callq 0x99e30
leaq 0x5a0(%rsp), %rdi
callq 0x169d0
movl $0x1, %eax
addq $0x608, %rsp            # imm = 0x608
retq
leaq 0x3f0(%rsp), %rdi
callq 0x99e30
leaq 0x4d0(%rsp), %rdi
callq 0x99e30
leaq 0x5a0(%rsp), %rdi
callq 0x169d0
movq 0x4c8(%rsp), %rdi
callq 0xf820
nopl (%rax,%rax)