// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3MeshCreateGeodesicBeamsForVertex(gaps::R3Mesh const*, gaps::R3MeshVertex const*, double, double, gaps::R3MeshGeodesicBeam*, double*, double*, double*, gaps::RNHeap<gaps::R3MeshGeodesicBeam*>&, gaps::RNArray<gaps::R3MeshGeodesicBeam*>&)
static void
R3MeshCreateGeodesicBeamsForVertex(const R3Mesh *mesh, const R3MeshVertex *source, 
  RNLength max_distance, RNLength distance_to_source, R3MeshGeodesicBeam *parent,
  RNLength *vertex_distances, RNLength *edge_distances, RNLength *face_distances,
  RNHeap<R3MeshGeodesicBeam *>& heap, RNArray<R3MeshGeodesicBeam *>& beams)
{
  // Create beams through edges across faces adjacent to source
  for (int i = 0; i < mesh->VertexValence(source); i++) {
    R3MeshEdge *e = mesh->EdgeOnVertex(source, i);
    R3MeshFace *face = mesh->FaceOnEdge(e, source, RN_CCW);
    if (!face) continue;

    // Get edge across face from  source
    R3MeshEdge *edge = mesh->EdgeAcrossFace(face, source);
    if (!mesh->FaceAcrossEdge(edge, face)) continue;

    // Construct beam coordinate system
    R3MeshVertex *v_ccw = mesh->VertexOnFace(face, edge, RN_CCW);
    R3MeshVertex *v_cw = mesh->VertexOnFace(face, edge, RN_CW);
    R3Vector face_normal = mesh->FaceNormal(face);
    R3Span edge_span(mesh->VertexPosition(v_ccw), mesh->VertexPosition(v_cw));
    R3Vector edge_vector = edge_span.Vector();
    R3Vector edge_normal = face_normal % edge_vector; edge_normal.Normalize();
    R3Triad edge_triad(edge_vector, edge_normal, face_normal);
    R3Point source_position = mesh->VertexPosition(source);
    R3CoordSystem face_cs(source_position, edge_triad);
    R3Affine affine(face_cs.InverseMatrix(), 0);

    // Get edge span in beam coordinate system
    edge_span.Transform(affine);

    // Get lower bound on distance to edge along beam
    RNLength beam_distance = distance_to_source + R3Distance(R3zero_point, edge_span);
    if ((max_distance > 0) && (beam_distance > max_distance)) continue;

    // Check distance to edge
    if (beam_distance >= edge_distances[mesh->EdgeID(edge)]) continue;

    // Check distance to neighbor face
    R3MeshFace *neighbor_face = mesh->FaceAcrossEdge(edge, face);
    if ((neighbor_face) && (beam_distance >= face_distances[mesh->FaceID(neighbor_face)])) continue;

    // Create beam
    R3MeshGeodesicBeam *beam = new R3MeshGeodesicBeam();
    beam->source = source;
    beam->face = face;
    beam->edge = edge;
    beam->affine = affine;
    beam->span = edge_span;
    beam->distance = beam_distance;
    beam->distance_to_source = distance_to_source;
    beam->parent = parent;

    // Add beam to heap
    heap.Push(beam);
    beams.Insert(beam);
  }
}

