// File: tomfunkhouser[P]gaps/apps/mshsegment/mshsegment.cpp
// Function: CreatePoints(gaps::R3Mesh*, gaps::R3Segmentation*)
static int 
CreatePoints(R3Mesh *mesh, R3Segmentation *segmentation)
{
  // Allocate points
  int npoints = mesh->NFaces();
  segmentation->point_buffer = new R3SegmentationPoint [ npoints ];
  if (!segmentation->point_buffer) {
    RNFail("Unable to allocate points\n");
    return 0;
  }

  // Fill points
  for (int i = 0; i < mesh->NFaces(); i++) {
    R3MeshFace *face = mesh->Face(i);
    R3SegmentationPoint *point = &segmentation->point_buffer[i];
    point->position = mesh->FaceCentroid(face);
    point->normal = mesh->FaceNormal(face);
    point->radius1 = 2 * sqrt(mesh->FaceArea(face));
    point->radius2 = point->radius2;
    point->area = mesh->FaceArea(face);
    point->color = RNblack_rgb;
    point->boundary = 0;
    point->data_index = i;
    segmentation->points.Insert(point);

    // Compute face color
    point->color.Reset(0,0,0);
    point->color += mesh->VertexColor(mesh->VertexOnFace(face, 0));
    point->color += mesh->VertexColor(mesh->VertexOnFace(face, 1));
    point->color += mesh->VertexColor(mesh->VertexOnFace(face, 2));
    point->color /= 3;
  }

  // Create kdtree of points
  R3SegmentationPoint tmp; int position_offset = (unsigned char *) &(tmp.position) - (unsigned char *) &tmp;
  segmentation->kdtree = new R3Kdtree<R3SegmentationPoint *>(segmentation->points, position_offset);
  if (!segmentation->kdtree) {
    RNFail("Unable to create kdtree\n");
    return 0;
  }
  
  // Create arrays of neighbor points
  for (int i = 0; i <  mesh->NFaces(); i++) {
    R3MeshFace *face = mesh->Face(i);
    R3SegmentationPoint *point = segmentation->points.Kth(i);
    for (int j = 0; j < 3; j++) {
      // Get neighbor face
      R3MeshFace *neighbor_face = mesh->FaceOnFace(face, j);
      if (!neighbor_face) continue;

      // Get neighbor point
      R3SegmentationPoint *neighbor_point = segmentation->points.Kth(mesh->FaceID(neighbor_face));

      // Check normal angle
      if (max_neighbor_normal_angle > 0) {
        RNScalar dot = point->normal.Dot(neighbor_point->normal);
        RNAngle normal_angle = (dot < 1) ? acos(dot) : 0;
        if (normal_angle > max_neighbor_normal_angle) continue;
      }
      
      // Check color difference
      if (max_neighbor_color_difference > 0) {
        RNLength color_difference = 0;
        color_difference += fabs(point->color.R() - neighbor_point->color.R());
        color_difference += fabs(point->color.R() - neighbor_point->color.R());
        color_difference += fabs(point->color.R() - neighbor_point->color.R());
        if (color_difference > max_neighbor_color_difference) continue;
      }

      // Insert neighbor point
      point->neighbors.Insert(neighbor_point);
    }
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x278, %rsp            # imm = 0x278
movq %rdi, 0x268(%rsp)
movq %rsi, 0x260(%rsp)
movq 0x268(%rsp), %rdi
callq 0x12060
movl %eax, 0x25c(%rsp)
movslq 0x25c(%rsp), %rax
movq %rax, 0xd8(%rsp)
movl $0xe0, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
addq $0x8, %rdi
setb %al
orb %al, %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0xd0(%rsp)
callq 0xd030
movq %rax, %rcx
movq 0xd8(%rsp), %rax
movq %rcx, 0xe0(%rsp)
movq %rax, (%rcx)
addq $0x8, %rcx
movq %rcx, 0xe8(%rsp)
cmpq $0x0, %rax
je 0x117fc
movq 0xe8(%rsp), %rax
movq 0xd8(%rsp), %rcx
imulq $0xe0, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0xc0(%rsp)
movq %rax, 0xc8(%rsp)
movq 0xc8(%rsp), %rdi
movq %rdi, 0xb8(%rsp)
callq 0x134c0
jmp 0x117d9
movq 0xc0(%rsp), %rcx
movq 0xb8(%rsp), %rax
addq $0xe0, %rax
cmpq %rcx, %rax
movq %rax, 0xc8(%rsp)
jne 0x117c2
movq 0xe8(%rsp), %rcx
movq 0x260(%rsp), %rax
movq %rcx, 0x28(%rax)
movq 0x260(%rsp), %rax
cmpq $0x0, 0x28(%rax)
jne 0x118c3
leaq 0x99a8f(%rip), %rdi     # 0xab2b9
movb $0x0, %al
callq 0xa9e70
movl $0x0, 0x274(%rsp)
jmp 0x1201e
movq 0xe8(%rsp), %rcx
movq %rax, %rsi
movq 0xb8(%rsp), %rax
movq %rsi, 0x250(%rsp)
movl %edx, 0x24c(%rsp)
cmpq %rax, %rcx
movq %rax, 0xb0(%rsp)
je 0x118a9
movq 0xb0(%rsp), %rdi
addq $-0xe0, %rdi
movq %rdi, 0xa8(%rsp)
callq 0x121a0
movq 0xe8(%rsp), %rcx
movq 0xa8(%rsp), %rax
cmpq %rcx, %rax
movq %rax, 0xb0(%rsp)
jne 0x11870
movq 0xd0(%rsp), %rsi
movq 0xe0(%rsp), %rdi
callq 0xd750
jmp 0x1202d
movl $0x0, 0x248(%rsp)
movl 0x248(%rsp), %eax
movl %eax, 0xa4(%rsp)
movq 0x268(%rsp), %rdi
callq 0x12060
movl %eax, %ecx
movl 0xa4(%rsp), %eax
cmpl %ecx, %eax
jge 0x11b91
movq 0x268(%rsp), %rdi
movl 0x248(%rsp), %esi
callq 0x12080
movq %rax, 0x240(%rsp)
movq 0x260(%rsp), %rax
movq 0x28(%rax), %rax
movslq 0x248(%rsp), %rcx
imulq $0xe0, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x238(%rsp)
movq 0x268(%rsp), %rsi
movq 0x240(%rsp), %rdx
leaq 0x220(%rsp), %rdi
callq 0x3b9e0
movq 0x238(%rsp), %rdi
addq $0x8, %rdi
leaq 0x220(%rsp), %rsi
callq 0x80b00
movq 0x268(%rsp), %rdi
movq 0x240(%rsp), %rsi
callq 0x121c0
movq %rax, %rsi
movq 0x238(%rsp), %rdi
addq $0x20, %rdi
callq 0x82290
movq 0x268(%rsp), %rdi
movq 0x240(%rsp), %rsi
callq 0x121f0
callq 0xd2f0
movaps %xmm0, %xmm1
movsd 0x99658(%rip), %xmm0    # 0xab018
mulsd %xmm1, %xmm0
movq 0x238(%rsp), %rax
movsd %xmm0, 0x50(%rax)
movq 0x238(%rsp), %rax
movsd 0x58(%rax), %xmm0
movq 0x238(%rsp), %rax
movsd %xmm0, 0x58(%rax)
movq 0x268(%rsp), %rdi
movq 0x240(%rsp), %rsi
callq 0x121f0
movq 0x238(%rsp), %rax
movsd %xmm0, 0x70(%rax)
movq 0x238(%rsp), %rdi
addq $0x78, %rdi
leaq 0xc2a48(%rip), %rsi     # 0xd4468
callq 0xa6590
movq 0x238(%rsp), %rax
movl $0x0, 0xa4(%rax)
movl 0x248(%rsp), %ecx
movq 0x238(%rsp), %rax
movl %ecx, 0xd4(%rax)
movq 0x260(%rsp), %rdi
movq 0x238(%rsp), %rsi
callq 0x12260
movq 0x238(%rsp), %rdi
addq $0x78, %rdi
xorps %xmm2, %xmm2
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x12290
movq 0x268(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0x268(%rsp), %rdi
movq 0x240(%rsp), %rsi
xorl %edx, %edx
callq 0x122f0
movq 0x88(%rsp), %rdi
movq %rax, %rsi
callq 0x122d0
movq %rax, %rsi
movq 0x238(%rsp), %rdi
addq $0x78, %rdi
callq 0xa65d0
movq 0x268(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x268(%rsp), %rdi
movq 0x240(%rsp), %rsi
movl $0x1, %edx
callq 0x122f0
movq 0x90(%rsp), %rdi
movq %rax, %rsi
callq 0x122d0
movq %rax, %rsi
movq 0x238(%rsp), %rdi
addq $0x78, %rdi
callq 0xa65d0
movq 0x268(%rsp), %rax
movq %rax, 0x98(%rsp)
movq 0x268(%rsp), %rdi
movq 0x240(%rsp), %rsi
movl $0x2, %edx
callq 0x122f0
movq 0x98(%rsp), %rdi
movq %rax, %rsi
callq 0x122d0
movq %rax, %rsi
movq 0x238(%rsp), %rdi
addq $0x78, %rdi
callq 0xa65d0
movq 0x238(%rsp), %rdi
addq $0x78, %rdi
movsd 0x9949a(%rip), %xmm0    # 0xab010
callq 0xa6710
movl 0x248(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x248(%rsp)
jmp 0x118ce
leaq 0x140(%rsp), %rdi
callq 0x134c0
movl $0x8, 0x13c(%rsp)
movl $0x60, %edi
callq 0xd3d0
movq %rax, 0x80(%rsp)
jmp 0x11bbd
movq 0x80(%rsp), %rdi
movq 0x260(%rsp), %rsi
movl 0x13c(%rsp), %edx
callq 0x12310
jmp 0x11bdb
movq 0x80(%rsp), %rcx
movq 0x260(%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0x260(%rsp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x11c6d
leaq 0x996cf(%rip), %rdi     # 0xab2d4
xorl %eax, %eax
callq 0xa9e70
jmp 0x11c0e
movl $0x0, 0x274(%rsp)
movl $0x1, 0x138(%rsp)
jmp 0x12000
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x250(%rsp)
movl %eax, 0x24c(%rsp)
jmp 0x1200f
movq 0x80(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x250(%rsp)
movl %eax, 0x24c(%rsp)
movl $0x60, %esi
callq 0xd3e0
jmp 0x1200f
movl $0x0, 0x134(%rsp)
movl 0x134(%rsp), %eax
movl %eax, 0x78(%rsp)
movq 0x268(%rsp), %rdi
callq 0x12060
movl %eax, 0x7c(%rsp)
jmp 0x11c96
movl 0x78(%rsp), %eax
movl 0x7c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x11fea
movq 0x268(%rsp), %rdi
movl 0x134(%rsp), %esi
callq 0x12080
movq %rax, 0x70(%rsp)
jmp 0x11cc1
movq 0x70(%rsp), %rax
movq %rax, 0x128(%rsp)
movq 0x260(%rsp), %rdi
movl 0x134(%rsp), %esi
callq 0x125b0
movq %rax, 0x68(%rsp)
jmp 0x11ce9
movq 0x68(%rsp), %rax
movq %rax, 0x120(%rsp)
movl $0x0, 0x11c(%rsp)
cmpl $0x3, 0x11c(%rsp)
jge 0x11fd2
movq 0x268(%rsp), %rdi
movq 0x128(%rsp), %rsi
movl 0x11c(%rsp), %edx
callq 0x125d0
movq %rax, 0x60(%rsp)
jmp 0x11d32
movq 0x60(%rsp), %rax
movq %rax, 0x110(%rsp)
cmpq $0x0, 0x110(%rsp)
jne 0x11d4f
jmp 0x11fbc
movq 0x260(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x268(%rsp), %rdi
movq 0x110(%rsp), %rsi
callq 0x12610
movl %eax, 0x5c(%rsp)
jmp 0x11d77
movl 0x5c(%rsp), %esi
movq 0x50(%rsp), %rdi
callq 0x125b0
movq %rax, 0x48(%rsp)
jmp 0x11d8c
movq 0x48(%rsp), %rax
movq %rax, 0x108(%rsp)
movsd 0xbff2f(%rip), %xmm0    # 0xd1cd0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x11e3f
movq 0x120(%rsp), %rdi
addq $0x20, %rdi
movq 0x108(%rsp), %rsi
addq $0x20, %rsi
callq 0x81be0
movsd %xmm0, 0x40(%rsp)
jmp 0x11dd3
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x100(%rsp)
movsd 0x9921e(%rip), %xmm0    # 0xab008
ucomisd 0x100(%rsp), %xmm0
jbe 0x11e0b
movsd 0x100(%rsp), %xmm0
callq 0xd390
movsd %xmm0, 0x38(%rsp)
jmp 0x11e16
xorps %xmm0, %xmm0
movsd %xmm0, 0x38(%rsp)
jmp 0x11e16
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0xf8(%rsp)
movsd 0xf8(%rsp), %xmm0
ucomisd 0xbfe9a(%rip), %xmm0    # 0xd1cd0
jbe 0x11e3d
jmp 0x11fbc
jmp 0x11e3f
movsd 0xbfe91(%rip), %xmm0    # 0xd1cd8
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x11f9c
movq $0x0, 0xf0(%rsp)
movq 0x120(%rsp), %rdi
addq $0x78, %rdi
callq 0x12630
movsd %xmm0, 0x30(%rsp)
jmp 0x11e79
movq 0x108(%rsp), %rdi
addq $0x78, %rdi
callq 0x12630
movsd %xmm0, 0x28(%rsp)
jmp 0x11e92
movsd 0x28(%rsp), %xmm0
movsd 0x30(%rsp), %xmm1
subsd %xmm0, %xmm1
movaps 0x99177(%rip), %xmm0    # 0xab020
pand %xmm0, %xmm1
movsd 0xf0(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xf0(%rsp)
movq 0x120(%rsp), %rdi
addq $0x78, %rdi
callq 0x12630
movsd %xmm0, 0x20(%rsp)
jmp 0x11edc
movq 0x108(%rsp), %rdi
addq $0x78, %rdi
callq 0x12630
movsd %xmm0, 0x18(%rsp)
jmp 0x11ef5
movsd 0x18(%rsp), %xmm0
movsd 0x20(%rsp), %xmm1
subsd %xmm0, %xmm1
movaps 0x99114(%rip), %xmm0    # 0xab020
pand %xmm0, %xmm1
movsd 0xf0(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xf0(%rsp)
movq 0x120(%rsp), %rdi
addq $0x78, %rdi
callq 0x12630
movsd %xmm0, 0x10(%rsp)
jmp 0x11f3f
movq 0x108(%rsp), %rdi
addq $0x78, %rdi
callq 0x12630
movsd %xmm0, 0x8(%rsp)
jmp 0x11f58
movsd 0x8(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
subsd %xmm1, %xmm0
movaps 0x990b1(%rip), %xmm1    # 0xab020
pand %xmm1, %xmm0
addsd 0xf0(%rsp), %xmm0
movsd %xmm0, 0xf0(%rsp)
movsd 0xf0(%rsp), %xmm0
ucomisd 0xbfd42(%rip), %xmm0    # 0xd1cd8
jbe 0x11f9a
jmp 0x11fbc
jmp 0x11f9c
movq 0x120(%rsp), %rdi
addq $0xb0, %rdi
movq 0x108(%rsp), %rsi
callq 0x12260
jmp 0x11fba
jmp 0x11fbc
movl 0x11c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x11c(%rsp)
jmp 0x11d01
jmp 0x11fd4
movl 0x134(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x134(%rsp)
jmp 0x11c78
movl $0x1, 0x274(%rsp)
movl $0x1, 0x138(%rsp)
leaq 0x140(%rsp), %rdi
callq 0x121a0
jmp 0x1201e
leaq 0x140(%rsp), %rdi
callq 0x121a0
jmp 0x1202d
movl 0x274(%rsp), %eax
addq $0x278, %rsp            # imm = 0x278
retq
movq 0x250(%rsp), %rdi
callq 0xd690
nopw (%rax,%rax)