// File: tomfunkhouser[P]gaps/apps/scn2scn/scn2scn.cpp
// Function: CountOverlapAreas(gaps::R3SceneNode*, gaps::R3Grid*, gaps::R3Affine const&, double&, double&)
static void
CountOverlapAreas(R3SceneNode *node, R3Grid *grid, const R3Affine& parent_transformation, RNArea& overlap_area, RNArea& total_area)
{
  // Update transformation
  R3Affine transformation = R3identity_affine;
  transformation.Transform(parent_transformation);
  transformation.Transform(node->Transformation());

  // Count overlapping triangle areas in references
  for (int i = 0; i < node->NReferences(); i++) {
    R3SceneReference *reference = node->Reference(i);
    R3Scene *referenced_scene = reference->ReferencedScene();
    CountOverlapAreas(referenced_scene->Root(), grid, transformation, overlap_area, total_area);
  }

  // Count overlapping triangle areas in elements
  for (int i = 0; i < node->NElements(); i++) {
    R3SceneElement *element = node->Element(i);
    for (int j = 0; j < element->NShapes(); j++) {
      R3Shape *shape = element->Shape(j);
      if (shape->ClassID() == R3TriangleArray::CLASS_ID()) {
        R3TriangleArray *triangles = (R3TriangleArray *) shape;
        for (int k = 0; k < triangles->NTriangles(); k++) {
          R3Triangle *triangle = triangles->Triangle(k);
          R3Point centroid = triangle->Centroid();
          centroid.Transform(transformation);
          RNScalar grid_value = grid->WorldValue(centroid);
          RNArea area = triangle->Area();
          if (grid_value > RN_EPSILON) overlap_area += area;
          total_area += area;
        }
      }
    }
  }
  
  // Count overlapping triangle areas in children
  for (int i = 0; i < node->NChildren(); i++) {
    R3SceneNode *child = node->Child(i);
    CountOverlapAreas(child, grid, transformation, overlap_area, total_area);
  }
}

