// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::Smooth(double)
void R3Mesh::
Smooth(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);
      if (radius > 0) {
        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 > 0) ? length / radius : 1;
          RNScalar w = exp((length * length) / (-2.0 * sigma * sigma));
          position += w * neighbor_position;
          weight += w;
        }
      
        // Update vertex position
        R3Point smooth_position = position / weight;
        SetVertexPosition(vertex, smooth_position);
      }
    }
  }
  
  // Delete copy of vertex positions
  delete [] positions;
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x130(%rsp)
movsd %xmm0, 0x128(%rsp)
movq 0x130(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x135e0
cltq
movq %rax, 0x50(%rsp)
movl $0x18, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x48(%rsp)
callq 0xf030
movq %rax, %rcx
movq 0x50(%rsp), %rax
movq %rcx, 0x58(%rsp)
cmpq $0x0, %rax
je 0x19351
movq 0x58(%rsp), %rax
movq 0x50(%rsp), %rcx
imulq $0x18, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x30(%rsp)
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x6eb40
jmp 0x19339
movq 0x30(%rsp), %rcx
movq 0x28(%rsp), %rax
addq $0x18, %rax
cmpq %rcx, %rax
movq %rax, 0x38(%rsp)
jne 0x19328
movq 0x58(%rsp), %rax
movq %rax, 0x120(%rsp)
cmpq $0x0, 0x120(%rsp)
jne 0x193a1
leaq 0x119f5e(%rip), %rdi    # 0x1332ce
movb $0x0, %al
callq 0xd4e20
jmp 0x193a1
movq 0x48(%rsp), %rsi
movq 0x58(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
callq 0xf990
jmp 0x19725
movl $0x0, 0x110(%rsp)
cvtsi2sdl 0x110(%rsp), %xmm1
movsd 0x128(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x19700
movl $0x0, 0x10c(%rsp)
movq 0x40(%rsp), %rdi
movl 0x10c(%rsp), %eax
movl %eax, 0x24(%rsp)
callq 0x135e0
movl %eax, %ecx
movl 0x24(%rsp), %eax
cmpl %ecx, %eax
jge 0x1944f
movq 0x40(%rsp), %rdi
movl 0x10c(%rsp), %esi
callq 0x13630
movq 0x40(%rsp), %rdi
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rsi
callq 0x13660
movq %rax, %rsi
movq 0x120(%rsp), %rdi
movslq 0x10c(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x6f1e0
movl 0x10c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10c(%rsp)
jmp 0x193d3
movl $0x0, 0xfc(%rsp)
movq 0x40(%rsp), %rdi
movl 0xfc(%rsp), %eax
movl %eax, 0x20(%rsp)
callq 0x135e0
movl %eax, %ecx
movl 0x20(%rsp), %eax
cmpl %ecx, %eax
jge 0x196e8
movq 0x40(%rsp), %rdi
movl 0xfc(%rsp), %esi
callq 0x13630
movq %rax, 0xf0(%rsp)
movsd 0x119b6a(%rip), %xmm0   # 0x133008
movsd %xmm0, 0xe8(%rsp)
movq 0x120(%rsp), %rsi
movq 0xf0(%rsp), %rax
movslq 0x70(%rax), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
leaq 0xd0(%rsp), %rdi
callq 0x6eb90
movq 0x40(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x16db0
movsd %xmm0, 0xc8(%rsp)
movsd 0xc8(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x196d0
movl $0x0, 0xc4(%rsp)
movq 0x40(%rsp), %rdi
movl 0xc4(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0xf0(%rsp), %rsi
callq 0x36b50
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x1969e
movq 0x40(%rsp), %rdi
movq 0xf0(%rsp), %rsi
movl 0xc4(%rsp), %edx
callq 0x36ec0
movq 0x40(%rsp), %rdi
movq %rax, 0xb8(%rsp)
movq 0xb8(%rsp), %rsi
movq 0xf0(%rsp), %rdx
callq 0x36f50
movq 0x40(%rsp), %rdi
movq %rax, 0xb0(%rsp)
movq 0x120(%rsp), %rax
movq 0xb0(%rsp), %rcx
movslq 0x70(%rcx), %rcx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0xa8(%rsp)
movq 0xb8(%rsp), %rsi
callq 0x13cc0
movsd %xmm0, 0xa0(%rsp)
movsd 0xa0(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x195e3
movsd 0xa0(%rsp), %xmm0
divsd 0xc8(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
jmp 0x195f3
movsd 0x119a1d(%rip), %xmm0   # 0x133008
movsd %xmm0, 0x10(%rsp)
jmp 0x195f3
movsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x98(%rsp)
movsd 0xa0(%rsp), %xmm0
mulsd 0xa0(%rsp), %xmm0
movsd 0x119bec(%rip), %xmm1   # 0x133208
mulsd 0x98(%rsp), %xmm1
mulsd 0x98(%rsp), %xmm1
divsd %xmm1, %xmm0
callq 0xf8c0
movsd %xmm0, 0x90(%rsp)
movsd 0x90(%rsp), %xmm0
movq 0xa8(%rsp), %rsi
leaq 0x78(%rsp), %rdi
callq 0x36b10
leaq 0xd0(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x6f820
movsd 0x90(%rsp), %xmm0
addsd 0xe8(%rsp), %xmm0
movsd %xmm0, 0xe8(%rsp)
movl 0xc4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc4(%rsp)
jmp 0x1950b
movsd 0xe8(%rsp), %xmm0
leaq 0x60(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x6fc00
movq 0x40(%rsp), %rdi
movq 0xf0(%rsp), %rsi
leaq 0x60(%rsp), %rdx
callq 0x18060
jmp 0x196d2
movl 0xfc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xfc(%rsp)
jmp 0x1945a
jmp 0x196ea
movl 0x110(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x110(%rsp)
jmp 0x193ac
movq 0x120(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x1971d
movq 0x8(%rsp), %rdi
callq 0xf670
addq $0x138, %rsp            # imm = 0x138
retq
movq 0x118(%rsp), %rdi
callq 0xf890
nopw %cs:(%rax,%rax)