Advertisement
maxim_shlyahtin

RK-4_main

Mar 21st, 2024 (edited)
468
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.73 KB | None | 0 0
  1. #ifndef MAIN
  2. #define MAIN
  3. #ifdef _WIN32
  4. #include <Windows.h>
  5. #include <GL/GL.h>
  6. #include <GL/GLU.h>
  7. #endif
  8. #ifndef _WIN32
  9. #include <GL/gl.h>
  10. #include <GL/glu.h>
  11. #endif
  12.  
  13. #include <chrono>
  14.  
  15. #include "SDL.h"
  16. #include "SDL_opengl.h"
  17. #include "SDL_image.h"
  18. #include "ode.cpp"
  19. #include "thread_pool.cpp"
  20. #define _USE_MATH_DEFINES
  21.  
  22.  
  23. #include <SDL_ttf.h>
  24. #include <SDL_image.h>
  25. #pragma comment(lib,"SDL2.lib")
  26. #pragma comment(lib,"SDL2main.lib")
  27. static SDL_Window* window;
  28. static SDL_Renderer* renderer;
  29. #pragma comment(lib,"opengl32.lib")
  30. #pragma comment(lib,"glu32.lib")
  31. #include <shellapi.h>
  32. #pragma comment(lib, "shell32.lib")
  33.  
  34.  
  35. static int const screen_size[2] = { 1000, 800 };
  36.  
  37. using glf = GLfloat;
  38. using point3d = std::array<glf, N>;
  39. using method = RungeKutta; // для выбора численного метода достаточно изменить значение method
  40.  
  41. double cameraX = 0.0;
  42. double cameraY = 0.0;
  43. const double cameraZ = 20.0;
  44. const double R = 10.0;
  45. double t;
  46. const int number_of_points = 300000;
  47. double dt = 20.0 / 100.0;
  48.  
  49. // переменные для создания потоков
  50. const int number_of_cores = std::thread::hardware_concurrency();
  51. std::vector<method> attractors;
  52.  
  53. std::array<point3d, number_of_points> points;
  54. ThreadPool thread_pool(number_of_cores);
  55.  
  56. int b_val_index = 0;
  57. // красивые формы аттрактора получаются при данных коэффициентах
  58. const int len = 5;
  59. std::array<double, len> b_values = { 0.11, 0.15, 0.215, 0.265, 0.32899 };
  60.  
  61. double red = 1.0f;
  62. double blue = 1.0f;
  63. double green = 1.0f;
  64.  
  65. double step_red = 0.05;
  66. double step_blue = 0.025;
  67. double step_green = 0.016;
  68.  
  69. float x = 16.0;
  70. float y = 16.0;
  71.  
  72.  
  73. // для обеспечения работы нескольких потоков, цикл с вызовом численного метода был вынесен в отделтную ф-ию
  74. void process(method& attr, int start, int end, double dt) {
  75.     for (int i = start; i < end; ++i) {
  76.         attr.SetInit({ points[i].at(0), points[i].at(1), points[i].at(2) });
  77.         attr.NextStep(dt);
  78.         points[i] = { static_cast<glf>(attr.getX(0)), static_cast<glf>(attr.getX(1)), static_cast<glf>(attr.getX(2)) };
  79.     }
  80. }
  81.  
  82. // для каждого потока необходимо создать отдельный объект класса у которого будет вызываться численный метод, в противном случае одна и та же точка может просчитываться в разных потоках
  83. void inittializeAttractors() {
  84.     for (size_t i = 0; i < number_of_cores; ++i)
  85.         attractors.push_back(method());
  86. }
  87.  
  88.  
  89. Uint32 callback(Uint32 interval, void* name) {
  90.     //Задаем с период вращения камеры
  91.     std::chrono::time_point<std::chrono::high_resolution_clock> tp = std::chrono::high_resolution_clock::now();
  92.     std::chrono::duration<double, std::micro> dur = tp.time_since_epoch();
  93.     t = dur.count();
  94.  
  95.     cameraX = R * cos((2 * M_PI) / (60.0 * 1000.0) * (t / 1000.0));
  96.     cameraY = R * sin((2 * M_PI) / (60.0 * 1000.0) * (t / 1000.0));
  97.     // ф-ия enqueue класса ThreadPool отвечает за пробуждение потока при появлении нового запроса на просчет координат точки
  98.     for (size_t i = 0; i < number_of_cores; ++i) {
  99.         thread_pool.enqueue([i] {
  100.             process(std::ref(attractors[i]), i * number_of_points / number_of_cores,
  101.             (i + 1) * number_of_points / number_of_cores, dt);
  102.             });
  103.     }
  104.     return interval;
  105. }
  106.  
  107. Uint32 colorChange(Uint32 interval, void* name) {
  108.     red += step_red;
  109.     blue += step_blue;
  110.     green += step_green;
  111.     step_red = (red >= 1 || red <= 0) ? -step_red : step_red;
  112.     step_blue = (blue >= 1 || blue <= 0) ? -step_blue : step_blue;
  113.     step_green = (green >= 1 || green <= 0) ? -step_green : step_green;
  114.     return interval;
  115. }
  116.  
  117. static bool get_input(void) {
  118.     SDL_Event event;
  119.     while (SDL_PollEvent(&event)) {
  120.         switch (event.type) {
  121.         case SDL_QUIT: return false; //The little X in the window got pressed
  122.         case SDL_KEYDOWN:
  123.             if (event.key.keysym.sym == SDLK_ESCAPE) {
  124.                 return false;
  125.             }
  126.             if (event.key.keysym.sym == SDLK_w) {
  127.                 b_val_index = (b_val_index + 1) % len;
  128.                 for (size_t i = 0; i < number_of_cores; ++i)
  129.                     attractors[i].b = b_values[b_val_index];
  130.  
  131.             }
  132.             if (event.key.keysym.sym == SDLK_s) {
  133.                 b_val_index = (b_val_index - 1) % len >= 0 ? (b_val_index - 1) % len : len + (b_val_index - 1) % len;
  134.                 for (size_t i = 0; i < number_of_cores; ++i)
  135.                     attractors[i].b = b_values[b_val_index];
  136.  
  137.             }
  138.             std::cout << b_values[b_val_index] << '\n';
  139.             break;
  140.         }
  141.     }
  142.     return true;
  143. }
  144.  
  145.  
  146.  
  147.  
  148. static void draw(void) {
  149.     //Clear the screen's color and depth (default color is black, but can change with glClearColor(...))
  150.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  151.  
  152.     //Drawing to an area starting at the bottom left, screen_size[0] wide, and screen_size[1] high.
  153.     glViewport(0, 0, screen_size[0], screen_size[1]);
  154.     //OpenGL is a state machine.  Tell it that future commands changing the matrix are to change OpenGL's projection matrix
  155.     glMatrixMode(GL_PROJECTION);
  156.     //Reset the projection matrix
  157.     glLoadIdentity();
  158.     //Multiply a perspective projection matrix into OpenGL's projection matrix
  159.     gluPerspective(45.0, (double)(screen_size[0]) / (double)(screen_size[1]), 0.1, 100.0);
  160.  
  161.     //Tell OpenGL that future commands changing the matrix are to change the modelview matrix
  162.     glMatrixMode(GL_MODELVIEW);
  163.     //Reset the modelview matrix
  164.     glLoadIdentity();
  165.     //Multiply OpenGL's modelview matrix with a transform matrix that simulates a camera at (2,3,4) looking towards the location (0,0,0) with up defined to be (0,1,0)
  166.  
  167.     gluLookAt(cameraX, cameraY, cameraZ, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
  168.     //gluLookAt(-20.0f, -15.0f, 20.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
  169.  
  170.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  171.  
  172.     glColor3f(red, blue, green); // Set the color to white
  173.     //int ind = 6;
  174.     //glColor3f(colors[ind].at(0), colors[ind].at(1), colors[ind].at(2)); // Set the color to white
  175.     glBegin(GL_POINTS);
  176.  
  177.     for (size_t i = 0; i < number_of_points; i++) {
  178.         glVertex3f(points[i].at(0), points[i].at(1), points[i].at(2));
  179.     }
  180.  
  181.     glEnd();
  182.  
  183.     //OpenGL works best double-buffered.  SDL automatically sets that up for us.  This will draw what we have
  184.     //  just drawn to the screen so that we can see it.
  185.     SDL_GL_SwapWindow(window);
  186. }
  187.  
  188. int main(int argc, char* argv[]) {
  189.     //TTF_Init();
  190.     inittializeAttractors();
  191.     //считываем заготовленные точки из файла
  192.     std::ifstream in("prep.txt");
  193.     if (in.is_open()) {
  194.         glf x, y, z;
  195.         int check = 0;
  196.         while (in >> x >> y >> z && check < number_of_points) {
  197.             points[check] = { x, y, z };
  198.             check++;
  199.         }
  200.     }
  201.     in.close();
  202.     //Initialize everything, but don't catch fatal signals; give them to the OS.
  203.     SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_NOPARACHUTE);
  204.  
  205.  
  206.  
  207.     //Creates the window
  208.     window = SDL_CreateWindow("Thomas' cyclically symmetric attractor", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_size[0], screen_size[1], SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI);
  209.     //Create an OpenGL context.  In SDL 1, this was done automatically.
  210.     SDL_GLContext context = SDL_GL_CreateContext(window);
  211.  
  212.     //We now have an OpenGL context, and can call OpenGL functions.
  213.  
  214.  
  215.  
  216.     //Objects need to test each other to see which one is in front.  If you don't do this, you'll "see through" things!
  217.     glEnable(GL_DEPTH_TEST);
  218.  
  219.     SDL_TimerID timerID = SDL_AddTimer(20, callback, const_cast<char*>("SDL"));
  220.     SDL_TimerID timerID_color = SDL_AddTimer(1000, colorChange, const_cast<char*>("SDL"));
  221.     // Clean up
  222.    
  223.     //Main application loop
  224.     while (true) {
  225.         if (!get_input()) break;
  226.         draw();
  227.        
  228.     }
  229.     //Мы можем отрисовать наш текст, как и любую другую текстуру, так как
  230.     //он был отрендерен в текстуру
  231.    
  232.    
  233.     SDL_RemoveTimer(timerID);
  234.     SDL_RemoveTimer(timerID_color);
  235.  
  236.     //Clean up
  237.    
  238.    
  239.     SDL_GL_DeleteContext(context);
  240.     SDL_DestroyWindow(window);
  241.     //TTF_Quit();
  242.     SDL_Quit();
  243.  
  244.     //Return success; program exits
  245.     return 0;
  246. }
  247.  
  248. #endif // !MAIN
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement