Update paths/build/package name/etc. to 'attac-man'
[attac-man.git] / render.c
blobc715dd32014ea0e241671d5a8bb26ea0fb8cd700
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: render.c,v 1.46 2003/11/22 17:32:10 nsubtil Exp $";
23 #ifdef _WIN32
24 #include <windows.h>
25 #endif
27 #include <SDL.h>
28 #include <GL/gl.h>
29 #include <GL/glu.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
34 #include "linked-lists.h"
35 #include "object.h"
36 #include "m_math.h"
37 #include "gfx.h"
38 #include "game.h"
39 #include "map.h"
40 #include "player.h"
41 #include "screen.h"
43 #include "render.h"
44 #include "render_bomb.h"
47 desenha um objecto
49 void render_object(struct object *o)
51 int c;
52 GLfloat last_color[4];
54 memcpy(last_color, o->fc_list[0]->color, sizeof(last_color));
55 glColor4fv(last_color);
57 glBegin(GL_TRIANGLES);
59 for(c = 0; c < o->num_fc; c++)
61 if(memcmp(last_color, o->fc_list[c]->color, sizeof(last_color)) != 0)
63 memcpy(last_color, o->fc_list[c]->color, sizeof(last_color));
64 glColor4fv(last_color);
67 glNormal3fv(o->fc_list[c]->na);
68 glVertex3fv(o->fc_list[c]->a);
70 glNormal3fv(o->fc_list[c]->nb);
71 glVertex3fv(o->fc_list[c]->b);
73 glNormal3fv(o->fc_list[c]->nc);
74 glVertex3fv(o->fc_list[c]->c);
77 glEnd();
81 desenha os polígonos com cor definida de um objecto
83 void render_object_colored_polygons(struct object *o)
85 int c;
86 GLfloat last_color[4];
88 /* tirar a primeira cor */
89 for(c = 0; c < o->num_fc; c++)
90 if(!o->fc_list[0]->color_tag)
92 memcpy(last_color, o->fc_list[0]->color, sizeof(last_color));
93 break;
96 glColor4fv(last_color);
97 glBegin(GL_TRIANGLES);
99 for(c = 0; c < o->num_fc; c++)
100 if(!o->fc_list[c]->color_tag)
102 if(memcmp(last_color, o->fc_list[c]->color, sizeof(last_color)) != 0)
104 memcpy(last_color, o->fc_list[c]->color, sizeof(last_color));
105 glColor4fv(last_color);
108 glNormal3fv(o->fc_list[c]->na);
109 glVertex3fv(o->fc_list[c]->a);
111 glNormal3fv(o->fc_list[c]->nb);
112 glVertex3fv(o->fc_list[c]->b);
114 glNormal3fv(o->fc_list[c]->nc);
115 glVertex3fv(o->fc_list[c]->c);
118 glEnd();
122 desenha polígonos sem cor
124 void render_object_no_colored_polygons(struct object *o)
126 int c;
128 glBegin(GL_TRIANGLES);
130 for(c = 0; c < o->num_fc; c++)
131 if(o->fc_list[c]->color_tag)
133 glNormal3fv(o->fc_list[c]->na);
134 glVertex3fv(o->fc_list[c]->a);
136 glNormal3fv(o->fc_list[c]->nb);
137 glVertex3fv(o->fc_list[c]->b);
139 glNormal3fv(o->fc_list[c]->nc);
140 glVertex3fv(o->fc_list[c]->c);
143 glEnd();
146 void render_object_color_tag(struct object *o, GLfloat color[4])
148 int c;
149 GLfloat last_color[4];
151 if(o->fc_list[0]->color_tag)
152 memcpy(last_color, color, sizeof(last_color));
153 else
154 memcpy(last_color, o->fc_list[0]->color, sizeof(last_color));
155 glColor4fv(last_color);
157 glBegin(GL_TRIANGLES);
159 for(c = 0; c < o->num_fc; c++)
161 if(o->fc_list[c]->color_tag)
163 if(memcmp(last_color, color, sizeof(last_color)) != 0)
165 memcpy(last_color, color, sizeof(last_color));
166 glColor4fv(last_color);
168 } else {
169 if(memcmp(last_color, o->fc_list[c]->color, sizeof(last_color)) != 0)
171 memcpy(last_color, o->fc_list[c]->color, sizeof(last_color));
172 glColor4fv(last_color);
176 glNormal3fv(o->fc_list[c]->na);
177 glVertex3fv(o->fc_list[c]->a);
179 glNormal3fv(o->fc_list[c]->nb);
180 glVertex3fv(o->fc_list[c]->b);
182 glNormal3fv(o->fc_list[c]->nc);
183 glVertex3fv(o->fc_list[c]->c);
186 glEnd();
190 desenha um objecto por display lists
192 void render_dlist(struct object *o, GLfloat *color)
194 if(o->dlist_color != -1)
196 glCallList(o->dlist_color);
197 if(color)
198 glColor4fv(color);
200 glCallList(o->dlist_nocolor);
201 } else {
202 if(color)
203 render_object_color_tag(o, color);
204 else
205 render_object(o);
210 compila a display list de um objecto
212 void render_compile_dlist(struct object *o)
214 if(o->dlist_color != -1)
216 glDeleteLists(o->dlist_color, 1);
217 glDeleteLists(o->dlist_nocolor, 1);
220 o->dlist_color = glGenLists(1);
221 glNewList(o->dlist_color, GL_COMPILE);
222 render_object_colored_polygons(o);
223 glEndList();
225 o->dlist_nocolor = glGenLists(1);
226 glNewList(o->dlist_nocolor, GL_COMPILE);
227 render_object_no_colored_polygons(o);
228 glEndList();
232 inicia o desenho de uma nova frame
234 void render_start_frame(void)
236 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
239 void render_setup(struct game *game, int player_no)
241 struct camera *camera;
242 struct viewport *vp;
244 /* light0: centro do mapa, aponta para baixo, spot branco */
245 GLfloat light0_ambient[] = {0.1, 0.1, 0.1, 1.0};
246 GLfloat light0_diffuse[] = {0.8, 0.8, 0.8, 1.0};
247 GLfloat light0_specular[] = {0.0, 0.0, 0.0, 1.0};
248 GLfloat light0_position[] =
249 {(GLfloat)game->map->width / 2.0, -15.0, (GLfloat)game->map->height / 2.0, 1.0};
250 GLfloat light0_direction[] =
251 {0.0, 1.0, 0.0, 1.0};
252 GLfloat light0_spot_cutoff = 90.0 * (game->map->width * game->map->height) / (31 * 31);
253 GLfloat light0_spot_exponent = 1.0;
254 /* attn: constant, linear, quadratic */
255 GLfloat light0_attn[] = {1.0, 0.0, 0.0};
257 /* light1: por cima do pacman, aponta para baixo, spot amarelo */
258 GLfloat light1_ambient[] = {0.0, 0.0, 0.0, 1.0};
259 GLfloat light1_diffuse[] = {1.0, 0.0, 0.0, 1.0};
260 GLfloat light1_specular[] = {0.0, 0.0, 0.0, 1.0};
261 /* XXX! */
262 GLfloat light1_position[] =
263 // {(GLfloat)players[0].position[X], -15.0, (GLfloat)players[0].position[Z], 1.0};
264 {0.0, 0.0, 0.0, 1.0};
265 GLfloat light1_direction[] =
266 {0.0, 1.0, 0.0, 1.0};
267 GLfloat light1_spot_cutoff = 20.0;
268 GLfloat light1_spot_exponent = 20.0;
269 GLfloat light1_attn[] = {1.0, 0.0, 0.0};
271 if(player_no == -1)
273 /* special case: demo mode */
274 camera = game->demo_camera;
275 screen_set_active_viewport(0);
276 vp = screen_get_viewport(0);
277 } else {
278 camera = game->players[player_no].camera;
279 screen_set_active_viewport(player_no);
280 vp = screen_get_viewport(player_no);
283 glMatrixMode(GL_MODELVIEW);
284 glLoadIdentity();
286 glMatrixMode(GL_PROJECTION);
287 glLoadIdentity();
288 glFrustum(-1.0, 1.0,
289 -1.0 * (GLfloat)vp->height / (GLfloat)vp->width,
290 1.0 * (GLfloat)vp->height / (GLfloat)vp->width, 1.0, 70.0);
292 gluLookAt(camera->pos[X], camera->pos[Y], camera->pos[Z],
293 camera->dir[X], camera->dir[Y], camera->dir[Z],
294 camera->pos[X] - camera->up[X],
295 camera->pos[Y] - camera->up[Y],
296 camera->pos[Z] - camera->up[Z]);
298 glEnable(GL_LINE_SMOOTH);
299 glHint(GL_LINE_SMOOTH, GL_NICEST);
301 glEnable(GL_CULL_FACE);
302 glCullFace(GL_BACK);
304 glEnable(GL_LIGHTING);
306 /* light 0 */
307 glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
308 glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
309 glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
310 glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
311 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0_direction);
313 glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, light0_spot_cutoff);
314 glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, light0_spot_exponent);
315 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, light0_attn[0]);
316 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, light0_attn[1]);
317 glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, light0_attn[2]);
319 glEnable(GL_LIGHT0);
321 if(game->n_players > 0)
323 light1_position[X] = (GLfloat)game->players[0].position[X];
324 light1_position[Y] = -15.0;
325 light1_position[Z] = (GLfloat)game->players[0].position[Z];
327 /* light 1 */
328 glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
329 glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
330 glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
331 glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
332 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light1_direction);
334 glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, light1_spot_cutoff);
335 glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light1_spot_exponent);
336 glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, light1_attn[0]);
337 glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light1_attn[1]);
338 glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light1_attn[2]);
341 glEnable(GL_COLOR_MATERIAL);
343 glDepthFunc(GL_LEQUAL);
347 calcula a geometria world-space de um quad
348 perpendicular à camera com size de lado
350 static GLfloat plane_vertexes[4][3];
351 static GLuint plane_dlist = -1;
352 void render_setup_plane_geometry(struct camera *camera, float size)
354 float tmp[3], cam[3], up[3];
356 math_sub_vec3(cam, camera->dir, camera->pos);
357 math_sub_vec3(up, camera->up, camera->pos);
358 math_rotate_vec3(tmp, cam, up, 90.0);
360 math_add_vec3(plane_vertexes[0], tmp, up);
361 math_scale_vec3(plane_vertexes[0], -1.0, plane_vertexes[0]);
362 math_len_vec3(plane_vertexes[0], plane_vertexes[0], size / 2.0);
364 math_sub_vec3(plane_vertexes[1], tmp, up);
365 math_len_vec3(plane_vertexes[1], plane_vertexes[1], size / 2.0);
367 math_add_vec3(plane_vertexes[2], tmp, up);
368 math_len_vec3(plane_vertexes[2], plane_vertexes[2], size / 2.0);
370 math_sub_vec3(plane_vertexes[3], up, tmp);
371 math_len_vec3(plane_vertexes[3], plane_vertexes[3], size / 2.0);
373 if(plane_dlist == -1)
374 plane_dlist = glGenLists(1);
376 glNewList(plane_dlist, GL_COMPILE);
378 glBegin(GL_QUADS);
379 glTexCoord2f(0.0, 1.0);
380 glVertex3fv(plane_vertexes[3]);
381 glTexCoord2f(1.0, 1.0);
382 glVertex3fv(plane_vertexes[2]);
383 glTexCoord2f(1.0, 0.0);
384 glVertex3fv(plane_vertexes[1]);
385 glTexCoord2f(0.0, 0.0);
386 glVertex3fv(plane_vertexes[0]);
387 glEnd();
389 glEndList();
393 desenha um quad perpendicular à camera
394 com origem em (x, y, z) e size de lado
396 void render_draw_plane(GLfloat x, GLfloat y, GLfloat z, GLfloat alpha)
398 glMatrixMode(GL_MODELVIEW);
399 glLoadIdentity();
400 glTranslatef(x, y, z);
402 glBlendFunc(GL_ONE, GL_ONE);
403 glColor4f(alpha, alpha, alpha, 1.0);
405 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
407 glCallList(plane_dlist);
410 void render_draw_colored_plane(GLfloat x, GLfloat y, GLfloat z, GLfloat color[3], GLfloat alpha)
412 glMatrixMode(GL_MODELVIEW);
413 glLoadIdentity();
414 glTranslatef(x, y, z);
416 glBlendFunc(GL_ONE, GL_ONE);
417 glColor4f(color[R] - (1.0 - alpha),
418 color[G] - (1.0 - alpha),
419 color[B] - (1.0 - alpha),
420 1.0);
421 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
423 glCallList(plane_dlist);
427 termina o desenho de uma frame
429 void render_finish_frame(void)
431 glFlush();
432 SDL_GL_SwapBuffers();
436 desenha os eixos
438 void render_draw_axes(float length)
440 glMatrixMode(GL_MODELVIEW);
441 glLoadIdentity();
443 glDisable(GL_BLEND);
444 glEnable(GL_DEPTH_TEST);
445 glDepthMask(GL_TRUE);
446 glDisable(GL_LIGHTING);
447 glDisable(GL_LINE_SMOOTH);
449 glBegin(GL_LINES);
451 /* x */
452 glColor3f(0.25, 0.0, 0.0);
453 glVertex3f(-length, 0.0, 0.0);
454 glColor3f(1.0, 0.0, 0.0);
455 glVertex3f(length, 0.0, 0.0);
457 /* y */
458 glColor3f(0.0, 0.25, 0.0);
459 glVertex3f(0.0, -length, 0.0);
460 glColor3f(0.0, 1.0, 0.0);
461 glVertex3f(0.0, length, 0.0);
463 /* z */
464 glColor3f(0.0, 0.0, 0.25);
465 glVertex3f(0.0, 0.0, -length);
466 glColor3f(0.0, 0.0, 1.0);
467 glVertex3f(0.0, 0.0, length);
469 glEnd();
473 posiciona a câmera em world-space
475 void render_move_camera(struct camera *camera, float x, float y, float z)
477 float cam[3], up[3];
479 math_sub_vec3(cam, camera->dir, camera->pos);
480 math_sub_vec3(up, camera->up, camera->pos);
482 camera->pos[X] = x;
483 camera->pos[Y] = y;
484 camera->pos[Z] = z;
486 math_add_vec3(camera->dir, camera->pos, cam);
487 math_add_vec3(camera->up, camera->pos, up);
491 translacção da camera em world-space
493 void render_translate_camera(struct camera *camera, float x, float y, float z)
495 camera->pos[X] += x;
496 camera->pos[Y] += y;
497 camera->pos[Z] += z;
499 camera->up[X] += x;
500 camera->up[Y] += y;
501 camera->up[Z] += z;
503 camera->dir[X] += x;
504 camera->dir[Y] += y;
505 camera->dir[Z] += z;
509 aponta a câmera para um ponto
511 void render_point_camera(struct camera *camera, float x, float y, float z)
513 float cam[3], up[3];
515 cam[X] = x - camera->pos[X];
516 cam[Y] = y - camera->pos[Y];
517 cam[Z] = z - camera->pos[Z];
519 up[X] = 0.0;
520 up[Y] = 1.0;
521 up[Z] = 0.0;
523 math_gschmidt_2vec3(up, cam, up);
524 math_len_vec3(cam, cam, 1.0);
525 math_len_vec3(up, up, 1.0);
527 math_add_vec3(camera->dir, camera->pos, cam);
528 math_add_vec3(camera->up, camera->pos, up);
532 camera em (0, 0, 0), apontada para (0, 0, 1), up (0, -1, 0)
534 void render_reset_camera(struct camera *camera)
536 camera->pos[X] = 0.0;
537 camera->pos[Y] = 0.0;
538 camera->pos[Z] = 0.0;
540 render_reset_camera_dir(camera);
544 aponta a camera do ponto actual na direcção de ez, up (0, -1, 0)
546 void render_reset_camera_dir(struct camera *camera)
548 camera->dir[X] = camera->pos[X];
549 camera->dir[Y] = camera->pos[Y];
550 camera->dir[Z] = camera->pos[Z] + 1.0;
552 camera->up[X] = camera->pos[X];
553 camera->up[Y] = camera->pos[Y] + 1.0;
554 camera->up[Z] = camera->pos[Z];
558 translacção segundo o sistema de eixos local da camera
559 (constituído por cam, up e vector resultante da rotação de cam 90
560 graus em sentido directo em torno de up)
562 void render_advance_camera(struct camera *camera, float x, float y, float z)
564 float r[3], cam[3], up[3];
565 float d[3], tmp[3];
567 /* cam = cam_dir - cam_pos */
568 math_sub_vec3(cam, camera->dir, camera->pos);
569 /* up = cam_up - cam_pos */
570 math_sub_vec3(up, camera->up, camera->pos);
572 /* x: seguir cam rodado 90 graus em torno de up */
573 math_rotate_vec3(r, cam, up, 90.0);
574 math_scale_vec3(d, x, r);
576 /* y: seguir up */
577 math_scale_vec3(tmp, y, up);
578 math_add_vec3(d, d, tmp);
580 /* z: seguir cam */
581 math_scale_vec3(tmp, z, cam);
582 math_add_vec3(d, d, tmp);
584 math_add_vec3(camera->pos, camera->pos, d);
585 math_add_vec3(camera->dir, camera->dir, d);
586 math_add_vec3(camera->up, camera->up, d);
590 rotação da camera no "seu" plano xOz ("esquerda/direita")
591 (cam roda em torno de up)
593 void render_camera_yaw(struct camera *camera, float angle)
595 float cam[3], up[3];
597 math_sub_vec3(cam, camera->dir, camera->pos);
598 math_sub_vec3(up, camera->up, camera->pos);
600 math_rotate_vec3(cam, cam, up, angle);
602 math_add_vec3(camera->dir, camera->pos, cam);
606 rotação da camera no "seu" plano xOy
607 (up roda em torno de cam)
609 void render_camera_roll(struct camera *camera, float angle)
611 float cam[3], up[3];
613 math_sub_vec3(cam, camera->dir, camera->pos);
614 math_sub_vec3(up, camera->up, camera->pos);
616 math_rotate_vec3(up, up, cam, angle);
618 math_add_vec3(camera->up, camera->pos, up);
622 rotação da camera no "seu" plano yOz ("cima/baixo")
623 (cam e up rodam em torno de um vector perpendicular aos dois)
625 void render_camera_pitch(struct camera *camera, float angle)
627 float cam[3], up[3], axis[3];
629 math_sub_vec3(cam, camera->dir, camera->pos);
630 math_sub_vec3(up, camera->up, camera->pos);
632 /* vector perpendicular: rodar cam 90 graus em torno de up */
633 math_rotate_vec3(axis, cam, up, 90.0);
635 /* rodar cam em torno de axis */
636 math_rotate_vec3(cam, cam, axis, angle);
638 /* rodar up em torno de axis */
639 math_rotate_vec3(up, up, axis, angle);
641 math_add_vec3(camera->dir, camera->pos, cam);
642 math_add_vec3(camera->up, camera->pos, up);
646 rotação da camera em torno de (0.0, 1.0, 0.0)
648 void render_camera_turn(struct camera *camera, float angle)
650 float cam[3], up[3], axis[3] = {0.0, 1.0, 0.0};
652 math_sub_vec3(cam, camera->dir, camera->pos);
653 math_sub_vec3(up, camera->up, camera->pos);
655 math_rotate_vec3(cam, cam, axis, angle);
656 math_rotate_vec3(up, up, axis, angle);
658 math_add_vec3(camera->dir, camera->pos, cam);
659 math_add_vec3(camera->up, camera->pos, up);
663 configura o opengl para desenhar a 2d
665 void render_setup_2d(struct viewport *vp)
667 glViewport(0, 0, vp->width, vp->height);
669 glMatrixMode(GL_PROJECTION);
670 glLoadIdentity();
671 /* XXX - glOrtho might need physical screen dimensions */
672 glOrtho(0, vp->width, vp->height, 0, -99999, 99999);
674 glMatrixMode(GL_MODELVIEW);
675 glLoadIdentity();
677 glDisable(GL_DEPTH_TEST);
678 glDisable(GL_CULL_FACE);
679 glDisable(GL_BLEND);
680 glDisable(GL_LIGHTING);
681 // glDisable(GL_ALPHA_TEST);
684 void render_draw_scaled_image(char *image, int ul_x, int ul_y, int lr_x, int lr_y)
686 struct image_rgba32 *img;
688 img = gfx_get(image);
689 if(img->id == -1)
690 gfx_upload_texture(image);
692 glEnable(GL_TEXTURE_2D);
693 glBindTexture(GL_TEXTURE_2D, img->id);
694 glEnable(GL_BLEND);
695 glBlendFunc(GL_ONE, GL_ONE);
697 glColor4f(1.0, 1.0, 1.0, 1.0);
699 glBegin(GL_QUADS);
701 glTexCoord2f(0.0, 0.0);
702 glVertex2i(ul_x, ul_y);
704 glTexCoord2f(0.0, 1.0);
705 glVertex2i(ul_x, lr_y);
707 glTexCoord2f(1.0, 1.0);
708 glVertex2i(lr_x, lr_y);
710 glTexCoord2f(1.0, 0.0);
711 glVertex2i(lr_x, ul_y);
713 glEnd();
716 void render_setup_model_direction(int direction)
718 switch(direction)
720 case DIRECTION_RIGHT:
721 /* virado para ex */
722 glRotatef(90.0, 0.0, 1.0, 0.0);
723 break;
725 case DIRECTION_LEFT:
726 /* virado para -ex */
727 glRotatef(-90.0, 0.0, 1.0, 0.0);
728 break;
730 case DIRECTION_DOWN:
731 /* virado para -ez */
732 glRotatef(180.0, 0.0, 1.0, 0.0);
733 break;
736 /* compensar sistema de eixos */
737 glRotatef(90.0, 1.0, 0.0, 0.0);
738 glRotatef(180.0, 0.0, 0.0, 1.0);