main.c 4.5 KB

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