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();
}
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 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 am trying to draw a Bezier curve in OpenGL using floating point values. I have tried using many different code examples. My current code below, runs ,but does not show the curve on screen. The usual way to draw Bezier curves are with integer values, which means using the GLUORTHO2D() function for drawing the curve. But I want to draw a curve using floating point values. Such as x range(-1,1) and y range(-1,1).
like if x=(500) then consider it (-1 to 1) and if y=(800) then consider it (-1,1).
I have already tried using integer values and it worked for me. my code using integer values is below:
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
int X1[3]={20,25,20}, Y1[3]={5,24,38}; //first point(x1[0],y1[0]) second(x1[1],y1[1]) third(x1[2],y1[2])
void myInit()
{
glClearColor(0.0,0.0,0.0,0.0);
glColor3f(1.0,0.0,0.0);
glPointSize(8.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,128.0,0.0,96.0);
}
//p(t)=(1-t)^3*p0+3t(1-t)^2*p1+3t^2(1-t)p2+t^3p3
float getNextBezierPointX(float t)
{
float x=0.0;
for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
c = 1;
else
{
c = ctrlPointsCount-1;
}
x += c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t)
{
float y=0.0;
for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
c = 1;
else
{
c = ctrlPointsCount-1;
}
y += c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for(int i=0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using cubic bezier curve formula
float oldX=ctrlPointsX[0], oldY=ctrlPointsY[0];
for(double t = 0.0;t <= 1.0; t += 0.01) {
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
ctrlPointsCount=3;
for(int i=0;i<3;i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(640,480);
glutInitWindowPosition(100,150);
glutCreateWindow("Bezier Curve");
glutDisplayFunc(myDisplay);
myInit();
glutMainLoop();
return 0;
}
But when i tried using floating point values , it does not work for me. It does not show the curved line on screen. My code using floating point values is below:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
using namespace std;
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = { 0.946875, 0.884375, 0.946875 };
//Initializes 3D rendering
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
float getNextBezierPointX(float t)
{
float x = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
{
c = ctrlPointsCount - 1;
}
x += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t)
{
float y = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
{
c = ctrlPointsCount - 1;
}
y += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for (int i = 0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using cubic bezier curve formula
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01)
{
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}
float _angle = 0.0;
float _cameraAngle = 0.0;
float _ang_tri = 0.0;
//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //Reset the drawing perspective
ctrlPointsCount = 3;
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glutSwapBuffers();
}
void update(int value) {
_angle += 2.0f;
if (_angle > 360) {
_angle -= 360;
}
_ang_tri += 2.0f;
if (_ang_tri > 360) {
_ang_tri -= 360;
}
glutPostRedisplay(); //Tell GLUT that the display has changed
//Tell GLUT to call update again in 25 milliseconds
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1331, 641);
glutInitWindowPosition(0, 0);
//Create the window
glutCreateWindow("Our cg project");
initRendering();
//Set handler functions
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0); //Add a timer
glClearColor(0.0, 0.7, 1.5,0.0);
glutMainLoop();
return 0;
}
The problem is this here:
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
ctrlPointsX and ctrlPointsYcan only hold integer values. So when you do ctrlPointsX[i] = X1[i] and ctrlPointsY[i] = Y1[i] you are converting the floats to integers, which will round them down. So all your controlPoints will be 0.
You have to declare the controlPoints arrays as type double too:
double ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };
This should fix your problem.
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.
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.