Laboratorio de Computación Gráfica

jueves, noviembre 23, 2006

Práctica #6 - Martes 21 de noviembre de 2006 - Ambos grupos

Laboratorio de Computación Gráfica
Práctica 6 - Picking y salvado y recuperación de geometrías.
21 de noviembre de 2006

Entrega: A más tardar el día 30 de noviembre de 2006.


Observe el siguiente código y resuelva los puntos señalados al final.



/*

Programa en OpenGL, usando GLUT, para dibujar un solido de revolucion
cuya generatriz es una curva NURBS con 8 puntos de control.
Se tiene un control limitado sobre los puntos de control
se puede rotar el solido usando las teclas
x,X,y,Y,z,Z para rotar en los respectivos ejes

las teclas t,T sirven para cambiar el modo de despliegue de modo poligonal a
sombreado

Inicialmente solo se visualiza la generatriz. Para generar el solido se pueden
utilizar las teclas g,G. El solido se puede desaparecer con las mismas teclas
para poder seguir editando la generatriz.

Junio de 1999

Santiago Igor Valiente Gomez

*/

# include <GL\glut.h>
//# include <stdlib.h>
# include <stdio.h>
# include <math.h>

# define PI 3.1415926535

GLfloat ctlpoints[8][3];
GLfloat cpoints1[8][8][3];
GLfloat cpoints2[8][8][3];
GLfloat cpoints3[8][8][3];
GLfloat cpoints4[8][8][3];
GLfloat cpoints5[8][8][3];
GLfloat cpoints6[8][8][3];
GLfloat cpoints7[8][8][3];
GLfloat cpoints8[8][8][3];
GLfloat eje_rotacion[2][3]={{0.0,-10.0,0.0},{0.0,10.0,0.0}};
GLfloat *line=&ctlpoints[0][0];
GLuint selectedPoint = ~0;
GLuint selectBuffer[64];
GLdouble modelMatrix[16], projMatrix[16];
GLint viewport[4];
GLfloat modo=GLU_OUTLINE_POLYGON;

GLfloat luz_ambiental[4]={1.0,1.0,1.0,1.0};

int showPoints=0;
int superficie=0;
int winWidth, winHeight;
int uSize = 8;
int vSize = 3;

static int angx=0;
static int angy=0;
static int angz=0;
static GLfloat x=0.0;
static GLfloat y=0.0;
static GLfloat z=0.0;
static float ang=0.0;

GLUnurbsObj *theNurb;

GLUnurbsObj *octante1;
GLUnurbsObj *octante2;
GLUnurbsObj *octante3;
GLUnurbsObj *octante4;
GLUnurbsObj *octante5;
GLUnurbsObj *octante6;
GLUnurbsObj *octante7;
GLUnurbsObj *octante8;

void init_curve(void)
{
int u;
for (u=0;u<uSize;u++)
{
ctlpoints[u][0] = 2.0*((GLfloat)u - 3.0);
ctlpoints[u][1] = 2.0*((GLfloat)u - 3.0);
ctlpoints[u][2] = 0.0;
}
}

void init_solid(void)
{
int i,j,k;
for(k=0;k<8;k++)
{
for(i=0;i<8;i++)
{
for(j=7;j>=0;j--)
{
if(k==0)
{
cpoints1[i][7-j][0]=ctlpoints[j][0]*cos((i*6.43)*PI/180.0) - ctlpoints[j][2]*sin((i*6.43)*PI/180.0);
cpoints1[i][7-j][1]=ctlpoints[j][1];
cpoints1[i][7-j][2]=ctlpoints[j][0]*sin((i*6.43)*PI/180.0) + ctlpoints[j][2]*cos((i*6.43)*PI/180.0);
}
if(k==1)
{
cpoints2[i][7-j][0]=ctlpoints[j][0]*cos((i*6.43+45.0)*PI/180.0) - ctlpoints[j][2]*sin((i*6.43+45.0)*PI/180.0);
cpoints2[i][7-j][1]=ctlpoints[j][1];
cpoints2[i][7-j][2]=ctlpoints[j][0]*sin((i*6.43+45.0)*PI/180.0) + ctlpoints[j][2]*cos((i*6.43+45.0)*PI/180.0);
}
if(k==2)
{
cpoints3[i][7-j][0]=ctlpoints[j][0]*cos((i*6.43+90.0)*PI/180.0) - ctlpoints[j][2]*sin((i*6.43+90.0)*PI/180.0);
cpoints3[i][7-j][1]=ctlpoints[j][1];
cpoints3[i][7-j][2]=ctlpoints[j][0]*sin((i*6.43+90.0)*PI/180.0) + ctlpoints[j][2]*cos((i*6.43+90.0)*PI/180.0);
}
if(k==3)
{
cpoints4[i][7-j][0]=ctlpoints[j][0]*cos((i*6.43+135.0)*PI/180.0) - ctlpoints[j][2]*sin((i*6.43+135.0)*PI/180.0);
cpoints4[i][7-j][1]=ctlpoints[j][1];
cpoints4[i][7-j][2]=ctlpoints[j][0]*sin((i*6.43+135.0)*PI/180.0) + ctlpoints[j][2]*cos((i*6.43+135.0)*PI/180.0);
}
if(k==4)
{
cpoints5[i][7-j][0]=ctlpoints[j][0]*cos((i*6.43+180.0)*PI/180.0) - ctlpoints[j][2]*sin((i*6.43+180.0)*PI/180.0);
cpoints5[i][7-j][1]=ctlpoints[j][1];
cpoints5[i][7-j][2]=ctlpoints[j][0]*sin((i*6.43+180.0)*PI/180.0) + ctlpoints[j][2]*cos((i*6.43+180.0)*PI/180.0);
}
if(k==5)
{
cpoints6[i][7-j][0]=ctlpoints[j][0]*cos((i*6.43+225.0)*PI/180.0) - ctlpoints[j][2]*sin((i*6.43+225.0)*PI/180.0);
cpoints6[i][7-j][1]=ctlpoints[j][1];
cpoints6[i][7-j][2]=ctlpoints[j][0]*sin((i*6.43+225.0)*PI/180.0) + ctlpoints[j][2]*cos((i*6.43+225.0)*PI/180.0);
}
if(k==6)
{
cpoints7[i][7-j][0]=ctlpoints[j][0]*cos((i*6.43+270.0)*PI/180.0) - ctlpoints[j][2]*sin((i*6.43+270.0)*PI/180.0);
cpoints7[i][7-j][1]=ctlpoints[j][1];
cpoints7[i][7-j][2]=ctlpoints[j][0]*sin((i*6.43+270.0)*PI/180.0) + ctlpoints[j][2]*cos((i*6.43+270.0)*PI/180.0);
}
if(k==7)
{
cpoints8[i][7-j][0]=ctlpoints[j][0]*cos((i*6.43+315.0)*PI/180.0) - ctlpoints[j][2]*sin((i*6.43+315.0)*PI/180.0);
cpoints8[i][7-j][1]=ctlpoints[j][1];
cpoints8[i][7-j][2]=ctlpoints[j][0]*sin((i*6.43+315.0)*PI/180.0) + ctlpoints[j][2]*cos((i*6.43+315.0)*PI/180.0);
}
}
}
}
}

