Search code examples
c++visual-studioopenglglut

Hot Air Balloon not visible


#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

float squareX = 0.0f;
float squareY = -0.3f;
float squareZ = 0.0f;
static int flag = 1;

#define RAINSIZE 200
int winWidth = 800, winHeight = 600;
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) {
    // color of the rain
    glColor3f(0.1, 0.6, 0.8);
    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
    // set the projection window size in x an y.
    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);
        base_time = elapsedTime;
        frames = 0;
    }
    frames++;
}

// the background
void drawBackground() {
    // draw the green ground
    glBegin(GL_POLYGON);
    glColor3f(0.3, 0.7, 0.0);
    glVertex2f(800, 100);
    glVertex2f(800, 0);
    glVertex2f(0, 0);
    glVertex2f(0, 100);
    glVertex2f(800, 100);
    glEnd();
    // draw the blue sky
    glBegin(GL_POLYGON);
    glColor3f(0.7, 0.7, 0.9);
    glVertex2f(800, 100);
    glVertex2f(800, 800);
    glVertex2f(0, 800);
    glVertex2f(0, 100);
    glVertex2f(800, 100);
    glEnd();
    glFlush();
}

// the hot air balloon
void drawAirBalloon(void) {
    glTranslatef(squareX, squareY, squareZ);
    // draw the balloon
    float theta;
    int cutsegment = 45;
    int start = -90 + cutsegment / 2;
    int end = 270 - cutsegment / 2;
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POLYGON);
    glColor3f(1.0, 0.0, 0.0);
    for (int i = -45; i <= 225; i++) {
        theta = i * 3.142 / 180;
        glVertex2f(355 + 70 * cos(theta), 225 + 90 * sin(theta));
    }
    glEnd();
    // draw first rope on the left
    glBegin(GL_LINES);
    glColor3f(0.0, 0.0, 0.0);
    glVertex2f(320, 95);
    glVertex2f(295, 177);
    glEnd();
    // draw first rope on the right
    glBegin(GL_LINES);
    glColor3f(0.0, 0.0, 0.0);
    glVertex2f(415, 180);
    glVertex2f(390, 95);
    glEnd();
    // draw propane burner
    glBegin(GL_POLYGON);
    glColor3f(0.1, 0.1, 0.1);
    glVertex2f(335, 140);
    glVertex2f(335, 120);
    glVertex2f(375, 120);
    glVertex2f(375, 140);
    glVertex2f(335, 140);
    glEnd();
    // first vertical line on basket
    glBegin(GL_LINES);
    glColor3f(0.6, 0.25, 0.1);
    glVertex2f(330, 95);
    glVertex2f(330, 40);
    glEnd();
    // second vertical line on basket
    glBegin(GL_LINES);
    glColor3f(0.6, 0.25, 0.1);
    glVertex2f(340, 95);
    glVertex2f(340, 40);
    glEnd();
    // third vertical line on basket
    glBegin(GL_LINES);
    glColor3f(0.6, 0.25, 0.1);
    glVertex2f(350, 95);
    glVertex2f(350, 40);
    glEnd();
    // fourth vertical line on basket
    glBegin(GL_LINES);
    glColor3f(0.6, 0.25, 0.1);
    glVertex2f(360, 95);
    glVertex2f(360, 40);
    glEnd();
    // fifth vertical line on basket
    glBegin(GL_LINES);
    glColor3f(0.6, 0.25, 0.1);
    glVertex2f(370, 95);
    glVertex2f(370, 40);
    glEnd();
    // sixth vertical line on basket
    glBegin(GL_LINES);
    glColor3f(0.6, 0.25, 0.1);
    glVertex2f(380, 95);
    glVertex2f(380, 40);
    glEnd();
    // first horizontal line on basket
    glBegin(GL_LINES);
    glColor3f(0.6, 0.25, 0.1);
    glVertex2f(390, 80);
    glVertex2f(320, 80);
    glEnd();
    // second horizontal line on basket
    glBegin(GL_LINES);
    glColor3f(0.6, 0.25, 0.1);
    glVertex2f(390, 55);
    glVertex2f(320, 55);
    glEnd();
    // draw basket
    glBegin(GL_POLYGON);
    glColor3f(0.6, 0.45, 0.1);
    glVertex2f(320, 95);
    glVertex2f(320, 40);
    glVertex2f(390, 40);
    glVertex2f(390, 95);
    glVertex2f(320, 95);
    glEnd();
}

