Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef MAIN
- #define MAIN
- #ifdef _WIN32
- #include <Windows.h>
- #include <GL/GL.h>
- #include <GL/GLU.h>
- #endif
- #ifndef _WIN32
- #include <GL/gl.h>
- #include <GL/glu.h>
- #endif
- #include <chrono>
- #include "ode.cpp"
- #include "thread_pool.cpp"
- #define _USE_MATH_DEFINES
- //Choose whether to use SDL1 or SDL2
- #include <SDL.h>
- #include <SDL_opengl.h>
- #pragma comment(lib,"SDL2.lib")
- #pragma comment(lib,"SDL2main.lib")
- static SDL_Window* window;
- static SDL_Renderer* renderer;
- #pragma comment(lib,"opengl32.lib")
- #pragma comment(lib,"glu32.lib")
- static int const screen_size[2] = { 1000, 800 };
- using glf = GLfloat;
- using point3d = std::array<glf, N>;
- using method = DOPRI8;
- double cameraX = 0.0;
- double cameraY = 0.0;
- const double cameraZ = 20.0;
- const double R = 10.0;
- double t;
- const int number_of_points = 200000;
- double dt = 20.0 / 100.0;
- // переменные для создания потоков
- const int number_of_cores = std::thread::hardware_concurrency();
- std::vector<method> attractors;
- std::array<point3d, number_of_points> points;
- ThreadPool thread_pool(number_of_cores);
- int b_val_index = 0;
- // красивые формы аттрактора получаются при данных коэффициентах
- const int len = 5;
- std::array<double, len> b_values = { 0.11, 0.15, 0.215, 0.265, 0.32899 };
- double red = 1.0f;
- double blue = 1.0f;
- double green = 1.0f;
- double step_red = 0.05;
- double step_blue = 0.025;
- double step_green = 0.016;
- void process(method& attr, int start, int end, double dt) {
- for (int i = start; i < end; ++i) {
- attr.SetInit({ points[i].at(0), points[i].at(1), points[i].at(2) });
- attr.NextStep(dt);
- points[i] = { static_cast<glf>(attr.getX(0)), static_cast<glf>(attr.getX(1)), static_cast<glf>(attr.getX(2)) };
- }
- }
- void inittializeAttractors() {
- for (size_t i = 0; i < number_of_cores; ++i)
- attractors.push_back(method());
- }
- Uint32 callback(Uint32 interval, void* name) {
- //Задаем с период вращения камеры
- std::chrono::time_point<std::chrono::high_resolution_clock> tp = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double, std::micro> dur = tp.time_since_epoch();
- t = dur.count();
- cameraX = R * cos((2 * M_PI) / (60.0 * 1000.0) * (t / 1000.0));
- cameraY = R * sin((2 * M_PI) / (60.0 * 1000.0) * (t / 1000.0));
- for (size_t i = 0; i < number_of_cores; ++i) {
- thread_pool.enqueue([i] {
- process(std::ref(attractors[i]), i * number_of_points / number_of_cores,
- (i + 1) * number_of_points / number_of_cores, dt);
- });
- }
- return interval;
- }
- Uint32 colorChange(Uint32 interval, void* name) {
- red += step_red;
- blue += step_blue;
- green += step_green;
- step_red = (red >= 1 || red <= 0) ? -step_red : step_red;
- step_blue = (blue >= 1 || blue <= 0) ? -step_blue : step_blue;
- step_green = (green >= 1 || green <= 0) ? -step_green : step_green;
- return interval;
- }
- static bool get_input(void) {
- SDL_Event event;
- while (SDL_PollEvent(&event)) {
- switch (event.type) {
- case SDL_QUIT: return false; //The little X in the window got pressed
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_ESCAPE) {
- return false;
- }
- if (event.key.keysym.sym == SDLK_w) {
- b_val_index = (b_val_index + 1) % len;
- for (size_t i = 0; i < number_of_cores; ++i)
- attractors[i].b = b_values[b_val_index];
- }
- if (event.key.keysym.sym == SDLK_s) {
- b_val_index = (b_val_index - 1) % len >= 0 ? (b_val_index - 1) % len : len + (b_val_index - 1) % len;
- for (size_t i = 0; i < number_of_cores; ++i)
- attractors[i].b = b_values[b_val_index];
- }
- std::cout << b_values[b_val_index] << '\n';
- break;
- }
- }
- return true;
- }
- static void draw(void) {
- //Clear the screen's color and depth (default color is black, but can change with glClearColor(...))
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- //Drawing to an area starting at the bottom left, screen_size[0] wide, and screen_size[1] high.
- glViewport(0, 0, screen_size[0], screen_size[1]);
- //OpenGL is a state machine. Tell it that future commands changing the matrix are to change OpenGL's projection matrix
- glMatrixMode(GL_PROJECTION);
- //Reset the projection matrix
- glLoadIdentity();
- //Multiply a perspective projection matrix into OpenGL's projection matrix
- gluPerspective(45.0, (double)(screen_size[0]) / (double)(screen_size[1]), 0.1, 100.0);
- //Tell OpenGL that future commands changing the matrix are to change the modelview matrix
- glMatrixMode(GL_MODELVIEW);
- //Reset the modelview matrix
- glLoadIdentity();
- //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)
- gluLookAt(cameraX, cameraY, cameraZ, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
- //gluLookAt(-20.0f, -15.0f, 20.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glColor3f(red, blue, green); // Set the color to white
- //int ind = 6;
- //glColor3f(colors[ind].at(0), colors[ind].at(1), colors[ind].at(2)); // Set the color to white
- glBegin(GL_POINTS);
- for (size_t i = 0; i < number_of_points; i++) {
- glVertex3f(points[i].at(0), points[i].at(1), points[i].at(2));
- }
- glEnd();
- //OpenGL works best double-buffered. SDL automatically sets that up for us. This will draw what we have
- // just drawn to the screen so that we can see it.
- SDL_GL_SwapWindow(window);
- }
- int main(int argc, char* argv[]) {
- inittializeAttractors();
- //считываем заготовленные точки из файла
- std::ifstream in("prep.txt");
- if (in.is_open()) {
- glf x, y, z;
- int check = 0;
- while (in >> x >> y >> z && check < number_of_points) {
- points[check] = { x, y, z };
- check++;
- }
- }
- in.close();
- //Initialize everything, but don't catch fatal signals; give them to the OS.
- SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_NOPARACHUTE);
- //Creates the window
- window = SDL_CreateWindow("Thomas' cyclically symmetric attractor", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_size[0], screen_size[1], SDL_WINDOW_OPENGL);
- //Create an OpenGL context. In SDL 1, this was done automatically.
- SDL_GLContext context = SDL_GL_CreateContext(window);
- //We now have an OpenGL context, and can call OpenGL functions.
- //Objects need to test each other to see which one is in front. If you don't do this, you'll "see through" things!
- glEnable(GL_DEPTH_TEST);
- SDL_TimerID timerID = SDL_AddTimer(20, callback, const_cast<char*>("SDL"));
- SDL_TimerID timerID_color = SDL_AddTimer(1000, colorChange, const_cast<char*>("SDL"));
- //Main application loop
- while (true) {
- if (!get_input()) break;
- draw();
- }
- SDL_RemoveTimer(timerID);
- SDL_RemoveTimer(timerID_color);
- //Clean up
- SDL_GL_DeleteContext(context);
- SDL_DestroyWindow(window);
- SDL_Quit();
- //Return success; program exits
- return 0;
- }
- #endif // !MAIN
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement