- implement model vertex buffer and draw MD2 models using it instead of using the GLCommands from the model.

This commit is contained in:
Christoph Oelckers 2014-06-29 23:24:16 +02:00
parent 2cd1118aad
commit 1efc2938b7
10 changed files with 122 additions and 137 deletions

View file

@ -45,6 +45,7 @@
#include "c_cvars.h"
#include "gl/system/gl_interface.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/shaders/gl_shader.h"
#include "gl/data/gl_data.h"
#include "gl/data/gl_vertexbuffer.h"
@ -332,6 +333,7 @@ void FFlatVertexBuffer::BindVBO()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableVertexAttribArray(VATTR_VERTEX2);
}
}

View file

@ -193,6 +193,7 @@ struct FModelVertex
class FModelVertexBuffer : public FVertexBuffer
{
int mIndexFrame[2];
unsigned int ibo_id;
public:
// these are public because it's the models having to fill them in.
@ -203,7 +204,7 @@ public:
~FModelVertexBuffer();
void BindVBO();
void UpdateBufferPointers(int frame1, int frame2);
unsigned int SetupFrame(unsigned int frame1, unsigned int frame2, float factor);
};
#define VMO ((FModelVertex*)NULL)

View file

@ -59,6 +59,7 @@
#include "gl/utility/gl_geometric.h"
#include "gl/utility/gl_convert.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/shaders/gl_shader.h"
static inline float GetTimeFloat()
{
@ -91,6 +92,76 @@ public:
DeletingModelArray Models;
//===========================================================================
//
//
//
//===========================================================================
FModelVertexBuffer::FModelVertexBuffer()
{
ibo_id = 0;
glGenBuffers(1, &ibo_id);
//for (unsigned i = 1; i < Models.Size(); i++)
for (int i = Models.Size() - 1; i >= 0; i--)
{
Models[i]->BuildVertexBuffer(this);
}
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glBufferData(GL_ARRAY_BUFFER,vbo_shadowdata.Size() * sizeof(FModelVertex), &vbo_shadowdata[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,ibo_shadowdata.Size() * sizeof(unsigned int), &ibo_shadowdata[0], GL_STATIC_DRAW);
}
FModelVertexBuffer::~FModelVertexBuffer()
{
if (ibo_id != 0)
{
glDeleteBuffers(1, &ibo_id);
}
}
//===========================================================================
//
//
//
//===========================================================================
void FModelVertexBuffer::BindVBO()
{
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id);
//glVertexPointer(3, GL_FLOAT, sizeof(FModelVertex), &VMO->x);
//glTexCoordPointer(2, GL_FLOAT, sizeof(FModelVertex), &VMO->u);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glEnableVertexAttribArray(VATTR_VERTEX2);
}
//===========================================================================
//
// Sets up the buffer starts for frame interpolation
// This must be called after gl_RenderState.Apply!
//
//===========================================================================
unsigned int FModelVertexBuffer::SetupFrame(unsigned int frame1, unsigned int frame2, float factor)
{
glVertexPointer(3, GL_FLOAT, sizeof(FModelVertex), &VMO[frame1].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(FModelVertex), &VMO[frame1].u);
glVertexAttribPointer(VATTR_VERTEX2, 3, GL_FLOAT, false, sizeof(FModelVertex), &VMO[frame2].x);
return frame1;
}
static TArray<FSpriteModelFrame> SpriteModelFrames;
static int * SpriteModelHash;
//TArray<FStateModelFrame> StateModelFrames;
@ -674,10 +745,14 @@ void gl_RenderFrameModels( const FSpriteModelFrame *smf,
if (mdl!=NULL)
{
gl_RenderState.SetVertexBuffer(GLRenderer->mModelVBO);
if ( smfNext && smf->modelframes[i] != smfNext->modelframes[i] )
mdl->RenderFrame(smf->skins[i], smf->modelframes[i], smfNext->modelframes[i], inter, translation);
else
mdl->RenderFrame(smf->skins[i], smf->modelframes[i], NULL, 0.f, translation);
mdl->RenderFrame(smf->skins[i], smf->modelframes[i], smf->modelframes[i], 0.f, translation);
gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
}
}
}

View file