void init(void)
{
GLfloat mat_diffuse[] = {0.7,1.0,0.7,1.0};
GLfloat mat_specular[] = {1.0,1.0,1.0,1.0};
GLfloat mat_shininess[] = {100.0};
glClearColor(0.0,0.0,0.0,0.0);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0,GL_AMBIENT,luz_ambiental);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_DEPTH_TEST);
glEnable (GL_AUTO_NORMAL);
glEnable (GL_NORMALIZE);
init_curve();
theNurb=gluNewNurbsRenderer();
gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
octante1=gluNewNurbsRenderer();
gluNurbsProperty(octante1, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(octante1, GLU_DISPLAY_MODE, modo);
octante2=gluNewNurbsRenderer();
gluNurbsProperty(octante2, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(octante2, GLU_DISPLAY_MODE, modo);
octante3=gluNewNurbsRenderer();
gluNurbsProperty(octante3, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(octante3, GLU_DISPLAY_MODE, modo);
octante4=gluNewNurbsRenderer();
gluNurbsProperty(octante4, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(octante4, GLU_DISPLAY_MODE, modo);
octante5=gluNewNurbsRenderer();
gluNurbsProperty(octante5, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(octante5, GLU_DISPLAY_MODE, modo);
octante6=gluNewNurbsRenderer();
gluNurbsProperty(octante6, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(octante6, GLU_DISPLAY_MODE, modo);
octante7=gluNewNurbsRenderer();
gluNurbsProperty(octante7, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(octante7, GLU_DISPLAY_MODE, modo);
octante8=gluNewNurbsRenderer();
gluNurbsProperty(octante8, GLU_SAMPLING_TOLERANCE, 25.0);
gluNurbsProperty(octante8, GLU_DISPLAY_MODE, modo);
}

void showcontrolpoints(void)
{
int i;
glPointSize(5.0);
glDisable(GL_LIGHTING);
glColor3f(1.0,1.0,0.0);
for(i=0;i<uSize;i++)
{
glBegin(GL_POINTS);
glVertex3fv(&line[i*3]);
glEnd();
}
glEnable(GL_LIGHTING);
}

void selectControlPoints(void)
{
int k;
for (k=0;k<uSize;k++)
{
glLoadName(k);
glBegin(GL_POINTS);
glVertex3fv(&line[k*3]);
glEnd();
}
}

void display(void)
{
GLfloat knots[16] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
gluNurbsProperty(octante1, GLU_DISPLAY_MODE, modo);
gluNurbsProperty(octante2, GLU_DISPLAY_MODE, modo);
gluNurbsProperty(octante3, GLU_DISPLAY_MODE, modo);
gluNurbsProperty(octante4, GLU_DISPLAY_MODE, modo);
gluNurbsProperty(octante5, GLU_DISPLAY_MODE, modo);
gluNurbsProperty(octante6, GLU_DISPLAY_MODE, modo);
gluNurbsProperty(octante7, GLU_DISPLAY_MODE, modo);
gluNurbsProperty(octante8, GLU_DISPLAY_MODE, modo);
glPushMatrix();
glRotatef((GLfloat)angx,1.0,0.0,0.0);
glRotatef((GLfloat)angy,0.0,1.0,0.0);
glRotatef((GLfloat)angz,0.0,0.0,1.0);
glTranslatef(x,0.0,0.0);
glTranslatef(0.0,y,0.0);
glTranslatef(0.0,0.0,z);
if(superficie)
{
gluBeginSurface(octante1);
gluNurbsSurface(octante1,16,knots,16,knots,8*3,3,&cpoints1[0][0][0],8,8,GL_MAP2_VERTEX_3);
gluEndSurface(octante1);
gluBeginSurface(octante2);
gluNurbsSurface(octante2,16,knots,16,knots,8*3,3,&cpoints2[0][0][0],8,8,GL_MAP2_VERTEX_3);
gluEndSurface(octante2);
gluBeginSurface(octante3);
gluNurbsSurface(octante3,16,knots,16,knots,8*3,3,&cpoints3[0][0][0],8,8,GL_MAP2_VERTEX_3);
gluEndSurface(octante3);
gluBeginSurface(octante4);
gluNurbsSurface(octante4,16,knots,16,knots,8*3,3,&cpoints4[0][0][0],8,8,GL_MAP2_VERTEX_3);
gluEndSurface(octante4);
gluBeginSurface(octante5);
gluNurbsSurface(octante5,16,knots,16,knots,8*3,3,&cpoints5[0][0][0],8,8,GL_MAP2_VERTEX_3);
gluEndSurface(octante5);
gluBeginSurface(octante6);
gluNurbsSurface(octante6,16,knots,16,knots,8*3,3,&cpoints6[0][0][0],8,8,GL_MAP2_VERTEX_3);
gluEndSurface(octante6);
gluBeginSurface(octante7);
gluNurbsSurface(octante7,16,knots,16,knots,8*3,3,&cpoints7[0][0][0],8,8,GL_MAP2_VERTEX_3);
gluEndSurface(octante7);
gluBeginSurface(octante8);
gluNurbsSurface(octante8,16,knots,16,knots,8*3,3,&cpoints8[0][0][0],8,8,GL_MAP2_VERTEX_3);
gluEndSurface(octante8);
}
glDisable(GL_LIGHTING);
glColor3f(1.0,0.0,1.0);
gluBeginCurve(theNurb);
gluNurbsCurve(theNurb,16,knots,3,line,8,GL_MAP1_VERTEX_3);
gluEndCurve(theNurb);
glEnable(GL_LIGHTING);
showcontrolpoints();
glPopMatrix();
glDisable(GL_LIGHTING);
glColor3f(0.0,1.0,1.0);
glBegin(GL_LINES);
glVertex3fv(&eje_rotacion[0][0]);
glVertex3fv(&eje_rotacion[1][0]);
glEnd();
glEnable(GL_LIGHTING);
glFlush();
glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 't':
case 'T':
if(modo==GLU_OUTLINE_POLYGON)
modo=GLU_FILL;
else
modo=GLU_OUTLINE_POLYGON;
glutPostRedisplay();
break;
case 'c':
case 'C':
z=z+0.5;
glutPostRedisplay();
break;
case 'l':
case 'L':
z=z-0.5;
glutPostRedisplay();
break;
case 's':
case 'S':
y=y+0.5;
glutPostRedisplay();
break;
case 'b':
case 'B':
y=y-0.5;
glutPostRedisplay();
break;
case 'i':
case 'I':
x=x-0.5;
glutPostRedisplay();
break;
case 'd':
case 'D':
x=x+0.5;
glutPostRedisplay();
break;
case 'g':
case 'G':
init_solid();
superficie=~superficie;
glutPostRedisplay();
break;
case 'x':
angx=(angx+10)%360;
glutPostRedisplay();
break;
case 'X':
angx=(angx-10)%360;
glutPostRedisplay();
break;
case 'y':
angy=(angy+10)%360;
glutPostRedisplay();
break;
case 'Y':
angy=(angy-10)%360;
glutPostRedisplay();
break;
case 'z':
angz=(angz+10)%360;
glutPostRedisplay();
break;
case 'Z':
angz=(angz-10)%360;
glutPostRedisplay();
break;
case 'r':
case 'R':
angx=0;
angy=0;
angz=0;
x=y=z=0.0;
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}

void ortho(void)
{
if (winWidth <= winHeight)
glOrtho(-10.0,10.0,-10.0*(GLfloat)winHeight/(GLfloat)winWidth,10.0*(GLfloat)winHeight/(GLfloat)winWidth,-10.0,10.0);
else
glOrtho(-10.0*(GLfloat)winWidth/(GLfloat)winHeight,10.0*(GLfloat)winWidth/(GLfloat)winHeight,-10.0,10.0,-10.0,10.0);
}

GLuint pick(int x, int y)
{
int hits;
(void)glRenderMode(GL_SELECT);
glInitNames();
glPushName(~0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(x,winHeight-y, 8.0, 8.0, viewport);
ortho();
glMatrixMode(GL_MODELVIEW);
selectControlPoints();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
hits = glRenderMode(GL_RENDER);
if (hits)
{
return selectBuffer[3];
}
else
{
return ~0;
}
}

void reshape (int w, int h)
{
glViewport(0, 0, w, h);
winWidth = w;
winHeight = h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
ortho();
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
viewport[0] = 0;
viewport[1] = 0;
viewport[2] = winWidth;
viewport[3] = winHeight;
}

void mouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON)
{
if(state == GLUT_DOWN)
{
selectedPoint = pick(x,y);
}
else
{
selectedPoint = -1;
}
}
}


void motion(int x, int y)
{
GLdouble objx, objy, objz;
if (selectedPoint!=~0)
{
gluUnProject(x,winHeight-y,0.95,modelMatrix,projMatrix,viewport,&objx,&objy,&objz);
line[selectedPoint*3+0]=objx;
line[selectedPoint*3+1]=objy;
glutPostRedisplay();
}
}

int main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500,500);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutKeyboardFunc(keyboard);
glSelectBuffer(sizeof(selectBuffer),selectBuffer);
glutMainLoop();
return 0;
}




Ahora conteste:

1.- Describa la funcionalidad del programa

2.- ¿Qué es una operación de picking? ¿Qué se necesita para hacer un picking?

3.- Modifique el programa para que se modifique y visualice el sólido de revolución al mismo tiempo que se edita la curva generatriz.

3a.- (bono extra - opcional) Mapee una textura de mapa de bits sobre el sólido de revolución generado.

4.- Modifique el programa para que se puedan guardar y recuperar cualquier sólido de revolución que se edite. Guarde al menos 4 sólidos distintos. Proponga una estructura basada en XML para el archivo en donde se almacene la curva.

5.- Tomando como modelo este programa, escriba uno en donde pueda modelar poliedros con el mouse, guarde en un archivo la geometría generada, la pueda recuperar y mostrar nuevamente.