2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
28 #define PI 3.1415926535897932
30 /*---------------------------------------------------------------------------*/
32 static GLuint mark_list;
36 int i, slices = b ? 32 : 16;
38 mark_list = glGenLists(1);
40 glNewList(mark_list, GL_COMPILE);
42 glBegin(GL_TRIANGLE_FAN);
44 glNormal3f(0.f, 1.f, 0.f);
46 for (i = 0; i < slices; i++)
48 float x = fcosf(-2.f * PI * i / slices);
49 float y = fsinf(-2.f * PI * i / slices);
61 glEnable(GL_COLOR_MATERIAL);
62 glDisable(GL_TEXTURE_2D);
63 glDepthMask(GL_FALSE);
65 glCallList(mark_list);
68 glEnable(GL_TEXTURE_2D);
69 glDisable(GL_COLOR_MATERIAL);
74 if (glIsList(mark_list))
75 glDeleteLists(mark_list, 1);
80 /*---------------------------------------------------------------------------*/
82 static void coin_head(int n, float radius, float thick)
86 glBegin(GL_TRIANGLE_FAN);
88 glNormal3f(0.f, 0.f, +1.f);
90 for (i = 0; i < n; i++)
92 float x = fcosf(+2.f * PI * i / n);
93 float y = fsinf(+2.f * PI * i / n);
95 glTexCoord2f(-x * 0.5f + 0.5f, +y * 0.5f + 0.5f);
96 glVertex3f(radius * x, radius * y, +thick);
102 static void coin_tail(int n, float radius, float thick)
106 glBegin(GL_TRIANGLE_FAN);
108 glNormal3f(0.f, 0.f, -1.f);
110 for (i = 0; i < n; i++)
112 float x = fcosf(-2.f * PI * i / n);
113 float y = fsinf(-2.f * PI * i / n);
115 glTexCoord2f(+x * 0.5f + 0.5f, +y * 0.5f + 0.5f);
116 glVertex3f(radius * x, radius * y, -thick);
122 static void coin_edge(int n, float radius, float thick)
126 glBegin(GL_QUAD_STRIP);
128 for (i = 0; i <= n; i++)
130 float x = fcosf(2.f * PI * i / n);
131 float y = fsinf(2.f * PI * i / n);
133 glNormal3f(x, y, 0.0f);
134 glVertex3f(radius * x, radius * y, +thick);
135 glVertex3f(radius * x, radius * y, -thick);
141 /*---------------------------------------------------------------------------*/
143 static GLuint item_coin_text;
144 static GLuint item_grow_text;
145 static GLuint item_shrink_text;
146 static GLuint item_list;
148 void item_color(const struct s_item *hp, float *c)
188 void item_init(int b)
192 item_coin_text = make_image_from_file(IMG_ITEM_COIN);
193 item_grow_text = make_image_from_file(IMG_ITEM_GROW);
194 item_shrink_text = make_image_from_file(IMG_ITEM_SHRINK);
196 item_list = glGenLists(1);
198 glNewList(item_list, GL_COMPILE);
200 glDisable(GL_TEXTURE_2D);
201 coin_edge(n, COIN_RADIUS, COIN_THICK);
202 glEnable (GL_TEXTURE_2D);
203 coin_head(n, COIN_RADIUS, COIN_THICK);
204 coin_tail(n, COIN_RADIUS, COIN_THICK);
211 if (glIsList(item_list))
212 glDeleteLists(item_list, 1);
214 if (glIsTexture(item_coin_text))
215 glDeleteTextures(1, &item_coin_text);
217 if (glIsTexture(item_grow_text))
218 glDeleteTextures(1, &item_grow_text);
220 if (glIsTexture(item_shrink_text))
221 glDeleteTextures(1, &item_shrink_text);
226 item_shrink_text = 0;
229 void item_push(int type)
231 static const float a[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
232 static const float s[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
233 static const float e[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
234 static const float h[1] = { 10.0f };
236 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, a);
237 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, s);
238 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, e);
239 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, h);
241 glEnable(GL_COLOR_MATERIAL);
246 glBindTexture(GL_TEXTURE_2D, item_coin_text);
250 glBindTexture(GL_TEXTURE_2D, item_grow_text);
254 glBindTexture(GL_TEXTURE_2D, item_shrink_text);
259 void item_draw(const struct s_item *hp, float r)
266 glCallList(item_list);
271 glColor3f(1.0f, 1.0f, 1.0f);
272 glDisable(GL_COLOR_MATERIAL);
275 /*---------------------------------------------------------------------------*/
277 static GLuint goal_list;
279 void goal_init(int b)
281 int i, n = b ? 32 : 8;
283 goal_list = glGenLists(1);
285 glNewList(goal_list, GL_COMPILE);
287 glBegin(GL_QUAD_STRIP);
289 for (i = 0; i <= n; i++)
291 float x = fcosf(2.f * PI * i / n);
292 float y = fsinf(2.f * PI * i / n);
294 glColor4f(1.0f, 1.0f, 0.0f, 0.5f);
295 glVertex3f(x, 0.0f, y);
297 glColor4f(1.0f, 1.0f, 0.0f, 0.0f);
298 glVertex3f(x, GOAL_HEIGHT, y);
308 if (glIsList(goal_list))
309 glDeleteLists(goal_list, 1);
316 glCallList(goal_list);
319 /*---------------------------------------------------------------------------*/
321 static GLuint jump_list;
323 void jump_init(int b)
325 int k, i, n = b ? 32 : 8;
327 jump_list = glGenLists(2);
329 for (k = 0; k < 2; k++)
331 glNewList(jump_list + k, GL_COMPILE);
333 glBegin(GL_QUAD_STRIP);
335 for (i = 0; i <= n; i++)
337 float x = fcosf(2.f * PI * i / n);
338 float y = fsinf(2.f * PI * i / n);
340 glColor4f(1.0f, 1.0f, 1.0f, (k == 0 ? 0.5f : 0.8f));
341 glVertex3f(x, 0.0f, y);
343 glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
344 glVertex3f(x, JUMP_HEIGHT, y);
355 glDeleteLists(jump_list, 2);
359 void jump_draw(int highlight)
361 glCallList(jump_list + highlight);
364 /*---------------------------------------------------------------------------*/
366 static GLuint swch_list;
368 static GLfloat swch_colors[8][4] = {
369 { 1.0f, 0.0f, 0.0f, 0.5f }, /* red out */
370 { 1.0f, 0.0f, 0.0f, 0.0f },
371 { 1.0f, 0.0f, 0.0f, 0.8f }, /* red in */
372 { 1.0f, 0.0f, 0.0f, 0.0f },
373 { 0.0f, 1.0f, 0.0f, 0.5f }, /* green out */
374 { 0.0f, 1.0f, 0.0f, 0.0f },
375 { 0.0f, 1.0f, 0.0f, 0.8f }, /* green in */
376 { 0.0f, 1.0f, 0.0f, 0.0f }};
378 void swch_init(int b)
380 int k, i, n = b ? 32 : 8;
382 swch_list = glGenLists(4);
384 /* Create the display lists. */
386 for (k = 0; k < 4; k++)
388 glNewList(swch_list + k, GL_COMPILE);
390 glBegin(GL_QUAD_STRIP);
392 for (i = 0; i <= n; i++)
394 float x = fcosf(2.f * PI * i / n);
395 float y = fsinf(2.f * PI * i / n);
397 glColor4fv(swch_colors[2 * k + 0]);
398 glVertex3f(x, 0.0f, y);
400 glColor4fv(swch_colors[2 * k + 1]);
401 glVertex3f(x, SWCH_HEIGHT, y);
412 if (glIsList(swch_list))
413 glDeleteLists(swch_list, 2);
418 void swch_draw(int b, int e)
420 glCallList(swch_list + b * 2 + e);
423 /*---------------------------------------------------------------------------*/
425 static GLuint flag_list;
427 void flag_init(int b)
429 int i, n = b ? 8 : 4;
431 flag_list = glGenLists(1);
433 glNewList(flag_list, GL_COMPILE);
435 glEnable(GL_COLOR_MATERIAL);
436 glDisable(GL_LIGHTING);
437 glDisable(GL_TEXTURE_2D);
439 glBegin(GL_TRIANGLES);
441 glColor3f(1.0f, 0.0f, 0.0f);
443 glVertex3f( 0.0f, GOAL_HEIGHT, 0.0f);
444 glVertex3f(GOAL_HEIGHT * 0.2f, GOAL_HEIGHT * 0.9f, 0.0f);
445 glVertex3f( 0.0f, GOAL_HEIGHT * 0.8f, 0.0f);
447 glVertex3f( 0.0f, GOAL_HEIGHT, 0.0f);
448 glVertex3f( 0.0f, GOAL_HEIGHT * 0.8f, 0.0f);
449 glVertex3f(GOAL_HEIGHT * 0.2f, GOAL_HEIGHT * 0.9f, 0.0f);
453 glBegin(GL_QUAD_STRIP);
455 for (i = 0; i <= n; i++)
457 float x = fcosf(2.f * PI * i / n) * 0.01f;
458 float y = fsinf(2.f * PI * i / n) * 0.01f;
460 glColor3f(1.0f, 1.0f, 1.0f);
461 glVertex3f(x, 0.0f, y);
462 glVertex3f(x, GOAL_HEIGHT, y);
467 glEnable(GL_TEXTURE_2D);
468 glEnable(GL_LIGHTING);
469 glDisable(GL_COLOR_MATERIAL);
476 if (glIsList(flag_list))
477 glDeleteLists(flag_list, 1);
484 glCallList(flag_list);
487 /*---------------------------------------------------------------------------*/
489 * A note about lighting and shadow: technically speaking, it's wrong.
490 * The light position and shadow projection behave as if the
491 * light-source rotates with the floor. However, the skybox does not
492 * rotate, thus the light should also remain stationary.
494 * The correct behavior would eliminate a significant 3D cue: the
495 * shadow of the ball indicates the ball's position relative to the
496 * floor even when the ball is in the air. This was the motivating
497 * idea behind the shadow in the first place, so correct shadow
498 * projection would only magnify the problem.
501 static GLuint shad_text;
505 shad_text = make_image_from_file(IMG_SHAD);
507 if (config_get_d(CONFIG_SHADOW) == 2)
509 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
510 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
516 if (glIsTexture(shad_text))
517 glDeleteTextures(1, &shad_text);
520 void shad_draw_set(const float *p, float r)
522 glMatrixMode(GL_TEXTURE);
526 glBindTexture(GL_TEXTURE_2D, shad_text);
529 glTranslatef(0.5f - k * p[0],
530 0.5f - k * p[2], 0.f);
531 glScalef(k, k, 1.0f);
533 glMatrixMode(GL_MODELVIEW);
536 void shad_draw_clr(void)
538 glMatrixMode(GL_TEXTURE);
542 glMatrixMode(GL_MODELVIEW);
545 /*---------------------------------------------------------------------------*/
547 void fade_draw(float k)
551 int w = config_get_d(CONFIG_WIDTH);
552 int h = config_get_d(CONFIG_HEIGHT);
556 glEnable(GL_COLOR_MATERIAL);
557 glDisable(GL_LIGHTING);
558 glDisable(GL_DEPTH_TEST);
559 glDisable(GL_TEXTURE_2D);
561 glColor4f(0.0f, 0.0f, 0.0f, k);
572 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
574 glEnable(GL_TEXTURE_2D);
575 glEnable(GL_DEPTH_TEST);
576 glEnable(GL_LIGHTING);
577 glDisable(GL_COLOR_MATERIAL);
583 /*---------------------------------------------------------------------------*/