@ -107,7 +107,6 @@ protected:
struct DMDLoD
{
FTriangle * triangles;
int * glCommands;
};
@ -116,27 +115,24 @@ protected:
DMDInfo info;
FTexture ** skins;
FTexCoord * texCoords;
unsigned int ib_index;
unsigned int ib_count;
ModelFrame * frames;
DMDLoDInfo lodInfo[MAX_LODS];
DMDLoD lods[MAX_LODS];
char *vertexUsage; // Bitfield for each vertex.
bool allowTexComp; // Allow texture compression with this.
static void RenderGLCommands(void *glCommands, unsigned int numVertices,DMDModelVertex * vertices, DMDModelVertex *vertices2, double inter);
public:
FDMDModel()
{
loaded = false;
frames = NULL;
skins = NULL;
lods[0].glCommands = NULL;
for (int i = 0; i < MAX_LODS; i++)
{
lods[i].triangles = NULL;
}
info.numLODs = 0;
ib_count = 0;
texCoords = NULL;
}
virtual ~FDMDModel();
@ -195,6 +191,7 @@ class FMD3Model : public FModel
unsigned int vindex; // contains numframes arrays of vertices
unsigned int iindex;
unsigned int icount;
MD3Surface()
{

View file

@ -43,11 +43,13 @@
#include "sc_man.h"
#include "m_crc32.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderstate.h"
#include "gl/scene/gl_drawinfo.h"
#include "gl/models/gl_models.h"
#include "gl/textures/gl_material.h"
#include "gl/shaders/gl_shader.h"
#include "gl/data/gl_vertexbuffer.h"
static float avertexnormals[NUMVERTEXNORMALS][3] = {
#include "tab_anorms.h"
@ -160,10 +162,11 @@ bool FDMDModel::Load(const char * path, int, const char * buffer, int length)
skins[i] = LoadSkin(path, buffer + info.offsetSkins + i*64);
}
texCoords = new FTexCoord[info.numTexCoords];
memcpy(texCoords, (byte*)buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord));
temp = (char*)buffer + info.offsetFrames;
frames = new ModelFrame[info.numFrames];
ib_count = 0;
for(i = 0, frame = frames; i < info.numFrames; i++, frame++)
{
@ -193,25 +196,11 @@ bool FDMDModel::Load(const char * path, int, const char * buffer, int length)
for(i = 0; i < info.numLODs; i++)
{
lodInfo[i].numTriangles = LittleLong(lodInfo[i].numTriangles);
lodInfo[i].numGlCommands = LittleLong(lodInfo[i].numGlCommands);
lodInfo[i].offsetTriangles = LittleLong(lodInfo[i].offsetTriangles);
lodInfo[i].offsetGlCommands = LittleLong(lodInfo[i].offsetGlCommands);
triangles[i] = (FTriangle*)(buffer + lodInfo[i].offsetTriangles);
lods[i].glCommands = new int[lodInfo[i].numGlCommands];
memcpy(lods[i].glCommands, buffer + lodInfo[i].offsetGlCommands, sizeof(int) * lodInfo[i].numGlCommands);
lods[i].triangles = triangles[i] = (FTriangle*)(buffer + lodInfo[i].offsetTriangles);
}
// Determine vertex usage at each LOD level.
vertexUsage = new char[info.numVertices];
memset(vertexUsage, 0, info.numVertices);
for(i = 0; i < info.numLODs; i++)
for(k = 0; k < lodInfo[i].numTriangles; k++)
for(c = 0; c < 3; c++)
vertexUsage[short(triangles[i][k].vertexIndices[c])] |= 1 << i;
loaded=true;
return true;
}
@ -240,10 +229,10 @@ FDMDModel::~FDMDModel()
for(i = 0; i < info.numLODs; i++)
{
delete [] lods[i].glCommands;
if (lods[i].triangles != NULL) delete[] lods[i].triangles;
}
if (vertexUsage != NULL) delete [] vertexUsage;
if (texCoords != NULL) delete[] texCoords;
}
@ -254,83 +243,33 @@ void FDMDModel::BuildVertexBuffer(FModelVertexBuffer *buf)
ModelFrame *frame = &frames[i];
DMDModelVertex *vert = frame->vertices;
DMDModelVertex *norm = frame->normals;
void *glCommands = lods[0].glCommands;
frame->vindex = buf->vbo_shadowdata.Size();
for (char *pos = (char*)glCommands; *pos;)
FTriangle *tri = lods[0].triangles;
for (int i = 0; i < lodInfo[0].numTriangles; i++)
{
int count = *(int *)pos;
pos += 4;
// The type of primitive depends on the sign.
int primtype = count > 0 ? GL_TRIANGLE_STRIP : GL_TRIANGLE_FAN;
count = abs(count);
if (i == 0)
{
// build the index buffer - we'll use the same buffer for all frames so only create it once
unsigned int bufindex = buf->vbo_shadowdata.Size() - frame->vindex;
unsigned int bufp = bufindex;
if (primtype == GL_TRIANGLE_STRIP)
{
for (int t = 0; t < count - 2; t++)
{
unsigned int *p = &buf->ibo_shadowdata[buf->ibo_shadowdata.Reserve(3)];
if ((t & 1) == 0)
{
p[0] = bufp;
p[1] = bufp + 1;
p[2] = bufp + 2;
}
else
{
p[0] = bufp;
p[2] = bufp + 2;
p[1] = bufp + 1;
}
bufp++;
}
}
else
{
bufp++;
for (int t = 0; t < count - 2; t++)
{
unsigned int *p = &buf->ibo_shadowdata[buf->ibo_shadowdata.Reserve(3)];
p[0] = bufindex;
p[1] = bufp;
p[2] = bufp + 1;
bufp++;
}
}
}
while (count--)
for (int j = 0; j < 3; j++)
{
FModelVertex bvert;
FGLCommandVertex * v = (FGLCommandVertex *)pos;
pos += sizeof(FGLCommandVertex);
int ti = tri->textureIndices[j];
int vi = tri->vertexIndices[j];
bvert.Set(vert[v->index].xyz[0], vert[v->index].xyz[1], vert[v->index].xyz[2], v->s, v->t);
bvert.SetNormal(norm[v->index].xyz[0], norm[v->index].xyz[1], norm[v->index].xyz[2]);
bvert.Set(vert[vi].xyz[0], vert[vi].xyz[1], vert[vi].xyz[2], (float)texCoords[ti].s /info.skinWidth, (float)texCoords[ti].t/info.skinHeight);
bvert.SetNormal(norm[vi].xyz[0], norm[vi].xyz[1], norm[vi].xyz[2]);
buf->vbo_shadowdata.Push(bvert);
}
tri++;
}
}
}
//===========================================================================
//
// FDMDModel::FindFrame
@ -347,50 +286,10 @@ int FDMDModel::FindFrame(const char * name)
//===========================================================================
//
// Render a set of GL commands using the given data.
//
//
//===========================================================================
void FDMDModel::RenderGLCommands(void *glCommands, unsigned int numVertices, DMDModelVertex * vertices, DMDModelVertex *vertices2, double inter)
{
char *pos;
FGLCommandVertex * v;
int count;
const bool interpolate = (vertices2 != NULL && inter != 0. && vertices != vertices2);
gl_RenderState.Apply();
for(pos = (char*)glCommands; *pos;)
{
count = *(int *) pos;
pos += 4;
// The type of primitive depends on the sign.
glBegin(count > 0 ? GL_TRIANGLE_STRIP : GL_TRIANGLE_FAN);
count = abs(count);
while (count--)
{
v = (FGLCommandVertex *)pos;
pos += sizeof(FGLCommandVertex);
glTexCoord2fv(&v->s);
if (!interpolate)
{
glVertex3fv(vertices[v->index].xyz);
}
else
{
float interp[3];
for (int i = 0; i < 3; i++)
interp[i] = inter * vertices[v->index].xyz[i] + (1. - inter) * vertices2[v->index].xyz[i];
glVertex3fv(interp);
}
}
glEnd();
}
}
void FDMDModel::RenderFrame(FTexture * skin, int frameno, int frameno2, double inter, int translation)
{
if (frameno >= info.numFrames || frameno2 >= info.numFrames) return;
@ -406,7 +305,9 @@ void FDMDModel::RenderFrame(FTexture * skin, int frameno, int frameno2, double i
tex->Bind(0, translation);
RenderGLCommands(lods[0].glCommands, info.numVertices, frames[frameno].vertices, frames[frameno2].vertices, inter);
gl_RenderState.Apply();
GLRenderer->mModelVBO->SetupFrame(frames[frameno].vindex, frames[frameno2].vindex, inter);
glDrawArrays(GL_TRIANGLES, 0, lodInfo[0].numTriangles * 3);
}
@ -464,7 +365,6 @@ bool FMD2Model::Load(const char * path, int, const char * buffer, int length)
header.magic = MD2_MAGIC;
header.version = 8;
header.flags = 0;
vertexUsage = NULL;
info.skinWidth = LittleLong(md2header->skinWidth);
info.skinHeight = LittleLong(md2header->skinHeight);
info.frameSize = LittleLong(md2header->frameSize);
@ -496,9 +396,12 @@ bool FMD2Model::Load(const char * path, int, const char * buffer, int length)
// The frames need to be unpacked.
md2_frames = (byte*)buffer + info.offsetFrames;
frames = new ModelFrame[info.numFrames];
texCoords = new FTexCoord[info.numTexCoords];
memcpy(texCoords, (byte*)buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord));
for(i = 0, frame = frames; i < info.numFrames; i++, frame++)
{
md2_packedFrame_t *pfr = (md2_packedFrame_t *) (md2_frames + info.frameSize * i);
@ -526,8 +429,9 @@ bool FMD2Model::Load(const char * path, int, const char * buffer, int length)
}
lods[0].glCommands = new int[lodInfo[0].numGlCommands];
memcpy(lods[0].glCommands, buffer + lodInfo[0].offsetGlCommands, sizeof(int) * lodInfo[0].numGlCommands);
lods[0].triangles = new FTriangle[lodInfo[0].numTriangles];
memcpy(lods[0].triangles, buffer + lodInfo[0].offsetTriangles, sizeof(FTriangle) * lodInfo[0].numTriangles);
skins = new FTexture *[info.numSkins];

