PrimeWorldEditor/OpenGL/CDynamicVertexBuffer.cpp

137 lines
3.3 KiB
C++

#include "CDynamicVertexBuffer.h"
#include "CVertexArrayManager.h"
static const u32 gskAttribSize[] = {
0xC, 0xC, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8
};
CDynamicVertexBuffer::CDynamicVertexBuffer()
{
mAttribFlags = eNoAttributes;
mBufferedFlags = eNoAttributes;
mNumVertices = 0;
}
CDynamicVertexBuffer::~CDynamicVertexBuffer()
{
CVertexArrayManager::DeleteAllArraysForVBO(this);
ClearBuffers();
}
void CDynamicVertexBuffer::SetVertexCount(u32 NumVerts)
{
ClearBuffers();
mNumVertices = NumVerts;
InitBuffers();
}
void CDynamicVertexBuffer::Bind()
{
CVertexArrayManager::Current()->BindVAO(this);
}
void CDynamicVertexBuffer::Unbind()
{
glBindVertexArray(0);
}
void CDynamicVertexBuffer::SetActiveAttribs(u32 AttribFlags)
{
ClearBuffers();
mAttribFlags = (EVertexDescription) AttribFlags;
InitBuffers();
}
void CDynamicVertexBuffer::BufferAttrib(EVertexDescription Attrib, const void *pData)
{
u32 Index;
switch (Attrib)
{
case ePosition: Index = 0; break;
case eNormal: Index = 1; break;
case eColor0: Index = 2; break;
case eColor1: Index = 3; break;
case eTex0: Index = 4; break;
case eTex1: Index = 5; break;
case eTex2: Index = 6; break;
case eTex3: Index = 7; break;
case eTex4: Index = 8; break;
case eTex5: Index = 9; break;
case eTex6: Index = 10; break;
case eTex7: Index = 11; break;
default: return;
}
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[Index]);
glBufferSubData(GL_ARRAY_BUFFER, 0, gskAttribSize[Index] * mNumVertices, pData);
}
void CDynamicVertexBuffer::ClearBuffers()
{
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
{
u8 Bit = 1 << iAttrib;
if (mBufferedFlags & Bit)
glDeleteBuffers(1, &mAttribBuffers[iAttrib]);
}
mBufferedFlags = eNoAttributes;
}
GLuint CDynamicVertexBuffer::CreateVAO()
{
GLuint VertexArray;
glGenVertexArrays(1, &VertexArray);
glBindVertexArray(VertexArray);
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
{
bool HasAttrib = ((3 << (iAttrib * 2)) != 0);
if (HasAttrib)
{
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
GLuint NumComponents;
GLenum DataType;
if ((iAttrib == 2) || (iAttrib == 3))
{
NumComponents = 4;
DataType = GL_UNSIGNED_BYTE;
}
else
{
NumComponents = gskAttribSize[iAttrib] / 4;
DataType = GL_FLOAT;
}
glVertexAttribPointer(iAttrib, NumComponents, DataType, GL_FALSE, 0, (void*) 0);
glEnableVertexAttribArray(iAttrib);
}
}
glBindVertexArray(0);
return VertexArray;
}
// ************ PRIVATE ************
void CDynamicVertexBuffer::InitBuffers()
{
if (mBufferedFlags) ClearBuffers();
for (u32 iAttrib = 0; iAttrib < 12; iAttrib++)
{
bool HasAttrib = ((3 << (iAttrib * 2)) != 0);
if (HasAttrib)
{
glGenBuffers(1, &mAttribBuffers[iAttrib]);
glBindBuffer(GL_ARRAY_BUFFER, mAttribBuffers[iAttrib]);
glBufferData(GL_ARRAY_BUFFER, gskAttribSize[iAttrib] * mNumVertices, NULL, GL_DYNAMIC_DRAW);
}
}
mBufferedFlags = mAttribFlags;
}