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"
45 #include "oglconsole.h"
50 void render_object(struct object
*o
)
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
);
82 desenha os polígonos com cor definida de um objecto
84 void render_object_colored_polygons(struct object
*o
)
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
));
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
);
123 desenha polígonos sem cor
125 void render_object_no_colored_polygons(struct object
*o
)
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
);
147 void render_object_color_tag(struct object
*o
, GLfloat color
[4])
150 GLfloat last_color
[4];
152 if(o
->fc_list
[0]->color_tag
)
153 memcpy(last_color
, color
, sizeof(last_color
));
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
);
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
);
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
);
201 glCallList(o
->dlist_nocolor
);
204 render_object_color_tag(o
, color
);
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
);
226 o
->dlist_nocolor
= glGenLists(1);
227 glNewList(o
->dlist_nocolor
, GL_COMPILE
);
228 render_object_no_colored_polygons(o
);
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
;
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};
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};
274 /* special case: demo mode */
275 camera
= game
->demo_camera
;
276 screen_set_active_viewport(0);
277 vp
= screen_get_viewport(0);
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
);
287 glMatrixMode(GL_PROJECTION
);
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
);
305 glEnable(GL_LIGHTING
);
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]);
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
];
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
);
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]);
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
);
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
);
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
),
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)
434 SDL_GL_SwapBuffers();
440 void render_draw_axes(float length
)
442 glMatrixMode(GL_MODELVIEW
);
446 glEnable(GL_DEPTH_TEST
);
447 glDepthMask(GL_TRUE
);
448 glDisable(GL_LIGHTING
);
449 glDisable(GL_LINE_SMOOTH
);
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);
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);
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
);
475 posiciona a câmera em world-space
477 void render_move_camera(struct camera
*camera
, float x
, float y
, float z
)
481 math_sub_vec3(cam
, camera
->dir
, camera
->pos
);
482 math_sub_vec3(up
, camera
->up
, camera
->pos
);
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
)
511 aponta a câmera para um ponto
513 void render_point_camera(struct camera
*camera
, float x
, float y
, float z
)
517 cam
[X
] = x
- camera
->pos
[X
];
518 cam
[Y
] = y
- camera
->pos
[Y
];
519 cam
[Z
] = z
- camera
->pos
[Z
];
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];
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
);
579 math_scale_vec3(tmp
, y
, up
);
580 math_add_vec3(d
, d
, tmp
);
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
)
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
)
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
);
673 /* XXX - glOrtho might need physical screen dimensions */
674 glOrtho(0, vp
->width
, vp
->height
, 0, -99999, 99999);
676 glMatrixMode(GL_MODELVIEW
);
679 glDisable(GL_DEPTH_TEST
);
680 glDisable(GL_CULL_FACE
);
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
);
697 glBlendFunc(GL_ONE
, GL_ONE
);
699 glColor4f(1.0, 1.0, 1.0, 1.0);
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
);
718 void render_setup_model_direction(int direction
)
722 case DIRECTION_RIGHT
:
724 glRotatef(90.0, 0.0, 1.0, 0.0);
728 /* virado para -ex */
729 glRotatef(-90.0, 0.0, 1.0, 0.0);
733 /* virado para -ez */
734 glRotatef(180.0, 0.0, 1.0, 0.0);
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);