Created
December 30, 2017 12:07
-
-
Save wernsey/0e9fc05aabbfdabf2b6dfffff21f27aa to your computer and use it in GitHub Desktop.
Milkshape 3D model loading in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
http://paulbourke.net/dataformats/ms3d/ms3dspec.h | |
http://www.chumba.ch/chumbalum-soft/files/ms3dsdk184.zip | |
http://sappersblog.blogspot.co.za/2014/08/milkshape-3d-185-ms3d-file-format.html | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdint.h> | |
#pragma pack(push, 1) | |
typedef struct { | |
char id[10]; | |
int version; | |
} ms3d_header; | |
typedef struct { | |
uint8_t flags; | |
float vertex[3]; | |
int8_t boneId; | |
uint8_t refCnt; | |
} ms3d_vertex; | |
typedef struct { | |
uint16_t flags; | |
uint16_t verts[3]; | |
float norms[3][3]; | |
float s[3]; | |
float t[3]; | |
uint8_t smthGrp; | |
uint8_t grpIndex; | |
} ms3d_triangle; | |
typedef struct { | |
uint8_t flags; | |
char name[32]; | |
uint16_t nTris; | |
uint16_t *triIdx; | |
int8_t matIdx; | |
} ms3d_group; | |
typedef struct { | |
char name[32]; | |
float ambient[4]; | |
float diffuse[4]; | |
float specular[4]; | |
float emissive[4]; | |
float shininess; | |
float transparency; | |
char mode; | |
char texture[128]; | |
char alphamap[128]; | |
} ms3d_material; | |
typedef struct { | |
float time; | |
float rotation[3]; | |
} ms3d_keyframe_rot; | |
typedef struct { | |
float time; | |
float position[3]; | |
} ms3d_keyframe_pos; | |
typedef struct { | |
uint8_t flags; | |
char name[32]; | |
char parentName[32]; | |
float rotation[3]; | |
float position[3]; | |
uint16_t nKeyFramesRot; | |
uint16_t nKeyFramesPos; | |
ms3d_keyframe_rot *keyFramesRot; | |
ms3d_keyframe_pos *keyFramesPos; | |
} ms3d_joint; | |
typedef struct { | |
uint16_t nVerts; | |
uint16_t nTris; | |
uint16_t nGrps; | |
uint16_t nMats; | |
uint16_t nJoints; | |
float animFps; | |
float currTime; | |
int32_t totalFrames; | |
ms3d_vertex *verts; | |
ms3d_triangle *tris; | |
ms3d_group *grps; | |
ms3d_material *mats; | |
ms3d_joint *joints; | |
} ms3d_model; | |
#pragma pack(pop) | |
void ms3d_free(ms3d_model *mdl); | |
ms3d_model *ms3d_load(const char *filename) { | |
ms3d_header hdr; | |
ms3d_model *mdl; | |
int i; | |
FILE *f = fopen(filename,"rb"); | |
if(!f) return NULL; | |
if(fread(&hdr, sizeof hdr, 1, f) != 1 | |
|| memcmp(hdr.id, "MS3D000000", 10)) { | |
fclose(f); | |
fprintf(stderr, "Not a MS3D file"); | |
return NULL; | |
} | |
printf("Version %d\n", hdr.version); | |
mdl = malloc(sizeof *mdl); | |
memset(mdl, 0, sizeof *mdl); | |
if(fread(&mdl->nVerts, sizeof mdl->nVerts, 1, f) != 1) | |
goto error; | |
printf("Vertices: %d\n", mdl->nVerts); | |
mdl->verts = calloc(mdl->nVerts, sizeof *mdl->verts); | |
if(fread(mdl->verts, sizeof *mdl->verts, mdl->nVerts, f) != mdl->nVerts) | |
goto error; | |
if(fread(&mdl->nTris, sizeof mdl->nTris, 1, f) != 1) | |
goto error; | |
printf("Triangles: %d\n", mdl->nTris); | |
mdl->tris = calloc(mdl->nTris, sizeof *mdl->tris); | |
if(fread(mdl->tris, sizeof *mdl->tris, mdl->nTris, f) != mdl->nTris) | |
goto error; | |
if(fread(&mdl->nGrps, sizeof mdl->nGrps, 1, f) != 1) | |
goto error; | |
printf("Groups: %d\n", mdl->nGrps); | |
mdl->grps = calloc(mdl->nGrps, sizeof *mdl->grps); | |
for(i = 0; i < mdl->nGrps; i++) { | |
ms3d_group *g = &mdl->grps[i]; | |
if(fread(&g->flags, sizeof g->flags, 1, f) != 1 || | |
fread(&g->name, sizeof g->name, 1, f) != 1 || | |
fread(&g->nTris, sizeof g->nTris, 1, f) != 1) | |
goto error; | |
printf("Group %d: '%s' : %d triangles\n", i, g->name, g->nTris); | |
g->triIdx = calloc(g->nTris, sizeof *g->triIdx); | |
if(fread(g->triIdx, sizeof *g->triIdx, g->nTris, f) != g->nTris) | |
goto error; | |
if(fread(&g->matIdx, sizeof g->matIdx, 1, f) != 1) | |
goto error; | |
} | |
if(fread(&mdl->nMats, sizeof mdl->nMats, 1, f) != 1) | |
goto error; | |
printf("Materials: %d\n", mdl->nMats); | |
mdl->mats = calloc(mdl->nMats, sizeof *mdl->mats); | |
if(fread(mdl->mats, sizeof *mdl->mats, mdl->nMats, f) != mdl->nMats) | |
goto error; | |
for(i = 0; i < mdl->nMats; i++) { | |
ms3d_material *m = &mdl->mats[i]; | |
printf("Material %d: '%s'; '%s'\n", i, m->name, m->texture); | |
} | |
if(fread(&mdl->animFps, sizeof mdl->animFps, 1, f) != 1 || | |
fread(&mdl->currTime, sizeof mdl->currTime, 1, f) != 1 || | |
fread(&mdl->totalFrames, sizeof mdl->totalFrames, 1, f) != 1) | |
goto error; | |
printf("animFps: %f\ncurrTime: %f\ntotalFrames: %d\n", mdl->animFps, mdl->currTime, mdl->totalFrames); | |
if(fread(&mdl->nJoints, sizeof mdl->nJoints, 1, f) != 1) | |
goto error; | |
printf("Joints: %d\n", mdl->nJoints); | |
mdl->joints = calloc(mdl->nJoints, sizeof *mdl->joints); | |
for(i = 0; i < mdl->nJoints; i++) { | |
ms3d_joint *j = &mdl->joints[i]; | |
if(fread(j, (sizeof *j) - (sizeof j->keyFramesRot) - (sizeof j->keyFramesPos), 1, f) != 1) | |
goto error; | |
printf("Joint %d: '%s' (%s) [%d;%d]\n", i, j->name, j->parentName, j->nKeyFramesRot, j->nKeyFramesPos); | |
j->keyFramesRot = calloc(j->nKeyFramesRot, sizeof *j->keyFramesRot); | |
j->keyFramesPos = calloc(j->nKeyFramesPos, sizeof *j->keyFramesPos); | |
if(fread(j->keyFramesRot, sizeof *j->keyFramesRot, j->nKeyFramesRot, f) != j->nKeyFramesRot || | |
fread(j->keyFramesPos, sizeof *j->keyFramesPos, j->nKeyFramesPos, f) != j->nKeyFramesPos) | |
goto error; | |
} | |
printf("success\n"); | |
goto done; | |
error: | |
ms3d_free(mdl); | |
mdl = NULL; | |
done: | |
fclose(f); | |
return mdl; | |
} | |
void ms3d_free(ms3d_model *mdl) { | |
int i; | |
if(!mdl) return; | |
if(mdl->verts) free(mdl->verts); | |
if(mdl->tris) free(mdl->tris); | |
if(mdl->grps) { | |
for(i = 0; i < mdl->nGrps; i++) { | |
if(mdl->grps[i].triIdx) free(mdl->grps[i].triIdx); | |
} | |
free(mdl->grps); | |
} | |
if(mdl->mats) free(mdl->mats); | |
if(mdl->joints) { | |
for(i = 0; i < mdl->nJoints; i++) { | |
if(mdl->joints[i].keyFramesRot) free(mdl->joints[i].keyFramesRot); | |
if(mdl->joints[i].keyFramesPos) free(mdl->joints[i].keyFramesPos); | |
} | |
free(mdl->joints); | |
} | |
free(mdl); | |
} | |
int main(int argc, char *argv[]) { | |
ms3d_model *mdl = ms3d_load("Animatedlion.ms3d"); | |
if(!mdl) { | |
fprintf(stderr, "error\n"); | |
return 1; | |
} | |
ms3d_free(mdl); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment