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