// Assembly:
subq $0x428, %rsp            # imm = 0x428
movq 0x438(%rsp), %rax
movq 0x430(%rsp), %rax
movq %rdi, 0x420(%rsp)
movq %rsi, 0x418(%rsp)
movsd %xmm0, 0x410(%rsp)
movsd %xmm1, 0x408(%rsp)
movq %rdx, 0x400(%rsp)
movq %rcx, 0x3f8(%rsp)
movq %r8, 0x3f0(%rsp)
movq %r9, 0x3e8(%rsp)
movl $0x0, 0x3e4(%rsp)
movl 0x3e4(%rsp), %eax
movl %eax, 0x9c(%rsp)
movq 0x420(%rsp), %rdi
movq 0x418(%rsp), %rsi
callq 0x36b50
movl %eax, %ecx
movl 0x9c(%rsp), %eax
cmpl %ecx, %eax
jge 0x27726
movq 0x420(%rsp), %rdi
movq 0x418(%rsp), %rsi
movl 0x3e4(%rsp), %edx
callq 0x36ec0
movq %rax, 0x3d8(%rsp)
movq 0x420(%rsp), %rdi
movq 0x3d8(%rsp), %rsi
movq 0x418(%rsp), %rdx
xorl %ecx, %ecx
callq 0x36ef0
movq %rax, 0x3d0(%rsp)
cmpq $0x0, 0x3d0(%rsp)
jne 0x27203
jmp 0x276de
movq 0x420(%rsp), %rdi
movq 0x3d0(%rsp), %rsi
movq 0x418(%rsp), %rdx
callq 0x39c40
movq %rax, 0x3c8(%rsp)
movq 0x420(%rsp), %rdi
movq 0x3c8(%rsp), %rsi
movq 0x3d0(%rsp), %rdx
callq 0x373c0
cmpq $0x0, %rax
jne 0x27250
jmp 0x276de
movq 0x420(%rsp), %rdi
movq 0x3d0(%rsp), %rsi
movq 0x3c8(%rsp), %rdx
xorl %ecx, %ecx
movl %ecx, 0x84(%rsp)
callq 0x37380
movq %rax, 0x3c0(%rsp)
movq 0x420(%rsp), %rdi
movq 0x3d0(%rsp), %rsi
movq 0x3c8(%rsp), %rdx
movl $0x1, %ecx
callq 0x37380
movq %rax, 0x3b8(%rsp)
movq 0x420(%rsp), %rdi
movq 0x3d0(%rsp), %rsi
callq 0x13840
movq %rax, %rsi
leaq 0x3a0(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x6fcf0
movq 0x420(%rsp), %rdi
movq 0x3c0(%rsp), %rsi
callq 0x13660
movq %rax, 0x40(%rsp)
movq 0x420(%rsp), %rdi
movq 0x3b8(%rsp), %rsi
callq 0x13660
movq 0x40(%rsp), %rsi
movq %rax, %rdx
leaq 0x350(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x6d550
movq 0x88(%rsp), %rdi
callq 0x392b0
movq %rax, %rsi
leaq 0x338(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x6fcf0
movq 0x48(%rsp), %rdx
movq 0x58(%rsp), %rsi
leaq 0x320(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x70af0
movq 0x50(%rsp), %rdi
callq 0x70410
movq 0x48(%rsp), %rsi
movq 0x50(%rsp), %rdx
movq 0x58(%rsp), %rcx
leaq 0x2d8(%rsp), %rdi
movq %rdi, 0x68(%rsp)
callq 0x4ec80
movq 0x420(%rsp), %rdi
movq 0x418(%rsp), %rsi
callq 0x13660
movq %rax, %rsi
leaq 0x2c0(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x6eb90
movq 0x60(%rsp), %rsi
movq 0x68(%rsp), %rdx
leaq 0x260(%rsp), %rdi
movq %rdi, 0x70(%rsp)
callq 0x4e4c0
movq 0x70(%rsp), %rsi
leaq 0xd0(%rsp), %rdi
movq %rdi, 0x78(%rsp)
callq 0x4e590
movq 0x78(%rsp), %rsi
movl 0x84(%rsp), %edx
leaq 0x150(%rsp), %rdi
movq %rdi, 0x90(%rsp)
callq 0x4d390
movq 0x88(%rsp), %rdi
movq 0x90(%rsp), %rsi
callq 0x6db30
jmp 0x2741c
movsd 0x408(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
leaq 0x55207e(%rip), %rdi    # 0x5794b0
leaq 0x350(%rsp), %rsi
callq 0x86d80
movsd %xmm0, 0x38(%rsp)
jmp 0x27447
movsd 0x38(%rsp), %xmm1
movsd 0x30(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xb8(%rsp)
movsd 0x410(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x274af
movsd 0xb8(%rsp), %xmm0
ucomisd 0x410(%rsp), %xmm0
jbe 0x274af
movl $0x4, 0xb4(%rsp)
jmp 0x276c0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
jmp 0x27717
movsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x3f0(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x420(%rsp), %rdi
movq 0x3c8(%rsp), %rsi
callq 0x36980
movsd 0x20(%rsp), %xmm0
movl %eax, %ecx
movq 0x28(%rsp), %rax
movslq %ecx, %rcx
ucomisd (%rax,%rcx,8), %xmm0
jb 0x27507
movl $0x4, 0xb4(%rsp)
jmp 0x276c0
movq 0x420(%rsp), %rdi
movq 0x3c8(%rsp), %rsi
movq 0x3d0(%rsp), %rdx
callq 0x373c0
movq %rax, 0xa8(%rsp)
cmpq $0x0, 0xa8(%rsp)
je 0x2758f
movsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x3e8(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x420(%rsp), %rdi
movq 0xa8(%rsp), %rsi
callq 0x369a0
movsd 0x10(%rsp), %xmm0
movl %eax, %ecx
movq 0x18(%rsp), %rax
movslq %ecx, %rcx
ucomisd (%rax,%rcx,8), %xmm0
jb 0x2758f
movl $0x4, 0xb4(%rsp)
jmp 0x276c0
movl $0x190, %edi            # imm = 0x190
callq 0xf4c0
movq %rax, 0x8(%rsp)
jmp 0x275a0
movq 0x8(%rsp), %rdi
xorl %esi, %esi
movl $0x190, %edx            # imm = 0x190
callq 0xf280
movq 0x8(%rsp), %rdi
callq 0x39010
jmp 0x275bd
movq 0x8(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0x418(%rsp), %rcx
movq 0xa0(%rsp), %rax
movq %rcx, (%rax)
movq 0x3d0(%rsp), %rcx
movq 0xa0(%rsp), %rax
movq %rcx, 0x8(%rax)
movq 0x3c8(%rsp), %rcx
movq 0xa0(%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0xa0(%rsp), %rdi
addq $0x18, %rdi
leaq 0x150(%rsp), %rsi
callq 0x392c0
jmp 0x27620
movq 0xa0(%rsp), %rdi
addq $0x128, %rdi            # imm = 0x128
leaq 0x350(%rsp), %rsi
callq 0x39330
jmp 0x2763e
movsd 0xb8(%rsp), %xmm0
movq 0xa0(%rsp), %rax
movsd %xmm0, 0x178(%rax)
movsd 0x408(%rsp), %xmm0
movq 0xa0(%rsp), %rax
movsd %xmm0, 0x180(%rax)
movq 0x400(%rsp), %rcx
movq 0xa0(%rsp), %rax
movq %rcx, 0x188(%rax)
movq 0x430(%rsp), %rdi
movq 0xa0(%rsp), %rsi
callq 0x39380
jmp 0x2769e
movq 0x438(%rsp), %rdi
movq 0xa0(%rsp), %rsi
callq 0x395a0
jmp 0x276b5
movl $0x0, 0xb4(%rsp)
leaq 0x150(%rsp), %rdi
callq 0x4d430
movl 0xb4(%rsp), %eax
testl %eax, %eax
je 0x276dc
jmp 0x276da
jmp 0x276de
jmp 0x276de
movl 0x3e4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3e4(%rsp)
jmp 0x27174
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
movl $0x190, %esi            # imm = 0x190
callq 0xf4d0
leaq 0x150(%rsp), %rdi
callq 0x4d430
jmp 0x2772e
addq $0x428, %rsp            # imm = 0x428
retq
movq 0xc8(%rsp), %rdi
callq 0xf890
nopl (%rax,%rax)