Advertisement
Kaelygon

slope erosion

Nov 9th, 2023 (edited)
481
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.13 KB | None | 0 0
  1. #include <iostream>
  2. #include <SDL2/SDL.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5.  
  6. const int FRAME_TIME_TARGET = 16.667;
  7. const int SCREEN_WIDTH = 1024;
  8. const int SCREEN_HEIGHT = 1024;
  9.  
  10. const int SCREEN_OFFSET_X = 3400;
  11. const int SCREEN_OFFSET_Y = 600;
  12.  
  13. const int GRID_SIZE = 16;  // Size of each grid cell
  14. const int GRID_ROWS = SCREEN_HEIGHT / GRID_SIZE;
  15. const int GRID_COLS = SCREEN_WIDTH / GRID_SIZE;
  16.  
  17. float gridCell[GRID_ROWS][GRID_COLS];
  18.  
  19. float MAX_SLOPE=0.05;
  20. float PROPAGATE_AMPLITUDE=0.025;
  21. bool DISPLAY_NORMAL=false;
  22.  
  23. void renderWholeGrid(SDL_Renderer* renderer) {
  24.     // Clear the renderer
  25.     SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
  26.  
  27.     // Set a different color for each cell
  28.     for (int i = 0; i < GRID_ROWS; ++i) {
  29.         for (int j = 0; j < GRID_COLS; ++j) {
  30.             int red,green,blue;
  31.  
  32.             if (DISPLAY_NORMAL == 1) {
  33.                 float sumSlope_x = 0.0f;
  34.                 float sumSlope_y = 0.0f;
  35.  
  36.                 int maskRadius = 1; // Adjust the mask radius as needed
  37.  
  38.                 for (int s = -maskRadius; s <= maskRadius; ++s) {
  39.                     for (int t = -maskRadius; t <= maskRadius; ++t) {
  40.  
  41.                         // Calculate indices of the neighboring cell
  42.                         int in = i + s;
  43.                         int jn = j + t;
  44.  
  45.                         // Make sure array index isn't out of bounds
  46.                         in = std::min(GRID_ROWS - 1, std::max(0, in));
  47.                         jn = std::min(GRID_COLS - 1, std::max(0, jn));
  48.                        
  49.                         // Calculate slope with the neighboring cell
  50.                         float slope = gridCell[i][j] - gridCell[in][jn];
  51.                         sumSlope_x += slope * s;
  52.                         sumSlope_y += slope * t;
  53.                            
  54.                     }
  55.                 }
  56.  
  57.                 // Normalize the normal vector
  58.                 float length = sqrt(sumSlope_x * sumSlope_x + sumSlope_y * sumSlope_y);
  59.                 if (length > 0) {
  60.                     sumSlope_x /= length;
  61.                     sumSlope_y /= length;
  62.                 }
  63.  
  64.                 // Map the normalized components to color values (assuming positive values)
  65.                 red = static_cast<int>((sumSlope_x + 1.0f) * 0.5f * 255);
  66.                 green = static_cast<int>((sumSlope_y + 1.0f) * 0.5f * 255);
  67.                 blue = 127;  // Set blue to a constant value for simplicity
  68.             } else {
  69.                 red = gridCell[i][j] * 255;
  70.                 green = gridCell[i][j] * 255;
  71.                 blue = gridCell[i][j] * 255;
  72.             }
  73.            
  74.             SDL_SetRenderDrawColor(renderer, red, green, blue, 255);
  75.  
  76.             SDL_Rect cell = {j * GRID_SIZE, i * GRID_SIZE, GRID_SIZE, GRID_SIZE};
  77.             SDL_RenderFillRect(renderer, &cell);
  78.         }
  79.     }
  80.  
  81.     // Present the renderer
  82.     SDL_RenderPresent(renderer);
  83. }
  84.  
  85. //Spills to neighbouring cells if slope is too high
  86. void updateHeight(SDL_Renderer* renderer) {
  87.     for (int i = 0; i < GRID_ROWS; i++) {
  88.         for (int j = 0; j < GRID_COLS; j++) {
  89.            
  90.             //loop through masked neighbors
  91.             int maskRadius=2;
  92.             for(int s=-maskRadius;s<=maskRadius;s++){
  93.                 for(int t=-maskRadius;t<=maskRadius;t++){
  94.  
  95.                     //offset to neighbor
  96.                     int in = i+s;
  97.                     int jn = j+t;
  98.  
  99.                     // Make sure array index isn't out of bounds
  100.                     in = std::min(GRID_ROWS - 1, std::max(0, in));
  101.                     jn = std::min(GRID_COLS - 1, std::max(0, jn));
  102.  
  103.                     //spill to neighbor
  104.                     float slope = gridCell[i][j]-gridCell[in][jn];
  105.                     bool tooHigh = abs(slope)>MAX_SLOPE;
  106.                     float centerDistance = sqrt(s*s+t*t)/sqrt(2*maskRadius*maskRadius);
  107.                     gridCell[i][j]  -= tooHigh*PROPAGATE_AMPLITUDE*(slope/2)*(1-centerDistance);
  108.                     gridCell[in][jn]+= tooHigh*PROPAGATE_AMPLITUDE*(slope/2)*(1-centerDistance);
  109.                 }
  110.             }
  111.  
  112.         }
  113.     }
  114. }
  115.  
  116. // Variables for key press cooldown
  117. const Uint32 COOLDOWN_TIME = 50;
  118. Uint32 lastKeyPressTime = 0;
  119.  
  120. // Variables to track mouse drag
  121. bool isMouseDragging = false;
  122. int dragStartX, dragStartY;
  123.  
  124. bool quit = false;
  125. SDL_Event e;
  126.  
  127. void detectKeys(){
  128.     while (SDL_PollEvent(&e) != 0) {
  129.  
  130.         if (e.type == SDL_QUIT) {
  131.             quit = true;
  132.             break;
  133.  
  134.         }
  135.  
  136.         if (e.type == SDL_KEYDOWN) {
  137.             if (e.key.keysym.sym == SDLK_ESCAPE) {
  138.                 quit = true;
  139.                 continue;
  140.             }
  141.             if (e.key.keysym.sym == SDLK_n) {
  142.                 DISPLAY_NORMAL = !DISPLAY_NORMAL;  // Toggle DISPLAY_NORMAL
  143.                 std::cout << "DISPLAY_NORMAL: " << DISPLAY_NORMAL << std::endl;  // Print to console
  144.                 continue;
  145.             }
  146.             if (e.key.keysym.sym == SDLK_r) {
  147.                 for (int i = 0; i < GRID_ROWS; ++i) {
  148.                     for (int j = 0; j < GRID_COLS; ++j) {
  149.                         int squareSize = 9;
  150.                         gridCell[i][j] = ( i/squareSize + j/squareSize )%2; //checker board
  151.                         gridCell[i][j]*= rand()/(float)RAND_MAX; //noise on white squares
  152.                     }
  153.                 }
  154.                 continue;
  155.             }
  156.             continue;
  157.         }
  158.  
  159.         if (e.type == SDL_MOUSEBUTTONDOWN) {
  160.             if (e.button.button == SDL_BUTTON_LEFT || e.button.button == SDL_BUTTON_RIGHT) {
  161.                 isMouseDragging = true;
  162.                 SDL_GetMouseState(&dragStartX, &dragStartY);
  163.             }
  164.             continue;
  165.         }
  166.        
  167.         if (e.type == SDL_MOUSEBUTTONUP) {
  168.             if (e.button.button == SDL_BUTTON_LEFT || e.button.button == SDL_BUTTON_RIGHT) {
  169.                 isMouseDragging = false;
  170.             }
  171.             continue;
  172.         }
  173.    
  174.        
  175.         if (e.type == SDL_MOUSEMOTION) {
  176.             if (isMouseDragging) {
  177.                 int mouseX, mouseY;
  178.                 SDL_GetMouseState(&mouseX, &mouseY);
  179.  
  180.                 // Calculate the grid position based on the mouse coordinates
  181.                 int gridX = mouseX / GRID_SIZE;
  182.                 int gridY = mouseY / GRID_SIZE;
  183.  
  184.                 // Determine the value based on the mouse button
  185.                 float valueToSet = (e.button.button == SDL_BUTTON_LEFT) ? 1.0f : 0.0f;
  186.  
  187.                 // Update the grid cells based on the value
  188.                 int maskRadius = 2;
  189.                 for (int s = -maskRadius; s <= maskRadius; s++) {
  190.                     for (int t = -maskRadius; t <= maskRadius; t++) {
  191.                         gridCell[gridY + s][gridX + t] = valueToSet;
  192.                     }
  193.                 }
  194.             }
  195.             continue;
  196.         }
  197.            
  198.  
  199.     }
  200. }
  201.  
  202. int main() {
  203.     srand(time(NULL));
  204.  
  205.     //Generate initial height map
  206.     for (int i = 0; i < GRID_ROWS; ++i) {
  207.         for (int j = 0; j < GRID_COLS; ++j) {
  208.             int squareSize = 9;
  209.             gridCell[i][j] = ( i/squareSize + j/squareSize )%2; //checker board
  210.             gridCell[i][j]*= rand()/(float)RAND_MAX; //noise on white squares
  211.         }
  212.     }
  213.  
  214.     // Initialize SDL
  215.     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
  216.         std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
  217.         return 1;
  218.     }
  219.  
  220.     // Create a window
  221.     SDL_Window* window = SDL_CreateWindow("Grid Renderer", SCREEN_OFFSET_X, SCREEN_OFFSET_Y, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
  222.     if (window == nullptr) {
  223.         std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
  224.         return 2;
  225.     }
  226.  
  227.     // Create a renderer for the window
  228.     SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
  229.     if (renderer == nullptr) {
  230.         std::cerr << "Renderer could not be created! SDL_Error: " << SDL_GetError() << std::endl;
  231.         return 3;
  232.     }
  233.  
  234.     Uint32 frameStartTime = SDL_GetTicks();
  235.     frameStartTime+=FRAME_TIME_TARGET;
  236.     renderWholeGrid(renderer);
  237.  
  238.     //Render loop
  239.     while (!quit) {
  240.        
  241.         // Calculate the time to render a frame
  242.         Uint32 currentFrameTime = SDL_GetTicks() - frameStartTime;
  243.  
  244.         // Wait till FRAME_TIME_TARGET is reached
  245.         if (currentFrameTime < FRAME_TIME_TARGET) {
  246.             SDL_Delay(FRAME_TIME_TARGET - currentFrameTime);
  247.             detectKeys();
  248.         }
  249.  
  250.         updateHeight(renderer);
  251.        
  252.  
  253.         renderWholeGrid(renderer);
  254.         frameStartTime = SDL_GetTicks();
  255.     }
  256.  
  257.     // Clean up and exit
  258.     SDL_DestroyRenderer(renderer);
  259.     SDL_DestroyWindow(window);
  260.     SDL_Quit();
  261.  
  262.     return 0;
  263. }
  264.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement