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

  // Count total value of faces
  RNArea total_value = ComputeFaceSamplingWeights(mesh,
    property, curvature_exponent, curvature_max);
  if (total_value == 0) return points;
  
  // Generate points
  RNSeedRandomScalar();
  for (int i = 0; i < mesh->NFaces(); i++) {
    R3MeshFace *face = mesh->Face(i);

    // Get vertex positions
    R3MeshVertex *v0 = mesh->VertexOnFace(face, 0);
    R3MeshVertex *v1 = mesh->VertexOnFace(face, 1);
    R3MeshVertex *v2 = mesh->VertexOnFace(face, 2);
    const R3Point& p0 = mesh->VertexPosition(v0);
    const R3Point& p1 = mesh->VertexPosition(v1);
    const R3Point& p2 = mesh->VertexPosition(v2);
    const R3Vector& n0 = mesh->VertexNormal(v0);
    const R3Vector& n1 = mesh->VertexNormal(v1);
    const R3Vector& n2 = mesh->VertexNormal(v2);

    // Determine number of points for face 
    RNScalar ideal_face_npoints = npoints * mesh->FaceValue(face) / total_value;
    int face_npoints = (int) ideal_face_npoints;
    RNScalar remainder = ideal_face_npoints - face_npoints;
    if (remainder > RNRandomScalar()) face_npoints++;

    // Generate random points in face
    for (int j = 0; j < face_npoints; j++) {
      RNScalar r1 = sqrt(RNRandomScalar());
      RNScalar r2 = RNRandomScalar();
      RNScalar t0 = (1.0 - r1);
      RNScalar t1 = r1 * (1.0 - r2);
      RNScalar t2 = r1 * r2;
      R3Point position = t0*p0 + t1*p1 + t2*p2;
      R3Vector normal = t0*n0 + t1*n1 + t2*n2; normal.Normalize();
      Point *point = new Point(position, normal);
      points->Insert(point);
    }
  }

  // Return points
  return points;
}

