#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:
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;
}