Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links
Este ejemplo muestra como se puede manipular un objeto 3D, utilizando el mouse
para simular un Tracknall, esto me permite rotar el objeto en torno a un eje arbitrario
es decir el movimiento de rotacion no esta limitado a los ejes X, Y, Z.
Para rotar el objeto solo basta tener presionado el boton del medio del mouse y
arrastrar en la direccion de rotacion.
Codigo fuente y ejecutable trackball.zip
/* * Simple trackball-like motion adapted (ripped off) from projtex.c * (written by David Yu and David Blythe). See the SIGGRAPH '96 * Advanced OpenGL course notes. * * * Usage: * * o call gltbInit() in before any other gltb call * o call gltbReshape() from the reshape callback * o call gltbMatrix() to get the trackball matrix rotation * o call gltbStartMotion() to begin trackball movememt * o call gltbStopMotion() to stop trackball movememt * o call gltbMotion() from the motion callback * o call gltbAnimate(GL_TRUE) if you want the trackball to continue * spinning after the mouse button has been released * o call gltbAnimate(GL_FALSE) if you want the trackball to stop * spinning after the mouse button has been released * * Typical setup: * * void init(void) { gltbInit(GLUT_MIDDLE_BUTTON); gltbAnimate(GL_TRUE); . . . } void reshape(int width, int height) { gltbReshape(width, height); . . . } void display(void) { glPushMatrix(); gltbMatrix(); . . . draw the scene . . . glPopMatrix(); } void mouse(int button, int state, int x, int y) { gltbMouse(button, state, x, y); . . . } void motion(int x, int y) { gltbMotion(x, y); . . . } int main(int argc, char** argv) { . . . init(); glutReshapeFunc(reshape); glutDisplayFunc(display); glutMouseFunc(mouse); glutMotionFunc(motion); . . . } ***/ /* functions */ void gltbInit(GLuint button); void gltbMatrix(void); void gltbReshape(int width, int height); void gltbMouse(int button, int state, int x, int y); void gltbMotion(int x, int y); void gltbAnimate(GLboolean animate); |
/* * Simple trackball-like motion adapted (ripped off) from projtex.c * (written by David Yu and David Blythe). See the SIGGRAPH '96 * Advanced OpenGL course notes. */ #include <math.h> #include <stdio.h> #include <assert.h> #include <GL/glut.h> #include "trackball.h" #define GLTB_TIME_EPSILON 10 static GLuint gltb_lasttime; static GLfloat gltb_lastposition[3]; static GLfloat gltb_angle = 0.0; static GLfloat gltb_axis[3]; static GLfloat gltb_transform[4][4]; static GLuint gltb_width; static GLuint gltb_height; static GLint gltb_button = -1; static GLboolean gltb_tracking = GL_FALSE; static GLboolean gltb_animate = GL_TRUE; static void _gltbPointToVector(int x, int y, int width, int height, float v[3]) { float d, a; /* project x, y onto a hemi-sphere centered within width, height. */ v[0] = (2.0 * x - width) / width; v[1] = (height - 2.0 * y) / height; d = sqrt(v[0] * v[0] + v[1] * v[1]); v[2] = cos((3.14159265 / 2.0) * ((d < 1.0) ? d : 1.0)); a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); v[0] *= a; v[1] *= a; v[2] *= a; } static void _gltbAnimate(void) { glutPostRedisplay(); } void _gltbStartMotion(int x, int y, int button, int time) { assert(gltb_button != -1); gltb_tracking = GL_TRUE; gltb_lasttime = time; _gltbPointToVector(x, y, gltb_width, gltb_height, gltb_lastposition); } void _gltbStopMotion(int button, unsigned time) { assert(gltb_button != -1); gltb_tracking = GL_FALSE; if (time - gltb_lasttime < GLTB_TIME_EPSILON && gltb_animate) { glutIdleFunc(_gltbAnimate); } else { gltb_angle = 0; if (gltb_animate) glutIdleFunc(0); } } void gltbAnimate(GLboolean animate) { gltb_animate = animate; } void gltbInit(GLuint button) { gltb_button = button; gltb_angle = 0.0; /* put the identity in the trackball transform */ glPushMatrix(); glLoadIdentity(); glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)gltb_transform); glPopMatrix(); } void gltbMatrix(void) { assert(gltb_button != -1); glPushMatrix(); glLoadIdentity(); glRotatef(gltb_angle, gltb_axis[0], gltb_axis[1], gltb_axis[2]); glMultMatrixf((GLfloat*)gltb_transform); glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)gltb_transform); glPopMatrix(); glMultMatrixf((GLfloat*)gltb_transform); } void gltbReshape(int width, int height) { assert(gltb_button != -1); gltb_width = width; gltb_height = height; } void gltbMouse(int button, int state, int x, int y) { assert(gltb_button != -1); if (state == GLUT_DOWN && button == gltb_button) _gltbStartMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME)); else if (state == GLUT_UP && button == gltb_button) _gltbStopMotion(button, glutGet(GLUT_ELAPSED_TIME)); } void gltbMotion(int x, int y) { GLfloat current_position[3], dx, dy, dz; assert(gltb_button != -1); if (gltb_tracking == GL_FALSE) return; _gltbPointToVector(x, y, gltb_width, gltb_height, current_position); /* calculate the angle to rotate by (directly proportional to the length of the mouse movement) */ dx = current_position[0] - gltb_lastposition[0]; dy = current_position[1] - gltb_lastposition[1]; dz = current_position[2] - gltb_lastposition[2]; gltb_angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz); /* calculate the axis of rotation (cross product) */ gltb_axis[0] = gltb_lastposition[1] * current_position[2] - gltb_lastposition[2] * current_position[1]; gltb_axis[1] = gltb_lastposition[2] * current_position[0] - gltb_lastposition[0] * current_position[2]; gltb_axis[2] = gltb_lastposition[0] * current_position[1] - gltb_lastposition[1] * current_position[0]; /* XXX - constrain motion */ gltb_axis[2] = 0; /* reset for next time */ gltb_lasttime = glutGet(GLUT_ELAPSED_TIME); gltb_lastposition[0] = current_position[0]; gltb_lastposition[1] = current_position[1]; gltb_lastposition[2] = current_position[2]; /* remember to draw new position */ glutPostRedisplay(); } |
/* Este programa permite simular el movimiento de un trackball, utilizando el mouse, la ventaja es que puedo rotar el modelo en torno a un eje arbitrario. El codigo del manipulador es una daptacion projtex.c (written by David Yu and David Blythe), SIGGRAPH '96 Advanced OpenGL course notes. autor: Ramiro Alcocer email: valcoey@hotmail.com www : www.oocities.org/valcoey/index.html */ #include <GL/glut.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> //------ trackball---------- #include "trackball.h" //implementacion del Trackball //-------------------------- //------ Trackball ------------ static GLint mouse_state; static GLint mouse_button; GLdouble pan_x = 0.0; GLdouble pan_y = 0.0; GLdouble pan_z = 0.0; //----------------------------- //parametros de la fuente de luz float LightPos[] = { 0.0f, 0.0f, 1.0f, 0.0f}; float LightAmb[] = { 0.5f, 0.5f, 0.5f, 1.0f}; float LightDif[] = { 1.0f, 1.0f, 1.0f, 1.0f}; float LightSpc[] = { 1.0f, 1.0f, 1.0f, 1.0f}; //los materiales que utilizo //Rojo float mat_ambient_rojo[]= {0.25, 0.0, 0.0, 1.0}; float mat_diffuse_rojo[]= {1.0, 0.0, 0.0, 1.0}; float mat_specular_rojo[]= {1.0, 1.0, 1.0, 1.0}; float mat_shininess_rojo= 100.0; //Verde float mat_ambient_verde[]={0.0, 0.25, 0.0, 1.0}; float mat_diffuse_verde[]={0.0, 1.0, 0.0, 1.0}; float mat_specular_verde[]={1.0, 1.0, 1.0, 1.0}; float mat_shininess_verde=100.0; //Azul float mat_ambient_azul[]={0.0, 0.0, 0.25, 1.0}; float mat_diffuse_azul[]={0.0, 0.0, 1.0, 1.0}; float mat_specular_azul[]={1.0, 1.0, 1.0, 1.0}; float mat_shininess_azul=100.0; //Blanco float mat_ambient_blanco[]={0.25, 0.25, 0.25, 1.0}; float mat_diffuse_blanco[]={1.0, 1.0, 1.0, 1.0}; float mat_specular_blanco[]={1.0, 1.0, 1.0, 1.0}; float mat_shininess_blanco=100.0; //Amarillo float mat_ambient_amarillo[]={0.25, 0.25, 0.0, 1.0}; float mat_diffuse_amarillo[]={1.0, 1.0, 0.0, 1.0}; float mat_specular_amarillo[]={1.0, 1.0, 1.0, 1.0}; float mat_shininess_amarillo=100.0; void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glCullFace(GL_BACK); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glLightfv(GL_LIGHT0, GL_POSITION, LightPos); glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb); glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif); glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpc); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); //------ Trackball ----------- gltbInit(GLUT_MIDDLE_BUTTON); //---------------------------- } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); //------ Trackball ----- gltbMatrix(); //---------------------- glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_rojo); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse_rojo); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular_rojo); glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess_rojo); glPushMatrix(); glTranslatef(0.0,-2.5,5.0); glutSolidSphere(1.0,20,20); glPopMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_verde); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse_verde); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular_verde); glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess_verde); glPushMatrix(); glTranslatef(4.33,-2.5,-2.5); glutSolidSphere(1.0,20,20); glPopMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_azul); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse_azul); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular_azul); glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess_azul); glPushMatrix(); glTranslatef(-4.33,-2.5,-2.5); glutSolidSphere(1.0,20,20); glPopMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_blanco); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse_blanco); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular_blanco); glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess_blanco); glPushMatrix(); glTranslatef(0.0,0.0,0.0); glutSolidSphere(1.25,20,20); glPopMatrix(); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_amarillo); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse_amarillo); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular_amarillo); glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess_amarillo); glPushMatrix(); glTranslatef(0.0,5.0,0.0); glutSolidSphere(1.0,20,20); glPopMatrix(); glPopMatrix(); glFlush(); glutSwapBuffers(); } void reshape(int w, int h) { if (!h) return; //------ Trackball -------- gltbReshape(w, h); //------------------------- glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (GLfloat) w/(GLfloat) h, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //------ Trackball ----------- glTranslatef(0.0, 0.0, -18.0); //---------------------------- } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; } } //----- Tracknall ----------- void mouse(int button, int state, int x, int y) { GLdouble model[4*4]; GLdouble proj[4*4]; GLint view[4]; /* fix for two-button mice -- left mouse + shift = middle mouse */ if (button == GLUT_LEFT_BUTTON && glutGetModifiers() & GLUT_ACTIVE_SHIFT) button = GLUT_MIDDLE_BUTTON; gltbMouse(button, state, x, y); mouse_state = state; mouse_button = button; if (state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON) { glGetDoublev(GL_MODELVIEW_MATRIX, model); glGetDoublev(GL_PROJECTION_MATRIX, proj); glGetIntegerv(GL_VIEWPORT, view); gluProject((GLdouble)x, (GLdouble)y, 0.0, model, proj, view, &pan_x, &pan_y, &pan_z); gluUnProject((GLdouble)x, (GLdouble)y, pan_z, model, proj, view, &pan_x, &pan_y, &pan_z); pan_y = -pan_y; } glutPostRedisplay(); } //------ Trackball-------------------- void motion(int x, int y) { GLdouble model[4*4]; GLdouble proj[4*4]; GLint view[4]; gltbMotion(x, y); if (mouse_state == GLUT_DOWN && mouse_button == GLUT_MIDDLE_BUTTON) { glGetDoublev(GL_MODELVIEW_MATRIX, model); glGetDoublev(GL_PROJECTION_MATRIX, proj); glGetIntegerv(GL_VIEWPORT, view); gluProject((GLdouble)x, (GLdouble)y, 0.0, model, proj, view, &pan_x, &pan_y, &pan_z); gluUnProject((GLdouble)x, (GLdouble)y, pan_z, model, proj, view, &pan_x, &pan_y, &pan_z); pan_y = -pan_y; } glutPostRedisplay(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitWindowSize(380, 380); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("Trackball en OpenGL"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); //----- Trackball -------- glutMouseFunc(mouse); glutMotionFunc(motion); //------------------------ glutMainLoop(); return 0; } |
Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links