Related
i wanna make a small app that allow me to move the triangle to top/bottm left/right.
and when i press w -> rotate above and move above , s => rotate bottom and move bottom ,, d -> rotate right and moves right , a -> rotate left and move left ..
here is my code :
#include <GL/glut.h> // (or others, depending on the system in use)
float xpoint1 = 0.0f;
float xpoint2 = 50.0f;
float xpoint3 = 25.0f;
float ypoint1 = 0.0f, ypoint2 = 0.0f, ypoint3 = 20.0f;
double direction = 0.0;
void Keys(unsigned char key, int x, int y) {
if (key == 'a') {
if (xpoint1 != 0) {
xpoint1 -= 1.0f;
xpoint2 -= 1.0f;
xpoint3 -= 1.0f;
direction = 90.0;
}
}
else if (key == 'd') {
if (xpoint2 != 200) {
xpoint1 += 1.0f;
xpoint2 += 1.0f;
xpoint3 += 1.0f;
direction = 270.0;
}
}
else if (key == 'w') {
if (ypoint3 != 150) {
ypoint1 += 1.0f;
ypoint2 += 1.0f;
ypoint3 += 1.0f;
direction = 0.0;
}
}
else if (key == 's') {
if (ypoint3 != 0) {
ypoint1 -= 1.0f;
ypoint2 -= 1.0f;
ypoint3 -= 1.0f;
direction = 180.0;
}
}
glutPostRedisplay();
}
void resizeChange(int w, int h) {
glClearColor(1.0, 1.0, 1.0, 0.0); // Set display-window color to white.
glMatrixMode(GL_PROJECTION); // Set projection parameters.
glLoadIdentity();
gluOrtho2D(0.0, 200.0, 0.0, 150.0);
glViewport(0, 0, w, h);
glMatrixMode(GL_MODELVIEW);
}
void lineSegment(void)
{
glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
glColor3f(0.0, 0.4, 0.2); // Set line segment color to green.
//gluLookAt(0.0, 0.0, 5.0,
// 0.0, 0.0,0.0,
// 0.0, 1.0, 0.0
//);
glLoadIdentity();
glRotated(direction, 0.0, 0.0, 1.0);
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(xpoint1, ypoint1);
glColor3f(0.0, 1.0, 0.0);
glVertex2f(xpoint2, ypoint2);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(xpoint3, ypoint3);
glEnd();
//degree += 1.0;
glFlush(); // Process all OpenGL routines as quickly as possible.
//glutSwapBuffers();
}
void main(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // Set display mode.
glutInitWindowPosition(50, 100); // Set top-left display-window position.
glutInitWindowSize(600, 600); // Set display-window width and height.
glutCreateWindow("An Example OpenGL Program"); // Create display window.
glutDisplayFunc(lineSegment); // Send graphics to display window.
glutReshapeFunc(resizeChange);
//glutIdleFunc(lineSegment);
glutKeyboardFunc(Keys);
glutMainLoop(); // Display everything and wait.
}
the problem is when i try to change direction of the triangle it disappered ?! , whats the problem ?!
glRotated rotates around (0, 0). Actually rotate the triangle out of sight. You have to rotate the triangle first and then move it to its place in the world.
Do not change the vertex coordinates but add a translation matrix with glTranslate:
double tx = 0.0, ty = 0.0;
double direction = 0.0;
void Keys(unsigned char key, int x, int y)
{
if (key == 'a') {
tx -= 1.0;
direction = 90.0;
}
else if (key == 'd') {
tx += 1.0;
direction = 270.0;
}
else if (key == 'w') {
ty += 1.0;
direction = 0.0;
}
else if (key == 's') {
ty -= 1.0;
direction = 180.0;
}
glutPostRedisplay();
}
void lineSegment(void)
{
// [...]
glTranslated(tx, ty, 0.0);
glRotated(direction, 0.0, 0.0, 1.0);
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(-25.0, 0.0);
glColor3f(0.0, 1.0, 0.0);
glVertex2f(25.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(0.0, 20.0);
glEnd();
// [...]
}
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)
{
// [...]
}
I am working on a project for mouse control to look around. I have been successful with rotating the camera using the mouse however I am trying to get the mouse to do 360 turns without the mouse leaving the screen before it can fully rotate. I read around and came across glutWarpPointer(), where most posts said to use it after getting the difference between the centre and the new mouse position in the window.
The issue this causes with my program is that when I move the mouse it will rotate very slightly for that frame the restart the location to the original point. Basically it i have a blue ball in front of me and green behind when i try to rotate towards the green ball the camera will move slightly but stay locked on the blue ball.
Is there a way to around or a fix?
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//rotate and translating the camera
glRotatef(-camVert, 1.0, 0.0, 0.0);
glRotatef(-camHor, 0.0, 1.0, 0.0);
glTranslatef(-posx,-posy,-posz);
//blue and green ball
glPushMatrix();
glColor3f(0.0, 1.0, 0.0);
glTranslatef(1, 0, 25);
glutSolidSphere(5, 20, 20);
glPopMatrix();
glPushMatrix();
glColor3f(0.0,0.0,1.0);
glTranslatef(0, 0, -25);
glutSolidSphere(5, 20, 20);
glPopMatrix();
};
void setAngle(float angy, float angx)
{
camVert = angy*1.5;
if (camVert > 90)
camVert = 90;
else if (camVert < -90)
camVert = -90;
camHor = angx*0.5;
}
void MoveCam(float distance, float direction)
{
float rads = (camHor+direction)*PI / 180;
posx -= sin(rads)*distance;
posz -= cos(rads)*distance;
};
void mouseMove(int x, int y)
{
float diffx = midx - x;
float diffy = midy - y;
setAngle(diffy,diffx);
//glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
}
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 have the following mouse event on QGLWidget class ...
void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
QPointF mousePosition = event->pos();
float dx = event->x() - lastPos.x();
float dy = event->y() - lastPos.y();
if (event->buttons() & Qt::LeftButton) {
setXRotation(xRot + 8.0 * dy);
setYRotation(yRot + 8.0 * dx);
} else if (event->buttons() & Qt::RightButton) {
xTrans += dx;
yTrans -= dy;
}
lastPos = event->pos();
}
Rotation in paint GL is working but not translation.. What am I doing wrong... ?
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(0.0, 0.0, -5.0);
glRotatef(xRot / 16.0, 1.0, 0.0, 0.0);
glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);
glTranslatef(xTrans, yTrans, 0.0f);
glScalef(scale, scale, scale);
//draw function here
glPopMatrix();
}
You have to pop the matrix for it to get it applied.
http://www.swiftless.com/tutorials/opengl/pop_and_push_matrices.html
That allows for the pushed matrix to actually finish calculating and get used.
glPopMatrix(); //end the current object transformations
Hope that helps.