-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.c
More file actions
336 lines (288 loc) · 8.95 KB
/
main.c
File metadata and controls
336 lines (288 loc) · 8.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
/*
* main.c
*
* Created on: Jan 26, 2011
* Author: Clinton Freeman
* Hacker such that it is unrecognizable: Shawn Waldon & Ryan Belt
*/
#include <SDL.h>
#include <SDL_main.h>
#include <SDL_opengl.h>
#include <SDL_keysym.h>
#include <stdio.h>
#include <math.h>
#include "headers/types.h"
#include "headers/vector_math.h"
#include "headers/rendererMagicNumbers.h"
#include "headers/camera_angling.h"
//Means of the user exiting the main loop - it is static because it will not be seen outside of this file.
static int user_exit = 0;
static float root3over4 = sqrt(3)/4.0;
static float RED[3] = {1.0,0.0,0.0};
static float GREEN[3] = {0.0,1.0,0.0};
static float BLUE[3] = {0.0,0.0,1.0};
static int keys_down[256];
static void input_update(CAMERA_POSITION *cam);
static void resetCamera(CAMERA_POSITION *camera);
static void input_keyDown(SDLKey k, CAMERA_POSITION *cam);
static void randomizeColors(float **colors);
static void input_keyUp(SDLKey k);
static void input_mouseMoved(CAMERA_POSITION *cam, int x, int y);
//Added two new functions - also static as they will not be used outside of this file.
//Eventually these will be moved out of here into a "rendering" subsystem, which is why they are prefixed r_.
static void r_init(CAMERA_POSITION *cam);
static void r_reset(CAMERA_POSITION *cam);
static void r_drawFrame(float **colors);
//Program entry point
int SDL_main(int argc, char* argv[])
{
int i;
SDL_Event event; //Used for handling input events, as you can see later on.
SDL_Surface *screen; //http://www.libsdl.org/cgi/docwiki.cgi/SDL_Surface
CAMERA_POSITION camera;
float *colors[3] = {&RED[0], &GREEN[0], &BLUE[0]};
for (i = 0; i < 256; i++) {
keys_down[i] = 0;
}
resetCamera(&camera);
//The following is pretty self-explanatory
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
{
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}
//You can of course customize this.
SDL_WM_SetCaption("Perspective Projection", "Perspective Projection");
//We need to explicitly enable double buffering
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//Initialize window, setting the resolution to 1024x768 @ 32 bits per pixel. We want an OpenGL window.
screen = SDL_SetVideoMode(1024, 768, 32, SDL_OPENGL);
if(!screen)
{
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}
//Any other one-time initialization would typically go here.
//"Renderer" initialization
r_init(&camera);
//This is what is referred to as the "game loop." Obviously there is not much here currently.
while(!user_exit)
{
bool mouseMoved = FALSE;
int x = 0, y = 0;
//Handle input
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
input_keyDown(event.key.keysym.sym, &camera);
break;
case SDL_KEYUP:
input_keyUp(event.key.keysym.sym);
break;
case SDL_MOUSEBUTTONDOWN:
randomizeColors(colors);
break;
case SDL_MOUSEMOTION:
x = event.motion.x;
y = event.motion.y;
mouseMoved = TRUE;
break;
case SDL_QUIT:
exit(0);
}
}
input_update(&camera);
if (mouseMoved) {
input_mouseMoved(&camera, x, y);
setUpAndLoadModelViewMatrix(&camera);
}
//Here is where you will do any OpenGL drawing. You would also do things like update moving objects, etc.
//Do whatever we need to do to draw a single image.
r_drawFrame(colors);
}
//Shut down SDL
SDL_Quit();
//Everything went OK.
return 0;
}
static void r_init(CAMERA_POSITION *cam)
{
//Enable depth buffering
glEnable(GL_DEPTH_TEST);
//Change to projection mode (three modes: modelview, projection, and texture
//we will be using the just the first two)
glMatrixMode(GL_PROJECTION);
//Load the identity matrix
glLoadIdentity();
//Generate a perspective projection matrix using the following parameters
//90 degree field of view (horizontal), 1.33 aspect ratio (width/height of viewport)
//Distance to the nearplane (must be positive), distance to the farplane (also positive).
gluPerspective(90.0, 1.33, 0.1, 30.0);
// set up and load the model view matrix for this camera
setUpAndLoadModelViewMatrix(cam);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
static void r_reset(CAMERA_POSITION *cam)
{
resetCamera(cam);
setUpAndLoadModelViewMatrix(cam);
}
//Produces a simple image
static void r_drawFrame(float **colors)
{
// Clear the color buffer (these are the final values that get sent to the monitor).
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// White triangle
glColor3f(1.0, 1.0, 1.0);
// first face
glBegin(GL_TRIANGLES);
glColor3fv(colors[0]);
glVertex3f(-0.5, -root3over4, -root3over4);
glColor3fv(colors[1]);
glVertex3f( 0.5, -root3over4, -root3over4);
glColor3fv(colors[2]);
glVertex3f( 0.0, 0.0, root3over4);
glEnd();
// second face
glBegin(GL_TRIANGLES);
glColor3fv(colors[2]);
glVertex3f(0.5, -root3over4, -root3over4);
glColor3fv(colors[0]);
glVertex3f( 0.0, root3over4, -root3over4);
glColor3fv(colors[1]);
glVertex3f( 0.0, 0.0, root3over4);
glEnd();
// third face
glBegin(GL_TRIANGLES);
glColor3fv(colors[1]);
glVertex3f(-0.5, -root3over4, -root3over4);
glColor3fv(colors[2]);
glVertex3f( 0.0, 0.0, root3over4);
glColor3fv(colors[0]);
glVertex3f( 0.0, root3over4, -root3over4);
glEnd();
// base
glBegin(GL_TRIANGLES);
glColor3fv(colors[1]);
glVertex3f(0.0, root3over4, -root3over4);
glColor3fv(colors[0]);
glVertex3f( 0.5, -root3over4, -root3over4);
glColor3fv(colors[2]);
glVertex3f( -0.5, -root3over4, -root3over4);
glEnd();
glBegin(GL_LINES);
// x axis from grey to red (red is +x)
glColor3f(.5,.5,.5);
glVertex3f(-5,0,0);
glColor3f(1,0,0);
glVertex3f(5,0,0);
// y axis from grey to green (green is +y)
glColor3f(.5,.5,.5);
glVertex3f(0,-5,0);
glColor3f(0,1,0);
glVertex3f(0,5,0);
// z axis from grey to blue (blue is +z)
glColor3f(.5,.5,.5);
glVertex3f(0,0,-5);
glColor3f(0,0,1);
glVertex3f(0,0,5);
glEnd();
//The view frustum at this point is still pointing down the negative Z (into the monitor).
//The near plane is located at Z = -1.0, and the far plane at Z = -10.0.
//This means, as before, drawing things at > -1.0 will lead to them being clipped out
//of the view. (Actually, it isn't quite that accurate, primitives at -1.0 get clipped
//as well).
//Try playing around with moving the triangle further away from the nearplane, (i.e. decreasing
//the Z values (-6.0, -7.0, etc.). You should notice it shrinking.
//Also, it is probably best to view a 3D object to see the effects of the perspective projection.
//Try making a cube using GL_QUADS or GL_POLYGON, and placing it offset from the center. You should
//see a foreshortening effect.
//Swap the front and back frame buffers to display the image in our window.
SDL_GL_SwapBuffers();
}
static void input_update(CAMERA_POSITION *cam) {
if (keys_down[SDLK_DOWN]) {
rotateCamera_X(cam, 0.005);
setUpAndLoadModelViewMatrix(cam);
} else if (keys_down[SDLK_UP]) {
rotateCamera_X(cam, -0.005);
setUpAndLoadModelViewMatrix(cam);
}
if (keys_down[SDLK_RIGHT]) {
rotateCamera_Z(cam, 0.005);
setUpAndLoadModelViewMatrix(cam);
} else if (keys_down[SDLK_LEFT]) {
rotateCamera_Z(cam, -0.005);
setUpAndLoadModelViewMatrix(cam);
}
if (keys_down[SDLK_q]) {
rotateCamera_Y(cam, -0.005);
setUpAndLoadModelViewMatrix(cam);
} else if (keys_down[SDLK_e]) {
rotateCamera_Y(cam, 0.005);
setUpAndLoadModelViewMatrix(cam);
}
if (keys_down[SDLK_w]) {
moveCameraForward(cam,0.005);
setUpAndLoadModelViewMatrix(cam);
} else if (keys_down[SDLK_s]) {
moveCameraForward(cam,-0.005);
setUpAndLoadModelViewMatrix(cam);
}
if (keys_down[SDLK_a]) {
moveCameraStrafe(cam, -0.005);
setUpAndLoadModelViewMatrix(cam);
} else if (keys_down[SDLK_d]) {
moveCameraStrafe(cam, 0.005);
setUpAndLoadModelViewMatrix(cam);
}
// if (keys_down[SDLK_SPACE]) {
// cam->offset[1] -= 0.001; // -y
// setUpAndLoadModelViewMatrix(cam);
// } else if (keys_down[SDLK_c]) {
// cam->offset[1] += 0.001; // +y
// setUpAndLoadModelViewMatrix(cam);
// }
if(keys_down[SDLK_r]) {
r_reset(cam);
}
}
static void input_keyDown(SDLKey k, CAMERA_POSITION *cam) {
keys_down[k] = 1;
if(k == SDLK_ESCAPE) user_exit = 1;
if(k == SDLK_BACKQUOTE) cam->isFree = !cam->isFree;
}
static void input_keyUp(SDLKey k) {
keys_down[k] = 0;
}
static void resetCamera(CAMERA_POSITION *camera) {
camera->offset[0] = 0;
camera->offset[1] = -3;
camera->offset[2] = 0;
camera->rot_x = 0;
camera->rot_y = 0;
camera->rot_z = 0;
camera->isFree = TRUE;
}
static void randomizeColors(float **colors) {
int i;
for (i = 2; i > 0; i--) {
float *c = colors[i];
int r = (int) (drand48() * (i+1));
colors[i] = colors[r];
colors[r] = c;
}
}
static void input_mouseMoved(CAMERA_POSITION *cam, int x, int y) {
float halfWinHeight = (float)WINDOW_HEIGHT/2.0;
float halfWinWidth = (float)WINDOW_WIDTH/2.0;
float dx = x-halfWinWidth;
float dy = y-halfWinHeight;
rotateCamera_X(cam, dy/120.0);
rotateCamera_Z(cam, dx/120.0);
//Reset cursor to center
SDL_WarpMouse(halfWinWidth, halfWinHeight);
}