Fix error message when SDL_ttf is not present.
[attac-man.git] / object.c
blobdad929415ef3f54d76b926ce7dd6f4329607de12
1 /*
2 Pacman Arena
3 Copyright (C) 2003 Nuno Subtil
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 static const char cvsid[] =
21 "$Id: object.c,v 1.26 2003/11/23 00:06:39 nsubtil Exp $";
23 #ifdef _WIN32
24 #include <windows.h>
25 #endif
27 #include <GL/gl.h>
28 #include <GL/glu.h>
29 #include <SDL.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
34 #include "linked-lists.h"
35 #include "object.h"
36 #include "game.h"
37 #include "map.h"
38 #include "game.h"
39 #include "screen.h"
40 #include "render.h"
41 #include "include/file.h"
43 struct ocache_entry *object_cache = NULL;
45 int object_hash_vertex(float vx[3])
47 int ret = -5;
49 if(vx[X] >= 0.0 && vx[Y] >= 0.0)
50 ret = 1;
52 if(vx[X] < 0.0 && vx[Y] >= 0.0)
53 ret = 2;
55 if(vx[X] < 0.0 && vx[Y] < 0.0)
56 ret = 3;
58 if(vx[X] >= 0.0 && vx[Y] < 0.0)
59 ret = 4;
61 if(vx[Z] >= 0.0)
62 ret += 4;
64 return ret - 1;
67 int object_hash_face(struct face_tri *face)
69 int a, b, c;
71 a = object_hash_vertex(face->a);
72 b = object_hash_vertex(face->b);
73 c = object_hash_vertex(face->c);
75 return (a + b + c) / 3;
78 void object_add_face(struct object *obj, struct face_tri *face)
80 obj->num_fc++;
81 obj->fc_list = realloc(obj->fc_list, sizeof(struct face_tri *) * obj->num_fc);
82 obj->fc_list[obj->num_fc - 1] = face;
86 procura um objecto na lista pelo nome do ficheiro correspondente
88 struct object *object_cache_find_file(char *fname, int *n_objs)
90 struct ocache_entry *cur;
92 cur = object_cache;
93 while(cur)
95 if(strcmp(cur->name, fname) == 0)
97 *n_objs = cur->n_objs;
98 return cur->objs;
101 cur = cur->next;
104 return NULL;
107 void object_cache_add_file(char *fname, struct object *objs, int n_objs)
109 struct ocache_entry *new;
111 new = malloc(sizeof(struct ocache_entry));
112 new->name = fname;
113 new->objs = objs;
114 new->n_objs = n_objs;
115 new->next = NULL;
117 LLIST_ADD(struct ocache_entry, object_cache, new);
120 int object_face_equal(struct face_tri *f1, struct face_tri *f2)
122 if(memcmp(f1->a, f2->a, sizeof(float) * 3) != 0)
123 return 0;
125 if(memcmp(f1->b, f2->b, sizeof(float) * 3) != 0)
126 return 0;
128 if(memcmp(f1->c, f2->c, sizeof(float) * 3) != 0)
129 return 0;
131 if(memcmp(f1->na, f2->na, sizeof(GLfloat) * 3) != 0)
132 return 0;
134 if(memcmp(f1->nb, f2->nb, sizeof(GLfloat) * 3) != 0)
135 return 0;
137 if(memcmp(f1->nc, f2->nc, sizeof(GLfloat) * 3) != 0)
138 return 0;
140 if(f1->color_tag != f2->color_tag)
141 return 0;
143 return 1;
146 /* XXX - que coisa lenta! */
147 int object_get_vertex_index(float **vx_list, int num_vx, float vec[3])
149 int c;
151 for(c = 0; c < num_vx; c++)
152 if(memcmp(vx_list[c], vec, sizeof(float) * 3) == 0)
153 return c;
155 return -1;
158 /* XXX - e este então nem se fala */
159 int object_get_face_index(struct face_tri **fc_list, int num_fc, struct face_tri *fc)
161 int c;
163 for(c = 0; c < num_fc; c++)
164 if(object_face_equal(fc_list[c], fc))
165 return c;
167 return -1;
171 formato:
172 num de vértices (4b)
173 lista de vértices (3f cada, sem repetições)
174 num de faces (4b)
175 lista de faces (sem repetições):
176 vértices a, b, c (índices na lista, 4b cada)
177 normais na, nb, nc (3 floats cada)
178 cor (4 floats)
179 tag de cor (1 byte)
180 num de objectos (4b)
181 lista de objectos:
182 num de faces do objecto
183 lista de índices das faces do objecto na lista de faces (4b cada)
185 XXX - isto é muito lento
187 void object_write_file(char *fname, struct object *objs, int n_objs)
189 FILE *fp;
190 int c, d;
191 float **vx_list[8];
192 int vx_num[8], vx_tot;
193 struct face_tri **fc_list[8];
194 int fc_num[8], fc_tot;
196 /* gerar lista de vértices */
197 printf("Building vertex list... ");
198 fflush(stdout);
200 for(c = 0; c < 8; c++)
202 vx_list[c] = NULL;
203 vx_num[c] = 0;
206 for(c = 0; c < n_objs; c++)
207 for(d = 0; d < objs[c].num_fc; d++)
209 int h;
211 h = object_hash_vertex(objs[c].fc_list[d]->a);
212 if(object_get_vertex_index(vx_list[h], vx_num[h], objs[c].fc_list[d]->a) == -1)
214 vx_num[h]++;
215 vx_list[h] = realloc(vx_list[h], vx_num[h] * sizeof(float *));
216 vx_list[h][vx_num[h] - 1] = objs[c].fc_list[d]->a;
219 h = object_hash_vertex(objs[c].fc_list[d]->b);
220 if(object_get_vertex_index(vx_list[h], vx_num[h], objs[c].fc_list[d]->b) == -1)
222 vx_num[h]++;
223 vx_list[h] = realloc(vx_list[h], vx_num[h] * sizeof(float *));
224 vx_list[h][vx_num[h] - 1] = objs[c].fc_list[d]->b;
227 h = object_hash_vertex(objs[c].fc_list[d]->c);
228 if(object_get_vertex_index(vx_list[h], vx_num[h], objs[c].fc_list[d]->c) == -1)
230 vx_num[h]++;
231 vx_list[h] = realloc(vx_list[h], vx_num[h] * sizeof(float *));
232 vx_list[h][vx_num[h] - 1] = objs[c].fc_list[d]->c;
237 vx_tot = 0;
238 for(c = 0; c < 8; c++)
239 vx_tot += vx_num[c];
241 printf("%d unique vertexes\n", vx_tot);
243 /* gerar lista de faces */
244 printf("Building face list... ");
245 fflush(stdout);
247 for(c = 0; c < 8; c++)
249 fc_list[c] = NULL;
250 fc_num[c] = 0;
253 for(c = 0; c < n_objs; c++)
254 for(d = 0; d < objs[c].num_fc; d++)
256 int h;
258 h = object_hash_face(objs[c].fc_list[d]);
259 if(object_get_face_index(fc_list[h], fc_num[h], objs[c].fc_list[d]) == -1)
261 /* face não existe na lista */
262 fc_num[h]++;
263 fc_list[h] = realloc(fc_list[h], fc_num[h] * sizeof(struct fc_tri *));
264 fc_list[h][fc_num[h] - 1] = objs[c].fc_list[d];
268 fc_tot = 0;
269 for(c = 0; c < 8; c++)
270 fc_tot += fc_num[c];
272 printf("%d unique faces\n", fc_tot);
274 fp = file_open(fname);
275 if(fp == NULL)
277 printf("object_write_file: parece que %s não dá para a coisa\n", fname);
278 exit(1);
282 /* escrever lista de vértices */
283 printf("Writing vertex list...");
284 fflush(stdout);
286 file_write_values32(&vx_tot, 1, fp);
287 for(d = 0; d < 8; d++)
288 for(c = 0; c < vx_num[d]; c++)
289 file_write_values32(vx_list[d][c], 3, fp);
291 /* escrever lista de faces */
292 printf("\nWriting face list...");
293 fflush(stdout);
295 file_write_values32(&fc_tot, 1, fp);
296 for(c = 0; c < 8; c++)
297 for(d = 0; d < fc_num[c]; d++)
299 int idx[3], h[3], e;
300 unsigned char tag;
302 h[0] = object_hash_vertex(fc_list[c][d]->a);
303 idx[0] = object_get_vertex_index(vx_list[h[0]], vx_num[h[0]], fc_list[c][d]->a);
304 h[1] = object_hash_vertex(fc_list[c][d]->b);
305 idx[1] = object_get_vertex_index(vx_list[h[1]], vx_num[h[1]], fc_list[c][d]->b);
306 h[2] = object_hash_vertex(fc_list[c][d]->c);
307 idx[2] = object_get_vertex_index(vx_list[h[2]], vx_num[h[2]], fc_list[c][d]->c);
309 if(idx[0] == -1 || idx[1] == -1 || idx[2] == -1)
311 printf("object_write_file: duh ?!\n");
312 abort();
315 for(e = 0; e < h[0]; e++)
316 idx[0] += vx_num[e];
318 for(e = 0; e < h[1]; e++)
319 idx[1] += vx_num[e];
321 for(e = 0; e < h[2]; e++)
322 idx[2] += vx_num[e];
324 file_write_values32(idx, 3, fp);
325 file_write_values32(fc_list[c][d]->na, 3, fp);
326 file_write_values32(fc_list[c][d]->nb, 3, fp);
327 file_write_values32(fc_list[c][d]->nc, 3, fp);
328 file_write_values32(fc_list[c][d]->color, 4, fp);
330 tag = fc_list[c][d]->color_tag & 0xff;
331 fwrite(&tag, 1, 1, fp);
334 printf("\nWriting objects... ");
335 fflush(stdout);
337 /* escrever objectos */
338 file_write_values32(&n_objs, 1, fp);
339 for(c = 0; c < n_objs; c++)
341 file_write_values32(&objs[c].num_fc, 1, fp);
342 for(d = 0; d < objs[c].num_fc; d++)
344 int i, h, e;
346 h = object_hash_face(objs[c].fc_list[d]);
347 i = object_get_face_index(fc_list[h], fc_num[h], objs[c].fc_list[d]);
349 if(i == -1)
351 printf("object_write_file: duh-duh!\n");
352 abort();
355 for(e = 0; e < h; e++)
356 i += fc_num[e];
358 file_write_values32(&i, 1, fp);
361 printf("%d ", c);
362 fflush(stdout);
365 printf("\n");
367 fclose(fp);
369 for(c = 0; c < 8; c++)
371 free(vx_list[c]);
372 free(fc_list[c]);
376 struct object *object_read_file(char *fname, int *n_objs)
378 FILE *fp;
379 int c, d;
380 float **vx_list;
381 int vx_num;
382 struct face_tri *fc_list;
383 int fc_num;
384 struct object *objs;
386 objs = object_cache_find_file(fname, n_objs);
388 if(objs)
389 return objs;
391 fp = file_open(fname);
392 if(fp == NULL)
394 printf("object_read_file: adonde 'tá a porcaria do %s ?\n", fname);
395 exit(1);
398 /* ler lista de vértices */
399 file_read_values32(&vx_num, 1, fp);
400 vx_list = malloc(sizeof(float *) * vx_num);
401 for(c = 0; c < vx_num; c++)
403 vx_list[c] = malloc(sizeof(float) * 3);
404 file_read_values32(vx_list[c], 3, fp);
407 /* ler lista de faces */
408 file_read_values32(&fc_num, 1, fp);
409 fc_list = malloc(sizeof(struct face_tri) * fc_num);
410 for(c = 0; c < fc_num; c++)
412 int idx[3];
413 unsigned char tag;
415 file_read_values32(idx, 3, fp);
416 fc_list[c].a = vx_list[idx[0]];
417 fc_list[c].b = vx_list[idx[1]];
418 fc_list[c].c = vx_list[idx[2]];
420 file_read_values32(fc_list[c].na, 3, fp);
421 file_read_values32(fc_list[c].nb, 3, fp);
422 file_read_values32(fc_list[c].nc, 3, fp);
424 file_read_values32(fc_list[c].color, 4, fp);
426 fread(&tag, 1, 1, fp);
427 fc_list[c].color_tag = (int)(tag & 0xff);
430 /* ler lista de objectos */
431 file_read_values32(n_objs, 1, fp);
432 printf("%s: %d objects (%d unique vertexes, %d unique faces)\n",
433 fname, *n_objs, vx_num, fc_num);
434 objs = malloc(sizeof(struct object) * (*n_objs));
435 for(c = 0; c < *n_objs; c++)
437 file_read_values32(&objs[c].num_fc, 1, fp);
438 objs[c].fc_list = malloc(sizeof(struct face_tri *) * objs[c].num_fc);
440 for(d = 0; d < objs[c].num_fc; d++)
442 int idx;
443 struct face_tri *face;
445 file_read_values32(&idx, 1, fp);
446 face = &fc_list[idx];
448 objs[c].fc_list[d] = face;
451 objs[c].dlist_color = -1;
452 objs[c].dlist_nocolor = -1;
454 /* evitar linkar o jogo todo no 3dsconv */
455 #ifndef TDSCONV
456 render_compile_dlist(&objs[c]);
457 #endif
460 fclose(fp);
461 free(vx_list);
463 object_cache_add_file(fname, objs, *n_objs);
465 return objs;
468 #ifndef TDSCONV
470 liberta todas as display lists na placa gráfica
472 void object_release_dlists(void)
474 struct ocache_entry *cur;
476 cur = object_cache;
477 while(cur)
479 int c;
481 for(c = 0; c < cur->n_objs; c++)
483 if(cur->objs[c].dlist_color != (GLuint)-1)
485 glDeleteLists(cur->objs[c].dlist_color, 1);
486 cur->objs[c].dlist_color = -1;
489 if(cur->objs[c].dlist_nocolor != (GLuint)-1)
491 glDeleteLists(cur->objs[c].dlist_nocolor, 1);
492 cur->objs[c].dlist_nocolor = -1;
496 cur = cur->next;
501 recompila display lists
503 void object_recompile_dlists(void)
505 struct ocache_entry *cur;
507 cur = object_cache;
508 while(cur)
510 int c;
512 for(c = 0; c < cur->n_objs; c++)
513 render_compile_dlist(&cur->objs[c]);
515 cur = cur->next;
518 #endif