Main.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. #include "Control.h"
  2. #include "GameEngine.h"
  3. #include "Vector3D.h"
  4. #include <math.h>
  5. long tickCounter = 0;
  6. long renderTickCounter = 0;
  7. long tickSum = 0;
  8. long renderTickSum = 0;
  9. long tickTime = -1;
  10. long renderTickTime = -1;
  11. typedef struct GameField {
  12. int id;
  13. float r;
  14. float g;
  15. float b;
  16. float a;
  17. } GameField;
  18. int amountGameFields = -1;
  19. GameField* gameFields = NULL;
  20. GLuint vbo = -1;
  21. GLuint vba = -1;
  22. int fieldSize = 0;
  23. int quality = 0;
  24. int vertices = 0;
  25. GLsizeiptr size = 0;
  26. GLfloat* data = NULL;
  27. Vector3D oldCamera;
  28. Vector3D camera;
  29. float oldLengthAngle;
  30. float lengthAngle;
  31. float oldWidthAngle;
  32. float widthAngle;
  33. float mouseX = 0.0f;
  34. float mouseY = 0.0f;
  35. Vector3D front;
  36. Vector3D back;
  37. Vector3D right;
  38. Vector3D left;
  39. Vector3D up;
  40. Vector3D down;
  41. int selectedIndex = -1;
  42. int selectedLayer = -1;
  43. GameField* getGameField(int layer, int index) {
  44. if(layer == 0) {
  45. return &gameFields[0];
  46. } else if(layer == 1 + fieldSize) {
  47. return &gameFields[1];
  48. }
  49. index += (layer - 1) * fieldSize + 2;
  50. if(index < 2 || index >= amountGameFields) {
  51. return NULL;
  52. }
  53. return &gameFields[index];
  54. }
  55. float interpolate(float lag, float old, float new) {
  56. return old + lag * (new - old);
  57. }
  58. void colorField(GameField* field) {
  59. if(field->id) {
  60. field->r = 1.0f;
  61. field->g = 0.0f;
  62. field->b = 0.0f;
  63. field->a = 1.0f;
  64. } else {
  65. field->r = 1.0f;
  66. field->g = 1.0f;
  67. field->b = 1.0f;
  68. field->a = 1.0f;
  69. }
  70. }
  71. void generateSphere() {
  72. int triangles = fieldSize * quality;
  73. int layers = (2 + fieldSize) * quality;
  74. if(gameFields == NULL) {
  75. amountGameFields = 2 + fieldSize * fieldSize;
  76. gameFields = malloc(sizeof(GameField) * amountGameFields);
  77. for(int i = 0; i < amountGameFields; i++) {
  78. gameFields[i].id = (rand() < RAND_MAX / 2) ? 1 : 0;
  79. colorField(&gameFields[i]);
  80. }
  81. }
  82. if(data == NULL) {
  83. vertices = triangles * layers * 3 * 2;
  84. size = sizeof(GLfloat) * 9 * vertices;
  85. data = malloc(size);
  86. }
  87. for(int l = 0; l < layers; l++) {
  88. float high1 = cos((M_PI * l) / layers);
  89. float high2 = cos((M_PI * (l + 1)) / layers);
  90. float texHigh1 = (l % quality) * (1.0f / quality);
  91. float texHigh2 = texHigh1 + (1.0f / quality);
  92. float r1 = sqrt(1 - high1 * high1);
  93. float r2 = sqrt(1 - high2 * high2);
  94. int flag = (l / quality) == 0;
  95. if(flag) {
  96. texHigh1 = 1 - texHigh1;
  97. texHigh2 = 1 - texHigh2;
  98. }
  99. flag |= (l / quality) >= fieldSize + 1;
  100. for(int i = 0; i < triangles; i++) {
  101. float first = 2 * M_PI * i / triangles;
  102. float second = 2 * M_PI * (i + 1) / triangles;
  103. int off = 27 * 2 * i + l * triangles * 27 * 2;
  104. float texWidth1 = (i % quality) * (1.0f / quality);
  105. float texWidth2 = texWidth1 + (1.0f / quality);
  106. float r = 0.0f;
  107. float g = 0.0f;
  108. float b = 0.0f;
  109. float a = 0.0f;
  110. GameField* field = getGameField(l / quality, i / quality);
  111. if(field != NULL) {
  112. r = field->r;
  113. g = field->g;
  114. b = field->b;
  115. a = field->a;
  116. }
  117. for(int j = 0; j < 54; j += 9) {
  118. data[3 + off + j] = r;
  119. data[4 + off + j] = g;
  120. data[5 + off + j] = b;
  121. data[6 + off + j] = a;
  122. }
  123. data[0 + off] = r2 * cos(first);
  124. data[1 + off] = high2;
  125. data[2 + off] = r2 * sin(first);
  126. data[9 + off] = r1 * cos(first);
  127. data[10 + off] = high1;
  128. data[11 + off] = r1 * sin(first);
  129. data[18 + off] = r1 * cos(second);
  130. data[19 + off] = high1;
  131. data[20 + off] = r1 * sin(second);
  132. if(flag) {
  133. data[7 + off] = texHigh2 * 0.5f;
  134. data[8 + off] = texHigh2 * 0.5f;
  135. data[16 + off] = texHigh1 * 0.5f;
  136. data[17 + off] = texHigh1 * 0.5f;
  137. data[25 + off] = texHigh1 * 0.5f;
  138. data[26 + off] = texHigh1 * 0.5f;
  139. } else {
  140. data[7 + off] = texWidth1;
  141. data[8 + off] = texHigh2;
  142. data[16 + off] = texWidth1;
  143. data[17 + off] = texHigh1;
  144. data[25 + off] = texWidth2;
  145. data[26 + off] = texHigh1;
  146. }
  147. data[27 + off] = r2 * cos(first);
  148. data[28 + off] = high2;
  149. data[29 + off] = r2 * sin(first);
  150. data[36 + off] = r1 * cos(second);
  151. data[37 + off] = high1;
  152. data[38 + off] = r1 * sin(second);
  153. data[45 + off] = r2 * cos(second);
  154. data[46 + off] = high2;
  155. data[47 + off] = r2 * sin(second);
  156. if(flag) {
  157. data[34 + off] = texHigh2 * 0.5f;
  158. data[35 + off] = texHigh2 * 0.5f;
  159. data[43 + off] = texHigh1 * 0.5f;
  160. data[44 + off] = texHigh1 * 0.5f;
  161. data[52 + off] = texHigh2 * 0.5f;
  162. data[53 + off] = texHigh2 * 0.5f;
  163. } else {
  164. data[34 + off] = texWidth1;
  165. data[35 + off] = texHigh2;
  166. data[43 + off] = texWidth2;
  167. data[44 + off] = texHigh1;
  168. data[52 + off] = texWidth2;
  169. data[53 + off] = texHigh2;
  170. }
  171. }
  172. }
  173. glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
  174. }
  175. void updateProjection(float aspect, int program) {
  176. float fovY = 60.0f;
  177. float nearClip = 0.1f;
  178. float farClip = 1000;
  179. float q = 1.0f / (float)tan((0.5f * fovY) * M_PI / 180.0f);
  180. float a = q / aspect;
  181. float b = (nearClip + farClip) / (nearClip - farClip);
  182. float c = (2.0f * nearClip * farClip) / (nearClip - farClip);
  183. GLfloat data[16];
  184. data[0] = a;
  185. data[1] = 0.0f;
  186. data[2] = 0.0f;
  187. data[3] = 0.0f;
  188. data[4] = 0.0f;
  189. data[5] = q;
  190. data[6] = 0.0f;
  191. data[7] = 0.0f;
  192. data[8] = 0.0f;
  193. data[9] = 0.0f;
  194. data[10] = b;
  195. data[11] = -1.0f;
  196. data[12] = 0.0f;
  197. data[13] = 0.0f;
  198. data[14] = c;
  199. data[15] = 0;
  200. GLint loc = glGetUniformLocation(program, "projMatrix");
  201. glUniformMatrix4fv(loc, 1, 0, data);
  202. }
  203. float chooseSmallerPositive(float a, float b) {
  204. if(a < 0) {
  205. return b;
  206. } else if(b < 0 || b > a) {
  207. return a;
  208. }
  209. return b;
  210. }
  211. void updateView(int program, float lag) {
  212. // front
  213. vectorSetAngles(&front, interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
  214. // calculate selected tile
  215. float a = camera.x * camera.x + camera.y * camera.y + camera.z * camera.z - 1;
  216. float b = 2 * (camera.x * front.x + camera.y * front.y + camera.z * front.z);
  217. float c = front.x * front.x + front.y * front.y + front.z * front.z;
  218. float p = b / c;
  219. float q = a / c;
  220. float det = p * p * 0.25f - q;
  221. if(det >= 0) {
  222. float k = sqrt(det);
  223. k = chooseSmallerPositive(-0.5f * p + k, -0.5f * p - k);
  224. if(k >= 0) {
  225. Vector3D v;
  226. vectorSetTo(&v, &camera);
  227. vectorAddMul(&v, &front, k);
  228. selectedLayer = (asin(-v.y) + M_PI_2) * M_1_PI * (2 + fieldSize);
  229. if(selectedLayer == 2 + fieldSize) {
  230. selectedLayer = fieldSize + 1;
  231. }
  232. float tan = atan2(v.z, v.x) * M_1_PI * 0.5;
  233. tan += (tan < 0);
  234. selectedIndex = tan * fieldSize;
  235. }
  236. }
  237. // back
  238. vectorSetToInverse(&back, &front);
  239. // right
  240. vectorSetTo(&right, &front);
  241. vectorCross(&right, 0.0f, 1.0f, 0.0f);
  242. vectorNormalize(&right);
  243. // left
  244. vectorSetToInverse(&left, &right);
  245. // up
  246. vectorSetTo(&up, &front);
  247. vectorCrossWith(&up, &left);
  248. vectorNormalize(&up);
  249. // down
  250. vectorSetToInverse(&down, &up);
  251. GLfloat data[16];
  252. data[0] = right.x;
  253. data[1] = up.x;
  254. data[2] = back.x;
  255. data[3] = 0.0f;
  256. data[4] = right.y;
  257. data[5] = up.y;
  258. data[6] = back.y;
  259. data[7] = 0.0f;
  260. data[8] = right.z;
  261. data[9] = up.z;
  262. data[10] = back.z;
  263. data[11] = 0.0f;
  264. Vector3D interCam;
  265. vectorSetTo(&interCam, &oldCamera);
  266. vectorAddMul(&interCam, &camera, lag);
  267. vectorAddMul(&interCam, &oldCamera, -lag);
  268. data[12] = vectorDotInverse(&right, &interCam);
  269. data[13] = vectorDotInverse(&up, &interCam);
  270. data[14] = vectorDotInverse(&back, &interCam);
  271. data[15] = 1.0f;
  272. // printf("%f %f %f %f\n", data[0], data[4], data[8], data[12]);
  273. // printf("%f %f %f %f\n", data[1], data[5], data[9], data[13]);
  274. // printf("%f %f %f %f\n", data[2], data[6], data[10], data[14]);
  275. // printf("%f %f %f %f\n", data[3], data[7], data[11], data[15]);
  276. // front
  277. vectorSetAngles(&front, interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
  278. front.y = 0;
  279. vectorNormalize(&front);
  280. // back
  281. vectorSetToInverse(&back, &front);
  282. // right
  283. vectorSetTo(&right, &front);
  284. vectorCross(&right, 0.0f, 1.0f, 0.0f);
  285. vectorNormalize(&right);
  286. // left
  287. vectorSetToInverse(&left, &right);
  288. // up
  289. vectorSet(&up, 0.0f, 1.0f, 0.0f);
  290. // down
  291. vectorSetToInverse(&down, &up);
  292. GLint loc = glGetUniformLocation(program, "viewMatrix");
  293. glUniformMatrix4fv(loc, 1, 0, data);
  294. }
  295. void init(int program) {
  296. printf("Init\n");
  297. glGenBuffers(1, &vbo);
  298. glGenVertexArrays(1, &vba);
  299. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  300. glBindVertexArray(vba);
  301. glVertexAttribPointer(0, 3, GL_FLOAT, 0, 36, (GLvoid*)0);
  302. glEnableVertexAttribArray(0);
  303. glVertexAttribPointer(1, 4, GL_FLOAT, 0, 36, (GLvoid*)12);
  304. glEnableVertexAttribArray(1);
  305. glVertexAttribPointer(2, 2, GL_FLOAT, 0, 36, (GLvoid*)28);
  306. glEnableVertexAttribArray(2);
  307. generateSphere();
  308. vectorSet(&camera, 0.0f, 0.0f, -5.0f);
  309. lengthAngle = 0.0f;
  310. widthAngle = 0.0f;
  311. updateProjection(4.0f / 3.0f, program);
  312. }
  313. void invertField(int layer, int index) {
  314. GameField* field = getGameField(layer, index);
  315. if(field != NULL) {
  316. field->id = 1 - field->id;
  317. colorField(field);
  318. }
  319. }
  320. void invertAt(int layer, int index) {
  321. if(layer == 0) {
  322. invertField(layer, index);
  323. layer++;
  324. for(int i = 0; i < fieldSize; i++) {
  325. invertField(layer, i);
  326. }
  327. } else if(layer == fieldSize + 1) {
  328. invertField(layer, index);
  329. layer--;
  330. for(int i = 0; i < fieldSize; i++) {
  331. invertField(layer, i);
  332. }
  333. } else {
  334. invertField(layer, index);
  335. invertField(layer, (index + 1) % fieldSize);
  336. invertField(layer, (index - 1 + fieldSize) % fieldSize);
  337. invertField(layer + 1, index);
  338. invertField(layer - 1, index);
  339. }
  340. }
  341. void tick(int program) {
  342. if(tickTime == -1) {
  343. tickTime = glfwGetTimerValue();
  344. } else {
  345. long time = glfwGetTimerValue();
  346. tickSum += time - tickTime;
  347. tickTime = time;
  348. tickCounter++;
  349. }
  350. vectorSetTo(&oldCamera, &camera);
  351. oldLengthAngle = lengthAngle;
  352. oldWidthAngle = widthAngle;
  353. float factor = 0.05f;
  354. if(keyIsDown(GLFW_KEY_A)) {
  355. vectorAddMul(&camera, &left, factor);
  356. }
  357. if(keyIsDown(GLFW_KEY_D)) {
  358. vectorAddMul(&camera, &right, factor);
  359. }
  360. if(keyIsDown(GLFW_KEY_W)) {
  361. vectorAddMul(&camera, &front, factor);
  362. }
  363. if(keyIsDown(GLFW_KEY_S)) {
  364. vectorAddMul(&camera, &back, factor);
  365. }
  366. if(keyIsDown(GLFW_KEY_SPACE)) {
  367. vectorAddMul(&camera, &up, factor);
  368. }
  369. if(keyIsDown(GLFW_KEY_LEFT_SHIFT)) {
  370. vectorAddMul(&camera, &down, factor);
  371. }
  372. if(mouseIsJustDown(GLFW_MOUSE_BUTTON_1) && selectedLayer != -1 && selectedIndex != -1) {
  373. invertAt(selectedLayer, selectedIndex);
  374. generateSphere();
  375. selectedLayer = -1;
  376. selectedIndex = -1;
  377. }
  378. widthAngle -= mouseY * 0.1f;
  379. lengthAngle -= mouseX * 0.1f;
  380. if(widthAngle >= 89.5) {
  381. widthAngle = 89.5f;
  382. } else if(widthAngle <= -89.5) {
  383. widthAngle = -89.5f;
  384. }
  385. mouseX = 0.0f;
  386. mouseY = 0.0f;
  387. }
  388. void renderTick(int program, float lag) {
  389. if(renderTickTime == -1) {
  390. renderTickTime = glfwGetTimerValue();
  391. } else {
  392. long time = glfwGetTimerValue();
  393. renderTickSum += time - renderTickTime;
  394. renderTickTime = time;
  395. renderTickCounter++;
  396. }
  397. updateView(program, lag);
  398. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  399. glBindVertexArray(vba);
  400. glDrawArrays(GL_TRIANGLES, 0, vertices);
  401. }
  402. void onWindowResize(int width, int height) {
  403. updateProjection((float)width / height, getProgram());
  404. }
  405. void onMouseMove(float x, float y) {
  406. mouseX += x;
  407. mouseY += y;
  408. }
  409. int readPositiveInt(int from, int to, char* message, int error) {
  410. fputs(message, stdout);
  411. fflush(stdout);
  412. int size = 16;
  413. int index = 0;
  414. char* buffer = malloc(sizeof(char) * size);
  415. while(1) {
  416. int c = fgetc(stdin);
  417. if(c == EOF) {
  418. free(buffer);
  419. return error;
  420. } else if(c == '\n') {
  421. int number = 0;
  422. int i = 0;
  423. while(i < index) {
  424. int n = buffer[i] - '0';
  425. if(n < 0 || n > 9) {
  426. break;
  427. }
  428. number = number * 10 + n;
  429. if(number > to) {
  430. break;
  431. }
  432. i++;
  433. }
  434. if(i >= index && number >= from) {
  435. free(buffer);
  436. return number;
  437. }
  438. fputs(message, stdout);
  439. fflush(stdout);
  440. index = 0;
  441. continue;
  442. }
  443. if(index >= size) {
  444. size *= 2;
  445. buffer = realloc(buffer, sizeof(char) * size);
  446. }
  447. buffer[index] = c;
  448. index++;
  449. }
  450. }
  451. int main() {
  452. /*fieldSize = readPositiveInt(5, 20, "Select a game size from 5 to 20:\n", 0);
  453. if(fieldSize == 0)
  454. {
  455. printf("Cannot read from stdin\n");
  456. return EXIT_SUCCESS;
  457. }
  458. quality = readPositiveInt(1, 9, "Select a rendering quality from 1 to 9:\n", 0);
  459. if(quality == 0)
  460. {
  461. printf("Cannot read from stdin\n");
  462. return EXIT_SUCCESS;
  463. }*/
  464. fieldSize = 5;
  465. quality = 8;
  466. if(startGame("Test Game", init, tick, renderTick, onWindowResize, onMouseMove)) {
  467. fprintf(stderr, "Exited with error\n");
  468. // return EXIT_FAILURE;
  469. }
  470. if(data != NULL) {
  471. free(data);
  472. }
  473. if(gameFields != NULL) {
  474. free(gameFields);
  475. }
  476. glDeleteBuffers(1, &vbo);
  477. glDeleteVertexArrays(1, &vba);
  478. printf("_______________TPS_______________\n");
  479. printf("%ld %ld %ld\n", tickCounter, tickSum, tickTime);
  480. printf("%lf\n", (double)tickSum / tickCounter);
  481. printf("%lf\n", 1000000000.0 * tickCounter / tickSum);
  482. printf("_______________FPS_______________\n");
  483. printf("%ld %ld %ld\n", renderTickCounter, renderTickSum, renderTickTime);
  484. printf("%lf\n", (double)renderTickSum / renderTickCounter);
  485. printf("%lf\n", 1000000000.0 * renderTickCounter / renderTickSum);
  486. return EXIT_SUCCESS;
  487. }