From 59448941389c01f1b7fcfc2d9b89f28d5e8781b5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 19 Jun 2014 17:06:26 +0200 Subject: [PATCH] - create vertex buffer data for MD2/DMD models. --- src/gl/data/gl_vertexbuffer.h | 7 +++ src/gl/models/gl_models.h | 15 +++-- src/gl/models/gl_models_md2.cpp | 98 +++++++++++++++++++++++++++++++-- 3 files changed, 111 insertions(+), 9 deletions(-) diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index f82172d08d..ad09fb5d95 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -182,6 +182,11 @@ struct FModelVertex u = uu; v = vv; } + + void SetNormal(float nx, float ny, float nz) + { + // GZDoom currently doesn't use normals. This function is so that the high level code can pretend it does. + } }; @@ -190,7 +195,9 @@ class FModelVertexBuffer : public FVertexBuffer int mIndexFrame[2]; public: + // these are public because it's the models having to fill them in. TArray vbo_shadowdata; // this is kept around for interpolating on GL 2.0 + TArray ibo_shadowdata; // this is kept around for interpolating on GL 2.0 FModelVertexBuffer(); ~FModelVertexBuffer(); diff --git a/src/gl/models/gl_models.h b/src/gl/models/gl_models.h index 7b32be085d..cc900649bb 100644 --- a/src/gl/models/gl_models.h +++ b/src/gl/models/gl_models.h @@ -30,6 +30,7 @@ public: virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0; virtual int FindFrame(const char * name) = 0; virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0) = 0; + virtual void BuildVertexBuffer(FModelVertexBuffer *buf); @@ -54,7 +55,7 @@ protected: int flags; }; - struct FModelVertex + struct DMDModelVertex { float xyz[3]; }; @@ -90,8 +91,9 @@ protected: struct ModelFrame { char name[16]; - FModelVertex *vertices; - FModelVertex *normals; + DMDModelVertex *vertices; + DMDModelVertex *normals; + unsigned int vindex; }; struct DMDLoDInfo @@ -114,6 +116,9 @@ protected: DMDInfo info; FTexture ** skins; FTexCoord * texCoords; + + unsigned int ib_index; + unsigned int ib_count; ModelFrame * frames; DMDLoDInfo lodInfo[MAX_LODS]; @@ -121,7 +126,7 @@ protected: char *vertexUsage; // Bitfield for each vertex. bool allowTexComp; // Allow texture compression with this. - static void RenderGLCommands(void *glCommands, unsigned int numVertices,FModelVertex * vertices, FModelVertex *vertices2, double inter); + static void RenderGLCommands(void *glCommands, unsigned int numVertices,DMDModelVertex * vertices, DMDModelVertex *vertices2, double inter); public: FDMDModel() @@ -131,12 +136,14 @@ public: skins = NULL; lods[0].glCommands = NULL; info.numLODs = 0; + ib_count = 0; } virtual ~FDMDModel(); virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length); virtual int FindFrame(const char * name); virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); + virtual void BuildVertexBuffer(FModelVertexBuffer *buf); }; diff --git a/src/gl/models/gl_models_md2.cpp b/src/gl/models/gl_models_md2.cpp index 8fa8310f7a..ccf604dca4 100644 --- a/src/gl/models/gl_models_md2.cpp +++ b/src/gl/models/gl_models_md2.cpp @@ -163,6 +163,7 @@ bool FDMDModel::Load(const char * path, int, const char * buffer, int length) temp = (char*)buffer + info.offsetFrames; frames = new ModelFrame[info.numFrames]; + ib_count = 0; for(i = 0, frame = frames; i < info.numFrames; i++, frame++) { @@ -170,8 +171,9 @@ bool FDMDModel::Load(const char * path, int, const char * buffer, int length) dmd_packedVertex_t *pVtx; memcpy(frame->name, pfr->name, sizeof(pfr->name)); - frame->vertices = new FModelVertex[info.numVertices]; - frame->normals = new FModelVertex[info.numVertices]; + frame->vertices = new DMDModelVertex[info.numVertices]; + frame->normals = new DMDModelVertex[info.numVertices]; + frame->vindex = UINT_MAX; // Translate each vertex. for(k = 0, pVtx = pfr->vertices; k < info.numVertices; k++, pVtx++) @@ -244,6 +246,91 @@ FDMDModel::~FDMDModel() if (vertexUsage != NULL) delete [] vertexUsage; } + +void FDMDModel::BuildVertexBuffer(FModelVertexBuffer *buf) +{ + for (int i = 0; i < info.numFrames; i++) + { + 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;) + { + 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--) + { + FModelVertex bvert; + + FGLCommandVertex * v = (FGLCommandVertex *)pos; + pos += sizeof(FGLCommandVertex); + + 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]); + buf->vbo_shadowdata.Push(bvert); + } + } + } +} + + + + + + + + + + //=========================================================================== // // FDMDModel::FindFrame @@ -264,7 +351,7 @@ int FDMDModel::FindFrame(const char * name) // //=========================================================================== -void FDMDModel::RenderGLCommands(void *glCommands, unsigned int numVertices, FModelVertex * vertices, FModelVertex *vertices2, double inter) +void FDMDModel::RenderGLCommands(void *glCommands, unsigned int numVertices, DMDModelVertex * vertices, DMDModelVertex *vertices2, double inter) { char *pos; FGLCommandVertex * v; @@ -418,8 +505,9 @@ bool FMD2Model::Load(const char * path, int, const char * buffer, int length) md2_triangleVertex_t *pVtx; memcpy(frame->name, pfr->name, sizeof(pfr->name)); - frame->vertices = new FModelVertex[info.numVertices]; - frame->normals = new FModelVertex[info.numVertices]; + frame->vertices = new DMDModelVertex[info.numVertices]; + frame->normals = new DMDModelVertex[info.numVertices]; + frame->vindex = UINT_MAX; // Translate each vertex. for(k = 0, pVtx = pfr->vertices; k < info.numVertices; k++, pVtx++)