mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- implement model vertex buffer and draw MD2 models using it instead of using the GLCommands from the model.
This commit is contained in:
parent
2cd1118aad
commit
1efc2938b7
10 changed files with 122 additions and 137 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -93,6 +93,7 @@ void FSkyVertexBuffer::BindVBO()
|
|||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glDisableVertexAttribArray(VATTR_VERTEX2);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue