Sunday, December 16, 2007

Trazo de splines

Trazo de splines

• Interpolar un conjunto de puntos usando los splines cubicos naturales.
• Interpolar un conjunto de puntos de una curva cerrada usando los mismos splines cubicos naturales.
• Interpolar el mismo conjunto de puntos del primer punto pero ahora usando los splines Catmull-Rom.
• El trazo debe realizase con gnuplot

Jose Angel Espinoza Portillo, onlyangel@onlyangel.net

Splines Cubicas Naturales

1 Teorıa
Fue una de las primeras curvas splines que se desarrollo para aplicaciones gr´aficas es el spline cubico natural. Esta se forma imponiendo que dos partes adyacentes e la curva posean la mismas primera y segunda derivada parametrica en su limite comun. Por tanto, los splines cubicos naturales tienen continuidad C 2 .




Si tenemos n + 1puntos de control, como en la Figura 1.1, entonces tenemos n partes de la curva con un total de 4n coeficientes de polinomio que hay que determinar. En cada uno de los n − 1 puntos de control interiores tenemos cuatro condiciones en el limite: las dos partes de la curva a cada lado de un punto de control deben tenerlas mismas primera y segunda derivadas parametricas en dicho punto de control, y cada curva debe pasar por ese punto de control. Esto nos proporciona 4n − 4 ecuaciones que hay que satisfacer con 4n coeficientes de polinomio, obtenemos una ecuaci´on adicional a partir del primer punto de control p0 y pn en el valor 0. Otra t´ecnica es anadir dos puntos de control extra (llamados puntos ficticios ), uno en cada extremo de la secuencia original de puntos de control. Es decir anadimos un punto de control etiquetado como p en el comienzo de la curva y un punto decontrol etiquetado como pn+1 en el final. Entonces todos los puntos e control originales son puntos anteriores y tenemos las 4n condiciones necesarias en el limite.

2 Base matematica del dibujo
Si tenemos una secuencia de puntos P = {P0 , P1 , · · · , Pn } donde cada Pa es un punto en el espacio (xa , ya ). Se tiene que desarrollar la siguiente Multiplicaci´on de matrices.



De esta manera se tienen todas las secciones de la curva a dibujar, la cual para ser rendereada por puntos se especifican segun la siguiente ecuaci´on basada en t.




3 Interpolando un Conjunto de Puntos
3.1 Se propone el siguiente P.




3.2 Se tendr´an unos M de:




3.3 Con lo que nos queda.


3.4 C´odigo de gluplot

X1(t) = 2*(1-t) + 4*t + (-30/6)*( (1-t)*(1-t)*(1-t) - (1-t) ) + (30/6)*( t*t*t - t )
Y1(t) = 3*(1-t) + 8*t + (30/6)*( (1-t)*(1-t)*(1-t) - (1-t) ) + (-30/6)*( t*t*t - t )
X2(t) = 4*(1-t) + 6*t + (-30/6)*( (1-t)*(1-t)*(1-t) - (1-t) ) + (30/6)*( t*t*t - t )
Y2(t) = 8*(1-t) + 3*t + (-30/6)*( (1-t)*(1-t)*(1-t) - (1-t) ) + (30/6)*( t*t*t - t )
X3(t) = 6*(1-t) + 8*t + (-30/6)*( (1-t)*(1-t)*(1-t)-(1-t) ) + (30/6)*( t*t*t - t)
Y3(t) = 3*(1-t) + 8*t + (30/6)*( (1-t)*(1-t)*(1-t)-(1-t) ) + (-30/6)*( t*t*t - t)
set xrange [0:10]
set yrange [0:10]
set multiplot
plot ’puntosNaturales.txt’ w p ps 2
set parametric
set trange [0:1]
plot X1(t),Y1(t), X2(t),Y2(t),X3(t),Y3(t)
unset multiplot
pause -1



3.5 Resultado



4 El caso del la figura circular
4.1 Se propone el siguiente P.




4.2 Se tendr´an unos M de:




4.3 Con lo que nos queda.



4.4 Codigo en GNUPLOT


