// File: tomfunkhouser[P]gaps/apps/conf2img/conf2img.cpp
// Function: CreateMeshChannels(gaps::RGBDImage*, gaps::R2Grid const&, gaps::R2Grid const&, gaps::R2Grid const&, gaps::R2Grid const&, gaps::R2Grid const&, gaps::R2Grid const&, gaps::R2Grid const&, gaps::R2Grid const&, gaps::R2Grid const&, gaps::R2Grid&, gaps::R2Grid&, gaps::R2Grid&, gaps::R2Grid&, gaps::R3Point const&, gaps::R3Vector const&, gaps::R3Vector const&, gaps::R3Mesh const&, double)
static int
CreateMeshChannels(RGBDImage *image, const R2Grid& depth_image,
  const R2Grid& px_image, const R2Grid& py_image, const R2Grid& pz_image, const R2Grid& boundary_image,
  const R2Grid& nx_image, const R2Grid& ny_image, const R2Grid& nz_image, const R2Grid& radius_image,
  R2Grid& mesh_face_image, R2Grid& mesh_material_image, R2Grid& mesh_segment_image, R2Grid& mesh_category_image,
  const R3Point& viewpoint, const R3Vector& towards, const R3Vector& up, const R3Mesh& mesh,
  RNLength max_world_distance_factor = 0.05)
{
  // Create kdtree for mesh
  R3MeshSearchTree kdtree((R3Mesh *) &mesh);

  // Initialize output images
  mesh_face_image.Resample(depth_image.XResolution(), depth_image.YResolution());
  mesh_material_image.Resample(depth_image.XResolution(), depth_image.YResolution());
  mesh_segment_image.Resample(depth_image.XResolution(), depth_image.YResolution());
  mesh_category_image.Resample(depth_image.XResolution(), depth_image.YResolution());

  // Compute output images
  for (int iy = 0; iy < depth_image.YResolution(); iy++) {
    for (int ix = 0; ix < depth_image.XResolution(); ix++) {
      // Check depth
      RNScalar depth = depth_image.GridValue(ix, iy);
      if (depth == R2_GRID_UNKNOWN_VALUE) continue;

      // Get world position
      RNScalar px = px_image.GridValue(ix, iy);
      if (px == R2_GRID_UNKNOWN_VALUE) continue;
      RNScalar py = py_image.GridValue(ix, iy);
      if (py == R2_GRID_UNKNOWN_VALUE) continue;
      RNScalar pz = pz_image.GridValue(ix, iy);
      if (pz == R2_GRID_UNKNOWN_VALUE) continue;
      R3Point world_position(px, py, pz);
      world_position.Transform(image->CameraToWorld());

#if 0
      // Get world normal
      RNScalar nx = nx_image.GridValue(ix, iy);
      if (nx == R2_GRID_UNKNOWN_VALUE) continue;
      RNScalar ny = ny_image.GridValue(ix, iy);
      if (ny == R2_GRID_UNKNOWN_VALUE) continue;
      RNScalar nz = nz_image.GridValue(ix, iy);
      if (nz == R2_GRID_UNKNOWN_VALUE) continue;
      R3Vector world_normal(nx, ny, nz);
      world_normal.Transform(image->CameraToWorld());
#else
      R3Vector world_normal(0,0,0);
#endif
      
      // Find closest compatible face on mesh
      R3MeshIntersection closest;
      RNScalar max_world_distance = max_world_distance_factor * depth;
      kdtree.FindClosest(world_position, world_normal, closest, 0, max_world_distance, IsFaceCompatible);
      if (closest.type == R3_MESH_NULL_TYPE) continue;
      R3MeshFace *face = closest.face;
      if (!face) continue;

      // Assign face properties to pixel of output images
      mesh_face_image.SetGridValue(ix, iy, mesh.FaceID(face)+1);
      mesh_material_image.SetGridValue(ix, iy, (mesh.FaceMaterial(face)%65535)+1);
      mesh_segment_image.SetGridValue(ix, iy, (mesh.FaceSegment(face)%65535)+1);
      mesh_category_image.SetGridValue(ix, iy, (mesh.FaceCategory(face)%65535)+1);
    }
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x1d8, %rsp            # imm = 0x1D8
movq 0x238(%rsp), %rax
movq 0x230(%rsp), %rax
movq 0x228(%rsp), %rax
movq 0x220(%rsp), %rax
movq 0x218(%rsp), %rax
movq 0x210(%rsp), %rax
movq 0x208(%rsp), %rax
movq 0x200(%rsp), %rax
movq 0x1f8(%rsp), %rax
movq 0x1f0(%rsp), %rax
movq 0x1e8(%rsp), %rax
movq 0x1e0(%rsp), %rax
movq %rdi, 0x1d0(%rsp)
movq %rsi, 0x1c8(%rsp)
movq %rdx, 0x1c0(%rsp)
movq %rcx, 0x1b8(%rsp)
movq %r8, 0x1b0(%rsp)
movq %r9, 0x1a8(%rsp)
movsd %xmm0, 0x1a0(%rsp)
movq 0x238(%rsp), %rsi
leaq 0x188(%rsp), %rdi
callq 0x98c10
movq 0x200(%rsp), %rax
movq %rax, 0xc0(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30740
movl %eax, 0xcc(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30760
movq 0xc0(%rsp), %rdi
movl 0xcc(%rsp), %esi
movl %eax, %edx
xorl %ecx, %ecx
callq 0x1212b0
jmp 0x2be50
movq 0x208(%rsp), %rax
movq %rax, 0xb0(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30740
movl %eax, 0xbc(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30760
movq 0xb0(%rsp), %rdi
movl 0xbc(%rsp), %esi
movl %eax, %edx
xorl %ecx, %ecx
callq 0x1212b0
jmp 0x2be9b
movq 0x210(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30740
movl %eax, 0xac(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30760
movq 0xa0(%rsp), %rdi
movl 0xac(%rsp), %esi
movl %eax, %edx
xorl %ecx, %ecx
callq 0x1212b0
jmp 0x2bee6
movq 0x218(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30740
movl %eax, 0x9c(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30760
movq 0x90(%rsp), %rdi
movl 0x9c(%rsp), %esi
movl %eax, %edx
xorl %ecx, %ecx
callq 0x1212b0
jmp 0x2bf31
movl $0x0, 0x178(%rsp)
movl 0x178(%rsp), %eax
movl %eax, 0x8c(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30760
movl %eax, %ecx
movl 0x8c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2c42d
movl $0x0, 0x174(%rsp)
movl 0x174(%rsp), %eax
movl %eax, 0x88(%rsp)
movq 0x1c8(%rsp), %rdi
callq 0x30740
movl %eax, %ecx
movl 0x88(%rsp), %eax
cmpl %ecx, %eax
jge 0x2c415
movq 0x1c8(%rsp), %rdi
movl 0x174(%rsp), %esi
movl 0x178(%rsp), %edx
callq 0x30830
movsd %xmm0, 0x80(%rsp)
jmp 0x2bfc5
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x168(%rsp)
movsd 0x168(%rsp), %xmm0
movsd 0x1b3068(%rip), %xmm1   # 0x1df050
ucomisd %xmm1, %xmm0
jne 0x2c01b
jp 0x2c01b
jmp 0x2c3ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x180(%rsp)
movl %eax, 0x17c(%rsp)
leaq 0x188(%rsp), %rdi
callq 0x98dd0
jmp 0x2c447
movq 0x1c0(%rsp), %rdi
movl 0x174(%rsp), %esi
movl 0x178(%rsp), %edx
callq 0x30830
movsd %xmm0, 0x78(%rsp)
jmp 0x2c03e
movsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x160(%rsp)
movsd 0x160(%rsp), %xmm0
movsd 0x1b2ff2(%rip), %xmm1   # 0x1df050
ucomisd %xmm1, %xmm0
jne 0x2c06b
jp 0x2c06b
jmp 0x2c3ff
movq 0x1b8(%rsp), %rdi
movl 0x174(%rsp), %esi
movl 0x178(%rsp), %edx
callq 0x30830
movsd %xmm0, 0x70(%rsp)
jmp 0x2c08e
movsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x158(%rsp)
movsd 0x158(%rsp), %xmm0
movsd 0x1b2fa2(%rip), %xmm1   # 0x1df050
ucomisd %xmm1, %xmm0
jne 0x2c0bb
jp 0x2c0bb
jmp 0x2c3ff
movq 0x1b0(%rsp), %rdi
movl 0x174(%rsp), %esi
movl 0x178(%rsp), %edx
callq 0x30830
movsd %xmm0, 0x68(%rsp)
jmp 0x2c0de
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x150(%rsp)
movsd 0x150(%rsp), %xmm0
movsd 0x1b2f52(%rip), %xmm1   # 0x1df050
ucomisd %xmm1, %xmm0
jne 0x2c10b
jp 0x2c10b
jmp 0x2c3ff
movsd 0x160(%rsp), %xmm0
movsd 0x158(%rsp), %xmm1
movsd 0x150(%rsp), %xmm2
leaq 0x138(%rsp), %rdi
callq 0x105900
jmp 0x2c135
movq 0x1d0(%rsp), %rdi
callq 0x30870
movq %rax, 0x60(%rsp)
jmp 0x2c149
movq 0x60(%rsp), %rsi
leaq 0x138(%rsp), %rdi
callq 0x106570
jmp 0x2c15d
leaq 0x120(%rsp), %rdi
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x106a60
jmp 0x2c175
leaq 0xe0(%rsp), %rdi
callq 0x30880
jmp 0x2c184
movsd 0x1a0(%rsp), %xmm0
movsd 0x168(%rsp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0xd8(%rsp)
movsd 0xd8(%rsp), %xmm1
leaq 0x2ad(%rip), %r8        # 0x2c460
xorl %eax, %eax
movl %eax, %r9d
leaq 0x188(%rsp), %rdi
leaq 0x138(%rsp), %rsi
leaq 0x120(%rsp), %rdx
leaq 0xe0(%rsp), %rcx
xorps %xmm0, %xmm0
callq 0x9ba90
jmp 0x2c1e2
cmpl $0x0, 0xe0(%rsp)
jne 0x2c1f1
jmp 0x2c3ff
movq 0xf8(%rsp), %rax
movq %rax, 0xd0(%rsp)
cmpq $0x0, 0xd0(%rsp)
jne 0x2c211
jmp 0x2c3ff
movq 0x200(%rsp), %rax
movq %rax, 0x48(%rsp)
movl 0x174(%rsp), %eax
movl %eax, 0x54(%rsp)
movl 0x178(%rsp), %eax
movl %eax, 0x58(%rsp)
movq 0x238(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x308f0
movl %eax, 0x5c(%rsp)
jmp 0x2c24f
movl 0x58(%rsp), %edx
movl 0x54(%rsp), %esi
movq 0x48(%rsp), %rdi
movl 0x5c(%rsp), %eax
incl %eax
cvtsi2sd %eax, %xmm0
callq 0x308a0
jmp 0x2c26d
movq 0x208(%rsp), %rax
movq %rax, 0x30(%rsp)
movl 0x174(%rsp), %eax
movl %eax, 0x3c(%rsp)
movl 0x178(%rsp), %eax
movl %eax, 0x40(%rsp)
movq 0x238(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x30910
movl %eax, 0x44(%rsp)
jmp 0x2c2ab
movl 0x40(%rsp), %edx
movl 0x3c(%rsp), %esi
movq 0x30(%rsp), %rdi
movl 0x44(%rsp), %r8d
movslq %r8d, %rax
imulq $-0x7fff7fff, %rax, %rax # imm = 0x80008001
shrq $0x20, %rax
addl %r8d, %eax
movl %eax, %ecx
shrl $0x1f, %ecx
sarl $0xf, %eax
addl %ecx, %eax
movl %eax, %ecx
shll $0x10, %ecx
subl %ecx, %eax
movl %eax, %ecx
movl %r8d, %eax
leal 0x1(%rax,%rcx), %eax
cvtsi2sd %eax, %xmm0
callq 0x308a0
jmp 0x2c2f3
movq 0x210(%rsp), %rax
movq %rax, 0x18(%rsp)
movl 0x174(%rsp), %eax
movl %eax, 0x24(%rsp)
movl 0x178(%rsp), %eax
movl %eax, 0x28(%rsp)
movq 0x238(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x30930
movl %eax, 0x2c(%rsp)
jmp 0x2c331
movl 0x28(%rsp), %edx
movl 0x24(%rsp), %esi
movq 0x18(%rsp), %rdi
movl 0x2c(%rsp), %r8d
movslq %r8d, %rax
imulq $-0x7fff7fff, %rax, %rax # imm = 0x80008001
shrq $0x20, %rax
addl %r8d, %eax
movl %eax, %ecx
shrl $0x1f, %ecx
sarl $0xf, %eax
addl %ecx, %eax
movl %eax, %ecx
shll $0x10, %ecx
subl %ecx, %eax
movl %eax, %ecx
movl %r8d, %eax
leal 0x1(%rax,%rcx), %eax
cvtsi2sd %eax, %xmm0
callq 0x308a0
jmp 0x2c379
movq 0x218(%rsp), %rax
movq %rax, (%rsp)
movl 0x174(%rsp), %eax
movl %eax, 0xc(%rsp)
movl 0x178(%rsp), %eax
movl %eax, 0x10(%rsp)
movq 0x238(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x30950
movl %eax, 0x14(%rsp)
jmp 0x2c3b6
movl 0x10(%rsp), %edx
movl 0xc(%rsp), %esi
movq (%rsp), %rdi
movl 0x14(%rsp), %r8d
movslq %r8d, %rax
imulq $-0x7fff7fff, %rax, %rax # imm = 0x80008001
shrq $0x20, %rax
addl %r8d, %eax
movl %eax, %ecx
shrl $0x1f, %ecx
sarl $0xf, %eax
addl %ecx, %eax
movl %eax, %ecx
shll $0x10, %ecx
subl %ecx, %eax
movl %eax, %ecx
movl %r8d, %eax
leal 0x1(%rax,%rcx), %eax
cvtsi2sd %eax, %xmm0
callq 0x308a0
jmp 0x2c3fd
jmp 0x2c3ff
movl 0x174(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x174(%rsp)
jmp 0x2bf73
jmp 0x2c417
movl 0x178(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x178(%rsp)
jmp 0x2bf3c
leaq 0x188(%rsp), %rdi
callq 0x98dd0
movl $0x1, %eax
addq $0x1d8, %rsp            # imm = 0x1D8
retq
movq 0x180(%rsp), %rdi
callq 0x25290
nopw %cs:(%rax,%rax)