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 $";
34 #include "linked-lists.h"
44 #include "render_bomb.h"
49 void render_object(struct object
*o
)
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
);
81 desenha os polígonos com cor definida de um objecto
83 void render_object_colored_polygons(struct object
*o
)
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
));
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
);
122 desenha polígonos sem cor
124 void render_object_no_colored_polygons(struct object
*o
)
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
);
146 void render_object_color_tag(struct object
*o
, GLfloat color
[4])
149 GLfloat last_color
[4];
151 if(o
->fc_list
[0]->color_tag
)
152 memcpy(last_color
, color
, sizeof(last_color
));
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
);
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
);
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
);
200 glCallList(o
->dlist_nocolor
);
203 render_object_color_tag(o
, color
);
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
);
225 o
->dlist_nocolor
= glGenLists(1);
226 glNewList(o
->dlist_nocolor
, GL_COMPILE
);
227 render_object_no_colored_polygons(o
);
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
;
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};
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};
273 /* special case: demo mode */
274 camera
= game
->demo_camera
;
275 screen_set_active_viewport(0);
276 vp
= screen_get_viewport(0);
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
);
286 glMatrixMode(GL_PROJECTION
);
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
);
304 glEnable(GL_LIGHTING
);
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]);
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
];
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
);
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]);
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
);
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
);
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
),
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)
432 SDL_GL_SwapBuffers();
438 void render_draw_axes(float length
)
440 glMatrixMode(GL_MODELVIEW
);
444 glEnable(GL_DEPTH_TEST
);
445 glDepthMask(GL_TRUE
);
446 glDisable(GL_LIGHTING
);
447 glDisable(GL_LINE_SMOOTH
);
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);
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);
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
);
473 posiciona a câmera em world-space
475 void render_move_camera(struct camera
*camera
, float x
, float y
, float z
)
479 math_sub_vec3(cam
, camera
->dir
, camera
->pos
);
480 math_sub_vec3(up
, camera
->up
, camera
->pos
);
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
)
509 aponta a câmera para um ponto
511 void render_point_camera(struct camera
*camera
, float x
, float y
, float z
)
515 cam
[X
] = x
- camera
->pos
[X
];
516 cam
[Y
] = y
- camera
->pos
[Y
];
517 cam
[Z
] = z
- camera
->pos
[Z
];
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];
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
);
577 math_scale_vec3(tmp
, y
, up
);
578 math_add_vec3(d
, d
, tmp
);
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
)
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
)
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
);
671 /* XXX - glOrtho might need physical screen dimensions */
672 glOrtho(0, vp
->width
, vp
->height
, 0, -99999, 99999);
674 glMatrixMode(GL_MODELVIEW
);
677 glDisable(GL_DEPTH_TEST
);
678 glDisable(GL_CULL_FACE
);
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
);
690 gfx_upload_texture(image
);
692 glEnable(GL_TEXTURE_2D
);
693 glBindTexture(GL_TEXTURE_2D
, img
->id
);
695 glBlendFunc(GL_ONE
, GL_ONE
);
697 glColor4f(1.0, 1.0, 1.0, 1.0);
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
);
716 void render_setup_model_direction(int direction
)
720 case DIRECTION_RIGHT
:
722 glRotatef(90.0, 0.0, 1.0, 0.0);
726 /* virado para -ex */
727 glRotatef(-90.0, 0.0, 1.0, 0.0);
731 /* virado para -ez */
732 glRotatef(180.0, 0.0, 1.0, 0.0);
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);