diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index a9619876d6..12b536f105 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -197,13 +197,16 @@ class FModelVertexBuffer : public FVertexBuffer unsigned int ibo_id; 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(bool needindex); ~FModelVertexBuffer(); + FModelVertex *LockVertexBuffer(unsigned int size); + void UnlockVertexBuffer(); + + unsigned int *LockIndexBuffer(unsigned int size); + void UnlockIndexBuffer(); + unsigned int SetupFrame(unsigned int frame1, unsigned int frame2); }; diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 31d05ab416..13a1ef9c3c 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -93,35 +93,44 @@ public: DeletingModelArray Models; -//=========================================================================== -// -// -// -//=========================================================================== - -FModelVertexBuffer::FModelVertexBuffer() +void gl_LoadModels() { - 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); + Models[i]->BuildVertexBuffer(); } +} +//=========================================================================== +// +// +// +//=========================================================================== + +FModelVertexBuffer::FModelVertexBuffer(bool needindex) +{ glBindVertexArray(vao_id); - 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); + ibo_id = 0; + if (needindex) + { + glGenBuffers(1, &ibo_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); + } + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); glEnableVertexAttribArray(VATTR_VERTEX); glEnableVertexAttribArray(VATTR_TEXCOORD); glEnableVertexAttribArray(VATTR_VERTEX2); glBindVertexArray(0); } +//=========================================================================== +// +// +// +//=========================================================================== + FModelVertexBuffer::~FModelVertexBuffer() { if (ibo_id != 0) @@ -130,6 +139,63 @@ FModelVertexBuffer::~FModelVertexBuffer() } } +//=========================================================================== +// +// +// +//=========================================================================== + +FModelVertex *FModelVertexBuffer::LockVertexBuffer(unsigned int size) +{ + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glBufferData(GL_ARRAY_BUFFER, size * sizeof(FModelVertex), NULL, GL_STATIC_DRAW); + return (FModelVertex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, size * sizeof(FModelVertex), GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void FModelVertexBuffer::UnlockVertexBuffer() +{ + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glUnmapBuffer(GL_ARRAY_BUFFER); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +unsigned int *FModelVertexBuffer::LockIndexBuffer(unsigned int size) +{ + if (ibo_id != 0) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, size * sizeof(unsigned int), NULL, GL_STATIC_DRAW); + return (unsigned int*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, size * sizeof(unsigned int), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + else + { + return NULL; + } +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void FModelVertexBuffer::UnlockIndexBuffer() +{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); +} + //=========================================================================== // @@ -147,6 +213,16 @@ unsigned int FModelVertexBuffer::SetupFrame(unsigned int frame1, unsigned int fr return frame1; } +//=========================================================================== +// +// FModel::~FModel +// +//=========================================================================== + +FModel::~FModel() +{ + if (mVBuf != NULL) delete mVBuf; +} @@ -293,7 +369,7 @@ static FModel * FindModel(const char * path, const char * modelfile) return NULL; } } - + // The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized model->mFileName = fullname; Models.Push(model); return model; @@ -734,7 +810,8 @@ void gl_RenderFrameModels( const FSpriteModelFrame *smf, if (mdl!=NULL) { - gl_RenderState.SetVertexBuffer(GLRenderer->mModelVBO); + mdl->BuildVertexBuffer(); + gl_RenderState.SetVertexBuffer(mdl->mVBuf); if ( smfNext && smf->modelframes[i] != smfNext->modelframes[i] ) mdl->RenderFrame(smf->skins[i], smf->modelframes[i], smfNext->modelframes[i], inter, translation); diff --git a/src/gl/models/gl_models.h b/src/gl/models/gl_models.h index d608f9874c..b80a11df44 100644 --- a/src/gl/models/gl_models.h +++ b/src/gl/models/gl_models.h @@ -24,16 +24,19 @@ FTexture * LoadSkin(const char * path, const char * fn); class FModel { public: - FModel() { } - virtual ~FModel() { } + + FModel() + { + mVBuf = NULL; + } + virtual ~FModel(); 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) = 0; - - + virtual void BuildVertexBuffer() = 0; + FModelVertexBuffer *mVBuf; FString mFileName; }; @@ -139,7 +142,8 @@ public: 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); + void BuildVertexBuffer(); + void CleanTempData(); }; @@ -201,11 +205,19 @@ class FMD3Model : public FModel } ~MD3Surface() + { + if (skins) delete [] skins; + CleanTempData(); + } + + void CleanTempData() { if (tris) delete [] tris; if (vertices) delete [] vertices; if (texcoords) delete [] texcoords; - if (skins) delete [] skins; + tris = NULL; + vertices = NULL; + texcoords = NULL; } }; @@ -231,7 +243,7 @@ public: 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); + void BuildVertexBuffer(); }; struct FVoxelVertexHash @@ -268,11 +280,10 @@ class FVoxelModel : public FModel protected: FVoxel *mVoxel; bool mOwningVoxel; // if created through MODELDEF deleting this object must also delete the voxel object + FTexture *mPalette; + unsigned int mNumIndices; TArray mVertices; TArray mIndices; - FTexture *mPalette; - unsigned int vindex; - unsigned int iindex; void MakeSlabPolys(int x, int y, kvxslab_t *voxptr, FVoxelMap &check); void AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int x4, int y4, int z4, BYTE color, FVoxelMap &check); @@ -286,7 +297,7 @@ public: virtual int FindFrame(const char * name); virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); FTexture *GetPaletteTexture() const { return mPalette; } - void BuildVertexBuffer(FModelVertexBuffer *buf); + void BuildVertexBuffer(); }; diff --git a/src/gl/models/gl_models_md2.cpp b/src/gl/models/gl_models_md2.cpp index 33548f2e69..3d01ade211 100644 --- a/src/gl/models/gl_models_md2.cpp +++ b/src/gl/models/gl_models_md2.cpp @@ -206,65 +206,97 @@ bool FDMDModel::Load(const char * path, int, const char * buffer, int length) } +//=========================================================================== +// +// +// +//=========================================================================== + FDMDModel::~FDMDModel() { - int i; + CleanTempData(); - // clean up - if (skins != NULL) - { - // skins are managed by the texture manager so they must not be deleted here. - delete [] skins; - } + // skins are managed by the texture manager so they must not be deleted here. + if (skins != NULL) delete [] skins; + if (frames != NULL) delete [] frames; +} + +//=========================================================================== +// +// Deletes everything that's no longer needed after building the vertex buffer +// +//=========================================================================== + +void FDMDModel::CleanTempData() +{ + int i; if (frames != NULL) { for (i=0;ivertices; - DMDModelVertex *norm = frame->normals; + int VertexBufferSize = info.numFrames * lodInfo[0].numTriangles * 3; + unsigned int vindex = 0; - frame->vindex = buf->vbo_shadowdata.Size(); + mVBuf = new FModelVertexBuffer(false); + FModelVertex *vertptr = mVBuf->LockVertexBuffer(VertexBufferSize); - - FTriangle *tri = lods[0].triangles; - - for (int i = 0; i < lodInfo[0].numTriangles; i++) + for (int i = 0; i < info.numFrames; i++) { - for (int j = 0; j < 3; j++) + ModelFrame *frame = &frames[i]; + DMDModelVertex *vert = frame->vertices; + DMDModelVertex *norm = frame->normals; + + frame->vindex = vindex; + + + FTriangle *tri = lods[0].triangles; + + for (int i = 0; i < lodInfo[0].numTriangles; i++) { - FModelVertex bvert; + for (int j = 0; j < 3; j++) + { - int ti = tri->textureIndices[j]; - int vi = tri->vertexIndices[j]; + int ti = tri->textureIndices[j]; + int vi = tri->vertexIndices[j]; - 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); + FModelVertex *bvert = &vertptr[vindex++]; + 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]); + } + tri++; } - tri++; } - + mVBuf->UnlockVertexBuffer(); + CleanTempData(); } } @@ -307,7 +339,7 @@ void FDMDModel::RenderFrame(FTexture * skin, int frameno, int frameno2, double i gl_RenderState.SetInterpolationFactor((float)inter); gl_RenderState.Apply(); - GLRenderer->mModelVBO->SetupFrame(frames[frameno].vindex, frames[frameno2].vindex); + mVBuf->SetupFrame(frames[frameno].vindex, frames[frameno2].vindex); glDrawArrays(GL_TRIANGLES, 0, lodInfo[0].numTriangles * 3); gl_RenderState.SetInterpolationFactor(0.f); } diff --git a/src/gl/models/gl_models_md3.cpp b/src/gl/models/gl_models_md3.cpp index 1dbda6acd7..cdd8d70826 100644 --- a/src/gl/models/gl_models_md3.cpp +++ b/src/gl/models/gl_models_md3.cpp @@ -207,37 +207,72 @@ bool FMD3Model::Load(const char * path, int, const char * buffer, int length) return true; } -void FMD3Model::BuildVertexBuffer(FModelVertexBuffer *buf) +//=========================================================================== +// +// +// +//=========================================================================== + +void FMD3Model::BuildVertexBuffer() { - for (int i = 0; i < numSurfaces; i++) + if (mVBuf == NULL) { - MD3Surface * surf = &surfaces[i]; + unsigned int vbufsize = 0; + unsigned int ibufsize = 0; - surf->vindex = buf->vbo_shadowdata.Size(); - surf->iindex = buf->ibo_shadowdata.Size(); - for (int j = 0; j < numFrames * surf->numVertices; j++) + for (int i = 0; i < numSurfaces; i++) { - MD3Vertex* vert = surf->vertices + j; - - FModelVertex bvert; - - int tc = j % surf->numVertices; - bvert.Set(vert->x, vert->z, vert->y, surf->texcoords[tc].s, surf->texcoords[tc].t); - bvert.SetNormal(vert->nx, vert->nz, vert->ny); - buf->vbo_shadowdata.Push(bvert); + MD3Surface * surf = &surfaces[i]; + vbufsize += numFrames * surf->numVertices; + ibufsize += 3 * surf->numTriangles; } - for (int k = 0; k < surf->numTriangles; k++) + mVBuf = new FModelVertexBuffer(true); + FModelVertex *vertptr = mVBuf->LockVertexBuffer(vbufsize); + unsigned int *indxptr = mVBuf->LockIndexBuffer(ibufsize); + + assert(vertptr != NULL && indxptr != NULL); + + unsigned int vindex = 0, iindex = 0; + + for (int i = 0; i < numSurfaces; i++) { - for (int l = 0; l < 3; l++) + MD3Surface * surf = &surfaces[i]; + + surf->vindex = vindex; + surf->iindex = iindex; + for (int j = 0; j < numFrames * surf->numVertices; j++) { - buf->ibo_shadowdata.Push(surf->tris[k].VertIndex[l]); + MD3Vertex* vert = surf->vertices + j; + + FModelVertex *bvert = &vertptr[vindex++]; + + int tc = j % surf->numVertices; + bvert->Set(vert->x, vert->z, vert->y, surf->texcoords[tc].s, surf->texcoords[tc].t); + bvert->SetNormal(vert->nx, vert->nz, vert->ny); } + + for (int k = 0; k < surf->numTriangles; k++) + { + for (int l = 0; l < 3; l++) + { + indxptr[iindex++] = surf->tris[k].VertIndex[l]; + } + } + surf->CleanTempData(); } + mVBuf->UnlockVertexBuffer(); + mVBuf->UnlockIndexBuffer(); } } +//=========================================================================== +// +// +// +//=========================================================================== + int FMD3Model::FindFrame(const char * name) { for (int i=0;i=numFrames || frameno2>=numFrames) return; @@ -271,12 +312,18 @@ void FMD3Model::RenderFrame(FTexture * skin, int frameno, int frameno2, double i gl_RenderState.SetMaterial(tex, CLAMP_NONE, translation, -1, false); gl_RenderState.Apply(); - GLRenderer->mModelVBO->SetupFrame(surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices); + mVBuf->SetupFrame(surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices); glDrawElements(GL_TRIANGLES, surf->numTriangles * 3, GL_UNSIGNED_INT, (void*)(intptr_t)(surf->iindex * sizeof(unsigned int))); } gl_RenderState.SetInterpolationFactor(0.f); } +//=========================================================================== +// +// +// +//=========================================================================== + FMD3Model::~FMD3Model() { if (frames) delete [] frames; diff --git a/src/gl/models/gl_voxels.cpp b/src/gl/models/gl_voxels.cpp index 7fb18766fb..c3ef4cd27e 100644 --- a/src/gl/models/gl_voxels.cpp +++ b/src/gl/models/gl_voxels.cpp @@ -214,8 +214,6 @@ FVoxelModel::FVoxelModel(FVoxel *voxel, bool owned) mVoxel = voxel; mOwningVoxel = owned; mPalette = new FVoxelTexture(voxel); - Initialize(); - iindex = vindex = UINT_MAX; } //=========================================================================== @@ -231,24 +229,6 @@ FVoxelModel::~FVoxelModel() } -//=========================================================================== -// -// -// -//=========================================================================== - -void FVoxelModel::BuildVertexBuffer(FModelVertexBuffer *buf) -{ - vindex = buf->vbo_shadowdata.Size(); - iindex = buf->ibo_shadowdata.Size(); - - FModelVertex *mv = &buf->vbo_shadowdata[buf->vbo_shadowdata.Reserve(mVertices.Size())]; - unsigned int *mi = &buf->ibo_shadowdata[buf->ibo_shadowdata.Reserve(mIndices.Size())]; - - memcpy(mv, &mVertices[0], sizeof(FModelVertex)* mVertices.Size()); - memcpy(mi, &mIndices[0], sizeof(unsigned int)* mIndices.Size()); -} - //=========================================================================== // // @@ -386,6 +366,37 @@ void FVoxelModel::Initialize() } } +//=========================================================================== +// +// +// +//=========================================================================== + +void FVoxelModel::BuildVertexBuffer() +{ + if (mVBuf == NULL) + { + Initialize(); + + mVBuf = new FModelVertexBuffer(true); + FModelVertex *vertptr = mVBuf->LockVertexBuffer(mVertices.Size()); + unsigned int *indxptr = mVBuf->LockIndexBuffer(mIndices.Size()); + + memcpy(vertptr, &mVertices[0], sizeof(FModelVertex)* mVertices.Size()); + memcpy(indxptr, &mIndices[0], sizeof(unsigned int)* mIndices.Size()); + + mVBuf->UnlockVertexBuffer(); + mVBuf->UnlockIndexBuffer(); + + // delete our temporary buffers + mVertices.Clear(); + mIndices.Clear(); + mVertices.ShrinkToFit(); + mIndices.ShrinkToFit(); + } +} + + //=========================================================================== // // @@ -420,7 +431,7 @@ void FVoxelModel::RenderFrame(FTexture * skin, int frame, int frame2, double int gl_RenderState.SetMaterial(tex, CLAMP_NOFILTER, translation, -1, false); gl_RenderState.Apply(); - GLRenderer->mModelVBO->SetupFrame(vindex, vindex); - glDrawElements(GL_TRIANGLES, mIndices.Size(), GL_UNSIGNED_INT, (void*)(intptr_t)(iindex * sizeof(unsigned int))); + mVBuf->SetupFrame(0, 0); + glDrawElements(GL_TRIANGLES, mNumIndices, GL_UNSIGNED_INT, (void*)(intptr_t)0); } diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 26e16d4dda..9466e5fd0a 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -99,6 +99,8 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) mLights = NULL; } +void gl_LoadModels(); + void FGLRenderer::Initialize() { glpart2 = FTexture::CreateTexture(Wads.GetNumForFullName("glstuff/glpart2.png"), FTexture::TEX_MiscPatch); @@ -107,13 +109,13 @@ void FGLRenderer::Initialize() mVBO = new FFlatVertexBuffer; mSkyVBO = new FSkyVertexBuffer; - mModelVBO = new FModelVertexBuffer; mLights = new FLightBuffer(); gl_RenderState.SetVertexBuffer(mVBO); mFBID = 0; SetupLevel(); mShaderManager = new FShaderManager; mSamplerManager = new FSamplerManager; + gl_LoadModels(); } FGLRenderer::~FGLRenderer() @@ -123,7 +125,6 @@ FGLRenderer::~FGLRenderer() if (mShaderManager != NULL) delete mShaderManager; if (mSamplerManager != NULL) delete mSamplerManager; if (mVBO != NULL) delete mVBO; - if (mModelVBO) delete mModelVBO; if (mSkyVBO != NULL) delete mSkyVBO; if (mLights != NULL) delete mLights; if (glpart2) delete glpart2; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 90f2c4a46f..0e5e996432 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -10,7 +10,6 @@ struct particle_t; class FCanvasTexture; class FFlatVertexBuffer; class FSkyVertexBuffer; -class FModelVertexBuffer; class OpenGLFrameBuffer; struct FDrawInfo; struct pspdef_t; @@ -72,7 +71,6 @@ public: FFlatVertexBuffer *mVBO; FSkyVertexBuffer *mSkyVBO; - FModelVertexBuffer *mModelVBO; FLightBuffer *mLights;