// File: /workspace/github_cpp_makefile_star2_O2/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:
cmpl $0x0, 0x6c(%rdi)
jne 0x4c262
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rdi, %r15
cmpl $0x0, 0x14(%rdi)
je 0x4c254
movl 0x24(%r15), %ebx
testl %ebx, %ebx
je 0x4c254
imull $0x90, %ebx, %eax
movq %rax, 0x10(%rsp)
leaq (,%rax,4), %rdi
callq 0xe030
movq %rax, %r14
xorl %ecx, %ecx
movq %rax, 0x8(%rsp)
movq %r15, 0x18(%rsp)
movslq %ebx, %rax
cmpq %rax, %rcx
jge 0x4c1e1
movq 0x18(%r15), %rax
movq %rcx, 0x20(%rsp)
movq (%rax,%rcx,8), %rbx
leaq 0x20(%rbx), %r13
movq %r13, %rdi
callq 0x38490
movsd 0x4e0d9(%rip), %xmm1    # 0x9a110
movl %eax, %ecx
leal 0x1(%rcx), %eax
cltd
pushq $0x3
popq %rdi
idivl %edi
movl %edx, %esi
addl $0x2, %ecx
movl %ecx, %eax
cltd
idivl %edi
movslq %esi, %rcx
movslq %edx, %rdx
pushq $0x1
popq %r12
movq %r13, 0x28(%rsp)
movq %rcx, 0x38(%rsp)
movq %rdx, 0x30(%rsp)
cmpq $0x4, %r12
je 0x4c1cb
movq (%rbx,%r12,8), %rbp
movupd (%rbp), %xmm0
cvtpd2ps %xmm0, %xmm0
movlpd %xmm0, (%r14)
cvtsd2ss 0x10(%rbp), %xmm0
movss %xmm0, 0x8(%r14)
movq 0x78(%rbx), %rax
btl $0x8, %eax
jae 0x4c09c
testb $0x1, 0x59(%rbp)
jne 0x4c0bb
movupd 0x20(%rbx), %xmm0
cvtpd2ps %xmm0, %xmm0
movlpd %xmm0, 0xc(%r14)
cvtsd2ss 0x30(%rbx), %xmm0
movss %xmm0, 0x14(%r14)
jmp 0x4c14b
leaq 0x18(%rbp), %rsi
leaq 0x40(%rsp), %r15
movq %r15, %rdi
callq 0x3831c
movq %r15, %rdi
movq %r13, %rsi
callq 0x38586
movsd 0x4dd61(%rip), %xmm1    # 0x99e40
ucomisd %xmm0, %xmm1
jbe 0x4c102
leaq 0x60(%rsp), %r13
movq %r13, %rdi
movq %r15, %rsi
callq 0x38c72
movq %r15, %rdi
movq %r13, %rsi
movq 0x28(%rsp), %r13
jmp 0x4c118
movsd 0x47c56(%rip), %xmm1    # 0x93d60
ucomisd %xmm0, %xmm1
jbe 0x4c11d
leaq 0x40(%rsp), %rdi
movq %r13, %rsi
callq 0x3887c
cvtpd2ps 0x40(%rsp), %xmm0
cvtsd2ss 0x50(%rsp), %xmm1
movlpd %xmm0, 0xc(%r14)
movss %xmm1, 0x14(%r14)
movq 0x78(%rbx), %rax
movsd 0x4dfcf(%rip), %xmm1    # 0x9a110
movq 0x38(%rsp), %rcx
movq 0x30(%rsp), %rdx
btl $0xa, %eax
jae 0x4c157
testb $0x4, 0x59(%rbp)
jne 0x4c167
movsd %xmm1, 0x18(%r14)
movl $0x3f000000, 0x20(%r14) # imm = 0x3F000000
jmp 0x4c181
movupd 0x30(%rbp), %xmm0
cvtpd2ps %xmm0, %xmm0
movlpd %xmm0, 0x18(%r14)
cvtsd2ss 0x40(%rbp), %xmm0
movss %xmm0, 0x20(%r14)
btl $0x9, %eax
jae 0x4c18d
testb $0x2, 0x59(%rbp)
jne 0x4c1a0
cvtsd2ss (%rbp,%rcx,8), %xmm0
movss %xmm0, 0x24(%r14)
leaq (%rbp,%rdx,8), %rbp
jmp 0x4c1af
cvtsd2ss 0x48(%rbp), %xmm0
movss %xmm0, 0x24(%r14)
addq $0x50, %rbp
cvtsd2ss (%rbp), %xmm0
movss %xmm0, 0x28(%r14)
andl $0x0, 0x2c(%r14)
addq $0x30, %r14
incq %r12
jmp 0x4c065
movq 0x20(%rsp), %rcx
incq %rcx
movq 0x18(%rsp), %r15
movl 0x24(%r15), %ebx
jmp 0x4c00a
movl 0x68(%r15), %esi
testl %esi, %esi
jne 0x4c200
leaq 0x68(%r15), %r12
movq 0x8dda4(%rip), %rax     # 0xd9f98
pushq $0x1
popq %rdi
movq %r12, %rsi
callq *(%rax)
movl (%r12), %esi
testl %esi, %esi
sete %al
movq 0x10(%rsp), %r14
testl %r14d, %r14d
sete %cl
orb %al, %cl
jne 0x4c24a
movq 0x8dd95(%rip), %rbx     # 0xd9fb0
movl $0x8892, %edi           # imm = 0x8892
callq *(%rbx)
movq 0x8dd9f(%rip), %rax     # 0xd9fc8
movl $0x8892, %edi           # imm = 0x8892
movq %r14, %rsi
movq 0x8(%rsp), %rdx
movl $0x88e4, %ecx           # imm = 0x88E4
callq *(%rax)
movl $0x8892, %edi           # imm = 0x8892
xorl %esi, %esi
callq *(%rbx)
movl %r14d, 0x6c(%r15)
movq 0x8(%rsp), %rdi
callq 0xe5d0
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop