// File: tomfunkhouser[P]gaps/apps/msh2pts/msh2pts.cpp
// Function: SelectVisibleSurfacePoints(gaps::R3Mesh*, int, double)
static RNArray<Point *> *
SelectVisibleSurfacePoints(R3Mesh *mesh, int npoints, double min_spacing)
{
  // Allocate array of points
  RNArray<Point *> *points = new RNArray<Point *>();
  if (!points) {
    RNFail("Unable to allocate array of points\n");
    return NULL;
  }

  // Initialze point search tree
  Point tmp; int position_offset = (unsigned char *) &(tmp.position) - (unsigned char *) &tmp;
  R3Kdtree<Point *> kdtree(mesh->BBox(), position_offset);

  // Get convenient variables
  // Need high resolution to avoid z-buffer quantization issues
  int resolution = 1024; 
  int nviews = npoints / (resolution * resolution);
  if (nviews < 128) nviews = 128;
  int npixels = resolution * resolution * nviews;
  RNScalar pixel_probability = (RNScalar) npoints / (RNScalar) npixels;
  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);

  // Insert points visible to random views
  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);
    }

    // Generate points
    for (int iy = 0; iy < depth_image.YResolution(); iy++) {
      for (int ix = 0; ix < depth_image.XResolution(); ix++) {
        if (RNRandomScalar() > pixel_probability) continue;
        RNScalar face_value = face_image.GridValue(ix, iy);
        if (face_value < 0)  continue;
        RNScalar depth = depth_image.GridValue(ix, iy);
        if (depth == RN_INFINITY) continue;
        R2Point xy_position = depth_image.WorldPosition(ix, iy);
        R3Point position(xy_position.X(), xy_position.Y(), depth);
        position.InverseTransform(transformation);
        if ((min_spacing > 0) && kdtree.FindAny(position, 0, min_spacing)) continue;
        int face_index = (int) (face_value + 0.5);
        if ((face_index < 0) || (face_index >= mesh->NFaces())) continue;
        R3MeshFace *face = mesh->Face(face_index);
        R3Vector normal = mesh->FaceNormal(face);
        R3Vector n = normal; n.Transform(transformation);
        if (n.Z() > 0) normal.Flip();
        Point *point = new Point(position, normal);
        if (min_spacing > 0) kdtree.InsertPoint(point);
        points->Insert(point);
      }
    }
  }

  // Return points
  return points;
}

