- made MD3 models reloadable.

This commit is contained in:
Christoph Oelckers 2015-04-12 19:42:03 +02:00
parent feeebf5265
commit 052dda0fdd
3 changed files with 127 additions and 81 deletions

View file

@ -220,10 +220,10 @@ class FMD3Model : public FModel
~MD3Surface() ~MD3Surface()
{ {
if (skins) delete [] skins; if (skins) delete [] skins;
CleanTempData(); UnloadGeometry();
} }
void CleanTempData() void UnloadGeometry()
{ {
if (tris) delete [] tris; if (tris) delete [] tris;
if (vertices) delete [] vertices; if (vertices) delete [] vertices;
@ -245,6 +245,7 @@ class FMD3Model : public FModel
int numFrames; int numFrames;
int numTags; int numTags;
int numSurfaces; int numSurfaces;
int mLumpNum;
MD3Frame * frames; MD3Frame * frames;
MD3Surface * surfaces; MD3Surface * surfaces;
@ -256,6 +257,7 @@ public:
virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length); virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length);
virtual int FindFrame(const char * name); virtual int FindFrame(const char * name);
virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0); virtual void RenderFrame(FTexture * skin, int frame, int frame2, double inter, int translation=0);
void LoadGeometry();
void BuildVertexBuffer(); void BuildVertexBuffer();
}; };

View file

