main.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * 3D Engine
  3. * main.c:
  4. * Based on pikuma.com 3D software renderer in C
  5. * Copyright (c) 2021 986-Studio. All rights reserved.
  6. *
  7. * Created by Manoël Trapier on 01/03/2021.
  8. */
  9. #include <stdio.h>
  10. #include <stdint.h>
  11. #include <stdbool.h>
  12. #include <SDL.h>
  13. #include <log.h>
  14. #include <array.h>
  15. #include <display.h>
  16. #include <vector.h>
  17. #include <mesh.h>
  18. bool isRunning = true;
  19. int previousFrameTime = 0;
  20. vec3_t cameraPosition =
  21. {
  22. .x = 0,
  23. .y = 0,
  24. .z = -5,
  25. };
  26. triangle_t *projectedTriangles = NULL;
  27. double fovFactor = 640;
  28. void setup()
  29. {
  30. frameBuffer = (uint32_t *)calloc(windowWidth * windowHeight, sizeof(uint32_t));
  31. if (!frameBuffer)
  32. {
  33. log(TLOG_PANIC, NULL, "Memory allocation error.");
  34. goto exit;
  35. }
  36. frameBufferTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, windowWidth,
  37. windowHeight);
  38. if (frameBufferTexture == NULL)
  39. {
  40. log(TLOG_PANIC, NULL, "SDL Texture creation error: %s", SDL_GetError());
  41. goto exit;
  42. }
  43. //loadCubeMeshData();
  44. loadOBJFile("assets/f22.obj");
  45. exit:
  46. return;
  47. }
  48. void processInput()
  49. {
  50. SDL_Event event;
  51. SDL_PollEvent(&event);
  52. switch (event.type)
  53. {
  54. case SDL_QUIT:isRunning = false;
  55. break;
  56. case SDL_KEYDOWN:
  57. if (event.key.keysym.sym == SDLK_ESCAPE)
  58. {
  59. isRunning = false;
  60. }
  61. break;
  62. default:
  63. break;
  64. }
  65. }
  66. vec2_t orthographicPointProjection(vec3_t point)
  67. {
  68. vec2_t ret;
  69. ret.x = point.x * fovFactor;
  70. ret.y = point.y * fovFactor;
  71. return ret;
  72. }
  73. vec2_t perspectivePointProjection(vec3_t point)
  74. {
  75. vec2_t ret;
  76. ret.x = (point.x/point.z) * (fovFactor/2.);
  77. ret.y = (point.y/point.z) * (fovFactor/2.);
  78. return ret;
  79. }
  80. void update()
  81. {
  82. uint32_t i, j;
  83. uint32_t faceCount;
  84. uint32_t timeToWait = FRAME_TARGET_TIME - (SDL_GetTicks() - previousFrameTime);
  85. if (timeToWait <= FRAME_TARGET_TIME)
  86. {
  87. SDL_Delay(timeToWait);
  88. }
  89. previousFrameTime = SDL_GetTicks();
  90. mesh.rotation.x += 0.01;
  91. //mesh.rotation.y += 0.01;
  92. //mesh.rotation.z += 0.01;
  93. arrayEmpty(projectedTriangles);
  94. faceCount = arrayGetSize(mesh.faces);
  95. for(i = 0; i < faceCount; i++)
  96. {
  97. triangle_t currentTriangle;
  98. vec3_t vertices[3] =
  99. {
  100. mesh.vertices[mesh.faces[i].a - 1],
  101. mesh.vertices[mesh.faces[i].b - 1],
  102. mesh.vertices[mesh.faces[i].c - 1],
  103. };
  104. for(j = 0; j < 3; j++)
  105. {
  106. vec3_t transformed = vertices[j];
  107. transformed = vec3RotateX(transformed, mesh.rotation.x);
  108. transformed = vec3RotateY(transformed, mesh.rotation.y);
  109. transformed = vec3RotateZ(transformed, mesh.rotation.z);
  110. transformed.z -= cameraPosition.z;
  111. vec2_t projected = perspectivePointProjection(transformed);
  112. projected.x += (windowWidth / 2);
  113. projected.y += (windowHeight / 2);
  114. currentTriangle.points[j] = projected;
  115. }
  116. arrayAdd(projectedTriangles, currentTriangle);
  117. }
  118. }
  119. void render()
  120. {
  121. int i;
  122. SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
  123. SDL_RenderClear(renderer);
  124. int triangleCount = arrayGetSize(projectedTriangles);
  125. for(i = 0; i < triangleCount; i++)
  126. {
  127. drawTriangle(projectedTriangles[i].points[0].x, projectedTriangles[i].points[0].y,
  128. projectedTriangles[i].points[1].x, projectedTriangles[i].points[1].y,
  129. projectedTriangles[i].points[2].x, projectedTriangles[i].points[2].y,
  130. 0xFF00FFFF);
  131. }
  132. renderFrameBuffer();
  133. clearFrameBuffer(0xFF000000);
  134. SDL_RenderPresent(renderer);
  135. }
  136. int main(int argc, char *argv[])
  137. {
  138. int param_i;
  139. bool fullScreen = false;
  140. MAX_DEBUG_LEVEL = TLOG_DEBUG;
  141. log(TLOG_ALWAYS, NULL, "Booting 3D Engine (version %s)!", VERSION);
  142. for (param_i = 1 ; (param_i < argc) && (argv[param_i][0] == '-') ; param_i++)
  143. {
  144. switch (argv[param_i][1])
  145. {
  146. default: exit(-1); /* Option not recognized */
  147. case 'f': fullScreen = true; break;
  148. case 'w': windowWidth = atoi(argv[++param_i]);
  149. case 'h': windowHeight = atoi(argv[++param_i]); break;
  150. #ifdef DYNA_LOG_LEVEL
  151. case 'l': MAX_DEBUG_LEVEL = atoi(argv[++param_i]); break;
  152. #endif
  153. case '-': goto no_more_params; /* Could use break, but this is more clear */
  154. }
  155. }
  156. no_more_params:
  157. isRunning = initialiseWindow(fullScreen);
  158. setup();
  159. while (isRunning)
  160. {
  161. processInput();
  162. update();
  163. render();
  164. }
  165. arrayFree(projectedTriangles);
  166. meshFree();
  167. destroyWindow();
  168. return 0;
  169. }