I have this little program that is supposed to rotate a square in 2D. When I give it fixed vertexes, it works fine. But when I try to put it in motion, the square just starts to flash and blink and not really resemble a square at all. Everything looks good to me, so I must be missing something. Can anyone see it?
#include <stdio.h>
#include <math.h>
#include <glut/glut.h>
#define DEG_TO_RAD 0.017453
GLsizei ww, wh;
GLfloat theta;
void display()
{
//clear window
glClear(GL_COLOR_BUFFER_BIT);
//draw unit square polygon
glBegin(GL_POLYGON);
glVertex2f(sin(DEG_TO_RAD*theta), cos(DEG_TO_RAD*theta));
glVertex2f(-sin(DEG_TO_RAD*theta), cos(DEG_TO_RAD*theta));
glVertex2f(-sin(DEG_TO_RAD*theta), -cos(DEG_TO_RAD*theta));
glVertex2f(sin(DEG_TO_RAD*theta), -cos(DEG_TO_RAD*theta));
// glVertex2f(-0.5, -0.5);
// glVertex2f(-0.5, 0.5);
// glVertex2f(0.5, 0.5);
// glVertex2f(0.5, -0.5);
glEnd();
//flush gl buffers
glFlush();
}
void init() {
//set color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
//set fill color to white
glColor3f(1.0, 1.0, 1.0);
//set up standard orthogonal view with clipping
//box as cube of side2 centered at origin
//this is default view and these statements could be removed
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
}
void myreshape(GLsizei w, GLsizei h) {
//adjust clipping window
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w<=h)
gluOrtho2D(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w);
else
gluOrtho2D(-2.0 * (GLfloat) w / (GLfloat) h, 2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0);
glMatrixMode(GL_MODELVIEW);
//adjust viewport
glViewport(0, 0, w, h);
//set global size for use by drawing routine
ww = w;
wh = h;
}
void myidle() {
theta += 2.0;
if (theta > 360.0) theta -= 360.0;
glutPostRedisplay();
}
int main(int argc, char** argv)
{
theta = 0.0;
// initialize mode and open a window in upper-left corner of screen
// window title is name of program (arg[0])
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);//Set the window size
glutInitWindowPosition(0, 0);
glutCreateWindow("rotating square");
glutDisplayFunc(display);
init();
glutReshapeFunc(myreshape);
glutIdleFunc(myidle);
glutMainLoop();
return 0;
}
Your vertex definitions just don't produce a square. Try the following:
glVertex2f(cos(DEG_TO_RAD*(theta + 135)), sin(DEG_TO_RAD*(theta + 135)));
glVertex2f(cos(DEG_TO_RAD*(theta + 45 )), sin(DEG_TO_RAD*(theta + 45 )));
glVertex2f(cos(DEG_TO_RAD*(theta - 45 )), sin(DEG_TO_RAD*(theta - 45 )));
glVertex2f(cos(DEG_TO_RAD*(theta - 135)), sin(DEG_TO_RAD*(theta - 135)));
The comment from Andon below your question is right. You should create the geometry (the vertices) only once and then rotate them by setting the matrix to ModelView and rotate with glRotatef(...). Recreating geometries on each render cycle is a wrong aproach.
Related
I didn't want to go back to the same question from yesterday, however before I am able to use the function to turn on and off the grid, I first need to know if my grid is actually working, I have been making new projects all night trying to display the grid but it isn't showing, the screen is always black and nothing is there at all.
#include "include\freeglut.h" // OpenGL toolkit - in the local shared folder
#include <iostream>
//set up some constants
#define X_CENTRE 0.0 /* centre point of square */
#define Y_CENTRE 0.0
#define LENGTH 1.0 /* lengths of sides of square */
GLfloat red = 1.0, green = 1.0, blue = 1.0;
int w;
int h;
/* reshape callback function
executed when window is moved or resized */
void reshape(int width, int height)
{
glViewport(0, 0, width, height);
/* uses orthographic (parallel) projection
use xmin = -1, xmax = 1
ymin = -1, ymax = 1
znear = -1, zfar = 1 - not relevant here (2D) */
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}
/* display callback function
called whenever contents of window need to be re-displayed */
//this is the all important drawing method - all drawing code goes in here
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT); /* clear window */
//glColor3f(red, green, blue); /* white drawing objects */
glColor3f(0.8, 0.8, 0.8);
GLint i;
glEnable(GL_LINE_STIPPLE); //Activates the line-style feature
glLineStipple(1, 0xAAAA); // Plots a dashed polyline
glBegin(GL_LINES);
for (i = 2; i <= 9; i++)
{
glVertex3f(i * 0.1 * w, 0.0, 0.0);
glVertex3f(i * 0.1 * w, 0.9 * h, 0.0);
}
for (i = 1; i <= 9; i++)
{
glVertex3f(0.1 * w, i * 0.1 * h, 0.0);
glVertex3f(w, i * 0.1 * h, 0.0);
}
glEnd();
glDisable(GL_LINE_STIPPLE);
glFlush(); /* execute drawing commands in buffer */
}
/* graphics initialisation */
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0); /* window will be cleared to black */
}
//rename this to main(...) and change example 2 to run this main function
int main(int argc, char** argv)
{
/* window management code ... */
/* initialises GLUT and processes any command line arguments */
glutInit(&argc, argv);
/* use single-buffered window and RGBA colour model */
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
/* window width = 400 pixels, height = 400 pixels */
glutInitWindowSize(400, 400);
/* window upper left corner at (100, 100) */
glutInitWindowPosition(100, 100);
/* creates an OpenGL window with command argument in its title bar */
glutCreateWindow("Example 1");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
The variables w and h a re not initialized. Initialize the variables by 1:
int w = 1;
int h = 1;
However, if you want to set the vertex coordinates in window space, you have to change the orthographic projection. The projection matrix defines the area (volume) with respect to the observer (viewer) which is projected onto the viewport. At orthographic projection, this area (volume) is defined by 6 distances (left, right, bottom, top, near and far) to the viewer's position.
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
glOrtho(0.0, (float)w, (float)h, 0.0, -1.0, 1.0);
Function reshape:
void reshape(int width, int height)
{
glViewport(0, 0, width, height);
/* uses orthographic (parallel) projection
use xmin = -1, xmax = 1
ymin = -1, ymax = 1
znear = -1, zfar = 1 - not relevant here (2D) */ #
w = width;
h = height;
glMatrixMode(GL_PROJECTION);
glOrtho(0.0, (float)w, (float)h, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
guys i try to make an GLUT application that could rotate object on key pressed, but it seems not worked.
#include <stdio.h>
#include <gl/glut.h>
GLfloat rotation = 90.0;
float posX = 0, posY = 0, posZ = 0;
void reshape(int width, int heigth){
/* window ro reshape when made it bigger or smaller*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//clip the windows so its shortest side is 2.0
if (width < heigth) {
glOrtho(-2.0, 2.0, -2.0 * (GLfloat)heigth / (GLfloat)width, 2.0 * (GLfloat)heigth / (GLfloat)width, 2.0, 2.0);
}
else{
glOrtho(-2.0, 2.0, -2.0 * (GLfloat)width / (GLfloat)heigth, 2.0 * (GLfloat)width / (GLfloat)heigth,2.0 , 2.0);
}
// set viewport to use the entire new window
glViewport(0, 0, width, heigth);
}
void rect(){
glBegin(GL_POLYGON);
glVertex2f(-0.2, -0.2);
glColor3f(1.0, 1.0, 0.0);
glVertex2f(-0.2, 0.2);
glColor3f(1.0, 0.0, 1.0);
glVertex2f(0.2, 0.2);
glColor3f(0.0, 1.0, 1.0);
glVertex2f(1.2, -0.2);
glColor3f(1.0, 1.0, 1.0);
glEnd();
}
void display(){
//Clear Window
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glTranslatef(posX,posY,posZ);
rect();
glPopMatrix();
glFlush();
}
void init(){
// 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);
//set up standard orthogonal view with clipping
//box as cube of side 2 centered at origin
//This is the default view and these statements could be removed
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
}
float move_unit = 10;
int deg = 0;
void keyboardown(int key, int x, int y)
{
switch (key){
case GLUT_KEY_RIGHT:
glRotatef((deg+=move_unit), posX, posY, posZ);;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
glRotatef(deg-=move_unit, posX, posY, posZ);;
break;
case GLUT_KEY_UP:
glRotatef(deg-=move_unit, posX, posY, posZ);;
break;
case GLUT_KEY_DOWN:
glRotatef(deg+=move_unit, posX, posY, posZ);;
break;
default:
break;
}
glutPostRedisplay();
}
int main(int argc, char** argv){
//initialize mode and open a windows in upper left corner of screen
//Windows tittle is name of program
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Move Test");
glutDisplayFunc(display);
init();
glutSpecialFunc(keyboardown);
glutMainLoop();
}
is there is something i did it wrong?
before, i tried to use the GLUT_KEY_ for moving 2d object and it worked, but when i change the command to glrotatef, it doesn't work.
have any suggestion?
The problem here is, that you override the matrix before it is used. In keyboardown the matrix is set, but at the begin of display the glLoadIdentity(); function is called, which resets the matrix and removes the rotation.
To solve this, you can, e.g., store the rotation angle in a variable. In keyboardown you increase/decrease the angle. When rendering in the display function, you reset the matrix as already done and then add the rotation by calling glRotatef with the previously stored angle.
I am trying to draw a solid cube in open GL to serve as a background of an interface button. The problem is, it is not being drawn on the screen at all. I have a class OGWindow that handles the drawing and a main class/method. I invoke all of the necessary methods from OGWindow in the main class. What am I doing wrong here?
This is my main class:
OGWindow theWindow;
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize( 1000, 600 );
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL Demo");
glEnable(GL_DEPTH_TEST); // enable the depth buffer test
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseMotion);
glutPassiveMotionFunc(mousePassiveMotion);
glutIdleFunc(Idle);
theWindow.initGL();
glutMainLoop();
}
void DrawGLScene(void) {
theWindow.myDrawGLScene();
}
This is my OGWindow class:
void OGWindow::initGL(void) {
glClearColor(1.0, 1.0, 1.0, 1.0);
squareX = 1.0;
squareY = 1.0;
squareWidth = 40.0;
squareHeight = 40.0;
squareColour = RED;
squareDraggingP = false;
}
void OGWindow::MyReSizeGLScene(int fwidth, int fheight)
{
// Store window size in class variables so it can be accessed in myDrawGLScene() if necessary
wWidth = fwidth;
wHeight = fheight;
// Calculate aspect ration of the OpenGL window
aspect_ratio = (float) fwidth / fheight;
// Set camera so it can see a square area of space running from 0 to 10
// in both X and Y directions, plus a bit of space around it.
Ymin = 0;
Xmin = 0;
Ymax = 600;
// Choose Xmax so that the aspect ration of the projection
// = the aspect ratio of the viewport
//Xmax = (aspect_ratio * (Ymax -Ymin)) + Xmin;
Xmax = 1000;
glMatrixMode(GL_PROJECTION); // Select The Projection Stack
glLoadIdentity();
glOrtho(Xmin, Xmax, Ymin, Ymax, -1.0, 1.0);
glViewport(0, 0, wWidth, wHeight); // Viewport fills the window
}
void OGWindow::myDrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the drawing area
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
OGWindow::myDrawModel();
glColor3f(0.0, 0.0, 0.0);
drawToolbar();
drawCreateButton();
glutSwapBuffers(); // Needed if we're running an animation
glFlush();
}
And this is the method that is suppose to draw a solid cube in the scene:
void OGWindow::drawCreateButton(GLvoid){
glPushMatrix();
glColor3f(0.0, 1.0, 0.0);
glTranslatef(10.0,30.0,0.0);
glutSolidCube(4);
glPopMatrix();
}
Sorry if i'm not answering your question, but it seems you're not using modern OpenGL, functions like glMatrixMode(GL_PROJECTION); and a lot more in your code should be avoided in modern applications.
Instead of glVertex() and glColor() you should use a VBO and a shader.
Here's a modern OpenGL tutorial wich is easy to follow: OpenGL tutorial for beginners
Here is my code that set a perspective view volume. The rectangle is displayed correctly.
I want to add a teapot to my scene now, so I add a line drawing a teapot after drawing the rectangle. But no teapot was displayed.
What params did I set wrong? What's the problem with my view and teapot?
GLint winWidth = 600, winHeight = 600; // Initial display-window size.
GLfloat x0 = 50.0, y0 = 50.0, z0 = 50.0; // Viewing-coordinate origin.
GLfloat xref = 50.0, yref = 50.0, zref = 0.0; // Look-at point.
GLfloat Vx = 0.0, Vy = 1.0, Vz = 0.0; // View-up vector.
/* Set coordinate limits for the clipping window: */
//GLfloat xwMin = -40.0, ywMin = -60.0, xwMax = 40.0, ywMax = 60.0;
GLfloat xwMin = -100.0, ywMin = -100.0, xwMax = 100.0, ywMax = 100.0;
/* Set positions for near and far clipping planes: */
GLfloat dnear = 25.0, dfar = 125.0;
void init (void)
{
glClearColor (1.0, 1.0, 1.0, 0.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
gluLookAt (x0, y0, z0, xref, yref, zref, Vx, Vy, Vz);
printf("look at orign:%.0f %.0f %.0f, pref: %.0f %.0f %.0f\n",x0, y0, z0, xref, yref, zref );
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glFrustum (xwMin, xwMax, ywMin, ywMax, dnear, dfar);
}
void displayFcn (void)
{
init ( );
glClear (GL_COLOR_BUFFER_BIT);
/* Set parameters for a square fill area. */
glColor3f (0.0, 1.0, 0.0); // Set fill color to green.
//glPolygonMode (GL_FRONT, GL_FILL);
glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode (GL_BACK, GL_LINE); // Wire-frame back face.
glBegin (GL_QUADS);
glVertex3f (0.0, 0.0, 0.0);
glVertex3f (100.0, 0.0, 0.0);
glVertex3f (100.0, 100.0, 0.0);
glVertex3f (0.0, 100.0, 0.0);
glEnd ( );
glutSolidTeapot(50.9);
glFlush ( );
}
void reshapeFcn (GLint newWidth, GLint newHeight)
{
glViewport (0, 0, newWidth, newHeight);
winWidth = newWidth;
winHeight = newHeight;
}
void keyboard(unsigned char key, int x, int y);
int main (int argc, char** argv)
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition (50, 50);
glutInitWindowSize (winWidth, winHeight);
glutCreateWindow ("Perspective View of A Square");
glutKeyboardFunc(keyboard);
glutDisplayFunc (displayFcn);
glutReshapeFunc (reshapeFcn);
glutMainLoop ( );
}
Your teapot is just totally off view.
You could place it inside the viewing volume like this:
glMatrixMode(GL_MODELVIEW);
glTranslatef(50.f, 50.f, 0.f);
glutSolidTeapot(50.9);
Also note that the field of view angle is insanely high for any normal viewing condition. Consider using the function gluPerspective instead of glFrustum to easily specify the angle, instead of manually having to specify the tangens of that angle scaled by the near plane distance as with glFrustum.
Also note that all of that is deprecated GL. Most of the functions you are using are removed from modern core profile contexts. If you start learning GL now, my advise is learning the new (well, 10 year old) way of using the programmable pipeline instead of the old (20 years) fixed-function pipeline with the builtin matrix stack.
I have a code where I want to draw a bowl and two cones at a time.
But, it is showing only those cones, not showing the ball.
#include <GL/glut.h>
#include <stdlib.h>
#include <Math.h> // Needed for sin, cos
#define PI 3.14159265f
GLfloat ballRadius = 0.5f; // Radius of the bouncing ball
GLfloat ballX = 0.0f; // Ball's center (x, y) position
GLfloat ballY = 0.0f;
GLfloat ballXMax, ballXMin, ballYMax, ballYMin; // Ball's center (x, y) bounds
GLfloat xSpeed = 0.02f; // Ball's speed in x and y directions
GLfloat ySpeed = 0.007f;
int refreshMillis = 30; // Refresh period in milliseconds
static void resize(int width, int height)
{
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
}
static void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// This is ball's code that is not being drawn.
***glTranslatef(ballX, ballY, 0.0f); // Translate to (xPos, yPos)
// Use triangular segments to form a circle
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0f, 0.0f, 0.0f); // Blue
glVertex2f(0.0f, 0.0f); // Center of circle
int numSegments = 100;
GLfloat angle;
for (int i = 0; i <= numSegments; i++) { // Last vertex same as first vertex
angle = i * 2.0f * PI / numSegments; // 360 deg for all segments
glVertex2f(cos(angle) * ballRadius, sin(angle) * ballRadius);
}
glEnd();***
//End of ball code
glColor3d(0,1,0);
glPushMatrix();
glTranslated(-1.0,0.5,-6);
glRotated(65, -1.0, 0.0, 0.0);
glutSolidCone(1, 2, 70, 50);
glPopMatrix();
glPushMatrix();
glTranslated(0.0,-1.5,-6);
glRotated(65, -1.0, 3.0, 0.0);
glutWireCone(1,2, 16, 16);
glPopMatrix();
glutSwapBuffers();
}
/* Program entry point */
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(740,580);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Programming Techniques - 3D Cones");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glClearColor(1,1,1,1);
glutMainLoop();
return EXIT_SUCCESS;
}
The reason you don't see the circle is that it's clipped against the near plane. With glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); you specify that the near plane is at z = -2, and the far plane at z = -100. Anything outside these values are clipped. But by using glVertex2, your z values for the circle vertices are 0, so all of them are clipped. You can fix it by calling glTranslatef(ballX, ballY, -10.0f); instead.
A couple more pointers:
Always reset the matrix mode to GL_MODELVIEW (e.g. in your resize() function). You don't have to, but it's a good convention.
Always glPush/PopMatrix() before modifying the matrix stack (e.g. when translating the circle).
glColor3f(1.0f, 0.0f, 0.0f); // Blue? ;)