// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/GSV/GSVMesh.cpp
// Function: gaps::GSVMesh::ReadPlyFile(gaps::GSVScan*, char const*)
int GSVMesh::
ReadPlyFile(GSVScan *scan, const char *filename)
{
  FILE *fp;
  int i,j;
  PlyFile *ply;
  int nelems;
  PlyProperty **plist;
  char **elist;
  int file_type;
  int nprops;
  int num_elems;
  char *elem_name;
  float version;

  typedef struct PlyVertex {
    float x, y, z;
    int scanline_index;
    int point_index;
    int boundary_type;
  } PlyVertex;

  typedef struct PlyFace {
    unsigned char nverts;
    int *verts;
    int segment;
  } PlyFace;

  // List of property information for a vertex 
  // List of property information for a vertex 
  static PlyProperty vert_props[] = { 
    {(char *) "x", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,x), 0, 0, 0, 0},
    {(char *) "y", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,y), 0, 0, 0, 0},
    {(char *) "z", PLY_FLOAT, PLY_FLOAT, offsetof(PlyVertex,z), 0, 0, 0, 0},
    {(char *) "scanline_index", PLY_INT, PLY_INT, offsetof(PlyVertex,scanline_index), 0, 0, 0, 0},
    {(char *) "point_index", PLY_INT, PLY_INT, offsetof(PlyVertex,point_index), 0, 0, 0, 0},
    {(char *) "boundary_type", PLY_INT, PLY_INT, offsetof(PlyVertex,boundary_type), 0, 0, 0, 0}
  };

  // List of property information for a vertex 
  static PlyProperty face_props[] = { 
    {(char *) "vertex_indices", PLY_INT, PLY_INT, offsetof(PlyFace,verts), 1, PLY_UCHAR, PLY_UCHAR, offsetof(PlyFace,nverts)},
    {(char *) "segment", PLY_INT, PLY_INT, offsetof(PlyFace,segment), 0, 0, 0, 0}
  };

  // Open file 
  fp = fopen(filename, "rb");
  if (!fp) {
    RNFail("Unable to open file: %s", filename);
    return 0;
  }

  // Read PLY header
  ply = ply_read (fp, &nelems, &elist);
  if (!ply) {
    RNFail("Unable to read ply file: %s", filename);
    fclose(fp);
    return 0;
  }
  
  // Get header info
  ply_get_info (ply, &version, &file_type);

  // Read obj infos
  int scan_index = 0;
  int segment_index = 0;
  char run_name[1024];
  int num_obj_infos = 0;
  char **obj_infos = ply_get_obj_info(ply, &num_obj_infos);
  for (int i = 0; i < num_obj_infos; i++) {
    char obj_info[1024];
    strncpy(obj_info, obj_infos[i], 1023);
    char *info_type = strtok(obj_info, " ");
    if (!info_type) continue;
    char *valuep = strtok(NULL, " ");
    if (!strcmp(info_type, "scan_index")) scan_index = atoi(valuep);
    else if (!strcmp(info_type, "segment_index")) segment_index = atoi(valuep);
    else if (!strcmp(info_type, "run_name")) strcpy(run_name, valuep);
  }

  // To silence compiler about unused variables
  if (scan_index == -146) printf("Wow\n");
  if (segment_index == -146) printf("Wow\n");

  // Read all elements
  for (i = 0; i < nelems; i++) {
    // Get the description of the element 
    elem_name = elist[i];
    plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);

    // Check element type
    if (equal_strings ("vertex", elem_name)) {
      // Allocate block of vertices
      gsv_vertex_block = new GSVMeshVertex [num_elems];
      if (!gsv_vertex_block) {
        RNFail("Unable to allocate vertex matrix\n");
        return 0;
      }

      // Resize array of vertices
      vertices.Resize(num_elems);

      // set up for getting vertex elements 
      for (j = 0; j < nprops; j++) {
	if (equal_strings("x", plist[j]->name)) ply_get_property (ply, elem_name, &vert_props[0]);
	else if (equal_strings("y", plist[j]->name)) ply_get_property (ply, elem_name, &vert_props[1]);
	else if (equal_strings("z", plist[j]->name)) ply_get_property (ply, elem_name, &vert_props[2]);
	else if (equal_strings("scanline_index", plist[j]->name)) ply_get_property (ply, elem_name, &vert_props[3]);
	else if (equal_strings("point_index", plist[j]->name)) ply_get_property (ply, elem_name, &vert_props[4]);
	else if (equal_strings("boundary_type", plist[j]->name)) ply_get_property (ply, elem_name, &vert_props[5]);
      }

      // Grab all the vertex elements 
      for (j = 0; j < num_elems; j++) {
        // Read vertex into local struct
        PlyVertex plyvertex;
        plyvertex.scanline_index = -1;
        plyvertex.point_index = -1;
        plyvertex.boundary_type = 0;
        ply_get_element(ply, (void *) &plyvertex);

        // Create mesh vertex
        R3Point position(plyvertex.x, plyvertex.y, plyvertex.z);
        GSVMeshVertex *v = (GSVMeshVertex *) CreateVertex(position, &gsv_vertex_block[j]);
        v->scanline = (scan && (plyvertex.scanline_index >= 0)) ? scan->Scanline(plyvertex.scanline_index) : NULL;
        v->point_index = plyvertex.point_index;
        v->boundary_type = plyvertex.boundary_type;
      }
    }
    else if (equal_strings ("face", elem_name)) {
      // Resize array of faces
      faces.Resize(num_elems);

      // set up for getting face elements 
      for (j = 0; j < nprops; j++) {
	if (equal_strings("vertex_indices", plist[j]->name)) ply_get_property (ply, elem_name, &face_props[0]);
	else if (equal_strings("segment", plist[j]->name)) ply_get_property (ply, elem_name, &face_props[1]);
      }

      // grab all the face elements 
      for (j = 0; j < num_elems; j++) {
        // Read face into local struct
        PlyFace plyface;
        plyface.nverts = 0;
        plyface.verts = NULL;
        plyface.segment = 0;
        ply_get_element(ply, (void *) &plyface);

        // Create mesh face(s)
        R3MeshVertex *v1 = vertices[plyface.verts[0]];
        for (int k = 2; k < plyface.nverts; k++) {
          // Get vertices
          R3MeshVertex *v2 = vertices[plyface.verts[k-1]];
          R3MeshVertex *v3 = vertices[plyface.verts[k]];

          // Check plyface
          assert(plyface.verts[0] >= 0);
          assert(plyface.verts[k-1] >= 0);
          assert(plyface.verts[k] >= 0);
          assert(plyface.verts[0] < vertices.NEntries());
          assert(plyface.verts[k-1] < vertices.NEntries());
          assert(plyface.verts[k] < vertices.NEntries());

          // Check vertices
          if ((v1 == v2) || (v2 == v3) || (v1 == v3)) continue;

          // Create face
          R3MeshFace *f = CreateFace(v1, v2, v3);
          if (!f) {
            // Must have been degeneracy (e.g., three faces sharing an edge), create new vertices
            // Note: these vertices are allocated separately, and so they will not be deleted (memory leak)
            // R3MeshVertex *v1a = CreateVertex(VertexPosition(v1));
            // R3MeshVertex *v2a = CreateVertex(VertexPosition(v2));
            // R3MeshVertex *v3a = CreateVertex(VertexPosition(v3));
            // f = CreateFace(v1a, v2a, v3a);
          } 

          // Set boundary_type
          if (f) SetFaceSegment(f, plyface.segment);
        }

        // Free face data allocated by ply 
        if (plyface.verts) free(plyface.verts);
      }
    }
    else {
      ply_get_other_element (ply, elem_name, num_elems);
    }
  }

  // Close the file 
  ply_close (ply);

  // Return number of faces created
  return faces.NEntries();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x488, %rsp            # imm = 0x488
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
leaq 0x108ba2(%rip), %rsi    # 0x14cbbb
movq %rdx, %rdi
callq 0x27b20
testq %rax, %rax
je 0x445f1
movq %rax, %r12
leaq 0x24(%rsp), %rsi
leaq 0x58(%rsp), %rdx
movq %rax, %rdi
callq 0xd991b
testq %rax, %rax
je 0x44606
movq %rax, %rbp
leaq 0x60(%rsp), %rsi
leaq 0x64(%rsp), %rdx
movq %rax, %rdi
callq 0xdad3c
leaq 0x3c(%rsp), %r14
movl $0x0, (%r14)
movq %rbp, %rdi
movq %r14, %rsi
callq 0xda899
movq %rax, 0x30(%rsp)
cmpl $0x0, (%r14)
movq %rbp, 0x10(%rsp)
jle 0x4416f
xorl %r12d, %r12d
leaq 0x10cae5(%rip), %r14    # 0x150b77
movl $0x0, 0x28(%rsp)
movl $0x0, 0x18(%rsp)
movq 0x30(%rsp), %rax
movq (%rax,%r12,8), %rsi
movl $0x3ff, %edx            # imm = 0x3FF
leaq 0x80(%rsp), %r13
movq %r13, %rdi
callq 0x27450
movq %r13, %rdi
movq %r14, %rsi
callq 0x27f80
testq %rax, %rax
je 0x44117
movq %rax, %rbp
xorl %edi, %edi
movq %r14, %r13
movq %r14, %rsi
callq 0x27f80
movq %rax, %r14
movq %rbp, %rdi
leaq 0x10932a(%rip), %rsi    # 0x14d417
callq 0x27d80
testl %eax, %eax
je 0x4411e
movq %rbp, %rdi
leaq 0x109322(%rip), %rsi    # 0x14d422
callq 0x27d80
testl %eax, %eax
jne 0x4412a
movq %r14, %rdi
callq 0x27f70
movl %eax, 0x18(%rsp)
jmp 0x4412a
movq 0x10(%rsp), %rbp
jmp 0x44132
movq %r14, %rdi
callq 0x27f70
movl %eax, 0x28(%rsp)
movq 0x10(%rsp), %rbp
movq %r13, %r14
incq %r12
movslq 0x3c(%rsp), %rax
cmpq %rax, %r12
jl 0x440a2
cmpl $0xffffff6e, 0x28(%rsp) # imm = 0xFFFFFF6E
jne 0x44159
leaq 0x1095f2(%rip), %rdi    # 0x14d746
callq 0x27f30
cmpl $0xffffff6e, 0x18(%rsp) # imm = 0xFFFFFF6E
jne 0x4416f
leaq 0x1095dc(%rip), %rdi    # 0x14d746
callq 0x27f30
cmpl $0x0, 0x24(%rsp)
jle 0x445e4
leaq 0x8(%rbx), %rcx
leaq 0x28(%rbx), %rax
movq %rax, 0x48(%rsp)
xorl %r14d, %r14d
movq %rcx, 0x30(%rsp)
movq %r15, 0x50(%rsp)
movq 0x58(%rsp), %rax
movq (%rax,%r14,8), %r12
movq %rbp, %rdi
movq %r12, %rsi
leaq 0x8(%rsp), %rdx
leaq 0xc(%rsp), %rcx
callq 0xda13a
movq %rax, %r13
leaq 0x109274(%rip), %rdi    # 0x14d430
movq %r12, %rsi
callq 0xd9ea9
testl %eax, %eax
movq %r14, 0x28(%rsp)
je 0x4426c
movslq 0x8(%rsp), %r14
movq %r14, %rax
movl $0xa8, %ecx
mulq %rcx
movq %rax, %rdi
seto %al
addq $0x8, %rdi
movq $-0x1, %rcx
cmovbq %rcx, %rdi
testb %al, %al
cmovneq %rcx, %rdi
movq %rdi, 0x18(%rsp)
callq 0x27040
leaq 0x8(%rax), %r15
movq %r14, (%rax)
testq %r14, %r14
je 0x443dd
movq %rax, 0x40(%rsp)
imulq $0xa8, %r14, %rbp
xorl %r14d, %r14d
leaq (%r15,%r14), %rdi
callq 0xb31d6
leaq 0x188c3b(%rip), %rax    # 0x1cce70
movq %rax, (%r15,%r14)
movq $0x0, 0x98(%r15,%r14)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, 0xa0(%r15,%r14)
addq $0xa8, %r14
cmpq %r14, %rbp
jne 0x44225
movl 0x8(%rsp), %esi
movq 0x10(%rsp), %rbp
jmp 0x443df
leaq 0x1091c4(%rip), %rdi    # 0x14d437
movq %r12, %rsi
callq 0xd9ea9
movl 0x8(%rsp), %edx
testl %eax, %eax
je 0x445be
movq 0x48(%rsp), %rdi
movl %edx, %esi
callq 0xf8c7a
cmpl $0x0, 0xc(%rsp)
jle 0x442f3
xorl %r14d, %r14d
movq (%r13,%r14,8), %rax
movq (%rax), %rsi
leaq 0x109128(%rip), %rdi    # 0x14d3d4
callq 0xd9ea9
leaq 0x1918f8(%rip), %rdx    # 0x1d5bb0
testl %eax, %eax
jne 0x442db
movq (%r13,%r14,8), %rax
movq (%rax), %rsi
leaq 0x12a272(%rip), %rdi    # 0x16e53d
callq 0xd9ea9
leaq 0x191901(%rip), %rdx    # 0x1d5bd8
testl %eax, %eax
je 0x442e6
movq %rbp, %rdi
movq %r12, %rsi
callq 0xda2d9
incq %r14
movslq 0xc(%rsp), %rax
cmpq %rax, %r14
jl 0x4429d
cmpl $0x0, 0x8(%rsp)
jle 0x445c9
xorl %ebp, %ebp
movb $0x0, 0x80(%rsp)
movq $0x0, 0x88(%rsp)
movl $0x0, 0x90(%rsp)
movq 0x10(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0xda361
movq 0x88(%rsp), %rdi
cmpb $0x3, 0x80(%rsp)
jb 0x443c7
movslq (%rdi), %rax
movq 0x30(%rsp), %r12
movq (%r12), %rcx
movq (%rcx,%rax,8), %r14
movl $0x2, %r13d
movq 0x88(%rsp), %rax
movslq -0x4(%rax,%r13,4), %rdx
movq (%r12), %rcx
movq (%rcx,%rdx,8), %rdx
cmpq %rdx, %r14
je 0x443aa
movslq (%rax,%r13,4), %rax
movq (%rcx,%rax,8), %rcx
cmpq %rcx, %rdx
je 0x443aa
cmpq %rcx, %r14
je 0x443aa
movq (%rbx), %rax
movq %rbx, %rdi
movq %r14, %rsi
xorl %r8d, %r8d
callq *0x48(%rax)
testq %rax, %rax
je 0x443aa
movl 0x90(%rsp), %ecx
movl %ecx, 0x9c(%rax)
incq %r13
movzbl 0x80(%rsp), %eax
cmpq %rax, %r13
jb 0x4435d
movq 0x88(%rsp), %rdi
testq %rdi, %rdi
je 0x443cc
callq 0x27b40
incl %ebp
cmpl 0x8(%rsp), %ebp
jl 0x44300
jmp 0x445c9
xorl %esi, %esi
movq %r15, 0x138(%rbx)
movq 0x30(%rsp), %rdi
callq 0xf8c7a
cmpl $0x0, 0xc(%rsp)
movq 0x50(%rsp), %r15
jle 0x444dd
xorl %r14d, %r14d
movq (%r13,%r14,8), %rax
movq (%rax), %rsi
leaq 0x129490(%rip), %rdi    # 0x16d8a2
callq 0xd9ea9
leaq 0x1916a2(%rip), %rdx    # 0x1d5ac0
testl %eax, %eax
jne 0x444c1
movq (%r13,%r14,8), %rax
movq (%rax), %rsi
leaq 0x10890c(%rip), %rdi    # 0x14cd41
callq 0xd9ea9
leaq 0x1916a7(%rip), %rdx    # 0x1d5ae8
testl %eax, %eax
jne 0x444c1
movq (%r13,%r14,8), %rax
movq (%rax), %rsi
leaq 0x1084a7(%rip), %rdi    # 0x14c8fb
callq 0xd9ea9
leaq 0x1916b0(%rip), %rdx    # 0x1d5b10
testl %eax, %eax
jne 0x444c1
movq (%r13,%r14,8), %rax
movq (%rax), %rsi
leaq 0x108f38(%rip), %rdi    # 0x14d3ab
callq 0xd9ea9
leaq 0x1916b9(%rip), %rdx    # 0x1d5b38
testl %eax, %eax
jne 0x444c1
movq (%r13,%r14,8), %rax
movq (%rax), %rsi
leaq 0x108f28(%rip), %rdi    # 0x14d3ba
callq 0xd9ea9
leaq 0x1916c2(%rip), %rdx    # 0x1d5b60
testl %eax, %eax
jne 0x444c1
movq (%r13,%r14,8), %rax
movq (%rax), %rsi
leaq 0x108f15(%rip), %rdi    # 0x14d3c6
callq 0xd9ea9
leaq 0x1916cb(%rip), %rdx    # 0x1d5b88
testl %eax, %eax
je 0x444cc
movq %rbp, %rdi
movq %r12, %rsi
callq 0xda2d9
incq %r14
movslq 0xc(%rsp), %rax
cmpq %rax, %r14
jl 0x44403
cmpl $0x0, 0x8(%rsp)
jle 0x445c9
xorl %r14d, %r14d
xorl %r13d, %r13d
testq %r15, %r15
setne %bpl
movq $-0x1, 0x8c(%rsp)
movl $0x0, 0x94(%rsp)
movq 0x10(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0xda361
xorps %xmm0, %xmm0
cvtss2sd 0x80(%rsp), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x84(%rsp), %xmm1
xorps %xmm2, %xmm2
cvtss2sd 0x88(%rsp), %xmm2
movq %r15, %r12
leaq 0x68(%rsp), %r15
movq %r15, %rdi
callq 0xd43de
movq 0x138(%rbx), %rdx
addq %r14, %rdx
movq (%rbx), %rax
movq %rbx, %rdi
movq %r15, %rsi
callq *0x20(%rax)
movl 0x8c(%rsp), %ecx
testl %ecx, %ecx
setns %dl
andb %bpl, %dl
cmpb $0x1, %dl
jne 0x44589
movl %ecx, %ecx
movq 0x28(%r12), %rdx
movq (%rdx,%rcx,8), %rcx
jmp 0x4458b
xorl %ecx, %ecx
movq %r12, %r15
movq %rcx, 0x98(%rax)
movq 0x90(%rsp), %rcx
movq %rcx, 0xa0(%rax)
incq %r13
movslq 0x8(%rsp), %rax
addq $0xa8, %r14
cmpq %rax, %r13
jl 0x444ee
jmp 0x445c9
movq %rbp, %rdi
movq %r12, %rsi
callq 0xdaa60
movq 0x28(%rsp), %r14
incq %r14
movslq 0x24(%rsp), %rax
cmpq %rax, %r14
movq 0x10(%rsp), %rbp
jl 0x44194
movq %rbp, %rdi
callq 0xdad27
movl 0x34(%rbx), %ebx
jmp 0x44621
leaq 0x108deb(%rip), %rdi    # 0x14d3e3
xorl %ebx, %ebx
movq %r14, %rsi
xorl %eax, %eax
callq 0xfb6f2
jmp 0x44621
leaq 0x108dee(%rip), %rdi    # 0x14d3fb
xorl %ebx, %ebx
movq %r14, %rsi
xorl %eax, %eax
callq 0xfb6f2
movq %r12, %rdi
callq 0x27920
movl %ebx, %eax
addq $0x488, %rsp            # imm = 0x488
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
testq %r14, %r14
je 0x4465b
movq 0x40(%rsp), %r15
addq $-0xa0, %r15
leaq (%r15,%r14), %rdi
callq 0xb3276
addq $-0xa8, %r14
jne 0x44649
movq 0x40(%rsp), %rdi
movq 0x18(%rsp), %rsi
callq 0x28330
movq %rbx, %rdi
callq 0x28150