0

I've created a program that draws a waving flag and I want to add a functionality that will create new wave on selected pixel, but I can't make it start where I want it to start an that even make the flag stop waving (prob. because of synced sin).

Here's my display func.

const int W = 800;
const int H = 600;
// simulates Frame Buffer
unsigned char pixels[H][W][3] = { 0 }; // 3 is for RGB
    void display()
    {
        glClear(GL_COLOR_BUFFER_BIT); // clean frame buffer
    
        createFlag();
        int i, j;
        double dist;
        offset += 0.25;
        for (i = 0; i < H; i++)
            for (j = 0; j < W; j++)
            {
                dist = sqrt(pow(i + H / 2.0, 2) + pow(j + W / 2.0, 2));
                pixels[i][j][0] += 135 + 55 * (1 + 1 * sin(dist / 25 - offset)) / 2; // red
                pixels[i][j][1] += 135 + 85 * (1 + 1 * sin(dist / 25 - offset)) / 2; // green
                pixels[i][j][2] += 135 + 105 * (1 + 1 * sin(dist / 25 - offset)) / 2; // blue
    
            }
        // draws the matrix pixels
        glDrawPixels(W, H, GL_RGB, GL_UNSIGNED_BYTE, pixels);
    
        glutSwapBuffers(); // show all
    }

And here is my mouse func.

void mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {
        double dist;
        offset += 0.1;
        for (y = 0; y < H; y++)
            for (x = 0; x < W; x++)
            {
                dist = sqrt(pow(H/2.0 -(H - y), 2) + pow(W/2.0 -x, 2)); //problem is prob. here
                pixels[y][x][0] += 135+ 55 * (1 + 1 * sin(dist / 50.0 - offset)) / 2; // red
                pixels[y][x][1] += 135+ 85 * (1 + 1 * sin(dist / 50.0 - offset)) / 2; // green
                pixels[y][x][2] += 135+105 * (1 + 1 * sin(dist / 50.0 - offset)) / 2; // blue
                if (offset < 0.3)
                    offset += 0.05;
            }
    }
}
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Not directly related to your actual problem, but: Please don't use `glDrawPixels`. It's been deprecated and removed from modern OpenGL. And for the legacy implementations of OpenGL that do have it, it usually is very slow, inefficient and in some cases outright buggy. If you have an image to draw, use a texture and draw it through a textured quad. – datenwolf Jul 20 '22 at 10:52
  • that's what I'm asked to use in my college. – יונתן אליהו Jul 20 '22 at 15:50
  • 1
    There's no nice way to sugarcoat this: If that's what your college's courses ask from you, then your college, or at least your course's professor and/or TA, suck. At any company that asks for OpenGL skills the interview will in some way or another test an applicant's knowledge about modern methods, and the limitations and caveats of the legacy APIs. To put it bluntly: Using `glDrawPixels` during a job interview at my company immediately sends you to the rejection pile. – datenwolf Jul 20 '22 at 19:01

1 Answers1

0

Here are some points that I see:

  • in your mouse function you don't use your arguments x and y which are the position of your mouse click, instead you create local variables x and y. If you want to start a wave from the pixel you clicked on, you have to center your dist to this point, so an idea of code could be (inspired by GLUT mouse button down):

    void mouse(int button, int state, int x, int y)
    {
        // save the left button state
        if (button == GLUT_LEFT_BUTTON)
        {
            leftMouseButtonDown = (state == GLUT_DOWN);
        }
    
        // save the mouse position
        mouseXPos = x;
        mouseYPos = y;
    }
    
    void display()
    {
        glClear(GL_COLOR_BUFFER_BIT); // clean frame buffer
    
        createFlag();
        double dist;
        offset += 0.25;
        for (i = 0; i < H; i++)
            for (j = 0; j < W; j++)
            {
                dist = sqrt(pow(i + H / 2.0, 2) + pow(j + W / 2.0, 2));
                pixels[i][j][0] += 135 + 55 * (1 + 1 * sin(dist / 25 - offset)) / 2; // red
                pixels[i][j][1] += 135 + 85 * (1 + 1 * sin(dist / 25 - offset)) / 2; // green
                pixels[i][j][2] += 135 + 105 * (1 + 1 * sin(dist / 25 - offset)) / 2; // blue
            }
    
        if (leftMouseButtonDown)   // the way you can get leftMouseButtonDown depends on your 
                                   // configuration of your different files 
                                   // (main.cpp, scene.cpp, ...)
            new_wave() ; //see below
    
        // draws the matrix pixels
        glDrawPixels(W, H, GL_RGB, GL_UNSIGNED_BYTE, pixels);
    
        glutSwapBuffers(); // show all
    }
    
    void new_wave()
    {
        x = mouseXPos ;   // same remark as leftMouseButtonDown 
        y = mouseYPos ;
        offset = 0.1;
        for (i = 0; i < H; i++)     // i and not y
            for (j = 0; j < W; j++)
            {
                dist = sqrt(pow(i - y, 2) + pow(j - x, 2));    // change here
                pixels[i][j][0] += 135+ 55 * (1 + 1 * sin(dist / 50.0 - offset)) / 2; // red
                pixels[i][j][1] += 135+ 85 * (1 + 1 * sin(dist / 50.0 - offset)) / 2; // green
                pixels[i][j][2] += 135+105 * (1 + 1 * sin(dist / 50.0 - offset)) / 2; // blue
                if (offset < 0.3)
                    offset += 0.05;   
    // I don't really get what you do here with the offset, but another parameter to
    // play with could be the amplitude of this wave that starts from the point 
    // you clicked, like when a drop falls on water
            }
    }
    
  • if you want a real-time waving flag you have to take time as a parameter of your pixels color value

  • I haven't tested it but I'm not sure on how openGL reacts to RGB coloring with values over 255, which happens in your case, maybe keep that in mind if you still have bugs

  • dist = sqrt(pow(i + H / 2.0, 2) + pow(j + W / 2.0, 2)); this is centered in (-W/2.0, -H/2.0), is that what you want? (maybe yes just want to make sure, if you want to simulate some wind you could set wind's origin where you want, which is what you do here)

  • int i, j; in your display isn't useful (just to clear some code)

So these are some remarks I would have made myself, this piece of code probably won't be your final one. Let me know if I misunderstood what you are aiming to do, or if something I wrote is unclear.

genpfault
  • 51,148
  • 11
  • 85
  • 139
JujuPat
  • 36
  • 4
  • if you saved the x , y from the click in different variables and than just used the in the other function , why not just use the directly? the color value is mod255 so you can go above and under how ever you want. yes I wanted the first wave to be centered over there. how would you do the display function without the i , j ? – יונתן אליהו Jul 20 '22 at 16:00
  • The mouse function is there to take into account new mouse click, and I would put it in the `main.cpp` file. Whereas your display function is responsible for what you will display on your screen, so for the modifications you apply on your pixels, and I would put it in a `scene.cpp` file. You could do differently. The main issue with `x` and `y` is that you don't use them as positions but created new local variables and didn't take into account the position of your mouse click. – JujuPat Jul 20 '22 at 16:08
  • And for the color value the mod255 means that you want to stay between 0 and 255 for RGB, since you will have color discontinuity if you go beyond or under. Then you should change the amplitude of your color variations, both in the display and new_wave functions so that your color parameters always stay between 0 and 255. – JujuPat Jul 20 '22 at 16:12