libzoom: XML level loader implemented.

zoom: Converted old test level to XML.
This commit is contained in:
neoraider 2007-05-14 17:38:01 +00:00
parent 4069752dbc
commit a5aa4b54e2
6 changed files with 389 additions and 151 deletions

6
init.c
View file

@ -6,7 +6,7 @@
#include <zoom/level.h> #include <zoom/level.h>
#include <zoom/light.h> #include <zoom/light.h>
LEVEL level; LEVEL *level;
GLuint sphere; GLuint sphere;
GLuint meditex_blue; GLuint meditex_blue;
GLuint lightmap; GLuint lightmap;
@ -57,7 +57,7 @@ int InitGame() {
gluQuadricDrawStyle(quadric, GLU_FILL); gluQuadricDrawStyle(quadric, GLU_FILL);
gluQuadricTexture(quadric, GL_TRUE); gluQuadricTexture(quadric, GL_TRUE);
LoadLevel("level2.lvl", &level); level = LoadLevel("level.lvl");
sphere = glGenLists(1); sphere = glGenLists(1);
glNewList(sphere, GL_COMPILE); glNewList(sphere, GL_COMPILE);
@ -71,6 +71,6 @@ int InitGame() {
} }
void UninitGame() { void UninitGame() {
FreeLevel(&level); FreeLevel(level);
free(texlist); free(texlist);
} }

346
level.c
View file

