view src/solar-system.cpp @ 2:c24af3462002

initial commit
author Eris Caffee <discordia@eldalin.com>
date Sat, 27 Apr 2013 13:22:17 -0500
parents
children 4f8b47ac2715 7ae4ee5c27f8
line source
1 #include <GLTools.h>
2 #include <GLShaderManager.h>
3 #include <GLFrustum.h>
4 #include <GLBatch.h>
5 #include <GLFrame.h>
6 #include <GLMatrixStack.h>
7 #include <GLGeometryTransform.h>
8 #include <StopWatch.h>
10 #include <math.h>
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include <string.h>
15 #include <dirent.h>
17 #include <GL/glut.h>
18 #include <GL/glx.h>
20 GLShaderManager shaderManager;
21 GLMatrixStack modelViewMatrix;
22 GLMatrixStack projectionMatrix;
23 GLFrustum viewFrustum;
24 GLGeometryTransform transformPipeline;
26 GLFrame cameraFrame;
28 GLenum polymode = GL_FILL;
30 int width = 800;
31 int height = 600;
32 int fullscreen = 0;
34 #define NUM_SPHERES 50
35 GLFrame spheres[NUM_SPHERES];
37 GLTriangleBatch jupiterBatch;
38 GLTriangleBatch sphereBatch;
39 GLTriangleBatch earthBatch;
40 GLTriangleBatch moonBatch;
41 GLTriangleBatch sunBatch;
42 GLBatch floorBatch;
44 #define TEX_EARTH 1
45 #define TEX_MOON 2
46 #define TEX_JUPITER 3
47 #define TEX_SUN 4
48 #define NUM_TEXTURES 5
49 GLuint uiTextures[NUM_TEXTURES];
51 ////////////////////////////////////////////////////////////////////////////////
52 #define SCREENSHOT_FILENAME_BASE "screenshot-"
53 #define SCREENSHOT_FILENAME_BASELEN 11
54 #define SCREENSHOT_FILENAME_EXT ".tga"
55 #define SCREENSHOT_FILENAME_EXTLEN 4
57 int scandir_filter(const struct dirent * d)
58 {
59 if (memcmp(d->d_name, SCREENSHOT_FILENAME_BASE,
60 SCREENSHOT_FILENAME_BASELEN) != 0) return 0;
61 if (memcmp(d->d_name+SCREENSHOT_FILENAME_BASELEN+3,
62 SCREENSHOT_FILENAME_EXT, SCREENSHOT_FILENAME_EXTLEN) != 0)
63 return 0;
64 if (isdigit(d->d_name[SCREENSHOT_FILENAME_BASELEN])
65 && isdigit(d->d_name[SCREENSHOT_FILENAME_BASELEN+1])
66 && isdigit(d->d_name[SCREENSHOT_FILENAME_BASELEN+2]))
67 return 1;
68 return 0;
69 }
72 int get_next_file_name(char * filename)
73 {
74 static int i = 0;
76 if (i == 0)
77 {
78 char pattern[SCREENSHOT_FILENAME_BASELEN+3+SCREENSHOT_FILENAME_EXTLEN];
79 struct dirent ** file_list;
80 int num_files = scandir(".", &file_list, scandir_filter, alphasort);
81 if (num_files != 0)
82 sprintf(pattern, "%s%%03d%s", SCREENSHOT_FILENAME_BASE,
83 SCREENSHOT_FILENAME_EXT);
84 sscanf(file_list[num_files-1]->d_name, pattern, &i);
85 }
86 i++;
88 sprintf(filename, "%s%03d%s", SCREENSHOT_FILENAME_BASE, i,
89 SCREENSHOT_FILENAME_EXT);
90 return i;
91 }
93 ////////////////////////////////////////////////////////////////////////////////
94 bool LoadTGATexture(const char * szFileName, GLenum minFilter,
95 GLenum magFilter, GLenum wrapMode)
96 {
97 GLbyte * pBits;
98 int nWidth, nHeight, nComponents;
99 GLenum eFormat;
101 pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
102 if (pBits == NULL)
103 {
104 fprintf(stderr, "Failed to load %s\n", szFileName);
105 exit(EXIT_FAILURE);
106 }
108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
114 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
115 glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,
116 eFormat, GL_UNSIGNED_BYTE, pBits);
118 free(pBits);
120 if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||
121 minFilter == GL_LINEAR_MIPMAP_NEAREST ||
122 minFilter == GL_NEAREST_MIPMAP_LINEAR ||
123 minFilter == GL_NEAREST_MIPMAP_NEAREST)
124 {
125 glGenerateMipmap(GL_TEXTURE_2D);
126 }
128 return true;
129 }
131 ////////////////////////////////////////////////////////////////////////////////
132 void DrawSolarSystem(GLfloat yRot)
133 {
134 static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
135 static GLfloat vLightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
136 static M3DVector3f vSunPos = { 0.0f, 0.0f, 0.0f };
137 static M3DVector3f vEarthPos = { 5.0f, 0.0f, 0.0f };
138 static M3DVector3f vJupiterPos = { 10.0f, 0.0f, 0.0f };
140 float RotScale = 100.0;
141 float SunRotSpeed = 1.0/(25*24) * RotScale;
143 float JupiterRotSpeed = 1.0/9 * RotScale;
144 float JupiterAxialTilt = 3.13;
146 float EarthRotSpeed = 1.0/24 * RotScale;
147 float EarthAxialTilt = 23.5;
149 float MoonRotSpeed = 1.0/29.5 * RotScale;
150 float MoonAxialTilt = 6.7;
151 float MoonOrbitSpeed = 1.0/29.5 * RotScale;
152 float MoonOrbitTilt = 5.145;
154 static CStopWatch rotTimer;
156 // Get the light position in eye space
157 M3DVector4f vLightTransformed;
158 M3DMatrix44f mCamera;
159 modelViewMatrix.GetMatrix(mCamera);
160 m3dTransformVector4(vLightTransformed, vLightPos, mCamera);
163 ////////////////////////////////
164 // Begin Sun
166 float SunRot = rotTimer.GetElapsedSeconds() * SunRotSpeed;
168 modelViewMatrix.PushMatrix();
170 modelViewMatrix.Translatev(vSunPos);
171 // North is up!
172 modelViewMatrix.Rotate(-90.0f, 1.0f, 0.0f, 0.0f);
173 // Rotate on axis
174 modelViewMatrix.Rotate(SunRot, 0.0f, 0.0f, 1.0f);
176 glBindTexture(GL_TEXTURE_2D, uiTextures[TEX_SUN]);
177 if (polymode == GL_FILL)
178 {
179 shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,
180 transformPipeline.GetModelViewProjectionMatrix(),
181 0);
182 }
183 else
184 {
185 shaderManager.UseStockShader(GLT_SHADER_FLAT,
186 transformPipeline.GetModelViewProjectionMatrix(),
187 vWhite);
188 }
189 sunBatch.Draw();
190 modelViewMatrix.PopMatrix();
191 // End Sun
192 /////////////////////////////////
195 ////////////////////////////////
196 // Jupiter
197 float JupiterRot = rotTimer.GetElapsedSeconds() * JupiterRotSpeed;
199 modelViewMatrix.PushMatrix();
200 modelViewMatrix.Translatev(vJupiterPos);
201 // North is up!
202 modelViewMatrix.Rotate(-90.0f - JupiterAxialTilt, 1.0f, 0.0f, 0.0f);
203 // Rotate on axis
204 modelViewMatrix.Rotate(JupiterRot, 0.0f, 0.0f, 1.0f);
206 glBindTexture(GL_TEXTURE_2D, uiTextures[TEX_JUPITER]);
207 if (polymode == GL_FILL)
208 {
209 // shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,
210 // transformPipeline.GetModelViewProjectionMatrix(),
211 // 0);
212 shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
213 modelViewMatrix.GetMatrix(),
214 transformPipeline.GetProjectionMatrix(),
215 vLightTransformed,
216 vWhite,
217 0);
218 }
219 else
220 {
221 shaderManager.UseStockShader(GLT_SHADER_FLAT,
222 transformPipeline.GetModelViewProjectionMatrix(),
223 vWhite);
225 }
226 jupiterBatch.Draw();
227 modelViewMatrix.PopMatrix();
228 // End Jupiter
229 ////////////////////////////////
234 /////////////////////////////////
235 // Begin Earth/Moon
237 // Begin Earth
238 float EarthRot = rotTimer.GetElapsedSeconds() * EarthRotSpeed;
240 modelViewMatrix.PushMatrix();
241 modelViewMatrix.Translatev(vEarthPos);
242 modelViewMatrix.PushMatrix(); // Save unrotated matrix for when we do the Moon
244 // NOrth is up!
245 modelViewMatrix.Rotate(-90.0f - EarthAxialTilt, 1.0f, 0.0f, 0.0f);
246 // Rotate on the axis
247 modelViewMatrix.Rotate(EarthRot, 0.0f, 0.0f, 1.0f);
249 if (polymode == GL_FILL)
250 {
251 glBindTexture(GL_TEXTURE_2D, uiTextures[TEX_EARTH]);
252 shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
253 modelViewMatrix.GetMatrix(),
254 transformPipeline.GetProjectionMatrix(),
255 vLightTransformed,
256 vWhite,
257 0);
258 }
259 else
260 {
261 shaderManager.UseStockShader(GLT_SHADER_FLAT,
262 transformPipeline.GetModelViewProjectionMatrix(),
263 vWhite);
265 }
266 earthBatch.Draw();
267 modelViewMatrix.PopMatrix();
269 // Begin Moon
272 // orbit the Earth
273 modelViewMatrix.Rotate(MoonOrbitTilt, 0.0f, 0.0f, 1.0f);
274 // NOrth is up!
275 modelViewMatrix.Rotate(-90.0f - MoonAxialTilt, 0.0f, 1.0f, 0.0f);
277 float MoonRot = rotTimer.GetElapsedSeconds() * MoonOrbitSpeed * 10;
278 modelViewMatrix.Rotate(MoonRot, 0.0f, 1.0f, 0.0f);
280 modelViewMatrix.Translate(0.5f, 0.0f, 0.0f);
283 glBindTexture(GL_TEXTURE_2D, uiTextures[TEX_MOON]);
284 if (polymode == GL_FILL)
285 {
286 shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
287 modelViewMatrix.GetMatrix(),
288 transformPipeline.GetProjectionMatrix(),
289 vLightTransformed,
290 vWhite,
291 0);
292 }
293 else
294 {
295 shaderManager.UseStockShader(GLT_SHADER_FLAT,
296 transformPipeline.GetModelViewProjectionMatrix(),
297 vWhite);
298 }
299 moonBatch.Draw();
300 modelViewMatrix.PopMatrix();
303 modelViewMatrix.PopMatrix();
304 // End Earth/Moon
305 ////////////////////////////////
307 }
309 ////////////////////////////////////////////////////////////////////////////////
310 void RenderScene(void)
311 {
312 static CStopWatch rotTimer;
313 float yRot = - rotTimer.GetElapsedSeconds() * 60.0f;
315 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
317 // Begin Render
318 modelViewMatrix.PushMatrix();
320 // Begin Camera position
321 static M3DMatrix44f mCamera;
322 cameraFrame.GetCameraMatrix(mCamera);
323 modelViewMatrix.MultMatrix(mCamera);
324 // End Camera position
326 DrawSolarSystem(yRot);
328 // End Render
329 modelViewMatrix.PopMatrix();
331 glutSwapBuffers();
332 glutPostRedisplay();
333 }
335 ////////////////////////////////////////////////////////////////////////////////
336 void SetupRC()
337 {
338 shaderManager.InitializeStockShaders();
339 glEnable(GL_DEPTH_TEST);
340 glEnable(GL_CULL_FACE);
341 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
343 gltMakeSphere(jupiterBatch, 0.5f, 128, 128 );
344 gltMakeSphere(earthBatch, 0.2f, 26, 26);
345 gltMakeSphere(moonBatch, 0.1f, 26, 26);
346 gltMakeSphere(sunBatch, 1.0f, 26, 26);
348 glGenTextures(NUM_TEXTURES, uiTextures);
350 glBindTexture(GL_TEXTURE_2D, uiTextures[TEX_EARTH]);
351 LoadTGATexture("../textures/earth.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
353 glBindTexture(GL_TEXTURE_2D, uiTextures[TEX_MOON]);
354 LoadTGATexture("../textures/moon.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
356 glBindTexture(GL_TEXTURE_2D, uiTextures[TEX_JUPITER]);
357 LoadTGATexture("../textures/jupiter.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
359 glBindTexture(GL_TEXTURE_2D, uiTextures[TEX_SUN]);
360 LoadTGATexture("../textures/sun.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);
362 static M3DMatrix44f mCamera;
363 cameraFrame.GetCameraMatrix(mCamera);
364 cameraFrame.MoveForward(-10.0);
365 // cameraFrame.RotateWorld(15.0, 0.0f, 1.0f, 0.0f);
366 }
368 ////////////////////////////////////////////////////////////////////////////////
369 void ShutDownRC(void)
370 {
371 glDeleteTextures(NUM_TEXTURES, uiTextures);
372 }
374 ////////////////////////////////////////////////////////////////////////////////
375 void ChangeSize(int nWidth, int nHeight)
376 {
377 if (nHeight == 0)
378 {
379 nHeight = 1;
380 }
381 glViewport(0,0,nWidth, nHeight);
382 viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
383 projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
384 transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
385 }
387 ////////////////////////////////////////////////////////////////////////////////
388 void SpecialKeys(int key, int x, int y)
389 {
390 }
392 ////////////////////////////////////////////////////////////////////////////////
393 void KeyboardFunc(unsigned char key, int x, int y)
394 {
395 static int changed;
396 static float linear = 0.1f;
398 changed = 0;
400 if ('w' == key)
401 {
402 cameraFrame.MoveForward(linear);
403 changed = 1;
404 }
405 else if ('W' == key)
406 {
407 cameraFrame.MoveForward(10*linear);
408 changed = 1;
409 }
410 else if ('s' == key)
411 {
412 cameraFrame.MoveForward(-linear);
413 changed = 1;
414 }
415 else if ('S' == key)
416 {
417 cameraFrame.MoveForward(-10*linear);
418 changed = 1;
419 }
420 else if ('a' == key)
421 {
422 cameraFrame.MoveRight(linear);
423 changed = 1;
424 }
425 else if ('A' == key)
426 {
427 cameraFrame.MoveRight(10*linear);
428 changed = 1;
429 }
430 else if ('d' == key)
431 {
432 cameraFrame.MoveRight(-linear);
433 changed = 1;
434 }
435 else if ('D' == key)
436 {
437 cameraFrame.MoveRight(-10*linear);
438 changed = 1;
439 }
441 else if ('q' == key)
442 {
443 exit(0);
444 }
445 else if ('f' == key)
446 {
447 if (fullscreen)
448 {
449 glutReshapeWindow(width, height);
450 fullscreen = 0;
451 }
452 else
453 {
454 width = glutGet(GLUT_WINDOW_WIDTH);
455 height = glutGet(GLUT_WINDOW_HEIGHT);
456 glutFullScreen();
457 fullscreen = 1;
458 }
459 }
460 else if ('o' == key)
461 {
462 // 'o' for 'outline' - toggle wireframe rendering
463 polymode = (polymode == GL_FILL) ? GL_LINE : GL_FILL;
464 glPolygonMode(GL_FRONT_AND_BACK, polymode);
465 }
466 else if ('p' == key)
467 {
468 // 'p' for 'print screen' - save a screenshot
469 char filename[20];
470 get_next_file_name(filename);
472 gltGrabScreenTGA(filename);
473 }
475 if (changed)
476 {
477 glutPostRedisplay();
478 }
479 }
481 ////////////////////////////////////////////////////////////////////////////////
482 void MouseMotionFunc (int x, int y)
483 {
484 static float angular = (float) m3dDegToRad(0.5f);
485 static int xx = -1;
486 static int yy = -1;
488 if (-1 == xx)
489 {
490 xx = x;
491 yy = y;
492 }
494 if ((0 == x) || (x < xx))
495 {
496 cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
497 glutPostRedisplay();
498 }
499 else if ((x == glutGet(GLUT_WINDOW_WIDTH) -1) || (x > xx))
500 {
501 cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
502 glutPostRedisplay();
503 }
504 // Hmm. Need to transform normal vector, don't I?
505 // if ((0 == y) || (y < yy))
506 // {
507 // cameraFrame.RotateWorld(angular, 1.0f, 0.0f, 0.0f);
508 // }
509 // else if ((y == glutGet(GLUT_WINDOW_HEIGHT) -1) || (y > yy))
510 // {
511 // cameraFrame.RotateWorld(-angular, 1.0f, 0.0f, 0.0f);
512 // }
514 xx = x;
515 yy = y;
516 }
518 ////////////////////////////////////////////////////////////////////////////////
519 int main (int argc, char * argv[])
520 {
521 gltSetWorkingDirectory(argv[0]);
522 glutInit(&argc, argv);
523 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
524 glutInitWindowSize(800, 600);
525 glutCreateWindow("OpenGL SphereWorld");
527 glutReshapeFunc(ChangeSize);
528 glutDisplayFunc(RenderScene);
529 glutSpecialFunc(SpecialKeys);
530 glutKeyboardFunc(KeyboardFunc);
531 glutMotionFunc(MouseMotionFunc);
532 glutPassiveMotionFunc(MouseMotionFunc);
533 glutSetCursor(GLUT_CURSOR_NONE);
535 GLenum err = glewInit();
536 if (GLEW_OK != err)
537 {
538 fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
539 return 1;
540 }
542 // This enabled vertical sync on Linux
543 // For full generality I should use Glew and check what OS I'm on.
544 // Note that the ATI Catalyst driver exports the WGL_EXT_swap_control
545 // extension name instead of SGI_swap_control as it should.
546 // but nonetheless the actual function provided is glXSwapIntervalSGI
548 PFNGLXSWAPINTERVALSGIPROC SwapInterval;
549 SwapInterval = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI");
551 if (SwapInterval)
552 SwapInterval(1);
554 SetupRC();
555 glutMainLoop();
556 ShutDownRC();
558 return 0;
559 }