// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3TriangleArray.cpp
// Function: gaps::R3TriangleArray::CreateVertexNormals(double)
void R3TriangleArray::
CreateVertexNormals(RNAngle max_angle)
{
  // Create data for computing vertex normals
  R3Vector *normals = new R3Vector [ vertices.NEntries() ];
  RNBoolean *smooth = new RNBoolean [ vertices.NEntries() ];
  for (int i = 0; i < vertices.NEntries(); i++) {
    R3TriangleVertex *vertex = vertices.Kth(i);
    normals[i] = R3zero_vector;
    smooth[i] = TRUE;
    vertex->SetMark(i);
  }

  // Aggregate info for vertex normals
  for (int i = 0; i < triangles.NEntries(); i++) {
    R3Triangle *triangle = triangles.Kth(i);
    RNArea weight = triangle->Area();
    const R3Vector& normal = triangle->Normal();
    for (int j = 0; j < 3; j++) {
      R3TriangleVertex *vertex = triangle->Vertex(j);
      int index = vertex->Mark();
      normals[index] += weight * normal;
    }
  }

  // Normalize vertex normals
  for (int i = 0; i < vertices.NEntries(); i++) {
    normals[i].Normalize();
  }

  // Mark smooth vertices
  RNScalar min_dot = (max_angle < RN_PI) ? cos(max_angle) : -1;
  for (int i = 0; i < triangles.NEntries(); i++) {
    R3Triangle *triangle = triangles.Kth(i);
    const R3Vector& normal = triangle->Normal();
    for (int j = 0; j < 3; j++) {
      R3TriangleVertex *vertex = triangle->Vertex(j);
      int index = vertex->Mark();
      if (normal.Dot(normals[index]) > min_dot) continue;
      smooth[index] = FALSE;
    }
  }
        
  // Update vertex normals
  for (int i = 0; i < vertices.NEntries(); i++) {
    R3TriangleVertex *vertex = vertices.Kth(i);
    if (vertex->HasNormal()) continue;
    if (normals[i].IsZero()) continue;
    if (!smooth[i]) continue;
    vertex->SetNormal(normals[i]);
  }

  // Update triangle flags
  for (int i = 0; i < triangles.NEntries(); i++) {
    R3Triangle *triangle = triangles.Kth(i);
    triangle->UpdateFlags();
  }

  // Delete temporary data
  delete [] normals;
  delete [] smooth;

  // Update
  Update();
}

