// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3MeshProperty.cpp
// Function: gaps::R3MeshProperty::Blur(double)
void R3MeshProperty::
Blur(RNScalar sigma)
{
  // Blur across mesh

  // Get convenient variables
  if (sigma == 0) return;
  RNScalar radius = 3 * sigma;
  RNScalar denom = -2 * sigma * sigma;

  // Make copy of values
  RNScalar *old_values = new RNScalar [ mesh->NVertices() ];
  for (int i = 0; i < mesh->NVertices(); i++) old_values[i] = values[i];

  // Allocate array of vertices within blur filter
  RNArray<R3MeshVertex *> neighbor_vertices;

  // Blur value at every vertex
  for (int i = 0; i < mesh->NVertices(); i++) {
    R3MeshVertex *vertex = mesh->Vertex(i);
    if (values[i] == RN_UNKNOWN) continue;

    // Compute distances
    RNLength *distances = mesh->DijkstraDistances(vertex, radius, neighbor_vertices);

    // Compute blurred value
    RNScalar total_value = 0;
    RNScalar total_weight = 0;
    for (int j = 0; j < neighbor_vertices.NEntries(); j++) {
      R3MeshVertex *neighbor_vertex = neighbor_vertices.Kth(j);
      int neighbor_id = mesh->VertexID(neighbor_vertex);
      RNScalar value = old_values[neighbor_id];
      if (value == RN_UNKNOWN) continue;
      RNLength distance = distances[neighbor_id];
      if (distance > radius) continue;
      RNScalar weight = exp(distance * distance / denom); 
      total_value += weight * value;
      total_weight += weight;
    }

    // Assign blurred value (normalized by total weight)
    if (total_weight > 0) {
      values[i] = total_value / total_weight;
    }

    // Delete distances
    delete [] distances;
  }

  // Delete copy of values
  delete [] old_values;

  // Reset statistics
  ResetStatistics();
}

// Assembly:
subq $0xf8, %rsp
movq %rdi, 0xf0(%rsp)
movsd %xmm0, 0xe8(%rsp)
movq 0xf0(%rsp), %rax
movq %rax, 0x48(%rsp)
movsd 0xe8(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x6fe2e
jp 0x6fe2e
jmp 0x70210
movq 0x48(%rsp), %rax
movsd 0x126865(%rip), %xmm0   # 0x1966a0
mulsd 0xe8(%rsp), %xmm0
movsd %xmm0, 0xe0(%rsp)
movsd 0x12673b(%rip), %xmm0   # 0x196590
mulsd 0xe8(%rsp), %xmm0
mulsd 0xe8(%rsp), %xmm0
movsd %xmm0, 0xd8(%rsp)
movq (%rax), %rdi
callq 0x2abd0
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x22040
movq %rax, 0xd0(%rsp)
movl $0x0, 0xcc(%rsp)
movq 0x48(%rsp), %rax
movl 0xcc(%rsp), %ecx
movl %ecx, 0x44(%rsp)
movq (%rax), %rdi
callq 0x2abd0
movl %eax, %ecx
movl 0x44(%rsp), %eax
cmpl %ecx, %eax
jge 0x6ff11
movq 0x48(%rsp), %rax
movq 0x410(%rax), %rax
movslq 0xcc(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0xd0(%rsp), %rax
movslq 0xcc(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0xcc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xcc(%rsp)
jmp 0x6feae
leaq 0xb8(%rsp), %rdi
callq 0x712b0
movl $0x0, 0xb4(%rsp)
movq 0x48(%rsp), %rax
movl 0xb4(%rsp), %ecx
movl %ecx, 0x3c(%rsp)
movq (%rax), %rdi
callq 0x2abd0
movl %eax, 0x40(%rsp)
jmp 0x6ff47
movl 0x3c(%rsp), %eax
movl 0x40(%rsp), %ecx
cmpl %ecx, %eax
jge 0x701dc
movq 0x48(%rsp), %rax
movq (%rax), %rdi
movl 0xb4(%rsp), %esi
callq 0x2abf0
movq %rax, 0x30(%rsp)
jmp 0x6ff72
movq 0x48(%rsp), %rax
movq 0x30(%rsp), %rcx
movq %rcx, 0x98(%rsp)
movq 0x410(%rax), %rax
movslq 0xb4(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd 0x126080(%rip), %xmm1   # 0x196020
ucomisd %xmm1, %xmm0
jne 0x6ffd3
jp 0x6ffd3
jmp 0x701c6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa8(%rsp)
movl %eax, 0xa4(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x712e0
jmp 0x70218
movq 0x48(%rsp), %rax
movq (%rax), %rdi
movq 0x98(%rsp), %rsi
movsd 0xe0(%rsp), %xmm0
xorl %eax, %eax
movl %eax, %ecx
leaq 0xb8(%rsp), %rdx
callq 0x9a840
movq %rax, 0x28(%rsp)
jmp 0x70004
movq 0x28(%rsp), %rax
movq %rax, 0x90(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x88(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x80(%rsp)
movl $0x0, 0x7c(%rsp)
movl 0x7c(%rsp), %eax
movl %eax, 0x20(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x2ac70
movl %eax, 0x24(%rsp)
jmp 0x7004c
movl 0x20(%rsp), %eax
movl 0x24(%rsp), %ecx
cmpl %ecx, %eax
jge 0x7016a
movl 0x7c(%rsp), %esi
leaq 0xb8(%rsp), %rdi
callq 0x712c0
movq %rax, 0x18(%rsp)
jmp 0x70074
movq 0x48(%rsp), %rax
movq 0x18(%rsp), %rcx
movq %rcx, 0x70(%rsp)
movq (%rax), %rdi
movq 0x70(%rsp), %rsi
callq 0x2b080
movl %eax, 0x14(%rsp)
jmp 0x70096
movl 0x14(%rsp), %eax
movl %eax, 0x6c(%rsp)
movq 0xd0(%rsp), %rax
movslq 0x6c(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x60(%rsp), %xmm0
movsd 0x125f5c(%rip), %xmm1   # 0x196020
ucomisd %xmm1, %xmm0
jne 0x700d1
jp 0x700d1
jmp 0x7015a
movq 0x90(%rsp), %rax
movslq 0x6c(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x58(%rsp), %xmm0
ucomisd 0xe0(%rsp), %xmm0
jbe 0x700fc
jmp 0x7015a
movsd 0x58(%rsp), %xmm0
mulsd 0x58(%rsp), %xmm0
divsd 0xd8(%rsp), %xmm0
callq 0x232d0
movsd %xmm0, 0x50(%rsp)
movsd 0x50(%rsp), %xmm0
movsd 0x60(%rsp), %xmm2
movsd 0x88(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0x50(%rsp), %xmm0
addsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x80(%rsp)
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x70031
movsd 0x80(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x701a7
movq 0x48(%rsp), %rax
movsd 0x88(%rsp), %xmm0
divsd 0x80(%rsp), %xmm0
movq 0x410(%rax), %rax
movslq 0xb4(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq 0x90(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x701c4
movq 0x8(%rsp), %rdi
callq 0x22d80
jmp 0x701c6
movl 0xb4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb4(%rsp)
jmp 0x6ff29
movq 0xd0(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x701f7
movq (%rsp), %rdi
callq 0x22d80
movq 0x48(%rsp), %rdi
callq 0x6c450
jmp 0x70203
leaq 0xb8(%rsp), %rdi
callq 0x712e0
addq $0xf8, %rsp
retq
movq 0xa8(%rsp), %rdi
callq 0x23270
nopw %cs:(%rax,%rax)