// File: /workspace/github_cpp_makefile_star2_O1/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, %r12
movq %rsi, %r15
movq %rdi, %rbx
leaq 0x10a6a2(%rip), %rsi    # 0x14ebab
movq %rdx, %rdi
callq 0x27b30
testq %rax, %rax
je 0x44642
movq %rax, %r13
leaq 0x14(%rsp), %rsi
leaq 0x58(%rsp), %rdx
movq %rax, %rdi
callq 0xdb36d
testq %rax, %rax
je 0x4465a
movq %rax, %rbp
leaq 0x60(%rsp), %rsi
leaq 0x64(%rsp), %rdx
movq %rax, %rdi
callq 0xdc77d
leaq 0x2c(%rsp), %r14
movl $0x0, (%r14)
movq %rbp, 0x30(%rsp)
movq %rbp, %rdi
movq %r14, %rsi
callq 0xdc2f2
movq %rax, 0x8(%rsp)
xorl %r12d, %r12d
cmpl $0x0, (%r14)
jle 0x4467a
movq $0x0, 0x20(%rsp)
leaq 0x10e5bf(%rip), %r14    # 0x152b4a
xorl %r13d, %r13d
movl $0x0, 0x18(%rsp)
movq 0x8(%rsp), %rax
movq (%rax,%r13,8), %rsi
movl $0x3ff, %edx            # imm = 0x3FF
leaq 0x80(%rsp), %r12
movq %r12, %rdi
callq 0x27450
movq %r12, %rdi
movq %r14, %rsi
callq 0x27f90
testq %rax, %rax
je 0x4461b
movq %rax, %r12
xorl %edi, %edi
movq %r14, %rbp
movq %r14, %rsi
callq 0x27f90
movq %rax, %r14
movq %r12, %rdi
leaq 0x10ae06(%rip), %rsi    # 0x14f3e7
callq 0x27d90
testl %eax, %eax
je 0x4460b
movq %r12, %rdi
leaq 0x10adfe(%rip), %rsi    # 0x14f3f2
callq 0x27d90
testl %eax, %eax
jne 0x44618
movq %r14, %rdi
callq 0x27f80
movl %eax, 0x18(%rsp)
jmp 0x44618
movq %r14, %rdi
callq 0x27f80
movq %rax, 0x20(%rsp)
movq %rbp, %r14
incq %r13
movslq 0x2c(%rsp), %rax
cmpq %rax, %r13
jl 0x44596
movl $0xffffff6e, %ecx       # imm = 0xFFFFFF6E
cmpl %ecx, 0x20(%rsp)
sete %al
cmpl %ecx, 0x18(%rsp)
sete %r12b
jmp 0x4467c
leaq 0x10ad6a(%rip), %rdi    # 0x14f3b3
xorl %ebx, %ebx
movq %r12, %rsi
xorl %eax, %eax
callq 0xfd64a
jmp 0x44b0b
leaq 0x10ad6a(%rip), %rdi    # 0x14f3cb
xorl %ebx, %ebx
movq %r12, %rsi
xorl %eax, %eax
callq 0xfd64a
movq %r13, %rdi
callq 0x27920
jmp 0x44b0b
xorl %eax, %eax
testb %al, %al
je 0x4468c
leaq 0x10b08f(%rip), %rdi    # 0x14f716
callq 0x27f40
testb %r12b, %r12b
movq 0x30(%rsp), %r13
je 0x446a2
leaq 0x10b079(%rip), %rdi    # 0x14f716
callq 0x27f40
cmpl $0x0, 0x14(%rsp)
jle 0x44b00
leaq 0x8(%rbx), %rax
movq %rax, 0x18(%rsp)
leaq 0x28(%rbx), %rax
movq %rax, 0x38(%rsp)
xorl %r14d, %r14d
movq %rbx, 0x8(%rsp)
movq %r15, 0x50(%rsp)
movq 0x58(%rsp), %rax
movq (%rax,%r14,8), %rbp
movq %r13, %rdi
movq %rbp, %rsi
movq %rsp, %rdx
leaq 0x4(%rsp), %rcx
callq 0xdbbde
movq %rax, %r12
leaq 0x10ad0e(%rip), %rdi    # 0x14f400
movq %rbp, %rsi
callq 0xdb933
testl %eax, %eax
movq %r14, 0x20(%rsp)
je 0x44977
movslq (%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, 0x48(%rsp)
callq 0x27040
leaq 0x8(%rax), %r13
movq %rax, 0x40(%rsp)
movq %r14, (%rax)
testq %r14, %r14
je 0x44790
imulq $0xa8, %r14, %r15
xorl %r14d, %r14d
leaq (%r14,%r13), %rdi
callq 0xb487c
leaq 0x18a70a(%rip), %rax    # 0x1cee70
movq %rax, (%r13,%r14)
movq $0x0, 0x98(%r13,%r14)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movq %rax, 0xa0(%r13,%r14)
addq $0xa8, %r14
cmpq %r14, %r15
jne 0x44756
movq %r13, 0x138(%rbx)
movl (%rsp), %esi
movq 0x18(%rsp), %rdi
callq 0xfa8c0
cmpl $0x0, 0x4(%rsp)
movq 0x50(%rsp), %r15
movq 0x30(%rsp), %r13
jle 0x44890
xorl %r14d, %r14d
movq (%r12,%r14,8), %rax
movq (%rax), %rsi
leaq 0x12b078(%rip), %rdi    # 0x16f842
callq 0xdb933
leaq 0x1932fa(%rip), %rdx    # 0x1d7ad0
testl %eax, %eax
jne 0x44874
movq (%r12,%r14,8), %rax
movq (%rax), %rsi
leaq 0x10a545(%rip), %rdi    # 0x14ed31
callq 0xdb933
leaq 0x193300(%rip), %rdx    # 0x1d7af8
testl %eax, %eax
jne 0x44874
movq (%r12,%r14,8), %rax
movq (%rax), %rsi
leaq 0x10a0e1(%rip), %rdi    # 0x14e8eb
callq 0xdb933
leaq 0x19330a(%rip), %rdx    # 0x1d7b20
testl %eax, %eax
jne 0x44874
movq (%r12,%r14,8), %rax
movq (%rax), %rsi
leaq 0x10ab53(%rip), %rdi    # 0x14f37b
callq 0xdb933
leaq 0x193314(%rip), %rdx    # 0x1d7b48
testl %eax, %eax
jne 0x44874
movq (%r12,%r14,8), %rax
movq (%rax), %rsi
leaq 0x10ab44(%rip), %rdi    # 0x14f38a
callq 0xdb933
leaq 0x19331e(%rip), %rdx    # 0x1d7b70
testl %eax, %eax
jne 0x44874
movq (%r12,%r14,8), %rax
movq (%rax), %rsi
leaq 0x10ab32(%rip), %rdi    # 0x14f396
callq 0xdb933
leaq 0x193328(%rip), %rdx    # 0x1d7b98
testl %eax, %eax
je 0x4487f
movq %r13, %rdi
movq %rbp, %rsi
callq 0xdbd81
incq %r14
movslq 0x4(%rsp), %rax
cmpq %rax, %r14
jl 0x447bc
cmpl $0x0, (%rsp)
jle 0x44ae5
xorl %r14d, %r14d
xorl %r12d, %r12d
testq %r15, %r15
setne %bpl
movq $-0x1, 0x8c(%rsp)
movl $0x0, 0x94(%rsp)
movq %r13, %rbx
movq %r13, %rdi
leaq 0x80(%rsp), %rsi
callq 0xdbe09
xorps %xmm0, %xmm0
cvtss2sd 0x80(%rsp), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x84(%rsp), %xmm1
xorps %xmm2, %xmm2
cvtss2sd 0x88(%rsp), %xmm2
movq %r15, %r13
leaq 0x68(%rsp), %r15
movq %r15, %rdi
callq 0xd5e2e
movq 0x8(%rsp), %rdi
movq 0x138(%rdi), %rdx
addq %r14, %rdx
movq (%rdi), %rax
movq %r15, %rsi
callq *0x20(%rax)
movl 0x8c(%rsp), %ecx
testl %ecx, %ecx
setns %dl
andb %bpl, %dl
cmpb $0x1, %dl
jne 0x4493d
movl %ecx, %ecx
movq 0x28(%r13), %rdx
movq (%rdx,%rcx,8), %rcx
jmp 0x4493f
xorl %ecx, %ecx
movq %r13, %r15
movq %rcx, 0x98(%rax)
movq 0x90(%rsp), %rcx
movq %rcx, 0xa0(%rax)
incq %r12
movslq (%rsp), %rax
addq $0xa8, %r14
cmpq %rax, %r12
movq %rbx, %r13
jl 0x448a0
jmp 0x44ae5
leaq 0x10aa89(%rip), %rdi    # 0x14f407
movq %rbp, %rsi
callq 0xdb933
movl (%rsp), %edx
testl %eax, %eax
je 0x44ada
movq 0x38(%rsp), %rdi
movl %edx, %esi
callq 0xfa8c0
cmpl $0x0, 0x4(%rsp)
jle 0x449fb
xorl %r14d, %r14d
movq (%r12,%r14,8), %rax
movq (%rax), %rsi
leaq 0x10a9ef(%rip), %rdi    # 0x14f3a4
callq 0xdb933
leaq 0x1931ff(%rip), %rdx    # 0x1d7bc0
testl %eax, %eax
jne 0x449e3
movq (%r12,%r14,8), %rax
movq (%rax), %rsi
leaq 0x12bb0a(%rip), %rdi    # 0x1704dd
callq 0xdb933
leaq 0x193209(%rip), %rdx    # 0x1d7be8
testl %eax, %eax
je 0x449ee
movq %r13, %rdi
movq %rbp, %rsi
callq 0xdbd81
incq %r14
movslq 0x4(%rsp), %rax
cmpq %rax, %r14
jl 0x449a7
cmpl $0x0, (%rsp)
jle 0x44ae5
xorl %ebp, %ebp
movb $0x0, 0x80(%rsp)
movq $0x0, 0x88(%rsp)
movl $0x0, 0x90(%rsp)
movq %r13, %rdi
leaq 0x80(%rsp), %rsi
callq 0xdbe09
cmpb $0x3, 0x80(%rsp)
movq 0x8(%rsp), %rbx
jb 0x44abb
movq 0x88(%rsp), %rax
movslq (%rax), %rax
movq 0x8(%rbx), %rcx
movq (%rcx,%rax,8), %r12
movl $0x2, %r14d
movq 0x88(%rsp), %rax
movslq -0x4(%rax,%r14,4), %rdx
movq 0x8(%rbx), %rcx
movq (%rcx,%rdx,8), %rdx
cmpq %rdx, %r12
je 0x44aab
movslq (%rax,%r14,4), %rax
movq (%rcx,%rax,8), %rcx
cmpq %rcx, %rdx
je 0x44aab
cmpq %rcx, %r12
je 0x44aab
movq (%rbx), %rax
movq %rbx, %rdi
movq %r12, %rsi
xorl %r8d, %r8d
callq *0x48(%rax)
testq %rax, %rax
je 0x44aab
movl 0x90(%rsp), %ecx
movl %ecx, 0x9c(%rax)
incq %r14
movzbl 0x80(%rsp), %eax
cmpq %rax, %r14
jb 0x44a5e
movq 0x88(%rsp), %rdi
testq %rdi, %rdi
je 0x44acd
callq 0x27b50
incl %ebp
cmpl (%rsp), %ebp
jl 0x44a07
jmp 0x44ae5
movq %r13, %rdi
movq %rbp, %rsi
callq 0xdc4ae
movq 0x20(%rsp), %r14
incq %r14
movslq 0x14(%rsp), %rax
cmpq %rax, %r14
movq 0x8(%rsp), %rbx
jl 0x446cc
movq %r13, %rdi
callq 0xdc768
movl 0x34(%rbx), %ebx
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
movq 0x40(%rsp), %r12
je 0x44b48
movq %r12, %r15
addq $-0xa0, %r15
leaq (%r15,%r14), %rdi
callq 0xb491c
addq $-0xa8, %r14
jne 0x44b36
movq %r12, %rdi
movq 0x48(%rsp), %rsi
callq 0x28340
movq %rbx, %rdi
callq 0x28160
nop