Muddy
Muddy

Reputation: 382

Creating rain drops

#include <stdio.h>  // this library is for standard input and output
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "glut.h"// this library is for glut the OpenGL Utility Toolkit

#define RAINSIZE 50
int winWidth = 1000, winHeight = 1000;
int counter = 0;
time_t t;
float rotationAngle = 0;

struct drop {
    float x = 400;
    float y = 400;
    float inc = 0.01;
    float radius = 5;
    float scale = 1.0;
    float rotationAngle = 0;
    float rotationInc = 1;
};

drop rain[RAINSIZE];

void initRain() {
    srand((unsigned)time(&t));
    for (int i = 0; i < RAINSIZE; i++) {
        rain[i].x = rand() % winWidth;
        rain[i].y = rand() % winHeight;
        rain[i].inc = 1.5 + (float)(rand() % 100) / 1000.0;
        rain[i].radius = (float)(rand() % 8);
        rain[i].scale = (float)(rand() % 20000) / 1000.0;
        rain[i].rotationAngle = (float)(rand() % 3000) / 1000.0;
        rain[i].rotationInc = (float)(rand() % 100) / 1000.0;
        if ((rand() % 100) > 50) {
            rain[i].rotationInc = -rain[i].rotationInc;
        }
    }
}

void drawParticleShape(int i) {
    glBegin(GL_POINTS);
    glVertex2d(rain[i].x, rain[i].y);
    glEnd();
    glBegin(GL_LINES);
    glVertex2d(rain[i].x, rain[i].y);
    glVertex2d(rain[i].x, rain[i].y + rain[i].radius * 2);
    glEnd();
}

void drawDrop(int i) {
    glColor3f(0.0, 0.0, 1.0);
    glLineWidth(2);
    drawParticleShape(i);
    rain[i].y -= rain[i].inc;
    if (rain[i].y < 0) {
        rain[i].y = winHeight;
    }
}

void drawRain() {
    for (int i = 0; i < RAINSIZE; i++) {
        drawDrop(i);
    }
}

// this is the initialisation function, called once only
void init() {
    glClearColor(0.0, 0.0, 0.0, 0.0); // set what colour you want the background to be
    glMatrixMode(GL_PROJECTION); // set the matrix mode, we will look at this later
    gluOrtho2D(0.0, winWidth, 0.0, winHeight);
}

float elapsedTime = 0, base_time = 0, fps = 0, frames;

void calcFPS() {
    elapsedTime = glutGet(GLUT_ELAPSED_TIME);
    if ((elapsedTime - base_time) > 1000.0) {
        fps = frames * 1000.0 / (elapsedTime - base_time);
        printf("fps: %f", fps);
        base_time = elapsedTime;
        frames = 0;
    }
    frames++;
}

// This is the display function it is called when ever you want to draw something
// all drawing should be called form here
void display() {
   glClear(GL_COLOR_BUFFER_BIT);
   drawRain();
   calcFPS();
   glFlush();
   counter++;
   glutPostRedisplay();
}

// This is the idle function it is called whenever the program is idle
// This has the effect of repeatedly calling the display function
void idle() {
    //display();
}

// As with many programming languages the main() function
// is the entry point for execution of the program
int main(int argc, char** argv) {
    srand(1);
    initRain();
    glutInit(&argc, argv);  //perform the GLUT initialization
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); // more initialisation
    glutInitWindowSize(winWidth, winHeight); // set window position
    glutInitWindowPosition(0, 0); // set window size
    glutCreateWindow("Hello"); // create a display with a given caption for the title bar
    glEnable(GL_BLEND); //Enable blending.
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Set blending function.
    init(); // call init function defined above
    glutIdleFunc(idle); //  define what function to call when the program is idle
    glutDisplayFunc(display); // define what function to call to draw
    // the last function in the program puts the program into infinite loop
    glutMainLoop();
    // this line exits the program
    return 0;
}

I am trying to create rain drops falling and spreading from the top of the screen, but the rain does not drop properly. It's supposed to drop like real rain. I have tried to figure out what the problem was, but I kept making it worse. I would appreciate if you could help me and tell me what the problem is.

How it works:

enter image description here

How I want it to work (edit of image above):

enter image description here

Upvotes: 2

Views: 3742

Answers (1)

Rabbid76
Rabbid76

Reputation: 210878

You have to clear the color plane of the default framebuffer (the "window") at the begin of each frame by glClear. Note, the content of the framebuffer won't change as long as you do not explicitly change it. Everything what you have drawn is kept until it s cleared or overwritten.

Further don't redraw the window in idle, but mark the current window as needing to be redisplayed in display by glutPostRedisplay. The GLUT event processing loop will do the display call for you:

void display() {
    glClear( GL_COLOR_BUFFER_BIT );
    drawRain();
    calcFPS();
    glFlush();
    counter++;
    glutPostRedisplay();
}

void idle() {
    //display();
}

Upvotes: 2

Related Questions