// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3TriangleArray.cpp
// Function: gaps::R3TriangleArray::UpdateVBO()
void R3TriangleArray::
UpdateVBO(void)
{
#if (RN_3D_GRFX == RN_OPENGL)
  // Check if VBO is uptodate
  if (vbo_size > 0) return;
  
  // Check triangle array
  if (NVertices() == 0) return;
  if (NTriangles() == 0) return;

  // Allocate buffer data
  static const unsigned int vertex_size = 12 * sizeof(GLfloat);
  unsigned int buffer_size = 3 * NTriangles() * vertex_size;
  GLfloat *buffer_data = new GLfloat [ buffer_size ];
  if (!buffer_data) return;
  
  // Fill vertex data 
  GLfloat *buffer_datap = buffer_data;
  for (int i = 0; i < NTriangles(); i++) {
    R3Triangle *triangle = Triangle(i);
    int dim = triangle->Normal().MaxDimension();
    int dim1 = (dim + 1) % 3;
    int dim2 = (dim + 2) % 3;
    for (int j = 0; j < 3; j++) {
      R3TriangleVertex *vertex = triangle->Vertex(j);

      // Load position
      *(buffer_datap++) = vertex->Position().X();
      *(buffer_datap++) = vertex->Position().Y();
      *(buffer_datap++) = vertex->Position().Z();

      // Load normal
      if (triangle->HasNormals() && vertex->HasNormal()) {
        R3Vector normal = vertex->Normal();
        RNScalar dot = normal.Dot(triangle->Normal());
        if (dot < -0.25) normal = -normal;
        else if (dot < 0.25) normal = triangle->Normal();
        *(buffer_datap++) = normal.X();
        *(buffer_datap++) = normal.Y();
        *(buffer_datap++) = normal.Z();
      }
      else {
        *(buffer_datap++) = triangle->Normal().X();
        *(buffer_datap++) = triangle->Normal().Y();
        *(buffer_datap++) = triangle->Normal().Z();
      }

      // Load color      
      if (triangle->HasColors() && vertex->HasColor()) {
        *(buffer_datap++) = vertex->Color().R();
        *(buffer_datap++) = vertex->Color().G();
        *(buffer_datap++) = vertex->Color().B();
      }
      else {
        *(buffer_datap++) = 0.5;
        *(buffer_datap++) = 0.5;
        *(buffer_datap++) = 0.5;
      }

      // Load texture coordinates
      if (triangle->HasTextureCoords() && vertex->HasTextureCoords()) {
        *(buffer_datap++) = vertex->TextureCoords().X();
        *(buffer_datap++) = vertex->TextureCoords().Y();
        *(buffer_datap++) = 0;
      }
      else {
        *(buffer_datap++) = vertex->Position()[dim1];
        *(buffer_datap++) = vertex->Position()[dim2];
        *(buffer_datap++) = 0;
      }
    }
  }

  // Just checking
  assert((long int) (buffer_datap - buffer_data) == (long int) (buffer_size / sizeof(GLfloat)));

  // Generate VBO buffer (first time only)
  if (vbo_id == 0) glGenBuffers(1, &vbo_id);

  // Load VBO buffer
  if (vbo_id && buffer_data && buffer_size) {
    glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
    glBufferData(GL_ARRAY_BUFFER, buffer_size, buffer_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    vbo_size = buffer_size;
  }

  // Delete in-memory data
  if (buffer_data) delete [] buffer_data;
#endif
}

// Assembly:
subq $0x98, %rsp
movq %rdi, 0x90(%rsp)
movq 0x90(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpl $0x0, 0x6c(%rax)
jbe 0x99987
jmp 0x99fc7
movq 0x10(%rsp), %rdi
callq 0x9a5c0
cmpl $0x0, %eax
jne 0x9999b
jmp 0x99fc7
movq 0x10(%rsp), %rdi
callq 0x81c30
cmpl $0x0, %eax
jne 0x999af
jmp 0x99fc7
movq 0x10(%rsp), %rdi
callq 0x81c30
imull $0x3, %eax, %eax
imull $0x30, %eax, %eax
movl %eax, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0xf030
movq %rax, 0x80(%rsp)
cmpq $0x0, 0x80(%rsp)
jne 0x99a06
jmp 0x99fc7
movq 0x80(%rsp), %rax
movq %rax, 0x78(%rsp)
movl $0x0, 0x74(%rsp)
movq 0x10(%rsp), %rdi
movl 0x74(%rsp), %eax
movl %eax, 0xc(%rsp)
callq 0x81c30
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jge 0x99efb
movq 0x10(%rsp), %rdi
movl 0x74(%rsp), %esi
callq 0x81c50
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rdi
callq 0x78960
movq %rax, %rdi
callq 0x6ffd0
movl %eax, 0x64(%rsp)
movl 0x64(%rsp), %eax
addl $0x1, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %edx, 0x60(%rsp)
movl 0x64(%rsp), %eax
addl $0x2, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %edx, 0x5c(%rsp)
movl $0x0, 0x58(%rsp)
cmpl $0x3, 0x58(%rsp)
jge 0x99ee9
movq 0x68(%rsp), %rdi
movl 0x58(%rsp), %esi
callq 0x81eb0
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rdi
callq 0x78950
movq %rax, %rdi
callq 0x37820
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x50(%rsp), %rdi
callq 0x78950
movq %rax, %rdi
callq 0x37870
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x50(%rsp), %rdi
callq 0x78950
movq %rax, %rdi
callq 0x378c0
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x68(%rsp), %rdi
callq 0x9a5e0
cmpl $0x0, %eax
je 0x99c52
movq 0x50(%rsp), %rdi
callq 0x78a20
cmpl $0x0, %eax
je 0x99c52
movq 0x50(%rsp), %rdi
callq 0x789e0
movq %rax, %rsi
leaq 0x38(%rsp), %rdi
callq 0x6fcf0
movq 0x68(%rsp), %rdi
callq 0x78960
movq %rax, %rsi
leaq 0x38(%rsp), %rdi
callq 0x702c0
movsd %xmm0, 0x30(%rsp)
movsd 0x9bdbd(%rip), %xmm0    # 0x135950
ucomisd 0x30(%rsp), %xmm0
jbe 0x99bbb
leaq 0x18(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x70fa0
leaq 0x38(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x70970
jmp 0x99be4
movsd 0x9bd85(%rip), %xmm0    # 0x135948
ucomisd 0x30(%rsp), %xmm0
jbe 0x99be2
movq 0x68(%rsp), %rdi
callq 0x78960
movq %rax, %rsi
leaq 0x38(%rsp), %rdi
callq 0x70970
jmp 0x99be4
leaq 0x38(%rsp), %rdi
callq 0x38c20
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
leaq 0x38(%rsp), %rdi
callq 0x38c30
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
leaq 0x38(%rsp), %rdi
callq 0x38c40
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
jmp 0x99cd3
movq 0x68(%rsp), %rdi
callq 0x78960
movq %rax, %rdi
callq 0x38c20
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x68(%rsp), %rdi
callq 0x78960
movq %rax, %rdi
callq 0x38c30
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x68(%rsp), %rdi
callq 0x78960
movq %rax, %rdi
callq 0x38c40
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x68(%rsp), %rdi
callq 0x9a620
cmpl $0x0, %eax
je 0x99d7c
movq 0x50(%rsp), %rdi
callq 0x9a660
cmpl $0x0, %eax
je 0x99d7c
movq 0x50(%rsp), %rdi
callq 0x789d0
movq %rax, %rdi
callq 0x38cb0
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x50(%rsp), %rdi
callq 0x789d0
movq %rax, %rdi
callq 0x38cc0
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x50(%rsp), %rdi
callq 0x789d0
movq %rax, %rdi
callq 0x38cd0
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
jmp 0x99dd3
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss 0x9bd43(%rip), %xmm0    # 0x135ad8
movss %xmm0, (%rax)
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss 0x9bd26(%rip), %xmm0    # 0x135ad8
movss %xmm0, (%rax)
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss 0x9bd09(%rip), %xmm0    # 0x135ad8
movss %xmm0, (%rax)
movq 0x68(%rsp), %rdi
callq 0x9a6a0
cmpl $0x0, %eax
je 0x99e61
movq 0x50(%rsp), %rdi
callq 0x9a6e0
cmpl $0x0, %eax
je 0x99e61
movq 0x50(%rsp), %rdi
callq 0x78a10
movq %rax, %rdi
callq 0x38c50
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x50(%rsp), %rdi
callq 0x78a10
movq %rax, %rdi
callq 0x38c60
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
xorps %xmm0, %xmm0
movss %xmm0, (%rax)
jmp 0x99ed7
movq 0x50(%rsp), %rdi
callq 0x78950
movq %rax, %rdi
movl 0x60(%rsp), %esi
callq 0x13af0
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x50(%rsp), %rdi
callq 0x78950
movq %rax, %rdi
movl 0x5c(%rsp), %esi
callq 0x13af0
cvtsd2ss %xmm0, %xmm0
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
movss %xmm0, (%rax)
movq 0x78(%rsp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, 0x78(%rsp)
xorps %xmm0, %xmm0
movss %xmm0, (%rax)
jmp 0x99ed9
movl 0x58(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x58(%rsp)
jmp 0x99a92
jmp 0x99eeb
movl 0x74(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x74(%rsp)
jmp 0x99a1b
movq 0x10(%rsp), %rax
cmpl $0x0, 0x68(%rax)
jne 0x99f20
movq 0x10(%rsp), %rsi
movq 0xd5096(%rip), %rax     # 0x16efa8
movq (%rax), %rax
addq $0x68, %rsi
movl $0x1, %edi
callq *%rax
movq 0x10(%rsp), %rax
cmpl $0x0, 0x68(%rax)
je 0x99f9f
cmpq $0x0, 0x80(%rsp)
je 0x99f9f
cmpl $0x0, 0x8c(%rsp)
je 0x99f9f
movq 0x10(%rsp), %rcx
movq 0xd5074(%rip), %rax     # 0x16efc0
movq (%rax), %rax
movl 0x68(%rcx), %esi
movl $0x8892, %edi           # imm = 0x8892
callq *%rax
movq 0xd5070(%rip), %rax     # 0x16efd0
movq (%rax), %rax
movl 0x8c(%rsp), %ecx
movl %ecx, %esi
movq 0x80(%rsp), %rdx
movl $0x8892, %edi           # imm = 0x8892
movl $0x88e4, %ecx           # imm = 0x88E4
callq *%rax
movl $0x8892, %edi           # imm = 0x8892
xorl %esi, %esi
movq 0xd5032(%rip), %rax     # 0x16efc0
callq *(%rax)
movq 0x10(%rsp), %rax
movl 0x8c(%rsp), %ecx
movl %ecx, 0x6c(%rax)
cmpq $0x0, 0x80(%rsp)
je 0x99fc7
movq 0x80(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x99fc5
movq (%rsp), %rdi
callq 0xf670
jmp 0x99fc7
addq $0x98, %rsp
retq
nop