Fix error message when SDL_ttf is not present.
[attac-man.git] / render.c
blobcd6a87671761b987abbde7ac10fa4da493f82bd7
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"
45 #include "oglconsole.h"
48 desenha um objecto
50 void render_object(struct object *o)
52 int c;
53 GLfloat last_color[4];
55 memcpy(last_color, o->fc_list[0]->color, sizeof(last_color));
56 glColor4fv(last_color);
58 glBegin(GL_TRIANGLES);
60 for(c = 0; c < o->num_fc; c++)
62 if(memcmp(last_color, o->fc_list[c]->color, sizeof(last_color)) != 0)
64 memcpy(last_color, o->fc_list[c]->color, sizeof(last_color));
65 glColor4fv(last_color);
68 glNormal3fv(o->fc_list[c]->na);
69 glVertex3fv(o->fc_list[c]->a);
71 glNormal3fv(o->fc_list[c]->nb);
72 glVertex3fv(o->fc_list[c]->b);
74 glNormal3fv(o->fc_list[c]->nc);
75 glVertex3fv(o->fc_list[c]->c);
78 glEnd();
82 desenha os polígonos com cor definida de um objecto
84 void render_object_colored_polygons(struct object *o)
86 int c;
87 GLfloat last_color[4];
89 /* tirar a primeira cor */
90 for(c = 0; c < o->num_fc; c++)
91 if(!o->fc_list[0]->color_tag)
93 memcpy(last_color, o->fc_list[0]->color, sizeof(last_color));
94 break;
97 glColor4fv(last_color);
98 glBegin(GL_TRIANGLES);
100 for(c = 0; c < o->num_fc; c++)
101 if(!o->fc_list[c]->color_tag)
103 if(memcmp(last_color, o->fc_list[c]->color, sizeof(last_color)) != 0)
105 memcpy(last_color, o->fc_list[c]->color, sizeof(last_color));
106 glColor4fv(last_color);
109 glNormal3fv(o->fc_list[c]->na);
110 glVertex3fv(o->fc_list[c]->a);
112 glNormal3fv(o->fc_list[c]->nb);
113 glVertex3fv(o->fc_list[c]->b);
115 glNormal3fv(o->fc_list[c]->nc);
116 glVertex3fv(o->fc_list[c]->c);
119 glEnd();
123 desenha polígonos sem cor
125 void render_object_no_colored_polygons(struct object *o)
127 int c;
129 glBegin(GL_TRIANGLES);
131 for(c = 0; c < o->num_fc; c++)
132 if(o->fc_list[c]->color_tag)
134 glNormal3fv(o->fc_list[c]->na);
135 glVertex3fv(o->fc_list[c]->a);
137 glNormal3fv(o->fc_list[c]->nb);
138 glVertex3fv(o->fc_list[c]->b);
140 glNormal3fv(o->fc_list[c]->nc);
141 glVertex3fv(o->fc_list[c]->c);
144 glEnd();
147 void render_object_color_tag(struct object *o, GLfloat color[4])
149 int c;
150 GLfloat last_color[4];
152 if(o->fc_list[0]->color_tag)
153 memcpy(last_color, color, sizeof(last_color));
154 else
155 memcpy(last_color, o->fc_list[0]->color, sizeof(last_color));
156 glColor4fv(last_color);
158 glBegin(GL_TRIANGLES);
160 for(c = 0; c < o->num_fc; c++)
162 if(o->fc_list[c]->color_tag)
164 if(memcmp(last_color, color, sizeof(last_color)) != 0)
166 memcpy(last_color, color, sizeof(last_color));
167 glColor4fv(last_color);
169 } else {
170 if(memcmp(last_color, o->fc_list[c]->color, sizeof(last_color)) != 0)
172 memcpy(last_color, o->fc_list[c]->color, sizeof(last_color));
173 glColor4fv(last_color);
177 glNormal3fv(o->fc_list[c]->na);
178 glVertex3fv(o->fc_list[c]->a);
180 glNormal3fv(o->fc_list[c]->nb);
181 glVertex3fv(o->fc_list[c]->b);
183 glNormal3fv(o->fc_list[c]->nc);
184 glVertex3fv(o->fc_list[c]->c);
187 glEnd();
191 desenha um objecto por display lists
193 void render_dlist(struct object *o, GLfloat *color)
195 if(o->dlist_color != (GLuint)-1)
197 glCallList(o->dlist_color);
198 if(color)
199 glColor4fv(color);
201 glCallList(o->dlist_nocolor);
202 } else {
203 if(color)
204 render_object_color_tag(o, color);
205 else
206 render_object(o);
211 compila a display list de um objecto
213 void render_compile_dlist(struct object *o)
215 if(o->dlist_color != (GLuint)-1)
217 glDeleteLists(o->dlist_color, 1);
218 glDeleteLists(o->dlist_nocolor, 1);
221 o->dlist_color = glGenLists(1);
222 glNewList(o->dlist_color, GL_COMPILE);
223 render_object_colored_polygons(o);
224 glEndList();
226 o->dlist_nocolor = glGenLists(1);
227 glNewList(o->dlist_nocolor, GL_COMPILE);
228 render_object_no_colored_polygons(o);
229 glEndList();
233 inicia o desenho de uma nova frame
235 void render_start_frame(void)
237 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
240 void render_setup(struct game *game, int player_no)
242 struct camera *camera;
243 struct viewport *vp;
245 /* light0: centro do mapa, aponta para baixo, spot branco */
246 GLfloat light0_ambient[] = {0.1, 0.1, 0.1, 1.0};
247 GLfloat light0_diffuse[] = {0.8, 0.8, 0.8, 1.0};
248 GLfloat light0_specular[] = {0.0, 0.0, 0.0, 1.0};
249 GLfloat light0_position[] =
250 {(GLfloat)game->map->width / 2.0, -15.0, (GLfloat)game->map->height / 2.0, 1.0};
251 GLfloat light0_direction[] =
252 {0.0, 1.0, 0.0, 1.0};
253 GLfloat light0_spot_cutoff = 90.0 * (game->map->width * game->map->height) / (31 * 31);
254 GLfloat light0_spot_exponent = 1.0;
255 /* attn: constant, linear, quadratic */
256 GLfloat light0_attn[] = {1.0, 0.0, 0.0};
258 /* light1: por cima do pacman, aponta para baixo, spot amarelo */
259 GLfloat light1_ambient[] = {0.0, 0.0, 0.0, 1.0};
260 GLfloat light1_diffuse[] = {1.0, 0.0, 0.0, 1.0};
261 GLfloat light1_specular[] = {0.0, 0.0, 0.0, 1.0};
262 /* XXX! */
263 GLfloat light1_position[] =
264 // {(GLfloat)players[0].position[X], -15.0, (GLfloat)players[0].position[Z], 1.0};
265 {0.0, 0.0, 0.0, 1.0};
266 GLfloat light1_direction[] =
267 {0.0, 1.0, 0.0, 1.0};
268 GLfloat light1_spot_cutoff = 20.0;
269 GLfloat light1_spot_exponent = 20.0;
270 GLfloat light1_attn[] = {1.0, 0.0, 0.0};
272 if(player_no == -1)
274 /* special case: demo mode */
275 camera = game->demo_camera;
276 screen_set_active_viewport(0);
277 vp = screen_get_viewport(0);
278 } else {
279 camera = game->players[player_no].camera;
280 screen_set_active_viewport(player_no);
281 vp = screen_get_viewport(player_no);
284 glMatrixMode(GL_MODELVIEW);
285 glLoadIdentity();
287 glMatrixMode(GL_PROJECTION);
288 glLoadIdentity();
289 glFrustum(-1.0, 1.0,
290 -1.0 * (GLfloat)vp->height / (GLfloat)vp->width,
291 1.0 * (GLfloat)vp->height / (GLfloat)vp->width, 1.0, 70.0);
293 gluLookAt(camera->pos[X], camera->pos[Y], camera->pos[Z],
294 camera->dir[X], camera->dir[Y], camera->dir[Z],
295 camera->pos[X] - camera->up[X],
296 camera->pos[Y] - camera->up[Y],
297 camera->pos[Z] - camera->up[Z]);
299 glEnable(GL_LINE_SMOOTH);
300 glHint(GL_LINE_SMOOTH, GL_NICEST);
302 glEnable(GL_CULL_FACE);
303 glCullFace(GL_BACK);
305 glEnable(GL_LIGHTING);
307 /* light 0 */
308 glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
309 glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
310 glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
311 glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
312 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0_direction);
314 glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, light0_spot_cutoff);
315 glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, light0_spot_exponent);
316 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, light0_attn[0]);
317 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, light0_attn[1]);
318 glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, light0_attn[2]);
320 glEnable(GL_LIGHT0);
322 if(game->n_players > 0)
324 light1_position[X] = (GLfloat)game->players[0].position[X];
325 light1_position[Y] = -15.0;
326 light1_position[Z] = (GLfloat)game->players[0].position[Z];
328 /* light 1 */
329 glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
330 glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
331 glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
332 glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
333 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light1_direction);
335 glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, light1_spot_cutoff);
336 glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light1_spot_exponent);
337 glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, light1_attn[0]);
338 glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light1_attn[1]);
339 glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light1_attn[2]);
342 glEnable(GL_COLOR_MATERIAL);
344 glDepthFunc(GL_LEQUAL);
348 calcula a geometria world-space de um quad
349 perpendicular à camera com size de lado
351 static GLfloat plane_vertexes[4][3];
352 static GLuint plane_dlist = -1;
353 void render_setup_plane_geometry(struct camera *camera, float size)
355 float tmp[3], cam[3], up[3];
357 math_sub_vec3(cam, camera->dir, camera->pos);
358 math_sub_vec3(up, camera->up, camera->pos);
359 math_rotate_vec3(tmp, cam, up, 90.0);
361 math_add_vec3(plane_vertexes[0], tmp, up);
362 math_scale_vec3(plane_vertexes[0], -1.0, plane_vertexes[0]);
363 math_len_vec3(plane_vertexes[0], plane_vertexes[0], size / 2.0);
365 math_sub_vec3(plane_vertexes[1], tmp, up);
366 math_len_vec3(plane_vertexes[1], plane_vertexes[1], size / 2.0);
368 math_add_vec3(plane_vertexes[2], tmp, up);
369 math_len_vec3(plane_vertexes[2], plane_vertexes[2], size / 2.0);
371 math_sub_vec3(plane_vertexes[3], up, tmp);
372 math_len_vec3(plane_vertexes[3], plane_vertexes[3], size / 2.0);
374 if(plane_dlist == (GLuint)-1)
375 plane_dlist = glGenLists(1);
377 glNewList(plane_dlist, GL_COMPILE);
379 glBegin(GL_QUADS);
380 glTexCoord2f(0.0, 1.0);
381 glVertex3fv(plane_vertexes[3]);
382 glTexCoord2f(1.0, 1.0);
383 glVertex3fv(plane_vertexes[2]);
384 glTexCoord2f(1.0, 0.0);
385 glVertex3fv(plane_vertexes[1]);
386 glTexCoord2f(0.0, 0.0);
387 glVertex3fv(plane_vertexes[0]);
388 glEnd();
390 glEndList();
394 desenha um quad perpendicular à camera
395 com origem em (x, y, z) e size de lado
397 void render_draw_plane(GLfloat x, GLfloat y, GLfloat z, GLfloat alpha)
399 glMatrixMode(GL_MODELVIEW);
400 glLoadIdentity();
401 glTranslatef(x, y, z);
403 glBlendFunc(GL_ONE, GL_ONE);
404 glColor4f(alpha, alpha, alpha, 1.0);
406 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
408 glCallList(plane_dlist);
411 void render_draw_colored_plane(GLfloat x, GLfloat y, GLfloat z, GLfloat color[3], GLfloat alpha)
413 glMatrixMode(GL_MODELVIEW);
414 glLoadIdentity();
415 glTranslatef(x, y, z);
417 glBlendFunc(GL_ONE, GL_ONE);
418 glColor4f(color[R] - (1.0 - alpha),
419 color[G] - (1.0 - alpha),
420 color[B] - (1.0 - alpha),
421 1.0);
422 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
424 glCallList(plane_dlist);
428 termina o desenho de uma frame
430 void render_finish_frame(void)
432 OGLCONSOLE_Draw();
433 glFlush();
434 SDL_GL_SwapBuffers();
438 desenha os eixos
440 void render_draw_axes(float length)
442 glMatrixMode(GL_MODELVIEW);
443 glLoadIdentity();
445 glDisable(GL_BLEND);
446 glEnable(GL_DEPTH_TEST);
447 glDepthMask(GL_TRUE);
448 glDisable(GL_LIGHTING);
449 glDisable(GL_LINE_SMOOTH);
451 glBegin(GL_LINES);
453 /* x */
454 glColor3f(0.25, 0.0, 0.0);
455 glVertex3f(-length, 0.0, 0.0);
456 glColor3f(1.0, 0.0, 0.0);
457 glVertex3f(length, 0.0, 0.0);
459 /* y */
460 glColor3f(0.0, 0.25, 0.0);
461 glVertex3f(0.0, -length, 0.0);
462 glColor3f(0.0, 1.0, 0.0);
463 glVertex3f(0.0, length, 0.0);
465 /* z */
466 glColor3f(0.0, 0.0, 0.25);
467 glVertex3f(0.0, 0.0, -length);
468 glColor3f(0.0, 0.0, 1.0);
469 glVertex3f(0.0, 0.0, length);
471 glEnd();
475 posiciona a câmera em world-space
477 void render_move_camera(struct camera *camera, float x, float y, float z)
479 float cam[3], up[3];
481 math_sub_vec3(cam, camera->dir, camera->pos);
482 math_sub_vec3(up, camera->up, camera->pos);
484 camera->pos[X] = x;
485 camera->pos[Y] = y;
486 camera->pos[Z] = z;
488 math_add_vec3(camera->dir, camera->pos, cam);
489 math_add_vec3(camera->up, camera->pos, up);
493 translacção da camera em world-space
495 void render_translate_camera(struct camera *camera, float x, float y, float z)
497 camera->pos[X] += x;
498 camera->pos[Y] += y;
499 camera->pos[Z] += z;
501 camera->up[X] += x;
502 camera->up[Y] += y;
503 camera->up[Z] += z;
505 camera->dir[X] += x;
506 camera->dir[Y] += y;
507 camera->dir[Z] += z;
511 aponta a câmera para um ponto
513 void render_point_camera(struct camera *camera, float x, float y, float z)
515 float cam[3], up[3];
517 cam[X] = x - camera->pos[X];
518 cam[Y] = y - camera->pos[Y];
519 cam[Z] = z - camera->pos[Z];
521 up[X] = 0.0;
522 up[Y] = 1.0;
523 up[Z] = 0.0;
525 math_gschmidt_2vec3(up, cam, up);
526 math_len_vec3(cam, cam, 1.0);
527 math_len_vec3(up, up, 1.0);
529 math_add_vec3(camera->dir, camera->pos, cam);
530 math_add_vec3(camera->up, camera->pos, up);
534 camera em (0, 0, 0), apontada para (0, 0, 1), up (0, -1, 0)
536 void render_reset_camera(struct camera *camera)
538 camera->pos[X] = 0.0;
539 camera->pos[Y] = 0.0;
540 camera->pos[Z] = 0.0;
542 render_reset_camera_dir(camera);
546 aponta a camera do ponto actual na direcção de ez, up (0, -1, 0)
548 void render_reset_camera_dir(struct camera *camera)
550 camera->dir[X] = camera->pos[X];
551 camera->dir[Y] = camera->pos[Y];
552 camera->dir[Z] = camera->pos[Z] + 1.0;
554 camera->up[X] = camera->pos[X];
555 camera->up[Y] = camera->pos[Y] + 1.0;
556 camera->up[Z] = camera->pos[Z];
560 translacção segundo o sistema de eixos local da camera
561 (constituído por cam, up e vector resultante da rotação de cam 90
562 graus em sentido directo em torno de up)
564 void render_advance_camera(struct camera *camera, float x, float y, float z)
566 float r[3], cam[3], up[3];
567 float d[3], tmp[3];
569 /* cam = cam_dir - cam_pos */
570 math_sub_vec3(cam, camera->dir, camera->pos);
571 /* up = cam_up - cam_pos */
572 math_sub_vec3(up, camera->up, camera->pos);
574 /* x: seguir cam rodado 90 graus em torno de up */
575 math_rotate_vec3(r, cam, up, 90.0);
576 math_scale_vec3(d, x, r);
578 /* y: seguir up */
579 math_scale_vec3(tmp, y, up);
580 math_add_vec3(d, d, tmp);
582 /* z: seguir cam */
583 math_scale_vec3(tmp, z, cam);
584 math_add_vec3(d, d, tmp);
586 math_add_vec3(camera->pos, camera->pos, d);
587 math_add_vec3(camera->dir, camera->dir, d);
588 math_add_vec3(camera->up, camera->up, d);
592 rotação da camera no "seu" plano xOz ("esquerda/direita")
593 (cam roda em torno de up)
595 void render_camera_yaw(struct camera *camera, float angle)
597 float cam[3], up[3];
599 math_sub_vec3(cam, camera->dir, camera->pos);
600 math_sub_vec3(up, camera->up, camera->pos);
602 math_rotate_vec3(cam, cam, up, angle);
604 math_add_vec3(camera->dir, camera->pos, cam);
608 rotação da camera no "seu" plano xOy
609 (up roda em torno de cam)
611 void render_camera_roll(struct camera *camera, float angle)
613 float cam[3], up[3];
615 math_sub_vec3(cam, camera->dir, camera->pos);
616 math_sub_vec3(up, camera->up, camera->pos);
618 math_rotate_vec3(up, up, cam, angle);
620 math_add_vec3(camera->up, camera->pos, up);
624 rotação da camera no "seu" plano yOz ("cima/baixo")
625 (cam e up rodam em torno de um vector perpendicular aos dois)
627 void render_camera_pitch(struct camera *camera, float angle)
629 float cam[3], up[3], axis[3];
631 math_sub_vec3(cam, camera->dir, camera->pos);
632 math_sub_vec3(up, camera->up, camera->pos);
634 /* vector perpendicular: rodar cam 90 graus em torno de up */
635 math_rotate_vec3(axis, cam, up, 90.0);
637 /* rodar cam em torno de axis */
638 math_rotate_vec3(cam, cam, axis, angle);
640 /* rodar up em torno de axis */
641 math_rotate_vec3(up, up, axis, angle);
643 math_add_vec3(camera->dir, camera->pos, cam);
644 math_add_vec3(camera->up, camera->pos, up);
648 rotação da camera em torno de (0.0, 1.0, 0.0)
650 void render_camera_turn(struct camera *camera, float angle)
652 float cam[3], up[3], axis[3] = {0.0, 1.0, 0.0};
654 math_sub_vec3(cam, camera->dir, camera->pos);
655 math_sub_vec3(up, camera->up, camera->pos);
657 math_rotate_vec3(cam, cam, axis, angle);
658 math_rotate_vec3(up, up, axis, angle);
660 math_add_vec3(camera->dir, camera->pos, cam);
661 math_add_vec3(camera->up, camera->pos, up);
665 configura o opengl para desenhar a 2d
667 void render_setup_2d(struct viewport *vp)
669 glViewport(0, 0, vp->width, vp->height);
671 glMatrixMode(GL_PROJECTION);
672 glLoadIdentity();
673 /* XXX - glOrtho might need physical screen dimensions */
674 glOrtho(0, vp->width, vp->height, 0, -99999, 99999);
676 glMatrixMode(GL_MODELVIEW);
677 glLoadIdentity();
679 glDisable(GL_DEPTH_TEST);
680 glDisable(GL_CULL_FACE);
681 glDisable(GL_BLEND);
682 glDisable(GL_LIGHTING);
683 // glDisable(GL_ALPHA_TEST);
686 void render_draw_scaled_image(char *image, int ul_x, int ul_y, int lr_x, int lr_y)
688 struct image_rgba32 *img;
690 img = gfx_get(image);
691 if(img->id == (GLuint)-1)
692 gfx_upload_texture(image);
694 glEnable(GL_TEXTURE_2D);
695 glBindTexture(GL_TEXTURE_2D, img->id);
696 glEnable(GL_BLEND);
697 glBlendFunc(GL_ONE, GL_ONE);
699 glColor4f(1.0, 1.0, 1.0, 1.0);
701 glBegin(GL_QUADS);
703 glTexCoord2f(0.0, 0.0);
704 glVertex2i(ul_x, ul_y);
706 glTexCoord2f(0.0, 1.0);
707 glVertex2i(ul_x, lr_y);
709 glTexCoord2f(1.0, 1.0);
710 glVertex2i(lr_x, lr_y);
712 glTexCoord2f(1.0, 0.0);
713 glVertex2i(lr_x, ul_y);
715 glEnd();
718 void render_setup_model_direction(int direction)
720 switch(direction)
722 case DIRECTION_RIGHT:
723 /* virado para ex */
724 glRotatef(90.0, 0.0, 1.0, 0.0);
725 break;
727 case DIRECTION_LEFT:
728 /* virado para -ex */
729 glRotatef(-90.0, 0.0, 1.0, 0.0);
730 break;
732 case DIRECTION_DOWN:
733 /* virado para -ez */
734 glRotatef(180.0, 0.0, 1.0, 0.0);
735 break;
738 /* compensar sistema de eixos */
739 glRotatef(90.0, 1.0, 0.0, 0.0);
740 glRotatef(180.0, 0.0, 0.0, 1.0);