// File: tomfunkhouser[P]gaps/apps/msh2msh/msh2msh.cpp
// Function: main
int main(int argc, char **argv)
{
  // Check number of arguments
  if (!ParseArgs(argc, argv)) exit(1);

  // Read mesh
  R3Mesh *mesh = ReadMesh(input_mesh_name);
  if (!mesh) exit(-1);

  // Merge meshes from list
  if (merge_list_name) {
    if (!MergeList(mesh, merge_list_name)) exit(-1);
  }

  // Rotate so that principal axes are aligned with canonical coordinate frame
  if (rotate_by_pca) {
    R3Point centroid = mesh->Centroid();
    R3Triad triad = mesh->PrincipleAxes(&centroid);
    R3Affine rotation = R3identity_affine;
    rotation.Translate(centroid.Vector());
    rotation.Transform(R3Affine(triad.InverseMatrix()));
    rotation.Translate(-centroid.Vector());
    xform.Transform(rotation);
  }

  // Scale based on mesh area
  if (scale_by_area) {
    RNArea area = mesh->Area();
    if (area > 0) xform.Scale(1 / sqrt(area));
  }

  // Scale based on principal component analysis
  if (scale_by_pca) {
    RNScalar variances[3];
    R3Point centroid = mesh->Centroid();
    mesh->PrincipleAxes(&centroid, variances);
    if (variances[0] > 0) xform.Scale(1.0 / sqrt(variances[0]));
  }

  // Center mesh at origin
  if (translate_by_centroid) {
    // R3Point centroid = R3zero_point;
    // for (int i = 0; i < mesh->NVertices(); i++) {
    //   R3MeshVertex *vertex = mesh->Vertex(i);
    //   centroid += mesh->VertexPosition(vertex);
    // }
    // if (mesh->NVertices() > 0) centroid /= mesh->NVertices();
    R3Point centroid = mesh->Centroid();
    xform.Translate(-centroid.Vector());
  }

  // Normalize translation, rotation, and scale
  if (align_by_pca) {
    xform = mesh->PCANormalizationTransformation();
  }

  // Transform 
  if (!xform.IsIdentity()) {
    mesh->Transform(xform);
  }

  // Delete interior faces
  if (delete_interior_faces) {
    DeleteInteriorFaces(mesh);
  }

  // Remove small components
  if (min_component_area > 0) {
    DeleteSmallConnectedComponents(mesh, min_component_area);
  }

  // Clean 
  if (clean) {
    mesh->DeleteUnusedEdges();
    mesh->DeleteUnusedVertices();
  }

  // Flip every face
  if (flip_faces) {
    for (int i = 0; i < mesh->NFaces(); i++) {
      mesh->FlipFace(mesh->Face(i));
    }
  }

  // Fill holes
  if (fill_holes) {
    mesh->FillHoles();
  }

  // Smooth
  if (smooth_factor > 0) {
    mesh->Smooth(smooth_factor);
  }

  // Subdivide edges that are too long
  if (max_edge_length > 0) {
    mesh->SubdivideLongEdges(max_edge_length);
  }

  // Split edges that are too long
  if (min_edge_length > 0) {
    mesh->CollapseShortEdges(min_edge_length);
  }

  // Swap edges
  if (swap_edges) {
    mesh->SwapEdges();
  }

  // Transfer colors
  if (source_mesh_name) {
    CopyFromSource(mesh, source_mesh_name);
  }
  
  // Write mesh
  if (!WriteMesh(mesh, output_mesh_name)) exit(-1);

  // Write transformation
  if (!xform.IsIdentity() && output_xform_name) {
    if (!WriteMatrix(xform.Matrix(), output_xform_name)) exit(-1);
  }

  // Return success 
  return 0;
}

