This code almost works, but the problem is that it leaves behind the last control point like if it doesn't exist. I cannot find the error and I don't know why, I checked the transformation matrix and the converted control point many times but nothing
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include <math.h>
// Begin globals.
static int numVal = 0;
// Final control points.
static float controlPoints[4][3] =
{
{-30.0, 0.0, 0.0}, { -10.0, 20.0, 0.0},
{10.0, -20.0, 0.0}, {30.0, 0.0, 0.0}
};
//Matrix multiplication Mb^-1 * Mi
static float conversion[4][4] =
{
{1.0,0.0,0.0,0.0},{-0.8333,3.0,-1.5,0.3333},{0.3333,-1.5,3.0,-0.8333},{0.0,0.0,0.0,1.0}
};
//End globals
//Control point conversion for evaluator
void convertcp(float ctrlpoints[4][3]){
int i,j,k;
float tot = 0.0;
for(i = 0; i < 4;i++){
for(j = 0;j < 4;j++){
ctrlpoints[i][j] = 0;
for(k = 0; k < 3;k++){
ctrlpoints[i][j] += conversion[i][k] * controlPoints[k][j];
}
}
}
}
// End globals.
// Initialization routine.
void setup(void){glClearColor(1.0, 1.0, 1.0, 0.0);}
// Drawing routine.
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
int indx;
float ctrlpoints[4][3];
convertcp(ctrlpoints);
// Draw the control polygon in light gray.
glColor3f(0.7,0.7, 0.7);
glBegin(GL_LINE_STRIP);
for (indx = 0; indx < 4; indx++)
glVertex3fv(controlPoints[indx]);
glEnd();
// Specify and enable the Bezier curve.
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
// Draw the Bezier curve by defining a sample grid and evaluating on it.
glColor3f(0.0, 0.0, 0.0);
glMapGrid1f(100, 0.0, 1.0);
glEvalMesh1(GL_LINE, 0, 100);
// Draw the Bezier control points as dots.
glPointSize(5.0);
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POINTS);
for (indx = 0; indx < 4; indx++)
glVertex3fv(controlPoints[indx]);
glEnd();
// Highlight selected control point,
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POINTS);
glVertex3fv(controlPoints[numVal]);
glEnd();
glutSwapBuffers();
glutPostRedisplay();
}
// OpenGL window reshape routine.
void resize(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Keyboard input processing routine.
void keyInput(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
case ' ':
if (numVal < 3) numVal++;
else numVal = 0;
glutPostRedisplay();
break;
default:
break;
}
}
// Callback routine for non-ASCII key entry.
void specialKeyInput(int key, int x, int y)
{
if(key == GLUT_KEY_UP) controlPoints[numVal][2] += 1.0;
if(key == GLUT_KEY_DOWN) controlPoints[numVal][2] -= 1.0;
if(key == GLUT_KEY_LEFT) controlPoints[numVal][0] -= 1.0;
if(key == GLUT_KEY_RIGHT) controlPoints[numVal][0] += 1.0;
glutPostRedisplay();
}
// Routine to output interaction instructions to the console window.
void printInteraction(void)
{
printf("Interaction:\n");
printf("Press space to select a control point.\n");
printf("Press the arrow keys to move the selected control point.\n");
}
// Main routine.
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Interpolating Curves");
glutDisplayFunc(drawScene);
glutReshapeFunc(resize);
glutKeyboardFunc(keyInput);
glutSpecialFunc(specialKeyInput);
glewExperimental = GL_TRUE;
glewInit();
setup();
glutMainLoop();
}
Related
I'm trying to move the camera around the object I loaded, but for some reason the key presses are not working.
I took the relevant code from a previous project I was working on, which worked.
Can someone point me in the the right direction of why they are not working?
#include <math.h>
#include <stdio.h>
#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#elif __linux__
#include <GL/glut.h>
#endif
float camera_position_x = 0.0, camera_position_y = 0.1, camera_position_z = 0.2;
float line_of_sight_x = 0.0, line_of_sight_y = 0.2, line_of_sight_z = 0.0;
GLuint objObject;
char ch='1';
void InitGL (int width, int height) // We call this right after our OpenGL window is created.
{
glClearColor (255.0f, 255.0f, 255.0f, 0.0f); // This will clear the background color to white
glClearDepth (1.0); // Enables clearing of the depth buffer
glDepthFunc (GL_LESS); // The type of depth test to do
glEnable (GL_DEPTH_TEST); // Enables depth testing
glShadeModel (GL_SMOOTH); // Enables smooth color shading
glMatrixMode (GL_PROJECTION);
glLoadIdentity (); // Reset the projection matrix
gluPerspective (45.0f, (GLfloat) width / (GLfloat) height, 0.1f, 100.0f); // Calculate the aspect ratio of the window
glMatrixMode (GL_MODELVIEW);
}
void loadObj(char *fname)
{
FILE *fp;
int read;
GLfloat x, y, z;
char ch;
objObject=glGenLists(1);
fp=fopen(fname,"r");
if (!fp)
{
printf("can't open file %s\n", fname);
exit(1);
}
glPointSize(2.0);
glNewList(objObject, GL_COMPILE);
{
glPushMatrix();
glBegin(GL_POINTS);
while(!(feof(fp)))
{
read=fscanf(fp,"%c %f %f %f",&ch,&x,&y,&z);
if(read==4&&ch=='v')
{
glVertex3f(x,y,z);
}
}
glEnd();
}
glPopMatrix();
glEndList();
fclose(fp);
}
void ReSizeGLScene (int width, int height)
{
if (height == 0) // Prevent A Divide By Zero If The Window Is Too Small
{
height = 1;
}
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (90, (GLfloat)width / (GLfloat)height, 1.0, 200.0);
//gluLookAt(0.0, 0.1, 0.2, 0.0, 0.2, 0.0, 0.0, 0.0, 1.0);
gluLookAt(camera_position_x, camera_position_y, camera_position_z,
line_of_sight_x, line_of_sight_y, line_of_sight_z, 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
void drawobjObject()
{
glPushMatrix();
glTranslatef(0,-40.00,-105);
glColor3f(1.0,0.23,0.27);
glScalef(600,600,600);
glCallList(objObject);
glPopMatrix();
}
void display(void)
{
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
drawobjObject();
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y) {
switch(key)
{
case 'a':
line_of_sight_y += 3.0f;
camera_position_y += 3.0f;
break;
case 'z':
line_of_sight_y -= 3.0f;
camera_position_y -= 3.0f;
break;
default: break;
}
}
void arrowkey(int key, int x, int y) {
switch(key) {
case GLUT_KEY_UP :
line_of_sight_z += 3.0f;
camera_position_z += 3.0f;
break;
case GLUT_KEY_DOWN :
line_of_sight_z -= 3.0f;
camera_position_z -= 3.0f;
break;
case GLUT_KEY_LEFT :
line_of_sight_x += 3.0f;
camera_position_x += 3.0f;
break;
case GLUT_KEY_RIGHT:
line_of_sight_x -= 3.0f;
camera_position_x -= 3.0f;
break;
}
}
int main(int argc,char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(800,450);
glutInitWindowPosition(20,20);
glutCreateWindow("ObjLoader");
glutReshapeFunc(ReSizeGLScene);
glutDisplayFunc(display);
glutIdleFunc(display);
glutKeyboardFunc(keyboard);
glutSpecialFunc(arrowkey);
loadObj("bunny.obj");
glutMainLoop();
return 0;
}
As far as I can tell, the desired change of geometry only happens when ReSizeGLScene() is called; because the keyboard callbacks only change variables. And the variables in turn only are accessed inside ReSizeGLScene().
So the change might only be observable when pressing one of the buttons and then e.g. stretch the window a little.
I expect that a solution would be to call ReSizeGLScene() from both keyboard callbacks, using previously stored values for height and width.
But you probably want to optimise that and do the gluLookAt() separately, to be triggered from the keyboard-callbacks and from the resizer.
I'm working with OpenGL and I want to drag a cube with glutmotionfunc. I didn't finish at all, I don't know how to configure my views and I don't know what's wrong.
#include <GL/gl.h>
#include <GL/glut.h>
double rotate_y=0;
double rotate_x=0;
double rotate_z=0;
GLfloat X = 0.0f;
GLfloat Y = 0.0f;
GLfloat Z = 0.0f;
GLfloat scale = 1.0f;
float ancho=800;
float alto=600;
int perspectiva = 0;
float rx, ry;
void motion(int x, int y) // this is my motion function
// called when a mouse is in motion with a button down
{
printf("YYYMotion call back: %d, %d)\n", x, y);
rx = x;
ry = alto - y;
}
void display()
{
// Borrar pantalla y Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Resetear transformaciones
glLoadIdentity();
gluLookAt(1.0, 2.0, 50.0, //eye (x,y,z)
0.0, 0.0, 0.0, //at(x,y,z)
0.0, 1.0, 0.0); //up (x,y,z)
glScalef(scale, scale, scale);
glTranslatef((rx/ancho), (1-(ry/alto)), 0);
glFlush();
glutSwapBuffers();
}
void menu(int valor)
{
switch(valor)
{
case 1:
glutWireTorus(0.5,2.0,20,20);
break;
case 2:
glutWireTeapot(1.0);
break;
case 3:
glutWireSphere(0.8,50,50);
break;
case 4:
glutWireCube(1.0f);
break;
case 5:
glutWireIcosahedron();
break;
case 6:
glutWireOctahedron();
break;
case 7:
glutWireTetrahedron();
break;
case 8:
glutWireCone(0.5,1,5,5);
break;
case 9:
exit(1);
break;
}
}
void menu_opciones(void)
{
glutCreateMenu(menu);
glutAddMenuEntry("Torus",1);
glutAddMenuEntry("Tetera",2);
glutAddMenuEntry("Esfera",3);
glutAddMenuEntry("Cubo",4);
glutAddMenuEntry("Icosaedro",5);
glutAddMenuEntry("Octaedro",6);
glutAddMenuEntry("Tetraedro",7);
glutAddMenuEntry("Cono",8);
glutAddMenuEntry("Salir",9);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
void init()
{
glClearColor(0,0,0,0);
// Habilitar la prueba de profundidad de Z-buffer
glEnable(GL_DEPTH_TEST);
ancho = 800;
alto = 600;
}
void reshape(int w, int h)
{
glViewport(0, 0, w,h);
glMatrixMode(GL_PROJECTION);
menu_opciones();
glLoadIdentity();
//gluPerspective(80.0f, (GLfloat)w/(GLfloat)h, 0.2f, 30.0f);
//glOrtho(-2,2, -2, 2, 1, 10);
//glOrtho(-2, 2, -2, 2, -2, 2);
glFrustum (-1.0, 1.0, -1.0, 1.0, 2.5, 50.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char* argv[])
{
// Inicializar los parĂ¡metros GLUT y de usuario proceso
glutInit(&argc,argv);
// Solicitar ventana con color real y doble buffer con Z-buffer
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize (800, 600);
glutInitWindowSize(ancho, alto);
// Crear ventana
glutCreateWindow("");
init();
// Funciones de retrollamada
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMotionFunc( motion);
//glutKeyboardFunc(keyboard);
//glutSpecialFunc(specialKeys);
// Pasar el control de eventos a GLUT
glutMainLoop();
// Regresar al sistema operativo
return 0;
}
Where do you actually draw things? Something is missing:
void display()
{
// Borrar pantalla y Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Resetear transformaciones
glLoadIdentity();
gluLookAt(1.0, 2.0, 50.0, //eye (x,y,z)
0.0, 0.0, 0.0, //at(x,y,z)
0.0, 1.0, 0.0); //up (x,y,z)
glScalef(scale, scale, scale);
glTranslatef((rx/ancho), (1-(ry/alto)), 0);
/* where are things actually drawn? <<<<<<<<<<<<<<<<< */
glFlush();
glutSwapBuffers();
}
OpenGL is a drawing API, not a scene graph. When you call OpenGL drawing functions, all it does is drawing points, lines or triangles to a framebuffer. One at a time each on its own. There is no such thing as "adding a model to a scene" in OpenGL. Son in your drawing code you actually have to draw something, to see something. And if something changes in your scene you have to redraw (everything).
I am trying to make a Chaos Game in c using OpenGL and for some reason I am only creating a triangle and one point right now, when I am expecting to get 60,000 points. I think that this is because of the begin and end statements being inside of a for loop, and if not, then I'm not sure what is wrong. Any help solving the problem would be appreciated!
BTW the chaos game is where you start with one point, and then choose a random point on the triangle and then place a new point halfway between the chosen point and the original point and continue, and in my case I will repeat this 60,000 times. :)
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT); //clears all pixels
int choice, i;
float x = 0.15, y = 0.85;
glColor3f (0.0, 0.0, 0.0); //this sets the drawing color to black
glBegin(GL_LINE_LOOP); //The triangle
glVertex3f(0.2, 0.2, 0.0);
glVertex3f(0.5, 0.8, 0.0);
glVertex3f(0.8, 0.2, 0.0);
glVertex3f(0.2, 0.2, 0.0);
glEnd();
glPointSize(3.0); //sets point size
glBegin(GL_POINTS); //this is the original point
glVertex3f(x, y, 0.0);
glEnd();
for(i=0; i<60,000; i++)
{
choice = (rand()%3);
switch(choice)
{
case 0:
x = (x + 0.5)/2; //this is the x1+x2/2 part of the midpoint theorem
y = (y + 0.8)/2; //this is the y1+y2/2 part of the midpoint theorem
glBegin(GL_POINTS);
glVertex3f(x, y, 0.0);
glEnd();
break;
case 1:
x = (x + 0.8)/2;
y = (y + 0.2)/2;
glBegin(GL_POINTS);
glVertex3f(x, y, 0.0);
glEnd();
break;
case 2:
x = (x + 0.2)/2;
y = (y + 0.2)/2;
glBegin(GL_POINTS);
glVertex3f(x, y, 0.0);
glEnd();
default:
break;
}
}
glFlush ();
}
void init (void)
{
glClearColor (1.0, 1.0, 1.0, 0.0); //this sets the background color to white
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (250, 250);
glutInitWindowPosition (100, 100);
glutCreateWindow(argv[0]);
init ();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Try replacing 60,000 with 60000. In C, 60,000 evaluates to 0.
For more on the comma operator, see the Wikipedia entry on it.
How is the reshape() function working in this code and how is it getting its parameter from glutReshapeFunc(reshape) without any parameter in reshape of glutReshapeFunc(reshape)?
What is the value of int x, int y in void keyboard (unsigned char key, int x, int y) function?
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
static int year = 0, day = 0;
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glPushMatrix();
glutWireSphere(1.0, 20, 16); /* draw sun */
glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);
glTranslatef (2.0, 0.0, 0.0);
glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);
glutWireSphere(0.2, 10, 8); /* draw smaller planet */
glPopMatrix();
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void keyboard (unsigned char key, int x, int y)
{
switch (key) {
case `d':
day = (day + 10) % 360;
glutPostRedisplay();
break;
case `D':
day = (day - 10) % 360;
glutPostRedisplay();
break;
case `y':
year = (year + 5) % 360;
glutPostRedisplay();
break;
case `Y':
year = (year - 5) % 360;
glutPostRedisplay();
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
It appears that the glutReshapeFunc() function takes a pointer to a function; presumably, in fact, it is declared as something somewhat similar to:
void glutReshapeFunc(void (*function)(int x, int y));
Similarly, glutDisplayFunc() takes another pointer to a function, and glutKeyboardFunc() also takes a pointer to a function. When a function is specified by name without the function call parentheses after it, it reduces to 'pointer to a function' (or you can think of a bare function name as a pointer to the function body, like a bare array name is a pointer to the start of the array).
You'd have to read the manual to discover the purpose of the x and y parameters to the keyboard() function. They aren't used by the code shown. They are likely the position of something, but which something is less than clear without reading the manual.
reshape and keyboard functions are used as so called callbacks. You're giving GLUT pointers to those functions, GLUT keeps those pointers and calls those function, with parameters, at the times as specified in the GLUT documentation.
About like that:
void (*display_callback)(void);
void (*reshape_callback)(int, int);
void (*keyboard_callback(unsigned char, int, int);
/* ... */
void eventloop(...)
{
while(...) {
if( keyboard_event )
keyboard_callback(keyboard_event->key, mouse_x, mouse_y);
if( window_reshaped )
reshape_callback(window->width, window->height);
if( needs_redraw )
display_callback();
}
}
Now regarding what's done in the reshape callback: Everything that's placed there in beginner tutorials is actually much better done in the display function. Setting the viewport, setting the projection I mean. Later you'll probably want to draw a HUD, some text or a minimap, or a split view. And once you've reached that point, a reshape function doing viewport and projection setup becomes a liability. So get rid of it now.
void display(void)
{
int const w = glutGet(GLUT_WINDOW_WIDTH);
int const h = glutGet(GLUT_WINDOW_HEIGHT);
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
glutWireSphere(1.0, 20, 16); /* draw sun */
glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);
glTranslatef (2.0, 0.0, 0.0);
glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);
glutWireSphere(0.2, 10, 8); /* draw smaller planet */
glPopMatrix();
glutSwapBuffers();
}
I hope this will be a direct answer to this question.
The reshape function is a call back function which is called whenever size or shape of the application window changes. Reshape function takes 2 arguments,they are width and height of reshaped window. Mainly these parameters are used to set a new viewport.
I've created a program to display a lined cube on a white canvas but I am unsure how to multiple that cube into lets say? 10 x 10.
Another question is how would I go about creating the same cube in a 3D space?
Here's my code:
void drawScene(void)
{
int i, j;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glLoadIdentity();
glTranslatef(0.0, 0.0, -25.0);
glutWireCube(5.0); // Box.
glColor3f(1.0, 0.0, 0.0);
for(i=5; i<5; i++)
{
for (j = -5; j < 5; j++)
{
glPushMatrix();
glTranslatef(i*5, j*5, -35.0);
glColor3f(1.0, 1.0, 0);
glutSolidCube(5.0);
glColor3f(0.0, 0.0, 1.0);
glutWireCube(5.0);
glPopMatrix();
}
}
glFlush();
}
void setup(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
}
void resize (int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-10.0, 10.0, -10.0, 10.0, 10.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
void KeyInput(unsigned char key, int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500); /* Size of the Program Window */
glutInitWindowPosition(100,100);
glutCreateWindow("Box.cpp");
setup();
glutDisplayFunc(drawScene);
glutReshapeFunc(resize);
glutKeyboardFunc(KeyInput);
glutMainLoop();
return 0;
}
The glu library has a lot of useful tidbits like gluLookAt( xfrom, yfrom, zfrom, xto, yto, zto, xup, yup, zup );
You can scale things using glScaled( factor ) / glScalef( factor )
You should poke around Google for some GL 1.X documentation.