PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/include/eol_graphics.c

http://github.com/engineerOfLies/EngineOfLies
C | 482 lines | 398 code | 46 blank | 38 comment | 35 complexity | fc366cd99745a57bff031fb794d76502 MD5 | raw file
  1. /*
  2. Copyright 2012 Donald Kehoe
  3. This file is part of the Engine of Lies game engine library
  4. The Engine of Lies (EOL) is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. EOL is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with the EOL game engine. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "eol_graphics.h"
  16. #include "eol_logger.h"
  17. #include "eol_config.h"
  18. #include <glib/glist.h>
  19. /*
  20. * Local Types
  21. */
  22. typedef struct
  23. {
  24. void (*callback)(eolGraphicsView info);
  25. }eolGraphicsCallback;
  26. typedef struct
  27. {
  28. eolBool trackFPS; /**if 1, outputs frame data to terminal*/
  29. eolBool fullScreen; /**1 for full screen, 0 for window mode*/
  30. eolDouble scaleFactor; /**all rendering will be scaled by this
  31. factor. default to 1*/
  32. eolUint frameDelay; /**minimum number of milliseconds to wait for
  33. drawing the next frame*/
  34. eolGraphicsView graphicsView; /**graphics view data*/
  35. }eolGraphicsConfig;
  36. /* internal globals. DO NOT EXTERN OUTSIDE OF THIS FILE!*/
  37. eolBool _eolGraphicsInitialized = eolFalse;
  38. eolGraphicsConfig _eolGraphicsConfig;
  39. SDL_Surface * _eol_videobuffer = NULL;
  40. SDL_PixelFormat * _eol_pixelFormat = NULL;
  41. GList * _eol_resize_callbacks = NULL;
  42. eolFloat _eol_graphics_FPS = 0; /*calculated Frames per second*/
  43. eolUint _eol_graphics_NOW = 0;
  44. /*local function prototypes*/
  45. void eol_graphics_setup_resize_callbacks();
  46. void eol_graphics_exit(void);
  47. void eol_resize_graphics(eolUint w, eolUint h, eolBool fs);
  48. int eol_register_resize_callback(void (*callback)(eolGraphicsView view));
  49. void eol_save_screen_shot(const char *file);
  50. /*function definitions*/
  51. void eol_graphics_config()
  52. {
  53. eolConfig *conf = NULL;
  54. _eolGraphicsConfig.graphicsView.depth = 32;
  55. _eolGraphicsConfig.trackFPS = eolTrue;
  56. _eolGraphicsConfig.fullScreen = 0;
  57. _eolGraphicsConfig.graphicsView.openGLOn = 1;
  58. _eolGraphicsConfig.scaleFactor = 1;
  59. _eolGraphicsConfig.frameDelay = 16;
  60. _eolGraphicsConfig.graphicsView.xRes = 640;
  61. _eolGraphicsConfig.graphicsView.yRes = 480;
  62. _eolGraphicsConfig.graphicsView.mipmapping = eolFalse;
  63. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  64. _eolGraphicsConfig.graphicsView.rMask = 0xff000000;
  65. _eolGraphicsConfig.graphicsView.gMask = 0x00ff0000;
  66. _eolGraphicsConfig.graphicsView.bMask = 0x0000ff00;
  67. _eolGraphicsConfig.graphicsView.aMask = 0x000000ff;
  68. #else
  69. _eolGraphicsConfig.graphicsView.rMask = 0x000000ff;
  70. _eolGraphicsConfig.graphicsView.gMask = 0x0000ff00;
  71. _eolGraphicsConfig.graphicsView.bMask = 0x00ff0000;
  72. _eolGraphicsConfig.graphicsView.aMask = 0xff000000;
  73. #endif
  74. conf = eol_config_load("system/graphics.cfg");
  75. if (conf == NULL)return;
  76. eol_config_get_uint_by_tag(&_eolGraphicsConfig.graphicsView.depth,conf,"bitdepth");
  77. eol_config_get_uint_by_tag(&_eolGraphicsConfig.graphicsView.xRes,conf,"x_resolution");
  78. eol_config_get_uint_by_tag(&_eolGraphicsConfig.graphicsView.yRes,conf,"y_resolution");
  79. eol_config_get_uint_by_tag(&_eolGraphicsConfig.frameDelay,conf,"frameDelay");
  80. eol_config_get_bool_by_tag(&_eolGraphicsConfig.fullScreen,conf,"fullScreen");
  81. eol_config_get_bool_by_tag(&_eolGraphicsConfig.trackFPS,conf,"trackFPS");
  82. eol_config_get_bool_by_tag(&_eolGraphicsConfig.graphicsView.mipmapping,conf,"mipmapping");
  83. eol_config_get_bool_by_tag(&_eolGraphicsConfig.graphicsView.openGLOn,conf,"openGLOn");
  84. eol_config_free(&conf);
  85. }
  86. void setup_default_fog()
  87. {
  88. float fogcolor[] = {0.75,0.50,4,1};
  89. glEnable(GL_FOG);
  90. glFogfv(GL_FOG_COLOR,fogcolor);
  91. glFogi(GL_FOG_MODE, GL_EXP);
  92. glFogf(GL_FOG_DENSITY, 0.001f);
  93. glFogf(GL_FOG_START, 1.0f);
  94. glFogf(GL_FOG_END, 200.0f);
  95. }
  96. void eol_graphics_init()
  97. {
  98. eolInt x,y;
  99. eolUint Vflags = SDL_ANYFORMAT | SDL_SRCALPHA;
  100. eolUint HWflag = 0;
  101. eol_logger_message(
  102. EOL_LOG_INFO,
  103. "eol_graphics: initializing\n");
  104. x = _eolGraphicsConfig.graphicsView.xRes;
  105. y = _eolGraphicsConfig.graphicsView.yRes;
  106. if(_eolGraphicsConfig.fullScreen)Vflags |= SDL_FULLSCREEN;
  107. if(_eolGraphicsConfig.graphicsView.openGLOn)Vflags |= SDL_OPENGL;
  108. #if defined(_WIN32)
  109. stream = freopen("stdout.txt", "w", stdout);
  110. stream = freopen("stderr.txt", "w", stderr);
  111. #endif
  112. if (SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_DOUBLEBUF) < 0 )
  113. {
  114. eol_logger_message(
  115. EOL_LOG_ERROR,
  116. "eol_graphics: Unable to init SDL: %s\n", SDL_GetError());
  117. exit(1);
  118. }
  119. atexit(SDL_Quit);
  120. if(SDL_VideoModeOK(x, y, 32, Vflags | SDL_HWSURFACE))
  121. {
  122. _eolGraphicsConfig.graphicsView.xRes = x;
  123. _eolGraphicsConfig.graphicsView.yRes = y;
  124. _eolGraphicsConfig.graphicsView.depth = 32;
  125. HWflag = SDL_HWSURFACE;
  126. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  127. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  128. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  129. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  130. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  131. }
  132. else if(SDL_VideoModeOK(x + 6, y, 32, Vflags | SDL_HWSURFACE))
  133. {
  134. _eolGraphicsConfig.graphicsView.xRes = x + 6;
  135. _eolGraphicsConfig.graphicsView.yRes = y;
  136. _eolGraphicsConfig.graphicsView.depth = 32;
  137. HWflag = SDL_HWSURFACE;
  138. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  139. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  140. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  141. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  142. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  143. }
  144. else if(SDL_VideoModeOK(x, y, 32, Vflags))
  145. {
  146. _eolGraphicsConfig.graphicsView.xRes = x;
  147. _eolGraphicsConfig.graphicsView.yRes = y;
  148. _eolGraphicsConfig.graphicsView.depth = 32;
  149. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  150. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  151. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  152. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  153. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  154. }
  155. else if(SDL_VideoModeOK(x + 6, y, 32, Vflags))
  156. {
  157. _eolGraphicsConfig.graphicsView.xRes = x + 6;
  158. _eolGraphicsConfig.graphicsView.yRes = y;
  159. _eolGraphicsConfig.graphicsView.depth = 32;
  160. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  161. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  162. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  163. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  164. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  165. }
  166. else if(SDL_VideoModeOK(x + 6, y, 32, Vflags))
  167. {
  168. _eolGraphicsConfig.graphicsView.xRes = x + 6;
  169. _eolGraphicsConfig.graphicsView.yRes = y;
  170. _eolGraphicsConfig.graphicsView.depth = 32;
  171. Vflags &= ~SDL_FULLSCREEN;
  172. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  173. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  174. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  175. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  176. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  177. }
  178. else
  179. {
  180. eol_logger_message(
  181. EOL_LOG_ERROR,
  182. "Unable to use your screen: %s\n Deepest apologies \n", SDL_GetError());
  183. exit(1);
  184. }
  185. _eol_videobuffer = SDL_SetVideoMode(
  186. _eolGraphicsConfig.graphicsView.xRes,
  187. _eolGraphicsConfig.graphicsView.yRes,
  188. _eolGraphicsConfig.graphicsView.depth,
  189. Vflags | HWflag);
  190. if ( _eol_videobuffer == NULL )
  191. {
  192. eol_logger_message(
  193. EOL_LOG_ERROR,
  194. "Unable to set video mode: %s\n", SDL_GetError());
  195. exit(1);
  196. }
  197. _eol_pixelFormat = _eol_videobuffer->format;
  198. /*sets the viewing port to the size of the videobuffer*/
  199. glViewport(0,0,_eolGraphicsConfig.graphicsView.xRes, _eolGraphicsConfig.graphicsView.yRes);
  200. glMatrixMode(GL_PROJECTION);
  201. glLoadIdentity();
  202. /*view angle, aspect ratio, near clip distance, far clip distance*/
  203. /*TODO: put near/far clip in graphics view config*/
  204. gluPerspective( 40, (eolDouble)x / (eolDouble)y, .01, 2000.0f);
  205. glMatrixMode( GL_MODELVIEW );
  206. glLoadIdentity();
  207. /*Clear color for the buffer*/
  208. glClearColor(0,0,0,0);
  209. /*Enables drawing pixels according to thier depth*/
  210. glDepthFunc(GL_LESS);
  211. glEnable(GL_DEPTH_TEST);
  212. /*Enables alpha testing*/
  213. glAlphaFunc(GL_GREATER,0);
  214. glEnable(GL_ALPHA_TEST);
  215. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  216. /*now record the matrix view data*/
  217. glGetIntegerv(GL_VIEWPORT,_eolGraphicsConfig.graphicsView.viewPort);
  218. glGetDoublev(GL_MODELVIEW_MATRIX, _eolGraphicsConfig.graphicsView.modelView);
  219. glGetDoublev(GL_PROJECTION_MATRIX, _eolGraphicsConfig.graphicsView.projection);
  220. _eolGraphicsInitialized = eolTrue;
  221. atexit(eol_graphics_exit);
  222. setup_default_fog();
  223. eol_logger_message(
  224. EOL_LOG_INFO,
  225. "eol_graphics: initialized\n"
  226. );
  227. }
  228. eolBool eol_graphics_initialized()
  229. {
  230. return _eolGraphicsInitialized;
  231. }
  232. eolUint eol_index_color(eolUint color)
  233. {
  234. switch(color)
  235. {
  236. case Eol_Red:
  237. return SDL_MapRGB(_eol_videobuffer->format,138,0,0);;
  238. case Eol_Green:
  239. return SDL_MapRGB(_eol_videobuffer->format,0,138,0);;
  240. case Eol_Blue:
  241. return SDL_MapRGB(_eol_videobuffer->format,0,0,138);;
  242. case Eol_Yellow:
  243. return SDL_MapRGB(_eol_videobuffer->format,196,196,0);;
  244. case Eol_Orange:
  245. return SDL_MapRGB(_eol_videobuffer->format,148,118,0);;
  246. case Eol_Violet:
  247. return SDL_MapRGB(_eol_videobuffer->format,128,0,128);
  248. case Eol_Brown:
  249. return SDL_MapRGB(_eol_videobuffer->format,100,64,4);
  250. case Eol_Grey:
  251. return SDL_MapRGB(_eol_videobuffer->format,128,128,128);
  252. case Eol_DarkRed:
  253. return SDL_MapRGB(_eol_videobuffer->format,64,0,0);
  254. case Eol_DarkGreen:
  255. return SDL_MapRGB(_eol_videobuffer->format,0,64,0);
  256. case Eol_DarkBlue:
  257. return SDL_MapRGB(_eol_videobuffer->format,0,0,64);
  258. case Eol_DarkYellow:
  259. return SDL_MapRGB(_eol_videobuffer->format,60,60,0);
  260. case Eol_DarkOrange:
  261. return SDL_MapRGB(_eol_videobuffer->format,64,56,0);
  262. case Eol_DarkViolet:
  263. return SDL_MapRGB(_eol_videobuffer->format,60,0,60);
  264. case Eol_DarkBrown:
  265. return SDL_MapRGB(_eol_videobuffer->format,56,32,2);
  266. case Eol_DarkGrey:
  267. return SDL_MapRGB(_eol_videobuffer->format,64,64,64);
  268. case Eol_LightRed:
  269. return SDL_MapRGB(_eol_videobuffer->format,255,32,32);
  270. case Eol_LightGreen:
  271. return SDL_MapRGB(_eol_videobuffer->format,32,255,32);
  272. case Eol_LightBlue:
  273. return SDL_MapRGB(_eol_videobuffer->format,32,32,255);
  274. case Eol_LightYellow:
  275. return SDL_MapRGB(_eol_videobuffer->format,250,250,60);
  276. case Eol_LightOrange:
  277. return SDL_MapRGB(_eol_videobuffer->format,255,234,30);
  278. case Eol_LightViolet:
  279. return SDL_MapRGB(_eol_videobuffer->format,250,30,250);
  280. case Eol_LightBrown:
  281. return SDL_MapRGB(_eol_videobuffer->format,200,100,32);
  282. case Eol_LightGrey:
  283. return SDL_MapRGB(_eol_videobuffer->format,196,196,196);
  284. case Eol_Black:
  285. return SDL_MapRGB(_eol_videobuffer->format,0,0,0);
  286. case Eol_White:
  287. return SDL_MapRGB(_eol_videobuffer->format,255,255,255);
  288. case Eol_Tan:
  289. return SDL_MapRGB(_eol_videobuffer->format,255,128,64);
  290. case Eol_Gold:
  291. return SDL_MapRGB(_eol_videobuffer->format,255,245,30);
  292. case Eol_Silver:
  293. return SDL_MapRGB(_eol_videobuffer->format,206,206,226);
  294. case Eol_YellowGreen:
  295. return SDL_MapRGB(_eol_videobuffer->format,196,255,30);
  296. case Eol_Cyan:
  297. return SDL_MapRGB(_eol_videobuffer->format,0,255,255);;
  298. case Eol_Magenta:
  299. return SDL_MapRGB(_eol_videobuffer->format,255,0,255);
  300. }
  301. return SDL_MapRGB(_eol_videobuffer->format,0,0,0);
  302. }
  303. void eol_frame_delay(eolUint delay)
  304. {
  305. static eolUint pass = 100;
  306. eolUint dif;
  307. dif = SDL_GetTicks() - pass;
  308. if(dif < delay)SDL_Delay( delay - dif);
  309. pass = SDL_GetTicks();
  310. }
  311. void eol_graphics_frame_begin()
  312. {
  313. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  314. glPushMatrix();
  315. }
  316. void eol_graphics_frame_end()
  317. {
  318. eolUint Then;
  319. eolUint delay;
  320. glPopMatrix();
  321. SDL_GL_SwapBuffers();
  322. eol_frame_delay(_eolGraphicsConfig.frameDelay);
  323. Then = _eol_graphics_NOW;
  324. _eol_graphics_NOW = SDL_GetTicks();
  325. if(_eolGraphicsConfig.trackFPS)
  326. {
  327. delay = _eol_graphics_NOW - Then;
  328. if (delay != 0)
  329. {
  330. _eol_graphics_FPS = (_eol_graphics_FPS + (1000.0 / delay))*0.5;
  331. }
  332. }
  333. }
  334. eolUint eol_graphics_get_now()
  335. {
  336. return _eol_graphics_NOW;
  337. }
  338. eolUint eol_graphics_get_pixel(SDL_Surface *surface, eolUint x, eolUint y)
  339. {
  340. /* Here p is the address to the pixel we want to retrieve*/
  341. Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;
  342. if((x < 0)||(x >= surface->w)||(y < 0)||(y >= surface->h))return -1;
  343. switch(surface->format->BytesPerPixel)
  344. {
  345. case 1:
  346. return *p;
  347. case 2:
  348. return *(Uint16 *)p;
  349. case 3:
  350. if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
  351. return p[0] << 16 | p[1] << 8 | p[2];
  352. else
  353. return p[0] | p[1] << 8 | p[2] << 16;
  354. case 4:
  355. return *(Uint32 *)p;
  356. }
  357. return 0; /*shouldn't happen, but avoids warnings*/
  358. }
  359. void eol_graphics_put_pixel(SDL_Surface *surface, eolUint x, eolUint y, eolUint pixel)
  360. {
  361. SDL_Rect point = {0,0,1,1};
  362. point.x = x;
  363. point.y = y;
  364. SDL_FillRect(surface,&point,pixel);
  365. }
  366. /**
  367. * @brief destructor for the graphics component. called at exit.
  368. * */
  369. void eol_graphics_exit(void)
  370. {
  371. eol_logger_message(
  372. EOL_LOG_INFO,
  373. "eol_graphics: closing\n");
  374. _eolGraphicsInitialized = eolFalse;
  375. g_list_foreach(_eol_resize_callbacks, (GFunc)free, NULL);
  376. g_list_free(_eol_resize_callbacks);
  377. eol_logger_message(
  378. EOL_LOG_INFO,
  379. "eol_graphics: closed\n");
  380. }
  381. void eol_graphics_register_resize(void (*callback)(eolGraphicsView info))
  382. {
  383. eolGraphicsCallback *newCallback = NULL;
  384. if ((callback == NULL) ||
  385. (_eolGraphicsInitialized == eolFalse))
  386. {
  387. return;
  388. }
  389. newCallback = (eolGraphicsCallback *)malloc(sizeof(eolGraphicsCallback));
  390. newCallback->callback = callback;
  391. _eol_resize_callbacks = g_list_append(_eol_resize_callbacks,(void *)newCallback);
  392. callback(_eolGraphicsConfig.graphicsView);
  393. }
  394. SDL_PixelFormat *eol_graphics_get_pixel_format()
  395. {
  396. if (!eol_graphics_initialized())
  397. {
  398. eol_logger_message(
  399. EOL_LOG_WARN,
  400. "eol_graphics:cannot get pixel format, graphics not initialized\n");
  401. return NULL;
  402. }
  403. return _eol_pixelFormat;
  404. }
  405. void eol_graphics_get_view(eolGraphicsView *view)
  406. {
  407. if (!eol_graphics_initialized())
  408. {
  409. eol_logger_message(
  410. EOL_LOG_WARN,
  411. "eol_graphics:cannot get view, graphics not initialized\n");
  412. return;
  413. }
  414. if (view == NULL)
  415. {
  416. eol_logger_message(
  417. EOL_LOG_WARN,
  418. "eol_graphics:cannot get view, passed a NULL view pointer\n");
  419. return;
  420. }
  421. /*TODO: make this thread safe*/
  422. memcpy(view,&_eolGraphicsConfig.graphicsView,sizeof(eolGraphicsView));
  423. }
  424. eolFloat eol_graphics_get_FPS()
  425. {
  426. return _eol_graphics_FPS;
  427. }
  428. void eol_graphics_get_size(eolUint * w, eolUint * h)
  429. {
  430. if (w != NULL)*w = _eolGraphicsConfig.graphicsView.xRes;
  431. if (h != NULL)*h = _eolGraphicsConfig.graphicsView.yRes;
  432. }
  433. /* eol @ eof*/