@ -7,6 +7,9 @@
#include <zoom/texture.h> #include <zoom/texture.h>
#include <zoom/level.h> #include <zoom/level.h>
#include <zoom/light.h> #include <zoom/light.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/valid.h>
extern GLuint sphere; extern GLuint sphere;
@ -15,59 +18,274 @@ extern float objrot;
extern LIGHT *lights; extern LIGHT *lights;
extern int nLights; 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/"); static int SortTextures(const void *t1, const void *t2) {
strcat(buffer, filename); return strcmp(((TEXTURE*)t1)->name, ((TEXTURE*)t2)->name);
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 *LoadLevel(char *filename) {
level->rooms = malloc(levelheader.nRooms * sizeof(ROOM)); 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;
for(i = 0; i < levelheader.nRooms; i++) {
fread(&roomheader, sizeof(ROOMHEADER), 1, file);
level->rooms[i].nWalls = roomheader.nWalls; name = malloc(strlen(filename)+8);
level->rooms[i].walls = malloc(roomheader.nWalls * sizeof(WALL)); strcpy(name, "levels/");
fread(level->rooms[i].walls, sizeof(WALL), roomheader.nWalls, file); strcat(name, filename);
level->rooms[i].nThings = roomheader.nThings; doc = xmlParseFile(name);
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; free(name);
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)); if(!doc)
for(j = 0; j < level->rooms[i].nGates; j++) level->rooms[i].gateinfo[j].state = STATE_CLOSED; return NULL;
}
level->nTextures = levelheader.nTextures; dtd = xmlParseDTD("-//libzoom//DTD level 0.1//EN", "levels/level.dtd");
level->textures = malloc(levelheader.nTextures * sizeof(GLuint));
for(i = 0; i < levelheader.nTextures; i++) { if(!dtd) {
fread(&c, 1, 1, file); xmlFreeDoc(doc);
fread(buffer, c, 1, file); xmlCleanupParser();
buffer[c] = 0; return NULL;
level->textures[i] = LoadTexture(buffer); }
}
fclose(file); validCtxt = xmlNewValidCtxt();
return 1;
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) { POLYGON_LIST *DrawRoom(LEVEL *level, int nr) {
@ -84,8 +302,11 @@ POLYGON_LIST *DrawRoom(LEVEL *level, int nr) {
p->polygons[i].vertices[2] = room.walls[i].vertices[2]; p->polygons[i].vertices[2] = room.walls[i].vertices[2];
p->polygons[i].normal = room.walls[i].normal; 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[0] = room.walls[i].texcoords[0];
p->polygons[i].texcoords[1] = room.walls[i].texcoords[1]; 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) { void FreeLevel(LEVEL *level) {
int i; int i;
if(level->nRooms) { if(level) {
for(i = 0; i < level->nRooms; i++) { if(level->info) {
if(level->rooms[i].nWalls) free(level->rooms[i].walls); free(level->info->name);
if(level->rooms[i].nThings) free(level->rooms[i].things); free(level->info->desc);
if(level->rooms[i].nGates) { free(level->info);
free(level->rooms[i].gates); }
free(level->rooms[i].gateinfo);
} if(level->nRooms) {
} for(i = 0; i < level->nRooms; i++) {
free(level->rooms); 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);
}
} }

View file

@ -20,7 +20,7 @@ float rotxspeed = 0, rotyspeed = 0;
float objrot = 0; float objrot = 0;
extern LEVEL level; extern LEVEL *level;
extern int nLights; extern int nLights;
extern LIGHT *lights; extern LIGHT *lights;
@ -77,7 +77,7 @@ void DoInput(int delta) {
s = player.rotysin; s = player.rotysin;
c = player.rotycos; c = player.rotycos;
if(!falling) { if(!falling) {
if((input & INPUT_UP) && !(input & INPUT_DOWN)) { if((input & INPUT_UP) && !(input & INPUT_DOWN)) {
if((input & INPUT_RIGHT) && !(input & INPUT_LEFT)) { if((input & INPUT_RIGHT) && !(input & INPUT_LEFT)) {
move.x = (s+c)*M_SQRT1_2; move.x = (s+c)*M_SQRT1_2;
@ -115,12 +115,12 @@ void DoInput(int delta) {
move.z = -s; move.z = -s;
} }
if(input & INPUT_OPEN) { if(input & INPUT_OPEN) {
for(i = 0; i < level.rooms[room].nGates; i++) { for(i = 0; i < level->rooms[room].nGates; i++) {
if(level.rooms[room].gateinfo[i].state != STATE_CLOSED) continue; if(level->rooms[room].gateinfo[i].state != STATE_CLOSED) continue;
if(CollisionSphereTriangle(player.pos, 1.0, level.rooms[room].gates[i].walls[0].triangle) || if(CollisionSphereTriangle(player.pos, 1.0, level->rooms[room].gates[i].walls[0].triangle) ||
CollisionSphereTriangle(player.pos, 1.0, level.rooms[room].gates[i].walls[1].triangle)) { CollisionSphereTriangle(player.pos, 1.0, level->rooms[room].gates[i].walls[1].triangle)) {
level.rooms[room].gateinfo[i].state = STATE_OPENING; level->rooms[room].gateinfo[i].state = STATE_OPENING;
level.rooms[room].gateinfo[i].timer = 1000; level->rooms[room].gateinfo[i].timer = 1000;
} }
} }
} }
@ -130,21 +130,21 @@ void DoInput(int delta) {
if(falling) pos.y -= delta/100.0; if(falling) pos.y -= delta/100.0;
for(i = 0; i < level.rooms[room].nGates; i++) { /*for(i = 0; i < level->rooms[room].nGates; i++) {
if(CollisionSphereTriangle(pos, 0.3, level.rooms[room].gates[i].walls[0].triangle) || if(CollisionSphereTriangle(pos, 0.3, level->rooms[room].gates[i].walls[0].triangle) ||
CollisionSphereTriangle(pos, 0.3, level.rooms[room].gates[i].walls[1].triangle)) { CollisionSphereTriangle(pos, 0.3, level->rooms[room].gates[i].walls[1].triangle)) {
if(level.rooms[room].gateinfo[i].state == STATE_OPENED) { if(level->rooms[room].gateinfo[i].state == STATE_OPENED) {
if(CollisionPointTriangle(pos, level.rooms[room].gates[i].walls[0].triangle) || if(CollisionPointTriangle(pos, level->rooms[room].gates[i].walls[0].triangle) ||
CollisionPointTriangle(pos, level.rooms[room].gates[i].walls[1].triangle)) { CollisionPointTriangle(pos, level->rooms[room].gates[i].walls[1].triangle)) {
p1 = level.rooms[room].gates[i].point; p1 = level->rooms[room].gates[i].point;
v1 = level.rooms[room].gates[i].walls[0].normal; v1 = level->rooms[room].gates[i].walls[0].normal;
level.rooms[room].gateinfo[i].state = STATE_CLOSED; level->rooms[room].gateinfo[i].state = STATE_CLOSED;
g = level.rooms[room].gates[i].gate; g = level->rooms[room].gates[i].gate;
room = level.rooms[room].gates[i].room; room = level->rooms[room].gates[i].room;
p2 = level.rooms[room].gates[g].point; p2 = level->rooms[room].gates[g].point;
v2 = VectorNeg(level.rooms[room].gates[g].walls[0].normal); v2 = VectorNeg(level->rooms[room].gates[g].walls[0].normal);
level.rooms[room].gateinfo[g].state = STATE_OPENED; level->rooms[room].gateinfo[g].state = STATE_OPENED;
level.rooms[room].gateinfo[g].timer = 5000; level->rooms[room].gateinfo[g].timer = 5000;
transform = VectorMatrix(p2, v2, p1, v1); transform = VectorMatrix(p2, v2, p1, v1);
pos = VectorMatrixMul(pos, transform); pos = VectorMatrixMul(pos, transform);
v1.x = p1.x + c; v1.x = p1.x + c;
@ -155,33 +155,33 @@ void DoInput(int delta) {
move = VectorSub(VectorMatrixMul(VectorAdd(move, p1), transform), p2); move = VectorSub(VectorMatrixMul(VectorAdd(move, p1), transform), p2);
break; break;
} }
level.rooms[room].gateinfo[i].timer = 5000; level->rooms[room].gateinfo[i].timer = 5000;
} }
else pos = player.pos; else pos = player.pos;
} }
} }*/
falling = 1; falling = 1;
for(i = 0; i < level.rooms[room].nWalls; i++) { for(i = 0; i < level->rooms[room].nWalls; i++) {
if(level.rooms[room].walls[i].type == TRIANGLE_WALL && if(level->rooms[room].walls[i].type == TRIANGLE_WALL &&
CollisionMovingSphereTriangle(VectorSub(pos, VectorMul(move, delta/150.0)), 0.3, move, delta/150.0, level.rooms[room].walls[i].triangle)) { CollisionMovingSphereTriangle(VectorSub(pos, VectorMul(move, delta/150.0)), 0.3, move, delta/150.0, level->rooms[room].walls[i].triangle)) {
pos = player.pos; pos = player.pos;
if(player.room != room) { if(player.room != room) {
level.rooms[room].gateinfo[g].state = STATE_CLOSED; level->rooms[room].gateinfo[g].state = STATE_CLOSED;
g = level.rooms[room].gates[g].gate; g = level->rooms[room].gates[g].gate;
room = player.room; room = player.room;
level.rooms[room].gateinfo[g].state = STATE_OPENED; level->rooms[room].gateinfo[g].state = STATE_OPENED;
} }
s = player.rotysin; s = player.rotysin;
c = player.rotycos; c = player.rotycos;
falling = 0; falling = 0;
break; break;
} }
else if(level.rooms[room].walls[i].type == TRIANGLE_FLOOR) { else if(level->rooms[room].walls[i].type == TRIANGLE_FLOOR) {
pos.y -= 1.81; pos.y -= 1.81;
if(CollisionPointTriangle(pos, level.rooms[room].walls[i].triangle)) { if(CollisionPointTriangle(pos, level->rooms[room].walls[i].triangle)) {
falling = 0; falling = 0;
pos.y += 1.81; pos.y += 1.81;
if(wasfalling && CollisionRayTriangle(pos, v, level.rooms[room].walls[i].triangle, &f)) pos.y -= f - 1.8; if(wasfalling && CollisionRayTriangle(pos, v, level->rooms[room].walls[i].triangle, &f)) pos.y -= f - 1.8;
} }
else pos.y += 1.81; else pos.y += 1.81;
} }
@ -191,29 +191,29 @@ void DoInput(int delta) {
player.rotysin = s; player.rotysin = s;
player.rotycos = c; player.rotycos = c;
for(i = 0; i < level.rooms[player.room].nThings; i++) { for(i = 0; i < level->rooms[player.room].nThings; i++) {
pos = VectorSub(level.rooms[player.room].things[i].pos, player.pos); pos = VectorSub(level->rooms[player.room].things[i].pos, player.pos);
pos.y += 0.9; pos.y += 0.9;
switch(level.rooms[player.room].things[i].type) { switch(level->rooms[player.room].things[i].type) {
case THING_MEDIPAK100: case THING_MEDIPAK100:
if((pos.x*pos.x + (pos.y*pos.y)/3 + pos.z*pos.z) < 0.36) level.rooms[player.room].things[i].visible = 0; if((pos.x*pos.x + (pos.y*pos.y)/3 + pos.z*pos.z) < 0.36) level->rooms[player.room].things[i].visible = 0;
} }
} }
for(i = 0; i < level.rooms[player.room].nGates; i++) { for(i = 0; i < level->rooms[player.room].nGates; i++) {
if(level.rooms[player.room].gateinfo[i].state == STATE_CLOSED) continue; if(level->rooms[player.room].gateinfo[i].state == STATE_CLOSED) continue;
if((level.rooms[player.room].gateinfo[i].timer - delta) < 0) { if((level->rooms[player.room].gateinfo[i].timer - delta) < 0) {
if(level.rooms[player.room].gateinfo[i].state == STATE_OPENING) { if(level->rooms[player.room].gateinfo[i].state == STATE_OPENING) {
level.rooms[player.room].gateinfo[i].state = STATE_OPENED; level->rooms[player.room].gateinfo[i].state = STATE_OPENED;
level.rooms[player.room].gateinfo[i].timer = 5000; level->rooms[player.room].gateinfo[i].timer = 5000;
} }
else if(level.rooms[player.room].gateinfo[i].state == STATE_OPENED) { else if(level->rooms[player.room].gateinfo[i].state == STATE_OPENED) {
level.rooms[player.room].gateinfo[i].state = STATE_CLOSING; level->rooms[player.room].gateinfo[i].state = STATE_CLOSING;
level.rooms[player.room].gateinfo[i].timer = 1000; level->rooms[player.room].gateinfo[i].timer = 1000;
} }
else level.rooms[player.room].gateinfo[i].state = STATE_CLOSED; else level->rooms[player.room].gateinfo[i].state = STATE_CLOSED;
} }
else level.rooms[player.room].gateinfo[i].timer -= delta; else level->rooms[player.room].gateinfo[i].timer -= delta;
} }
static int lightpos = 0; static int lightpos = 0;

View file

@ -10,7 +10,7 @@
extern PLAYER player; extern PLAYER player;
extern LEVEL level; extern LEVEL *level;
extern GLuint sphere; extern GLuint sphere;
extern int nLights; extern int nLights;
extern LIGHT *lights; extern LIGHT *lights;
@ -47,7 +47,7 @@ void Render() {
glTranslatef(-player.pos.x, -player.pos.y, -player.pos.z); glTranslatef(-player.pos.x, -player.pos.y, -player.pos.z);
room = DrawRoom(&level, player.room); room = DrawRoom(level, player.room);
qsort(room->polygons, room->nPolygons, sizeof(POLYGON), SortByTex); qsort(room->polygons, room->nPolygons, sizeof(POLYGON), SortByTex);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
@ -118,14 +118,14 @@ void Render() {
c = VectorMul(lights[i].diffuse, 1.0/(d*d)); c = VectorMul(lights[i].diffuse, 1.0/(d*d));
glColor3fv((GLfloat*)&c); glColor3fv((GLfloat*)&c);
p = VectorAdd(lights[i].pos, VectorMul(room->polygons[j].normal, d));
v1 = VectorNormalize(VectorSub(room->polygons[j].vertices[0], room->polygons[j].vertices[1])); v1 = VectorNormalize(VectorSub(room->polygons[j].vertices[0], room->polygons[j].vertices[1]));
v2 = VectorCross(v1, room->polygons[j].normal);
for(k = 0; k < 3; k++) { for(k = 0; k < 3; k++) {
p = VectorAdd(lights[i].pos, VectorMul(room->polygons[j].normals[k], d));
v = VectorSub(room->polygons[j].vertices[k], p); v = VectorSub(room->polygons[j].vertices[k], p);
v2 = VectorCross(v1, room->polygons[j].normals[k]);
glMultiTexCoord2f(0, VectorDot(v, v1)*0.04 / d + 0.5, VectorDot(v, v2)*0.04 / d + 0.5); glMultiTexCoord2f(0, VectorDot(v, v1)*0.04 / d + 0.5, VectorDot(v, v2)*0.04 / d + 0.5);
glMultiTexCoord2fv(1, (GLfloat*)&room->polygons[j].texcoords[k]); glMultiTexCoord2fv(1, (GLfloat*)&room->polygons[j].texcoords[k]);
glVertex3fv((GLfloat*)&room->polygons[j].vertices[k]); glVertex3fv((GLfloat*)&room->polygons[j].vertices[k]);

View file

@ -5,45 +5,44 @@
#include <zoom/types.h> #include <zoom/types.h>
#include <zoom/render.h> #include <zoom/render.h>
#pragma pack(push, 2)
typedef struct _LEVELHEADER {
char l, f;
int nRooms;
int nTextures;
} LEVELHEADER;
typedef struct _ROOMHEADER {
int nWalls;
int nThings;
int nGates;
} ROOMHEADER;
typedef struct _GATEINFO { typedef struct _GATEINFO {
unsigned short state; unsigned short state;
unsigned short timer; unsigned short timer;
} GATEINFO; } GATEINFO;
typedef struct _ROOM { typedef struct _ROOM {
int nWalls; int nWalls;
int nThings; int nThings;
int nGates; int nGates;
WALL *walls; WALL *walls;
THING *things; THING *things;
GATE *gates; GATE *gates;
GATEINFO *gateinfo; GATEINFO *gateinfo;
} ROOM; } ROOM;
typedef struct _LEVELINFO {
char *name;
char *desc;
VERTEX start;
} LEVELINFO;
typedef struct _TEXTURE {
char *name;
GLuint id;
} TEXTURE;
typedef struct _LEVEL { typedef struct _LEVEL {
int nRooms; LEVELINFO *info;
ROOM *rooms; int nRooms;
int nTextures; ROOM *rooms;
GLuint *textures; int nTextures;
TEXTURE *textures;
} LEVEL; } LEVEL;
#pragma pack(pop)
typedef struct _POLYGON { typedef struct _POLYGON {
VECTOR normal;
VERTEX vertices[3]; VERTEX vertices[3];
VECTOR normal; VECTOR normals[3];
GLuint texture; GLuint texture;
TEXCOORDS texcoords[3]; TEXCOORDS texcoords[3];
@ -56,7 +55,7 @@ typedef struct _POLYGON_LIST {
} POLYGON_LIST; } POLYGON_LIST;
int LoadLevel(char *, LEVEL *); LEVEL *LoadLevel(char *);
POLYGON_LIST *DrawRoom(LEVEL *, int); POLYGON_LIST *DrawRoom(LEVEL *, int);
void FreeLevel(LEVEL *); void FreeLevel(LEVEL *);

View file

@ -32,6 +32,7 @@ typedef struct WALL {
VECTOR normal; VECTOR normal;
}; };
}; };
VECTOR normals[3];
int texture; int texture;
TEXCOORDS texcoords[3]; TEXCOORDS texcoords[3];
} WALL; } WALL;