models: ReadMD5Anim use strtol for parse

This commit is contained in:
Denis Pauk 2024-03-02 19:08:17 +02:00
parent 55576952d7
commit b0f2538951

View file

@ -105,7 +105,7 @@ typedef struct md5_model_s
int num_verts; int num_verts;
int num_tris; int num_tris;
int num_skins; int num_skins;
int frameRate; float frameRate;
} md5_model_t; } md5_model_t;
/* Joint info */ /* Joint info */
@ -358,6 +358,37 @@ get_line(char **buff, char *curr_buff)
return curr_buff; return curr_buff;
} }
/**
* Free frames allocated for the model.
*/
static void
FreeModelMd5Frames(md5_model_t *mdl)
{
int i;
if (mdl->skelFrames)
{
for (i = 0; i < mdl->num_frames; ++i)
{
if (mdl->skelFrames[i].vertexArray)
{
free(mdl->skelFrames[i].vertexArray);
mdl->skelFrames[i].vertexArray = NULL;
}
if (mdl->skelFrames[i].skelJoints)
{
free(mdl->skelFrames[i].skelJoints);
mdl->skelFrames[i].skelJoints = NULL;
}
}
free(mdl->skelFrames);
mdl->skelFrames = NULL;
mdl->num_frames = 0;
}
}
/** /**
* Load an MD5 animation from file. * Load an MD5 animation from file.
*/ */
@ -400,19 +431,15 @@ ReadMD5Anim(md5_model_t *anim, const char *buffer, size_t size)
/* Bad version */ /* Bad version */
R_Printf(PRINT_ALL, "Error: bad animation version\n"); R_Printf(PRINT_ALL, "Error: bad animation version\n");
/* broken file */ /* broken file */
anim->num_frames = 0; FreeModelMd5Frames(anim);
break; break;
} }
} }
else else if (!strcmp(token, "numFrames"))
{ {
/* get end of string */ token = COM_Parse(&curr_buff);
curr_buff = get_line(&buff, curr_buff); anim->num_frames = (int)strtol(token, (char **)NULL, 10);
if (!strcmp(token, "numFrames"))
{
if (sscanf(buff, "%d", &anim->num_frames) == 1)
{
/* Allocate memory for skeleton frames and bounding boxes */ /* Allocate memory for skeleton frames and bounding boxes */
if (anim->num_frames > 0) if (anim->num_frames > 0)
{ {
@ -420,11 +447,11 @@ ReadMD5Anim(md5_model_t *anim, const char *buffer, size_t size)
malloc(sizeof(md5_frame_t) * anim->num_frames); malloc(sizeof(md5_frame_t) * anim->num_frames);
} }
} }
}
else if (!strcmp(token, "numJoints")) else if (!strcmp(token, "numJoints"))
{ {
if (sscanf(buff, "%d", &anim->num_joints) == 1) token = COM_Parse(&curr_buff);
{ anim->num_joints = (int)strtol(token, (char **)NULL, 10);
if (anim->num_joints > 0) if (anim->num_joints > 0)
{ {
AllocateFrames(anim); AllocateFrames(anim);
@ -437,26 +464,31 @@ ReadMD5Anim(md5_model_t *anim, const char *buffer, size_t size)
malloc(sizeof(md5_baseframe_joint_t) * anim->num_joints); malloc(sizeof(md5_baseframe_joint_t) * anim->num_joints);
} }
} }
}
else if (!strcmp(token, "frameRate")) else if (!strcmp(token, "frameRate"))
{ {
if (sscanf(buff, "%d", &anim->frameRate) == 1) token = COM_Parse(&curr_buff);
{ anim->frameRate = (float)strtod(token, (char **)NULL);
R_Printf(PRINT_DEVELOPER, "md5anim: animation's frame rate is %d\n", anim->frameRate);
} R_Printf(PRINT_DEVELOPER, "%s: animation's frame rate is %f\n",
__func__, anim->frameRate);
} }
else if (!strcmp(token, "numAnimatedComponents")) else if (!strcmp(token, "numAnimatedComponents"))
{ {
if (sscanf(buff, "%d", &numAnimatedComponents) == 1) token = COM_Parse(&curr_buff);
{ numAnimatedComponents = (int)strtol(token, (char **)NULL, 10);
if (numAnimatedComponents > 0) if (numAnimatedComponents > 0)
{ {
/* Allocate memory for animation frame data */ /* Allocate memory for animation frame data */
animFrameData = (float *)malloc(sizeof(float) * numAnimatedComponents); animFrameData = (float *)malloc(sizeof(float) * numAnimatedComponents);
} }
} }
} else
else if (!strcmp(token, "hierarchy")) {
/* get end of string */
curr_buff = get_line(&buff, curr_buff);
if (!strcmp(token, "hierarchy"))
{ {
if (buff[0] == '{') if (buff[0] == '{')
{ {
@ -474,7 +506,7 @@ ReadMD5Anim(md5_model_t *anim, const char *buffer, size_t size)
{ {
R_Printf(PRINT_ALL, "Error: expected block close\n"); R_Printf(PRINT_ALL, "Error: expected block close\n");
/* broken file */ /* broken file */
anim->num_frames = 0; FreeModelMd5Frames(anim);
break; break;
} }
} }
@ -502,7 +534,7 @@ ReadMD5Anim(md5_model_t *anim, const char *buffer, size_t size)
{ {
R_Printf(PRINT_ALL, "Error: expected block close\n"); R_Printf(PRINT_ALL, "Error: expected block close\n");
/* broken file */ /* broken file */
anim->num_frames = 0; FreeModelMd5Frames(anim);
break; break;
} }
} }
@ -531,7 +563,7 @@ ReadMD5Anim(md5_model_t *anim, const char *buffer, size_t size)
{ {
R_Printf(PRINT_ALL, "Error: expected block close\n"); R_Printf(PRINT_ALL, "Error: expected block close\n");
/* broken file */ /* broken file */
anim->num_frames = 0; FreeModelMd5Frames(anim);
break; break;
} }
} }
@ -548,10 +580,10 @@ ReadMD5Anim(md5_model_t *anim, const char *buffer, size_t size)
{ {
R_Printf(PRINT_ALL, "Error: expected frame close\n"); R_Printf(PRINT_ALL, "Error: expected frame close\n");
/* broken file */ /* broken file */
anim->num_frames = 0; FreeModelMd5Frames(anim);
break; break;
} }
sscanf(token, "%f", &animFrameData[i]); animFrameData[i] = (float)strtod(token, (char **)NULL);
} }
/* Build frame skeleton from the collected data */ /* Build frame skeleton from the collected data */
@ -563,7 +595,7 @@ ReadMD5Anim(md5_model_t *anim, const char *buffer, size_t size)
{ {
R_Printf(PRINT_ALL, "Error: expected block close\n"); R_Printf(PRINT_ALL, "Error: expected block close\n");
/* broken file */ /* broken file */
anim->num_frames = 0; FreeModelMd5Frames(anim);
break; break;
} }
} }
@ -598,26 +630,7 @@ FreeModelMd5(md5_model_t *mdl)
{ {
int i; int i;
if (mdl->skelFrames) FreeModelMd5Frames(mdl);
{
for (i = 0; i < mdl->num_frames; ++i)
{
if (mdl->skelFrames[i].vertexArray)
{
free(mdl->skelFrames[i].vertexArray);
mdl->skelFrames[i].vertexArray = NULL;
}
if (mdl->skelFrames[i].skelJoints)
{
free(mdl->skelFrames[i].skelJoints);
mdl->skelFrames[i].skelJoints = NULL;
}
}
free(mdl->skelFrames);
mdl->skelFrames = NULL;
}
if (mdl->vertexIndices) if (mdl->vertexIndices)
{ {
@ -718,69 +731,22 @@ ReadMD5Model(const char *buffer, size_t size)
return NULL; return NULL;
} }
} }
else else if (!strcmp(token, "numSkins"))
{ {
/* get end of string */ token = COM_Parse(&curr_buff);
curr_buff = get_line(&buff, curr_buff); mdl->num_skins = (int)strtol(token, (char **)NULL, 10);
if (!strcmp(token, "numskins"))
{
if (sscanf(buff, "%d", &mdl->num_skins) == 1)
{
if (mdl->num_skins > 0) if (mdl->num_skins > 0)
{ {
mdl->skins = malloc(mdl->num_skins * MAX_SKINNAME); mdl->skins = malloc(mdl->num_skins * MAX_SKINNAME);
memset(mdl->skins, 0, mdl->num_skins * MAX_SKINNAME); memset(mdl->skins, 0, mdl->num_skins * MAX_SKINNAME);
} }
} }
}
else if (!strcmp(token, "skin"))
{
char *line;
int pos;
line = buff;
token = COM_Parse(&line);
pos = (int)strtol(token, (char **)NULL, 10);
if (pos < mdl->num_skins)
{
int quote = 0, j = 0;
char *skinname;
skinname = mdl->skins + pos * MAX_SKINNAME;
/* Copy the shader name whithout the quote marks */
while (*line)
{
if (*line == '"')
{
quote++;
if (quote >= 2)
{
break;
}
}
else if (quote == 1)
{
if ((j >= (MAX_SKINNAME - 1)))
{
break;
}
skinname[j] = *line;
j ++;
}
line ++;
}
}
}
else if (!strcmp(token, "numJoints")) else if (!strcmp(token, "numJoints"))
{ {
if (sscanf(buff, "%d", &mdl->num_joints) == 1) token = COM_Parse(&curr_buff);
{ mdl->num_joints = (int)strtol(token, (char **)NULL, 10);
if (mdl->num_joints > 0) if (mdl->num_joints > 0)
{ {
/* Allocate memory for base skeleton joints */ /* Allocate memory for base skeleton joints */
@ -788,11 +754,11 @@ ReadMD5Model(const char *buffer, size_t size)
calloc (mdl->num_joints, sizeof(md5_joint_t)); calloc (mdl->num_joints, sizeof(md5_joint_t));
} }
} }
}
else if (!strcmp(token, "numMeshes")) else if (!strcmp(token, "numMeshes"))
{ {
if (sscanf(buff, "%d", &mdl->num_meshes) == 1) token = COM_Parse(&curr_buff);
{ mdl->num_meshes = (int)strtol(token, (char **)NULL, 10);
if (mdl->num_meshes > 0) if (mdl->num_meshes > 0)
{ {
/* Allocate memory for meshes */ /* Allocate memory for meshes */
@ -800,8 +766,28 @@ ReadMD5Model(const char *buffer, size_t size)
calloc (mdl->num_meshes, sizeof(md5_mesh_t)); calloc (mdl->num_meshes, sizeof(md5_mesh_t));
} }
} }
else if (!strcmp(token, "skin"))
{
int pos;
token = COM_Parse(&curr_buff);
pos = (int)strtol(token, (char **)NULL, 10);
token = COM_Parse(&curr_buff);
if (pos >= 0 && pos < mdl->num_skins)
{
char *skinname;
skinname = mdl->skins + pos * MAX_SKINNAME;
strncpy(skinname, token, MAX_SKINNAME - 1);
} }
else if (!strcmp(token, "joints")) }
else
{
/* get end of string */
curr_buff = get_line(&buff, curr_buff);
if (!strcmp(token, "joints"))
{ {
if (buff[0] == '{') if (buff[0] == '{')
{ {