98f5d7631bb2d57d6a4192515f47bde0a96da318
[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 cam_theta, cam_phi = 20, cam_dist;
35 static cgm_vec3 cam_pan;
36
37 static struct goat3d *gscn;
38 static int dlist;
39
40
41 static int ginit(void)
42 {
43         int i, num, nfaces;
44         int *idxarr;
45         float *varr, *narr, *uvarr;
46         float xform[16];
47
48         if(!(gscn = goat3d_create()) || goat3d_load(gscn, "data/level1.g3d")) {
49                 return -1;
50         }
51
52         dlist = glGenLists(1);
53         glNewList(dlist, GL_COMPILE);
54         num = goat3d_get_node_count(gscn);
55         for(i=0; i<num; i++) {
56                 struct goat3d_node *node = goat3d_get_node(gscn, i);
57                 if(match_prefix(goat3d_get_node_name(node), "portal_")) {
58                         continue;
59                 }
60                 if(goat3d_get_node_type(node) == GOAT3D_NODE_MESH) {
61                         struct goat3d_mesh *mesh = goat3d_get_node_object(node);
62
63                         goat3d_get_node_matrix(node, xform);
64                         glPushMatrix();
65                         glMultMatrixf(xform);
66
67                         varr = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX);
68                         narr = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL);
69                         uvarr = goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD);
70
71                         glEnableClientState(GL_VERTEX_ARRAY);
72                         glVertexPointer(3, GL_FLOAT, 0, varr);
73
74                         if(narr) {
75                                 glEnableClientState(GL_NORMAL_ARRAY);
76                                 glNormalPointer(GL_FLOAT, 0, narr);
77                         }
78                         if(uvarr) {
79                                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
80                                 glTexCoordPointer(2, GL_FLOAT, 0, uvarr);
81                         }
82
83                         nfaces = goat3d_get_mesh_face_count(mesh);
84                         idxarr = goat3d_get_mesh_faces(mesh);
85                         glDrawElements(GL_TRIANGLES, nfaces * 3, GL_UNSIGNED_INT, idxarr);
86
87                         glDisableClientState(GL_VERTEX_ARRAY);
88                         glDisableClientState(GL_NORMAL_ARRAY);
89                         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
90
91                         glPopMatrix();
92                 }
93         }
94         glEndList();
95
96         return 0;
97 }
98
99 static void gdestroy(void)
100 {
101         goat3d_free(gscn);
102 }
103
104 static int gstart(void)
105 {
106         float amb[] = {0.25, 0.25, 0.25, 1};
107
108         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
109
110         set_light_color(0, 1, 1, 1, 0.8);
111         glEnable(GL_LIGHT0);
112         set_light_color(1, 1, 0.6, 0.5, 0.2);
113         glEnable(GL_LIGHT1);
114         set_light_color(2, 0.5, 0.6, 1, 0.3);
115         glEnable(GL_LIGHT2);
116         return 0;
117 }
118
119 static void gstop(void)
120 {
121 }
122
123 #define TSTEP   (1.0f / 30.0f)
124
125 static void gupdate(void)
126 {
127         if(inpstate & INP_MOVE_BITS) {
128                 cgm_vec3 fwd, right;
129                 float theta = cam_theta * M_PI / 180.0f;
130                 float phi = cam_phi * M_PI / 180.0f;
131
132                 float dx = 0, dy = 0;
133
134                 fwd.x = -sin(theta) * cos(phi);
135                 fwd.y = sin(phi);
136                 fwd.z = cos(theta) * cos(phi);
137                 right.x = cos(theta);
138                 right.y = 0;
139                 right.z = sin(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         glMatrixMode(GL_MODELVIEW);
176         glLoadIdentity();
177         glTranslatef(0, 0, -cam_dist);
178         glRotatef(cam_phi, 1, 0, 0);
179         glRotatef(cam_theta, 0, 1, 0);
180         glTranslatef(cam_pan.x, cam_pan.y, cam_pan.z);
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 }
192
193 static void gkeyb(int key, int press)
194 {
195         int i;
196
197         for(i=0; i<MAX_INPUTS; i++) {
198                 if(inpmap[i].key == key) {
199                         if(press) {
200                                 inpstate |= 1 << inpmap[i].inp;
201                         } else {
202                                 inpstate &= ~(1 << inpmap[i].inp);
203                         }
204                         break;
205                 }
206         }
207 }
208
209 static void gmouse(int bn, int press, int x, int y)
210 {
211 }
212
213 static void gmotion(int x, int y)
214 {
215         int dx = x - mouse_x;
216         int dy = y - mouse_y;
217
218         if(!(dx | dy)) return;
219
220         if(mouse_state[0]) {
221                 cam_theta += dx * 0.5;
222                 cam_phi += dy * 0.5;
223                 if(cam_phi < -90) cam_phi = -90;
224                 if(cam_phi > 90) cam_phi = 90;
225         }
226         /*
227         if(mouse_state[1]) {
228                 float up[3], right[3];
229                 float theta = cam_theta * M_PI / 180.0f;
230                 float phi = cam_phi * M_PI / 180.0f;
231
232                 up[0] = -sin(theta) * sin(phi);
233                 up[1] = -cos(phi);
234                 up[2] = cos(theta) * sin(phi);
235                 right[0] = cos(theta);
236                 right[1] = 0;
237                 right[2] = sin(theta);
238
239                 cam_pan[0] += (right[0] * dx + up[0] * dy) * 0.01;
240                 cam_pan[1] += up[1] * dy * 0.01;
241                 cam_pan[2] += (right[2] * dx + up[2] * dy) * 0.01;
242         }
243         */
244         if(mouse_state[2]) {
245                 cam_dist += dy * 0.1;
246                 if(cam_dist < 0) cam_dist = 0;
247         }
248 }
249
250 static void set_light_dir(int idx, float x, float y, float z)
251 {
252         float pos[4];
253         pos[0] = x;
254         pos[1] = y;
255         pos[2] = z;
256         pos[3] = 0;
257         glLightfv(GL_LIGHT0 + idx, GL_POSITION, pos);
258 }
259
260 static void set_light_color(int idx, float r, float g, float b, float s)
261 {
262         float color[4];
263         color[0] = r * s;
264         color[1] = g * s;
265         color[2] = b * s;
266         color[3] = 1;
267         glLightfv(GL_LIGHT0 + idx, GL_DIFFUSE, color);
268         glLightfv(GL_LIGHT0 + idx, GL_SPECULAR, color);
269 }
270