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

View file

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

View file

@ -59,6 +59,7 @@
#include "gl/utility/gl_geometric.h" #include "gl/utility/gl_geometric.h"
#include "gl/utility/gl_convert.h" #include "gl/utility/gl_convert.h"
#include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderstate.h"
#include "gl/shaders/gl_shader.h"
static inline float GetTimeFloat() static inline float GetTimeFloat()
{ {
@ -91,6 +92,76 @@ public:
DeletingModelArray Models; 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 TArray<FSpriteModelFrame> SpriteModelFrames;
static int * SpriteModelHash; static int * SpriteModelHash;
//TArray<FStateModelFrame> StateModelFrames; //TArray<FStateModelFrame> StateModelFrames;
@ -674,10 +745,14 @@ void gl_RenderFrameModels( const FSpriteModelFrame *smf,
if (mdl!=NULL) if (mdl!=NULL)
{ {
gl_RenderState.SetVertexBuffer(GLRenderer->mModelVBO);
if ( smfNext && smf->modelframes[i] != smfNext->modelframes[i] ) if ( smfNext && smf->modelframes[i] != smfNext->modelframes[i] )
mdl->RenderFrame(smf->skins[i], smf->modelframes[i], smfNext->modelframes[i], inter, translation); mdl->RenderFrame(smf->skins[i], smf->modelframes[i], smfNext->modelframes[i], inter, translation);
else 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 struct DMDLoD
{ {
FTriangle * triangles; FTriangle * triangles;
int * glCommands;
}; };
@ -116,27 +115,24 @@ protected:
DMDInfo info; DMDInfo info;
FTexture ** skins; FTexture ** skins;
FTexCoord * texCoords; FTexCoord * texCoords;
unsigned int ib_index;
unsigned int ib_count;
ModelFrame * frames; ModelFrame * frames;
DMDLoDInfo lodInfo[MAX_LODS]; DMDLoDInfo lodInfo[MAX_LODS];
DMDLoD lods[MAX_LODS]; DMDLoD lods[MAX_LODS];
char *vertexUsage; // Bitfield for each vertex.
bool allowTexComp; // Allow texture compression with this. bool allowTexComp; // Allow texture compression with this.
static void RenderGLCommands(void *glCommands, unsigned int numVertices,DMDModelVertex * vertices, DMDModelVertex *vertices2, double inter);
public: public:
FDMDModel() FDMDModel()
{ {
loaded = false; loaded = false;
frames = NULL; frames = NULL;
skins = NULL; skins = NULL;
lods[0].glCommands = NULL; for (int i = 0; i < MAX_LODS; i++)
{
lods[i].triangles = NULL;
}
info.numLODs = 0; info.numLODs = 0;
ib_count = 0; texCoords = NULL;
} }
virtual ~FDMDModel(); virtual ~FDMDModel();
@ -195,6 +191,7 @@ class FMD3Model : public FModel
unsigned int vindex; // contains numframes arrays of vertices unsigned int vindex; // contains numframes arrays of vertices
unsigned int iindex; unsigned int iindex;
unsigned int icount;
MD3Surface() MD3Surface()
{ {

View file

@ -43,11 +43,13 @@
#include "sc_man.h" #include "sc_man.h"
#include "m_crc32.h" #include "m_crc32.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderstate.h"
#include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_drawinfo.h"
#include "gl/models/gl_models.h" #include "gl/models/gl_models.h"
#include "gl/textures/gl_material.h" #include "gl/textures/gl_material.h"
#include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_shader.h"
#include "gl/data/gl_vertexbuffer.h"
static float avertexnormals[NUMVERTEXNORMALS][3] = { static float avertexnormals[NUMVERTEXNORMALS][3] = {
#include "tab_anorms.h" #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); 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; temp = (char*)buffer + info.offsetFrames;
frames = new ModelFrame[info.numFrames]; frames = new ModelFrame[info.numFrames];
ib_count = 0;
for(i = 0, frame = frames; i < info.numFrames; i++, frame++) 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++) for(i = 0; i < info.numLODs; i++)
{ {
lodInfo[i].numTriangles = LittleLong(lodInfo[i].numTriangles); lodInfo[i].numTriangles = LittleLong(lodInfo[i].numTriangles);
lodInfo[i].numGlCommands = LittleLong(lodInfo[i].numGlCommands);
lodInfo[i].offsetTriangles = LittleLong(lodInfo[i].offsetTriangles); lodInfo[i].offsetTriangles = LittleLong(lodInfo[i].offsetTriangles);
lodInfo[i].offsetGlCommands = LittleLong(lodInfo[i].offsetGlCommands);
triangles[i] = (FTriangle*)(buffer + lodInfo[i].offsetTriangles); lods[i].triangles = 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);
} }
// 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; loaded=true;
return true; return true;
} }
@ -240,10 +229,10 @@ FDMDModel::~FDMDModel()
for(i = 0; i < info.numLODs; i++) 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]; ModelFrame *frame = &frames[i];
DMDModelVertex *vert = frame->vertices; DMDModelVertex *vert = frame->vertices;
DMDModelVertex *norm = frame->normals; DMDModelVertex *norm = frame->normals;
void *glCommands = lods[0].glCommands;
frame->vindex = buf->vbo_shadowdata.Size(); 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; for (int j = 0; j < 3; j++)
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--)
{ {
FModelVertex bvert; FModelVertex bvert;
FGLCommandVertex * v = (FGLCommandVertex *)pos; int ti = tri->textureIndices[j];
pos += sizeof(FGLCommandVertex); 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.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[v->index].xyz[0], norm[v->index].xyz[1], norm[v->index].xyz[2]); bvert.SetNormal(norm[vi].xyz[0], norm[vi].xyz[1], norm[vi].xyz[2]);
buf->vbo_shadowdata.Push(bvert); buf->vbo_shadowdata.Push(bvert);
} }
tri++;
} }
} }
} }
//=========================================================================== //===========================================================================
// //
// FDMDModel::FindFrame // 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) void FDMDModel::RenderFrame(FTexture * skin, int frameno, int frameno2, double inter, int translation)
{ {
if (frameno >= info.numFrames || frameno2 >= info.numFrames) return; 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); 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.magic = MD2_MAGIC;
header.version = 8; header.version = 8;
header.flags = 0; header.flags = 0;
vertexUsage = NULL;
info.skinWidth = LittleLong(md2header->skinWidth); info.skinWidth = LittleLong(md2header->skinWidth);
info.skinHeight = LittleLong(md2header->skinHeight); info.skinHeight = LittleLong(md2header->skinHeight);
info.frameSize = LittleLong(md2header->frameSize); 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. // The frames need to be unpacked.
md2_frames = (byte*)buffer + info.offsetFrames; md2_frames = (byte*)buffer + info.offsetFrames;
frames = new ModelFrame[info.numFrames]; 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++) for(i = 0, frame = frames; i < info.numFrames; i++, frame++)
{ {
md2_packedFrame_t *pfr = (md2_packedFrame_t *) (md2_frames + info.frameSize * i); 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]; lods[0].triangles = new FTriangle[lodInfo[0].numTriangles];
memcpy(lods[0].glCommands, buffer + lodInfo[0].offsetGlCommands, sizeof(int) * lodInfo[0].numGlCommands);
memcpy(lods[0].triangles, buffer + lodInfo[0].offsetTriangles, sizeof(FTriangle) * lodInfo[0].numTriangles);
skins = new FTexture *[info.numSkins]; 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]); 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; mVBO = new FFlatVertexBuffer;
mSkyVBO = new FSkyVertexBuffer; mSkyVBO = new FSkyVertexBuffer;
mModelVBO = new FModelVertexBuffer;
gl_RenderState.SetVertexBuffer(mVBO); gl_RenderState.SetVertexBuffer(mVBO);
mFBID = 0; mFBID = 0;
SetupLevel(); SetupLevel();
@ -123,6 +124,7 @@ FGLRenderer::~FGLRenderer()
//if (mThreadManager != NULL) delete mThreadManager; //if (mThreadManager != NULL) delete mThreadManager;
if (mShaderManager != NULL) delete mShaderManager; if (mShaderManager != NULL) delete mShaderManager;
if (mVBO != NULL) delete mVBO; if (mVBO != NULL) delete mVBO;
if (mModelVBO) delete mModelVBO;
if (mSkyVBO != NULL) delete mSkyVBO; if (mSkyVBO != NULL) delete mSkyVBO;
if (glpart2) delete glpart2; if (glpart2) delete glpart2;
if (glpart) delete glpart; if (glpart) delete glpart;

View file

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

View file

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

View file

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