View file

@ -233,6 +233,7 @@ void FMD3Model::BuildVertexBuffer(FModelVertexBuffer *buf)
buf->ibo_shadowdata.Push(surf->tris[k].VertIndex[l]);
}
}
surf->icount = buf->ibo_shadowdata.Size() - surf->iindex;
}
}

View file

@ -109,6 +109,7 @@ void FGLRenderer::Initialize()
mVBO = new FFlatVertexBuffer;
mSkyVBO = new FSkyVertexBuffer;
mModelVBO = new FModelVertexBuffer;
gl_RenderState.SetVertexBuffer(mVBO);
mFBID = 0;
SetupLevel();
@ -123,6 +124,7 @@ FGLRenderer::~FGLRenderer()
//if (mThreadManager != NULL) delete mThreadManager;
if (mShaderManager != NULL) delete mShaderManager;
if (mVBO != NULL) delete mVBO;
if (mModelVBO) delete mModelVBO;
if (mSkyVBO != NULL) delete mSkyVBO;
if (glpart2) delete glpart2;
if (glpart) delete glpart;

View file

@ -10,6 +10,7 @@ struct particle_t;
class FCanvasTexture;
class FFlatVertexBuffer;
class FSkyVertexBuffer;
class FModelVertexBuffer;
class OpenGLFrameBuffer;
struct FDrawInfo;
struct pspdef_t;
@ -71,6 +72,7 @@ public:
FFlatVertexBuffer *mVBO;
FSkyVertexBuffer *mSkyVBO;
FModelVertexBuffer *mModelVBO;
FGLRenderer(OpenGLFrameBuffer *fb);

View file

@ -93,6 +93,7 @@ void FSkyVertexBuffer::BindVBO()
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisableVertexAttribArray(VATTR_VERTEX2);
}

View file

@ -6,7 +6,7 @@ out vec2 glowdist;
void main()
{
vec4 worldcoord = mix(gl_Vertex, aVertex2, uInterpolationFactor);
vec4 worldcoord = ModelMatrix * mix(gl_Vertex, aVertex2, uInterpolationFactor);
vec4 eyeCoordPos = ViewMatrix * worldcoord;
gl_FrontColor = gl_Color;