246 lines
6.0 KiB
C++
246 lines
6.0 KiB
C++
|
#include "VertexBufferImpl.h"
|
||
|
|
||
|
#include <Kore/Graphics3/Graphics.h>
|
||
|
|
||
|
#include "ShaderImpl.h"
|
||
|
#include "ogl.h"
|
||
|
|
||
|
#include <assert.h>
|
||
|
|
||
|
using namespace Kore;
|
||
|
|
||
|
Graphics3::VertexBuffer *VertexBufferImpl::current = nullptr;
|
||
|
|
||
|
VertexBufferImpl::VertexBufferImpl(int count, int instanceDataStepRate) : myCount(count), instanceDataStepRate(instanceDataStepRate) {
|
||
|
#ifndef NDEBUG
|
||
|
initialized = false;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
Graphics3::VertexBuffer::VertexBuffer(int vertexCount, const Graphics4::VertexStructure &structure, Usage usage, int instanceDataStepRate)
|
||
|
: VertexBufferImpl(vertexCount, instanceDataStepRate) {
|
||
|
myStride = 0;
|
||
|
for (int i = 0; i < structure.size; ++i) {
|
||
|
Graphics4::VertexElement element = structure.elements[i];
|
||
|
switch (element.data) {
|
||
|
case Graphics4::ColorVertexData:
|
||
|
myStride += 1 * 4;
|
||
|
break;
|
||
|
case Graphics4::Float1VertexData:
|
||
|
myStride += 1 * 4;
|
||
|
break;
|
||
|
case Graphics4::Float2VertexData:
|
||
|
myStride += 2 * 4;
|
||
|
break;
|
||
|
case Graphics4::Float3VertexData:
|
||
|
myStride += 3 * 4;
|
||
|
break;
|
||
|
case Graphics4::Float4VertexData:
|
||
|
myStride += 4 * 4;
|
||
|
break;
|
||
|
case Graphics4::Float4x4VertexData:
|
||
|
myStride += 4 * 4 * 4;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
this->structure = structure;
|
||
|
|
||
|
glGenBuffers(1, &bufferId);
|
||
|
glCheckErrors();
|
||
|
data = new float[vertexCount * myStride / 4];
|
||
|
}
|
||
|
|
||
|
Graphics3::VertexBuffer::~VertexBuffer() {
|
||
|
unset();
|
||
|
delete[] data;
|
||
|
}
|
||
|
|
||
|
float *Graphics3::VertexBuffer::lock() {
|
||
|
return data;
|
||
|
}
|
||
|
/*
|
||
|
// TODO: FIXME!
|
||
|
float* VertexBuffer::lock(int start, int count) {
|
||
|
myCount = count;
|
||
|
return nullptr;//&buffer[start * 9];
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
void Graphics3::VertexBuffer::unlock() {
|
||
|
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
|
||
|
glCheckErrors();
|
||
|
glBufferData(GL_ARRAY_BUFFER, myStride * myCount, data, GL_STATIC_DRAW);
|
||
|
glCheckErrors();
|
||
|
#ifndef NDEBUG
|
||
|
initialized = true;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int Graphics3::VertexBuffer::_set(int offset) {
|
||
|
assert(initialized); // Vertex Buffer is used before lock/unlock was called
|
||
|
int offsetoffset = setVertexAttributes(offset);
|
||
|
if (IndexBuffer::current != nullptr)
|
||
|
IndexBuffer::current->_set();
|
||
|
return offsetoffset;
|
||
|
}
|
||
|
|
||
|
void VertexBufferImpl::unset() {
|
||
|
if ((void *)current == (void *)this)
|
||
|
current = nullptr;
|
||
|
}
|
||
|
|
||
|
int Graphics3::VertexBuffer::count() {
|
||
|
return myCount;
|
||
|
}
|
||
|
|
||
|
int Graphics3::VertexBuffer::stride() {
|
||
|
return myStride;
|
||
|
}
|
||
|
|
||
|
int VertexBufferImpl::setVertexAttributes(int offset) {
|
||
|
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
|
||
|
glCheckErrors();
|
||
|
|
||
|
// Enable vertex attributes
|
||
|
unsigned int usedAttribsMask = 0;
|
||
|
|
||
|
int internaloffset = 0;
|
||
|
int actualIndex = 0;
|
||
|
|
||
|
for (int index = 0; index < structure.size; ++index) {
|
||
|
Graphics4::VertexElement element = structure.elements[index];
|
||
|
int size = 0;
|
||
|
GLenum type = GL_FLOAT;
|
||
|
|
||
|
switch (element.data) {
|
||
|
case Graphics4::ColorVertexData:
|
||
|
size = 4;
|
||
|
type = GL_UNSIGNED_BYTE;
|
||
|
break;
|
||
|
case Graphics4::Float1VertexData:
|
||
|
size = 1;
|
||
|
break;
|
||
|
case Graphics4::Float2VertexData:
|
||
|
size = 2;
|
||
|
break;
|
||
|
case Graphics4::Float3VertexData:
|
||
|
size = 3;
|
||
|
break;
|
||
|
case Graphics4::Float4VertexData:
|
||
|
size = 4;
|
||
|
break;
|
||
|
case Graphics4::Float4x4VertexData:
|
||
|
size = 16;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (element.attribute) {
|
||
|
case Graphics4::VertexCoord:
|
||
|
assert(size >= 2 && size <= 4);
|
||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||
|
glVertexPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
|
||
|
break;
|
||
|
|
||
|
case Graphics4::VertexNormal:
|
||
|
assert(size == 3);
|
||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||
|
glNormalPointer(type, myStride, reinterpret_cast<const void *>(internaloffset));
|
||
|
break;
|
||
|
|
||
|
case Graphics4::VertexColor0:
|
||
|
assert(size >= 3 && size <= 4);
|
||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||
|
glColorPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
|
||
|
break;
|
||
|
|
||
|
case Graphics4::VertexColor1:
|
||
|
assert(size == 3);
|
||
|
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
|
||
|
glSecondaryColorPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
|
||
|
break;
|
||
|
|
||
|
case Graphics4::VertexTexCoord0:
|
||
|
case Graphics4::VertexTexCoord1:
|
||
|
case Graphics4::VertexTexCoord2:
|
||
|
case Graphics4::VertexTexCoord3:
|
||
|
case Graphics4::VertexTexCoord4:
|
||
|
case Graphics4::VertexTexCoord5:
|
||
|
case Graphics4::VertexTexCoord6:
|
||
|
case Graphics4::VertexTexCoord7:
|
||
|
assert(size >= 1 && size <= 4);
|
||
|
glClientActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(element.attribute - Graphics4::VertexTexCoord0));
|
||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||
|
glTexCoordPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
usedAttribsMask |= (1u << element.attribute);
|
||
|
++actualIndex;
|
||
|
|
||
|
switch (element.data) {
|
||
|
case Graphics4::ColorVertexData:
|
||
|
internaloffset += 4 * 1;
|
||
|
break;
|
||
|
case Graphics4::Float1VertexData:
|
||
|
internaloffset += 4 * 1;
|
||
|
break;
|
||
|
case Graphics4::Float2VertexData:
|
||
|
internaloffset += 4 * 2;
|
||
|
break;
|
||
|
case Graphics4::Float3VertexData:
|
||
|
internaloffset += 4 * 3;
|
||
|
break;
|
||
|
case Graphics4::Float4VertexData:
|
||
|
internaloffset += 4 * 4;
|
||
|
break;
|
||
|
case Graphics4::Float4x4VertexData:
|
||
|
internaloffset += 4 * 4 * 4;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Disable unused vertex attributes
|
||
|
for (int attrib = Graphics4::VertexCoord; attrib <= Graphics4::VertexTexCoord7; ++attrib) {
|
||
|
if ((usedAttribsMask & (1u << attrib)) == 0) {
|
||
|
switch (attrib) {
|
||
|
case Graphics4::VertexCoord:
|
||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||
|
break;
|
||
|
|
||
|
case Graphics4::VertexNormal:
|
||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||
|
break;
|
||
|
|
||
|
case Graphics4::VertexColor0:
|
||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||
|
break;
|
||
|
|
||
|
case Graphics4::VertexColor1:
|
||
|
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
|
||
|
break;
|
||
|
|
||
|
case Graphics4::VertexTexCoord0:
|
||
|
case Graphics4::VertexTexCoord1:
|
||
|
case Graphics4::VertexTexCoord2:
|
||
|
case Graphics4::VertexTexCoord3:
|
||
|
case Graphics4::VertexTexCoord4:
|
||
|
case Graphics4::VertexTexCoord5:
|
||
|
case Graphics4::VertexTexCoord6:
|
||
|
case Graphics4::VertexTexCoord7:
|
||
|
glClientActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(attrib - Graphics4::VertexTexCoord0));
|
||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
glCheckErrors();
|
||
|
}
|
||
|
|
||
|
return actualIndex;
|
||
|
}
|