diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index bfbf21dd20..fb63c2cf61 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -101,6 +101,14 @@ void gl_LoadModels() } } +void gl_FlushModels() +{ + for (int i = Models.Size() - 1; i >= 0; i--) + { + Models[i]->DestroyVertexBuffer(); + } +} + //=========================================================================== // // diff --git a/src/gl/models/gl_models.h b/src/gl/models/gl_models.h index 0d479b68c5..6ca096ca1c 100644 --- a/src/gl/models/gl_models.h +++ b/src/gl/models/gl_models.h @@ -33,6 +33,11 @@ public: 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() = 0; + void DestroyVertexBuffer() + { + delete mVBuf; + mVBuf = NULL; + } virtual float getAspectFactor() { return 1.f; } FModelVertexBuffer *mVBuf; @@ -93,9 +98,13 @@ protected: struct ModelFrame { char name[16]; + unsigned int vindex; + }; + + struct ModelFrameVertexData + { DMDModelVertex *vertices; DMDModelVertex *normals; - unsigned int vindex; }; struct DMDLoDInfo @@ -112,21 +121,23 @@ protected: }; - bool loaded; + int mLumpNum; DMDHeader header; DMDInfo info; FTexture ** skins; - FTexCoord * texCoords; - ModelFrame * frames; + bool allowTexComp; // Allow texture compression with this. + + // Temp data only needed for buffer construction + FTexCoord * texCoords; + ModelFrameVertexData *framevtx; DMDLoDInfo lodInfo[MAX_LODS]; DMDLoD lods[MAX_LODS]; - bool allowTexComp; // Allow texture compression with this. public: FDMDModel() { - loaded = false; + mLumpNum = -1; frames = NULL; skins = NULL; for (int i = 0; i < MAX_LODS; i++) @@ -135,14 +146,16 @@ public: } info.numLODs = 0; texCoords = NULL; + framevtx = NULL; } 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 LoadGeometry(); + void UnloadGeometry(); void BuildVertexBuffer(); - void CleanTempData(); }; @@ -154,6 +167,7 @@ public: virtual ~FMD2Model(); virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length); + virtual void LoadGeometry(); }; diff --git a/src/gl/models/gl_models_md2.cpp b/src/gl/models/gl_models_md2.cpp index 402b20472d..c40e20d90d 100644 --- a/src/gl/models/gl_models_md2.cpp +++ b/src/gl/models/gl_models_md2.cpp @@ -74,53 +74,58 @@ static void UnpackVector(unsigned short packed, float vec[3]) } +//=========================================================================== +// +// DMD file structure +// +//=========================================================================== + +struct dmd_chunk_t +{ + int type; + int length; // Next chunk follows... +}; + +#pragma pack(1) +struct dmd_packedVertex_t +{ + byte vertex[3]; + unsigned short normal; // Yaw and pitch. +}; + +struct dmd_packedFrame_t +{ + float scale[3]; + float translate[3]; + char name[16]; + dmd_packedVertex_t vertices[1]; +}; +#pragma pack() + +// Chunk types. +enum +{ + DMC_END, // Must be the last chunk. + DMC_INFO // Required; will be expected to exist. +}; + //=========================================================================== // // FDMDModel::Load // //=========================================================================== -bool FDMDModel::Load(const char * path, int, const char * buffer, int length) +bool FDMDModel::Load(const char * path, int lumpnum, const char * buffer, int length) { - struct dmd_chunk_t - { - int type; - int length; // Next chunk follows... - }; - -#pragma pack(1) - struct dmd_packedVertex_t - { - byte vertex[3]; - unsigned short normal; // Yaw and pitch. - }; - - struct dmd_packedFrame_t - { - float scale[3]; - float translate[3]; - char name[16]; - dmd_packedVertex_t vertices[1]; - } ; -#pragma pack() - - // Chunk types. - enum - { - DMC_END, // Must be the last chunk. - DMC_INFO // Required; will be expected to exist. - }; - - dmd_chunk_t * chunk = (dmd_chunk_t*)(buffer+12); + dmd_chunk_t * chunk = (dmd_chunk_t*)(buffer + 12); char *temp; ModelFrame *frame; - int i, k, c; - int axis[3] = { VX, VY, VZ }; + int i; - int fileoffset=12+sizeof(dmd_chunk_t); + int fileoffset = 12 + sizeof(dmd_chunk_t); chunk->type = LittleLong(chunk->type); - while(chunk->type != DMC_END) + while (chunk->type != DMC_END) { switch (chunk->type) { @@ -148,7 +153,7 @@ bool FDMDModel::Load(const char * path, int, const char * buffer, int length) break; } // Read the next chunk header. - chunk = (dmd_chunk_t*)(buffer+fileoffset); + chunk = (dmd_chunk_t*)(buffer + fileoffset); chunk->type = LittleLong(chunk->type); fileoffset += sizeof(dmd_chunk_t); } @@ -156,34 +161,58 @@ bool FDMDModel::Load(const char * path, int, const char * buffer, int length) // Allocate and load in the data. skins = new FTexture *[info.numSkins]; - for(i = 0; i < info.numSkins; i++) + for (i = 0; i < info.numSkins; i++) { - 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; frames = new ModelFrame[info.numFrames]; - for(i = 0, frame = frames; i < info.numFrames; i++, frame++) + for (i = 0, frame = frames; i < info.numFrames; i++, frame++) + { + dmd_packedFrame_t *pfr = (dmd_packedFrame_t *)(temp + info.frameSize * i); + + memcpy(frame->name, pfr->name, sizeof(pfr->name)); + frame->vindex = UINT_MAX; + } + mLumpNum = lumpnum; + return true; +} + +//=========================================================================== +// +// FDMDModel::LoadGeometry +// +//=========================================================================== + +void FDMDModel::LoadGeometry() +{ + static int axis[3] = { VX, VY, VZ }; + FMemLump lumpdata = Wads.ReadLump(mLumpNum); + const char *buffer = (const char *)lumpdata.GetMem(); + texCoords = new FTexCoord[info.numTexCoords]; + memcpy(texCoords, buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord)); + + const char *temp = buffer + info.offsetFrames; + framevtx= new ModelFrameVertexData[info.numFrames]; + + ModelFrameVertexData *framev; + int i, k, c; + for(i = 0, framev = framevtx; i < info.numFrames; i++, framev++) { dmd_packedFrame_t *pfr = (dmd_packedFrame_t *) (temp + info.frameSize * i); dmd_packedVertex_t *pVtx; - memcpy(frame->name, pfr->name, sizeof(pfr->name)); - frame->vertices = new DMDModelVertex[info.numVertices]; - frame->normals = new DMDModelVertex[info.numVertices]; - frame->vindex = UINT_MAX; + framev->vertices = new DMDModelVertex[info.numVertices]; + framev->normals = new DMDModelVertex[info.numVertices]; // Translate each vertex. for(k = 0, pVtx = pfr->vertices; k < info.numVertices; k++, pVtx++) { - UnpackVector((unsigned short)(pVtx->normal), frame->normals[k].xyz); + UnpackVector((unsigned short)(pVtx->normal), framev->normals[k].xyz); for(c = 0; c < 3; c++) { - frame->vertices[k].xyz[axis[c]] = + framev->vertices[k].xyz[axis[c]] = (pVtx->vertex[c] * FLOAT(pfr->scale[c]) + FLOAT(pfr->translate[c])); } } @@ -209,24 +238,6 @@ bool FDMDModel::Load(const char * path, int, const char * buffer, int length) } } - loaded=true; - return true; -} - - -//=========================================================================== -// -// -// -//=========================================================================== - -FDMDModel::~FDMDModel() -{ - CleanTempData(); - - // skins are managed by the texture manager so they must not be deleted here. - if (skins != NULL) delete [] skins; - if (frames != NULL) delete [] frames; } //=========================================================================== @@ -235,20 +246,22 @@ FDMDModel::~FDMDModel() // //=========================================================================== -void FDMDModel::CleanTempData() +void FDMDModel::UnloadGeometry() { int i; - if (frames != NULL) + if (framevtx != NULL) { for (i=0;ivertices; - DMDModelVertex *norm = frame->normals; - - frame->vindex = vindex; + DMDModelVertex *vert = framevtx[i].vertices; + DMDModelVertex *norm = framevtx[i].normals; + frames[i].vindex = vindex; FTriangle *tri = lods[0].triangles; @@ -304,7 +332,7 @@ void FDMDModel::BuildVertexBuffer() } } mVBuf->UnlockVertexBuffer(); - CleanTempData(); + UnloadGeometry(); } } @@ -353,55 +381,60 @@ void FDMDModel::RenderFrame(FTexture * skin, int frameno, int frameno2, double i } + +//=========================================================================== +// +// Internal data structures of MD2 files - only used during loading +// +//=========================================================================== + +struct md2_header_t +{ + int magic; + int version; + int skinWidth; + int skinHeight; + int frameSize; + int numSkins; + int numVertices; + int numTexCoords; + int numTriangles; + int numGlCommands; + int numFrames; + int offsetSkins; + int offsetTexCoords; + int offsetTriangles; + int offsetFrames; + int offsetGlCommands; + int offsetEnd; +}; + +struct md2_triangleVertex_t +{ + byte vertex[3]; + byte lightNormalIndex; +}; + +struct md2_packedFrame_t +{ + float scale[3]; + float translate[3]; + char name[16]; + md2_triangleVertex_t vertices[1]; +}; + //=========================================================================== // // FMD2Model::Load // //=========================================================================== -bool FMD2Model::Load(const char * path, int, const char * buffer, int length) +bool FMD2Model::Load(const char * path, int lumpnum, const char * buffer, int length) { - // Internal data structures of MD2 files - only used during loading! - struct md2_header_t - { - int magic; - int version; - int skinWidth; - int skinHeight; - int frameSize; - int numSkins; - int numVertices; - int numTexCoords; - int numTriangles; - int numGlCommands; - int numFrames; - int offsetSkins; - int offsetTexCoords; - int offsetTriangles; - int offsetFrames; - int offsetGlCommands; - int offsetEnd; - } ; - - struct md2_triangleVertex_t - { - byte vertex[3]; - byte lightNormalIndex; - }; - - struct md2_packedFrame_t - { - float scale[3]; - float translate[3]; - char name[16]; - md2_triangleVertex_t vertices[1]; - }; - md2_header_t * md2header = (md2_header_t *)buffer; ModelFrame *frame; byte *md2_frames; - int i, k, c; - int axis[3] = { VX, VY, VZ }; + int i; // Convert it to DMD. header.magic = MD2_MAGIC; @@ -436,39 +469,71 @@ bool FMD2Model::Load(const char * path, int, const char * buffer, int length) return false; } + skins = new FTexture *[info.numSkins]; + + for (i = 0; i < info.numSkins; i++) + { + skins[i] = LoadSkin(path, buffer + info.offsetSkins + i * 64); + } + // The frames need to be unpacked. md2_frames = (byte*)buffer + info.offsetFrames; frames = new ModelFrame[info.numFrames]; + for (i = 0, frame = frames; i < info.numFrames; i++, frame++) + { + md2_packedFrame_t *pfr = (md2_packedFrame_t *)(md2_frames + info.frameSize * i); + + memcpy(frame->name, pfr->name, sizeof(pfr->name)); + frame->vindex = UINT_MAX; + } + mLumpNum = lumpnum; + return true; +} + +//=========================================================================== +// +// FMD2Model::LoadGeometry +// +//=========================================================================== + +void FMD2Model::LoadGeometry() +{ + static int axis[3] = { VX, VY, VZ }; + byte *md2_frames; + FMemLump lumpdata = Wads.ReadLump(mLumpNum); + const char *buffer = (const char *)lumpdata.GetMem(); + texCoords = new FTexCoord[info.numTexCoords]; memcpy(texCoords, (byte*)buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord)); + md2_frames = (byte*)buffer + info.offsetFrames; + framevtx = new ModelFrameVertexData[info.numFrames]; + ModelFrameVertexData *framev; + int i, k, c; - for(i = 0, frame = frames; i < info.numFrames; i++, frame++) + for(i = 0, framev = framevtx; i < info.numFrames; i++, framev++) { md2_packedFrame_t *pfr = (md2_packedFrame_t *) (md2_frames + info.frameSize * i); md2_triangleVertex_t *pVtx; - memcpy(frame->name, pfr->name, sizeof(pfr->name)); - frame->vertices = new DMDModelVertex[info.numVertices]; - frame->normals = new DMDModelVertex[info.numVertices]; - frame->vindex = UINT_MAX; + framev->vertices = new DMDModelVertex[info.numVertices]; + framev->normals = new DMDModelVertex[info.numVertices]; // Translate each vertex. for(k = 0, pVtx = pfr->vertices; k < info.numVertices; k++, pVtx++) { - memcpy(frame->normals[k].xyz, + memcpy(framev->normals[k].xyz, avertexnormals[pVtx->lightNormalIndex], sizeof(float) * 3); for(c = 0; c < 3; c++) { - frame->vertices[k].xyz[axis[c]] = + framev->vertices[k].xyz[axis[c]] = (pVtx->vertex[c] * pfr->scale[c] + pfr->translate[c]); } } } - lods[0].triangles = new FTriangle[lodInfo[0].numTriangles]; int cnt = lodInfo[0].numTriangles; @@ -481,15 +546,6 @@ bool FMD2Model::Load(const char * path, int, const char * buffer, int length) lods[0].triangles[j].vertexIndices[k] = LittleShort(lods[0].triangles[j].vertexIndices[k]); } } - - skins = new FTexture *[info.numSkins]; - - for(i = 0; i < info.numSkins; i++) - { - skins[i] = LoadSkin(path, buffer + info.offsetSkins + i*64); - } - loaded=true; - return true; } FMD2Model::~FMD2Model() diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 48864ab24c..08eb3b26d2 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -765,11 +765,13 @@ void GLDrawList::DrawSorted() MakeSortList(); sorted=DoSort(SortNodes[SortNodeStart]); } + gl_RenderState.ClearClipSplit(); glEnable(GL_CLIP_DISTANCE2); glEnable(GL_CLIP_DISTANCE3); DoDrawSorted(sorted); glDisable(GL_CLIP_DISTANCE2); glDisable(GL_CLIP_DISTANCE3); + gl_RenderState.ClearClipSplit(); } //========================================================================== diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index eba8b4d063..54bc9b540c 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -800,7 +800,7 @@ void GLPlaneMirrorPortal::DrawContents() float f = FIXED2FLOAT(planez); if (PlaneMirrorMode < 0) { - gl_RenderState.SetClipHeightTop(f); // ceiling mirror: clip everytihng with a z lower than the portal's ceiling + gl_RenderState.SetClipHeightTop(f); // ceiling mirror: clip everything with a z lower than the portal's ceiling glEnable(GL_CLIP_DISTANCE1); } else