// move the hot air balloon up
void update(int value) {
    if (flag) {
        squareY += 1.0f;
        if (squareY > 350.0) {
            flag = 0;
        }
    }
    glutPostRedisplay();
    glutTimerFunc(25, update, 0);
}

// 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);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    // draw hot air balloon
    glPushMatrix();
    drawAirBalloon();
    glPopMatrix();
    // draw background  
    drawBackground();
    // draw rain
    drawRain();
    calcFPS();
    glFlush();
    counter++;
    //glutPostRedisplay();
    glutSwapBuffers();
}

// 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("Hot Air Balloon"); // 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
    glutTimerFunc(25, update, 0);
    // the last function in the program puts the program into infinite loop
    glutMainLoop();
    // this line exits the program
    return 0;
}

I have put all the work I have done into one cpp file. I am trying to create a hot air balloon to float up to the sky from the ground, and it is a bad weather day because it is pouring down rain. The problem is that I can't display my Hot Air Balloon.

This is a continuous work and I have posted about it on here before. If you don't understand my code, you can see my previous work:

OpenGL - Creating rain drops

OpenGL - Stop the background from moving


Solution

  • I compare the the previous questions you have disabled the depth test. I recommend to enable the dept test again and to draw the object with different depths (z coordinates).

    If you don't want to enable the depth test, you have to draw the background first, then the balloon and finally the rain:

    void display() {
        glClear(GL_COLOR_BUFFER_BIT);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        // draw background  
        drawBackground();
        // draw hot air balloon
        glPushMatrix();
        drawAirBalloon();
        glPopMatrix();
        // draw rain
        drawRain();
        calcFPS();
        counter++;
        glFlush();
        glutSwapBuffers();
        glutPostRedisplay();
    } 
    

    Further you have to remove the glClear from drawAirBalloon:

    void drawAirBalloon(void) {
    
        // .....
    
        // glClear(GL_COLOR_BUFFER_BIT);  <---- delete this
    

    And the glFlush from draw background

     void drawBackground() {
    
         // .....
    
         // glFlush();  <---- delete this, too
     }
    

    Note, arbitrary glClear and glFlush in the middle of the rendering will cause partial rendering and flickering (especially when using single buffering).

    Final code:

    #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
    
    float squareX = 0.0f;
    float squareY = -0.3f;
    float squareZ = 0.0f;
    static int flag = 1;
    
    #define RAINSIZE 200
    int winWidth = 800, winHeight = 600;
    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) {
        // color of the rain
        glColor3f(0.1, 0.6, 0.8);
        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
        // set the projection window size in x an y.
        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);
            base_time = elapsedTime;
            frames = 0;
        }
        frames++;
    }
    
    // the background
    void drawBackground() {
        // draw the green ground
        glBegin(GL_POLYGON);
        glColor3f(0.3, 0.7, 0.0);
        glVertex2f(800, 100);
        glVertex2f(800, 0);
        glVertex2f(0, 0);
        glVertex2f(0, 100);
        glVertex2f(800, 100);
        glEnd();
        // draw the blue sky
        glBegin(GL_POLYGON);
        glColor3f(0.7, 0.7, 0.9);
        glVertex2f(800, 100);
        glVertex2f(800, 800);
        glVertex2f(0, 800);
        glVertex2f(0, 100);
        glVertex2f(800, 100);
        glEnd();
        //glFlush();
    }
    
    // the hot air balloon
    void drawAirBalloon(void) {
        glTranslatef(squareX, squareY, squareZ);
        // draw the balloon
        float theta;
        int cutsegment = 45;
        int start = -90 + cutsegment / 2;
        int end = 270 - cutsegment / 2;
        //glClear(GL_COLOR_BUFFER_BIT);
        glBegin(GL_POLYGON);
        glColor3f(1.0, 0.0, 0.0);
        for (int i = -45; i <= 225; i++) {
            theta = i * 3.142 / 180;
            glVertex2f(355 + 70 * cos(theta), 225 + 90 * sin(theta));
        }
        glEnd();
        // draw first rope on the left
        glBegin(GL_LINES);
        glColor3f(0.0, 0.0, 0.0);
        glVertex2f(320, 95);
        glVertex2f(295, 177);
        glEnd();
        // draw first rope on the right
        glBegin(GL_LINES);
        glColor3f(0.0, 0.0, 0.0);
        glVertex2f(415, 180);
        glVertex2f(390, 95);
        glEnd();
        // draw propane burner
        glBegin(GL_POLYGON);
        glColor3f(0.1, 0.1, 0.1);
        glVertex2f(335, 140);
        glVertex2f(335, 120);
        glVertex2f(375, 120);
        glVertex2f(375, 140);
        glVertex2f(335, 140);
        glEnd();
        // first vertical line on basket
        glBegin(GL_LINES);
        glColor3f(0.6, 0.25, 0.1);
        glVertex2f(330, 95);
        glVertex2f(330, 40);
        glEnd();
        // second vertical line on basket
        glBegin(GL_LINES);
        glColor3f(0.6, 0.25, 0.1);
        glVertex2f(340, 95);
        glVertex2f(340, 40);
        glEnd();
        // third vertical line on basket
        glBegin(GL_LINES);
        glColor3f(0.6, 0.25, 0.1);
        glVertex2f(350, 95);
        glVertex2f(350, 40);
        glEnd();
        // fourth vertical line on basket
        glBegin(GL_LINES);
        glColor3f(0.6, 0.25, 0.1);
        glVertex2f(360, 95);
        glVertex2f(360, 40);
        glEnd();
        // fifth vertical line on basket
        glBegin(GL_LINES);
        glColor3f(0.6, 0.25, 0.1);
        glVertex2f(370, 95);
        glVertex2f(370, 40);
        glEnd();
        // sixth vertical line on basket
        glBegin(GL_LINES);
        glColor3f(0.6, 0.25, 0.1);
        glVertex2f(380, 95);
        glVertex2f(380, 40);
        glEnd();
        // first horizontal line on basket
        glBegin(GL_LINES);
        glColor3f(0.6, 0.25, 0.1);
        glVertex2f(390, 80);
        glVertex2f(320, 80);
        glEnd();
        // second horizontal line on basket
        glBegin(GL_LINES);
        glColor3f(0.6, 0.25, 0.1);
        glVertex2f(390, 55);
        glVertex2f(320, 55);
        glEnd();
        // draw basket
        glBegin(GL_POLYGON);
        glColor3f(0.6, 0.45, 0.1);
        glVertex2f(320, 95);
        glVertex2f(320, 40);
        glVertex2f(390, 40);
        glVertex2f(390, 95);
        glVertex2f(320, 95);
        glEnd();
    }
    
    // move the hot air balloon up
    void update(int value) {
        if (flag) {
            squareY += 1.0f;
            if (squareY > 350.0) {
                flag = 0;
            }
        }
        glutPostRedisplay();
        glutTimerFunc(25, update, 0);
    }
    
    // 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);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        // draw background  
        drawBackground();
        // draw hot air balloon
        glPushMatrix();
        drawAirBalloon();
        glPopMatrix();
        // draw rain
        drawRain();
        calcFPS();
        counter++;
        glFlush();
        glutSwapBuffers();
        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("Hot Air Balloon"); // 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
        glutTimerFunc(25, update, 0);
        // the last function in the program puts the program into infinite loop
        glutMainLoop();
        // this line exits the program
        return 0;
    }