// Assembly:
subq $0x158, %rsp            # imm = 0x158
movq %rdi, 0x150(%rsp)
movsd %xmm0, 0x148(%rsp)
movq 0x150(%rsp), %rdi
movq %rdi, 0x50(%rsp)
addq $0x8, %rdi
callq 0x13600
cltq
movq %rax, 0x60(%rsp)
movl $0x18, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x58(%rsp)
callq 0xf030
movq %rax, %rcx
movq 0x60(%rsp), %rax
movq %rcx, 0x68(%rsp)
cmpq $0x0, %rax
je 0x98895
movq 0x68(%rsp), %rax
movq 0x60(%rsp), %rcx
imulq $0x18, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x40(%rsp)
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x6fca0
jmp 0x9887d
movq 0x40(%rsp), %rcx
movq 0x38(%rsp), %rax
addq $0x18, %rax
cmpq %rcx, %rax
movq %rax, 0x48(%rsp)
jne 0x9886c
movq 0x50(%rsp), %rdi
movq 0x68(%rsp), %rax
movq %rax, 0x140(%rsp)
addq $0x8, %rdi
callq 0x13600
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq %rax, 0x128(%rsp)
movl $0x0, 0x124(%rsp)
movq 0x50(%rsp), %rdi
movl 0x124(%rsp), %eax
movl %eax, 0x34(%rsp)
addq $0x8, %rdi
callq 0x13600
movl %eax, %ecx
movl 0x34(%rsp), %eax
cmpl %ecx, %eax
jge 0x989b6
movq 0x50(%rsp), %rdi
addq $0x8, %rdi
movl 0x124(%rsp), %esi
callq 0x9a260
movq %rax, 0x118(%rsp)
movq 0x140(%rsp), %rdi
movslq 0x124(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
leaq 0x4e0c58(%rip), %rsi    # 0x5795a0
callq 0x70970
movq 0x128(%rsp), %rax
movslq 0x124(%rsp), %rcx
movl $0x1, (%rax,%rcx,4)
movq 0x118(%rsp), %rdi
movl 0x124(%rsp), %esi
callq 0x9a2f0
movl 0x124(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x124(%rsp)
jmp 0x988e6
movq 0x58(%rsp), %rsi
movq 0x68(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
callq 0xf990
jmp 0x98e39
movl $0x0, 0x114(%rsp)
movq 0x50(%rsp), %rdi
movl 0x114(%rsp), %eax
movl %eax, 0x30(%rsp)
addq $0x18, %rdi
callq 0x13600
movl %eax, %ecx
movl 0x30(%rsp), %eax
cmpl %ecx, %eax
jge 0x98aea
movq 0x50(%rsp), %rdi
addq $0x18, %rdi
movl 0x114(%rsp), %esi
callq 0x9a310
movq %rax, 0x108(%rsp)
movq 0x108(%rsp), %rdi
movq (%rdi), %rax
callq *0x58(%rax)
movsd %xmm0, 0x100(%rsp)
movq 0x108(%rsp), %rdi
callq 0x78960
movq %rax, 0xf8(%rsp)
movl $0x0, 0xf4(%rsp)
cmpl $0x3, 0xf4(%rsp)
jge 0x98ad2
movq 0x108(%rsp), %rdi
movl 0xf4(%rsp), %esi
callq 0x81eb0
movq %rax, 0xe8(%rsp)
movq 0xe8(%rsp), %rdi
callq 0x9a330
movl %eax, 0xe4(%rsp)
movsd 0x100(%rsp), %xmm0
movq 0xf8(%rsp), %rsi
leaq 0xc8(%rsp), %rdi
callq 0x13800
movq 0x140(%rsp), %rdi
movslq 0xe4(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
leaq 0xc8(%rsp), %rsi
callq 0x70be0
movl 0xf4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf4(%rsp)
jmp 0x98a3c
jmp 0x98ad4
movl 0x114(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x114(%rsp)
jmp 0x989c1
movl $0x0, 0xc4(%rsp)
movq 0x50(%rsp), %rdi
movl 0xc4(%rsp), %eax
movl %eax, 0x2c(%rsp)
addq $0x8, %rdi
callq 0x13600
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jge 0x98b47
movq 0x140(%rsp), %rdi
movslq 0xc4(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x70410
movl 0xc4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc4(%rsp)
jmp 0x98af5
movsd 0x148(%rsp), %xmm1
leaq 0x9dd81(%rip), %rax     # 0x1368d8
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x98b77
movsd 0x148(%rsp), %xmm0
callq 0xf930
movsd %xmm0, 0x20(%rsp)
jmp 0x98b87
movsd 0x9a499(%rip), %xmm0    # 0x133018
movsd %xmm0, 0x20(%rsp)
jmp 0x98b87
movsd 0x20(%rsp), %xmm0
movsd %xmm0, 0xb8(%rsp)
movl $0x0, 0xb4(%rsp)
movq 0x50(%rsp), %rdi
movl 0xb4(%rsp), %eax
movl %eax, 0x1c(%rsp)
addq $0x18, %rdi
callq 0x13600
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x98cb9
movq 0x50(%rsp), %rdi
addq $0x18, %rdi
movl 0xb4(%rsp), %esi
callq 0x9a310
movq %rax, 0xa8(%rsp)
movq 0xa8(%rsp), %rdi
callq 0x78960
movq %rax, 0xa0(%rsp)
movl $0x0, 0x9c(%rsp)
cmpl $0x3, 0x9c(%rsp)
jge 0x98ca1
movq 0xa8(%rsp), %rdi
movl 0x9c(%rsp), %esi
callq 0x81eb0
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rdi
callq 0x9a330
movl %eax, 0x8c(%rsp)
movq 0xa0(%rsp), %rdi
movq 0x140(%rsp), %rsi
movslq 0x8c(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
callq 0x702c0
ucomisd 0xb8(%rsp), %xmm0
jbe 0x98c74
jmp 0x98c8b
movq 0x128(%rsp), %rax
movslq 0x8c(%rsp), %rcx
movl $0x0, (%rax,%rcx,4)
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x98c05
jmp 0x98ca3
movl 0xb4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb4(%rsp)
jmp 0x98ba1
movl $0x0, 0x88(%rsp)
movq 0x50(%rsp), %rdi
movl 0x88(%rsp), %eax
movl %eax, 0x18(%rsp)
addq $0x8, %rdi
callq 0x13600
movl %eax, %ecx
movl 0x18(%rsp), %eax
cmpl %ecx, %eax
jge 0x98d91
movq 0x50(%rsp), %rdi
addq $0x8, %rdi
movl 0x88(%rsp), %esi
callq 0x9a260
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rdi
callq 0x78a20
cmpl $0x0, %eax
je 0x98d1c
jmp 0x98d7b
movq 0x140(%rsp), %rdi
movslq 0x88(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x375a0
cmpl $0x0, %eax
je 0x98d3f
jmp 0x98d7b
movq 0x128(%rsp), %rax
movslq 0x88(%rsp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jne 0x98d57
jmp 0x98d7b
movq 0x80(%rsp), %rdi
movq 0x140(%rsp), %rsi
movslq 0x88(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
callq 0x9a4a0
movl 0x88(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x88(%rsp)
jmp 0x98cc4
movl $0x0, 0x7c(%rsp)
movq 0x50(%rsp), %rdi
movl 0x7c(%rsp), %eax
movl %eax, 0x14(%rsp)
addq $0x18, %rdi
callq 0x13600
movl %eax, %ecx
movl 0x14(%rsp), %eax
cmpl %ecx, %eax
jge 0x98deb
movq 0x50(%rsp), %rdi
addq $0x18, %rdi
movl 0x7c(%rsp), %esi
callq 0x9a310
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rdi
movq (%rdi), %rax
callq *0x248(%rax)
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x98d99
movq 0x140(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x98e08
movq 0x8(%rsp), %rdi
callq 0xf670
movq 0x128(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x98e23
movq (%rsp), %rdi
callq 0xf670
movq 0x50(%rsp), %rdi
movq (%rdi), %rax
callq *0x248(%rax)
addq $0x158, %rsp            # imm = 0x158
retq
movq 0x138(%rsp), %rdi
callq 0xf890
nopw %cs:(%rax,%rax)