I've written a simple program in C++ to practice OpenGL. It takes a set of numbers through stdin and then plots it in Decartes coordinate system with x
for position in input, and y
for the value itself.
Example
Input:
1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400
Points to paint:
(0, 1) (1, 4) (2, 9) (3, 16) ... (19, 400)
Code
Mind the headers when compiling.
main.cpp
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>
#include <GLUT/glut.h>
typedef float real_t;
std::vector <real_t> DATA;
real_t
size_x = 800,
size_y = 800,
width(size_x * 4),
height(size_y * 4),
change = 0.05,
BOLD = 3,
bold_x(BOLD * width / size_x),
bold_y(BOLD * height / size_y),
shift_x = 0,
shift_y = 0;
void DrawText(real_t x, real_t y, const char *string) {
glRasterPos2f(x, y);
for (const char *c = string; *c != '\0'; ++c)
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *c);
}
inline void DrawPoint(real_t &x, real_t &y) {
real_t
point_x = 2 * x - shift_x,
point_y = 2 * y - shift_y;
if(
point_x >= width
||
point_x < 0
||
point_y >= height
||
point_y < 0
)
return;
glPushMatrix();
glTranslatef(point_x, point_y, 0);
glBegin(GL_QUADS);
glVertex3f( bold_x, bold_y, 0.0);
glVertex3f( bold_x, -bold_y, 0.0);
glVertex3f( -bold_x, -bold_y, 0.0);
glVertex3f( -bold_x, bold_y, 0.0);
glEnd();
glPopMatrix();
}
void Display() {
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glOrtho(0, width, 0, height, 1, -1);
glColor3f(0.8f,0.6f,0.0f);
DrawText(width - 230 * width/size_x, height - 30 * height/size_y, std::string(std::string() + "Width: " + std::to_string(width)).c_str());
DrawText(width - 230 * width/size_x, height - 60 * height/size_y, std::string(std::string() + "Height: " + std::to_string(height)).c_str());
glColor3f(0.0f,1.0f,0.0f);
for(real_t i = 0; i < DATA.size(); ++i) {
real_t
*x = &i,
*y = &DATA[i];
DrawPoint(*x, *y);
}
glColor3f(1.0f,1.0f,0.0f);
glPushMatrix();
glTranslatef(0, -shift_y, 0);
glBegin(GL_QUADS);
glVertex3f( 0, bold_y / 2 , 0.0);
glVertex3f( 0, -bold_y / 2 , 0.0);
glVertex3f( width, -bold_y / 2 , 0.0);
glVertex3f( width, bold_y / 2 , 0.0);
glEnd();
glPopMatrix();
glPushMatrix();
glTranslatef(-shift_x, 0, 0);
glBegin(GL_QUADS);
glVertex3f( -bold_x / 2, 0 , 0.0);
glVertex3f( bold_x / 2, 0 , 0.0);
glVertex3f( bold_x / 2, height , 0.0);
glVertex3f( -bold_x / 2, height , 0.0);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void Reshape(int new_size_x, int new_size_y) {
width *= real_t(new_size_x) / size_x;
height *= real_t(new_size_y) / size_y;
size_x = new_size_x;
size_y = new_size_y;
bold_x = BOLD * width/size_x;
bold_y = BOLD * height/size_y;
glViewport(0, 0, size_x, size_y);
glutPostRedisplay();
}
void Keyboard(unsigned char key, int x, int y) {
real_t
increase = 1 + change,
decrease = 1 / increase;
switch(key) {
case 27:
case 'q':
case 'Q':
exit(0);
break;
case 'm':
width *= decrease;
height *= decrease;
shift_x *= decrease;
shift_y *= decrease;
break;
case 'M':
width *= increase;
height *= increase;
shift_x *= increase;
shift_y *= increase;
break;
case 'b':
BOLD *= decrease;
break;
case 'B':
BOLD *= increase;
break;
case 't':
width *= decrease;
shift_x *= decrease;
break;
case 'T':
width *= increase;
shift_x *= increase;
break;
case 'y':
height *= decrease;
shift_y *= decrease;
break;
case 'Y':
height *= increase;
shift_y *= increase;
break;
case 'w':
shift_y += height * change;
break;
case 's':
shift_y -= height * change;
break;
case 'a':
shift_x -= width * change;
break;
case 'd':
shift_x += width * change;
break;
}
bold_x = BOLD * width/size_x;
bold_y = BOLD * height/size_y;
Display();
}
void Special(int key, int x, int y) {
switch(key) {
case 100 :
Keyboard('a', x, y);
break;
case 101 :
Keyboard('w', x, y);
break;
case 102 :
Keyboard('d', x, y);
break;
case 103 :
Keyboard('s', x, y);
break;
}
}
template <class anything_t>
void fill_data(std::vector <anything_t> &data) {
real_t value;
while(std::cin >> value)
data.push_back(value);
}
int main(int argc, char **argv) {
fill_data(DATA);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(size_x, size_y);
glutCreateWindow("gl_world");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Keyboard);
glutSpecialFunc(Special);
Display();
glutMainLoop();
return 0;
}
Could you, please, help me to improve it's readability, performance and style? What are the better practices?