// Assembly:
subq $0x698, %rsp            # imm = 0x698
movq %rdi, 0x688(%rsp)
movl %esi, 0x684(%rsp)
movsd %xmm0, 0x678(%rsp)
movl $0x10, %edi
callq 0xf4d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0xf0(%rsp)
callq 0x1b5a0
jmp 0x16c7e
movq 0xf0(%rsp), %rax
movq %rax, 0x670(%rsp)
cmpq $0x0, 0x670(%rsp)
jne 0x16ce3
leaq 0x13396f(%rip), %rdi    # 0x14a60f
movb $0x0, %al
callq 0xebe00
movq $0x0, 0x690(%rsp)
jmp 0x17828
movq 0xf0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x668(%rsp)
movl %eax, 0x664(%rsp)
movl $0x10, %esi
callq 0xf4e0
jmp 0x17838
leaq 0x618(%rsp), %rdi
callq 0x1ba90
leaq 0x618(%rsp), %rax
addq $0x10, %rax
leaq 0x618(%rsp), %rcx
subq %rcx, %rax
movl %eax, 0x614(%rsp)
movq 0x688(%rsp), %rdi
callq 0x1ba30
movq %rax, %rsi
movl 0x614(%rsp), %edx
leaq 0x5b0(%rsp), %rdi
callq 0x1bbb0
movl $0x400, 0x5ac(%rsp) # imm = 0x400
movl 0x684(%rsp), %eax
movl 0x5ac(%rsp), %ecx
imull 0x5ac(%rsp), %ecx
cltd
idivl %ecx
movl %eax, 0x5a8(%rsp)
cmpl $0x80, 0x5a8(%rsp)
jge 0x16d75
movl $0x80, 0x5a8(%rsp)
movl 0x5ac(%rsp), %eax
imull %eax, %eax
movl 0x5a8(%rsp), %ecx
imull %ecx, %eax
movl %eax, 0x5a4(%rsp)
cvtsi2sdl 0x684(%rsp), %xmm0
cvtsi2sdl 0x5a4(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x598(%rsp)
movq 0x688(%rsp), %rdi
callq 0x1ba30
movq %rax, %rsi
movq (%rsi), %rax
movq 0x68(%rax), %rax
leaq 0x580(%rsp), %rdi
callq *%rax
jmp 0x16dd2
movq 0x688(%rsp), %rdi
callq 0x1ba30
movq %rax, %rdi
callq 0x1e0d0
movsd %xmm0, 0xe8(%rsp)
jmp 0x16df2
movsd 0xe8(%rsp), %xmm0
movsd %xmm0, 0x578(%rsp)
movsd 0x578(%rsp), %xmm3
movaps %xmm3, %xmm1
movaps 0x133249(%rip), %xmm0   # 0x14a060
pxor %xmm0, %xmm1
leaq 0x550(%rsp), %rdi
movaps %xmm1, %xmm0
movaps %xmm3, %xmm2
callq 0xd44e0
jmp 0x16e30
movsd 0x578(%rsp), %xmm0
cvtsi2sdl 0x5ac(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x480(%rsp), %rdi
leaq 0x550(%rsp), %rsi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0xbdd90
jmp 0x16e61
leaq 0x3b0(%rsp), %rdi
leaq 0x480(%rsp), %rsi
callq 0xbe2f0
jmp 0x16e78
movl $0x0, 0x3ac(%rsp)
movl 0x3ac(%rsp), %eax
cmpl 0x5a8(%rsp), %eax
jge 0x177ac
leaq 0x17acd2(%rip), %rsi    # 0x191b70
leaq 0x298(%rsp), %rdi
callq 0x1e0f0
jmp 0x16ead
leaq 0x280(%rsp), %rdi
callq 0x9f360
jmp 0x16ebc
leaq 0x137085(%rip), %rax    # 0x14df48
movsd (%rax), %xmm0
movsd %xmm0, 0xd8(%rsp)
callq 0xeb5e0
movsd %xmm0, 0xe0(%rsp)
jmp 0x16ee0
movsd 0xe0(%rsp), %xmm1
movsd 0xd8(%rsp), %xmm0
mulsd %xmm1, %xmm0
leaq 0x298(%rsp), %rdi
leaq 0x280(%rsp), %rsi
callq 0x1e1a0
jmp 0x16f0d
leaq 0x268(%rsp), %rdi
callq 0x9f360
jmp 0x16f1c
leaq 0x137025(%rip), %rax    # 0x14df48
movsd (%rax), %xmm0
movsd %xmm0, 0xc8(%rsp)
callq 0xeb5e0
movsd %xmm0, 0xd0(%rsp)
jmp 0x16f40
movsd 0xd0(%rsp), %xmm1
movsd 0xc8(%rsp), %xmm0
mulsd %xmm1, %xmm0
leaq 0x298(%rsp), %rdi
leaq 0x268(%rsp), %rsi
callq 0x1e1a0
jmp 0x16f6d
leaq 0x250(%rsp), %rdi
callq 0x9f360
jmp 0x16f7c
leaq 0x136fc5(%rip), %rax    # 0x14df48
movsd (%rax), %xmm0
movsd %xmm0, 0xb8(%rsp)
callq 0xeb5e0
movsd %xmm0, 0xc0(%rsp)
jmp 0x16fa0
movsd 0xc0(%rsp), %xmm1
movsd 0xb8(%rsp), %xmm0
mulsd %xmm1, %xmm0
leaq 0x298(%rsp), %rdi
leaq 0x250(%rsp), %rsi
callq 0x1e1a0
jmp 0x16fcd
leaq 0x220(%rsp), %rdi
leaq 0x580(%rsp), %rsi
callq 0x1e230
jmp 0x16fe4
leaq 0x238(%rsp), %rdi
leaq 0x220(%rsp), %rsi
callq 0x9f0b0
jmp 0x16ffb
leaq 0x298(%rsp), %rdi
leaq 0x238(%rsp), %rsi
callq 0x1e1f0
jmp 0x17012
leaq 0x480(%rsp), %rdi
movsd 0x133016(%rip), %xmm0   # 0x14a038
callq 0xc0c70
jmp 0x17029
leaq 0x17a4f0(%rip), %rax    # 0x191520
movsd (%rax), %xmm0
leaq 0x3b0(%rsp), %rdi
callq 0xc0c70
jmp 0x17043
movl $0x0, 0x21c(%rsp)
movl 0x21c(%rsp), %eax
movl %eax, 0xb4(%rsp)
movq 0x688(%rsp), %rdi
callq 0x1b420
movl %eax, %ecx
movl 0xb4(%rsp), %eax
cmpl %ecx, %eax
jge 0x173b2
movq 0x688(%rsp), %rdi
movl 0x21c(%rsp), %esi
callq 0x1b480
movq %rax, 0xa8(%rsp)
jmp 0x17098
movq 0xa8(%rsp), %rax
movq %rax, 0x210(%rsp)
movq 0x688(%rsp), %rdi
movq 0x210(%rsp), %rsi
xorl %edx, %edx
callq 0x1b870
movq %rax, 0x208(%rsp)
movq 0x688(%rsp), %rdi
movq 0x210(%rsp), %rsi
movl $0x1, %edx
callq 0x1b870
movq %rax, 0x200(%rsp)
movq 0x688(%rsp), %rdi
movq 0x210(%rsp), %rsi
movl $0x2, %edx
callq 0x1b870
movq %rax, 0x1f8(%rsp)
movq 0x688(%rsp), %rdi
movq 0x208(%rsp), %rsi
callq 0x1b740
movq %rax, %rsi
leaq 0x1e0(%rsp), %rdi
callq 0x9cca0
jmp 0x17132
movq 0x688(%rsp), %rdi
movq 0x200(%rsp), %rsi
callq 0x1b740
movq %rax, %rsi
leaq 0x1c8(%rsp), %rdi
callq 0x9cca0
jmp 0x17159
movq 0x688(%rsp), %rdi
movq 0x1f8(%rsp), %rsi
callq 0x1b740
movq %rax, %rsi
leaq 0x1b0(%rsp), %rdi
callq 0x9cca0
jmp 0x17180
leaq 0x1e0(%rsp), %rdi
leaq 0x298(%rsp), %rsi
callq 0x9d8d0
jmp 0x17197
leaq 0x1c8(%rsp), %rdi
leaq 0x298(%rsp), %rsi
callq 0x9d8d0
jmp 0x171ae
leaq 0x1b0(%rsp), %rdi
leaq 0x298(%rsp), %rsi
callq 0x9d8d0
jmp 0x171c5
leaq 0x1e0(%rsp), %rdi
movq %rdi, 0x98(%rsp)
callq 0x1b340
movq 0x98(%rsp), %rdi
movsd %xmm0, 0xa0(%rsp)
callq 0x1b350
movaps %xmm0, %xmm1
movsd 0xa0(%rsp), %xmm0
leaq 0x1a0(%rsp), %rdi
callq 0xda010
jmp 0x1720b
leaq 0x1c8(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x1b340
movq 0x88(%rsp), %rdi
movsd %xmm0, 0x90(%rsp)
callq 0x1b350
movaps %xmm0, %xmm1
movsd 0x90(%rsp), %xmm0
leaq 0x190(%rsp), %rdi
callq 0xda010
jmp 0x17251
leaq 0x1b0(%rsp), %rdi
movq %rdi, 0x78(%rsp)
callq 0x1b340
movq 0x78(%rsp), %rdi
movsd %xmm0, 0x80(%rsp)
callq 0x1b350
movaps %xmm0, %xmm1
movsd 0x80(%rsp), %xmm0
leaq 0x180(%rsp), %rdi
callq 0xda010
jmp 0x17291
cvtsi2sdl 0x21c(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
leaq 0x1e0(%rsp), %rdi
callq 0x1b360
movsd %xmm0, 0x68(%rsp)
leaq 0x1c8(%rsp), %rdi
callq 0x1b360
movsd %xmm0, 0x70(%rsp)
leaq 0x1b0(%rsp), %rdi
callq 0x1b360
movsd 0x60(%rsp), %xmm2
movsd 0x68(%rsp), %xmm3
movsd 0x70(%rsp), %xmm4
movaps %xmm0, %xmm5
leaq 0x480(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
leaq 0x190(%rsp), %rdx
leaq 0x180(%rsp), %rcx
leaq 0x3b0(%rsp), %r8
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x1e270
jmp 0x1731d
jmp 0x1731f
movl 0x21c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x21c(%rsp)
jmp 0x1704e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x668(%rsp)
movl %eax, 0x664(%rsp)
jmp 0x17819
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x668(%rsp)
movl %eax, 0x664(%rsp)
jmp 0x1780c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x668(%rsp)
movl %eax, 0x664(%rsp)
jmp 0x177ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x668(%rsp)
movl %eax, 0x664(%rsp)
jmp 0x177f2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x668(%rsp)
movl %eax, 0x664(%rsp)
jmp 0x1779d
movl $0x0, 0x17c(%rsp)
movl 0x17c(%rsp), %eax
movl %eax, 0x58(%rsp)
leaq 0x3b0(%rsp), %rdi
callq 0x1e360
movl %eax, 0x5c(%rsp)
jmp 0x173db
movl 0x58(%rsp), %eax
movl 0x5c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x1777a
movl $0x0, 0x178(%rsp)
movl 0x178(%rsp), %eax
movl %eax, 0x50(%rsp)
leaq 0x3b0(%rsp), %rdi
callq 0x1e380
movl %eax, 0x54(%rsp)
jmp 0x17414
movl 0x50(%rsp), %eax
movl 0x54(%rsp), %ecx
cmpl %ecx, %eax
jge 0x17762
callq 0xeb5e0
movsd %xmm0, 0x48(%rsp)
jmp 0x17431
movsd 0x48(%rsp), %xmm0
ucomisd 0x598(%rsp), %xmm0
jbe 0x17447
jmp 0x1774c
movl 0x178(%rsp), %esi
movl 0x17c(%rsp), %edx
leaq 0x480(%rsp), %rdi
callq 0x1e3a0
movsd %xmm0, 0x40(%rsp)
jmp 0x1746a
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x170(%rsp)
xorps %xmm0, %xmm0
ucomisd 0x170(%rsp), %xmm0
jbe 0x1748c
jmp 0x1774c
movl 0x178(%rsp), %esi
movl 0x17c(%rsp), %edx
leaq 0x3b0(%rsp), %rdi
callq 0x1e3a0
movsd %xmm0, 0x38(%rsp)
jmp 0x174af
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x168(%rsp)
movsd 0x168(%rsp), %xmm0
leaq 0x17a052(%rip), %rax    # 0x191520
ucomisd (%rax), %xmm0
jne 0x174db
jp 0x174db
jmp 0x1774c
cvtsi2sdl 0x178(%rsp), %xmm0
cvtsi2sdl 0x17c(%rsp), %xmm1
leaq 0x158(%rsp), %rdi
leaq 0x3b0(%rsp), %rsi
callq 0xcac30
jmp 0x17504
leaq 0x158(%rsp), %rdi
callq 0x1e3e0
movsd %xmm0, 0x30(%rsp)
jmp 0x17519
leaq 0x158(%rsp), %rdi
callq 0x1e3f0
movsd %xmm0, 0x28(%rsp)
jmp 0x1752e
movsd 0x28(%rsp), %xmm1
movsd 0x30(%rsp), %xmm0
movsd 0x168(%rsp), %xmm2
leaq 0x140(%rsp), %rdi
callq 0x9cc60
jmp 0x17552
leaq 0x140(%rsp), %rdi
leaq 0x298(%rsp), %rsi
callq 0x9d900
jmp 0x17569
movsd 0x678(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x175b3
movsd 0x678(%rsp), %xmm1
leaq 0x5b0(%rsp), %rdi
leaq 0x140(%rsp), %rsi
xorps %xmm0, %xmm0
callq 0x1bf60
movq %rax, 0x20(%rsp)
jmp 0x175a3
movq 0x20(%rsp), %rax
cmpq $0x0, %rax
je 0x175b3
jmp 0x1774c
movsd 0x132a6d(%rip), %xmm0   # 0x14a028
addsd 0x170(%rsp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x13c(%rsp)
cmpl $0x0, 0x13c(%rsp)
jl 0x175fb
movl 0x13c(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0x688(%rsp), %rdi
callq 0x1b420
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jl 0x17600
jmp 0x1774c
movq 0x688(%rsp), %rdi
movl 0x13c(%rsp), %esi
callq 0x1b480
movq %rax, 0x10(%rsp)
jmp 0x1761b
movq 0x10(%rsp), %rax
movq %rax, 0x130(%rsp)
movq 0x688(%rsp), %rdi
movq 0x130(%rsp), %rsi
callq 0x1b4b0
movq %rax, 0x8(%rsp)
jmp 0x17644
movq 0x8(%rsp), %rsi
leaq 0x118(%rsp), %rdi
callq 0x9de00
jmp 0x17658
leaq 0x100(%rsp), %rdi
leaq 0x118(%rsp), %rsi
callq 0x9de00
jmp 0x1766f
leaq 0x100(%rsp), %rdi
leaq 0x298(%rsp), %rsi
callq 0x9ef20
jmp 0x17686
leaq 0x100(%rsp), %rdi
callq 0x1b390
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x176ad
leaq 0x118(%rsp), %rdi
callq 0x9e5a0
jmp 0x176ab
jmp 0x176ad
movl $0x48, %edi
callq 0xf4d0
movq %rax, (%rsp)
jmp 0x176bd
movq (%rsp), %rdi
leaq 0x140(%rsp), %rsi
leaq 0x118(%rsp), %rdx
callq 0x1b4e0
jmp 0x176d8
movq (%rsp), %rax
movq %rax, 0xf8(%rsp)
movsd 0x678(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x17733
movq 0xf8(%rsp), %rsi
leaq 0x5b0(%rsp), %rdi
callq 0x1c030
jmp 0x1770d
jmp 0x17733
movq (%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x668(%rsp)
movl %eax, 0x664(%rsp)
movl $0x48, %esi
callq 0xf4e0
jmp 0x1779d
movq 0x670(%rsp), %rdi
movq 0xf8(%rsp), %rsi
callq 0x1b540
jmp 0x1774a
jmp 0x1774c
movl 0x178(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x178(%rsp)
jmp 0x173f6
jmp 0x17764
movl 0x17c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x17c(%rsp)
jmp 0x173bd
leaq 0x298(%rsp), %rdi
callq 0x7b560
movl 0x3ac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3ac(%rsp)
jmp 0x16e83
leaq 0x298(%rsp), %rdi
callq 0x7b560
jmp 0x177f2
movq 0x670(%rsp), %rax
movq %rax, 0x690(%rsp)
leaq 0x3b0(%rsp), %rdi
callq 0xbe5e0
leaq 0x480(%rsp), %rdi
callq 0xbe5e0
leaq 0x550(%rsp), %rdi
callq 0x1e400
leaq 0x5b0(%rsp), %rdi
callq 0x1c090
jmp 0x17828
leaq 0x3b0(%rsp), %rdi
callq 0xbe5e0
leaq 0x480(%rsp), %rdi
callq 0xbe5e0
leaq 0x550(%rsp), %rdi
callq 0x1e400
leaq 0x5b0(%rsp), %rdi
callq 0x1c090
jmp 0x17838
movq 0x690(%rsp), %rax
addq $0x698, %rsp            # imm = 0x698
retq
movq 0x668(%rsp), %rdi
callq 0xf8a0
nopw %cs:(%rax,%rax)