rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <assert.h>
|
nuclear@0
|
3 #include "opengl.h"
|
nuclear@0
|
4 #include "game.h"
|
nuclear@0
|
5 #include "sdr.h"
|
nuclear@0
|
6 #include "shader.h"
|
nuclear@0
|
7 #include "shadow.h"
|
nuclear@0
|
8 #include "opt.h"
|
nuclear@3
|
9 #include "mesh.h"
|
nuclear@0
|
10
|
nuclear@2
|
11 #include "room.h"
|
nuclear@6
|
12 #include "dragon.h"
|
nuclear@2
|
13
|
nuclear@0
|
14 static void draw_scene();
|
nuclear@0
|
15
|
nuclear@0
|
16 int win_width, win_height;
|
nuclear@0
|
17 unsigned long cur_time;
|
nuclear@0
|
18 bool dbg_wireframe;
|
nuclear@0
|
19 int dbg_int;
|
nuclear@0
|
20
|
nuclear@0
|
21 unsigned int sdr_shadow, sdr_shadow_notex;
|
nuclear@0
|
22
|
nuclear@6
|
23 static float cam_theta, cam_phi = 23, cam_dist = 26;
|
nuclear@6
|
24 static float cam_x, cam_y, cam_z = 9;
|
nuclear@0
|
25 static bool bnstate[8];
|
nuclear@0
|
26 static int prev_x, prev_y;
|
nuclear@6
|
27 static bool gamectl = false;
|
nuclear@0
|
28
|
nuclear@0
|
29 static unsigned int modkeys;
|
nuclear@0
|
30
|
nuclear@0
|
31
|
nuclear@7
|
32 static Dragon *dragon;
|
nuclear@6
|
33
|
nuclear@6
|
34
|
nuclear@0
|
35 bool game_init()
|
nuclear@0
|
36 {
|
nuclear@0
|
37 if(init_opengl() == -1) {
|
nuclear@0
|
38 return false;
|
nuclear@0
|
39 }
|
nuclear@0
|
40
|
nuclear@0
|
41 glEnable(GL_DEPTH_TEST);
|
nuclear@0
|
42 glEnable(GL_CULL_FACE);
|
nuclear@0
|
43 glEnable(GL_NORMALIZE);
|
nuclear@0
|
44 glEnable(GL_LIGHTING);
|
nuclear@0
|
45 glEnable(GL_LIGHT0);
|
nuclear@0
|
46
|
nuclear@2
|
47 float amb[] = {0.1, 0.1, 0.1, 1.0};
|
nuclear@0
|
48 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
|
nuclear@0
|
49
|
nuclear@0
|
50 if(glcaps.sep_spec) {
|
nuclear@0
|
51 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
|
nuclear@0
|
52 }
|
nuclear@0
|
53 glEnable(GL_MULTISAMPLE);
|
nuclear@0
|
54
|
nuclear@0
|
55 if(!init_shadow(4096)) {
|
nuclear@0
|
56 fprintf(stderr, "failed to initialize shadowmaps\n");
|
nuclear@0
|
57 return false;
|
nuclear@0
|
58 }
|
nuclear@0
|
59 if(!(sdr_shadow = create_program_load("sdr/shadow.v.glsl", "sdr/shadow.p.glsl"))) {
|
nuclear@0
|
60 return false;
|
nuclear@0
|
61 }
|
nuclear@0
|
62 set_uniform_int(sdr_shadow, "tex", 0);
|
nuclear@0
|
63 set_uniform_int(sdr_shadow, "shadowmap", 1);
|
nuclear@0
|
64
|
nuclear@0
|
65 if(!(sdr_shadow_notex = create_program_load("sdr/shadow.v.glsl", "sdr/shadow-notex.p.glsl"))) {
|
nuclear@0
|
66 return false;
|
nuclear@0
|
67 }
|
nuclear@0
|
68 set_uniform_int(sdr_shadow_notex, "shadowmap", 1);
|
nuclear@0
|
69
|
nuclear@2
|
70 if(!init_room()) {
|
nuclear@2
|
71 return false;
|
nuclear@2
|
72 }
|
nuclear@0
|
73
|
nuclear@7
|
74 dragon = new Dragon;
|
nuclear@7
|
75 dragon->set_position(Vector3(0, 5, 20));
|
nuclear@7
|
76 dragon->set_direction(Vector3(0, 0, -1));
|
nuclear@7
|
77 dragon->set_target(Vector3(0, 3, 0));
|
nuclear@7
|
78 dragon->move_head(Vector3(0, 6, 10));
|
nuclear@7
|
79 dragon->set_head_limits(-ROOM_WIDTH * 0.2, ROOM_WIDTH * 0.2, 1, ROOM_HEIGHT - 3);
|
nuclear@6
|
80
|
nuclear@3
|
81 Mesh::use_custom_sdr_attr = false;
|
nuclear@3
|
82
|
nuclear@0
|
83 assert(glGetError() == GL_NO_ERROR);
|
nuclear@0
|
84 return true;
|
nuclear@0
|
85 }
|
nuclear@0
|
86
|
nuclear@0
|
87 void game_cleanup()
|
nuclear@0
|
88 {
|
nuclear@7
|
89 delete dragon;
|
nuclear@2
|
90 cleanup_room();
|
nuclear@0
|
91 }
|
nuclear@0
|
92
|
nuclear@0
|
93 void game_update(unsigned long time_msec)
|
nuclear@0
|
94 {
|
nuclear@0
|
95 cur_time = time_msec;
|
nuclear@6
|
96
|
nuclear@7
|
97 dragon->update();
|
nuclear@0
|
98 }
|
nuclear@0
|
99
|
nuclear@0
|
100 void game_display()
|
nuclear@0
|
101 {
|
nuclear@0
|
102 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@0
|
103
|
nuclear@0
|
104 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
105 glLoadIdentity();
|
nuclear@0
|
106 glTranslatef(0, 0.1, -cam_dist);
|
nuclear@0
|
107 glRotatef(cam_phi, 1, 0, 0);
|
nuclear@0
|
108 glRotatef(cam_theta, 0, 1, 0);
|
nuclear@6
|
109 glTranslatef(-cam_x, -cam_y, -cam_z);
|
nuclear@0
|
110
|
nuclear@6
|
111 float lpos[] = {0, 10, 24, 1};
|
nuclear@0
|
112 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
|
nuclear@0
|
113
|
nuclear@0
|
114 if(opt.shadows && sdr_shadow) {
|
nuclear@6
|
115 begin_shadow_pass(Vector3(lpos[0], lpos[1], lpos[2]), Vector3(0, 0, 0), 45);
|
nuclear@0
|
116 draw_scene();
|
nuclear@0
|
117 end_shadow_pass();
|
nuclear@0
|
118
|
nuclear@0
|
119 glActiveTexture(GL_TEXTURE1);
|
nuclear@0
|
120 glBindTexture(GL_TEXTURE_2D, get_shadow_tex());
|
nuclear@0
|
121
|
nuclear@0
|
122 glMatrixMode(GL_TEXTURE);
|
nuclear@0
|
123 Matrix4x4 shadow_matrix = get_shadow_matrix();
|
nuclear@0
|
124 glLoadTransposeMatrixf(shadow_matrix[0]);
|
nuclear@0
|
125
|
nuclear@0
|
126 glActiveTexture(GL_TEXTURE0);
|
nuclear@0
|
127 glMatrixMode(GL_MODELVIEW);
|
nuclear@0
|
128
|
nuclear@2
|
129 override_shader(sdr_shadow_notex);
|
nuclear@0
|
130
|
nuclear@0
|
131 draw_scene();
|
nuclear@0
|
132
|
nuclear@0
|
133 glActiveTexture(GL_TEXTURE1);
|
nuclear@0
|
134 glBindTexture(GL_TEXTURE_2D, 0);
|
nuclear@0
|
135 glActiveTexture(GL_TEXTURE0);
|
nuclear@0
|
136 glBindTexture(GL_TEXTURE_2D, 0);
|
nuclear@0
|
137 } else {
|
nuclear@0
|
138 draw_scene();
|
nuclear@0
|
139 }
|
nuclear@0
|
140 }
|
nuclear@0
|
141
|
nuclear@0
|
142 static void glmaterial(float r, float g, float b, float spec, float shin)
|
nuclear@0
|
143 {
|
nuclear@0
|
144 float color[] = {r, g, b, 1};
|
nuclear@0
|
145 float scolor[] = {spec, spec, spec, 1};
|
nuclear@0
|
146 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
|
nuclear@0
|
147 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scolor);
|
nuclear@0
|
148 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shin);
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151 static void draw_scene()
|
nuclear@0
|
152 {
|
nuclear@2
|
153 draw_room();
|
nuclear@2
|
154
|
nuclear@0
|
155 glPushMatrix();
|
nuclear@2
|
156 glTranslatef(0, 0.75, 0);
|
nuclear@0
|
157
|
nuclear@3
|
158 glmaterial(1.0, 0.4, 0.3, 0.8, 60.0);
|
nuclear@0
|
159 draw_teapot();
|
nuclear@2
|
160
|
nuclear@2
|
161 glPopMatrix();
|
nuclear@6
|
162
|
nuclear@7
|
163 dragon->draw();
|
nuclear@0
|
164 }
|
nuclear@0
|
165
|
nuclear@0
|
166
|
nuclear@0
|
167 void game_reshape(int x, int y)
|
nuclear@0
|
168 {
|
nuclear@0
|
169 glMatrixMode(GL_PROJECTION);
|
nuclear@0
|
170 glLoadIdentity();
|
nuclear@0
|
171 gluPerspective(45, (float)x / (float)y, 0.2, 200.0);
|
nuclear@0
|
172
|
nuclear@0
|
173 glViewport(0, 0, x, y);
|
nuclear@0
|
174 }
|
nuclear@0
|
175
|
nuclear@0
|
176 void game_keyboard(int bn, bool press)
|
nuclear@0
|
177 {
|
nuclear@0
|
178 if(press) {
|
nuclear@0
|
179 switch(bn) {
|
nuclear@0
|
180 case 27:
|
nuclear@0
|
181 quit();
|
nuclear@0
|
182
|
nuclear@6
|
183 case ' ':
|
nuclear@6
|
184 gamectl = !gamectl;
|
nuclear@6
|
185 break;
|
nuclear@6
|
186
|
nuclear@0
|
187 case 'w':
|
nuclear@0
|
188 dbg_wireframe = !dbg_wireframe;
|
nuclear@0
|
189 redisplay();
|
nuclear@0
|
190 break;
|
nuclear@0
|
191
|
nuclear@0
|
192 case 's':
|
nuclear@0
|
193 opt.shadows = !opt.shadows;
|
nuclear@0
|
194 redisplay();
|
nuclear@0
|
195 break;
|
nuclear@6
|
196
|
nuclear@6
|
197 case 'p':
|
nuclear@6
|
198 printf("camera pos(%g %g %g) rot(%g %g) d(%g)\n",
|
nuclear@6
|
199 cam_x, cam_y, cam_z, cam_theta, cam_phi, cam_dist);
|
nuclear@6
|
200 break;
|
nuclear@0
|
201 }
|
nuclear@0
|
202 }
|
nuclear@0
|
203 }
|
nuclear@0
|
204
|
nuclear@0
|
205 void game_modifier_key(int key, bool press)
|
nuclear@0
|
206 {
|
nuclear@0
|
207 if(press) {
|
nuclear@0
|
208 modkeys |= (1 << key);
|
nuclear@0
|
209 } else {
|
nuclear@0
|
210 modkeys &= ~(1 << key);
|
nuclear@0
|
211 }
|
nuclear@0
|
212 }
|
nuclear@0
|
213
|
nuclear@0
|
214 void game_mbutton(int bn, bool press, int x, int y)
|
nuclear@0
|
215 {
|
nuclear@0
|
216 bnstate[bn] = press;
|
nuclear@0
|
217 prev_x = x;
|
nuclear@0
|
218 prev_y = y;
|
nuclear@0
|
219
|
nuclear@0
|
220 if(modkeys) {
|
nuclear@0
|
221 return;
|
nuclear@0
|
222 }
|
nuclear@0
|
223
|
nuclear@0
|
224 if(bn == 0) {
|
nuclear@0
|
225 }
|
nuclear@0
|
226 }
|
nuclear@0
|
227
|
nuclear@0
|
228 void game_mmotion(int x, int y)
|
nuclear@0
|
229 {
|
nuclear@0
|
230 int dx = x - prev_x;
|
nuclear@0
|
231 int dy = y - prev_y;
|
nuclear@0
|
232 prev_x = x;
|
nuclear@0
|
233 prev_y = y;
|
nuclear@0
|
234
|
nuclear@6
|
235 if(gamectl) {
|
nuclear@7
|
236 dragon->move_head(dx * 0.1, -dy * 0.1);
|
nuclear@6
|
237 }
|
nuclear@6
|
238
|
nuclear@0
|
239 if(modkeys) {
|
nuclear@0
|
240 if(bnstate[0]) {
|
nuclear@0
|
241 cam_theta += dx * 0.5;
|
nuclear@0
|
242 cam_phi += dy * 0.5;
|
nuclear@0
|
243
|
nuclear@0
|
244 if(cam_phi < -90) cam_phi = -90;
|
nuclear@0
|
245 if(cam_phi > 90) cam_phi = 90;
|
nuclear@0
|
246 }
|
nuclear@6
|
247 if(bnstate[1]) {
|
nuclear@6
|
248 float theta = DEG_TO_RAD(cam_theta);
|
nuclear@6
|
249
|
nuclear@6
|
250 float dxp = dx * 0.1;
|
nuclear@6
|
251 float dyp = dy * 0.1;
|
nuclear@6
|
252
|
nuclear@6
|
253 cam_x += cos(theta) * dxp - sin(theta) * dyp;
|
nuclear@6
|
254 if(modkeys & (1 << MOD_SHIFT)) {
|
nuclear@6
|
255 cam_y -= sin(theta) * dxp + cos(theta) * dyp;
|
nuclear@6
|
256 } else {
|
nuclear@6
|
257 cam_z += sin(theta) * dxp + cos(theta) * dyp;
|
nuclear@6
|
258 }
|
nuclear@6
|
259 }
|
nuclear@0
|
260 if(bnstate[2]) {
|
nuclear@0
|
261 cam_dist += dy * 0.1;
|
nuclear@0
|
262 if(cam_dist < 0.0) cam_dist = 0.0;
|
nuclear@0
|
263 }
|
nuclear@0
|
264 }
|
nuclear@0
|
265 }
|