mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-28 06:32:29 +00:00
- made MD3 models reloadable.
This commit is contained in:
parent
feeebf5265
commit
052dda0fdd
3 changed files with 127 additions and 81 deletions
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue