Wrapper.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #include "Wrapper.h"
  2. #include <fstream>
  3. #include <cstring>
  4. #include <iostream>
  5. using namespace std;
  6. DummyClient DummyClient::dummy;
  7. IClient* Engine::client = &DummyClient::dummy;
  8. GLFWwindow* Engine::window = nullptr;
  9. GLuint Engine::vShader = 0;
  10. GLuint Engine::fShader = 0;
  11. GLuint Engine::program = 0;
  12. int Engine::scale = 1;
  13. int Engine::width = 0;
  14. int Engine::height = 0;
  15. bool Engine::init(int width, int height, const char* name)
  16. {
  17. Engine::width = width;
  18. Engine::height = height;
  19. updateScale();
  20. if(!glfwInit())
  21. {
  22. cout << "could not initialize GLFW" << endl;
  23. return false;
  24. }
  25. glfwDefaultWindowHints();
  26. glfwWindowHint(GLFW_VISIBLE, 0);
  27. glfwWindowHint(GLFW_RESIZABLE, 1);
  28. window = glfwCreateWindow(width, height, name, nullptr, nullptr);
  29. if(!window)
  30. {
  31. cout << "could not create window" << endl;
  32. glfwTerminate();
  33. return false;
  34. }
  35. glfwMakeContextCurrent(window);
  36. glfwSwapInterval(1);
  37. glfwShowWindow(window);
  38. GLenum err = glewInit();
  39. if(GLEW_OK != err)
  40. {
  41. cout << "could not initialize GLEW: " << glewGetErrorString(err) << endl;
  42. return false;
  43. }
  44. cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
  45. vShader = 0;
  46. fShader = 0;
  47. program = createProgram(vShader, program);
  48. if(program == 0)
  49. {
  50. if(vShader != 0)
  51. {
  52. glDeleteShader(vShader);
  53. }
  54. if(fShader != 0)
  55. {
  56. glDeleteShader(fShader);
  57. }
  58. glfwDestroyWindow(window);
  59. glfwTerminate();
  60. return false;
  61. }
  62. glfwSetKeyCallback(window, onKeyEvent);
  63. glfwSetMouseButtonCallback(window, onMouseClick);
  64. glfwSetFramebufferSizeCallback(window, onWindowResize);
  65. //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  66. //glfwSetCursorPosCallback(window, onMouseMove);
  67. return true;
  68. }
  69. void Engine::start(IClient& client)
  70. {
  71. Engine::client = &client;
  72. glEnable(GL_CULL_FACE);
  73. glEnable(GL_DEPTH_TEST);
  74. glDepthFunc(GL_LEQUAL);
  75. uint64_t newTime = glfwGetTimerValue();
  76. uint64_t oldTime = newTime;
  77. uint64_t lag = 0;
  78. while(!glfwWindowShouldClose(window))
  79. {
  80. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  81. oldTime = newTime;
  82. newTime = glfwGetTimerValue();
  83. lag += newTime - oldTime;
  84. int ticksPerFrame = 0;
  85. while(lag >= NANOS_PER_TICK)
  86. {
  87. lag -= NANOS_PER_TICK;
  88. Engine::client->tick();
  89. ticksPerFrame++;
  90. if(ticksPerFrame >= MAX_TICKS_PER_FRAME)
  91. {
  92. long skip = lag / NANOS_PER_TICK;
  93. lag -= skip * NANOS_PER_TICK;
  94. if(skip > 0)
  95. {
  96. cout << "skipped " << skip << " game ticks " << lag << endl;
  97. }
  98. break;
  99. }
  100. }
  101. Engine::client->renderTick((float) lag / NANOS_PER_TICK);
  102. glfwSwapBuffers(window);
  103. glfwPollEvents();
  104. }
  105. glDeleteShader(vShader);
  106. glDeleteShader(fShader);
  107. glDeleteProgram(program);
  108. glfwDestroyWindow(window);
  109. glfwTerminate();
  110. }
  111. void Engine::stop()
  112. {
  113. glfwSetWindowShouldClose(window, 1);
  114. }
  115. GLchar* Engine::readFile(const char* name)
  116. {
  117. ifstream in;
  118. in.open(name);
  119. if(!in.fail())
  120. {
  121. int size = 128;
  122. int index = 0;
  123. GLchar* content = new GLchar[size];
  124. while(true)
  125. {
  126. GLchar c = in.get();
  127. if(in.eof())
  128. {
  129. break;
  130. }
  131. if(index >= size - 1)
  132. {
  133. GLchar* newContent = new GLchar[size * 2];
  134. memcpy(newContent, content, size);
  135. size *= 2;
  136. delete[] content;
  137. content = newContent;
  138. }
  139. content[index] = c;
  140. index++;
  141. }
  142. content[index] = '\0';
  143. index++;
  144. in.close();
  145. return content;
  146. }
  147. return nullptr;
  148. }
  149. bool Engine::checkShaderErrors(const char* name, GLuint shader)
  150. {
  151. bool returnValue = false;
  152. cout << "compiling " << name << " shader ..." << endl;
  153. GLenum error = glGetError();
  154. if(error)
  155. {
  156. cout << "error: " << glGetError() << endl;
  157. returnValue = true;
  158. }
  159. else
  160. {
  161. cout << "no error occured ..." << endl;
  162. }
  163. GLint compiled[1];
  164. glGetShaderiv(shader, GL_COMPILE_STATUS, compiled);
  165. if(compiled[0])
  166. {
  167. cout << name << " shader successfully compiled" << endl;
  168. }
  169. else
  170. {
  171. cout << name << "compiling of " << name << " failed:" << endl;
  172. GLchar buffer[512];
  173. GLsizei bufferSize = 512;
  174. GLsizei charsUsed = 0;
  175. glGetShaderInfoLog(shader, bufferSize, &charsUsed, buffer);
  176. // glGetProgramInfoLog should be null terminated ...
  177. buffer[bufferSize - 1] = '\0';
  178. cout << buffer << endl;
  179. returnValue = true;
  180. }
  181. return returnValue;
  182. }
  183. GLuint Engine::compileProgram(GLuint& vShader, GLuint& fShader, const GLchar* vertex, const GLchar* fragment)
  184. {
  185. vShader = glCreateShader(GL_VERTEX_SHADER);
  186. glShaderSource(vShader, 1, &vertex, nullptr);
  187. glCompileShader(vShader);
  188. if(checkShaderErrors("vertex", vShader))
  189. {
  190. return 0;
  191. }
  192. fShader = glCreateShader(GL_FRAGMENT_SHADER);
  193. glShaderSource(fShader, 1, &fragment, nullptr);
  194. glCompileShader(fShader);
  195. if(checkShaderErrors("fragment", fShader))
  196. {
  197. return 0;
  198. }
  199. GLuint program = glCreateProgram();
  200. glAttachShader(program, vShader);
  201. glAttachShader(program, fShader);
  202. glLinkProgram(program);
  203. cout << "linking shaders to program ..." << endl;
  204. GLenum error = glGetError();
  205. if(error)
  206. {
  207. cout << "error: " << glGetError() << endl;
  208. return 0;
  209. }
  210. else
  211. {
  212. cout << "no error occured ..." << endl;
  213. }
  214. GLint compiled[1];
  215. glGetProgramiv(program, GL_LINK_STATUS, compiled);
  216. if(compiled[0])
  217. {
  218. cout << "shaders successfully linked" << endl;
  219. }
  220. else
  221. {
  222. cout << "linking of shaders failed:" << endl;
  223. GLchar buffer[512];
  224. GLsizei bufferSize = 512;
  225. GLsizei charsUsed = 0;
  226. glGetProgramInfoLog(program, bufferSize, &charsUsed, buffer);
  227. // glGetProgramInfoLog should be null terminated ...
  228. buffer[bufferSize - 1] = '\0';
  229. cout << buffer << endl;
  230. return 0;
  231. }
  232. glUseProgram(program);
  233. return program;
  234. }
  235. GLuint Engine::createProgram(GLuint& vShader, GLuint& fShader)
  236. {
  237. GLchar* vertex = readFile("shader/vertex.vs");
  238. if(vertex == nullptr)
  239. {
  240. cout << "cannot read vertex.vs" << endl;
  241. return 0;
  242. }
  243. GLchar* fragment = readFile("shader/fragment.fs");
  244. if(fragment == nullptr)
  245. {
  246. cout << "cannot read fragment.fs" << endl;
  247. delete[] vertex;
  248. return 0;
  249. }
  250. GLuint program = compileProgram(vShader, fShader, vertex, fragment);
  251. delete[] vertex;
  252. delete[] fragment;
  253. return program;
  254. }
  255. void Engine::onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods)
  256. {
  257. client->onKeyEvent(key, scancode, action, mods);
  258. }
  259. void Engine::onMouseClick(GLFWwindow* w, int button, int action, int mods)
  260. {
  261. client->onMouseClick(button, action, mods);
  262. }
  263. void Engine::onWindowResize(GLFWwindow* w, int width, int height)
  264. {
  265. glViewport(0, 0, width, height);
  266. Engine::width = width;
  267. Engine::height = height;
  268. updateScale();
  269. }
  270. void Engine::updateScale()
  271. {
  272. scale = 1;
  273. while(width / (scale + 1) >= 400 && height / (scale + 1) >= 300)
  274. {
  275. scale++;
  276. }
  277. }
  278. int Engine::getScale()
  279. {
  280. return scale;
  281. }
  282. int Engine::getWidth()
  283. {
  284. return width;
  285. }
  286. int Engine::getHeight()
  287. {
  288. return height;
  289. }
  290. GLint Engine::getUniformLocation(const GLchar* name)
  291. {
  292. return glGetUniformLocation(program, name);
  293. }
  294. void Engine::setMatrix(GLint location, const GLfloat* m)
  295. {
  296. glUniformMatrix4fv(location, 1, 0, m);
  297. }
  298. void Engine::setInt(GLint location, GLint i)
  299. {
  300. glUniform1i(location, i);
  301. }
  302. void Engine::setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4)
  303. {
  304. glUniform4f(location, f1, f2, f3, f4);
  305. }
  306. void Engine::printError()
  307. {
  308. GLenum error = glGetError();
  309. switch(error)
  310. {
  311. case GL_NO_ERROR:
  312. cout << "> No error has been recorded." << endl;
  313. break;
  314. case GL_INVALID_ENUM:
  315. cout << "> An unacceptable value is specified for an enumerated argument." << endl;
  316. break;
  317. case GL_INVALID_VALUE:
  318. cout << "> A numeric argument is out of range." << endl;
  319. break;
  320. case GL_INVALID_OPERATION:
  321. cout << "> The specified operation is not allowed in the current state." << endl;
  322. break;
  323. case GL_INVALID_FRAMEBUFFER_OPERATION:
  324. cout << "> The framebuffer object is not complete." << endl;
  325. break;
  326. case GL_OUT_OF_MEMORY:
  327. cout << "> There is not enough memory left to execute the command." << endl;
  328. break;
  329. case GL_STACK_UNDERFLOW:
  330. cout << "> An attempt has been made to perform an operation that would cause an internal stack to underflow." << endl;
  331. break;
  332. case GL_STACK_OVERFLOW:
  333. cout << "> An attempt has been made to perform an operation that would cause an internal stack to overflow." << endl;
  334. break;
  335. default:
  336. cout << "> Unknown OpenGL error: " << error << endl;
  337. }
  338. }