@ -50,9 +50,14 @@
#define MAX_QPATH 64 #define MAX_QPATH 64
//===========================================================================
//
// decode the lat/lng normal to a 3 float normal
//
//===========================================================================
static void UnpackVector(unsigned short packed, float & nx, float & ny, float & nz) static void UnpackVector(unsigned short packed, float & nx, float & ny, float & nz)
{ {
// decode the lat/lng normal to a 3 float normal
double lat = ( packed >> 8 ) & 0xff; double lat = ( packed >> 8 ) & 0xff;
double lng = ( packed & 0xff ); double lng = ( packed & 0xff );
lat *= PI/128; lat *= PI/128;
@ -63,13 +68,15 @@ static void UnpackVector(unsigned short packed, float & nx, float & ny, float &
nz = cos(lng); nz = cos(lng);
} }
//===========================================================================
//
// MD3 File structure
//
//===========================================================================
#pragma pack(4)
bool FMD3Model::Load(const char * path, int, const char * buffer, int length) struct md3_header_t
{ {
#pragma pack(4)
struct md3_header_t
{
DWORD Magic; DWORD Magic;
DWORD Version; DWORD Version;
char Name[MAX_QPATH]; char Name[MAX_QPATH];
@ -82,10 +89,10 @@ bool FMD3Model::Load(const char * path, int, const char * buffer, int length)
DWORD Ofs_Tags; DWORD Ofs_Tags;
DWORD Ofs_Surfaces; DWORD Ofs_Surfaces;
DWORD Ofs_Eof; DWORD Ofs_Eof;
}; };
struct md3_surface_t struct md3_surface_t
{ {
DWORD Magic; DWORD Magic;
char Name[MAX_QPATH]; char Name[MAX_QPATH];
DWORD Flags; DWORD Flags;
@ -98,40 +105,49 @@ bool FMD3Model::Load(const char * path, int, const char * buffer, int length)
DWORD Ofs_Texcoord; DWORD Ofs_Texcoord;
DWORD Ofs_XYZNormal; DWORD Ofs_XYZNormal;
DWORD Ofs_End; DWORD Ofs_End;
}; };
struct md3_triangle_t struct md3_triangle_t
{ {
DWORD vt_index[3]; DWORD vt_index[3];
}; };
struct md3_shader_t struct md3_shader_t
{ {
char Name[MAX_QPATH]; char Name[MAX_QPATH];
DWORD index; DWORD index;
}; };
struct md3_texcoord_t struct md3_texcoord_t
{ {
float s,t; float s, t;
}; };
struct md3_vertex_t struct md3_vertex_t
{ {
short x,y,z,n; short x, y, z, n;
}; };
struct md3_frame_t struct md3_frame_t
{ {
float min_Bounds[3]; float min_Bounds[3];
float max_Bounds[3]; float max_Bounds[3];
float localorigin[3]; float localorigin[3];
float radius; float radius;
char Name[16]; char Name[16];
}; };
#pragma pack() #pragma pack()
md3_header_t * hdr=(md3_header_t *)buffer;
//===========================================================================
//
//
//
//===========================================================================
bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int length)
{
md3_header_t * hdr = (md3_header_t *)buffer;
numFrames = LittleLong(hdr->Num_Frames); numFrames = LittleLong(hdr->Num_Frames);
numTags = LittleLong(hdr->Num_Tags); numTags = LittleLong(hdr->Num_Tags);
@ -140,16 +156,17 @@ bool FMD3Model::Load(const char * path, int, const char * buffer, int length)
md3_frame_t * frm = (md3_frame_t*)(buffer + LittleLong(hdr->Ofs_Frames)); md3_frame_t * frm = (md3_frame_t*)(buffer + LittleLong(hdr->Ofs_Frames));
frames = new MD3Frame[numFrames]; frames = new MD3Frame[numFrames];
for(int i=0;i<numFrames;i++) for (int i = 0; i < numFrames; i++)
{ {
strncpy(frames[i].Name, frm[i].Name, 16); strncpy(frames[i].Name, frm[i].Name, 16);
for(int j=0;j<3;j++) frames[i].origin[j] = frm[i].localorigin[j]; for (int j = 0; j < 3; j++) frames[i].origin[j] = frm[i].localorigin[j];
} }
md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces)); md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces));
surfaces = new MD3Surface[numSurfaces]; surfaces = new MD3Surface[numSurfaces];
for(int i=0;i<numSurfaces;i++)
for (int i = 0; i < numSurfaces; i++)
{ {
MD3Surface * s = &surfaces[i]; MD3Surface * s = &surfaces[i];
md3_surface_t * ss = surf; md3_surface_t * ss = surf;
@ -160,6 +177,43 @@ bool FMD3Model::Load(const char * path, int, const char * buffer, int length)
s->numTriangles = LittleLong(ss->Num_Triangles); s->numTriangles = LittleLong(ss->Num_Triangles);
s->numVertices = LittleLong(ss->Num_Verts); s->numVertices = LittleLong(ss->Num_Verts);
// copy shaders (skins)
md3_shader_t * shader = (md3_shader_t*)(((char*)ss) + LittleLong(ss->Ofs_Shaders));
s->skins = new FTexture *[s->numSkins];
for (int i = 0; i < s->numSkins; i++)
{
// [BB] According to the MD3 spec, Name is supposed to include the full path.
s->skins[i] = LoadSkin("", shader[i].Name);
// [BB] Fall back and check if Name is relative.
if (s->skins[i] == NULL)
s->skins[i] = LoadSkin(path, shader[i].Name);
}
}
mLumpNum = lumpnum;
return true;
}
//===========================================================================
//
//
//
//===========================================================================
void FMD3Model::LoadGeometry()
{
FMemLump lumpdata = Wads.ReadLump(mLumpNum);
const char *buffer = (const char *)lumpdata.GetMem();
md3_header_t * hdr = (md3_header_t *)buffer;
md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces));
for(int i=0;i<numSurfaces;i++)
{
MD3Surface * s = &surfaces[i];
md3_surface_t * ss = surf;
surf = (md3_surface_t *)(((char*)surf) + LittleLong(surf->Ofs_End));
// copy triangle indices // copy triangle indices
md3_triangle_t * tris = (md3_triangle_t*)(((char*)ss)+LittleLong(ss->Ofs_Triangles)); md3_triangle_t * tris = (md3_triangle_t*)(((char*)ss)+LittleLong(ss->Ofs_Triangles));
s->tris = new MD3Triangle[s->numTriangles]; s->tris = new MD3Triangle[s->numTriangles];
@ -169,19 +223,6 @@ bool FMD3Model::Load(const char * path, int, const char * buffer, int length)
s->tris[i].VertIndex[j]=LittleLong(tris[i].vt_index[j]); s->tris[i].VertIndex[j]=LittleLong(tris[i].vt_index[j]);
} }
// copy shaders (skins)
md3_shader_t * shader = (md3_shader_t*)(((char*)ss)+LittleLong(ss->Ofs_Shaders));
s->skins = new FTexture *[s->numSkins];
for(int i=0;i<s->numSkins;i++)
{
// [BB] According to the MD3 spec, Name is supposed to include the full path.
s->skins[i] = LoadSkin("", shader[i].Name);
// [BB] Fall back and check if Name is relative.
if ( s->skins[i] == NULL )
s->skins[i] = LoadSkin(path, shader[i].Name);
}
// Load texture coordinates // Load texture coordinates
md3_texcoord_t * tc = (md3_texcoord_t*)(((char*)ss)+LittleLong(ss->Ofs_Texcoord)); md3_texcoord_t * tc = (md3_texcoord_t*)(((char*)ss)+LittleLong(ss->Ofs_Texcoord));
s->texcoords = new MD3TexCoord[s->numVertices]; s->texcoords = new MD3TexCoord[s->numVertices];
@ -204,7 +245,6 @@ bool FMD3Model::Load(const char * path, int, const char * buffer, int length)
UnpackVector( LittleShort(vt[i].n), s->vertices[i].nx, s->vertices[i].ny, s->vertices[i].nz); UnpackVector( LittleShort(vt[i].n), s->vertices[i].nx, s->vertices[i].ny, s->vertices[i].nz);
} }
} }
return true;
} }
//=========================================================================== //===========================================================================
@ -217,6 +257,8 @@ void FMD3Model::BuildVertexBuffer()
{ {
if (mVBuf == NULL) if (mVBuf == NULL)
{ {
LoadGeometry();
unsigned int vbufsize = 0; unsigned int vbufsize = 0;
unsigned int ibufsize = 0; unsigned int ibufsize = 0;
@ -259,7 +301,7 @@ void FMD3Model::BuildVertexBuffer()
indxptr[iindex++] = surf->tris[k].VertIndex[l]; indxptr[iindex++] = surf->tris[k].VertIndex[l];
} }
} }
surf->CleanTempData(); surf->UnloadGeometry();
} }
mVBuf->UnlockVertexBuffer(); mVBuf->UnlockVertexBuffer();
mVBuf->UnlockIndexBuffer(); mVBuf->UnlockIndexBuffer();

View file

@ -99,6 +99,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
} }
void gl_LoadModels(); void gl_LoadModels();
void gl_FlushModels();
void FGLRenderer::Initialize() void FGLRenderer::Initialize()
{ {
@ -119,6 +120,7 @@ void FGLRenderer::Initialize()
FGLRenderer::~FGLRenderer() FGLRenderer::~FGLRenderer()
{ {
gl_FlushModels();
gl_DeleteAllAttachedLights(); gl_DeleteAllAttachedLights();
FMaterial::FlushAll(); FMaterial::FlushAll();
if (mShaderManager != NULL) delete mShaderManager; if (mShaderManager != NULL) delete mShaderManager;