1
0
forked from 0ad/0ad
0ad/source/renderer/FixedFunctionModelRenderer.cpp
prefect 0346ba1b18 Refactor model rendering to perform vertex setup in ModelVertexRenderer.
Sort all transparent models by distance to camera (however, do not sort
polygons by default).

This was SVN commit r3096.
2005-11-05 23:15:23 +00:00

240 lines
6.0 KiB
C++

/**
* =========================================================================
* File : FixedFunctionModelRenderer.cpp
* Project : Pyrogenesis
* Description : Implementation of FixedFunctionModelRenderer
*
* @author Nicolai Hähnle <nicolai@wildfiregames.com>
* =========================================================================
*/
#include "precompiled.h"
#include "ogl.h"
#include "Vector3D.h"
#include "Vector4D.h"
#include "ps/CLogger.h"
#include "graphics/Color.h"
#include "graphics/Model.h"
#include "graphics/ModelDef.h"
#include "renderer/FixedFunctionModelRenderer.h"
#include "renderer/Renderer.h"
#include "renderer/RenderModifiers.h"
#include "renderer/VertexArray.h"
#define LOG_CATEGORY "graphics"
///////////////////////////////////////////////////////////////////////////////////////////////
// FixedFunctionModelRenderer implementation
struct FFModelDef : public CModelDefRPrivate
{
/// Indices are the same for all models, so share them
u16* m_Indices;
/// Static per-CModelDef vertex array
VertexArray m_Array;
/// UV coordinates are stored in the static array
VertexArray::Attribute m_UV;
FFModelDef(CModelDefPtr mdef);
~FFModelDef() { delete[] m_Indices; }
};
FFModelDef::FFModelDef(CModelDefPtr mdef)
: m_Array(false)
{
size_t numVertices = mdef->GetNumVertices();
m_UV.type = GL_FLOAT;
m_UV.elems = 2;
m_Array.AddAttribute(&m_UV);
m_Array.SetNumVertices(numVertices);
m_Array.Layout();
VertexArrayIterator<float[2]> UVit = m_UV.GetIterator<float[2]>();
ModelRenderer::BuildUV(mdef, UVit);
m_Array.Upload();
m_Array.FreeBackingStore();
m_Indices = new u16[mdef->GetNumFaces()*3];
ModelRenderer::BuildIndices(mdef, m_Indices);
}
struct FFModel
{
/// Dynamic per-CModel vertex array
VertexArray m_Array;
/// Position and lighting are recalculated on CPU every frame
VertexArray::Attribute m_Position;
VertexArray::Attribute m_Color;
FFModel() : m_Array(true) { }
};
struct FixedFunctionModelRendererInternals
{
/// Transformed vertex normals - required for recalculating lighting on skinned models
std::vector<CVector3D> normals;
/// Previously prepared modeldef
FFModelDef* ffmodeldef;
};
// Construction and Destruction
FixedFunctionModelRenderer::FixedFunctionModelRenderer()
{
m = new FixedFunctionModelRendererInternals;
m->ffmodeldef = 0;
}
FixedFunctionModelRenderer::~FixedFunctionModelRenderer()
{
delete m;
}
// Build model data (and modeldef data if necessary)
void* FixedFunctionModelRenderer::CreateModelData(CModel* model)
{
CModelDefPtr mdef = model->GetModelDef();
FFModelDef* ffmodeldef = (FFModelDef*)mdef->GetRenderData(m);
if (!ffmodeldef)
{
ffmodeldef = new FFModelDef(mdef);
mdef->SetRenderData(m, ffmodeldef);
}
// Build the per-model data
FFModel* ffmodel = new FFModel;
ffmodel->m_Position.type = GL_FLOAT;
ffmodel->m_Position.elems = 3;
ffmodel->m_Array.AddAttribute(&ffmodel->m_Position);
ffmodel->m_Color.type = GL_UNSIGNED_BYTE;
ffmodel->m_Color.elems = 4;
ffmodel->m_Array.AddAttribute(&ffmodel->m_Color);
ffmodel->m_Array.SetNumVertices(mdef->GetNumVertices());
ffmodel->m_Array.Layout();
return ffmodel;
}
// Fill in and upload dynamic vertex array
void FixedFunctionModelRenderer::UpdateModelData(CModel* model, void* data, u32 updateflags)
{
FFModel* ffmodel = (FFModel*)data;
if (updateflags & RENDERDATA_UPDATE_VERTICES)
{
CModelDefPtr mdef = model->GetModelDef();
size_t numVertices = mdef->GetNumVertices();
// build vertices
if (m->normals.size() < numVertices)
m->normals.resize(numVertices);
VertexArrayIterator<CVector3D> Position = ffmodel->m_Position.GetIterator<CVector3D>();
VertexArrayIterator<CVector3D> Normal = VertexArrayIterator<CVector3D>((char*)&m->normals[0], sizeof(CVector3D));
ModelRenderer::BuildPositionAndNormals(model, Position, Normal);
VertexArrayIterator<SColor4ub> Color = ffmodel->m_Color.GetIterator<SColor4ub>();
ModelRenderer::BuildColor4ub(model, Normal, Color);
// upload everything to vertex buffer
ffmodel->m_Array.Upload();
}
}
// Cleanup per-model data.
// Note that per-CModelDef data is deleted by the CModelDef itself.
void FixedFunctionModelRenderer::DestroyModelData(CModel* UNUSED(model), void* data)
{
FFModel* ffmodel = (FFModel*)data;
delete ffmodel;
}
// Setup one rendering pass
void FixedFunctionModelRenderer::BeginPass(uint streamflags)
{
glEnableClientState(GL_VERTEX_ARRAY);
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (streamflags & STREAM_COLOR) glEnableClientState(GL_COLOR_ARRAY);
}
// Cleanup one rendering pass
void FixedFunctionModelRenderer::EndPass(uint streamflags)
{
if (streamflags & STREAM_UV0) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (streamflags & STREAM_COLOR) glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
// Prepare UV coordinates for this modeldef
void FixedFunctionModelRenderer::PrepareModelDef(uint streamflags, CModelDefPtr def)
{
m->ffmodeldef = (FFModelDef*)def->GetRenderData(m);
debug_assert(m->ffmodeldef);
if (streamflags & STREAM_UV0)
{
u8* base = m->ffmodeldef->m_Array.Bind();
GLsizei stride = (GLsizei)m->ffmodeldef->m_Array.GetStride();
glTexCoordPointer(2, GL_FLOAT, stride, base + m->ffmodeldef->m_UV.offset);
}
}
// Render one model
void FixedFunctionModelRenderer::RenderModel(uint streamflags, CModel* model, void* data)
{
CModelDefPtr mdldef = model->GetModelDef();
FFModel* ffmodel = (FFModel*)data;
u8* base = ffmodel->m_Array.Bind();
GLsizei stride = (GLsizei)ffmodel->m_Array.GetStride();
glVertexPointer(3, GL_FLOAT, stride, base + ffmodel->m_Position.offset);
if (streamflags & STREAM_COLOR)
glColorPointer(3, ffmodel->m_Color.type, stride, base + ffmodel->m_Color.offset);
// render the lot
size_t numFaces = mdldef->GetNumFaces();
pglDrawRangeElementsEXT(GL_TRIANGLES, 0, (GLuint)mdldef->GetNumVertices(),
(GLsizei)numFaces*3, GL_UNSIGNED_SHORT, m->ffmodeldef->m_Indices);
// bump stats
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_ModelTris += numFaces;
}