I have a small program using glut and i need for many reasons to use glfw now. Since I have never used glfw I have a lot of problems.
The main ones are the functions : glutDisplayFunc, glutReshapeFunc, glutIdleFunc and glutMainLoop. I have just found out that there are no equivalent functions in glfw. How should I modify my program ?
My program is about a cone rotating in 3 dimensions
I have a function displaycone:
void displayCone(void){
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT); //
// set matrix mode
glMatrixMode(GL_MODELVIEW);
// clear model view matrix
glLoadIdentity();
// multiply view matrix to current matrix
gluLookAt(3.0, 3.0, 3.0-4.5, 0.0, 0.0,-4.5,0,1,0);
// ******
glPushMatrix();
glTranslatef(0.0, 0.0, -4.5);
glBegin(GL_LINES);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(2.0, 0.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 2.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 2.0);
glEnd();
glPopMatrix();
// clear the drawing buffer.
// traslate the draw by z = -4.0
// Note this when you decrease z like -8.0 the drawing will looks far , or smaller.
glTranslatef(0.0,0.0,-4.5);
// Red color used to draw.
glColor3f(0.8, 0.2, 0.1);
// changing in transformation matrix.
// rotation about X axis
glRotatef(xRotated,1.0,0.0,0.0);
// rotation about Y axis
glRotatef(yRotated,0.0,1.0,0.0);
// rotation about Z axis
glRotatef(zRotated,0.0,0.0,1.0);
// scaling transfomation
glScalef(1.0,1.0,1.0);
// built-in (glut library) function , draw you a Cone.
// move the peak of the cone to the origin
glTranslatef(0.0, 0.0, -height);
glutSolidCone(base,height,slices,stacks);
// Flush buffers to screen
// gluLookAt(3,3,3,0,0,-4.5,0,1,0); <----------------------- delete
glFlush();
// sawp buffers called because we are using double buffering
// glutSwapBuffers();
}
a function reshapecone:
void reshapeCone(int x, int y)
{
if (y == 0 || x == 0) return; //Nothing is visible then, so return
//Set a new projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//Angle of view:40 degrees
//Near clipping plane distance: 0.5
//Far clipping plane distance: 20.0
gluPerspective(35.0,(GLdouble)x/(GLdouble)y,0.5,20.0);
glViewport(0,0,x,y); //Use the whole window for rendering
}
and a function idleCone:
void idleCone(void)
{
for(int j = 1; j<10000 ; j++){
double i = dati[j+1][0];
int win = glfwGetWindow();
if(i == 0.) break;
xRotated = 180/M_PI*(dati[j][0]);
yRotated = 180/M_PI*(dati[j][1]);
zRotated = 180/M_PI*(dati[j][2]);
displayCone();
xRotated += 0.;
yRotated += 0.;
zRotated += 0.;
displayCone();
}
}
In my previous program i had in main:
glfwInit(&argc, argv);
//double buffering used to avoid flickering problem in animation
glutInitDisplayMode(GLUT_SINGLE | GL_RGB);
//glfwInitWindowSize(800,700);
glfwCreateWindow(800,700,"Rotation of the top",NULL,NULL);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
xRotated = yRotated = zRotated = 0.0;
xRotated=0.0;
yRotated=0.0;
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(displayCone);
glutReshapeFunc(reshapeCone);
glutIdleFunc(idleCone);
glutMainLoop();
When using glfw, then you've to create your own application loop. Note, it is important to to make the OpenGL context current, before calling any OpenGL instruction, by glfwMakeContextCurrent. e.g.:
GLFWwindow *wnd = glfwCreateWindow(800,700,"Rotation of the top",NULL,NULL);
glfwMakeContextCurrent(wnd);
// do the OpenGL initialization
// [...]
while (!glfwWindowShouldClose(wnd))
{
// do the drawing
displayCone();
glfwSwapBuffers(wnd);
glfwPollEvents();
}
Instead of glutReshapeFunc you can set the size callback by glfwSetWindowSizeCallback: e.g.:
glfwSetWindowSizeCallback(wnd, reshapeCone);
void reshapeCone(GLFWwindow* window, int x, int y)
{
// [...]
}
Related
First of all, let me tell i am quite new using OpenGL and C++. However, i want to get involved with this two topics.
So let me explain my case, ive been searching how to get the new coordinates of an object after glTrasnlatef and glRotatef were applied. However, i did not find the find info, actually i found some info about java but i am not getting it, as i told you i am working with C++.
I read there is something to deal with the glPushMatrix(); function but idont know how to handle it.
I know that after applying some trnaslation and rotation i am doing changes into the actual matrix.
Finally, the main purpose of this is because ill use those vertices from the rombohedrom and do a lot of translations and rotations, those are going to be needed as well.
So far this is my code (BTW i am working with lines and the vertices of course because i only need those).
i will really appreciate if someone can address me through the right path.
Thanks in advance
Alberto
#include <GL/glut.h>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
// Global variables
double rotate_y=0;
double rotate_x=0;
int width = 640;
int height = 640;
#define PI 3.14159265
float theta = 60;
float edgeLength = 1;
float sinThetaOverHypotenuse = (sin((theta*PI)/180))/edgeLength;
vector<vector<float>> coordinates{{0.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{1.5, sinThetaOverHypotenuse, 0.0},
{1.5, sinThetaOverHypotenuse, 0.0},
{0.5, sinThetaOverHypotenuse, 0},
{0.5, sinThetaOverHypotenuse, 0},
{0.0, 0.0, 0.0}};
void rhombohedrom()
{
vector<vector<float>> rotated {};
// glClearColor(1,1,0,0)
// Clear screen and Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
glOrtho( -1 * w, 1 * w, -1 * h, 1 * h, 10, -10);
glMatrixMode( GL_MODELVIEW );
// Reset transformations
glLoadIdentity();
// Rotate when user changes rotate_x and rotate_y
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );
/*
FACE 0
FACE 0
FACE 0
FACE 0
*/
// random color side - front
glBegin(GL_LINE_LOOP);
glColor3f( 0.7, 0.3, 0.8 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
/*
FACE 1
FACE 1
FACE 1
FACE 1
*/
glPushMatrix();
glTranslatef(0.0,0.0,0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glColor3f( 1.0, 1.0, 1.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
/*
FACE 2
FACE 2
FACE 2
FACE 2
*/
glPushMatrix();
glTranslatef(0.5,0.0,sinThetaOverHypotenuse);
glBegin(GL_LINE_LOOP);
glColor3f( 0.5, 0.5, 0.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
/*
FACE 3
FACE 3
FACE 3
FACE 3
*/
glPushMatrix();
glTranslatef(0.5,sinThetaOverHypotenuse,0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glColor3f( 0.5, 0.0, 0.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void specialKeys(int key, int x, int y)
{
// Right arrow - increase rotation by 5 degree
if (key == GLUT_KEY_RIGHT)
rotate_y += 5;
// Left arrow - decrease rotation by 5 degree
else if (key == GLUT_KEY_LEFT)
rotate_y -= 5;
else if (key == GLUT_KEY_UP)
rotate_x += 5;
else if (key == GLUT_KEY_DOWN)
rotate_x -= 5;
// Request display update
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
// Initialize GLUT and process user parameters
glutInit(&argc,argv);
glutInitWindowSize(width,height);
// Position of the window
glutInitWindowPosition(10,10);
// Request double buffered true color window with Z-buffer
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
// Create window
glutCreateWindow("rhombohedrom");
// Enable Z-buffer depth test
glEnable(GL_DEPTH_TEST);
// Callback functions
glutDisplayFunc(rhombohedrom);
glutSpecialFunc(specialKeys);
//
glutMainLoop();
return 0;
}
First, I want to address some remarks such as:
glPushMatrix() is an old way, try to use the MVP technique which will help you solving your problem. So, you have to write your Vertex Shader and pass the Matrices through what called uniform in OpenGL. Obviously, you have to use new Routines.
glPopMatrix() is also an old routine.
I'm happy to answer your further questions if you want to know more about those remarks.
Use Vertex Shader instead of simple calculus using the CPU!
you can change glTranslatef() and glRotatef() by lookAt so you can change the scale, rotation and translation.
Use Vertex Shader instead of using or stressing the CPU by graphic calculus. Even if you have an Intel integrated GPU
I am trying to close an OpenGL's window in a program compile with g++-9 -framework GLUT -framework OpenGL in the Terminal of a MacOS Mojave 10.14.5
I tried using glutDestroyWindow() but i get a warnign :
GLUT Warning: glutDestroyWindow attempted on bogus window 0
I have a cone that is rotating and implements its rotattion from an array of datas. I would want the animation to stop as soon as the array finishes its elements.
void idleCone(void)
{
for(int j = 1; j<10000 ; j++){
double i = dati[j+1][0];
int win = glutGetWindow();
if(i == 0.) { glutDestroyWindow(win);
}
xRotated = 180/M_PI*(dati[j][0]);
yRotated = 180/M_PI*(dati[j][1]);
zRotated = 180/M_PI*(dati[j][2]);
displayCone();
xRotated += 0.;
yRotated += 0.;
zRotated += 0.;
displayCone();
}}
where dati is :
std::vector<std::array<GLfloat, 3>> &dati
In main I have
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
xRotated = yRotated = zRotated = 0.0;
xRotated=0.0;
yRotated=0.0;
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(displayCone);
glutReshapeFunc(reshapeCone);
glutIdleFunc(idleCone);
glutMainLoop();
where this is displayCone function
void displayCone(void){
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT); //
// set matrix mode
glMatrixMode(GL_MODELVIEW);
// clear model view matrix
glLoadIdentity();
// multiply view matrix to current matrix
gluLookAt(3.0, 3.0, 3.0-4.5, 0.0, 0.0,-4.5,0,1,0);
// ******
glPushMatrix();
glTranslatef(0.0, 0.0, -4.5);
glBegin(GL_LINES);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(2.0, 0.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 2.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 2.0);
glEnd();
glPopMatrix();
// clear the drawing buffer.
// glClear(GL_COLOR_BUFFER_BIT); // <---- delete
// traslate the draw by z = -4.0
// Note this when you decrease z like -8.0 the drawing will looks far , or smaller.
glTranslatef(0.0,0.0,-4.5);
// Red color used to draw.
glColor3f(0.8, 0.2, 0.1);
// changing in transformation matrix.
// rotation about X axis
glRotatef(xRotated,1.0,0.0,0.0);
// rotation about Y axis
glRotatef(yRotated,0.0,1.0,0.0);
// rotation about Z axis
glRotatef(zRotated,0.0,0.0,1.0);
// scaling transfomation
glScalef(1.0,1.0,1.0);
// built-in (glut library) function , draw you a Cone.
// move the peak of the cone to the origin
glTranslatef(0.0, 0.0, -height);
glutSolidCone(base,height,slices,stacks);
// Flush buffers to screen
// gluLookAt(3,3,3,0,0,-4.5,0,1,0); <----------------------- delete
glFlush();
// sawp buffers called because we are using double buffering
// glutSwapBuffers();
}
I also tried to use
exit(0)
but I would want the program to keep going after the animation.
I know that i should use something such as glutLeaveMainLoop() but i am still not able to do it since my Mac says
Undefined symbols for architecture x86_64:
"_glutLeaveMainLoop", referenced from:
idleCone() in ccnOmxBT.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
even if i included freeglut.h . Is there any way to compile from terminal including freeglut.h or closing the window successfully ?
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.
Hi I'm trying to implement a opengl program with rotation&translation. But I got this problem that, the world axes will rotating along with my object(a cube). It's like, first I rotate cube along Z-axis, it works fine, then I middle-click the mouse and want to rotate the cube along the original Y-axis. At the moment I click, the cube will stop rotating along Z and start to rotate along Y. But it turns out it will rotate along a "new and invisible" Y-axis. I figure out that's because when I rotate the cube along Z with glRotatef(), the other two axis:X,Y also rotate. How can I fix the axes when I'm rotating the cube. I know the glRotatef() will multiply all matrix in screen with a rotation axis, so I tried added a glLoadIdentity() in each rotation but it still not work. can anyone give me the solution?
the code is here for reference:
#include <stdlib.h>
#include <GL/glut.h>
#include <iostream>
GLfloat vertices[8][3] =
{ { -1.0, -1.0, -1.0 }, { 1.0, -1.0, -1.0 },
{ 1.0, 1.0, -1.0 }, { -1.0, 1.0, -1.0 }, { -1.0, -1.0, 1.0 },
{ 1.0, -1.0, 1.0 }, { 1.0, 1.0, 1.0 }, { -1.0, 1.0, 1.0 } };
GLuint listName;
GLfloat theta[3] = { 0.0, 0.0, 0.0 };
GLint axis = 2;
GLfloat delta = 0.02;
GLint stop = 0;
GLfloat distance = 0;
void face(int a, int b, int c, int d)
{
glBegin(GL_POLYGON);
//glColor3fv(colors[a]);
glVertex3fv(vertices[a]);
//glColor3fv(colors[b]);
glVertex3fv(vertices[b]);
//glColor3fv(colors[c]);
glVertex3fv(vertices[c]);
//glColor3fv(colors[d]);
glVertex3fv(vertices[d]);
glEnd();
}
void cube(void)
{
glColor3f(1.0f,1.0f,1.0f);
face(0, 3, 2, 1);
face(2, 3, 7, 6);
face(0, 4, 7, 3);
face(1, 2, 6, 5);
face(4, 5, 6, 7);
face(0, 1, 5, 4);
glutWireCube(2.5f);
glutPostRedisplay();
}
void drawAxis(void){
// save previous matrix
glPushMatrix();
// clear matrix
glLoadIdentity();
// draw our axes
glRotatef(45.0, 1.0, 0.0, 0.0);
glRotatef(45.0, 0.0, -1.0, 0.0);
glBegin(GL_LINES);
// draw line for x axis
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(10.0, 0.0, 0.0);
// draw line for y axis
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 10.0, 0.0);
// draw line for Z axis
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 10.0);
glEnd();
// load the previous matrix
glPopMatrix();
glutPostRedisplay();
}
void spinCube()
{
theta[axis] += delta;
if (theta[axis] > 360.0) theta[axis] -= 360.0;
glutPostRedisplay();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(45.0, 1.0, 0.0, 0.0);
glRotatef(45.0, 0.0, -1.0, 0.0);
drawAxis();
glPushMatrix();
glRotatef(theta[0], 1.0, 0.0, 0.0);
glRotatef(theta[1], 0.0, 1.0, 0.0);
glRotatef(theta[2], 0.0, 0.0, 1.0);
glTranslatef(0.0, 0.0, distance + 2.0);
glCallList(listName);
glPopMatrix();
glutSwapBuffers();
}
void myReshape(int w, int h)
{
GLfloat aspect = (GLfloat) w / (GLfloat) h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-10.0, 10.0, -10.0 / aspect, 10.0 / aspect, -50.0, 50.0);
else
glOrtho(-10.0*aspect, 10.0*aspect, -10.0, 10.0, -50.0, 50.0);
glMatrixMode(GL_MODELVIEW);
}
void mouse(int btn, int state, int x, int y)
{
if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { axis = 0;
}
if (btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) { axis = 1;
}
if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) { axis = 2;
}
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 'q' || key == 'Q') exit(0);
if (key == ' ') { stop = !stop; }
if (stop)
glutIdleFunc(NULL);
else
glutIdleFunc(spinCube);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
glutInitWindowSize(600, 600);
glutCreateWindow("cube");
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutIdleFunc(spinCube);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
//creating a display list:
listName = glGenLists(1);
glNewList(listName, GL_COMPILE);
cube();
glEndList();
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}
What you're after might be accumulating arbitrary rotations. This can't be done with euler angles, which gimbal lock. It's pretty common to have euler angle rotations and in most cases the issue is simply to do with the order they're applied in. The first thing I'd suggest is to reverse the order of your x/y/z rotations.
Next, if you want to accumulate rotations you'll really want to get into quaternions. This can be done with matrices but can easily become numerically unstable. Quaternions can be normalized which solves this issue.
If you rotate around X, the first call is of course, glRotatef(a, 1, 0, 0); draw(). Then you want to rotate the object and its current rotation around y. Note that the object and current rotation are grouped in this line of thinking. So you glRotatef(b, 0, 1, 0); glRotatef(a, 1, 0, 0); draw();. Each time you rotate, you add the rotation behind the existing list of transforms. If you added in front, it'd transform the object in its local space and not global. What you could do is this (near-pseudo-code with an imaginary matrix implementation):
Keep a current object transform matrix M
In spinCube, M = rotationMatrix(delta, axis==0?1:0, axis==1?1:0, axis==2?1:0) * M (note it's rotation * M and not M * rotation.
Before you draw the cube, glMultMatrixf(M.data)
The problem is floating point error will build up over time and the matrix will start to skew/scale your object in weird ways. Instead, you'll want a quaternion implementation (again near-pseudo-code):
Q = rotationQuaternion(delta, axis==0?1:0, axis==1?1:0, axis==2?1:0) * Q
Q.normalize()
...
glMultMatrixf(Q.toMatrix().data)
I've been experimenting with programs from my text book that involved clipping 2-D polygons using glOrtho and then creating glutWireSpheres in gluPerspective. My goal is to clip half the sphere with a plane, however, I am having trouble clipping 3-D objects. I created a toggle button to show the sphere clipped and unclipped, however, the button instead shows the sphere moving in a ellipse motion I believe.
Here is my drawscene for creating the sphere
double eqn0[4] = {1, 0, 0.0, -60}; // Data for clipping plane 0.
// Choose window.
glutSetWindow(id2);
gluLookAt(0.0, 3.0, 12.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glClipPlane(GL_CLIP_PLANE0, eqn0); // Specify clipping plane 0.
if (isClip0) glEnable(GL_CLIP_PLANE0); // Clip points s.t. z > 0.25.
else glDisable(GL_CLIP_PLANE0);
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glutWireSphere(1.0, 10, 10);
glPopMatrix();
glFlush();
And here is my toggle
case '0':
if (isClip0 == 0) isClip0 = 1;
else isClip0 = 0;
glutPostRedisplay();
break;
Can someone help me get in the right direction for clipping 3-D objects? Because this will work on 2-D polygons, yet when I try to apply it to spheres, the toggle button doesn't even act like a toggle.
EDIT: Full code:
#include <cmath>
#include <iostream>
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
#define PI 3.14159265
using namespace std;
// Globals.
static int id1, id2; // Window identifiers.
static int isClip0 = 0; // Is clipping plane 0 enabled?
static int isClip1 = 0; // Is clipping plane 1 enabled?
static int isClip3 = 0; // Is clipping plane 0 enabled?
static int isClip4 = 0; // Is clipping plane 1 enabled?
// Drawing routine for first window.
void drawScene1(void)
{
// Choose window.
glutSetWindow(id1);
glClear(GL_COLOR_BUFFER_BIT);
// A red square.
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(10.0, 10.0, 0.0);
glVertex3f(40.0, 10.0, 0.0);
glVertex3f(40.0, 40.0, 0.0);
glVertex3f(10.0, 40.0, 0.0);
glEnd();
glFlush();
}
// Drawing routine for second window.
void drawScene2(void)
{
double eqn0[4] = {1, 0, 0.0, -1000}; // Data for clipping plane 0.
// Choose window.
glutSetWindow(id2);
gluLookAt(0.0, 3.0, 12.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glClipPlane(GL_CLIP_PLANE0, eqn0); // Specify clipping plane 0.
if (isClip0) glEnable(GL_CLIP_PLANE0); // Clip points s.t. z > 0.25.
else glDisable(GL_CLIP_PLANE0);
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glutWireSphere(1.0, 10, 10);
glPopMatrix();
glFlush();
}
// Initialization routine for first window.
void setup1(void)
{
// Black background.
glClearColor(0.0, 0.0, 0.0, 0.0);
}
// Initialization routine for second window.
void setup2(void)
{
// Green background.
glClearColor(1.0, 1.0, 1.0, 0.0);
}
// Reshape routine for first window.
void resize1(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Non-square aspect ratio squashes the square.
glOrtho(0.0, 50.0, 0.0, 100.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Reshape routine for second window.
void resize2(int w, int h)
{
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (float)w/(float)h, 1.0, 50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Keyboard input processing routine shared by both windows.
void keyInput(unsigned char key, int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
case '0':
if (isClip0 == 0) isClip0 = 1;
else isClip0 = 0;
glutPostRedisplay();
break;
default:
break;
}
}
// Main routine.
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
// First top-level window definition.
glutInitWindowSize(250, 500);
glutInitWindowPosition(100, 100);
// Create the first window and return id.
id1 = glutCreateWindow("windows.cpp - window 1");
// Initialization, display, and other routines of the first window.
setup1();
glutDisplayFunc(drawScene1);
glutReshapeFunc(resize1);
glutKeyboardFunc(keyInput); // Routine is shared by both windows.
// Second top-level window definition.
glutInitWindowSize(250, 500);
glutInitWindowPosition(400, 100);
// Create the second window and return id.
id2 = glutCreateWindow("windows.cpp - window 2");
// Initialization, display, and other routines of the second window.
setup2();
glutDisplayFunc(drawScene2);
glutReshapeFunc(resize2);
glutKeyboardFunc(keyInput); // Routine is shared by both windows.
glutMainLoop();
return 0;
}
Sphere is dealt with in drawScene2
So, after adding a glLoadIdentity() right before the gluLookAt(), the movements will go away (as I already had suggested...). And when one sets a useful clip plane equation, the clipping works as expected, too. As you define a sphere with radius 1 around the object space center, setting
GLdouble eqn0[4] = {1, 0, 0.0, 0.5};
will result in the sphere being clipped at x=-0.5, so 3/4 of it is still visible, as one would expect.