I'm encountering a strange OpenGL Bug. OpenGL is pretty new to me, but we're required to use it in my AI class (because the teacher is really a Graphics professor).
Either way, this is happening: http://img818.imageshack.us/img818/422/reversiothello.png
It happens to only the topmost, leftmost polygon. In other words, it finds the furthest polygon left, and then the furthest up and it does that to it. (There is not currently anything erasing polygons from the board).
My display function is this:
void display_func(void)
{
glClearColor(0.0, 0.45, 0.0, 1.0); // Background Color (Forest Green :3)
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
draw_board();
glFlush();
glutSwapBuffers();
};
My draw_board function is this:
void draw_board()
{
int size = 8;
int stepX = WINDOW_XS / size;
int stepY = WINDOW_YS / size;
glColor3f(0.0,0.0,0.0); // line color black
glBegin(GL_LINES);
// Draw Columns
for(int i = 0;i <= WINDOW_XS;i += stepX)
{
glVertex2i(i,0);
glVertex2i(i, WINDOW_YS);
}
// Draw Rows
for(int j = 0;j <= WINDOW_YS;j += stepY)
{
glVertex2i(0, j);
glVertex2i(WINDOW_XS, j);
}
// Draw Circles
for(int i = 0;i < 8;++i)
{
for(int j = 0;j < 8;++j)
{
if(engine->getOnBoard(i,j) == Reversi::PIECE_NONE) continue;
if(engine->getOnBoard(i,j) == Reversi::PIECE_WHITE)
glColor3f(1.0,1.0,1.0);
if(engine->getOnBoard(i,j) == Reversi::PIECE_BLACK)
glColor3f(0.0,0.0,0.0);
int drawX = ((i+1)*64)-32;
int drawY = 512-((j+1)*64)+32;
gl_drawCircle(drawX,drawY,30);
}
}
glEnd();
};
My mouse function is this:
void mouse_func(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && x < WINDOW_XS)
{
// row and column index
x = (int)( x / (WINDOW_XS/8) );
y = (int)( y / (WINDOW_YS/8) );
std::cout << "Attempting to make a move at " << x << "," << y << std::endl;
if(engine->makeMove(x,y))
{
glutPostRedisplay();
}
}
};
and my gl_drawCircle function is this:
void gl_drawCircle(float x, float y, float r)
{
// http://stackoverflow.com/questions/5094992/c-drawing-a-2d-circle-in-opengl/5095188#5095188
glBegin( GL_POLYGON );
float t;
int n;
for(t = 0,n = 0; n <= 90; ++n, t = float(n)/90.f ) // increment by a fraction of the maximum
{
glVertex2f( x + sin( t * 2 * PI ) * r, y + cos( t * 2 * PI ) * r );
}
glEnd();
}
Can anyone please help me?
The only bug worth giving an answer that I can find is that your draw_board function doesn't use properly the glBegin and glEnd statements. You have to use a glEnd statement before calling gl_drawCircle, otherwise you'll get a nasty behavior.
Edit: you first circle is drawn using lines because the glBegin is ignored (since you are in a glBegin context). All other circles are done ok because you do a glEnd before calling glBegin again. The first drawn circle is the leftmost, topmost circle.
You need a call to glEnd after drawing the rows.
When you do not call glEnd, OpenGL ignores your call glBegin( GL_POLYGON ); and assumes you still want to draw lines.
So just adding
glEnd ();
after drawing the rows should solve it.
Related
Example Screenshot
I am new to programming in c++ and I am stuck on this homework problem. I need to draw a grid of trees. The dimensions of this grid must be the parameters of the function. So, if you call forest(2,2) it will make 4 trees, forest (3,5) will render 15. Additionally, the trees need to alternate between pine and tree. I just can't seem to get my forest to match the example screenshot and would love any help to steer me in the right direction.
#include "cgt215.h"
#include "demo.h"
#include <time.h>
using namespace std;
using namespace cgt215;
// Place global variables here
int mode = 1;
int framesDrawn = 0;
float secondsPassed = 0;
static int counter;
int x = 0;
int y = 0;
int parameterX = 5;
int parameterY = 4;
// Declare new functions here
void drawPine(double x, double z);
void drawTree(double x, double z);
void trunk(void);
void modeSwitch(char keyToPress, int modeToSwitchTo);
void forest(int, int);
void renderFrame(float lastFrameDuration) {
// Place interactive/animated drawing code here
enable3d();
//Frames Drawn
framesDrawn++;
secondsPassed += lastFrameDuration;
modeSwitch('w', 2);
if (mode == 2) {
forest(parameterX,parameterY);
}
void drawPine(double x, double z) {
glPushMatrix();
glTranslated(x, 0.0, z);
trunk();
glPushMatrix();
glTranslated(0.0, 15.0, 0.0);
glScaled(1.0, 0.75, 1.0);
drawCone();
glPopMatrix();
glPopMatrix();
return;
}
void drawTree(double x, double z) {
glPushMatrix();
glTranslated(x, 0.0, z);
trunk();
glPushMatrix();
glTranslated(0.0, 40.0, 0.0);
drawSphere(25.0);
glPopMatrix();
glPopMatrix();
return;
}
void trunk(void) {
glPushMatrix();
glScaled(1.0, 4.0, 1.0);
glRotated(90.0, 1.0, 0.0, 0.0);
drawTorus(5.0, 6.0);
glPopMatrix();
}
void modeSwitch(char keyToPress, int modeToSwitchTo) {
if (keyPressed(keyToPress)) {
mode = modeToSwitchTo;
}
}
void forest(int, int) {
for (x = 0; x < parameterX; x++)
for (y = 0; y < parameterY; y++)
if (x % 2 == 0) {
drawTree(-(9 * 100 / 2) + x * 100, -(9 * 100 / 2) + y * 100);
else {
drawPine(-(9 * 100 / 2) + x * 100, -(9 * 100 / 2) + y * 100);
}
}
}
Let's take a look at 2D arrangement in ASCII of the trees and pines you want to see.
T P T P T
P T P T P
T P T P T
The places where T are found, (x+y) is even.
The places where P are found, (x+y) is odd.
The code must reflect that.
void forest(int parameterX, int parameterY) {
for (x = 0; x < parameterX; x++) {
for (y = 0; y < parameterY; y++) {
// Check whether x+y is even. not just x
if ( (x+y) % 2 == 0) {
drawTree(-(9 * 100 / 2) + x * 100, -(9 * 100 / 2) + y * 100);
}
else {
drawPine( ... );
}
}
}
}
I am working on a program that is supposed to allow the user to create a polygon, and then specify random points for the program to check if they are inside the polygon or not.
GLint vert[100][2];
int width = 400, height = 600, n = 0, type = GL_LINE_STRIP, v;
bool rubberbanding = false;
void display(){
glClear(GL_COLOR_BUFFER_BIT);
if(n == 1 && (type == GL_LINE_STRIP)){
glBegin(GL_POINTS);
glVertex2iv(vert[0]);
glEnd();
}
glBegin(type);
for(int i = 0; i < n; i++){
glVertex2iv(vert[i]);
}
glEnd();
glutSwapBuffers();
}
I am having trouble with this next part here. The user creates lines with GL_LINE_STRIP, and then they are supposed to click 'c' to close the polygon. However after they close the polygon I want them to be able specify random points. But when I switch the type to GL_POINTS it removes all the lines, and I am left with points at the vertices.
void keyboard(unsigned char key, int x, int y){
switch(key){
case 'r': n = 0; type = GL_LINE_STRIP; break;
case 'c': type = GL_LINE_LOOP; break;
//case 'v': type = GL_POINTS; break;
}
// type = GL_POINTS;
glutPostRedisplay();
}
How can I fix this so that after the user closes the polygon, they can create points without the polygon disappearing?
Edit: This is the code for the button click:
void mouse(int button, int state, int x, int y){
switch(button){
case GLUT_LEFT_BUTTON:
if(state == GLUT_DOWN){
v = n++;
vert[v][0] = x;
vert[v][1] = height - 1 - y;
rubberbanding = true;
glutPostRedisplay();
}
else{
rubberbanding = false;
}
break;
}
}
I recommend to do the following:
Create a display function, which can draw lines and points. The lines are stored in the array of vertices starting with index 0 and ending at index m-1.
The points are stored in the array of vertices, too. The start at index m and end at index n-1.
The lines are drawn using the primitive type GL_LINE_STRIP. If the line is closed then the primitive type GL_LINE_LOOP is used.
The points are drawn using GL_POINTS.
GLint vert[100][2];
int n = 0, m = 0;
bool closed = false;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(closed ? GL_LINE_LOOP : GL_LINE_STRIP);
for(int i = 0; i < m; i++)
glVertex2iv(vert[i]);
glEnd();
glBegin(GL_POINTS);
for(int i = m; i < n; i++)
glVertex2iv(vert[i]);
glEnd();
glutSwapBuffers();
glutPostRedisplay();
}
In the keybord function, the states are changed:
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'r': n = 0; m = 0; closed = false; break;
case 'c': closed = true; break;
}
}
The mouse function adds a vertex coordinate to the container and increments n and/or m with respect to the state closed.
void mouse(int button, int state, int x, int y)
{
switch(button)
{
case GLUT_LEFT_BUTTON:
if( state == GLUT_DOWN )
{
if ( n < 100 )
{
vert[n][0] = x;
vert[n][1] = height - 1 - y;
n ++;
if ( !closed )
m = n;
}
}
break;
}
}
When a glVertex is called then the color which was set by glColor. OpenGL is a state a engine. If a state is changed it is kept until it is changed again, even beyond frames.
If you want to draw the lines in one color, but the point in another color, than you have to set the colors before the loops which draw the lines and points:
glColor3f(1,1,1);
glBegin(closed ? GL_LINE_LOOP : GL_LINE_STRIP);
for(int i = 0; i < m; i++)
glVertex2iv(vert[i]);
glEnd();
glColor3f(1,0,0);
glBegin(GL_POINTS);
for(int i = m; i < n; i++)
glVertex2iv(vert[i]);
glEnd();
Even rubber banding can be implemented with ease. Implement the glutPassiveMotionFunc callback and store the current mouse position:
int mx = 0, my = 0;
void mousemove(int x, int y)
{
mx = x;
my = height - 1 - y;
}
glutPassiveMotionFunc(mousemove);
Add a final vertex coordinate to the current mouse position when you draw the line, dependent on the state of drawing:
glBegin(closed ? GL_LINE_LOOP : GL_LINE_STRIP);
for(int i = 0; i < m; i++)
glVertex2iv(vert[i]);
if (n>0 && !closed)
glVertex2i(mx, my);
glEnd();
I have an OpenGL project with a screen size of 1000x800, and I want to be able to draw a triangle when I click the left mouse button.
I already have a mouse function set up that works fine:
struct point
{
int x;
int y;
};
std::vector <point> dots;
point OneDot;
void processMouse(int button, int state, int x, int y)
{
if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
{
int yy;
yy = glutGet(GLUT_WINDOW_HEIGHT);
y = yy - y; /* In Glut, Y coordinate increases from top to bottom */
OneDot.x = x;
OneDot.y = y;
dots.push_back(OneDot);
}
}
void display(){
for (int i = 0; i < dots.size();i++){
glPointSize(10)
glBegin(GL_POINTS);
glVertex2i(dots[i].x, dots[i].y);
}
}
So in my display() function, how can I add some code that prints a triangle at the mouse location when I click?
UPDATE:
Here's my current drawCircle function:
void drawCircle(float cx, float cy, float r, float num_segments) {
// Sets variables for X, Y, Radius and Segments
glColor3f(1.0, 0.0, 0.0); // Red
glBegin(GL_POLYGON);
// To set 0 as origin point
for (int i = 0; i < num_segments; i++) {
float theta = 2.0f * 3.14 * i / num_segments;
float x = r * cosf(theta);
float y = r * sinf(theta);
glVertex2f(x + cx, y + cy);
}
glEnd();
}
Is there a way I could draw this function somehow at the mouse location when I left click?
In your code you're almost there. Two things you have to add: In your mouse event handler you have to set the flag that tells your window manager (in your case GLUT) to refresh the display. That function would be glutPostRedisplay.
Then in your display function you have to push 3 vertices instead of 1 and change the primitive type to GL_TRIANGLES. Like this
void processMouse(int button, int state, int x, int y)
{
if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
{
int yy;
yy = glutGet(GLUT_WINDOW_HEIGHT);
y = yy - y; /* In Glut, Y coordinate increases from top to bottom */
OneDot.x = x;
OneDot.y = y;
dots.push_back(OneDot);
glutPostRedisplay(); ///<<<<<<<<<<
}
}
and
void display(){
glBegin(GL_TRIANGLES);
for (int i = 0; i < dots.size();i++){
glPointSize(10)
glVertex2i(dots[i].x-3, dots[i].y-5);
glVertex2i(dots[i].x+3, dots[i].y-5);
glVertex2i(dots[i].x, dots[i].y+5);
}
glEnd();
}
or, if you want to define the corners of the triangle(s) by the clicks just
void display(){
glBegin(GL_TRIANGLES);
for (int i = 0; i < dots.size();i++){
glPointSize(10);
glVertex2i(dots[i].x, dots[i].y);
}
glEnd();
}
You don't really have to check if 3 <= dots.size() because OpenGL will simply draw nothing then.
I haven't got experience in glbegin notation, but seems you miss glend
It should be something like this:
void display(){
glPointSize(10)
glBegin(GL_POINTS);
for (int i = 0; i < dots.size();i++){
glVertex2i(dots[i].x, dots[i].y);
}
glEnd()
}
I'm trying to create a nested while-loop structure, which will create a 3 * 3 grid of cubes. It only appears to run the internal loop one time, creating an "L" shape out of cubes. So, my guess is that the internal while loop is not resetting after it runs the first time, but I do appear to be explicitly resetting it.
I'd rather not post the entire code, as some is code given by my TA, and it feels wrong to post that without their permission.
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
UpdateTransform();
int x = 0;
int y = 0;
float Xres = 0;
float Yres = 0;
while(x < 3)
{
glPushMatrix();
glTranslatef(Xres,0,0);
drawOneCube();
glPopMatrix();
Xres += 0.3;
while(y < 3)
{
glPushMatrix();
glTranslatef(0,Yres,0);
drawOneCube();
glPopMatrix();
Yres += 0.3;
y++;
}
y = 0;
Yres = 0;
x++;
}
glutSwapBuffers();//this prevents that problem where the window copies the contents behind the window, possibly with glClear at the top of this function
}
It looks like your logic is incorrect. You should only be calling the cube drawing function at one point, something like this:
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
UpdateTransform();
int x = 0;
int y = 0;
float Xres = 0;
float Yres = 0;
for (x = 0; x < 3; ++x)
{
Yres = 0;
for (y = 0; y < 3; ++y)
{
glPushMatrix();
glTranslatef(Xres,Yres,0);
drawOneCube();
glPopMatrix();
Yres += 0.3;
}
Xres += 0.3;
}
glutSwapBuffers();
}
I'm trying to rotate a polygon in place, but it keeps revolving instead.
To rotate, I calculate the center by finding the average location of each vertex. I call the rotation functions and then call a translation using the center to move it to the middle of the screen. It does end up centered, but it still rotates as if it's not. Any ideas as to what I could be doing wrong?
Here's my code:
void Polygon::DrawPolygon()
{
glPushMatrix();
glLoadMatrixf(matrix);
glTranslatef(displace[0], displace[1], displace[2]);
glRotatef(rotation[0], 1, 0, 0);
glRotatef(rotation[1], 0, 1, 0);
glRotatef(rotation[2], 0, 0, 1);
glTranslatef(-displace[0], -displace[1], displace[2]);
displace[0] = 0; displace[1] = 0; displace[2] = 0;
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
DrawMaterial();
DrawFaces();
ConnectFaces();
glPopMatrix();
}
Here's how I calculate the center:
void Polygon::FindCenter()
{
float x = 0;
float y = 0;
float z = 0;
for(int j = 0; j < 2; j++)
{
for(int i = 0; i < vertexCount; i++)
{
x += vertices[i][0];
y += vertices[i][1];
z += vertices[i][2] + extrusionDistance * j;
}
}
x = x / (vertexCount * 2);
y = y / (vertexCount * 2);
z = z / (vertexCount * 2);
displace[0] = x;
displace[1] = y;
displace[2] = z;
}
Because of the way my extrusion works I don't need to add the x and y for the vertices of both faces, but I did anyway to keep it consistent.
Here is how I draw the shape:
void Polygon::DrawFaces()
{
for(int j = 0; j < 2; j++)
{
glBegin(GL_POLYGON);
for(int i = 0; i < vertexCount; i++)
{
glVertex3f(vertices[i][0], vertices[i][1], j*extrusionDistance);
}
glEnd();
}
}
void Polygon::ConnectFaces()
{
for(int i = 0; i < vertexCount; i++)
{
glBegin(GL_POLYGON);
glVertex3f(vertices[i][0], vertices[i][1], 0);
glVertex3f(vertices[i][0], vertices[i][1], extrusionDistance);
glVertex3f(vertices[(i+1)%vertexCount][0], vertices[(i+1)%vertexCount][1], extrusionDistance);
glVertex3f(vertices[(i+1)%vertexCount][0], vertices[(i+1)%vertexCount][1], 0);
glEnd();
}
}
I see a few things that stand out to me as being odd:
1) You're calling glLoadMatrixf(matrix) before the call to glTranslate() and glRotate(). Depending on what's in the matrix you're loading, that changes things.
2) You're FindCenter() method calculates the center by including the vertex[i][2] in the calculation of z, but when you actually draw the faces in DrawFaces(), you don't include the vertex[i][2] part, just the extrusion * j part. So you're not drawing the same thing that you're calculating the center of.