X1(t) = 4*(1-t)+3*t + ((-11.81041)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((8.33644)/6)*(t*t*t-t)
Y1(t) = 4*(1-t)+0*t + ((-12.21815)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((0.76353)/6)*(t*t*t-t)
X2(t) = 3*(1-t)+4*t + ((8.33644)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((-9.53533)/6)*(t*t*t-t)
Y2(t) = 0*(1-t)-4*t + ((0.76353)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((9.16403)/6)*(t*t*t-t)
X3(t) = 4*(1-t)+0*t + ((-9.53533)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((-0.19511)/6)*(t*t*t-t)
Y3(t) = -4*(1-t)-3*t + ((9.16403)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + (( -7.41963)/6)*(t*t*t-t)
X4(t) = 0*(1-t)-4*t + ((-0.19511)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((10.31579)/6)*(t*t*t-t)
Y4(t) = -3*(1-t)-4*t + (( -7.41963)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((8.51451)/6)*(t*t*t-t)
X5(t) = -4*(1-t)-3*t + ((10.31579)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((-11.06804)/6)*(t*t*t-t)
Y5(t) = -4*(1-t)+0*t + ((8.51451)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((3.36161)/6)*(t*t*t-t)
X6(t) = -3*(1-t)-4*t + ((-11.06804)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((21.95635)/6)*(t*t*t-t)
Y6(t) = 0*(1-t)+4*t + ((-3.36161)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((-21.96094)/6)*(t*t*t-t)
X7(t) = -4*(1-t)+0*t + ((21.95635)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((-2.84467)/6)*(t*t*t-t)
Y7(t) = 4*(1-t)+3*t + ((-21.96094)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((10.56027)/6)*(t*t*t-t)
X8(t) = 0*(1-t)+4*t + ((-2.84467)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((10.57766)/6)*(t*t*t-t)
Y8(t) = 3*(1-t)+4*t + ((10.56027)/6)*((1-t)*(1-t)*(1-t)-(1-t)) + ((-8.28013)/6)*(t*t*t-t)
set xrange [-7:7]
set yrange [-7:7]
set multiplot
plot ’puntosNaturalesCirculo.txt’ w p ps 2
set parametric
set trange [0:1]
plot X1(t),Y1(t), X2(t),Y2(t),X3(t),Y3(t), X4(t),Y4(t),X5(t),Y5(t), X6(t),Y6(t),X7(t),Y7(t),X8(t),Y8(
unset multiplot
pause -1


4.5 Resultado



Splines de Catmull-Rom
1 Teor´ıa y base matematica
Al igual que los splines de Hermite, los splines Catmull-Rom son polinomio de interpolaci´on por tramos c´ubicos con tangentes especificas en los puntos extremos en los limites de cada secci´on de la curva. La diferencia es que no introducimos los valores de las tangentes en los puntos extremos. En un spline CR, la pendiente en en el punto de control se calcula a partir de las coordenadas de los dos puntos de control adyacentes.

Una secci´on de un spline queda completamente determinada con cuatro puntos de control consecutivos. Los puntos de control centrales son los puntos extremos de la secci´on, y otros dos los puntos se utilizan en el calculo de las pendientes en los puntos extremos. Si tomamos P(u) como la representaci´on de la funci´on de punto param´etrica cubica de la secci´on de curva entre los puntos de control Pk−1 hasta Pk+1 se utilizan para establecer las condiciones en los limites de la secci´on del spline de este modo:




Por tanto, las pendientes en los puntos de control Pk y Pk+1 se toman proporcionales, respectivamente, a las cuerdas Pk
−1 Pk+1 y Pk Pk+2 el par´ametro t se denomina par´ametro de tensi´on, ya que controla como de flo jo o apretado se a justa el spline a los puntos de control de entrada.
Utilizando m´etodos similares a los utilizados para los polinomios Hermite, podemos convertir las condiciones de (2.1) de los limites en su forma matricial,



Donde la Matriz Catmun-Rom es:



con s = (1 − t)/2.
Desarrollando la Ecuacion matricial (2.2) en forma polinomica, tenemos:



donde los polinomios C ARK (u) con K = 0, 1, 2, 3 son las funciones de combinacion de la matriz base de los splines Catmull-Rom.

2 El caso del Curva Catmull-Rom
2.1 Se propone el siguiente P.




2.2 Se tienen unos M’s de:



De donde obtenemos la matriz base de Catmull-Rom multiplicandolas:



2.3 Con lo que nos queda un P(u).
Obtenemos C ARen conformidad con (2.2) para obtener (2.4) matricial(P (u)).




2.4 El Codigo en GNUPLOT

P1(t) = (-0.5*t*t*t + 1*t*t - 0.5*t + 0)
P2(t) = ( 1.5*t*t*t - 2.5*t*t + 0*t + 1)
P3(t) = (-1.5*t*t*t + 2*t*t + 0.5*t + 0)
P4(t) = ( 0.5*t*t*t - 0.5*t*t + 0*t + 0)
x1(t) = 1*P1(t) + 2*P2(t) + 4*P3(t) + 6*P4(t)
y1(t) = 8*P1(t) + 3*P2(t) + 8*P3(t) + 3*P4(t)
x2(t) = 2*P1(t) + 4*P2(t) + 6*P3(t) + 8*P4(t)
y2(t) = 3*P1(t) + 8*P2(t) + 3*P3(t) + 8*P4(t)
x3(t) = 4*P1(t) + 6*P2(t) + 8*P3(t) + 10*P4(t)
y3(t) = 8*P1(t) + 3*P2(t) + 8*P3(t) + 3*P4(t)
x4(t) = 4*P1(t) + 6*P2(t) + 8*P3(t) + 20*P4(t)
y4(t) = 8*P1(t) + 3*P2(t) + 8*P3(t) + 20*P4(t)
set xrange [0:10]
set yrange [0:10]
set multiplot
plot ’puntos.txt’ w p ps 2
set parametric
set trange [0:1]
plot x1(t), y1(t), x2(t), y2(t), x3(t), y3(t) ,x4(t), y4(t)
unset multiplot
pause -1

2.5 Resultado

Labels: ,

Wednesday, December 12, 2007

Mi carro con PovRay

Mi carro con PovRay
Dibujado de un carro en OpenGL utilizando ????

Jose Angel Espinoza Portillo
Graficacion • 14 Diciembre 2007



Que es Pov-Ray?
Pov-Ray es una herramienta que sirve para generar ambientes en 3D, basada la técnica de trazo de rayo. La cual consiste en dividir el campo de visión en una maya de pixeles y evaluar simular un rayo que pasa por cada pixel y evalúa el objeto que choca y el rebote de la luz desde todos los objetos y las fuentes de luz en el. y así sucesivamente con cada pixel, un ejemplo de esta técnica se puede ver en en la siguiente figura.

Implementación
Como implementar y que pasos seguir para el dibujado.

Base
De manera similar que en Open GL se programan muchas cosas dentro del código, el primer paso antes de empezar a implementar el carro es especificar las características básicas las cuales se especifican a continuación:




#include "colors.inc"
#include "shapes.inc"
#include "textures.inc"

camera {
location <2,5,>
look_at <0,>
}

background { color SkyBlue }
light_source { <20,> color rgb<1,> }


Esto posesionara la cámara en el punto <15,> mirando hacia <0,>, define el fondo en color azul cielo y posiciona una fuente de luz blanca en las coordenadas <20,>

Plano
Ahora se procede a agregar el siguiente código para integrar un plano infinito dentro de la vista:




plane { y, 1
pigment { checker Green, White }
finish { ambient .3 diffuse .7 }
}

El valor de pigment le dice que va a ser una maya de cuadros a continuación de los colores de los cuadros.






Cielo
Para simular el cielo, se agrega una esfera, la cual es magnificada para abarcar el espacio del cielo. Esta esfera es creada de la siguiente manera:

#declare Sky = sky_sphere {
pigment {
gradient y
color_map {
[0.75 color CornflowerBlue]
[1.00 color MidnightBlue]
}
scale 2
translate <-1, -1, -1>
}
pigment {
bozo
turbulence 0.6
octaves 7
omega .49876
lambda 2.5432
color_map {
[0.0 color rgbf<.75, .75, .75, 0.1>]
[0.4 color rgbf<.9, .9, .9, .9>]
[0.7 color rgbf<1,>]
}
scale 6/10
scale <1,>
}
pigment {
bozo
turbulence 0.6
octaves 8
omega .5123
lambda 2.56578
color_map {
[0.0 color rgbf<.375, .375, .375, 0.2>]
[0.4 color rgbf<.45, .45, .45, .9>]
[0.6 color rgbf<0.5,>]
}
scale 6/10
scale <1,>
}
}
sky_sphere { Sky }



El carrito
Los colores
Para hacer el carro primero se especificaron las 6 texturas del objeto pertenecientes a cada lado del mismo especificandole un grado de refleccion y el material del mismo(metal) de la siguiente manera:

#declare TRed = texture {
pigment { color rgb<0.8,> }
finish {
reflection {0.5 metallic}
diffuse 0.4

brilliance 2
specular 1 roughness 0.01
metallic
}
}
#declare TGreen = texture {
pigment { color rgb<0.2,> }
finish {
reflection {0.5 metallic}
diffuse 0.4

brilliance 2
specular 1 roughness 0.01
metallic
}
}
#declare TBlue = texture {
pigment { color rgb<0.2,> }
finish {
reflection {0.5 metallic}
diffuse 0.4

brilliance 2
specular 1 roughness 0.01
metallic
}
}

#declare TWhite = texture {
pigment { color rgb<0.8,> }
finish {
reflection {0.5 metallic}
diffuse 0.4

brilliance 2
specular 1 roughness 0.01
metallic
}
}
#declare TViolet = texture {
pigment { color rgb<0.8,> }
finish {
reflection {0.5 metallic}
diffuse 0.4

brilliance 2
specular 1 roughness 0.01
metallic
}
}

#declare TPurple = texture {
pigment { color rgb<0.8,> }
finish {
reflection {0.5 metallic}
diffuse 0.4

brilliance 2
specular 1 roughness 0.01
metallic
}
}


La figura
Basado en la figura diseñada para el mismo proyecto en OpenGL se implemento un objeto mesh basado en mayas de triángulos especificando que textura tiene cada triángulo esto se dibuja de la siguiente manera:


mesh {

triangle {
<0,>, <5,>, <5,>
texture { TRed }
}
triangle {
<0,>, <5,>, <0,>
texture { TRed }
}
triangle {
<1.25,>, <3.75,>, <3.75,>
texture { TRed }
}
triangle {
<1.25,>, <3.75,>, <1.25,>
texture { TRed }
}

triangle {
<0,>, <5,>, <5,>
texture { TGreen }
}
triangle {
<0,>, <5,>, <0,>
texture { TGreen }
}

triangle {
<0,>, <0,>, <0,>
texture { TWhite }
}
triangle {
<0,>, <0,>, <0,>
texture { TWhite }
}
triangle {
<1.25,>, <1,>, <1,>
texture { TWhite }
}
triangle {
<1.25,>, <1,>, <1.25,>
texture { TWhite }
}

triangle {
<0,>, <5,>, <5,>
texture { TViolet }
}
triangle {
<0,>, <5,> <0,>
texture { TViolet }
}
triangle {
<1,>, <4,>, <3.75,>
texture { TViolet }
}
triangle {
<1,>, <3.75,>, <1.25,>
texture { TViolet }
}

triangle {
<5,>, <5,>, <5,>
texture { TBlue }
}
triangle {
<5,>, <5,>, <5,>
texture { TBlue }
}
triangle {
<4,>, <4,>, <3.75,>
texture { TBlue }
}
triangle {
<4,>, <3.75,>, <3.75,>
texture { TBlue }
}

triangle {
<5,>, <0,>, <0,>
texture { TPurple }
}
triangle {
<5,>, <0,>, <5,>
texture { TPurple }
}
triangle {
<3.75,>, <1.25,>, <1,>
texture { TPurple }
}
triangle {
<3.75,>, <1,>, <4,>
texture { TPurple }
}

rotate x*-90
}

Cámara
Para efectos de presentación se moverá la cámara a otro punto para poder notar mejor la sombra y el efecto de reflejo de el piso en el objeto, reemplazando la cámara por lo siguiente.


camera {
location <15,>
look_at <0,>
}

Labels: ,

BRAZO ARTICULADO CON ILUMINACIÓN

BRAZO ARTICULADO CON ILUMINACIÓN
Implementando la estructura de un brazo articulado con movimiento en 4 grados de libertad e iluminación artificial.
Jose Angel Espinoza Portillo
Otoño 2007



Definiendo el problema
Dibujar un brazo articulado en 3D que pueda moverse con las pulsaciones de teclas e implementar un sistema de iluminación que permita ver un reflejo de la luz en la estructura del brazo.
Primer paso - Colocar la cámara
Como en la analogía del camarógrafo explicado en clase, el primero paso es colocar la cámara apuntando hacia donde esta lo que se desea visualizar, para esto cargamos la matriz de proyección y especificamos el punto de vista basado en la elevación de la cámara y el ángulo de visión (rotado en el eje y) y llamamos gluLookAt para ser ejecutado con esas coordenadas mirando al origen, con el siguiente código:

glMatrixMode (GL_PROJECTION);
glLoadIdentity ();

gluPerspective(30,1,0.01,100);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity (); /* clear the matrix */
eye[0] = zoom *sin(azi*3.1416/180) * cos(ele*3.1416/180);
eye[1] = zoom *sin(ele*3.1416/180) ;
eye[2] = zoom *cos(azi*3.1416/180) * cos(ele*3.1416/180);

gluLookAt(eye[0],eye[1],eye[2],0,0,0,0,1,0);


Iluminación


Lo que se quiere lograr con la iluminación es tener un efecto de reflejo de la luz blanca en las superficies de as figuras, con respecto a la cámara y la fuente de luz (que se colocara en el punto (1,1,1)), y que el material del objeto permanezca del color que se le da a el objeto esto se hace habilitando el GL_COLOR_MATERIAL, esto se realiza con el siguiente código:

// Define el punto de origen de luz y su brillo
GLfloat light0_pos[]={1.0,1.0,1.0,1.0};
GLfloat shininess[]={5.0}; // Mientras mas pequeño da la apariencia de mas brillo.

glEnable(GL_LIGHTING);// habilita la iluminación
glEnable(GL_LIGHT0);

Color_white[0]=1.0; Color_white[1]=1.0; Color_white[2]=1.0; Color_white[3]=1.0;
Color_blue[0]=0.0; Color_white[1]=0.0; Color_white[2]=1.0; Color_white[3]=1.0;

// Configura los puntos de luz
glLightfv(GL_LIGHT0,GL_POSITION,light0_pos);
glLightfv(GL_LIGHT0,GL_AMBIENT,Color_white);
glLightfv(GL_LIGHT0,GL_DIFFUSE,Color_white);
glLightfv(GL_LIGHT0,GL_SPECULAR,Color_white);


mat[0][0]=1.0; mat[0][1]=1.0; mat[0][2]=1.0; mat[0][3]=1.0;

glEnable(GL_COLOR_MATERIAL);// Se habilita que respete el color de la forma como
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); // el color del material

glMaterialfv(GL_FRONT,GL_SPECULAR,&mat[0][0]); // Se especifica la luz especular.
glMaterialfv(GL_FRONT,GL_SHININESS,shininess);










El brazo articulado.
Como se comento al inicio del reporte se desea dibujar un brazo articulado el cual esta constituido por tres piezas movibles y una base rotatoria y la transformación que se le haga a cada uno de los elementos desde la base debe afectar a todos los demás elementos hasta la punta, para esto se baso en ir aplicando las transformaciones entre dibujado y dibujado de cada parte del brazo, así las nuevas partes dibujadas heredaran las transformaciones anteriores. Para hacer esto se utilizo el siguiente código:

float h0=2,h1=5,h2=4,h3=4;

glMatrixMode (GL_MODELVIEW);
glPushMatrix();

RotaX(-90);

RotaZ(angulo1);
DibujaCilindro(2,2,h0,20,Color_blue);

RotaY(angulo2);
DibujaCilindro(.5,.2,h1,20,Color_blue);

RotaY(angulo3);
DibujaCilindro(.4,.2,h2,20, Color_blue);

RotaY(angulo4);
DibujaCilindro(.4,.2,h3,20, Color_blue);

glPopMatrix();


Donde Rotax, RotaX y RotaZ son funciones donde están implementadas las matrices de transformación de cada una de estas rotaciones.


Modificación desde el teclado.
En el código anterior se a mostrado como iluminar y dibujar un objeto en 3D, pero no se a explicado la manera en que se modifican las variables de donde se toman los valores para guiarse en el dibujado.

Estas instrucciones se hacen directamente desde el teclado modificando las variables de los parámetros usados anteriormente.

float step = 10;
switch (event->key()) {
case Qt::Key_Plus:
signo = 1;
break;
case Qt::Key_Minus:
signo = -1;
break;
case Qt::Key_Left:
azi += step;
break;
case Qt::Key_Right:
azi -= step;
break;
case Qt::Key_PageDown:
zoom += 1;
break;
case Qt::Key_PageUp:
zoom -= 1;
break;
case Qt::Key_Up:
ele += step;
break;
case Qt::Key_Down:
ele -= step;
break;
case Qt::Key_T:
angulo1 += 10;
break;
case Qt::Key_G:
angulo1 -= 10;
break;
case Qt::Key_Y:
angulo2 += 10;
break;
case Qt::Key_H:
angulo2 -= 10;
break;
case Qt::Key_U:
angulo3 += 10;
break;
case Qt::Key_J:
angulo3 -= 10;
break;
case Qt::Key_I:
angulo4 += 10;
break;
case Qt::Key_K:
angulo4 -= 10;
break;
case Qt::Key_D:
lightXYZ[0] += .1;
break;
case Qt::Key_A:
lightXYZ[0] -= .1;
break;
case Qt::Key_W:
lightXYZ[1] += .1;
break;
case Qt::Key_S:
lightXYZ[1] -= .1;
break;
case Qt::Key_X:
lightXYZ[2] += .1;
break;
case Qt::Key_Z:
lightXYZ[2] -= .1;
break;
default:
QWidget::keyPressEvent(event);
}
updateGL();