// File: tomfunkhouser[P]gaps/pkgs/R3Utils/R3SurfelViewer.cpp
// Function: gaps::R3SurfelViewer::ComputeVBOBuffers(std::vector<float, std::allocator<float>>&, std::vector<float, std::allocator<float>>&, std::vector<unsigned char, std::allocator<unsigned char>>&) const
void R3SurfelViewer::
ComputeVBOBuffers(std::vector<GLfloat>& surfel_positions,
    std::vector<GLfloat>& surfel_normals, std::vector<GLubyte>& surfel_colors) const
{
  // Count surfels
  int nsurfels = 0;
  for (int i = 0; i < resident_nodes.NNodes(); i++) {
    R3SurfelNode *node = resident_nodes.Node(i);
    if (!NodeVisibility(node)) continue;
    for (int j = 0; j < node->NBlocks(); j++) {
      R3SurfelBlock *block = node->Block(j);
      nsurfels += block->NSurfels() / subsampling_factor;
      if (block->NSurfels() % subsampling_factor > 0) nsurfels++;
    }
  }

  // Allocate in-memory buffers
  surfel_positions.resize(3 * nsurfels);
  surfel_normals.resize(3 * nsurfels);
  surfel_colors.resize(2 * 3 * nsurfels);

  // Fill in-memory buffers 
  int count = 0;
  unsigned int pick_color_offset = 3 * nsurfels;
  for (int i = 0; i < resident_nodes.NNodes(); i++) {
    R3SurfelNode *node = resident_nodes.Node(i);
    if (!NodeVisibility(node)) continue;
    R3SurfelObject *object = node->Object(TRUE, TRUE);
    while (object && object->Parent() && (object->Parent() != scene->RootObject())) object = object->Parent();
    R3SurfelLabel *label = (object) ? object->CurrentLabel() : NULL;
    for (int j = 0; j < node->NBlocks(); j++) {
      R3SurfelBlock *block = node->Block(j);
      const R3Point& block_origin = block->PositionOrigin();
      for (int k = 0; k < block->NSurfels(); k += subsampling_factor) {
        const R3Surfel *surfel = block->Surfel(k);

        // Compute colors
        GLubyte surfel_color[3], pick_color[3];
        CreateColor(surfel_color, surfel_color_scheme,
          surfel, block, node, object, label);
        CreateColor(pick_color, R3_SURFEL_VIEWER_COLOR_BY_PICK_INDEX,
          surfel, block, node, object, label);
        assert(count < nsurfels);

        // Fill buffers
        int i0 = 3 * (count++);
        int i1 = i0+1;
        int i2 = i1+1;
        surfel_positions[i0] = block_origin.X() + surfel->X();
        surfel_positions[i1] = block_origin.Y() + surfel->Y();
        surfel_positions[i2] = block_origin.Z() + surfel->Z();
        surfel_normals[i0] = surfel->NX();
        surfel_normals[i1] = surfel->NY();
        surfel_normals[i2] = surfel->NZ();
        surfel_colors[i0] = surfel_color[0];
        surfel_colors[i1] = surfel_color[1];
        surfel_colors[i2] = surfel_color[2];
        surfel_colors[i0 + pick_color_offset] = pick_color[0];
        surfel_colors[i1 + pick_color_offset] = pick_color[1];
        surfel_colors[i2 + pick_color_offset] = pick_color[2];
      }
    }
  }
  
  // Just checking
  assert(count == nsurfels);
}

