#include #include #include #include #include #include "q3bsp.h" void print_direntries(struct q3bsp_header * header) { // direntries static const char * lump_name[] = { "entities", "textures", "planes", "nodes", "leafs", "leaffaces", "leafbrushes", "models", "brushes", "brushsides", "vertexes", "meshverts", "effects", "faces", "lightmaps", "lightvols", "visdata", }; for (int i = 0; i < 17; i++) { printf("%s offset=%d length=%d\n", lump_name[i], header->direntries[i].offset, header->direntries[i].length); } } void print_header(struct q3bsp_header * header) { printf("magic: "); putchar(header->magic[0]); putchar(header->magic[1]); putchar(header->magic[2]); putchar(header->magic[3]); putchar('\n'); printf("version: %x\n", header->version); print_direntries(header); } void print_textures(uint8_t * buf, struct q3bsp_header * header) { q3bsp_direntry * te = &header->direntries[LUMP_TEXTURES]; q3bsp_texture_t * textures = reinterpret_cast(&buf[te->offset]); int count = te->length / (sizeof (struct q3bsp_texture)); for (int i = 0; i < count; i++) { q3bsp_texture_t * texture = &textures[i]; printf("texture [%d]\n", i); printf(" name=%s\n", texture->name); printf(" flags=%x\n", texture->flags); printf(" contents=%x\n", texture->contents); } } void print_models(uint8_t * buf, struct q3bsp_header * header) { q3bsp_direntry * me = &header->direntries[LUMP_MODELS]; q3bsp_model_t * models = reinterpret_cast(&buf[me->offset]); int count = me->length / (sizeof (struct q3bsp_model)); for (int i = 0; i < count; i++) { q3bsp_model_t * model = &models[i]; printf("model [%d]\n", i); printf(" mins={%f, %f, %f}\n", model->mins[0], model->mins[2], model->mins[2]); printf(" maxs={%f, %f, %f}\n", model->maxs[0], model->maxs[2], model->maxs[2]); printf(" face=%d\n", model->face); printf(" n_faces=%d\n", model->n_faces); printf(" brush=%d\n", model->brush); printf(" n_brushes=%d\n", model->n_brushes); } } void print_vertexes(uint8_t * buf, struct q3bsp_header * header) { q3bsp_direntry * ve = &header->direntries[LUMP_VERTEXES]; q3bsp_vertex_t * vertexes = reinterpret_cast(&buf[ve->offset]); int count = ve->length / (sizeof (struct q3bsp_vertex)); printf("vertexes count: %d\n", count); for (int i = 0; i < count; i++) { q3bsp_vertex_t * vertex = &vertexes[i]; printf("vertex [%d]: lightmapcoord=(%f %f)\n", i, vertex->lightmapcoord[0], vertex->lightmapcoord[1]); //assert(vertex->lightmapcoord[0] >= 0.0 && vertex->lightmapcoord[0] <= 1.0); //assert(vertex->lightmapcoord[1] >= 0.0 && vertex->lightmapcoord[1] <= 1.0); } } void print_faces(uint8_t * buf, struct q3bsp_header * header) { q3bsp_direntry * fe = &header->direntries[LUMP_FACES]; q3bsp_face_t * faces = reinterpret_cast(&buf[fe->offset]); int count = fe->length / (sizeof (struct q3bsp_face)); printf("faces count: %d\n", count); for (int i = 0; i < count; i++) { q3bsp_face_t * face = &faces[i]; printf("face [%d]\n", i); printf(" type=%d n_vertexes=%d n_meshverts=%d texture=%d lightmap=%d\n", face->type, face->n_vertexes, face->n_meshverts, face->texture, face->lm_index); } } void print_lightmaps(uint8_t * buf, struct q3bsp_header * header) { q3bsp_direntry * lme = &header->direntries[LUMP_LIGHTMAPS]; q3bsp_lightmap_t * lightmaps = reinterpret_cast(&buf[lme->offset]); int count = lme->length / (sizeof (struct q3bsp_lightmap)); printf("lightmaps count: %d offset: %d\n", count, lme->offset); } void debug_print_q3bsp(uint8_t * buf, q3bsp_header_t * header) { // header //print_header(header); if (1) { print_textures(buf, header); } if (0) { print_models(buf, header); } if (0) { print_vertexes(buf, header); } if (0) { print_faces(buf, header); } if (0) { print_lightmaps(buf, header); } if (0) { q3bsp_direntry * fe = &header->direntries[LUMP_FACES]; q3bsp_face_t * faces = reinterpret_cast(&buf[fe->offset]); int face_count = fe->length / (sizeof (struct q3bsp_face)); q3bsp_direntry * te = &header->direntries[LUMP_TEXTURES]; q3bsp_texture_t * textures = reinterpret_cast(&buf[te->offset]); int texture_count = te->length / (sizeof (struct q3bsp_texture)); int texture_uses[texture_count] = {}; for (int i = 0; i < face_count; i++) { q3bsp_face_t * face = &faces[i]; texture_uses[face->texture] += 1; } for (int i = 0; i < texture_count; i++) { q3bsp_texture_t * texture = &textures[i]; printf("[%d] %s %d %08x\n", i, texture->name, texture_uses[i], texture->flags); } } } int read_file(const char * filename, uint8_t ** buf, uint32_t * size_out) { FILE * file = fopen(filename, "rb"); if (file == NULL) { fprintf(stderr, "fopen(\"%s\", \"rb\"): %s\n", filename, strerror(errno)); return -1; } int ret; ret = fseek(file, 0L, SEEK_END); if (ret < 0) { fprintf(stderr, "fseek(SEEK_END)"); return -1; } long offset = ftell(file); if (offset < 0) { fprintf(stderr, "ftell"); return -1; } size_t size = offset; ret = fseek(file, 0L, SEEK_SET); if (ret < 0) { fprintf(stderr, "fseek(SEEK_SET)"); return -1; } fprintf(stderr, "read_file: %s size %ld\n", filename, size); *buf = (uint8_t *)malloc(size); size_t fread_size = fread(*buf, 1, size, file); if (fread_size != size) { fprintf(stderr, "fread `%s` short read: %d ; expected: %d\n", filename, (int)fread_size, (int)size); return -1; } ret = fclose(file); if (ret < 0) { fprintf(stderr, "fclose"); return -1; } *size_out = size; return 0; } int main(int argc, const char * argv[]) { assert(argc == 2); const char * filename = argv[1]; uint8_t * buf; uint32_t size; int res = read_file(filename, &buf, &size); if (res != 0) return EXIT_FAILURE; q3bsp_header_t * header = reinterpret_cast(buf); debug_print_q3bsp(buf, header); return EXIT_SUCCESS; }