// Assembly:
subq $0x578, %rsp            # imm = 0x578
movl $0x0, 0x574(%rsp)
movl %edi, 0x570(%rsp)
movq %rsi, 0x568(%rsp)
movl 0x570(%rsp), %edi
movq 0x568(%rsp), %rsi
callq 0x12510
cmpl $0x0, %eax
jne 0x13c64
movl $0x1, %edi
callq 0xf5d0
movq 0x14d08d(%rip), %rdi    # 0x160cf8
callq 0x14240
movq %rax, 0x560(%rsp)
cmpq $0x0, 0x560(%rsp)
jne 0x13c8d
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0xf5d0
cmpq $0x0, 0x14d083(%rip)    # 0x160d18
je 0x13cbc
movq 0x560(%rsp), %rdi
movq 0x14d072(%rip), %rsi    # 0x160d18
callq 0x143a0
cmpl $0x0, %eax
jne 0x13cba
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0xf5d0
jmp 0x13cbc
cmpl $0x0, 0x14d1c5(%rip)    # 0x160e88
je 0x13e47
movq 0x560(%rsp), %rsi
leaq 0x548(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x33820
movq 0x18(%rsp), %rdx
movq 0x560(%rsp), %rsi
xorl %eax, %eax
movl %eax, %ecx
leaq 0x500(%rsp), %rdi
callq 0x34230
leaq 0x14d708(%rip), %rsi    # 0x161410
leaq 0x3f0(%rsp), %rdi
callq 0x16070
movq 0x18(%rsp), %rsi
leaq 0x3d8(%rsp), %rdi
callq 0x16470
jmp 0x13d29
leaq 0x3f0(%rsp), %rdi
leaq 0x3d8(%rsp), %rsi
callq 0x16430
jmp 0x13d40
leaq 0x238(%rsp), %rdi
leaq 0x500(%rsp), %rsi
callq 0x6f1c0
jmp 0x13d57
leaq 0x2b8(%rsp), %rdi
leaq 0x238(%rsp), %rsi
xorl %edx, %edx
callq 0x6d660
jmp 0x13d70
leaq 0x3f0(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
callq 0x6d9d0
jmp 0x13d87
leaq 0x2b8(%rsp), %rdi
callq 0x6d700
leaq 0x208(%rsp), %rdi
leaq 0x548(%rsp), %rsi
callq 0x16470
jmp 0x13dab
leaq 0x220(%rsp), %rdi
leaq 0x208(%rsp), %rsi
callq 0x7a950
jmp 0x13dc2
leaq 0x3f0(%rsp), %rdi
leaq 0x220(%rsp), %rsi
callq 0x16430
jmp 0x13dd9
leaq 0x14cf70(%rip), %rdi    # 0x160d50
leaq 0x3f0(%rsp), %rsi
callq 0x6d9d0
jmp 0x13def
leaq 0x3f0(%rsp), %rdi
callq 0x6d700
jmp 0x13e47
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3d0(%rsp)
movl %eax, 0x3cc(%rsp)
jmp 0x13e35
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3d0(%rsp)
movl %eax, 0x3cc(%rsp)
leaq 0x2b8(%rsp), %rdi
callq 0x6d700
leaq 0x3f0(%rsp), %rdi
callq 0x6d700
jmp 0x14228
cmpl $0x0, 0x14d032(%rip)    # 0x160e80
je 0x13ea3
movq 0x560(%rsp), %rdi
callq 0x33aa0
movsd %xmm0, 0x200(%rsp)
movsd 0x200(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x13ea1
movsd 0x200(%rsp), %xmm0
callq 0xf370
movaps %xmm0, %xmm1
movsd 0x112177(%rip), %xmm0   # 0x126008
divsd %xmm1, %xmm0
leaq 0x14ceb4(%rip), %rdi    # 0x160d50
callq 0x16190
jmp 0x13ea3
cmpl $0x0, 0x14cfda(%rip)    # 0x160e84
je 0x13f23
movq 0x560(%rsp), %rsi
leaq 0x1c8(%rsp), %rdi
callq 0x33820
movq 0x560(%rsp), %rsi
leaq 0x1e0(%rsp), %rcx
leaq 0x180(%rsp), %rdi
leaq 0x1c8(%rsp), %rdx
callq 0x34230
movsd 0x1e0(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x13f21
movsd 0x1e0(%rsp), %xmm0
callq 0xf370
movaps %xmm0, %xmm1
movsd 0x1120f7(%rip), %xmm0   # 0x126008
divsd %xmm1, %xmm0
leaq 0x14ce34(%rip), %rdi    # 0x160d50
callq 0x16190
jmp 0x13f23
cmpl $0x0, 0x14cf66(%rip)    # 0x160e90
je 0x13f7f
movq 0x560(%rsp), %rsi
leaq 0x168(%rsp), %rdi
callq 0x33820
leaq 0x138(%rsp), %rdi
leaq 0x168(%rsp), %rsi
callq 0x16470
leaq 0x150(%rsp), %rdi
leaq 0x138(%rsp), %rsi
callq 0x7a950
leaq 0x14cdde(%rip), %rdi    # 0x160d50
leaq 0x150(%rsp), %rsi
callq 0x16430
cmpl $0x0, 0x14cf06(%rip)    # 0x160e8c
je 0x13fed
movq 0x560(%rsp), %rsi
leaq 0x28(%rsp), %rdi
movq %rdi, 0x10(%rsp)
movl $0x1, %r8d
movl %r8d, %edx
movl %r8d, %ecx
callq 0x34d90
movq 0x10(%rsp), %rsi
leaq 0x14cd99(%rip), %rdi    # 0x160d50
callq 0x16120
jmp 0x13fbe
leaq 0x28(%rsp), %rdi
callq 0x6d700
jmp 0x13fed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3d0(%rsp)
movl %eax, 0x3cc(%rsp)
leaq 0x28(%rsp), %rdi
callq 0x6d700
jmp 0x14228
leaq 0x14cd5c(%rip), %rdi    # 0x160d50
callq 0x6d810
cmpl $0x0, %eax
jne 0x14016
movq 0x560(%rsp), %rdi
movq (%rdi), %rax
leaq 0x14cd40(%rip), %rsi    # 0x160d50
callq *0x118(%rax)
cmpl $0x0, 0x14cd23(%rip)    # 0x160d40
je 0x1402c
movq 0x560(%rsp), %rdi
callq 0x14500
movsd 0x14ce3c(%rip), %xmm0   # 0x160e70
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x14052
movq 0x560(%rsp), %rdi
movsd 0x14ce23(%rip), %xmm0   # 0x160e70
callq 0x150e0
cmpl $0x0, 0x14ccdb(%rip)    # 0x160d34
je 0x1407a
movq 0x560(%rsp), %rdi
movq (%rdi), %rax
callq *0x80(%rax)
movq 0x560(%rsp), %rdi
movq (%rdi), %rax
callq *0x78(%rax)
cmpl $0x0, 0x14ccaf(%rip)    # 0x160d30
je 0x140e6
movl $0x0, 0x24(%rsp)
movl 0x24(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0x560(%rsp), %rdi
callq 0x164b0
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jge 0x140e4
movq 0x560(%rsp), %rax
movq %rax, (%rsp)
movq 0x560(%rsp), %rdi
movl 0x24(%rsp), %esi
callq 0x164d0
movq (%rsp), %rdi
movq %rax, %rsi
movq (%rdi), %rax
callq *0xe0(%rax)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x1408b
jmp 0x140e6
cmpl $0x0, 0x14cc4f(%rip)    # 0x160d3c
je 0x14102
movq 0x560(%rsp), %rdi
xorps %xmm1, %xmm1
movaps %xmm1, %xmm0
callq 0x3ff80
movsd 0x14cc3e(%rip), %xmm0   # 0x160d48
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x1412c
movq 0x560(%rsp), %rdi
movsd 0x14cc25(%rip), %xmm0   # 0x160d48
movq (%rdi), %rax
callq *0xf8(%rax)
movsd 0x14cd34(%rip), %xmm0   # 0x160e68
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x14152
movq 0x560(%rsp), %rdi
movsd 0x14cd1b(%rip), %xmm0   # 0x160e68
callq 0x3d670
movsd 0x14cd06(%rip), %xmm0   # 0x160e60
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x14178
movq 0x560(%rsp), %rdi
movsd 0x14cced(%rip), %xmm0   # 0x160e60
callq 0x3d0f0
cmpl $0x0, 0x14cbb9(%rip)    # 0x160d38
je 0x14196
movq 0x560(%rsp), %rdi
movsd 0x111e87(%rip), %xmm0   # 0x126018
callq 0x3e740
cmpq $0x0, 0x14cb72(%rip)    # 0x160d10
je 0x141b4
movq 0x560(%rsp), %rdi
movq 0x14cb61(%rip), %rsi    # 0x160d10
callq 0x157c0
movq 0x560(%rsp), %rdi
movq 0x14cb3d(%rip), %rsi    # 0x160d00
callq 0x15ea0
cmpl $0x0, %eax
jne 0x141d7
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0xf5d0
leaq 0x14cb72(%rip), %rdi    # 0x160d50
callq 0x6d810
cmpl $0x0, %eax
jne 0x1421e
cmpq $0x0, 0x14cb18(%rip)    # 0x160d08
je 0x1421e
leaq 0x14cb57(%rip), %rdi    # 0x160d50
callq 0x16500
movq %rax, %rdi
movq 0x14cb00(%rip), %rsi    # 0x160d08
callq 0x15f90
cmpl $0x0, %eax
jne 0x1421c
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0xf5d0
jmp 0x1421e
xorl %eax, %eax
addq $0x578, %rsp            # imm = 0x578
retq
movq 0x3d0(%rsp), %rdi
callq 0xf820
nopw %cs:(%rax,%rax)