Reputation: 1197
I am trying to incorporate openGL into my c++ code for the first time. As a start up, I made this very primitive code, which defines a class called polygon and should display a polygon with a method polygon.draw(). Right now, everything below resides in a single main.cpp file, though for easy reading I am separating into section here:
The problem is, the below code compiles and runs alright. Only when the window named "simple" is created, displays garbage (mostly collected from my computer background screen :(.
Firstly, the class polygon:
#include <GL/glut.h>
#include "utility.hpp"
#include <vector>
void init(void);
class nikPolygon{
public:
std::vector<nikPosition> m_vertices;
nikColor m_color;
double m_alpha;
// constructors
// without alpha (default is 1.0)
nikPolygon(std::vector<nikPosition> vList, nikColor c):
m_vertices(vList), m_color(c), m_alpha(1.0){
}
nikPolygon(std::vector<nikPosition> vList, nikColor c, double a):
m_vertices(vList), m_color(c), m_alpha(a){
}
// default constructor
nikPolygon(){
}
// member functions
// add vertex
void addVertex(nikPosition v) { m_vertices.push_back(v); }
// remove vertex
void removeVertex(nikPosition v);
// adjust vertex
void modifyVertex(unsigned int vIndex, nikPosition newPosition);
// fill color
void setColor(nikColor col) { m_color = col; }
// set alpha
void setAlpha(double a) { m_alpha = a; }
// display
void drawPolygon(void){
// color the objet
glColor4f(m_color.red,
m_color.green,
m_color.blue,
m_alpha);
// construct polygon
glBegin(GL_POLYGON);
for (std::vector<nikPosition>::iterator it = m_vertices.begin();
it != m_vertices.end(); it++)
glVertex2f(it->x, it->y);
glEnd();
// send to screen
glFlush();
}
void draw(void);
};
Then the c/c++ callback interface (trampoline/thunk):
// for c++/c callback
nikPolygon* currentPolygon;
extern "C"
void drawCallback(void){
currentPolygon->drawPolygon();
}
void nikPolygon::draw(){
currentPolygon = this;
glutDisplayFunc(drawCallback);
}
And then the rest of it:
// initialize openGL etc
void init(void){
// set clear color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
// set fill color to white
glColor3f(1.0, 1.0, 1.0);
// enable transperancy
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// setup standard orthogonal view with clipping
// box as cube of side 2 centered at origin
// this is the default view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
}
int main(int argc, char** argv){
nikPolygon poly;
poly.addVertex(nikPosition(-0.5, -0.5));
poly.addVertex(nikPosition(-0.5, 0.5));
poly.addVertex(nikPosition(0.5, 0.5));
poly.addVertex(nikPosition(0.5, -0.5));
poly.setColor(nikColor(0.3, 0.5, 0.1));
poly.setAlpha(0.4);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("simple");
init();
poly.draw();
glutMainLoop();
}
Upvotes: 0
Views: 427
Reputation: 162164
First and foremost, the original code is completely overengineered. This may be part of the original confusion. Also there's not really much you can do, to fix the code, without throwing out most of it. For example representing each polygon (triangle) with a own object instance is about as inefficient as it can get. You normally do not want to do this. The usual approach at representing a model is a Mesh, which consists of a list/array of vertex attributes, and a list of faces, which is in essence a list of 3-tuples defining the triangles, making up the surface of the mesh. In class form
class Mesh
{
std::vector<float> vert_position;
std::vector<float> vert_normal;
std::vector<float> vert_texUV;
std::vector<unsigned int> faces_indices;
public:
void draw();
};
Then to draw a mesh you use Vertex Arrays
void Mesh::draw()
{
// This is the API as used up to including OpenGL-2.1
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXCOORD_ARRAY);
// sizes of attributes depend on actual application
glVertexPointer(3, GL_FLOAT, 0, &vert_position[0]);
glNormalPointer(GL_FLOAT, 0, &vert_normal[0]);
glTexCoordPointer(2, GL_FLOAT, 0, &vert_texUV[0]);
glDrawElements(GL_TRIANGLES, faces_indices.size(), GL_UNSIGNED_INT, &faces_indices[0]);
}
You put references to these Mesh object instances into a list, or array, and iterate over that in the display function, calling the draw
method, after setting the appropriate transformation.
std::list<Mesh> list_meshes;
void display()
{
clear_framebuffer();
set_viewport_and_projection();
for(std::list<Mesh>::iterator mesh_iter = list_meshes.begin();
mesh_iter != list_meshes.end();
mesh_iter++) {
mesh_iter->draw()
}
swap_buffers();
}
Upvotes: 1
Reputation: 6368
At the beginning of your drawPolygon
function you need to do a glClear(GL_COLOR_BUFFER_BIT);
Upvotes: 1