From a5aa4b54e23d0793793384a6794cc543ea48ad34 Mon Sep 17 00:00:00 2001 From: neoraider Date: Mon, 14 May 2007 17:38:01 +0000 Subject: libzoom: XML level loader implemented. zoom: Converted old test level to XML. --- level.c | 370 ++++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 304 insertions(+), 66 deletions(-) (limited to 'level.c') diff --git a/level.c b/level.c index e7b8343..0d22f64 100644 --- a/level.c +++ b/level.c @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include extern GLuint sphere; @@ -15,66 +18,281 @@ extern float objrot; extern LIGHT *lights; extern int nLights; -int LoadLevel(char *filename, LEVEL *level) { - FILE *file; - LEVELHEADER levelheader; - ROOMHEADER roomheader; - int i, j; - unsigned char c; - unsigned char buffer[260]; - - strcpy(buffer, "levels/"); - strcat(buffer, filename); - file = fopen(buffer, "rb"); - if(!file) return 0; - - fread(&levelheader, sizeof(LEVELHEADER), 1, file); - if(levelheader.l != 'L' || levelheader.f != 'F') { - fclose(file); - return 0; - } - - level->nRooms = levelheader.nRooms; - level->rooms = malloc(levelheader.nRooms * sizeof(ROOM)); - - for(i = 0; i < levelheader.nRooms; i++) { - fread(&roomheader, sizeof(ROOMHEADER), 1, file); - - level->rooms[i].nWalls = roomheader.nWalls; - level->rooms[i].walls = malloc(roomheader.nWalls * sizeof(WALL)); - fread(level->rooms[i].walls, sizeof(WALL), roomheader.nWalls, file); - - level->rooms[i].nThings = roomheader.nThings; - level->rooms[i].things = malloc(roomheader.nThings * sizeof(THING)); - fread(level->rooms[i].things, sizeof(THING), roomheader.nThings, file); - - level->rooms[i].nGates = roomheader.nGates; - level->rooms[i].gates = malloc(roomheader.nGates * sizeof(GATE)); - fread(level->rooms[i].gates, sizeof(GATE), roomheader.nGates, file); - - level->rooms[i].gateinfo = malloc(roomheader.nGates * sizeof(GATEINFO)); - for(j = 0; j < level->rooms[i].nGates; j++) level->rooms[i].gateinfo[j].state = STATE_CLOSED; - } - - level->nTextures = levelheader.nTextures; - level->textures = malloc(levelheader.nTextures * sizeof(GLuint)); - - for(i = 0; i < levelheader.nTextures; i++) { - fread(&c, 1, 1, file); - fread(buffer, c, 1, file); - buffer[c] = 0; - level->textures[i] = LoadTexture(buffer); - } - - fclose(file); - return 1; + +static int SortTextures(const void *t1, const void *t2) { + return strcmp(((TEXTURE*)t1)->name, ((TEXTURE*)t2)->name); +} + + +LEVEL *LoadLevel(char *filename) { + LEVEL *level; + xmlDocPtr doc; + xmlDtdPtr dtd; + xmlValidCtxtPtr validCtxt; + xmlNodePtr root, node, node2, node3, rooms = NULL; + xmlChar *data; + char *name; + int i, j, k; + VECTOR v; + TEXTURE tex; + TEXTURE *texp; + + + name = malloc(strlen(filename)+8); + strcpy(name, "levels/"); + strcat(name, filename); + + doc = xmlParseFile(name); + + free(name); + + if(!doc) + return NULL; + + dtd = xmlParseDTD("-//libzoom//DTD level 0.1//EN", "levels/level.dtd"); + + if(!dtd) { + xmlFreeDoc(doc); + xmlCleanupParser(); + return NULL; + } + + validCtxt = xmlNewValidCtxt(); + + if(!validCtxt) { + xmlFreeDtd(dtd); + xmlFreeDoc(doc); + xmlCleanupParser(); + return NULL; + } + + if(!xmlValidateDtd(validCtxt, doc, dtd)) { + xmlFreeValidCtxt(validCtxt); + xmlFreeDtd(dtd); + xmlFreeDoc(doc); + xmlCleanupParser(); + return NULL; + } + + xmlFreeValidCtxt(validCtxt); + xmlFreeDtd(dtd); + + root = xmlDocGetRootElement(doc); + if(!root || xmlStrcmp(root->name, "level")) { + xmlFreeDoc(doc); + xmlCleanupParser(); + return NULL; + } + + level = calloc(1, sizeof(LEVEL)); + + for(node = root->children; node = node->next; node != NULL) { + if(node->type != XML_ELEMENT_NODE) continue; + + if(!xmlStrcmp(node->name, "info")) { + level->info = calloc(1, sizeof(LEVELINFO)); + + for(node2 = node->children; node2 = node2->next; node2 != NULL) { + if(node2->type != XML_ELEMENT_NODE) continue; + + if(!xmlStrcmp(node2->name, "name")) { + if(level->info->name != NULL) continue; + + data = xmlNodeGetContent(node2); + level->info->name = strdup(data); + xmlFree(data); + } + else if(!xmlStrcmp(node2->name, "desc")) { + if(level->info->desc != NULL) continue; + + data = xmlNodeGetContent(node2); + level->info->desc = strdup(data); + xmlFree(data); + } + else if(!xmlStrcmp(node2->name, "start")) { + data = xmlGetProp(node2, "x"); + if(data) level->info->start.x = atof(data); + xmlFree(data); + + data = xmlGetProp(node2, "y"); + if(data) level->info->start.y = atof(data); + xmlFree(data); + + data = xmlGetProp(node2, "z"); + if(data) level->info->start.z = atof(data); + xmlFree(data); + } + } + } + else if(!xmlStrcmp(node->name, "rooms")) { + if(rooms != NULL) continue; + + rooms = node; + + for(node2 = node->children; node2 = node2->next; node2 != NULL) { + if(node2->type == XML_ELEMENT_NODE && !xmlStrcmp(node2->name, "room")) level->nRooms++; + } + } + else if(!xmlStrcmp(node->name, "textures")) { + if(level->textures != NULL) continue; + + for(node2 = node->children; node2 = node2->next; node2 != NULL) { + if(node2->type == XML_ELEMENT_NODE && !xmlStrcmp(node2->name, "texture")) level->nTextures++; + } + + level->textures = calloc(level->nTextures, sizeof(TEXTURE)); + + i = 0; + for(node2 = node->children; node2 = node2->next; node2 != NULL) { + if(node2->type != XML_ELEMENT_NODE || xmlStrcmp(node2->name, "texture")) continue; + + data = xmlGetProp(node2, "name"); + if(data) { + level->textures[i].id = LoadTexture(data); + + xmlFree(data); + } + + data = xmlGetProp(node2, "id"); + if(data) { + level->textures[i].name = strdup(data); + + xmlFree(data); + } + + i++; + } + + qsort(level->textures, level->nTextures, sizeof(TEXTURE), SortTextures); + } + } + + level->rooms = calloc(level->nRooms, sizeof(ROOM)); + + i = 0; + for(node = rooms->children; node = node->next; node != NULL) { + if(node->type != XML_ELEMENT_NODE || xmlStrcmp(node->name, "room")) continue; + + for(node2 = node->children; node2 = node2->next; node2 != NULL) { + if(node2->type == XML_ELEMENT_NODE && !xmlStrcmp(node2->name, "triangle")) level->rooms[i].nWalls++; + } + + level->rooms[i].walls = calloc(level->rooms[i].nWalls, sizeof(WALL)); + + j = 0; + for(node2 = node->children; node2 = node2->next; node2 != NULL) { + if(node2->type != XML_ELEMENT_NODE || xmlStrcmp(node2->name, "triangle")) continue; + + data = xmlGetProp(node2, "type"); + if(data) { + if(!xmlStrcmp(data, "wall")) level->rooms[i].walls[j].type = TRIANGLE_WALL; + else if(!xmlStrcmp(data, "floor")) level->rooms[i].walls[j].type = TRIANGLE_FLOOR; + else level->rooms[i].walls[j].type = TRIANGLE_UNKNOWN; + xmlFree(data); + } + + level->rooms[i].walls[j].visible = 1; + data = xmlGetProp(node2, "visible"); + if(data) { + if(!xmlStrcmp(data, "false")) level->rooms[i].walls[j].visible = 0; + xmlFree(data); + } + + data = xmlGetProp(node2, "texture"); + if(data) { + tex.name = data; + texp = bsearch(&tex, level->textures, level->nTextures, sizeof(TEXTURE), SortTextures); + + if(texp) level->rooms[i].walls[j].texture = texp->id; + + xmlFree(data); + } + + k = -1; + for(node3 = node2->children; node3 = node3->next; node3 != NULL) { + if(node3->type != XML_ELEMENT_NODE) continue; + + if(!xmlStrcmp(node3->name, "vertex")) { + if(++k > 2) break; + + data = xmlGetProp(node3, "x"); + if(data) { + level->rooms[i].walls[j].vertices[k].x = atof(data); + xmlFree(data); + } + + data = xmlGetProp(node3, "y"); + if(data) { + level->rooms[i].walls[j].vertices[k].y = atof(data); + xmlFree(data); + } + + data = xmlGetProp(node3, "z"); + if(data) { + level->rooms[i].walls[j].vertices[k].z = atof(data); + xmlFree(data); + } + } + else if(!xmlStrcmp(node3->name, "normal")) { + if(k < 0) continue; + + data = xmlGetProp(node3, "x"); + if(data) { + level->rooms[i].walls[j].normals[k].x = atof(data); + xmlFree(data); + } + + data = xmlGetProp(node3, "y"); + if(data) { + level->rooms[i].walls[j].normals[k].y = atof(data); + xmlFree(data); + } + + data = xmlGetProp(node3, "z"); + if(data) { + level->rooms[i].walls[j].normals[k].z = atof(data); + xmlFree(data); + } + } + else if(!xmlStrcmp(node3->name, "texcoords")) { + if(k < 0) continue; + + data = xmlGetProp(node3, "s"); + if(data) { + level->rooms[i].walls[j].texcoords[k].s = atof(data); + xmlFree(data); + } + + data = xmlGetProp(node3, "t"); + if(data) { + level->rooms[i].walls[j].texcoords[k].t = atof(data); + xmlFree(data); + } + } + } + v = VectorCross( + VectorSub(level->rooms[i].walls[j].vertices[1], level->rooms[i].walls[j].vertices[0]), + VectorSub(level->rooms[i].walls[j].vertices[2], level->rooms[i].walls[j].vertices[0]) + ); + if(VectorLengthSq(v)) level->rooms[i].walls[j].normal = VectorNormalize(v); + + j++; + } + + i++; + } + + xmlFreeDoc(doc); + xmlCleanupParser(); + + return level; } POLYGON_LIST *DrawRoom(LEVEL *level, int nr) { ROOM room = level->rooms[nr]; POLYGON_LIST *p; int i; - + p = malloc(sizeof(POLYGON_LIST)+sizeof(POLYGON)*room.nWalls); p->nPolygons = room.nWalls; @@ -84,8 +302,11 @@ POLYGON_LIST *DrawRoom(LEVEL *level, int nr) { p->polygons[i].vertices[2] = room.walls[i].vertices[2]; p->polygons[i].normal = room.walls[i].normal; + p->polygons[i].normals[0] = room.walls[i].normals[0]; + p->polygons[i].normals[1] = room.walls[i].normals[1]; + p->polygons[i].normals[2] = room.walls[i].normals[2]; - p->polygons[i].texture = level->textures[room.walls[i].texture]; + p->polygons[i].texture = room.walls[i].texture; p->polygons[i].texcoords[0] = room.walls[i].texcoords[0]; p->polygons[i].texcoords[1] = room.walls[i].texcoords[1]; @@ -334,15 +555,32 @@ POLYGON_LIST *DrawRoom(LEVEL *level, int nr) { void FreeLevel(LEVEL *level) { int i; - if(level->nRooms) { - for(i = 0; i < level->nRooms; i++) { - if(level->rooms[i].nWalls) free(level->rooms[i].walls); - if(level->rooms[i].nThings) free(level->rooms[i].things); - if(level->rooms[i].nGates) { - free(level->rooms[i].gates); - free(level->rooms[i].gateinfo); - } - } - free(level->rooms); - } + if(level) { + if(level->info) { + free(level->info->name); + free(level->info->desc); + free(level->info); + } + + if(level->nRooms) { + for(i = 0; i < level->nRooms; i++) { + if(level->rooms[i].nWalls) free(level->rooms[i].walls); + if(level->rooms[i].nThings) free(level->rooms[i].things); + if(level->rooms[i].nGates) { + free(level->rooms[i].gates); + free(level->rooms[i].gateinfo); + } + } + free(level->rooms); + } + + if(level->nTextures) { + for(i = 0; i < level->nTextures; i++) + free(level->textures[i].name); + + free(level->textures); + } + + free(level); + } } -- cgit v1.2.3