Optional use of vertex arrays in the particle system.
[neverball] / share / geom.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
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.
8  *
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.
13  */
14
15 #include <SDL.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
19
20 #include "glext.h"
21 #include "geom.h"
22 #include "part.h"
23 #include "vec3.h"
24 #include "image.h"
25 #include "config.h"
26 #include "video.h"
27
28 #include "solid_draw.h"
29
30 /*---------------------------------------------------------------------------*/
31
32 static struct s_full beam;
33 static struct s_full jump;
34 static struct s_full goal;
35 static struct s_full flag;
36 static struct s_full mark;
37 static struct s_full vect;
38 static struct s_full back;
39
40 static int back_state = 0;
41
42 /*---------------------------------------------------------------------------*/
43
44 void geom_init(void)
45 {
46     sol_load_full(&beam, "geom/beam/beam.sol", 0);
47     sol_load_full(&jump, "geom/jump/jump.sol", 0);
48     sol_load_full(&goal, "geom/goal/goal.sol", 0);
49     sol_load_full(&flag, "geom/flag/flag.sol", 0);
50     sol_load_full(&mark, "geom/mark/mark.sol", 0);
51     sol_load_full(&vect, "geom/vect/vect.sol", 0);
52 }
53
54 void geom_free(void)
55 {
56     sol_free_full(&vect);
57     sol_free_full(&mark);
58     sol_free_full(&flag);
59     sol_free_full(&goal);
60     sol_free_full(&jump);
61     sol_free_full(&beam);
62 }
63
64 /*---------------------------------------------------------------------------*/
65
66 void back_init(const char *name)
67 {
68     if (back_state)
69         back_free();
70
71     /* Load the background SOL and modify its material in-place to use the   */
72     /* named gradient texture.                                               */
73
74     sol_load_full(&back, "geom/back/back.sol", 0);
75     back.draw.mv[0].o = make_image_from_file(name);
76
77     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
78
79     back_state = 1;
80 }
81
82 void back_free(void)
83 {
84     if (back_state)
85         sol_free_full(&back);
86     
87     back_state = 0;
88 }
89
90 /*---------------------------------------------------------------------------*/
91
92 static const struct d_mtrl *jump_part_draw(const struct d_mtrl *mq,
93                                            GLfloat s, GLfloat a)
94 {
95     glMatrixMode(GL_TEXTURE);
96     glTranslatef(s, 0.0f, 0.0f);
97     glMatrixMode(GL_MODELVIEW);
98
99     glRotatef(a, 0.0f, 1.0f, 0.0f);
100     mq = sol_draw(&jump.draw, mq, 1, 1);
101     glScalef(0.9f, 0.9f, 0.9f);
102
103     return mq;
104 }
105
106 static const struct d_mtrl *goal_part_draw(const struct d_mtrl *mq, GLfloat s)
107 {
108     glMatrixMode(GL_TEXTURE);
109     glTranslatef(0.0f, -s, 0.0f);
110     glMatrixMode(GL_MODELVIEW);
111
112     mq = sol_draw(&goal.draw, mq, 1, 1);
113     glScalef(0.8f, 1.1f, 0.8f);
114
115     return mq;
116 }
117
118 /*---------------------------------------------------------------------------*/
119
120 const struct d_mtrl *goal_draw(const struct d_mtrl *mq, float t)
121 {
122     glPushMatrix();
123     {
124         glScalef(1.0f, 3.0f, 1.0f);
125         glColor4f(1.0f, 1.0f, 0.0f, 0.5f);
126
127         mq = sol_draw(&beam.draw, mq, 1, 1);
128
129         mq = goal_part_draw(mq, t * 0.10f);
130         mq = goal_part_draw(mq, t * 0.10f);
131         mq = goal_part_draw(mq, t * 0.10f);
132         mq = goal_part_draw(mq, t * 0.10f);
133
134         glMatrixMode(GL_TEXTURE);
135         glLoadIdentity();
136         glMatrixMode(GL_MODELVIEW);
137
138         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
139     }
140     glPopMatrix();
141
142     return mq;
143 }
144
145 const struct d_mtrl *jump_draw(const struct d_mtrl *mq, float t, int h)
146 {
147     static GLfloat jump_colors[4][4] = {
148         { 0.75f, 0.5f, 1.0f, 0.5f },
149         { 0.75f, 0.5f, 1.0f, 0.8f },
150     };
151
152     glPushMatrix();
153     {
154         glColor4fv(jump_colors[h]);
155
156         glScalef(1.0f, 2.0f, 1.0f);
157
158         mq = sol_draw(&beam.draw, mq, 1, 1);
159
160         mq = jump_part_draw(mq, t * 0.15f, t * 360.0f);
161         mq = jump_part_draw(mq, t * 0.20f, t * 360.0f);
162         mq = jump_part_draw(mq, t * 0.25f, t * 360.0f);
163
164         glMatrixMode(GL_TEXTURE);
165         glLoadIdentity();
166         glMatrixMode(GL_MODELVIEW);
167
168         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
169     }
170     glPopMatrix();
171
172     return mq;
173 }
174
175 const struct d_mtrl *swch_draw(const struct d_mtrl *mq, int b, int e)
176 {
177     static GLfloat swch_colors[4][4] = {
178         { 1.0f, 0.0f, 0.0f, 0.5f }, /* red out */
179         { 1.0f, 0.0f, 0.0f, 0.8f }, /* red in */
180         { 0.0f, 1.0f, 0.0f, 0.5f }, /* green out */
181         { 0.0f, 1.0f, 0.0f, 0.8f }, /* green in */
182     };
183
184     glPushMatrix();
185     {
186         glScalef(1.0f, 2.0f, 1.0f);
187
188         glColor4fv(swch_colors[b * 2 + e]);
189         mq = sol_draw(&beam.draw, mq, 1, 1);
190         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
191     }
192     glPopMatrix();
193
194     return mq;
195 }
196
197 const struct d_mtrl *flag_draw(const struct d_mtrl *mq)
198 {
199     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
200     return sol_draw(&flag.draw, mq, 1, 1);
201 }
202
203 const struct d_mtrl *mark_draw(const struct d_mtrl *mq)
204 {
205     return sol_draw(&mark.draw, mq, 1, 1);
206 }
207
208 const struct d_mtrl *vect_draw(const struct d_mtrl *mq)
209 {
210     mq = sol_draw(&vect.draw, mq, 0, 1);
211     mq = sol_draw(&vect.draw, mq, 0, 0);
212     return mq;
213 }
214
215 const struct d_mtrl *back_draw(const struct d_mtrl *mq, float t)
216 {
217     glPushMatrix();
218     {
219         GLfloat dx =  60.0f * fsinf(t / 10.0f);
220         GLfloat dz = 180.0f * fsinf(t / 12.0f);
221
222         glDisable(GL_LIGHTING);
223         glDepthMask(GL_FALSE);
224         {
225             glScalef(-BACK_DIST, BACK_DIST, -BACK_DIST);
226             glRotatef(dz, 0.0f, 0.0f, 1.0f);
227             glRotatef(dx, 1.0f, 0.0f, 0.0f);
228
229             mq = sol_draw(&back.draw, mq, 1, 1);
230         }
231         glDepthMask(GL_TRUE);
232         glEnable(GL_LIGHTING);
233     }
234     glPopMatrix();
235
236     return mq;
237 }
238
239 void back_draw_easy(void)
240 {
241     sol_draw_disable(back_draw(sol_draw_enable(), 0.0f));
242 }
243
244 /*---------------------------------------------------------------------------*/
245 /*
246 static GLuint clip_text;
247
248 static GLubyte clip_data[] = { 0xff, 0xff, 0x0, 0x0 };
249
250 void clip_init(void)
251 {
252     if (!glActiveTexture_)
253         return;
254
255     glActiveTexture_(GL_TEXTURE1);
256     {
257         glGenTextures(1, &clip_text);
258         glBindTexture(GL_TEXTURE_1D, clip_text);
259
260         glTexImage1D(GL_TEXTURE_1D, 0,
261                      GL_LUMINANCE_ALPHA, 2, 0,
262                      GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, clip_data);
263
264         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
265         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
266
267         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
268     }
269     glActiveTexture_(GL_TEXTURE0);
270 }
271
272 void clip_free(void)
273 {
274     if (glIsTexture(clip_text))
275         glDeleteTextures(1, &clip_text);
276 }
277
278 void clip_draw_set(void)
279 {
280     if (!glActiveTexture_)
281         return;
282
283     glActiveTexture_(GL_TEXTURE1);
284     {
285         glBindTexture(GL_TEXTURE_1D, clip_text);
286
287         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
288
289         glEnable(GL_TEXTURE_GEN_S);
290         glEnable(GL_TEXTURE_1D);
291     }
292     glActiveTexture_(GL_TEXTURE0);
293 }
294
295 void clip_draw_clr(void)
296 {
297     if (!glActiveTexture_)
298         return;
299
300     glActiveTexture_(GL_TEXTURE1);
301     {
302         glDisable(GL_TEXTURE_GEN_S);
303         glDisable(GL_TEXTURE_1D);
304     }
305     glActiveTexture_(GL_TEXTURE0);
306 }
307 */
308 /*---------------------------------------------------------------------------*/
309
310 /*
311  * A note about lighting and shadow: technically speaking, it's wrong.
312  * The  light  position  and   shadow  projection  behave  as  if  the
313  * light-source rotates with the  floor.  However, the skybox does not
314  * rotate, thus the light should also remain stationary.
315  *
316  * The  correct behavior  would eliminate  a significant  3D  cue: the
317  * shadow of  the ball indicates  the ball's position relative  to the
318  * floor even  when the ball is  in the air.  This  was the motivating
319  * idea  behind the  shadow  in  the first  place,  so correct  shadow
320  * projection would only magnify the problem.
321  */
322
323 static GLuint shad_text;
324
325 void shad_init(void)
326 {
327     shad_text = make_image_from_file(IMG_SHAD);
328
329     if (config_get_d(CONFIG_SHADOW) == 2)
330     {
331         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
332         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
333     }
334 }
335
336 void shad_free(void)
337 {
338     if (glIsTexture(shad_text))
339         glDeleteTextures(1, &shad_text);
340 }
341
342 void shad_draw_set(void)
343 {
344     glActiveTexture_(GL_TEXTURE1);
345     {
346         glEnable(GL_TEXTURE_2D);
347         glBindTexture(GL_TEXTURE_2D, shad_text);
348         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
349     }
350     glActiveTexture_(GL_TEXTURE0);
351 }
352
353 void shad_draw_clr(void)
354 {
355     glActiveTexture_(GL_TEXTURE1);
356     {
357         glBindTexture(GL_TEXTURE_2D, 0);
358         glDisable(GL_TEXTURE_2D);
359     }
360     glActiveTexture_(GL_TEXTURE0);
361 }
362
363 /*---------------------------------------------------------------------------*/