Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

System.cpp 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*!
  2. * \file src/System.cpp
  3. * \brief Mostly defines the interface of System implementations.
  4. *
  5. * Currently only SDL is used, but there was a GLUT implementation.
  6. *
  7. * \author Mongoose
  8. */
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <sys/stat.h>
  12. #include <sys/types.h>
  13. #include <string.h>
  14. #include <stdarg.h>
  15. #include <cmath>
  16. #ifdef __APPLE__
  17. #include <OpenGL/gl.h>
  18. #include <OpenGL/glu.h>
  19. #else
  20. #include <GL/gl.h>
  21. #include <GL/glu.h>
  22. #endif
  23. #if defined(linux) || defined(__APPLE__)
  24. #include <time.h>
  25. #include <sys/time.h>
  26. #endif
  27. #include "MatMath.h"
  28. #include "System.h"
  29. ////////////////////////////////////////////////////////////
  30. // Constructors
  31. ////////////////////////////////////////////////////////////
  32. System::System()
  33. {
  34. m_width = 800;
  35. m_height = 600;
  36. m_driver = 0x0;
  37. m_clipFar = 4000.0f;
  38. m_clipNear = 4.0f;
  39. m_fovY = 45.0f;
  40. mConsoleMode = false;
  41. mCommandMode = 0;
  42. printf("[System.Core]\n");
  43. // Hack for bad Map class, as well as reserved commands
  44. addCommandMode("[System.Console]");
  45. mConsoleKey = '`';
  46. bindKeyCommand("+console", mConsoleKey, 0);
  47. #ifdef WIN32
  48. setDriverGL("libGL32.dll");
  49. #else
  50. setDriverGL("/usr/lib/libGL.so.1");
  51. #endif
  52. }
  53. System::~System()
  54. {
  55. }
  56. ////////////////////////////////////////////////////////////
  57. // Public Accessors
  58. ////////////////////////////////////////////////////////////
  59. char *System::bufferString(const char *string, ...)
  60. {
  61. int sz = 60;
  62. int n;
  63. char *text;
  64. va_list args;
  65. // Mongoose 2002.01.01, Only allow valid strings
  66. // we must assume it's NULL terminated also if it passes...
  67. if (!string || !string[0])
  68. {
  69. return NULL;
  70. }
  71. text = new char[sz];
  72. va_start(args, string);
  73. // Mongoose 2002.01.01, Get exact size needed if the first try fails
  74. n = vsnprintf(text, sz, string, args);
  75. // Mongoose 2002.01.01, Realloc correct amount if truncated
  76. while (1)
  77. {
  78. if (n > -1 && n < sz)
  79. {
  80. break;
  81. }
  82. // Mongoose 2002.01.01, For glibc 2.1
  83. if (n > -1)
  84. {
  85. sz = n + 1;
  86. delete [] text;
  87. text = new char[sz];
  88. n = vsnprintf(text, sz, string, args);
  89. break;
  90. }
  91. else // glibc 2.0
  92. {
  93. sz *= 2;
  94. delete [] text;
  95. text = new char[sz];
  96. n = vsnprintf(text, sz, string, args);
  97. }
  98. }
  99. va_end(args);
  100. return text;
  101. }
  102. char *System::fullPath(const char *path, char end)
  103. {
  104. unsigned int i, lenPath, lenEnv, len;
  105. char *env, *dir;
  106. if (!path || !path[0])
  107. return 0;
  108. if (path[0] == '~')
  109. {
  110. #if defined(unix) || defined(__APPLE__)
  111. env = getenv("HOME");
  112. if (!env || !env[0])
  113. {
  114. return 0;
  115. }
  116. lenEnv = strlen(env);
  117. lenPath = strlen(path);
  118. len = lenEnv + lenPath;
  119. dir = new char[len+1];
  120. // Mongoose 2002.08.17, Copy ENV, strip '~', append rest of path
  121. for (i = 0; i < len; ++i)
  122. {
  123. if (i < lenEnv)
  124. {
  125. dir[i] = env[i];
  126. }
  127. else
  128. {
  129. dir[i] = path[1+(i-lenEnv)];
  130. }
  131. }
  132. #else
  133. #error Platform not supported!
  134. #endif
  135. }
  136. else
  137. {
  138. lenPath = strlen(path);
  139. dir = new char[lenPath+1];
  140. strncpy(dir, path, lenPath);
  141. i = lenPath;
  142. }
  143. // Make sure ends in "end" char
  144. if (end && dir[i-1] != end)
  145. {
  146. dir[i++] = end;
  147. }
  148. dir[i] = 0;
  149. return dir;
  150. }
  151. char *System::getFileFromFullPath(char *filename)
  152. {
  153. int i, j, len;
  154. char *str;
  155. len = strlen(filename);
  156. for (i = len, j = 0; i > 0; --i, ++j)
  157. {
  158. if (filename[i] == '/' || filename[i] == '\\')
  159. break;
  160. }
  161. j--;
  162. str = new char[len - j + 1];
  163. for (i = 0; i < len - j; ++i)
  164. {
  165. str[i] = filename[i + len - j];
  166. }
  167. str[i] = 0;
  168. return str;
  169. }
  170. unsigned int System::getTicks()
  171. {
  172. return system_timer(1);
  173. }
  174. int System::createDir(char *path)
  175. {
  176. #ifdef WIN32
  177. return _mkdir(path);
  178. #else
  179. return mkdir(path, S_IRWXU | S_IRWXG);
  180. #endif
  181. }
  182. ////////////////////////////////////////////////////////////
  183. // Public Mutators
  184. ////////////////////////////////////////////////////////////
  185. unsigned int System::addCommandMode(const char *command)
  186. {
  187. if (command && command[0] == '[')
  188. {
  189. mCmdModes.pushBack(command);
  190. return (mCmdModes.size() - 1);
  191. }
  192. else
  193. {
  194. return 0;
  195. }
  196. }
  197. //! \fixme Modifer support later
  198. void System::bindKeyCommand(const char *cmd, unsigned int key, int event)
  199. {
  200. printf("Bound command '%s' -> event %i (0x%x key)\n", cmd, event, key);
  201. mKeyEvents[key] = event;
  202. }
  203. void System::command(const char *cmd)
  204. {
  205. bool modeFound = false;
  206. char *cmdbuf;
  207. if (!cmd || !cmd[0]) // Null command string
  208. return;
  209. if (cmd[0] == '[') // Set a mode, eg "[Engine.OpenGL.Driver]"
  210. {
  211. for (mCmdModes.start(); mCmdModes.forward(); mCmdModes.next())
  212. {
  213. if (strcmp(cmd, mCmdModes.current()) == 0)
  214. {
  215. mCommandMode = mCmdModes.getCurrentIndex();
  216. modeFound = true;
  217. }
  218. }
  219. if (!modeFound)
  220. {
  221. // mCommandMode = 0;
  222. printf("Command> Unknown mode '%s'\n", cmd);
  223. }
  224. }
  225. else // Execute a command in current mode, eg "stat fps"
  226. {
  227. cmdbuf = new char[strlen(cmd) + 1];
  228. strncpy(cmdbuf, cmd, strlen(cmd) + 1);
  229. handleCommand(cmdbuf, mCommandMode);
  230. }
  231. }
  232. int System::loadResourceFile(const char *filename)
  233. {
  234. char buffer[256];
  235. bool line_comment = false;
  236. FILE *f;
  237. char c;
  238. int i, j;
  239. f = fopen(filename, "r");
  240. if (!f)
  241. {
  242. perror(filename);
  243. return -1;
  244. }
  245. printf("Loading %s...\n", filename);
  246. i = 0;
  247. buffer[0] = 0;
  248. // Strip out whitespace and comments
  249. while (fscanf(f, "%c", &c) != EOF)
  250. {
  251. if (line_comment && c != '\n')
  252. continue;
  253. if (i > 254)
  254. {
  255. printf("loadResourceFile> Overflow handled\n");
  256. i = 254;
  257. }
  258. switch (c)
  259. {
  260. case '\v':
  261. case '\t':
  262. break;
  263. case '#':
  264. buffer[i++] = 0;
  265. line_comment = true;
  266. break;
  267. case '\n':
  268. if (line_comment)
  269. {
  270. line_comment = false;
  271. }
  272. if (buffer[0] == 0)
  273. {
  274. i = 0;
  275. continue;
  276. }
  277. buffer[i] = 0;
  278. //printf("'%s'\n", buffer);
  279. // 'Preprocessor' commands
  280. if (buffer[0] == '@')
  281. {
  282. if (strncmp(buffer, "@include ", 9) == 0)
  283. {
  284. for (j = 9; j < i; ++j)
  285. {
  286. buffer[j-9] = buffer[j];
  287. buffer[j-8] = 0;
  288. }
  289. printf("Importing '%s'\n", buffer);
  290. loadResourceFile(fullPath(buffer, '/'));
  291. }
  292. }
  293. else
  294. {
  295. command(buffer);
  296. }
  297. i = 0;
  298. buffer[0] = 0;
  299. break;
  300. default:
  301. buffer[i++] = c;
  302. }
  303. }
  304. fclose(f);
  305. return 0;
  306. }
  307. void System::setDriverGL(const char *driver)
  308. {
  309. unsigned int len;
  310. if (m_driver)
  311. {
  312. delete [] m_driver;
  313. }
  314. if (driver && driver[0])
  315. {
  316. len = strlen(driver);
  317. m_driver = new char[len+1];
  318. strncpy(m_driver, driver, len);
  319. m_driver[len] = 0;
  320. }
  321. }
  322. void System::resetTicks()
  323. {
  324. system_timer(0);
  325. }
  326. void System::initGL()
  327. {
  328. char *s;
  329. // Print driver support information
  330. printf("\n\n\t## GL Driver Info 1 ##\n");
  331. printf("\tVendor : %s\n", glGetString(GL_VENDOR));
  332. printf("\tRenderer : %s\n", glGetString(GL_RENDERER));
  333. printf("\tVersion : %s\n", glGetString(GL_VERSION));
  334. printf("\tExtensions : %s\n\n\n", (char*)glGetString(GL_EXTENSIONS));
  335. // Testing for goodies
  336. // Mongoose 2001.12.31, Fixed string use to check for bad strings
  337. s = (char*)glGetString(GL_EXTENSIONS);
  338. if (s && s[0])
  339. {
  340. printf("\tGL_ARB_multitexture \t\t");
  341. if (strstr(s, "GL_ARB_multitexture"))
  342. {
  343. printf("YES\n");
  344. }
  345. else
  346. {
  347. printf("NO\n");
  348. }
  349. //glActiveTextureARB
  350. //glMultiTexCoord2fARB
  351. //glFogCoordfEXT
  352. printf("\tGL_EXT_texture_env_combine\t\t");
  353. if (strstr(s, "GL_EXT_texture_env_combine"))
  354. {
  355. printf("YES\n");
  356. }
  357. else
  358. {
  359. printf("NO\n");
  360. }
  361. }
  362. // Set up Z buffer
  363. glEnable(GL_DEPTH_TEST);
  364. glDepthFunc(GL_LESS);
  365. // Set up culling
  366. glEnable(GL_CULL_FACE);
  367. //glFrontFace(GL_CW);
  368. glFrontFace(GL_CCW);
  369. //glCullFace(GL_FRONT);
  370. // Set background to black
  371. glClearColor(0.0, 0.0, 0.0, 1.0);
  372. // Disable lighting
  373. glDisable(GL_LIGHTING);
  374. // Set up alpha blending
  375. glEnable(GL_BLEND);
  376. glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  377. //glEnable(GL_ALPHA_TEST); // Disable per pixel alpha blending
  378. glAlphaFunc(GL_GREATER, 0);
  379. glPointSize(5.0);
  380. // Setup shading
  381. glShadeModel(GL_SMOOTH);
  382. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  383. glHint(GL_FOG_HINT, GL_NICEST);
  384. glEnable(GL_COLOR_MATERIAL);
  385. glEnable(GL_DITHER);
  386. // AA polygon edges
  387. glEnable(GL_POLYGON_SMOOTH);
  388. glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
  389. glEnable(GL_POINT_SMOOTH);
  390. glEnable(GL_FOG);
  391. glDisable(GL_LINE_SMOOTH);
  392. glDisable(GL_AUTO_NORMAL);
  393. glDisable(GL_LOGIC_OP);
  394. glDisable(GL_TEXTURE_1D);
  395. glDisable(GL_STENCIL_TEST);
  396. glDisable(GL_NORMALIZE);
  397. glEnableClientState(GL_VERTEX_ARRAY);
  398. glDisableClientState(GL_EDGE_FLAG_ARRAY);
  399. glDisableClientState(GL_COLOR_ARRAY);
  400. glDisableClientState(GL_NORMAL_ARRAY);
  401. glPolygonMode(GL_FRONT, GL_FILL);
  402. glMatrixMode(GL_MODELVIEW);
  403. }
  404. void System::resizeGL(unsigned int w, unsigned int h)
  405. {
  406. if (!w || !h)
  407. {
  408. printf("resizeGL> ERROR assertions 'w > 0', 'h > 0' failed\n");
  409. return;
  410. }
  411. glViewport(0, 0, w, h);
  412. glMatrixMode(GL_PROJECTION);
  413. glLoadIdentity();
  414. // Adjust clipping
  415. // gluPerspective is deprecated!
  416. // gluPerspective(m_fovY, ((GLdouble)w)/((GLdouble)h), m_clipNear, m_clipFar);
  417. // Fix: http://stackoverflow.com/a/2417756
  418. GLfloat fH = tanf(m_fovY * HEL_PI / 360.0f) * m_clipNear;
  419. GLfloat fW = fH * ((GLfloat)w)/((GLfloat)h);
  420. glFrustum(-fW, fW, -fH, fH, m_clipNear, m_clipFar);
  421. glMatrixMode(GL_MODELVIEW);
  422. }
  423. ////////////////////////////////////////////////////////////
  424. // Private Accessors
  425. ////////////////////////////////////////////////////////////
  426. ////////////////////////////////////////////////////////////
  427. // Private Mutators
  428. ////////////////////////////////////////////////////////////
  429. ////////////////////////////////////////////////////////////
  430. // Gobal helper functions
  431. ////////////////////////////////////////////////////////////
  432. // Mongoose 2002.03.23, Checks command to see if it's same
  433. // as symbol, then returns the arg list in command buffer
  434. bool rc_command(const char *symbol, char *command)
  435. {
  436. int i, j, lens, lenc;
  437. if (!symbol || !symbol[0] || !command || !command[0])
  438. {
  439. return false;
  440. }
  441. lens = strlen(symbol);
  442. if (strncmp(command, symbol, lens) == 0)
  443. {
  444. lenc = strlen(command);
  445. // lens+1 skips '=' or ' '
  446. for (i = 0, j = lens+1; j < lenc; ++i, ++j)
  447. {
  448. command[i] = command[j];
  449. command[i+1] = 0;
  450. }
  451. return true;
  452. }
  453. return false;
  454. }
  455. int rc_get_bool(char *buffer, bool *val)
  456. {
  457. if (!buffer || !buffer[0])
  458. {
  459. return -1;
  460. }
  461. if ((strncmp(buffer, "true", 4) == 0) || (buffer[0] == '1'))
  462. *val = true;
  463. else if ((strncmp(buffer, "false", 5) == 0) || (buffer[0] == '0'))
  464. *val = false;
  465. else
  466. return -2;
  467. return 0;
  468. }
  469. unsigned int system_timer(int state)
  470. {
  471. static struct timeval start;
  472. static struct timeval stop;
  473. static struct timezone tz;
  474. switch (state)
  475. {
  476. case 0:
  477. gettimeofday(&start, &tz);
  478. break;
  479. case 1:
  480. gettimeofday(&stop, &tz);
  481. if (start.tv_usec > stop.tv_usec)
  482. {
  483. stop.tv_usec += 1000000;
  484. stop.tv_sec--;
  485. }
  486. stop.tv_usec -= start.tv_usec;
  487. stop.tv_sec -= start.tv_sec;
  488. return ((stop.tv_sec - start.tv_sec) * 1000) + ((stop.tv_usec - start.tv_usec) / 1000);
  489. }
  490. return 0;
  491. }