I'm following the xoax.net tutorials for OpenGL in C++, and I am stuck on drawing the stripes in the U.S. flag using a for loop. I just get a blue screen (since I set the background colour to blue). Here is the code for the 'DrawStripes' function:
void DrawStripes() {
for (int x = 0; x < 13; ++x) {
if (x % 2 == 0) {
glColor3f(204/255, 0, 0);
} else {
glColor3f(1, 1, 1);
}
float fStartX = 0;
float fEndX = 1;
float fStartY = x * (1/13);
float fEndY = (x + 1) * (1/13);
if (x > 5) {
fStartX = .76/1.9;
}
glBegin(GL_QUADS);
glVertex3f(fStartX, fStartY, 0);
glVertex3f(fEndX, fStartY, 0);
glVertex3f(fEndX, fEndY, 0);
glVertex3f(fStartX, fEndY, 0);
glEnd();
}
}
(I have put this function in the 'draw' function so it isn't just I'm not telling it to use the function)
Any ideas?
--- EDIT ---
Here are the 'Draw' and 'Initialize' functions:
void Draw() {
glClear(GL_COLOR_BUFFER_BIT);
DrawStripes();
glFlush();
}
void Initialize() {
glClearColor(0.0, 0.0, 0.5, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}
1/13 is 0 in C++. Been there, done that. For float constants you want to use 1.0f/13.0f.
Related
When I execute the code I get a hot air balloon formed of three elements. My issue is that when I move the objects from the keyboard, the objects loose color, and become more like wire than solid.
From what I discovered until now, my trouble comes from this function call:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
But I need it to make the ropes...
/*
This program shows a hot air balloon rotating around its own axe to the left and to the right
*/
#include "glos.h"
#include<math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
void myinit(void);
void CALLBACK display(void);
void CALLBACK myReshape(GLsizei w, GLsizei h);
void CALLBACK rotateRight(void);
void CALLBACK rotateLeft(void);
static GLfloat x = 0;
static GLfloat y = 0;
static GLfloat z = 0;
static GLfloat alfa = 0;
double PI = 3.14159265;
void myinit (void) {
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
}
void CALLBACK rotateLeft(void) { y -= 5; }
void CALLBACK rotateRight(void) { y += 5; }
void CALLBACK display (void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(x, 1, 0, 0);
glRotatef(y, 0, 1, 0);
glTranslatef(0, -80, 0);
//cube = basket
glColor3f(1, 1, 0);
auxSolidCube(50);
//full sphere = baloon
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0,200,0);
glRotatef(-90, 1, 0, 0);
auxSolidSphere(130.0);
glPopMatrix();
//polygon cylinder = ropes
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_QUAD_STRIP);
glColor3f(0.0, 1.0, 1.0);
for (alfa = 0; alfa <= 360; alfa+=30) {
glVertex3f(65 * sin((PI * alfa) / 180), 100, 65 * cos((PI * alfa) / 180));//top of the cylinder
glVertex3f(15 * sin((PI * alfa) / 180),0, 15 * cos((PI * alfa) / 180));//base of the cylinder
}
glEnd();
glPopMatrix();
glPopMatrix();
glFlush();
}
void CALLBACK myReshape(GLsizei w, GLsizei h)
{
if (!h) return;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-400,400, -400 *(GLfloat)h / (GLfloat)w, +400.0*(GLfloat)h/(GLfloat)w, -1000.0, 1000.0);
else
glOrtho (-400*(GLfloat)w / (GLfloat)h, 400.0*(GLfloat)w/(GLfloat)h, -400, 400.0, -1000.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGB | AUX_DEPTH);
auxInitPosition (100, 0, 600, 400);
auxInitWindow ("Hot air balloon");
myinit ();
auxKeyFunc(AUX_RIGHT, rotateRight);
auxKeyFunc(AUX_LEFT, rotateLeft);
auxReshapeFunc (myReshape);
auxMainLoop(display);
return(0);
}
OpenGL is a state engine. Once a state has been set, it is retained until it is changed again, even beyond frames. Therefore, you need to set the polygon mode GL_FILL before rendering the solid geometry:
void CALLBACK display (void)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// render solid geometry
// [...]
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// render wireframe geometry
// [...]
}
I've got a taks from university and have to make a small example of solar system, the objects have to rotate etc. The problem is that when I do not call GluLookAt() everything looks fine, but I would like to change the view and when I call the function, there occurs that one orbit renders completely strangely.
I do not know if problem is with wrong creation of the first orbit, or with the proper values in gluLookAt parameters. Can anyone help?
Here's how it looks without calling gluLookAt():
Here's how it looks after gluLookAt():
Here's the code:
#include "stdafx.h"
#include <GL\glut.h>
#include <math.h>
GLfloat yRotated=1;
GLfloat movement = 0;
void drawCircle(float r) { // radius
glBegin(GL_LINE_LOOP);
for (int i = 0; i <= 300; i++) {
double angle = 2 * 3.14 * i / 300;
double x = r*cos(angle);
double y = r*sin(angle);
glVertex3d(x, y, -5.5);
}
glEnd();
}
void display(void) {
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
//gluLookAt(5, 5, 5, 0, 0, -8, 0, 1, 0); // 3rd coordinate - depth
float radius1 = 6;
float radius2 = 1;
//first orbit
glColor3f(1, 1, 1);
glPushMatrix();
glTranslatef(0, 0, -5.5);
drawCircle(radius1);
glPopMatrix();
//second orbit with rotation
glPushMatrix();
glRotatef(yRotated, 0, 0, 1);
glPushMatrix();
glTranslatef(radius1 / 2, 0, 0);
drawCircle(radius2);
glPopMatrix();
glPopMatrix();
//first czajnik
glColor3f(0.8, 0.2, 0.1);
glPushMatrix();
glTranslatef(0.0, 0.0, -5.5);
// glScalef(1.0, 1.0, 1.0);
glRotatef(yRotated, 0, 0, 1);
glRotatef(90, 1, 0, 0);
glutSolidSphere(1,20,20);
//second czajnik
glPushMatrix();
glColor3f(0, 0, 1);
glTranslatef(radius1/2, 0, 0);
glRotatef(yRotated, 0, 1, 0);
glutSolidSphere(0.5, 20, 20);
//third czajnik
glPushMatrix();
glTranslatef(radius2, 0, 0);
glColor3f(1, 1, 0);
glRotatef(yRotated, 0, 1, 0);
glutSolidSphere(0.2, 20, 20);
glPopMatrix();
//second czajnik pop
glPopMatrix();
//first czajnik pop
glPopMatrix();
glFlush();
}
void idle() {
yRotated += 0.1;
Sleep(2);
display();
}
void myReshape(int w, int h) {
if (w == 0 || h == 0) return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70.0, (GLdouble)w / (GLdouble)h, 0.5, 20.0);
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(900, 600);
glutCreateWindow("Solar system");
//window with a title
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glClearColor(0, 0, 0, 1.0);
glutDisplayFunc(display);
glutReshapeFunc(myReshape);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
Some of your objects are at different z values, e.g. 1st orbit at -5.5, second at 0, because you "popped" the matrix.
In general, do not do so many push\pops nested into each other, matrix stack isn't made of rubber.
There is more efficient circle drawing procedure than to calculate sine and cosine for each step, e.g. to get advantage of circle being a figure of rotation:
inline void circle(F32 r, U32 quality)
{
if (r < F_ALMOST_ZERO) return;
F32 th = M_PI /(quality-1);
F32 s = sinf(th);
F32 c = cosf(th);
F32 t;
F32 x = r;
F32 y = 0;
::glBegin (GL_LINE_LOOP);
for(U32 i = 0; i < quality; i++)
{
glVertex2f(x, y);
t = x;
x = c*x + s*y;
y = -s*t + c*y;
}
::glEnd();
}
it can be optimized further by using symmetry, but this one is the basis.
I'm trying to do selection in opengl but it is not working.
I draw objects I receive from a .obj file (v, vn, f, o and such indices). Each object consists from "groups" and each group is a group of GL_POLYGON.
Here is the draw function:
void draw(GLenum mode) {
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(100.0, 0.0, 0.0);
glColor3f(0, 0, 1);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 100.0, 0.0);
glColor3f(0, 1, 0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 100.0);
glEnd();
glColor4f(1.0, 1.0, 1.0, 1.0);
if (changeFOV) {
fovAngle += fovScale;
changeFOV = false;
setTransformations();
}
for (unsigned int i = 0; i < objects.size(); i++) {
objectItem currObject = objects[i];
for (unsigned int j = 0; j < currObject.getGroups().size(); j++) {
group currGroup = currObject.getGroups().at(j);
for (unsigned int k = 0; k < currGroup.getFs().size(); k++) {
if (mode == GL_SELECT)
glPushName(currGroup.getName());
glPushMatrix();
vector<pair<int, int> > currF = currGroup.getFs()[k];
glBegin(GL_POLYGON);
for (unsigned int kk = 0; kk < currF.size(); kk++) {
Vector3f currVertex = vertexes.at(
(currF.at(kk).first - 1 >= 0) ?
currF.at(kk).first - 1 : 0);
Vector3f currNormal = vertexesNormal.at(
(currF.at(kk).second - 1 >= 0) ?
currF.at(kk).second - 1 : 0);
glNormal3f(currNormal.x, currNormal.y, currNormal.z);
glVertex3f(currVertex.x / 1, currVertex.y / 1,
currVertex.z / 1);
}
glEnd();
glPopMatrix();
}
}
}
}
The drawing works ok and I see the object on the screen.
This is all the picking procedure
/* PICKING */
void processHits(GLint hits, GLuint *buffer) {
float z1, z2;
for (int i = 0; buffer[i] > 0; i += 5) {
z1 = buffer[i + 1] / 4294967295.0;
z2 = buffer[i + 2] / 4294967295.0;
printf("z1 = %f ,z2 = %f zValue = %f\n", z1, z2, zValue[0]);
if ((zValue[0] <= z1 + 0.0001 && zValue[0] >= z2 - 0.0001)
|| (zValue[0] >= z1 - 0.0001 && zValue[0] <= z2 + 0.0001)) { //try to locate which name is correlated with the pressed pixel according to z value
ii = buffer[i + 3];
jj = buffer[i + 4];
}
}
}
void startPicking(GLuint *selectionBuf) {
glSelectBuffer(bufSize, selectionBuf); //declare buffer for input in selection mode
glRenderMode(GL_SELECT); //change to selecting mode
glInitNames(); //initialize names stack
glPushName(-1); //push name
}
void pick(int button, int x, int y) {
//use selection mode to pick
glReadPixels(x, viewport[3] - y, 1, 1, GL_RGBA, GL_FLOAT, pix);
//printf("depth = %f, x = %d, y = %d\n",pixels[(viewport[3]-y)*512+x],x,viewport[3]-y);
glMatrixMode(GL_PROJECTION);
glReadPixels((GLdouble) x, (GLdouble) viewport[3] - y, 2, 2,
GL_DEPTH_COMPONENT, GL_FLOAT, zValue);
glPushMatrix(); //saves current projection matrix
startPicking(selectionBuf); //preper selection mode
glLoadIdentity();
gluPickMatrix((GLdouble) x, (GLdouble) viewport[3] - y, 1, 1, viewport); //change matrices so only the area of the picking pixel can be seen.
gluPerspective(fovAngle, 1, near, far); //return to perspective state
glMatrixMode(GL_MODELVIEW);
draw(GL_SELECT); //draws board on background
hits = glRenderMode(GL_RENDER); //gets hits number
glMatrixMode(GL_PROJECTION);
glPopMatrix(); //restores projection matrix
glMatrixMode(GL_MODELVIEW);
processHits(hits, selectionBuf); //check hits
if(hits > 0)
printf("touched: %d\n",selectionBuf[3]);
//printf("depth %f hits: %d\n\n",pixels[(viewport[3]-y)*512+x], hits);
if (zValue[0] < 1.0) {
isPick = true;
xx = x;
yy = y;
if (button == GLUT_RIGHT_BUTTON)
zMove = true;
else
zMove = false;
}
}
the pick function is called when the mouse is clicked (using opengl mouse function).
The error I'm receiving is that no objects appears to be hit when clicking on an object.
I'm using Ubuntu 14.04 LTS with Opengl 3.0
I don't know how to ask or what specifically ask, I would appreciate some inputs on the code if you see something wrong..
You seemed to have missed using glPopName()
GLNames used in the selection buffer are pushed on a stack. So unless you call glPopName() the stack would never unwind. The working of this is similar to the calls glPushMatrix() and glPopMatrix().
Typically this is what the code flow looks like.
//Push the name of the primitives on top of selection stack
glPushName(...)
//Set Transformations / Draw the primitives
..
..
//Pop the name (Clear the stack for pushing another name)
glPopName();
this is my cube. Once created, it has a random x position on either -2, -1, 0, 1, or 2.
void cube(void)
{
srand (time(0));
int cube_posX;
int lowv = -2;
int highv = 2;
cube_posX = rand() % (highv - lowv + 1) + lowv;
glTranslatef(cube_posX, 0.0, cube_angle);
glRotatef(cube_angle, 90.0, 0.0, 1.0);
glutSolidCube(0.25);
}
and this is how I move the cube slowly forward
void MOVE_CUBE(int value)
{
cube_posZ = cube_posZ - 0.01;
glutPostRedisplay();
glutTimerFunc(25, MOVE_CUBE, 0);
}
and finally putting them in display:
void init(void)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
float cam_eyeX = 0.0, cam_eyeY = 1.5, cam_eyeZ = 5.0;
float cam_centerX = 0.0, cam_centerY = 0.0, cam_centerZ = 0.0;
void display(void)
{
glClearColor(1.0,1.0,1.0,1.0); //to add background color (white)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(cam_eyeX, cam_eyeY, cam_eyeZ, cam_centerX, cam_centerY, cam_centerZ, 0.0, 1.0, 0.0); //camera! (cam position X, cam position Y, cam position Z, cam target X, cam target Y, cam target Z, up position X, up position Y, up position Z)
cube();
glutSwapBuffers();
angle += 0.05; //to affect the glRotate function
glFlush();
}
void reshape(int w, int h)
{
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
glMatrixMode (GL_MODELVIEW);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); // Set up display buffer
glutInitWindowSize(750, 500); //window's size
glutInitWindowPosition(100, 100); //window's position
glutCreateWindow("Hendra Ganteng!"); //window's title
init();
glutDisplayFunc(display);
glutIdleFunc (display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard_Handler);
MOVE_CUBE(0);
glutMainLoop();
return 0;
}
But when I see it in action, the cube moves forward flawlessly, but keeps changing x position onto those 5 possibilities (-2,-1,0,1,2) every 0.5 to 1 second. If I disable the srand(time(0)), the cube changes its x position rapidly. I just want to make it stay in 1 x position so then I can call more cubes in different x position. Could someone please kindly what's wrong in my code?
How is that behaviour not expected? You are generating a random X position every time you display your cube. If you re-seed the random number generator using the time, then it will be start a different sequence whenever the time changes (once per second).
Instead, you should pre-generate your cube(s). How about this:
// Global cube data
struct Cube {
int x;
double angle;
};
vector<Cube> cubes;
const int num_cubes = 1;
// Example initialisation...
void InitCubes()
{
cubes.reserve(num_cubes);
for( int i = 0; i < num_cubes; i++ )
{
Cube cube;
cube.x = rand() % (highv - lowv + 1) + lowv;
cube.angle = 0.0;
cubes.push_back(cube);
}
}
Now the update/display cycles simply need to modify the angle, but not the x-position.
void UpdateCube( Cube & cube )
{
cube.angle += 0.05;
}
void DisplayCube( Cube & cube )
{
glTranslatef((double)cube.x, 0.0, cube.angle);
glRotatef(cube.angle, 90.0, 0.0, 1.0);
glutSolidCube(0.25);
}
In your main function, call InitCubes() during startup.
In your display function, do this:
void display(void)
{
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(cam_eyeX, cam_eyeY, cam_eyeZ, cam_centerX, cam_centerY, cam_centerZ, 0.0, 1.0, 0.0);
// Display cubes
for( int i = 0; i < cubes.size(); i++ ) DisplayCube( cubes[i] );
glutSwapBuffers();
glFlush();
// Update cubes for next render cycle.
for( int i = 0; i < cubes.size(); i++ ) UpdateCube( cubes[i] );
}
I have the following code
int i = 0;
void display(void)
{
glLoadIdentity();
glColor3f(1.0f, 0.0f, 0.0f);
glPushMatrix();
glTranslatef(20.0f, 20.0f, -40.f);
glRotatef(180.f, 0.0, 0.0, 1.0);
glBegin(GL_TRIANGLES);
glVertex3f(pts[tri[i]], (pts[ptsLength/2 + tri[i]] - maximum) * -1, 0);
glVertex3f(pts[tri[i+1]], (pts[ptsLength/2 + tri[i+1]] - maximum) * -1, 0);
glVertex3f(pts[tri[i+2]], (pts[ptsLength/2 + tri[i+2]] - maximum) * -1, 0);
glEnd();
i+=3;
glPopMatrix();
glutSwapBuffers();
}
How can I make this method pause and wait for a keystroke before rendering the next triangle?
Is this the glutIdleFunc, or the one called when you glutPostRedisplay?
In either case, you need to first setup a glutKeyboardFunc, in which you detect whether a certain key is pressed or not.
In the case you update the screen only on certain events:
... inside the keyboard function
if (key_pressed == THE_KEY_YOU_WANT)
glutPostRedisplay();
In the case you are using display as the idle function, you can do:
global:
bool go_next = false;
... inside the keyboard function
if (key_pressed == THE_KEY_YOU_WANT)
go_next = true;
... inside display:
void display(void)
{
if (go_next)
{
go_next = false;
glLoadIdentity();
glColor3f(1.0f, 0.0f, 0.0f);
glPushMatrix();
... etc
glPopMatrix();
}
glutSwapBuffers();
}
Side note: It is best to keep the logic and rendering separate. So perhaps a code like this is best:
int triangles_to_draw = 0;
... inside the keyboard function
if (key_pressed == THE_KEY_YOU_WANT)
process_event_next_triangle();
void process_event_next_triangle()
{
if (triangles_to_draw < maximum)
++triangles_to_draw;
}
void display(void)
{
go_next = false;
glLoadIdentity();
glColor3f(1.0f, 0.0f, 0.0f);
glPushMatrix();
glTranslatef(20.0f, 20.0f, -40.f);
glRotatef(180.f, 0.0, 0.0, 1.0);
glBegin(GL_TRIANGLES);
for (int i = 0; i < 3*triangles_to_draw; i += 3)
{
glVertex3f(pts[tri[i]], (pts[ptsLength/2 + tri[i]] - maximum) * -1, 0);
glVertex3f(pts[tri[i+1]], (pts[ptsLength/2 + tri[i+1]] - maximum) * -1, 0);
glVertex3f(pts[tri[i+2]], (pts[ptsLength/2 + tri[i+2]] - maximum) * -1, 0);
}
glEnd();
glPopMatrix();
glutSwapBuffers();
}
Note that this way, you can make the process_event_next_triangle as complicated as you want without affecting the display function. This makes life much easier when you have many keys doing different stuff.
when processing glut keyboard event add code:
if (key == DESIRED_KEY_CODE)
i+=3
and remove that i+=3 in the display() func
but note that this way we will have only one triangle at a time... if you want to show several triangles you have to have some counter of visible triangles and display them in a loop.