// Assembly:
subq $0x128, %rsp            # imm = 0x128
movq %rdi, 0x120(%rsp)
movq %rsi, 0x118(%rsp)
movq %rdx, 0x110(%rsp)
movq %rcx, 0x108(%rsp)
movq 0x120(%rsp), %rax
movq %rax, 0x78(%rsp)
movl $0x0, 0x104(%rsp)
movl $0x0, 0x100(%rsp)
movq 0x78(%rsp), %rdi
movl 0x100(%rsp), %eax
movl %eax, 0x74(%rsp)
addq $0x10, %rdi
callq 0x3df90
movl %eax, %ecx
movl 0x74(%rsp), %eax
cmpl %ecx, %eax
jge 0x3bf9d
movq 0x78(%rsp), %rdi
addq $0x10, %rdi
movl 0x100(%rsp), %esi
callq 0x3dfb0
movq 0x78(%rsp), %rdi
movq %rax, 0xf8(%rsp)
movq 0xf8(%rsp), %rsi
callq 0x30370
cmpl $0x0, %eax
jne 0x3beca
jmp 0x3bf87
movl $0x0, 0xf4(%rsp)
movl 0xf4(%rsp), %eax
movl %eax, 0x70(%rsp)
movq 0xf8(%rsp), %rdi
callq 0x2f200
movl %eax, %ecx
movl 0x70(%rsp), %eax
cmpl %ecx, %eax
jge 0x3bf85
movq 0xf8(%rsp), %rdi
movl 0xf4(%rsp), %esi
callq 0x2f280
movq %rax, 0xe8(%rsp)
movq 0xe8(%rsp), %rdi
callq 0x2f2b0
movq 0x78(%rsp), %rcx
cltd
idivl 0x48c(%rcx)
addl 0x104(%rsp), %eax
movl %eax, 0x104(%rsp)
movq 0xe8(%rsp), %rdi
callq 0x2f2b0
movq 0x78(%rsp), %rcx
cltd
idivl 0x48c(%rcx)
cmpl $0x0, %edx
jle 0x3bf6d
movl 0x104(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x104(%rsp)
jmp 0x3bf6f
movl 0xf4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf4(%rsp)
jmp 0x3bed5
jmp 0x3bf87
movl 0x100(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x100(%rsp)
jmp 0x3be6a
movq 0x118(%rsp), %rdi
imull $0x3, 0x104(%rsp), %eax
movslq %eax, %rsi
callq 0x3eee0
movq 0x110(%rsp), %rdi
imull $0x3, 0x104(%rsp), %eax
movslq %eax, %rsi
callq 0x3eee0
movq 0x108(%rsp), %rdi
imull $0x6, 0x104(%rsp), %eax
movslq %eax, %rsi
callq 0x3ef80
movl $0x0, 0xe4(%rsp)
imull $0x3, 0x104(%rsp), %eax
movl %eax, 0xe0(%rsp)
movl $0x0, 0xdc(%rsp)
movq 0x78(%rsp), %rdi
movl 0xdc(%rsp), %eax
movl %eax, 0x6c(%rsp)
addq $0x10, %rdi
callq 0x3df90
movl %eax, %ecx
movl 0x6c(%rsp), %eax
cmpl %ecx, %eax
jge 0x3c5bc
movq 0x78(%rsp), %rdi
addq $0x10, %rdi
movl 0xdc(%rsp), %esi
callq 0x3dfb0
movq 0x78(%rsp), %rdi
movq %rax, 0xd0(%rsp)
movq 0xd0(%rsp), %rsi
callq 0x30370
cmpl $0x0, %eax
jne 0x3c06a
jmp 0x3c5a6
movq 0xd0(%rsp), %rdi
movl $0x1, %edx
movl %edx, %esi
callq 0x58f70
movq %rax, 0xc8(%rsp)
xorl %eax, %eax
cmpq $0x0, 0xc8(%rsp)
movb %al, 0x6b(%rsp)
je 0x3c0e8
movq 0xc8(%rsp), %rdi
callq 0x3d2e0
movq %rax, %rcx
xorl %eax, %eax
cmpq $0x0, %rcx
movb %al, 0x6b(%rsp)
je 0x3c0e8
movq 0xc8(%rsp), %rdi
callq 0x3d2e0
movq %rax, %rcx
movq 0x78(%rsp), %rax
movq %rcx, 0x60(%rsp)
movq 0x8(%rax), %rdi
callq 0x3d2f0
movq %rax, %rcx
movq 0x60(%rsp), %rax
cmpq %rcx, %rax
setne %al
movb %al, 0x6b(%rsp)
movb 0x6b(%rsp), %al
testb $0x1, %al
jne 0x3c0f2
jmp 0x3c10c
movq 0xc8(%rsp), %rdi
callq 0x3d2e0
movq %rax, 0xc8(%rsp)
jmp 0x3c086
cmpq $0x0, 0xc8(%rsp)
je 0x3c12b
movq 0xc8(%rsp), %rdi
callq 0x662c0
movq %rax, 0x58(%rsp)
jmp 0x3c134
xorl %eax, %eax
movq %rax, 0x58(%rsp)
jmp 0x3c134
movq 0x58(%rsp), %rax
movq %rax, 0xc0(%rsp)
movl $0x0, 0xbc(%rsp)
movl 0xbc(%rsp), %eax
movl %eax, 0x54(%rsp)
movq 0xd0(%rsp), %rdi
callq 0x2f200
movl %eax, %ecx
movl 0x54(%rsp), %eax
cmpl %ecx, %eax
jge 0x3c5a4
movq 0xd0(%rsp), %rdi
movl 0xbc(%rsp), %esi
callq 0x2f280
movq %rax, 0xb0(%rsp)
movq 0xb0(%rsp), %rdi
callq 0x3d6b0
movq %rax, 0xa8(%rsp)
movl $0x0, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
movl %eax, 0x50(%rsp)
movq 0xb0(%rsp), %rdi
callq 0x2f2b0
movl %eax, %ecx
movl 0x50(%rsp), %eax
cmpl %ecx, %eax
jge 0x3c58c
movq 0xb0(%rsp), %rdi
movl 0xa4(%rsp), %esi
callq 0x3e050
movq 0x78(%rsp), %rdi
movq %rax, 0x98(%rsp)
leaq 0x95(%rsp), %rsi
movl 0x360(%rdi), %edx
movq 0x98(%rsp), %rcx
movq 0xb0(%rsp), %r8
movq 0xd0(%rsp), %r9
movq 0xc8(%rsp), %r11
movq 0xc0(%rsp), %r10
movq (%rdi), %rax
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
callq *0x210(%rax)
movq 0x78(%rsp), %rdi
leaq 0x92(%rsp), %rsi
movq 0x98(%rsp), %rcx
movq 0xb0(%rsp), %r8
movq 0xd0(%rsp), %r9
movq 0xc8(%rsp), %r11
movq 0xc0(%rsp), %r10
movq (%rdi), %rax
movl $0xe, %edx
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
callq *0x210(%rax)
movl 0xe4(%rsp), %eax
movl %eax, %ecx
addl $0x1, %ecx
movl %ecx, 0xe4(%rsp)
imull $0x3, %eax, %eax
movl %eax, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x88(%rsp)
movl 0x88(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x84(%rsp)
movq 0xa8(%rsp), %rdi
callq 0x2ee70
movsd %xmm0, 0x10(%rsp)
movq 0x98(%rsp), %rdi
callq 0x3e0c0
movaps %xmm0, %xmm1
movsd 0x10(%rsp), %xmm0
cvtss2sd %xmm1, %xmm1
addsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x1c(%rsp)
movq 0x118(%rsp), %rdi
movslq 0x8c(%rsp), %rsi
callq 0x3f020
movss 0x1c(%rsp), %xmm0
movss %xmm0, (%rax)
movq 0xa8(%rsp), %rdi
callq 0x2ee80
movsd %xmm0, 0x20(%rsp)
movq 0x98(%rsp), %rdi
callq 0x3e0d0
movaps %xmm0, %xmm1
movsd 0x20(%rsp), %xmm0
cvtss2sd %xmm1, %xmm1
addsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x2c(%rsp)
movq 0x118(%rsp), %rdi
movslq 0x88(%rsp), %rsi
callq 0x3f020
movss 0x2c(%rsp), %xmm0
movss %xmm0, (%rax)
movq 0xa8(%rsp), %rdi
callq 0x2ee90
movsd %xmm0, 0x30(%rsp)
movq 0x98(%rsp), %rdi
callq 0x3d6c0
movaps %xmm0, %xmm1
movsd 0x30(%rsp), %xmm0
cvtss2sd %xmm1, %xmm1
addsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x38(%rsp)
movq 0x118(%rsp), %rdi
movslq 0x84(%rsp), %rsi
callq 0x3f020
movss 0x38(%rsp), %xmm0
movss %xmm0, (%rax)
movq 0x98(%rsp), %rdi
callq 0x3d650
movss %xmm0, 0x3c(%rsp)
movq 0x110(%rsp), %rdi
movslq 0x8c(%rsp), %rsi
callq 0x3f020
movss 0x3c(%rsp), %xmm0
movss %xmm0, (%rax)
movq 0x98(%rsp), %rdi
callq 0x3d670
movss %xmm0, 0x40(%rsp)
movq 0x110(%rsp), %rdi
movslq 0x88(%rsp), %rsi
callq 0x3f020
movss 0x40(%rsp), %xmm0
movss %xmm0, (%rax)
movq 0x98(%rsp), %rdi
callq 0x3d690
movss %xmm0, 0x44(%rsp)
movq 0x110(%rsp), %rdi
movslq 0x84(%rsp), %rsi
callq 0x3f020
movss 0x44(%rsp), %xmm0
movss %xmm0, (%rax)
movb 0x95(%rsp), %al
movb %al, 0x4a(%rsp)
movq 0x108(%rsp), %rdi
movslq 0x8c(%rsp), %rsi
callq 0x3f040
movb 0x4a(%rsp), %cl
movb %cl, (%rax)
movb 0x96(%rsp), %al
movb %al, 0x4b(%rsp)
movq 0x108(%rsp), %rdi
movslq 0x88(%rsp), %rsi
callq 0x3f040
movb 0x4b(%rsp), %cl
movb %cl, (%rax)
movb 0x97(%rsp), %al
movb %al, 0x4c(%rsp)
movq 0x108(%rsp), %rdi
movslq 0x84(%rsp), %rsi
callq 0x3f040
movb 0x4c(%rsp), %cl
movb %cl, (%rax)
movb 0x92(%rsp), %al
movb %al, 0x4d(%rsp)
movq 0x108(%rsp), %rdi
movl 0x8c(%rsp), %eax
addl 0xe0(%rsp), %eax
movl %eax, %eax
movl %eax, %esi
callq 0x3f040
movb 0x4d(%rsp), %cl
movb %cl, (%rax)
movb 0x93(%rsp), %al
movb %al, 0x4e(%rsp)
movq 0x108(%rsp), %rdi
movl 0x88(%rsp), %eax
addl 0xe0(%rsp), %eax
movl %eax, %eax
movl %eax, %esi
callq 0x3f040
movb 0x4e(%rsp), %cl
movb %cl, (%rax)
movb 0x94(%rsp), %al
movb %al, 0x4f(%rsp)
movq 0x108(%rsp), %rdi
movl 0x84(%rsp), %eax
addl 0xe0(%rsp), %eax
movl %eax, %eax
movl %eax, %esi
callq 0x3f040
movb 0x4f(%rsp), %cl
movb %cl, (%rax)
movq 0x78(%rsp), %rax
movl 0x48c(%rax), %eax
addl 0xa4(%rsp), %eax
movl %eax, 0xa4(%rsp)
jmp 0x3c1ae
jmp 0x3c58e
movl 0xbc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xbc(%rsp)
jmp 0x3c14c
jmp 0x3c5a6
movl 0xdc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xdc(%rsp)
jmp 0x3c00a
addq $0x128, %rsp            # imm = 0x128
retq
nopw %cs:(%rax,%rax)