// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Mesh.cpp
// Function: gaps::R3Mesh::SplitEdge(gaps::R3MeshEdge*, gaps::R3Point const&, gaps::R3MeshEdge**, gaps::R3MeshEdge**)
R3MeshVertex *R3Mesh::
SplitEdge(R3MeshEdge *edge, const R3Point& point, R3MeshEdge **e0, R3MeshEdge **e1)
{
  // Create vertex at split point
  R3MeshVertex *vertex = CreateVertex(R3zero_point);

  // Get vertices on edge
  R3MeshVertex *v[2];
  v[0] = edge->vertex[0];
  v[1] = edge->vertex[1];

  // Get faces on edge
  R3MeshFace *f[2];
  f[0] = edge->face[0];
  f[1] = edge->face[1];

  // Get other edges and vertex on f[0]
  R3MeshEdge *ef[2][2] = { { NULL, NULL }, { NULL, NULL } };
  R3MeshVertex *vf[2] = { NULL, NULL };
  int m[2] = { 0, 0 };
  int s[2] = { 0, 0 };
  int c[2] = { 0, 0 };
  if (f[0]) {
    ef[0][0] = EdgeAcrossVertex(v[0], edge, f[0]);
    ef[0][1] = EdgeAcrossVertex(v[1], edge, f[0]);
    vf[0] = VertexAcrossEdge(ef[0][1], v[1]);
    assert(vf[0] == VertexAcrossEdge(ef[0][0], v[0]));
    m[0] = FaceMaterial(f[0]);
    s[0] = FaceSegment(f[0]);
    c[0] = FaceCategory(f[0]);
  }
  if (f[1]) {
    ef[1][0] = EdgeAcrossVertex(v[0], edge, f[1]);
    ef[1][1] = EdgeAcrossVertex(v[1], edge, f[1]);
    vf[1] = VertexAcrossEdge(ef[1][1], v[1]);
    assert(vf[1] == VertexAcrossEdge(ef[1][0], v[0]));
    m[1] = FaceMaterial(f[1]);
    s[1] = FaceSegment(f[1]);
    c[1] = FaceCategory(f[1]);
  }

  // Delete the edge and the two adjacent faces
  if (f[0]) DeleteFace(f[0]);
  if (f[1]) DeleteFace(f[1]);
  DeleteEdge(edge);

  // Create two new edges
  R3MeshEdge *e[2];
  e[0] = CreateEdge(v[0], vertex);
  e[1] = CreateEdge(vertex, v[1]);

  // Create two new faces on one side
  if (f[0]) {
    // Create edge splitting f[0]
    R3MeshEdge *es = CreateEdge(vertex, vf[0]);

    // Create new face on v[0] side of split
    assert((vf[0] != v[0]) && (vf[0] != vertex) && (v[0] != vertex));
    assert((ef[0][0] != e[0]) && (ef[0][0] != es) && (e[0] != es));
    R3MeshFace *f00 = CreateFace(vf[0], v[0], vertex, ef[0][0], e[0], es);
    SetFaceMaterial(f00, m[0]);
    SetFaceSegment(f00, s[0]);
    SetFaceCategory(f00, c[0]);

    // Create new face on v[1] side of split
    assert((es != e[1]) && (es != ef[0][1]) && (e[1] != ef[0][1]));
    R3MeshFace *f01 = CreateFace(vf[0], vertex, v[1], es, e[1], ef[0][1]);
    SetFaceMaterial(f01, m[0]);
    SetFaceSegment(f01, s[0]);
    SetFaceCategory(f01, c[0]);
  }

  // Create two new faces on other side
  if (f[1]) {
    // Create edge splitting f[1]
    R3MeshEdge *es = CreateEdge(vertex, vf[1]);
    
    // Create new face on v[1] side of split
    assert((vf[1] != v[1]) && (vf[1] != vertex) && (v[1] != vertex));
    assert((ef[1][1] != e[1]) && (ef[1][1] != es) && (e[1] != es));
    R3MeshFace *f10 = CreateFace(vf[1], v[1], vertex, ef[1][1], e[1], es);
    SetFaceMaterial(f10, m[1]);
    SetFaceSegment(f10, s[1]);
    SetFaceCategory(f10, c[1]);

    // Create new face on v[0] side of split
    assert((es != e[0]) && (es != ef[1][0]) && (e[0] != ef[1][0]));
    R3MeshFace *f11 = CreateFace(vf[1], vertex, v[0], es, e[0], ef[1][0]);
    SetFaceMaterial(f11, m[1]);
    SetFaceSegment(f11, s[1]);
    SetFaceCategory(f11, c[1]);
  }

  // Interpolate vertex properties
  RNScalar d0 = R3Distance(point, VertexPosition(v[0]));
  RNScalar d1 = R3Distance(point, VertexPosition(v[1]));
  RNScalar dsum = d0 + d1;
  if (RNIsPositive(dsum)) {
    d0 /= dsum;  d1 /= dsum;
    SetVertexTextureCoords(vertex, d1*VertexTextureCoords(v[0]) + d0*VertexTextureCoords(v[1])); 
    SetVertexColor(vertex, d1*VertexColor(v[0]) + d0*VertexColor(v[1])); 
  }

  // Set vertex position (also marks things in need of update)
  SetVertexPosition(vertex, point);

  // Return edges
  if (e0) *e0 = e[0];
  if (e1) *e1 = e[1];

  // Return vertex
  return vertex;
}

// Assembly:
subq $0x1d8, %rsp            # imm = 0x1D8
movq %rdi, 0x1d0(%rsp)
movq %rsi, 0x1c8(%rsp)
movq %rdx, 0x1c0(%rsp)
movq %rcx, 0x1b8(%rsp)
movq %r8, 0x1b0(%rsp)
movq 0x1d0(%rsp), %rdi
movq %rdi, 0x58(%rsp)
movq (%rdi), %rax
leaq 0x55c6ea(%rip), %rsi    # 0x5794b0
xorl %ecx, %ecx
movl %ecx, %edx
callq *0x20(%rax)
movq %rax, 0x1a8(%rsp)
movq 0x1c8(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x190(%rsp)
movq 0x1c8(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x198(%rsp)
movq 0x1c8(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x180(%rsp)
movq 0x1c8(%rsp), %rax
movq 0x20(%rax), %rax
movq %rax, 0x188(%rsp)
leaq 0x160(%rsp), %rdi
xorl %esi, %esi
movl $0x20, %edx
callq 0xf280
leaq 0x150(%rsp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0xf280
leaq 0x148(%rsp), %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0xf280
leaq 0x140(%rsp), %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0xf280
leaq 0x138(%rsp), %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0xf280
cmpq $0x0, 0x180(%rsp)
je 0x1cf59
movq 0x58(%rsp), %rdi
movq 0x190(%rsp), %rsi
movq 0x1c8(%rsp), %rdx
movq 0x180(%rsp), %rcx
callq 0x18410
movq 0x58(%rsp), %rdi
movq %rax, 0x160(%rsp)
movq 0x198(%rsp), %rsi
movq 0x1c8(%rsp), %rdx
movq 0x180(%rsp), %rcx
callq 0x18410
movq 0x58(%rsp), %rdi
movq %rax, 0x168(%rsp)
movq 0x168(%rsp), %rsi
movq 0x198(%rsp), %rdx
callq 0x36f50
movq 0x58(%rsp), %rdi
movq %rax, 0x150(%rsp)
movq 0x180(%rsp), %rsi
callq 0x369e0
movq 0x58(%rsp), %rdi
movl %eax, 0x148(%rsp)
movq 0x180(%rsp), %rsi
callq 0x36a20
movq 0x58(%rsp), %rdi
movl %eax, 0x140(%rsp)
movq 0x180(%rsp), %rsi
callq 0x36a60
movl %eax, 0x138(%rsp)
cmpq $0x0, 0x188(%rsp)
je 0x1d029
movq 0x58(%rsp), %rdi
movq 0x190(%rsp), %rsi
movq 0x1c8(%rsp), %rdx
movq 0x188(%rsp), %rcx
callq 0x18410
movq 0x58(%rsp), %rdi
movq %rax, 0x170(%rsp)
movq 0x198(%rsp), %rsi
movq 0x1c8(%rsp), %rdx
movq 0x188(%rsp), %rcx
callq 0x18410
movq 0x58(%rsp), %rdi
movq %rax, 0x178(%rsp)
movq 0x178(%rsp), %rsi
movq 0x198(%rsp), %rdx
callq 0x36f50
movq 0x58(%rsp), %rdi
movq %rax, 0x158(%rsp)
movq 0x188(%rsp), %rsi
callq 0x369e0
movq 0x58(%rsp), %rdi
movl %eax, 0x14c(%rsp)
movq 0x188(%rsp), %rsi
callq 0x36a20
movq 0x58(%rsp), %rdi
movl %eax, 0x144(%rsp)
movq 0x188(%rsp), %rsi
callq 0x36a60
movl %eax, 0x13c(%rsp)
cmpq $0x0, 0x180(%rsp)
je 0x1d047
movq 0x58(%rsp), %rdi
movq 0x180(%rsp), %rsi
movq (%rdi), %rax
callq *0x70(%rax)
cmpq $0x0, 0x188(%rsp)
je 0x1d065
movq 0x58(%rsp), %rdi
movq 0x188(%rsp), %rsi
movq (%rdi), %rax
callq *0x70(%rax)
movq 0x58(%rsp), %rdi
movq 0x1c8(%rsp), %rsi
movq (%rdi), %rax
callq *0x68(%rax)
movq 0x58(%rsp), %rdi
movq 0x190(%rsp), %rsi
movq 0x1a8(%rsp), %rdx
movq (%rdi), %rax
xorl %ecx, %ecx
callq *0x40(%rax)
movq 0x58(%rsp), %rdi
movq %rax, 0x120(%rsp)
movq 0x1a8(%rsp), %rsi
movq 0x198(%rsp), %rdx
movq (%rdi), %rax
xorl %ecx, %ecx
callq *0x40(%rax)
movq %rax, 0x128(%rsp)
cmpq $0x0, 0x180(%rsp)
je 0x1d232
movq 0x58(%rsp), %rdi
movq 0x1a8(%rsp), %rsi
movq 0x150(%rsp), %rdx
movq (%rdi), %rax
xorl %ecx, %ecx
callq *0x40(%rax)
movq 0x58(%rsp), %rdi
movq %rax, 0x118(%rsp)
movq 0x150(%rsp), %rsi
movq 0x190(%rsp), %rdx
movq 0x1a8(%rsp), %rcx
movq 0x160(%rsp), %r8
movq 0x120(%rsp), %r9
movq 0x118(%rsp), %r10
movq (%rdi), %rax
xorl %r11d, %r11d
movq %r10, (%rsp)
movq $0x0, 0x8(%rsp)
callq *0x58(%rax)
movq 0x58(%rsp), %rdi
movq %rax, 0x110(%rsp)
movq 0x110(%rsp), %rsi
movl 0x148(%rsp), %edx
callq 0x369c0
movq 0x58(%rsp), %rdi
movq 0x110(%rsp), %rsi
movl 0x140(%rsp), %edx
callq 0x36a00
movq 0x58(%rsp), %rdi
movq 0x110(%rsp), %rsi
movl 0x138(%rsp), %edx
callq 0x36a40
movq 0x58(%rsp), %rdi
movq 0x150(%rsp), %rsi
movq 0x1a8(%rsp), %rdx
movq 0x198(%rsp), %rcx
movq 0x118(%rsp), %r8
movq 0x128(%rsp), %r9
movq 0x168(%rsp), %r10
movq (%rdi), %rax
xorl %r11d, %r11d
movq %r10, (%rsp)
movq $0x0, 0x8(%rsp)
callq *0x58(%rax)
movq 0x58(%rsp), %rdi
movq %rax, 0x108(%rsp)
movq 0x108(%rsp), %rsi
movl 0x148(%rsp), %edx
callq 0x369c0
movq 0x58(%rsp), %rdi
movq 0x108(%rsp), %rsi
movl 0x140(%rsp), %edx
callq 0x36a00
movq 0x58(%rsp), %rdi
movq 0x108(%rsp), %rsi
movl 0x138(%rsp), %edx
callq 0x36a40
cmpq $0x0, 0x188(%rsp)
je 0x1d3a2
movq 0x58(%rsp), %rdi
movq 0x1a8(%rsp), %rsi
movq 0x158(%rsp), %rdx
movq (%rdi), %rax
xorl %ecx, %ecx
callq *0x40(%rax)
movq 0x58(%rsp), %rdi
movq %rax, 0x100(%rsp)
movq 0x158(%rsp), %rsi
movq 0x198(%rsp), %rdx
movq 0x1a8(%rsp), %rcx
movq 0x178(%rsp), %r8
movq 0x128(%rsp), %r9
movq 0x100(%rsp), %r10
movq (%rdi), %rax
xorl %r11d, %r11d
movq %r10, (%rsp)
movq $0x0, 0x8(%rsp)
callq *0x58(%rax)
movq 0x58(%rsp), %rdi
movq %rax, 0xf8(%rsp)
movq 0xf8(%rsp), %rsi
movl 0x14c(%rsp), %edx
callq 0x369c0
movq 0x58(%rsp), %rdi
movq 0xf8(%rsp), %rsi
movl 0x144(%rsp), %edx
callq 0x36a00
movq 0x58(%rsp), %rdi
movq 0xf8(%rsp), %rsi
movl 0x13c(%rsp), %edx
callq 0x36a40
movq 0x58(%rsp), %rdi
movq 0x158(%rsp), %rsi
movq 0x1a8(%rsp), %rdx
movq 0x190(%rsp), %rcx
movq 0x100(%rsp), %r8
movq 0x120(%rsp), %r9
movq 0x170(%rsp), %r10
movq (%rdi), %rax
xorl %r11d, %r11d
movq %r10, (%rsp)
movq $0x0, 0x8(%rsp)
callq *0x58(%rax)
movq 0x58(%rsp), %rdi
movq %rax, 0xf0(%rsp)
movq 0xf0(%rsp), %rsi
movl 0x14c(%rsp), %edx
callq 0x369c0
movq 0x58(%rsp), %rdi
movq 0xf0(%rsp), %rsi
movl 0x144(%rsp), %edx
callq 0x36a00
movq 0x58(%rsp), %rdi
movq 0xf0(%rsp), %rsi
movl 0x13c(%rsp), %edx
callq 0x36a40
movq 0x58(%rsp), %rdi
movq 0x1c0(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x190(%rsp), %rsi
callq 0x13660
movq 0x48(%rsp), %rdi
movq %rax, %rsi
callq 0x86c40
movq 0x58(%rsp), %rdi
movsd %xmm0, 0xe8(%rsp)
movq 0x1c0(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x198(%rsp), %rsi
callq 0x13660
movq 0x50(%rsp), %rdi
movq %rax, %rsi
callq 0x86c40
movsd %xmm0, 0xe0(%rsp)
movsd 0xe8(%rsp), %xmm0
addsd 0xe0(%rsp), %xmm0
movsd %xmm0, 0xd8(%rsp)
movsd 0xd8(%rsp), %xmm0
leaq 0x15b0a9(%rip), %rax    # 0x1784e0
movsd (%rax), %xmm1
callq 0x36d50
cmpl $0x0, %eax
je 0x1d5d9
movq 0x58(%rsp), %rdi
movsd 0xd8(%rsp), %xmm1
movsd 0xe8(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0xe8(%rsp)
movsd 0xd8(%rsp), %xmm1
movsd 0xe0(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0xe0(%rsp)
movq 0x1a8(%rsp), %rax
movq %rax, 0x28(%rsp)
movsd 0xe0(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movq 0x190(%rsp), %rsi
callq 0x368f0
movsd 0x18(%rsp), %xmm0
movq %rax, %rsi
leaq 0xb8(%rsp), %rdi
callq 0x37910
movq 0x58(%rsp), %rdi
movsd 0xe8(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x198(%rsp), %rsi
callq 0x368f0
movsd 0x20(%rsp), %xmm0
movq %rax, %rsi
leaq 0xa8(%rsp), %rdi
callq 0x37910
leaq 0xc8(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
leaq 0xa8(%rsp), %rdx
callq 0xc3750
movq 0x28(%rsp), %rsi
movq 0x58(%rsp), %rdi
leaq 0xc8(%rsp), %rdx
callq 0x376a0
movq 0x58(%rsp), %rdi
movq 0x1a8(%rsp), %rax
movq %rax, 0x40(%rsp)
movsd 0xe0(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
movq 0x190(%rsp), %rsi
callq 0x368d0
movsd 0x30(%rsp), %xmm0
movq %rax, %rsi
leaq 0x78(%rsp), %rdi
callq 0x37950
movq 0x58(%rsp), %rdi
movsd 0xe8(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movq 0x198(%rsp), %rsi
callq 0x368d0
movsd 0x38(%rsp), %xmm0
movq %rax, %rsi
leaq 0x60(%rsp), %rdi
callq 0x37950
leaq 0x90(%rsp), %rdi
leaq 0x78(%rsp), %rsi
leaq 0x60(%rsp), %rdx
callq 0x37200
movq 0x58(%rsp), %rdi
movq 0x40(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq 0x37670
movq 0x58(%rsp), %rdi
movq 0x1a8(%rsp), %rsi
movq 0x1c0(%rsp), %rdx
callq 0x18060
cmpq $0x0, 0x1b8(%rsp)
je 0x1d611
movq 0x120(%rsp), %rcx
movq 0x1b8(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0x1b0(%rsp)
je 0x1d62f
movq 0x128(%rsp), %rcx
movq 0x1b0(%rsp), %rax
movq %rcx, (%rax)
movq 0x1a8(%rsp), %rax
addq $0x1d8, %rsp            # imm = 0x1D8
retq
nop