// Assembly:
subq $0x258, %rsp            # imm = 0x258
movq %rdi, 0x250(%rsp)
movq %rsi, 0x248(%rsp)
movq %rdx, 0x240(%rsp)
movq %rcx, 0x238(%rsp)
movq %r8, 0x230(%rsp)
leaq 0x21521a(%rip), %rsi    # 0x23f130
leaq 0x120(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x2a480
movq 0x88(%rsp), %rdi
movq 0x240(%rsp), %rsi
callq 0xc0e40
jmp 0x29f42
movq 0x250(%rsp), %rdi
callq 0x2a530
movq %rax, 0x80(%rsp)
jmp 0x29f59
movq 0x80(%rsp), %rsi
leaq 0x120(%rsp), %rdi
callq 0xc0e40
jmp 0x29f70
movl $0x0, 0x110(%rsp)
movl 0x110(%rsp), %eax
movl %eax, 0x7c(%rsp)
movq 0x250(%rsp), %rdi
callq 0x2ac40
movl %eax, %ecx
movl 0x7c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2a068
movq 0x250(%rsp), %rdi
movl 0x110(%rsp), %esi
callq 0x2ad40
movq %rax, 0x70(%rsp)
jmp 0x29fbc
movq 0x70(%rsp), %rax
movq %rax, 0x108(%rsp)
movq 0x108(%rsp), %rdi
callq 0x2ad70
movq %rax, 0x68(%rsp)
jmp 0x29fdd
movq 0x68(%rsp), %rax
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rdi
callq 0x2a470
movq %rax, 0x60(%rsp)
jmp 0x29ffe
movq 0x60(%rsp), %rdi
movq 0x248(%rsp), %rsi
movq 0x238(%rsp), %rcx
movq 0x230(%rsp), %r8
leaq 0x120(%rsp), %rdx
callq 0x29ee0
jmp 0x2a02a
jmp 0x2a02c
movl 0x110(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x110(%rsp)
jmp 0x29f7b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
leaq 0x120(%rsp), %rdi
callq 0xc0b70
jmp 0x2a38f
movl $0x0, 0xfc(%rsp)
movl 0xfc(%rsp), %eax
movl %eax, 0x5c(%rsp)
movq 0x250(%rsp), %rdi
callq 0x2ac60
movl %eax, %ecx
movl 0x5c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2a2de
movq 0x250(%rsp), %rdi
movl 0xfc(%rsp), %esi
callq 0x2ad80
movq %rax, 0x50(%rsp)
jmp 0x2a0b4
movq 0x50(%rsp), %rax
movq %rax, 0xf0(%rsp)
movl $0x0, 0xec(%rsp)
movl 0xec(%rsp), %eax
movl %eax, 0x48(%rsp)
movq 0xf0(%rsp), %rdi
callq 0x2adb0
movl %eax, 0x4c(%rsp)
jmp 0x2a0ea
movl 0x48(%rsp), %eax
movl 0x4c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x2a2c6
movq 0xf0(%rsp), %rdi
movl 0xec(%rsp), %esi
callq 0x2add0
movq %rax, 0x40(%rsp)
jmp 0x2a115
movq 0x40(%rsp), %rax
movq %rax, 0xe0(%rsp)
movq 0xe0(%rsp), %rdi
movq (%rdi), %rax
movq 0xb8(%rax), %rax
callq *%rax
movl %eax, 0x3c(%rsp)
jmp 0x2a13c
callq 0xab670
movl %eax, 0x38(%rsp)
jmp 0x2a147
movl 0x3c(%rsp), %eax
movl 0x38(%rsp), %ecx
cmpl %ecx, %eax
jne 0x2a2ae
movq 0xe0(%rsp), %rax
movq %rax, 0xd8(%rsp)
movl $0x0, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
movl %eax, 0x30(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x2ae00
movl %eax, 0x34(%rsp)
jmp 0x2a190
movl 0x30(%rsp), %eax
movl 0x34(%rsp), %ecx
cmpl %ecx, %eax
jge 0x2a2ac
movq 0xd8(%rsp), %rdi
movl 0xd4(%rsp), %esi
callq 0x2ae20
movq %rax, 0x28(%rsp)
jmp 0x2a1bb
movq 0x28(%rsp), %rax
movq %rax, 0xc8(%rsp)
movq 0xc8(%rsp), %rsi
movq (%rsi), %rax
movq 0x68(%rax), %rax
leaq 0xb0(%rsp), %rdi
callq *%rax
jmp 0x2a1e3
leaq 0xb0(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0xe31a0
jmp 0x2a1fa
movq 0x248(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x2ae50
movsd %xmm0, 0x20(%rsp)
jmp 0x2a217
movsd 0x20(%rsp), %xmm0
movsd %xmm0, 0xa8(%rsp)
movq 0xc8(%rsp), %rdi
movq (%rdi), %rax
movq 0x58(%rax), %rax
callq *%rax
movsd %xmm0, 0x18(%rsp)
jmp 0x2a23f
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
movsd 0xa8(%rsp), %xmm0
leaq 0x20c7ca(%rip), %rax    # 0x236a28
ucomisd (%rax), %xmm0
jbe 0x2a27d
movsd 0xa0(%rsp), %xmm0
movq 0x238(%rsp), %rax
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movsd 0xa0(%rsp), %xmm0
movq 0x230(%rsp), %rax
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movl 0xd4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd4(%rsp)
jmp 0x2a172
jmp 0x2a2ae
jmp 0x2a2b0
movl 0xec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xec(%rsp)
jmp 0x2a0cc
jmp 0x2a2c8
movl 0xfc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xfc(%rsp)
jmp 0x2a073
movl $0x0, 0x9c(%rsp)
movl 0x9c(%rsp), %eax
movl %eax, 0x14(%rsp)
movq 0x250(%rsp), %rdi
callq 0x2aba0
movl %eax, %ecx
movl 0x14(%rsp), %eax
cmpl %ecx, %eax
jge 0x2a37a
movq 0x250(%rsp), %rdi
movl 0x9c(%rsp), %esi
callq 0x2abc0
movq %rax, 0x8(%rsp)
jmp 0x2a326
movq 0x8(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rdi
movq 0x248(%rsp), %rsi
movq 0x238(%rsp), %rcx
movq 0x230(%rsp), %r8
leaq 0x120(%rsp), %rdx
callq 0x29ee0
jmp 0x2a362
jmp 0x2a364
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x2a2e9
leaq 0x120(%rsp), %rdi
callq 0xc0b70
addq $0x258, %rsp            # imm = 0x258
retq
movq 0x118(%rsp), %rdi
callq 0x24210
nopl (%rax)