1
0
forked from 0ad/0ad
0ad/source/renderer/VertexArray.cpp
Ykkrosh 2f53eea71a Actor Viewer: Added controls for wireframe, background colour, move-when-walking. Reduced CPU usage when 'playing' things with no animation.
Color: Moved SColor* structs into SColor.h, so they can be used without
indirectly including CVector[34]D.
Terrain: Added 'base colour', for the Actor Viewer to be able to
modulate the colour of normally-white terrain.
Removed some "using namespace std" (because it doesn't make the code
easier to read, and it defeats the point of namespaces, and the rest of
the code doesn't do it).

This was SVN commit r4392.
2006-09-26 01:44:20 +00:00

213 lines
4.2 KiB
C++

#include "precompiled.h"
#include "lib/ogl.h"
#include "maths/Vector3D.h"
#include "maths/Vector4D.h"
#include "graphics/SColor.h"
#include "renderer/VertexArray.h"
#include "renderer/VertexBuffer.h"
#include "renderer/VertexBufferManager.h"
VertexArray::VertexArray(bool dynamic)
{
m_Dynamic = dynamic;
m_NumVertices = 0;
m_VB = 0;
m_BackingStore = 0;
m_Stride = 0;
}
VertexArray::~VertexArray()
{
Free();
}
// Free all resources on destruction or when a layout parameter changes
void VertexArray::Free()
{
delete[] m_BackingStore;
m_BackingStore = 0;
if (m_VB)
{
g_VBMan.Release(m_VB);
m_VB = 0;
}
}
// Set the number of vertices stored in the array
void VertexArray::SetNumVertices(size_t num)
{
if (num == m_NumVertices)
return;
Free();
m_NumVertices = num;
}
// Add vertex attributes like Position, Normal, UV
void VertexArray::AddAttribute(Attribute* attr)
{
debug_assert((attr->type == GL_FLOAT || attr->type == GL_UNSIGNED_BYTE) && "Unsupported attribute type");
debug_assert(attr->elems >= 1 && attr->elems <= 4);
attr->vertexArray = this;
m_Attributes.push_back(attr);
Free();
}
// Template specialization for GetIterator().
// We can put this into the source file because only a fixed set of types
// is supported for type safety.
template<>
VertexArrayIterator<CVector3D> VertexArray::Attribute::GetIterator<CVector3D>() const
{
debug_assert(vertexArray);
debug_assert(type == GL_FLOAT);
debug_assert(elems >= 3);
return vertexArray->MakeIterator<CVector3D>(this);
}
template<>
VertexArrayIterator<CVector4D> VertexArray::Attribute::GetIterator<CVector4D>() const
{
debug_assert(vertexArray);
debug_assert(type == GL_FLOAT);
debug_assert(elems >= 4);
return vertexArray->MakeIterator<CVector4D>(this);
}
template<>
VertexArrayIterator<float[2]> VertexArray::Attribute::GetIterator<float[2]>() const
{
debug_assert(vertexArray);
debug_assert(type == GL_FLOAT);
debug_assert(elems >= 2);
return vertexArray->MakeIterator<float[2]>(this);
}
template<>
VertexArrayIterator<SColor3ub> VertexArray::Attribute::GetIterator<SColor3ub>() const
{
debug_assert(vertexArray);
debug_assert(type == GL_UNSIGNED_BYTE);
debug_assert(elems >= 3);
return vertexArray->MakeIterator<SColor3ub>(this);
}
template<>
VertexArrayIterator<SColor4ub> VertexArray::Attribute::GetIterator<SColor4ub>() const
{
debug_assert(vertexArray);
debug_assert(type == GL_UNSIGNED_BYTE);
debug_assert(elems >= 4);
return vertexArray->MakeIterator<SColor4ub>(this);
}
static size_t RoundStride(size_t stride)
{
if (stride <= 0)
return 0;
if (stride <= 4)
return 4;
if (stride <= 8)
return 8;
if (stride <= 16)
return 16;
return (stride + 31) & ~31;
}
// Re-layout by assigning offsets on a first-come first-serve basis,
// then round up to a reasonable stride.
// Backing store is also created here, VBOs are created on upload.
void VertexArray::Layout()
{
Free();
m_Stride = 0;
//debug_printf("Layouting VertexArray\n");
for(int idx = (int)m_Attributes.size()-1; idx >= 0; --idx)
{
Attribute* attr = m_Attributes[idx];
if (!attr->type || !attr->elems)
continue;
size_t attrSize = 0;
switch(attr->type)
{
case GL_UNSIGNED_BYTE:
attrSize = sizeof(GLubyte);
break;
case GL_FLOAT:
attrSize = sizeof(GLfloat);
break;
default:
attrSize = 0;
debug_warn("Bad AttributeInfo::Type"); break;
}
attrSize *= attr->elems;
attr->offset = m_Stride;
m_Stride = (m_Stride + attrSize + 3) & ~3;
//debug_printf("%i: offset: %u\n", idx, attr->offset);
}
m_Stride = RoundStride(m_Stride);
//debug_printf("Stride: %u\n", m_Stride);
if (m_Stride)
m_BackingStore = new char[m_Stride * m_NumVertices];
}
// (Re-)Upload the attributes.
// Create the VBO if necessary.
void VertexArray::Upload()
{
debug_assert(m_BackingStore);
if (!m_VB)
m_VB = g_VBMan.Allocate(m_Stride, m_NumVertices, m_Dynamic);
m_VB->m_Owner->UpdateChunkVertices(m_VB, m_BackingStore);
}
// Bind this array, returns the base address for calls to glVertexPointer etc.
u8* VertexArray::Bind()
{
u8* base = m_VB->m_Owner->Bind();
base += m_VB->m_Index*m_Stride;
return base;
}
// Free the backing store to save some memory
void VertexArray::FreeBackingStore()
{
delete[] m_BackingStore;
m_BackingStore = 0;
}