foo
[deeprace] / src / scr_game.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <GL/gl.h>
5 #include "miniglut.h"
6 #include "game.h"
7 #include "util.h"
8 #include "goat3d.h"
9 #include "input.h"
10 #include "cgmath/cgmath.h"
11
12 static int ginit(void);
13 static void gdestroy(void);
14 static int gstart(void);
15 static void gstop(void);
16 static void gdisplay(void);
17 static void greshape(int x, int y);
18 static void gkeyb(int key, int press);
19 static void gmouse(int bn, int press, int x, int y);
20 static void gmotion(int x, int y);
21
22 static void set_light_dir(int idx, float x, float y, float z);
23 static void set_light_color(int idx, float r, float g, float b, float s);
24
25
26 struct game_screen scr_game = {
27         "game",
28         ginit, gdestroy,
29         gstart, gstop,
30         gdisplay, greshape,
31         gkeyb, gmouse, gmotion
32 };
33
34 static float view_mat[16], proj_mat[16];
35
36 static float cam_theta, cam_phi, cam_dist;
37 static cgm_vec3 cam_pan;
38
39 static struct goat3d *gscn;
40 static int dlist;
41
42
43 static int ginit(void)
44 {
45         int i, num, nfaces;
46         int *idxarr;
47         float *varr, *narr, *uvarr;
48         float xform[16];
49
50         if(!(gscn = goat3d_create()) || goat3d_load(gscn, "data/level1.g3d")) {
51                 return -1;
52         }
53
54         dlist = glGenLists(1);
55         glNewList(dlist, GL_COMPILE);
56         num = goat3d_get_node_count(gscn);
57         for(i=0; i<num; i++) {
58                 struct goat3d_node *node = goat3d_get_node(gscn, i);
59                 if(match_prefix(goat3d_get_node_name(node), "portal_")) {
60                         continue;
61                 }
62                 if(goat3d_get_node_type(node) == GOAT3D_NODE_MESH) {
63                         struct goat3d_mesh *mesh = goat3d_get_node_object(node);
64
65                         goat3d_get_node_matrix(node, xform);
66                         glPushMatrix();
67                         glMultMatrixf(xform);
68
69                         varr = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX);
70                         narr = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL);
71                         uvarr = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD);
72
73                         glEnableClientState(GL_VERTEX_ARRAY);
74                         glVertexPointer(3, GL_FLOAT, 0, varr);
75
76                         if(narr) {
77                                 glEnableClientState(GL_NORMAL_ARRAY);
78                                 glNormalPointer(GL_FLOAT, 0, narr);
79                         }
80                         if(uvarr) {
81                                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
82                                 glTexCoordPointer(2, GL_FLOAT, 0, uvarr);
83                         }
84
85                         nfaces = goat3d_get_mesh_face_count(mesh);
86                         idxarr = goat3d_get_mesh_faces(mesh);
87                         glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, idxarr);
88
89                         glDisableClientState(GL_VERTEX_ARRAY);
90                         glDisableClientState(GL_NORMAL_ARRAY);
91                         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
92
93                         glPopMatrix();
94                 }
95         }
96         glEndList();
97
98         return 0;
99 }
100
101 static void gdestroy(void)
102 {
103         goat3d_free(gscn);
104 }
105
106 static int gstart(void)
107 {
108         float amb[] = {0.25, 0.25, 0.25, 1};
109
110         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
111
112         set_light_color(0, 1, 1, 1, 0.8);
113         glEnable(GL_LIGHT0);
114         set_light_color(1, 1, 0.6, 0.5, 0.2);
115         glEnable(GL_LIGHT1);
116         set_light_color(2, 0.5, 0.6, 1, 0.3);
117         glEnable(GL_LIGHT2);
118         return 0;
119 }
120
121 static void gstop(void)
122 {
123 }
124
125 #define TSTEP   (1.0f / 30.0f)
126
127 static void gupdate(void)
128 {
129         if(inpstate & INP_MOVE_BITS) {
130                 cgm_vec3 fwd, right;
131
132                 float dx = 0, dy = 0;
133
134                 fwd.x = -sin(cam_theta) * cos(cam_phi);
135                 fwd.y = sin(cam_phi);
136                 fwd.z = cos(cam_theta) * cos(cam_phi);
137                 right.x = cos(cam_theta);
138                 right.y = 0;
139                 right.z = sin(cam_theta);
140
141                 if(inpstate & INP_FWD_BIT) {
142                         dy += 0.1;
143                 }
144                 if(inpstate & INP_BACK_BIT) {
145                         dy -= 0.1;
146                 }
147                 if(inpstate & INP_RIGHT_BIT) {
148                         dx -= 0.1;
149                 }
150                 if(inpstate & INP_LEFT_BIT) {
151                         dx += 0.1;
152                 }
153
154                 cam_pan.x += right.x * dx + fwd.x * dy;
155                 cam_pan.y += fwd.y * dy;
156                 cam_pan.z += right.z * dx + fwd.z * dy;
157         }
158 }
159
160 static void gdisplay(void)
161 {
162         static long prev_msec;
163         static float tm_acc;
164         long msec;
165
166         msec = glutGet(GLUT_ELAPSED_TIME);
167         tm_acc += (float)(msec - prev_msec) / 1000.0f;
168         prev_msec = msec;
169
170         while(tm_acc >= TSTEP) {
171                 gupdate();
172                 tm_acc -= TSTEP;
173         }
174
175         cgm_mtranslation(view_mat, 0, 0, -cam_dist);
176         cgm_mprerotate(view_mat, cam_phi, 1, 0, 0);
177         cgm_mprerotate(view_mat, cam_theta, 0, 1, 0);
178         cgm_mpretranslate(view_mat, cam_pan.x, cam_pan.y, cam_pan.z);
179         glMatrixMode(GL_MODELVIEW);
180         glLoadMatrixf(view_mat);
181
182         set_light_dir(0, -1, 1, 5);
183         set_light_dir(1, 5, 0, 3);
184         set_light_dir(2, -0.5, -2, -3);
185
186         glCallList(dlist);
187 }
188
189 static void greshape(int x, int y)
190 {
191         cgm_mperspective(proj_mat, cgm_deg_to_rad(60), win_aspect, 0.1, 100);
192         glMatrixMode(GL_PROJECTION);
193         glLoadMatrixf(proj_mat);
194 }
195
196 static void gkeyb(int key, int press)
197 {
198         int i;
199
200         for(i=0; i<MAX_INPUTS; i++) {
201                 if(inpmap[i].key == key) {
202                         if(press) {
203                                 inpstate |= 1 << inpmap[i].inp;
204                         } else {
205                                 inpstate &= ~(1 << inpmap[i].inp);
206                         }
207                         break;
208                 }
209         }
210
211         if(press) {
212                 switch(key) {
213                 case '`':
214                         if(!fullscr) {
215                                 game_grabmouse(-1);     /* toggle */
216                         }
217                         break;
218                 }
219         }
220 }
221
222 static void gmouse(int bn, int press, int x, int y)
223 {
224 }
225
226 #define PIHALF  (M_PI / 2.0)
227
228 static void gmotion(int x, int y)
229 {
230         int dx, dy;
231
232         if(mouse_grabbed) {
233                 dx = x - win_width / 2;
234                 dy = y - win_height / 2;
235         } else {
236                 dx = x - mouse_x;
237                 dy = y - mouse_y;
238         }
239
240         if(!(dx | dy)) return;
241
242         if(mouse_state[0] || mouse_grabbed) {
243                 cam_theta += dx * 0.01;
244                 cam_phi += dy * 0.01;
245                 if(cam_phi < -PIHALF) cam_phi = -PIHALF;
246                 if(cam_phi > PIHALF) cam_phi = PIHALF;
247         }
248         /*
249         if(mouse_state[1]) {
250                 float up[3], right[3];
251                 float theta = cam_theta * M_PI / 180.0f;
252                 float phi = cam_phi * M_PI / 180.0f;
253
254                 up[0] = -sin(theta) * sin(phi);
255                 up[1] = -cos(phi);
256                 up[2] = cos(theta) * sin(phi);
257                 right[0] = cos(theta);
258                 right[1] = 0;
259                 right[2] = sin(theta);
260
261                 cam_pan[0] += (right[0] * dx + up[0] * dy) * 0.01;
262                 cam_pan[1] += up[1] * dy * 0.01;
263                 cam_pan[2] += (right[2] * dx + up[2] * dy) * 0.01;
264         }
265         */
266         if(mouse_state[2]) {
267                 cam_dist += dy * 0.1;
268                 if(cam_dist < 0) cam_dist = 0;
269         }
270 }
271
272 static void set_light_dir(int idx, float x, float y, float z)
273 {
274         float pos[4];
275         pos[0] = x;
276         pos[1] = y;
277         pos[2] = z;
278         pos[3] = 0;
279         glLightfv(GL_LIGHT0 + idx, GL_POSITION, pos);
280 }
281
282 static void set_light_color(int idx, float r, float g, float b, float s)
283 {
284         float color[4];
285         color[0] = r * s;
286         color[1] = g * s;
287         color[2] = b * s;
288         color[3] = 1;
289         glLightfv(GL_LIGHT0 + idx, GL_DIFFUSE, color);
290         glLightfv(GL_LIGHT0 + idx, GL_SPECULAR, color);
291 }
292