// Assembly:
subq $0x258, %rsp            # imm = 0x258
movq %rdi, 0x248(%rsp)
movq %rsi, 0x240(%rsp)
movl %edx, 0x23c(%rsp)
movl $0x10, %edi
callq 0xf4d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x78(%rsp)
callq 0x1b5a0
jmp 0x14e5a
movq 0x78(%rsp), %rax
movq %rax, 0x230(%rsp)
cmpq $0x0, 0x230(%rsp)
jne 0x14eb9
leaq 0x135796(%rip), %rdi    # 0x14a60f
movb $0x0, %al
callq 0xebe00
movq $0x0, 0x250(%rsp)
jmp 0x153b6
movq 0x78(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x228(%rsp)
movl %eax, 0x224(%rsp)
movl $0x10, %esi
callq 0xf4e0
jmp 0x153c6
movq 0x248(%rsp), %rdi
movq 0x240(%rsp), %rsi
movsd 0x17c71f(%rip), %xmm0   # 0x1915f0
movsd 0x173657(%rip), %xmm1   # 0x188530
callq 0x19410
movsd %xmm0, 0x218(%rsp)
movsd 0x218(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x14f10
jp 0x14f10
movq 0x230(%rsp), %rax
movq %rax, 0x250(%rsp)
jmp 0x153b6
xorps %xmm0, %xmm0
callq 0xeb580
movl $0x0, 0x214(%rsp)
movl 0x214(%rsp), %eax
movl %eax, 0x74(%rsp)
movq 0x248(%rsp), %rdi
callq 0x1b420
movl %eax, %ecx
movl 0x74(%rsp), %eax
cmpl %ecx, %eax
jge 0x153a6
movq 0x248(%rsp), %rdi
movl 0x214(%rsp), %esi
callq 0x1b480
movq %rax, 0x208(%rsp)
movq 0x248(%rsp), %rdi
movq 0x208(%rsp), %rsi
xorl %edx, %edx
callq 0x1b870
movq %rax, 0x200(%rsp)
movq 0x248(%rsp), %rdi
movq 0x208(%rsp), %rsi
movl $0x1, %edx
callq 0x1b870
movq %rax, 0x1f8(%rsp)
movq 0x248(%rsp), %rdi
movq 0x208(%rsp), %rsi
movl $0x2, %edx
callq 0x1b870
movq %rax, 0x1f0(%rsp)
movq 0x248(%rsp), %rdi
movq 0x200(%rsp), %rsi
callq 0x1b740
movq %rax, 0x1e8(%rsp)
movq 0x248(%rsp), %rdi
movq 0x1f8(%rsp), %rsi
callq 0x1b740
movq %rax, 0x1e0(%rsp)
movq 0x248(%rsp), %rdi
movq 0x1f0(%rsp), %rsi
callq 0x1b740
movq %rax, 0x1d8(%rsp)
movq 0x248(%rsp), %rdi
movq 0x200(%rsp), %rsi
callq 0x1b760
movq %rax, 0x1d0(%rsp)
movq 0x248(%rsp), %rdi
movq 0x1f8(%rsp), %rsi
callq 0x1b760
movq %rax, 0x1c8(%rsp)
movq 0x248(%rsp), %rdi
movq 0x1f0(%rsp), %rsi
callq 0x1b760
movq %rax, 0x1c0(%rsp)
cvtsi2sdl 0x23c(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movq 0x248(%rsp), %rdi
movq 0x208(%rsp), %rsi
callq 0x1b890
movaps %xmm0, %xmm1
movsd 0x60(%rsp), %xmm0
mulsd %xmm1, %xmm0
divsd 0x218(%rsp), %xmm0
movsd %xmm0, 0x1b8(%rsp)
cvttsd2si 0x1b8(%rsp), %eax
movl %eax, 0x1b4(%rsp)
movsd 0x1b8(%rsp), %xmm0
cvtsi2sdl 0x1b4(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x1a8(%rsp)
movsd 0x1a8(%rsp), %xmm0
movsd %xmm0, 0x68(%rsp)
callq 0xeb5e0
movaps %xmm0, %xmm1
movsd 0x68(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1511c
movl 0x1b4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1b4(%rsp)
movl $0x0, 0x1a4(%rsp)
movl 0x1a4(%rsp), %eax
cmpl 0x1b4(%rsp), %eax
jge 0x1538e
callq 0xeb5e0
callq 0xf390
movsd %xmm0, 0x198(%rsp)
callq 0xeb5e0
movsd %xmm0, 0x190(%rsp)
movsd 0x198(%rsp), %xmm2
movsd 0x134eb3(%rip), %xmm1   # 0x14a020
movaps %xmm1, %xmm0
subsd %xmm2, %xmm0
movsd %xmm0, 0x188(%rsp)
movsd 0x198(%rsp), %xmm0
movsd 0x190(%rsp), %xmm2
subsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x180(%rsp)
movsd 0x198(%rsp), %xmm0
movsd 0x190(%rsp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x178(%rsp)
movsd 0x188(%rsp), %xmm0
movq 0x1e8(%rsp), %rsi
leaq 0x130(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x1b8b0
movsd 0x180(%rsp), %xmm0
movq 0x1e0(%rsp), %rsi
leaq 0x118(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x1b8b0
movq 0x8(%rsp), %rsi
movq 0x10(%rsp), %rdx
leaq 0x148(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x9db50
movsd 0x178(%rsp), %xmm0
movq 0x1d8(%rsp), %rsi
leaq 0x100(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x1b8b0
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %rdx
leaq 0x160(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x9db50
movsd 0x188(%rsp), %xmm0
movq 0x1d0(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x1b8f0
movsd 0x180(%rsp), %xmm0
movq 0x1c8(%rsp), %rsi
leaq 0xa0(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x1b8f0
movq 0x28(%rsp), %rsi
movq 0x30(%rsp), %rdx
leaq 0xd0(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x9f140
movsd 0x178(%rsp), %xmm0
movq 0x1c0(%rsp), %rsi
leaq 0x88(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x1b8f0
movq 0x38(%rsp), %rsi
movq 0x40(%rsp), %rdx
leaq 0xe8(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x9f140
movq 0x50(%rsp), %rdi
callq 0x9e520
movl $0x48, %edi
callq 0xf4d0
movq 0x48(%rsp), %rsi
movq 0x50(%rsp), %rdx
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x58(%rsp)
callq 0x1b4e0
jmp 0x15331
movq 0x58(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x230(%rsp), %rdi
movq 0x80(%rsp), %rsi
callq 0x1b540
movl 0x1a4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1a4(%rsp)
jmp 0x15127
movq 0x58(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x228(%rsp)
movl %eax, 0x224(%rsp)
movl $0x48, %esi
callq 0xf4e0
jmp 0x153c6
jmp 0x15390
movl 0x214(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x214(%rsp)
jmp 0x14f23
movq 0x230(%rsp), %rax
movq %rax, 0x250(%rsp)
movq 0x250(%rsp), %rax
addq $0x258, %rsp            # imm = 0x258
retq
movq 0x228(%rsp), %rdi
callq 0xf8a0
nopw %cs:(%rax,%rax)