// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::Sharpen(double)
void R3Mesh::
Sharpen(RNScalar factor)
{
  // Allocate buffer for copy of vertex positions
  R3Point *positions = new R3Point [ NVertices() ];
  if (!positions) RNAbort("Unable to allocate vertex positions");
  
  // Iteratively average vertex positions
  for (int iter = 0; iter < factor; iter++) {
    // Copy vertex positions
    for (int i = 0; i < NVertices(); i++) {
      R3MeshVertex *vertex = Vertex(i);
      positions[i] = VertexPosition(vertex);
    }

    // Update vertex positions
    for (int i = 0; i < NVertices(); i++) {
      R3MeshVertex *vertex = Vertex(i);
      RNScalar weight = 1;
      R3Point position = positions[vertex->id];
      RNLength radius = VertexAverageEdgeLength(vertex);
      for (int j = 0; j < VertexValence(vertex); j++) {
        R3MeshEdge *edge = EdgeOnVertex(vertex, j);
        R3MeshVertex *neighbor_vertex = VertexAcrossEdge(edge, vertex);
        const R3Point& neighbor_position = positions[neighbor_vertex->id];
        RNLength length = EdgeLength(edge);
        RNLength sigma = length / radius;
        RNScalar w = exp((length * length) / (-2.0 * sigma * sigma));
        position += w * neighbor_position;
        weight += w;
      }

      // Update vertex position
      R3Point smooth_position = position / weight;
      R3Point sharpen_position = 2 * positions[vertex->id] - smooth_position.Vector();
      SetVertexPosition(vertex, sharpen_position);
    }
  }
  
  // Delete copy of vertex positions
  delete [] positions;
}

// Assembly:
subq $0x178, %rsp            # imm = 0x178
movq %rdi, 0x170(%rsp)
movsd %xmm0, 0x168(%rsp)
movq 0x170(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x135e0
cltq
movq %rax, 0x48(%rsp)
movl $0x18, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x40(%rsp)
callq 0xf030
movq %rax, %rcx
movq 0x48(%rsp), %rax
movq %rcx, 0x50(%rsp)
cmpq $0x0, %rax
je 0x197f1
movq 0x50(%rsp), %rax
movq 0x48(%rsp), %rcx
imulq $0x18, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x28(%rsp)
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x6eb40
jmp 0x197d9
movq 0x28(%rsp), %rcx
movq 0x20(%rsp), %rax
addq $0x18, %rax
cmpq %rcx, %rax
movq %rax, 0x30(%rsp)
jne 0x197c8
movq 0x50(%rsp), %rax
movq %rax, 0x160(%rsp)
cmpq $0x0, 0x160(%rsp)
jne 0x19841
leaq 0x119abe(%rip), %rdi    # 0x1332ce
movb $0x0, %al
callq 0xd4e20
jmp 0x19841
movq 0x40(%rsp), %rsi
movq 0x50(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x158(%rsp)
movl %eax, 0x154(%rsp)
callq 0xf990
jmp 0x19bdf
movl $0x0, 0x150(%rsp)
cvtsi2sdl 0x150(%rsp), %xmm1
movsd 0x168(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x19bba
movl $0x0, 0x14c(%rsp)
movq 0x38(%rsp), %rdi
movl 0x14c(%rsp), %eax
movl %eax, 0x1c(%rsp)
callq 0x135e0
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x198ef
movq 0x38(%rsp), %rdi
movl 0x14c(%rsp), %esi
callq 0x13630
movq 0x38(%rsp), %rdi
movq %rax, 0x140(%rsp)
movq 0x140(%rsp), %rsi
callq 0x13660
movq %rax, %rsi
movq 0x160(%rsp), %rdi
movslq 0x14c(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x6f1e0
movl 0x14c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14c(%rsp)
jmp 0x19873
movl $0x0, 0x13c(%rsp)
movq 0x38(%rsp), %rdi
movl 0x13c(%rsp), %eax
movl %eax, 0x18(%rsp)
callq 0x135e0
movl %eax, %ecx
movl 0x18(%rsp), %eax
cmpl %ecx, %eax
jge 0x19ba2
movq 0x38(%rsp), %rdi
movl 0x13c(%rsp), %esi
callq 0x13630
movq %rax, 0x130(%rsp)
movsd 0x1196ca(%rip), %xmm0   # 0x133008
movsd %xmm0, 0x128(%rsp)
movq 0x160(%rsp), %rsi
movq 0x130(%rsp), %rax
movslq 0x70(%rax), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
leaq 0x110(%rsp), %rdi
callq 0x6eb90
movq 0x38(%rsp), %rdi
movq 0x130(%rsp), %rsi
callq 0x16db0
movsd %xmm0, 0x108(%rsp)
movl $0x0, 0x104(%rsp)
movq 0x38(%rsp), %rdi
movl 0x104(%rsp), %eax
movl %eax, 0x14(%rsp)
movq 0x130(%rsp), %rsi
callq 0x36b50
movl %eax, %ecx
movl 0x14(%rsp), %eax
cmpl %ecx, %eax
jge 0x19afe
movq 0x38(%rsp), %rdi
movq 0x130(%rsp), %rsi
movl 0x104(%rsp), %edx
callq 0x36ec0
movq 0x38(%rsp), %rdi
movq %rax, 0xf8(%rsp)
movq 0xf8(%rsp), %rsi
movq 0x130(%rsp), %rdx
callq 0x36f50
movq 0x38(%rsp), %rdi
movq %rax, 0xf0(%rsp)
movq 0x160(%rsp), %rax
movq 0xf0(%rsp), %rcx
movslq 0x70(%rcx), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0xe8(%rsp)
movq 0xf8(%rsp), %rsi
callq 0x13cc0
movsd %xmm0, 0xe0(%rsp)
movsd 0xe0(%rsp), %xmm0
divsd 0x108(%rsp), %xmm0
movsd %xmm0, 0xd8(%rsp)
movsd 0xe0(%rsp), %xmm0
mulsd 0xe0(%rsp), %xmm0
movsd 0x119792(%rip), %xmm1   # 0x133208
mulsd 0xd8(%rsp), %xmm1
mulsd 0xd8(%rsp), %xmm1
divsd %xmm1, %xmm0
callq 0xf8c0
movsd %xmm0, 0xd0(%rsp)
movsd 0xd0(%rsp), %xmm0
movq 0xe8(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
callq 0x36b10
leaq 0x110(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x6f820
movsd 0xd0(%rsp), %xmm0
addsd 0x128(%rsp), %xmm0
movsd %xmm0, 0x128(%rsp)
movl 0x104(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x104(%rsp)
jmp 0x19995
movsd 0x128(%rsp), %xmm0
leaq 0xa0(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x6fc00
movq 0x160(%rsp), %rsi
movq 0x130(%rsp), %rax
movslq 0x70(%rax), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
leaq 0x70(%rsp), %rdi
movsd 0x1196bc(%rip), %xmm0   # 0x133200
callq 0x36b10
leaq 0x58(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x36d10
leaq 0x88(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x58(%rsp), %rdx
callq 0x6fab0
movq 0x38(%rsp), %rdi
movq 0x130(%rsp), %rsi
leaq 0x88(%rsp), %rdx
callq 0x18060
movl 0x13c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x13c(%rsp)
jmp 0x198fa
jmp 0x19ba4
movl 0x150(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x150(%rsp)
jmp 0x1984c
movq 0x160(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x19bd7
movq 0x8(%rsp), %rdi
callq 0xf670
addq $0x178, %rsp            # imm = 0x178
retq
movq 0x158(%rsp), %rdi
callq 0xf890
nopl (%rax)