distance function generation from level data, first pass
[raydungeon] / src / scr_game.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include "opengl.h"
5 #include "cgmath/cgmath.h"
6 #include "game.h"
7 #include "sdr.h"
8 #include "level.h"
9 #include "util.h"
10
11 static int ginit(void);
12 static void gdestroy(void);
13 static int gstart(void);
14 static void gstop(void);
15 static void gdisplay(void);
16 static void greshape(int x, int y);
17 static void gkeyb(int key, int press);
18 static void gmouse(int bn, int press, int x, int y);
19 static void gmotion(int x, int y);
20
21 struct game_screen scr_game = {
22         "game",
23         ginit, gdestroy,
24         gstart, gstop,
25         gdisplay, greshape,
26         gkeyb, gmouse, gmotion
27 };
28
29 static struct level *lvl;
30
31 static float proj_mat[16], view_mat[16];
32
33 static float cam_theta, cam_phi = 20, cam_dist = 10;
34 static cgm_vec3 cam_pan;
35
36 static unsigned int sdr;
37
38 static int ginit(void)
39 {
40         return 0;
41 }
42
43 static void gdestroy(void)
44 {
45 }
46
47 static int gstart(void)
48 {
49         lvl = malloc_nf(sizeof *lvl);
50         init_level(lvl);
51         if(load_level(lvl, "data/test.lvl") == -1) {
52                 return -1;
53         }
54         cam_pan.x = -(lvl->xsz / 2.0f) * lvl->scale;
55         cam_pan.y = 0;
56         cam_pan.z = -(lvl->ysz / 2.0f) * lvl->scale;
57
58         glEnable(GL_DEPTH_TEST);
59
60         if(lvl->sdf_src) {
61                 add_shader_footer(GL_FRAGMENT_SHADER, lvl->sdf_src);
62         } else {
63                 add_shader_footer(GL_FRAGMENT_SHADER, "float eval_sdf(in vec3 p) { return 10000.0; }\n");
64         }
65         if(!(sdr = create_program_load("sdr/raydungeon.v.glsl", "sdr/raydungeon.p.glsl"))) {
66                 return -1;
67         }
68         clear_shader_footer(GL_FRAGMENT_SHADER);
69         glUseProgram(sdr);
70         return 0;
71 }
72
73 static void gstop(void)
74 {
75         destroy_level(lvl);
76         free(lvl);
77
78         free_program(sdr);
79 }
80
81 static void gdisplay(void)
82 {
83         int i, j;
84         float x, y;
85         struct level_cell *cell;
86
87         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
88
89         cgm_mtranslation(view_mat, 0, 0, -cam_dist);
90         cgm_mprerotate_x(view_mat, cam_phi);
91         cgm_mprerotate_y(view_mat, cam_theta);
92         cgm_mpretranslate(view_mat, cam_pan.x, cam_pan.y, cam_pan.z);
93         glMatrixMode(GL_MODELVIEW);
94         glLoadMatrixf(view_mat);
95
96         glUseProgram(sdr);
97
98         glBegin(GL_TRIANGLES);
99         glTexCoord2f(0, 0); glVertex2f(-1, -1);
100         glTexCoord2f(2, 0); glVertex2f(3, -1);
101         glTexCoord2f(0, 2); glVertex2f(-1, 3);
102         glEnd();
103
104         glUseProgram(0);
105
106
107         cell = lvl->cells;
108         glBegin(GL_QUADS);
109         glColor3f(1, 1, 1);
110         glNormal3f(0, 1, 0);
111         for(i=0; i<lvl->ysz; i++) {
112                 y = (float)i * lvl->scale;
113                 for(j=0; j<lvl->xsz; j++) {
114                         x = (float)j * lvl->scale;
115                         if(cell->type) {
116                                 glVertex3f(x - 0.48, -1, y - 0.48);
117                                 glVertex3f(x + 0.48, -1, y - 0.48);
118                                 glVertex3f(x + 0.48, -1, y + 0.48);
119                                 glVertex3f(x - 0.48, -1, y + 0.48);
120                         }
121                         cell++;
122                 }
123         }
124         glEnd();
125 }
126
127 static void greshape(int x, int y)
128 {
129         cgm_mperspective(proj_mat, cgm_deg_to_rad(60), win_aspect, 0.5, 40.0);
130         glMatrixMode(GL_PROJECTION);
131         glLoadMatrixf(proj_mat);
132 }
133
134 static void gkeyb(int key, int press)
135 {
136         if(press) {
137                 switch(key) {
138                 case '`':
139                         if(!fullscr) {
140                                 game_grabmouse(-1);     /* toggle */
141                         }
142                         break;
143
144                 default:
145                         break;
146                 }
147         }
148 }
149
150 static void gmouse(int bn, int press, int x, int y)
151 {
152 }
153
154 static void gmotion(int x, int y)
155 {
156         int dx = x - mouse_x;
157         int dy = y - mouse_y;
158
159         if(!(dx | dy)) return;
160
161         if(mouse_state[0]) {
162                 cam_theta += dx * 0.02;
163                 cam_phi += dy * 0.02;
164                 if(cam_phi < -M_PI/2) cam_phi = -M_PI/2;
165                 if(cam_phi > M_PI/2) cam_phi = M_PI/2;
166         }
167         if(mouse_state[1]) {
168                 float up[3], right[3];
169
170                 up[0] = -sin(cam_theta) * sin(cam_phi);
171                 up[1] = -cos(cam_phi);
172                 up[2] = cos(cam_theta) * sin(cam_phi);
173                 right[0] = cos(cam_theta);
174                 right[1] = 0;
175                 right[2] = sin(cam_theta);
176
177                 cam_pan.x += (right[0] * dx + up[0] * dy) * 0.01;
178                 cam_pan.y += up[1] * dy * 0.01;
179                 cam_pan.z += (right[2] * dx + up[2] * dy) * 0.01;
180         }
181         if(mouse_state[2]) {
182                 cam_dist += dy * 0.01;
183                 if(cam_dist < 0) cam_dist = 0;
184         }
185 }