diff --git a/Makefile b/Makefile index 23ac41f..f945ff5 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CFLAGS= -I"include" all: main -main: devil1pld.o devil1tex.o +main: devil1pld.o devil1tex.o src/devil1geo.o $(CC) $^ test/main.c $(CFLAGS) -o $(EX) devil1pld.o: src/devil1pld.c @@ -13,5 +13,8 @@ devil1pld.o: src/devil1pld.c devil1tex.o: src/devil1tex.c $(CC) -c $^ $(CFLAGS) +devil1geo.o: src/devil1geo.c + $(CC) -c $^ $(CFLAGS) + clean: rm *.o $(EX) diff --git a/include/devil1geo.h b/include/devil1geo.h index 8d07d1c..048b5e1 100644 --- a/include/devil1geo.h +++ b/include/devil1geo.h @@ -2,7 +2,10 @@ #ifndef DEVIL1GEO_H #define DEVIL1GEO_H #include -#pragma pack(1) +#include + + +#pragma pack(push, 1) struct Header { unsigned char numMesh; unsigned char unknownNumberB; @@ -12,7 +15,7 @@ struct Header { uint64_t unknownOffset; }; -struct MeshHeaders { +struct MeshHeader { int16_t numBatch; int16_t numVertex; uint32_t u; // @@ -20,11 +23,7 @@ struct MeshHeaders { uint64_t flags; }; // put these in an array of size: [header.numMesh] -struct Positions { - float x, y, z; -}; - -struct Normals { +struct Coordinate { float x, y, z; }; @@ -40,9 +39,7 @@ struct BoneWeights { uint16_t weights; // }; -// This is where most of the parsing will be. -// this struct is in-order of what the file format will have. -struct Batch { +struct BatchData { int16_t numVertex; int16_t uB; uint32_t padding; // @@ -52,18 +49,43 @@ struct Batch { uint64_t offsetBoneIndexes; // uint64_t offsetBoneWeights; // uint64_t offsets[1]; // - int64_t pos; // set while parsing batch from ftell(); - // following structs should in an array of size numVertex - struct Positions *p; - struct Normals *n; +}; + +struct VertexData { + // following structs should in an array of size 'numVertex' + struct Coordinate *positions; + struct Coordinate *normals; struct UVs *u; struct BoneIndexes *bi; struct BoneWeights *bw; }; -struct Mesh { - struct Batch b; +struct Batch { + struct BatchData *bd; // pointer to region in file data + struct VertexData vd; // collection of pointers to regions in file data }; +struct Mesh { + // array of batches + struct Batch *b; +}; + +#pragma pack(pop) + +void printgheader(struct Header*); + +void printmeshheader(struct MeshHeader*); + +void printmeshbatch(struct Batch*); + +void printcoordinate(struct Coordinate*, unsigned int); + +// ** = 'pass by reference' of a pointer to struct +bool getmeshheader(struct MeshHeader**, unsigned int i, const char * const); + +bool getmeshbatch(struct Batch*, unsigned int offset, const char * const); + +bool getmesh(struct Mesh*, unsigned int i, const char* filename); + #endif diff --git a/src/devil1geo.c b/src/devil1geo.c new file mode 100644 index 0000000..401eafe --- /dev/null +++ b/src/devil1geo.c @@ -0,0 +1,115 @@ +#include "devil1geo.h" +#include + +void printgheader(struct Header *gh) { + if (gh != NULL) { + printf("pointer %x\n", gh); + printf("number of meshes %x\n", gh -> numMesh); + printf("unknown number B %x\n", gh -> unknownNumberB); + printf("unknown number C %x\n", gh -> unknownNumberC); + printf("unknown number D %x\n", gh -> unknownNumberD); + printf("padding %x\n", gh -> padding); + printf("unknown offset %x\n", gh -> unknownOffset); + } +} + +void printmeshheader(struct MeshHeader *mh) { + if (mh == NULL) { + return; + } + printf("number of batches %x\n", mh -> numBatch); + printf("number of vertices %x\n", mh -> numVertex); + printf("unknown %x\n", mh -> u); + printf("batch offset %x\n", mh -> offsetBatches); + printf("flags %x\n\n", mh -> flags); +} + +void printmeshbatch(struct Batch *b) { + if (b == NULL) { + return; + } + struct BatchData *bd = b -> bd; + printf("number of vertices %x\n", bd -> numVertex); + printf("unknown byte %x\n", bd -> uB); + printf("padding %x\n", bd -> padding); + printf("offsetPositions %x\n", bd -> offsetPositions); + printf("offsetNormals %x\n", bd -> offsetNormals); + printf("offsetUVs %x\n", bd -> offsetUVs); + printf("offsetBoneIndexes %x\n", bd -> offsetBoneIndexes); + printf("offsetBoneWeights %x\n", bd -> offsetBoneWeights); + printf("offsets %x\n\n", bd -> offsets[0]); + printcoordinate(b -> vd.positions, 3); +} + +void printcoordinate(struct Coordinate *p, unsigned int count) { + if (p == NULL) { + return; + } + unsigned int i; + for (i = 0; i < count; i++) { + printf("(%f, %f, %f)\n", (p[i]).x, (p[i]).y, (p[i]).z); + } +} + +bool getmeshheader(struct MeshHeader **hs, + unsigned int i, + const char * const filedata) { + bool done = false; + if (hs == NULL || filedata == NULL) { + return done; + } + struct Header *h = (struct Header*)filedata; + if (h -> numMesh < i) { + return done; + } + unsigned int pos = sizeof(struct MeshHeader) * i + sizeof(struct Header); + (*hs) = (struct MeshHeader*)(filedata + pos); + done = true; + return done; +} + +bool getmeshbatch(struct Batch *b, + unsigned int offset, + const char * const filedata) { + bool done = false; + if (b == NULL || filedata == NULL) { + return done; + } + struct BatchData *d1 = NULL; + struct VertexData d2; + d1 = (struct BatchData*) (filedata + offset); + d2.positions = (struct Coordinate*) (filedata + (d1 -> offsetPositions)); + d2.normals = (struct Coordinate*) (filedata + (d1 -> offsetNormals)); + d2.u = (struct UVs*) (filedata + (d1 -> offsetUVs)); + d2.bi = (struct BoneIndexes*)(filedata + (d1 -> offsetBoneIndexes)); + d2.bw = (struct BoneWeights*)(filedata + (d1 -> offsetBoneWeights)); + b -> bd = d1; + b -> vd = d2; + done = true; + return done; +} + +// assume client has allocated memory for mesh +bool getmesh(struct Mesh *m, + unsigned int i, + const char * const filedata) { + bool done = false; + if (m == NULL || filedata == NULL || m -> b == NULL) { + return done; + } + struct MeshHeader *mh = NULL; + bool ok = getmeshheader(&mh, i, filedata); + if (ok) { + unsigned int j; + struct Batch b; + for (j = 0; j < mh -> numBatch; j++) { + unsigned int offset = mh->offsetBatches + j * sizeof(struct BatchData); + getmeshbatch(&b, offset, filedata); + printmeshbatch(&b); + m -> b[j] = b; + } + done = true; + } + return done; +} + diff --git a/test/main.c b/test/main.c index 1c70c73..881b260 100644 --- a/test/main.c +++ b/test/main.c @@ -5,6 +5,7 @@ #include "devil1pld.h" #include "devil1tex.h" +#include "devil1geo.h" #define TYPE_ID_LENGTH 4 @@ -116,13 +117,37 @@ void exporttextures(const char *filedata, return; } +void extractmeshes(const char *filedata, + unsigned int filesize, + const char *filename) { + if (filedata == NULL || filesize <= 0) { + return; + } + struct Header *h = (struct Header*)filedata; + struct MeshHeader *mh = NULL; + struct Mesh m; + m.b = NULL; + unsigned int i; + for (i = 0; i < h -> numMesh; i++) { + getmeshheader(&mh, i, filedata); + m.b = (struct Batch*)malloc(sizeof(struct Batch) * (mh -> numBatch)); + if (m.b != NULL) { + getmesh(&m, i, filedata); + // do something with mesh e.g write to file. + free(m.b); + } + } // end for +} + int main(int argc, char ** argv) { char *f = argv[1]; unsigned int bufsize = 0; char *buffer = loadfile(f, &bufsize); - unpackpld(buffer, bufsize, f); +// unpackpld(buffer, bufsize, f); // exporttextures(buffer, bufsize, f); + extractmeshes(buffer, bufsize, f); free(buffer); return 0; } +