Related
I and my college project partner are doing this project. We write this in c++ and OpenGL 2.1 with the freeglut.lib We turned the cylinder to lay down on the ground by 90 degrees. Now the cylinder is oddly misshaped. How can we fix the misshape? Is this a perspective thing? We wanted to use the cylinder later as wheels for a car which we should animate driving in a circle track. Right now the wheels on the car are only 2D circles.
void draw_cylinder(GLfloat radius,
GLfloat height,
GLubyte R,
GLubyte G,
GLubyte B)
{
GLfloat x = 0.0;
GLfloat y = 0.0;
GLfloat angle = 0.0;
GLfloat angle_stepsize = 0.1;
/** Draw the tube */
glColor3ub(R - 40, G - 40, B - 40);
glBegin(GL_QUAD_STRIP);
angle = 0.0;
while (angle < 2 * PI) {
x = radius * cos(angle);
y = radius * sin(angle);
glVertex3f(x, y, height);
glVertex3f(x, y, 0.0);
angle = angle + angle_stepsize;
}
glVertex3f(radius, 0.0, height);
glVertex3f(radius, 0.0, 0.0);
glEnd();
/** Draw the circle on top and bottom of cylinder */
glColor3ub(R, G, B);
glBegin(GL_POLYGON);
angle = 0.0;
while (angle < 2 * PI) {
x = radius * cos(angle);
y = radius * sin(angle);
glVertex3f(x, y, height);
angle = angle + angle_stepsize;
}
glVertex3f(radius, 0.0, height);
glEnd();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0, -0.4, -3.0);
//glRotatef(-40, 1.0, 0.0, 0.0);
glRotatef(-200, 1.0, 0.0, 0.0);
draw_cylinder(0.3, 0.5, 255, 160, 100);
glFlush();
}
void reshape(int width, int height)
{
if (width == 0 || height == 0) return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, (GLdouble)width / (GLdouble)height,
0.5, 20.0);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, width, height);
}
int main(int argc, char** argv)
{
/** Initialize glut */
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutCreateWindow("Create Cylinder");
glClearColor(0.0, 0.0, 0.0, 0.0);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
You need to enable the Depth Test:
glEnable(GL_DEPTH_TEST);
and clear the depth buffer as well
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Example:
float angle = 0.0f;
void display(void)
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0, -0.4, -3.0);
glRotatef(angle, 0.0, 1.0, 0.0);
angle += 0.1f;
glRotatef(-200, 1.0, 0.0, 0.0);
draw_cylinder(0.3, 0.5, 255, 160, 100);
glFlush();
glutPostRedisplay();
}
I'm trying to make the gluLookAt() function so that when I press the up & down key the camera moves around the X axis
I'm trying a method I saw at: http://www.lighthouse3d.com/tutorials/glut-tutorial/keyboard-example-moving-around-the-world/
but it's not working for me. Anyone knows an easier way? and where should I put the gluLookAt() so on myDisplay() func?
#include"glut.h"
#include<cmath>
#include<iostream>
using namespace std;
float xr = 0, yr = 0; //to control the object's movement from left to right
// actual vector representing the camera's direction
float lx = 0.0f, lz = -1.0f;
// XZ position of the camera
float x = 0.0f, z = 5.0f;
GLfloat angle = 0.0f;
int refreshmill = 1;
void timer(int value) { //to control the rotation of the object
glutPostRedisplay();
glutTimerFunc(refreshmill, timer, 0);
}
void myDisplay(void) {
//Circle One
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glBegin(GL_POLYGON);
for (int x = 0; x < 360; x++) {
theta = x * 3.142 / 180;
glVertex2f(150 * cos(theta)+xr,150 * sin(theta)+yr);
}
glEnd();
glPopMatrix();
//Circle Two
float theta2;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(0.5f, 0.0f, 0.0f); // rotation
glRotatef(angle, 0.0f, 0.0f, -0.5f); // rotation
glBegin(GL_POLYGON);
glColor3f(0, 0, 1);
for (int x = 0; x < 360; x++) {
theta2 = x * 3.142 / 180;
glVertex2f(150 + 15 * cos(theta2) + xr, 15 * sin(theta2) + yr);
}
glutSwapBuffers();
angle += 0.2; // rotation
glEnd();
glPopMatrix();
//Draw Star
glColor3ub(119, 193, 15);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glBegin(GL_POLYGON);
glVertex2d(15+xr, 60+yr);
glVertex2d(75+xr, 75+yr); //right peak
glVertex2d(15+xr, 90+yr);
glVertex2d(0+xr, 150+yr); //Up-peak Changed
glVertex2d(-15+xr, 90+yr);
glVertex2d(-75+xr,75+yr);
glVertex2d(-15+xr, 60+yr);
glVertex2d(0+xr,0+yr);
glEnd();
glPopMatrix();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
void renderScene(void) {
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
// Set the camera
gluLookAt(x, 1.0f, z,
x + lx, 1.0f, z + lz,
0.0f, 1.0f, 0.0f);
// Draw ground
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
myDisplay();
glutSwapBuffers();
}
//Move to left or right
void keyboard(int key, int x, int y) {
float fraction = 0.1f;
switch (key) {
case GLUT_KEY_RIGHT:
xr++;
cout << x << endl;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
xr--;
cout << x << endl;
glutPostRedisplay();
break;
case GLUT_KEY_UP:
angle -= 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
case GLUT_KEY_DOWN:
angle += 0.01f;
lx = sin(angle);
lz = -cos(angle);
break;
}
}
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-250, 250, -250, 250); //IMPORTANT- Define from negative to positive
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
// init GLUT and create window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Homework: Circle");
// register callbacks
glutDisplayFunc(myDisplay);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutTimerFunc(0,timer,0);
glutSpecialFunc(keyboard);
// OpenGL init
init();
// enter GLUT event processing cycle
glutMainLoop();
}
First of all there should be only 1 display call back function:
int main(int argc, char** argv) {
// [...]
// glutDisplayFunc(myDisplay); <----- DELETE!!!
glutDisplayFunc(renderScene);
// glutIdleFunc(renderScene); <----- DELETE!!!
// [...]
}
Setup an an orthographic projection with an extended near and far plane. If the object is rotated around the X axis, it takes space in the 3 dimensions:
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-250, 250, -250, 250, -250, 250); // <----
glMatrixMode(GL_MODELVIEW);
}
Add a variable anglaX which is changed in the keyboard event:
float angleX = 0.0f;
void keyboard(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT: xr++; break;
case GLUT_KEY_LEFT: xr--; break;
case GLUT_KEY_UP: angleX -= 1.0f; break;
case GLUT_KEY_DOWN: angleX += 1.0f; break;
}
}
Rotate the model, after the view was set:
gluLookAt(x, 0.0f, z, x, 0.0f, z-1.0f, 0.0f, 1.0f, 0.0f);
glRotatef(angleX, 1, 0, 0);
Don't do any calls to glutSwapBuffers(), glFlush() and glutPostRedisplay(), except at the end of renderScene:
void timer(int value) { //to control the rotation of the object
// glutPostRedisplay(); <--- DELETE
glutTimerFunc(refreshmill, timer, 0);
}
void myDisplay(void) {
//Circle One
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glPushMatrix();
glBegin(GL_POLYGON);
for (int x = 0; x < 360; x++) {
theta = x * 3.142 / 180;
glVertex2f(150 * cos(theta)+xr,150 * sin(theta)+yr);
}
glEnd();
glPopMatrix();
//Circle Two
float theta2;
glPushMatrix();
glTranslatef(0.5f, 0.0f, 0.0f); // rotation
glRotatef(angle, 0.0f, 0.0f, -0.5f); // rotation
glBegin(GL_POLYGON);
glColor3f(0, 0, 1);
for (int x = 0; x < 360; x++) {
theta2 = x * 3.142 / 180;
glVertex2f(150 + 15 * cos(theta2) + xr, 15 * sin(theta2) + yr);
}
angle += 0.2; // rotation
glEnd();
glPopMatrix();
//Draw Star
glColor3ub(119, 193, 15);
glPushMatrix();
glBegin(GL_POLYGON);
glVertex2d(15+xr, 60+yr);
glVertex2d(75+xr, 75+yr); //right peak
glVertex2d(15+xr, 90+yr);
glVertex2d(0+xr, 150+yr); //Up-peak Changed
glVertex2d(-15+xr, 90+yr);
glVertex2d(-75+xr,75+yr);
glVertex2d(-15+xr, 60+yr);
glVertex2d(0+xr,0+yr);
glEnd();
glPopMatrix();
}
void renderScene(void) {
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set the camera
gluLookAt(x, 0.0f, z, x, 0.0f, z-1.0f, 0.0f, 1.0f, 0.0f);
glRotatef(angleX, 1, 0, 0);
// Draw ground
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
myDisplay();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
Further I recommend to use double buffering:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
You can init your camera with gluLookAt at init(), then rotate it when arrow keys pressed. If you want to rotate camera around it's local x axis, assume your initial modelview matrix is V, newly happened rotation around x axis is R, you need to set modelview matrix to R*V, not V*R.
case GLUT_KEY_UP:
GLfloat temp[16];
glGetFloatv(GL_MODELVIEW_MATRIX, temp);
glLoadIdentity();
glRotate(stepAngle, 1, 0, 0); // calculate stepAngle by your self
glMultMatrixf(temp);
break;
You don need to reset modelview matrix during rendering, view part is already done, make sure you restore it after rendering the whole scene:
glPushMatrix(GL_MODELVIEW_MATRIX)
// don't call glLoadIdentity() here, you don't need to reset view part.
...
...
glPopMatrix()
#include <stdio.h>
#include <math.h>
#include "glut.h"
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 400, 0.0, 300.0);
}
void drawTurbine() {
// draw the tower
glBegin(GL_LINES);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(160, 40);
glVertex2f(163, 180);
glVertex2f(160, 40);
glVertex2f(175, 40);
glVertex2f(175, 40);
glVertex2f(172, 180);
glEnd();
// Rotate object
glPushMatrix();
glRotatef(100, 0, 1, 0);
// draw first rotor blade
glBegin(GL_TRIANGLES);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(173, 180);
glVertex2f(163, 180);
glVertex2f(168, 270);
glEnd();
// draw second rotor blade
glBegin(GL_TRIANGLES);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(170, 174);
glVertex2f(175, 180);
glVertex2f(247, 140);
glEnd();
// draw third rotor blade
glBegin(GL_TRIANGLES);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(162, 180);
glVertex2f(167, 174);
glVertex2f(88, 140);
glEnd();
// circle in the middle
float theta;
glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0);
for (int i = 0; i <= 360; i++) {
theta = i * 3.142 / 180;
glVertex2f(168 + 7 * cos(theta), 180 + 6.5 * sin(theta));
}
glEnd();
glPopMatrix();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawTurbine();
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}
void idle() {
display();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(700, 600);
glutInitWindowPosition(10, 10);
glutCreateWindow("Wind Turbine");
init();
glutIdleFunc(idle);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
I have created a wind turbine and I am trying to rotate the rotor blades, but the code just makes it disappear. I want it to rotate clockwise. I just need an idea on how I can make it rotate like a real wind turbine. I am new to using glRotatef, and this will be my first time rotating an object with OpenGL.
You need a variable for the current angle of the wind turbine (current_angle) and the rotation angle per frame (step_angle). Further you have to know the center of the wind turbine (center_x, center_y):
float current_angle = 0.0f;
float step_angle = 0.2f;
float center_x = 168.0f;
float center_y = 180.0f;
To rotate around a pivot you have to define a model matrix, which displace by the inverted pivot, then rotates and final transforms back by to the pivot. The rotation axis is the z axis (0, 0, 1) because your geometry is drawn in the xy-plane:
glTranslatef( center_x, center_y, 0.0f );
glRotatef(current_angle, 0, 0, 1);
current_angle += step_angle;
glTranslatef(-center_x, -center_y, 0.0f );
Preview:
Complete code of the function drawTurbine:
void drawTurbine() {
// draw the tower
glBegin(GL_LINES);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(160, 40);
glVertex2f(163, 180);
glVertex2f(160, 40);
glVertex2f(175, 40);
glVertex2f(175, 40);
glVertex2f(172, 180);
glEnd();
// Rotate object
glPushMatrix();
glTranslatef( center_x, center_y, 0.0f );
glRotatef(current_angle, 0, 0, 1);
current_angle += step_angle;
glTranslatef(-center_x, -center_y, 0.0f );
// draw first rotor blade
glBegin(GL_TRIANGLES);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(173, 180);
glVertex2f(163, 180);
glVertex2f(168, 270);
glEnd();
// draw second rotor blade
glBegin(GL_TRIANGLES);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(170, 174);
glVertex2f(175, 180);
glVertex2f(247, 140);
glEnd();
// draw third rotor blade
glBegin(GL_TRIANGLES);
glColor3f(1.0, 1.0, 1.0);
glVertex2f(162, 180);
glVertex2f(167, 174);
glVertex2f(88, 140);
glEnd();
// circle in the middle
float theta;
glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0);
for (int i = 0; i <= 360; i++) {
theta = i * 3.142 / 180;
glVertex2f(168 + 7 * cos(theta), 180 + 6.5 * sin(theta));
}
glEnd();
glPopMatrix();
}
I'm using code to draw text as textures in OpenGL (Qt4.8.3 + Linux (debian-like)).
Code was ported from 2D project, where it is working good.
2D project was using gluOrtho2D, now I use gluLookAt for 3D.
The issue is that instead of text I'm seing colored rectangle.
If I turn on GL_DEPTH_TEST I see artifacts instead of text. BTW artifacts change if I move camera, which is quite strange.
Here's the code:
void GLWidget::paintGL() {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Set blending function.
glEnable(GL_BLEND); //Enable blending.
glShadeModel(GL_SMOOTH);
glEnable(GL_MULTISAMPLE);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60.0f, (GLdouble) width() / (GLdouble) height(), 0.001f, 10000.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// Set up current camera
gluLookAt( cameraDistance * sin(cameraTheta * M_PI / 180) * cos(cameraPhi * M_PI / 180),
cameraDistance * sin(cameraTheta * M_PI / 180) * sin(cameraPhi * M_PI / 180),
cameraDistance * cos(cameraTheta * M_PI / 180),
0.0, 0.0, 0.0,
0.0, 0.0, 1.0);
glTranslatef(-4.5355, -4.5355, 0.0);
glPushMatrix();
// draw text labels
drawLabel(1, 0, 90, "1");
drawLabel(2, 0, 90, "2");
drawLabel(3, 0, 90, "3");
drawLabel(4, 0, 90, "4");
drawLabel(5, 0, 90, "5");
glPopMatrix();
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glPopMatrix();
}
void GLWidget::drawLabel(float xpos, float ypos, float angle, char *txt) {
float labelHeight = 0.3;
float labelWidth = labelHeight / 2;
float margin = labelWidth / 10;
float len = (float) strlen(txt);
glPushMatrix();
glRotatef(-angle, 0, 0, -1);
glTranslatef(xpos, ypos, 0.0f);
glRotatef(angle, 0, 0, -1);
glScalef(1.0, -1.0, 1.0);
glTranslatef(- len * labelWidth / 2, -labelHeight / 2 + margin, 0.0f);
// background
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-margin, -margin, 0);
glVertex3f(len * labelWidth + margin, -margin, 0);
glVertex3f(len * labelWidth + margin, labelHeight + margin, 0);
glVertex3f(-margin, labelHeight + margin, 0);
glEnd();
// text
glColor3f(0.5f, 0.5f, 0.5f);
glEnable(GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, glFont->getTextureID() );
glFont->drawText(labelWidth, labelHeight, txt);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
void oglFont::drawText(GLfloat cw, GLfloat ch, char *txt)
{
glBegin(GL_QUADS);
//character location and dimensions
GLfloat cx = 0.0f;
GLfloat cy = 0.0f;
//calculate how wide each character is in term of texture coords
GLfloat dtx = float(c_width) / float(m_width);
GLfloat dty = float(c_height) / float(m_height);
for (char * c = txt; *c != 0; c++, cx += cw) {
int index = getCharIndex(c);
int row = index / c_per_row;
int col = index % c_per_row;
if (index < 0) {
//qDebug() << "glFont: Character outside of font! char: " << c;
}
// find the texture coords
GLfloat tx = float(col * c_width) / float(m_width);
GLfloat ty = float(row * c_height) / float(m_height);
glTexCoord2f(0, 0);
glVertex2f(cx, cy);
glTexCoord2f(1, 0);
glVertex2f(cx + cw, cy);
glTexCoord2f(1, 1);
glVertex2f(cx + cw, cy + ch);
glTexCoord2f(0, 1);
glVertex2f(cx, cy + ch);
}
glEnd();
}
The reason for the artifacts is Z fighting.
This problem can be solved by increasing the depth buffer precision OR by making the different objects further apart from each-other (the ones from drawlable ).
Also make sure that your generated text doesn't get culled by the far plane / near plane (maybe you generate the geometry very near the edges ? ).
It turns out that because texture was loaded in QGLWidget constructor, context was either not created or not set.
I moved texture loading in initializeGL() method and it works great.
I'm having an awful time trying to get these triangle strips to show up.
Where am I going wrong?
InitGL:
InitGL()
{
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//
gluPerspective(45, //view angle
WINDOW_WIDTH/WINDOW_HEIGHT, //aspect ratio
1.0, //near clip
2000.0);//far clip
glMatrixMode(GL_MODELVIEW);
glClearColor(0, 0, 0, 0);
}
and Display:
void display ( void ) // Create The Display Function
{
int height = sourceImage->nx;
int width = sourceImage->ny;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glScalef(.005, .004, .005); //all vertices are in the range x[0,200], y[0,255], z[0,200]
glTranslatef(0, 0, -2); //so scale to put all vertices in the range [0,1] and move the z coord from [0,1] to the -z axis [-1,-2]
glColor3f(0, 0, 0);
glPushMatrix(); //save this view
float cell_height = 0;
for(float z = 0; z < width; z++)
{
glBegin(GL_TRIANGLE_STRIP);
for(float x = 0; x < height; x++)
{
cell_height = cellHeight(x, z);
glVertex3f(x, cell_height, z);
cell_height = cellHeight(x, z+1);
glVertex3f(x, cell_height,(z+1));
cell_height = cellHeight(x+1, z);
glVertex3f(x+1, cell_height, z);
cell_height = cellHeight(x+1, z+1);
glVertex3f(x+1, cell_height, (z+1));
}
glEnd();
}
glPopMatrix(); //restore view
Set your color to something other than pure black:
glColor3f(1.0f, 1.0f, 1.0f);