summaryrefslogtreecommitdiffstats
path: root/level.c
blob: ccee0bc836662e97836e9b8b97dbfb4dfb363f01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <zoom/types.h>
#include <zoom/level.h>
#include <zoom/texture.h>
#include <neofx/math.h>

extern GLuint sphere;
extern GLuint meditex_blue;
extern float objrot;

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].nObjects = roomheader.nObjects;
		level->rooms[i].objects = malloc(roomheader.nObjects * sizeof(OBJECT));
		fread(level->rooms[i].objects, sizeof(OBJECT), roomheader.nObjects, 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;
}

void DrawRoom(LEVEL *level, int room) {
	int i;
	int r, g;
	GLfloat std_emission[] = {0.0, 0.0, 0.0, 1.0};
	GLfloat medipak100_emission[] = {1.0, 0.0, 0.0, 1.0};
	WALL t1, t2;
	VERTEX p1, p2;
	VECTOR v1, v2;
	MATRIX transform;
	
	for(i = 0; i < level->rooms[room].nWalls; i++) {
		glBindTexture(GL_TEXTURE_2D, level->textures[level->rooms[room].walls[i].texture]);
		
		glBegin(GL_TRIANGLES);
		
		glNormal3fv((GLfloat*)&level->rooms[room].walls[i].normal);
		glTexCoord2fv((GLfloat*)&level->rooms[room].walls[i].texcoords[0]);
		glVertex3fv((GLfloat*)&level->rooms[room].walls[i].vertices[0]);
		glTexCoord2fv((GLfloat*)&level->rooms[room].walls[i].texcoords[1]);
		glVertex3fv((GLfloat*)&level->rooms[room].walls[i].vertices[1]);
		glTexCoord2fv((GLfloat*)&level->rooms[room].walls[i].texcoords[2]);
		glVertex3fv((GLfloat*)&level->rooms[room].walls[i].vertices[2]);
		
		glEnd();
	}
	
	for(i = 0; i < level->rooms[room].nObjects; i++) {
		if(!level->rooms[room].objects[i].visible) continue;
		switch(level->rooms[room].objects[i].type) {
			case OBJECT_MEDIPAK100:
				glPushMatrix();
				glBindTexture(GL_TEXTURE_2D, meditex_blue);
				glMaterialfv(GL_FRONT, GL_EMISSION, medipak100_emission);
				glTranslatef(level->rooms[room].objects[i].pos.x, level->rooms[room].objects[i].pos.y, level->rooms[room].objects[i].pos.z);
				glRotatef(objrot*10, 0.0, 1.0, 0.0);
				glScalef(0.3, 0.3, 0.3);
				glCallList(sphere);
				glMaterialfv(GL_FRONT, GL_EMISSION, std_emission);
				glPopMatrix();
		}
	}
	
	for(i = 0; i < level->rooms[room].nGates; i++) {
		if(level->rooms[room].gateinfo[i].state == STATE_CLOSED) {
			glBindTexture(GL_TEXTURE_2D, level->textures[level->rooms[room].gates[i].walls[0].texture]);
			
			glBegin(GL_TRIANGLES);
			
			glNormal3fv((GLfloat*)&level->rooms[room].gates[i].walls[0].normal);
			glTexCoord2fv((GLfloat*)&level->rooms[room].gates[i].walls[0].texcoords[0]);
			glVertex3fv((GLfloat*)&level->rooms[room].gates[i].walls[0].vertices[0]);
			glTexCoord2fv((GLfloat*)&level->rooms[room].gates[i].walls[0].texcoords[1]);
			glVertex3fv((GLfloat*)&level->rooms[room].gates[i].walls[0].vertices[1]);
			glTexCoord2fv((GLfloat*)&level->rooms[room].gates[i].walls[0].texcoords[2]);
			glVertex3fv((GLfloat*)&level->rooms[room].gates[i].walls[0].vertices[2]);
			
			glEnd();
			
			glBindTexture(GL_TEXTURE_2D, level->textures[level->rooms[room].gates[i].walls[0].texture]);
			
			glBegin(GL_TRIANGLES);
			
			glNormal3fv((GLfloat*)&level->rooms[room].gates[i].walls[1].normal);
			glTexCoord2fv((GLfloat*)&level->rooms[room].gates[i].walls[1].texcoords[0]);
			glVertex3fv((GLfloat*)&level->rooms[room].gates[i].walls[1].vertices[0]);
			glTexCoord2fv((GLfloat*)&level->rooms[room].gates[i].walls[1].texcoords[1]);
			glVertex3fv((GLfloat*)&level->rooms[room].gates[i].walls[1].vertices[1]);
			glTexCoord2fv((GLfloat*)&level->rooms[room].gates[i].walls[1].texcoords[2]);
			glVertex3fv((GLfloat*)&level->rooms[room].gates[i].walls[1].vertices[2]);
			
			glEnd();
		}
		else if(level->rooms[room].gateinfo[i].state == STATE_OPENING) {
			t1 = level->rooms[room].gates[i].walls[0];
			t2 = level->rooms[room].gates[i].walls[1];
			
			t1.vertices[2] = VectorAdd(VectorMul(t1.vertices[2], level->rooms[room].gateinfo[i].timer/1000.0),
									VectorMul(t1.vertices[1], 1 - (level->rooms[room].gateinfo[i].timer/1000.0)));
			t2.vertices[1] = t1.vertices[2];
			t2.vertices[2] = VectorAdd(VectorMul(t2.vertices[2], level->rooms[room].gateinfo[i].timer/1000.0),
									VectorMul(t2.vertices[0], 1 - (level->rooms[room].gateinfo[i].timer/1000.0)));
			
			
			t1.texcoords[0].s = t1.texcoords[0].s * level->rooms[room].gateinfo[i].timer/1000.0
						+ t2.texcoords[2].s * (1 - level->rooms[room].gateinfo[i].timer/1000.0);
			t1.texcoords[0].t = t1.texcoords[0].t * level->rooms[room].gateinfo[i].timer/1000.0
						+ t2.texcoords[2].t * (1 - level->rooms[room].gateinfo[i].timer/1000.0);
			t1.texcoords[1].s = t1.texcoords[1].s * level->rooms[room].gateinfo[i].timer/1000.0
						+ t1.texcoords[2].s * (1 - level->rooms[room].gateinfo[i].timer/1000.0);
			t1.texcoords[1].t = t1.texcoords[1].t * level->rooms[room].gateinfo[i].timer/1000.0
						+ t1.texcoords[2].t * (1 - level->rooms[room].gateinfo[i].timer/1000.0);
			t2.texcoords[0] = t1.texcoords[0];
			
			glBindTexture(GL_TEXTURE_2D, level->textures[t1.texture]);
			
			glBegin(GL_TRIANGLES);
			
			glNormal3fv((GLfloat*)&t1.normal);
			glTexCoord2fv((GLfloat*)&t1.texcoords[0]);
			glVertex3fv((GLfloat*)&t1.vertices[0]);
			glTexCoord2fv((GLfloat*)&t1.texcoords[1]);
			glVertex3fv((GLfloat*)&t1.vertices[1]);
			glTexCoord2fv((GLfloat*)&t1.texcoords[2]);
			glVertex3fv((GLfloat*)&t1.vertices[2]);
			
			glEnd();
			
			glBindTexture(GL_TEXTURE_2D, level->textures[t2.texture]);
			
			glBegin(GL_TRIANGLES);
			
			glNormal3fv((GLfloat*)&t2.normal);
			glTexCoord2fv((GLfloat*)&t2.texcoords[0]);
			glVertex3fv((GLfloat*)&t2.vertices[0]);
			glTexCoord2fv((GLfloat*)&t2.texcoords[1]);
			glVertex3fv((GLfloat*)&t2.vertices[1]);
			glTexCoord2fv((GLfloat*)&t2.texcoords[2]);
			glVertex3fv((GLfloat*)&t2.vertices[2]);
			
			glEnd();
			
			r = level->rooms[room].gates[i].room;
			g = level->rooms[room].gates[i].gate;
			
			t1 = level->rooms[room].gates[i].walls[0];
			t2 = level->rooms[room].gates[i].walls[1];
			p1 = level->rooms[room].gates[i].point;
			v1 = t1.normal;
			
			t1 = level->rooms[r].gates[g].walls[0];
			t2 = level->rooms[r].gates[g].walls[1];
			p2 = level->rooms[r].gates[g].point;
			v2 = VectorNeg(t1.normal);
			
			glPushMatrix();
			transform = VectorMatrix(p1, v1, p2, v2);
			glMultMatrixf(transform.f);
			DrawRoom(level, r);
			glPopMatrix();
		}
		else if(level->rooms[room].gateinfo[i].state == STATE_CLOSING) {
			t1 = level->rooms[room].gates[i].walls[0];
			t2 = level->rooms[room].gates[i].walls[1];
			
			t1.vertices[2] = VectorAdd(VectorMul(t1.vertices[2], 1 - (level->rooms[room].gateinfo[i].timer/1000.0)),
									VectorMul(t1.vertices[1], level->rooms[room].gateinfo[i].timer/1000.0));
			t2.vertices[1] = t1.vertices[2];
			t2.vertices[2] = VectorAdd(VectorMul(t2.vertices[2], 1 - (level->rooms[room].gateinfo[i].timer/1000.0)),
									VectorMul(t2.vertices[0], level->rooms[room].gateinfo[i].timer/1000.0));
			
			
			t1.texcoords[0].s = t1.texcoords[0].s * (1 - level->rooms[room].gateinfo[i].timer/1000.0)
						+ t2.texcoords[2].s * level->rooms[room].gateinfo[i].timer/1000.0;
			t1.texcoords[0].t = t1.texcoords[0].t * (1 - level->rooms[room].gateinfo[i].timer/1000.0)
						+ t2.texcoords[2].t * level->rooms[room].gateinfo[i].timer/1000.0;
			t1.texcoords[1].s = t1.texcoords[1].s * (1 - level->rooms[room].gateinfo[i].timer/1000.0)
						+ t1.texcoords[2].s * level->rooms[room].gateinfo[i].timer/1000.0;
			t1.texcoords[1].t = t1.texcoords[1].t * (1 - level->rooms[room].gateinfo[i].timer/1000.0)
						+ t1.texcoords[2].t * level->rooms[room].gateinfo[i].timer/1000.0;
			t2.texcoords[0] = t1.texcoords[0];
			
			glBindTexture(GL_TEXTURE_2D, level->textures[t1.texture]);
			
			glBegin(GL_TRIANGLES);
			
			glNormal3fv((GLfloat*)&t1.normal);
			glTexCoord2fv((GLfloat*)&t1.texcoords[0]);
			glVertex3fv((GLfloat*)&t1.vertices[0]);
			glTexCoord2fv((GLfloat*)&t1.texcoords[1]);
			glVertex3fv((GLfloat*)&t1.vertices[1]);
			glTexCoord2fv((GLfloat*)&t1.texcoords[2]);
			glVertex3fv((GLfloat*)&t1.vertices[2]);
			
			glEnd();
			
			glBindTexture(GL_TEXTURE_2D, level->textures[t2.texture]);
			
			glBegin(GL_TRIANGLES);
			
			glNormal3fv((GLfloat*)&t2.normal);
			glTexCoord2fv((GLfloat*)&t2.texcoords[0]);
			glVertex3fv((GLfloat*)&t2.vertices[0]);
			glTexCoord2fv((GLfloat*)&t2.texcoords[1]);
			glVertex3fv((GLfloat*)&t2.vertices[1]);
			glTexCoord2fv((GLfloat*)&t2.texcoords[2]);
			glVertex3fv((GLfloat*)&t2.vertices[2]);
			
			glEnd();
			
			r = level->rooms[room].gates[i].room;
			g = level->rooms[room].gates[i].gate;
			
			t1 = level->rooms[room].gates[i].walls[0];
			t2 = level->rooms[room].gates[i].walls[1];
			p1 = level->rooms[room].gates[i].point;
			v1 = t1.normal;
			
			t1 = level->rooms[r].gates[g].walls[0];
			t2 = level->rooms[r].gates[g].walls[1];
			p2 = level->rooms[r].gates[g].point;
			v2 = VectorNeg(t1.normal);
			
			glPushMatrix();
			transform = VectorMatrix(p1, v1, p2, v2);
			glMultMatrixf(transform.f);
			DrawRoom(level, r);
			glPopMatrix();
		}
		else {
			r = level->rooms[room].gates[i].room;
			g = level->rooms[room].gates[i].gate;
			
			t1 = level->rooms[room].gates[i].walls[0];
			t2 = level->rooms[room].gates[i].walls[1];
			p1 = level->rooms[room].gates[i].point;
			v1 = t1.normal;
			
			t1 = level->rooms[r].gates[g].walls[0];
			t2 = level->rooms[r].gates[g].walls[1];
			p2 = level->rooms[r].gates[g].point;
			v2 = VectorNeg(t1.normal);
			
			glPushMatrix();
			transform = VectorMatrix(p1, v1, p2, v2);
			glMultMatrixf(transform.f);
			DrawRoom(level, r);
			glPopMatrix();
		}
	}
}

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].nObjects) free(level->rooms[i].objects);
			if(level->rooms[i].nGates) free(level->rooms[i].gates);
		}
		free(level->rooms);
	}
}