// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::VertexGaussCurvature(gaps::R3MeshVertex const*) const
RNScalar R3Mesh::
VertexGaussCurvature(const R3MeshVertex *v) const
{
  // Sum areas and interior angles of adjacent faces
  RNArea area = 0;
  RNAngle angle = 0;
  const R3Point& p = VertexPosition(v);
  for (int i = 0; i < VertexValence(v); i++) {
    R3MeshEdge *e1 = EdgeOnVertex(v, i);
    if (!e1) { angle = 0; area = 0; break; }
    R3MeshVertex *v1 = VertexAcrossEdge(e1, v);
    R3MeshEdge *e2 = EdgeOnVertex(v, e1, RN_CCW);
    if (!e2) { angle = 0; area = 0; break; }
    R3MeshVertex *v2 = VertexAcrossEdge(e2, v);
    R3MeshFace *f = FaceOnVertex(v, e1, RN_CCW);
    if (!f) { angle = 0; area = 0; break; }
    const R3Point& p1 = VertexPosition(v1);
    const R3Point& p2 = VertexPosition(v2);
    angle += R3InteriorAngle(p1 - p, p2 - p);
    area += FaceArea(f);
  }

  // Compute curvature using Gauss-Bonet
  RNScalar curvature = (area > 0) ? 3  * (RN_TWO_PI - angle) / area : 0;

  // Return Gauss curvature
  return curvature;
}

// Assembly:
subq $0xb8, %rsp
movq %rdi, 0xb0(%rsp)
movq %rsi, 0xa8(%rsp)
movq 0xb0(%rsp), %rdi
movq %rdi, 0x10(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0xa0(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x98(%rsp)
movq 0xa8(%rsp), %rsi
callq 0x13660
movq %rax, 0x90(%rsp)
movl $0x0, 0x8c(%rsp)
movq 0x10(%rsp), %rdi
movl 0x8c(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0xa8(%rsp), %rsi
callq 0x36b50
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jge 0x170e5
movq 0x10(%rsp), %rdi
movq 0xa8(%rsp), %rsi
movl 0x8c(%rsp), %edx
callq 0x36ec0
movq %rax, 0x80(%rsp)
cmpq $0x0, 0x80(%rsp)
jne 0x16f70
xorps %xmm0, %xmm0
movsd %xmm0, 0x98(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x170e5
movq 0x10(%rsp), %rdi
movq 0x80(%rsp), %rsi
movq 0xa8(%rsp), %rdx
callq 0x36f50
movq 0x10(%rsp), %rdi
movq %rax, 0x78(%rsp)
movq 0xa8(%rsp), %rsi
movq 0x80(%rsp), %rdx
xorl %ecx, %ecx
callq 0x36fa0
movq %rax, 0x70(%rsp)
cmpq $0x0, 0x70(%rsp)
jne 0x16fd5
xorps %xmm0, %xmm0
movsd %xmm0, 0x98(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x170e5
movq 0x10(%rsp), %rdi
movq 0x70(%rsp), %rsi
movq 0xa8(%rsp), %rdx
callq 0x36f50
movq 0x10(%rsp), %rdi
movq %rax, 0x68(%rsp)
movq 0xa8(%rsp), %rsi
movq 0x80(%rsp), %rdx
xorl %ecx, %ecx
callq 0x37010
movq %rax, 0x60(%rsp)
cmpq $0x0, 0x60(%rsp)
jne 0x17037
xorps %xmm0, %xmm0
movsd %xmm0, 0x98(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x170e5
movq 0x10(%rsp), %rdi
movq 0x78(%rsp), %rsi
callq 0x13660
movq 0x10(%rsp), %rdi
movq %rax, 0x58(%rsp)
movq 0x68(%rsp), %rsi
callq 0x13660
movq %rax, 0x50(%rsp)
movq 0x58(%rsp), %rsi
movq 0x90(%rsp), %rdx
leaq 0x38(%rsp), %rdi
callq 0x6eeb0
movq 0x50(%rsp), %rsi
movq 0x90(%rsp), %rdx
leaq 0x20(%rsp), %rdi
callq 0x6eeb0
leaq 0x38(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x8c230
movq 0x10(%rsp), %rdi
addsd 0x98(%rsp), %xmm0
movsd %xmm0, 0x98(%rsp)
movq 0x60(%rsp), %rsi
callq 0x36aa0
addsd 0xa0(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
jmp 0x16efc
movsd 0xa0(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x17127
leaq 0x11f7fa(%rip), %rax    # 0x1368f8
movsd (%rax), %xmm1
subsd 0x98(%rsp), %xmm1
movsd 0x11c0cd(%rip), %xmm0   # 0x1331e0
mulsd %xmm1, %xmm0
divsd 0xa0(%rsp), %xmm0
movsd %xmm0, (%rsp)
jmp 0x17131
xorps %xmm0, %xmm0
movsd %xmm0, (%rsp)
jmp 0x17131
movsd (%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x18(%rsp), %xmm0
addq $0xb8, %rsp
retq
nopw (%rax,%rax)