viernes, 27 de septiembre de 2013

ACCESORIO DE COMPUTADORA


#include "stdafx.h"
#include <stdlib.h>
#include <GL/glut.h>


GLfloat tras= 1.5f;
GLfloat esc = 1.5f;
GLfloat ang = 0.0f; 

GLfloat isLeftKeyPressed=false;
GLfloat isRightKeyPressed=false;


void reshape(int width, int height)
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION); 
glLoadIdentity();
 glOrtho(-10,20,-4,10,-8,5);
glMatrixMode(GL_MODELVIEW);

}


void display(){

glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
glLoadIdentity();


ang+=0.1555f;



glTranslatef(tras,0.0f,0.0f);

glScalef(esc, esc, esc);

glRotatef(ang, 0.0f, 1.0f, 0.0f);



//cara frontal
//hilera 1
 glColor3f(0,1,0);
 glBegin(GL_POLYGON);
 glVertex3f(0,0,0);
 glVertex3f(5,0,0);
 glVertex3f(5,5,0);
 glVertex3f(0,5,0);
  glVertex3f(0,0,0);
 glEnd();

 //pantllanegra
   glColor3f(0,0,0);
 glBegin(GL_POLYGON);
 glVertex3f(1,1,-.1f);
 glVertex3f(4,1,0);
 glVertex3f(4,4,0);
 glVertex3f(1,4,0);
  glVertex3f(1,1,0);
 glEnd();

 //cara delado dr
 glColor3f(0,1,0);
 glBegin(GL_POLYGON);
 glVertex3f(5,0,0);
 glVertex3f(5,5,0);
 glVertex3f(5,5,2);
 glVertex3f(5,0,2);
 glVertex3f(5,0,0);
 glEnd();


    //cara delado 1zq
 glColor3f(0,1,0);
 glBegin(GL_POLYGON);
 glVertex3f(0,0,0);
 glVertex3f(0,5,0);
 glVertex3f(0,5,2);
 glVertex3f(0,0,2);
 glVertex3f(0,0,0);
 glEnd();


   //cara tras
 glColor3f(0,1,0);
 glBegin(GL_POLYGON);
 glVertex3f(0,0,2);
 glVertex3f(5,0,2);
 glVertex3f(5,5,2);
 glVertex3f(0,5,2);
 glVertex3f(0,0,2);
 glEnd();

 /* glColor3f(3,0,0);
 glBegin(GL_POLYGON);
 glVertex3f(3,1,.1f);
 glVertex3f(4,1,0);
 glVertex3f(4,2,0);
 glVertex3f(3,2,0);
  glVertex3f(3,1,0);
 glEnd();
 */

 glColor3f(0,1,0);
 glBegin(GL_POLYGON);
 glVertex3f(1,0,2);
 glVertex3f(1,-1,2);
 glVertex3f(4,-1,2);
 glVertex3f(4,0,2);
 glVertex3f(1,0,2);
 glEnd();

 glColor3f(0,1,0);
 glBegin(GL_POLYGON);
 glVertex3f(0,-1,2);
 glVertex3f(0,-1.5,2);
 glVertex3f(5,-1.5,2);
 glVertex3f(5,-1,2);
 glVertex3f(0,-1,2);
 glEnd();





 //******************************



  glColor3f(0,0,0);
 glBegin(GL_LINE_LOOP);
 glVertex3f(0,0,0);
 glVertex3f(5,0,0);
 glVertex3f(5,5,0);
 glVertex3f(0,5,0);
  glVertex3f(0,0,0);
 glEnd();



 //cara delado dr
 glColor3f(0,0,0);
glBegin(GL_LINE_LOOP);
 glVertex3f(5,0,0);
 glVertex3f(5,5,0);
 glVertex3f(5,5,2);
 glVertex3f(5,0,2);
 glVertex3f(5,0,0);
 glEnd();


    //cara delado 1zq
 glColor3f(0,0,0);
 glBegin(GL_LINE_LOOP);
 glVertex3f(0,0,0);
 glVertex3f(0,5,0);
 glVertex3f(0,5,2);
 glVertex3f(0,0,2);
 glVertex3f(0,0,0);
 glEnd();


   //cara tras
 glColor3f(0,0,0);
glBegin(GL_LINE_LOOP);
 glVertex3f(0,0,2);
 glVertex3f(5,0,2);
 glVertex3f(5,5,2);
 glVertex3f(0,5,2);
 glVertex3f(0,0,2);
 glEnd();


 glColor3f(0,0,0);
glBegin(GL_LINE_LOOP);
 glVertex3f(1,0,2);
 glVertex3f(1,-1,2);
 glVertex3f(4,-1,2);
 glVertex3f(4,0,2);
 glVertex3f(1,0,2);
 glEnd();

 glColor3f(0,0,0);
glBegin(GL_LINE_LOOP);
 glVertex3f(0,-1,2);
 glVertex3f(0,-1.5,2);
 glVertex3f(5,-1.5,2);
 glVertex3f(5,-1,2);
 glVertex3f(0,-1,2);
 glEnd();




glFlush();
glutSwapBuffers();
}
void idle()
{
display();
}

void init()
{
glClearColor(0,0,0,0);

}



void keyboard(unsigned char key, int x, int y)
 {
switch (key) {
 case 27:
 exit(0);
 break;
 }
}


void ArrowKey(int key, int x, int y){ 

switch(key){


case GLUT_KEY_RIGHT:
  
if( tras<2.5){tras =   tras + 0.2;}
if(tras>0.1 && tras<2){esc =tras;}

break;
case

GLUT_KEY_LEFT:

if( tras>-2.5){tras = tras- 0.2;}

if(tras>0.1 && tras<1){esc = tras;}


break;
}}
/*void handleSpecialKeyReleased(int key, int x, int y) {
 switch (key) {
 case GLUT_KEY_LEFT:
  angulo=0.0f;
  break;
 case GLUT_KEY_RIGHT:
  angulo=0.0f;
  break;
 }
}*/


int main(int argc, char **argv) 
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(500,60);
glutInitWindowSize(600,500);
glutCreateWindow("monitor");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
   glEnable(GL_DEPTH_TEST);
glutIdleFunc(idle);
glutKeyboardFunc(keyboard);
glutSpecialFunc(ArrowKey);

//glutSpecialUpFunc(handleSpecialKeyReleased);

glutMainLoop();


}




RESUMEN Y CONCEPTOS





Aspect ratio: 
La relación de aspecto, ratio, ratio de aspecto, proporción de aspecto o razón de aspecto (traducciones literales de la expresión en inglés aspect ratio) de una imagen es la proporción entre su ancho y su altura. Se calcula dividiendo el ancho por la altura de la imagen visible en pantalla, y se expresa normalmente como «X:Y».







Viewports o visor: 
Un viewport es una región rectangular visualización en gráficos de computadora, o un término utilizado para los componentes ópticos. Ventana de recorte o de visualizacion.
http://www.di.ubi.pt/~agomes/cg/teoricas/04e-windows.pdf







Pipeline Grafico: 
El Pipeline de renderizado de OpenGL
La mayor parte de las implementaciones de OpenGL siguen un mismo
orden en sus operaciones, una serie de plataformas de proceso, que en su
conjunto crean lo que se suele llamar el “OpenGL Rendering Pipeline”. La palabra renderización define un proceso de cálculo complejo desarrollado por un ordenador destinado a generar una imagen 2D a partir de una escena 3D. Así podría decirse que en el proceso de renderización, la
computadora "interpreta" la escena 3D y la plasma en una imagen 2D Este proceso se desarrolla con el fin de imitar un espacio 3D formado por estructuras poligonales, comportamiento de luces, texturas, materiales, animación, simulando ambientes y estructuras físicas verosímiles, etc
Cuando se trabaja en un programa de diseño 3D por computadora, no es posible visualizar en tiempo real el acabado final deseado de una escena 3D compleja ya que esto requiere una potencia de cálculo demasiado elevada. Por lo que se opta por crear el entorno 3D con una forma de visualización más simple y técnica y luego generar el lento proceso de renderización para
conseguir los resultados finales deseados.

El siguiente diagrama describe el funcionamiento del pipeline escena


. Luego se configuran las condiciones de iluminación, es decir posición, color, tipo y demás atributos de cada fuente de luz presente en la escena. Por último, se determina la posición y dirección del punto de vista o de la cámara a través de la cual se visualiza el ambiente. La visualización del ambiente en un dispositivo, como la pantalla de un monitor, es posible gracias a software y hardware especializado. Dicha especialización permite dibujar eficientemente sobre una pantalla bidimensional la proyección, comúnmente en perspectiva, de una escena tridimensional.



Pipeline de OpenGL: 
La mayoría de las implementaciones de OpenGL tienen un orden similar de operaciones, una serie de etapas de procesamiento de llamada de la canalización de representación de OpenGL.Este orden, como se muestra en la Figura , no es una regla estricta de cómo se implementa OpenGL, pero proporciona una guía confiable para predecir lo que va a hacer OpenGL.





Transformaciones en OpenGL

OpenGL y las bibliotecas asociadas componen por nosotros las transformaciones necesarias para posicionar los objetos, las luces y la cámara en la escena, para luego proyectarlos y armar la imagen.
Debemos recordar que OpenGL funciona como máquina de estados: lo primero que se lee en el programa se aplica a todo lo que sigue, por lo tanto es lo último que se hace.
Dispositivo de salida y ventana:
La ventana en el dispositivo de salida se define al inicializar el subprograma gráfico, cuando se pideuna ventana al sistema operativo. Con GLUT se hace así:
glutInitWindowSize(width, height); glutInitWindowPosition(x, y);
 los parámetros son coordenadas y tamaños (enteros) en el sistema de coordenadas del
dispositivo o imagen donde se vaya a renderizar (device coordinates). Hay que recordar que para glut, para el SO, y para los programas de imágenes: 0,0 = upper,left.
Esta primera llamada es la última transformación que sufre el modelo, la que mapea la ventana de dibujo en el dispositivo de salida. En este caso se trata de una salida al monitor, pero bien podría haber sido a una impresora o un buffer en memoria que se guardará como imagen. Siendo una salida al monitor, esta transformación se define solamente en la inicialización (notar el glutInit…) luego es el sistema operativo el que maneja el movimiento y cambio de tamaño de la ventana del programa.
La penúltima transformación es la que mapea la parte del espacio visible en un viewport o ventana de dibujo con sus coordenadas de ventana (window coordinates), permite rasterizar y proyectar: glViewport(x, y, width, height)
los números, enteros, definen el rectángulo en píxeles referidos a la ventana del programa, donde se dibujaran los objetos. Para OpenGL el origen es lower,left.
Si glViewport no esta presente, se considera que es toda la ventana del programa.
El tamaño del viewport cambia junto con el tamaño de la ventana del programa, por lo tanto solo aparece en la rutina que maneja el resize. Es el programador el que decide como cambiar la ventana de dibujo cuando el usuario cambia la del programa.



Clipping: 
Es el fenómeno que se produce cuando un cuerpo sólido atraviesa otro "sin romperlo", es decir, si por ejemplo un personaje está pegado a la pared de una habitación y un brazo o parte de su cuerpo puede verse al otro lado de la pared. El clipping puede ser sólo parcial o total, es decir, tomando el ejemplo de antes, si el brazo atraviesa la pared pero no podemos interactuar con él se trata de un clipping parcial.



Proyeccion: 
La proyección es la representación gráfica de un objeto sobre una superficie plana, obtenida al unir las intersecciones sobre dicho plano de las líneas proyectantes de todos los puntos del objeto desde el vértice.

La proyección de objetos tridimensionales es definida por rayos de proyección rectos, llamados proyectores, que emanan de un centro de proyección, pasan por cada punto del objeto e intersecan un plano de proyección para formar la proyección. Por lo general, el centro de proyección se encuentra a una distancia finita del plano de proyección. Sin embargo, en algunos tipos de proyecciones es conveniente pensar en función de un centro de proyección que tienda a estar infinitamente lejos.






Rasterizacion: 
http://www.cimec.org.ar/twiki/pub/Cimec/ComputacionGrafica/transformaciones_practica.pdf















DIFERENCIA  ENTRE ROTACION ENTRE UN PUNTO FIJO
el movimiento de cambio de orientación de un cuerpo o un sistema de referencia de forma que una línea (llamada eje de rotación) o un punto que permanece fijo
Para poder girar un objeto de nuestra escena lo haremos con la función glrotatef(alpha,x,y,z) donde alpha serán los grados que queremos que se roten respecto el eje x, y,z. 
y ahora dibujaríamos el objeto o objetosque queremos que se roten.

#include "stdafx.h"

#include <stdlib.h>

#include <GL/glut.h>
//GLfloat anguloCuboX = 0.0f;
GLfloat anguloCuboY = 0.0f;
GLfloat anguloEsfera = 0.0f;
GLint ancho=400;
GLint alto=400;
int hazPerspectiva = 0;
void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    if(hazPerspectiva)
     gluPerspective(60.0f, (GLfloat)width/(GLfloat)height, 1.0f, 20.0f);
    else

      glOrtho(-4,4, -4, 4, 1, 10);

    glMatrixMode(GL_MODELVIEW);
    ancho = width;
    alto = height;
}
void drawCube(void)
{
    glColor3f(1.0f, 0.0f, 0.0f);
    glBegin(GL_QUADS);       //cara frontal
    glVertex3f(-1.0f, -1.0f,  1.0f);
    glVertex3f( 1.0f, -1.0f,  1.0f);
    glVertex3f( 1.0f,  1.0f,  1.0f);
    glVertex3f(-1.0f,  1.0f,  1.0f);

    glEnd();

    glColor3f(0.0f, 1.0f, 0.0f);

    glBegin(GL_QUADS);       //cara trasera
    glVertex3f( 1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-1.0f,  1.0f, -1.0f);
    glVertex3f( 1.0f,  1.0f, -1.0f);

    glEnd();

    glColor3f(0.0f, 0.0f, 1.0f);
    glBegin(GL_QUADS);       //cara lateral izq
    glVertex3f(-1.0f,-1.0f, -1.0f);
    glVertex3f(-1.0f,-1.0f,  1.0f);
    glVertex3f(-1.0f, 1.0f,  1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glEnd();

    glColor3f(1.0f, 1.0f, 0.0f);
    glBegin(GL_QUADS);       //cara lateral dcha
    glVertex3f(1.0f, -1.0f,  1.0f);
    glVertex3f(1.0f, -1.0f, -1.0f);
    glVertex3f(1.0f,  1.0f, -1.0f);
    glVertex3f(1.0f,  1.0f,  1.0f);
    glEnd(); 
    glColor3f(0.0f,      1.0f, 1.0f);
    glBegin(GL_QUADS);       //cara arriba
    glVertex3f(-1.0f, 1.0f,  1.0f);
    glVertex3f( 1.0f, 1.0f,  1.0f);
    glVertex3f( 1.0f, 1.0f, -1.0f);
    glVertex3f(-1.0f, 1.0f, -1.0f);
    glEnd();
    glColor3f(1.0f, 0.0f, 1.0f);
    glBegin(GL_QUADS);       //cara abajo
    glVertex3f( 1.0f,-1.0f, -1.0f);
    glVertex3f( 1.0f,-1.0f,  1.0f);
    glVertex3f(-1.0f,-1.0f,  1.0f);
    glVertex3f(-1.0f,-1.0f, -1.0f);
    glEnd();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -5.0f);
    //glRotatef(anguloCuboX, 1.0f, 0.0f, 0.0f);
    glRotatef(anguloCuboY, 0.0f, 1.0f, 0.0f);
    drawCube();
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -5.0f);
    glRotatef(anguloEsfera, 0.0f, 1.0f, 0.0f);
    glTranslatef(3.0f, 0.0f, 0.0f);
    glColor3f(1.0f, 1.0f, 1.0f);
    glutWireSphere(0.5f, 8, 8);
    glFlush();
    glutSwapBuffers();
    //anguloCuboX+=0.1f;
    anguloCuboY-=0.1f;
    anguloEsfera+=0.2f;
}

void init()
{
    glClearColor(0,0,0,0);
    glEnable(GL_DEPTH_TEST);
    ancho = 400;
    alto = 400;
}

void idle()
{
    display();
}
void keyboard(unsigned char key, int x, int y)
{
    switch(key)
    {
    case 'p':
    case 'P':
      hazPerspectiva=1;
      reshape(ancho,alto);
      break;
    case 'o':
    case 'O':
      hazPerspectiva=0;
      reshape(ancho,alto);
      break;
    case 27:   // escape
      exit(0);
      break;
    }
}
int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(ancho, alto);
    glutCreateWindow("Cubo 1");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
    glutKeyboardFunc(keyboard);
    glutMainLoop();
    return 0;
}




SECUENCIA

Las herramientas matemáticas utilizada para realizar la variación de la posición y/o
el tamaño de los objetos, con respecto a los sistemas de referencia, son
Las transformaciones lineales que se expondrán serán las siguientes: traslación, cambio de escala, giro, y reflexión.

En la Informática Gráfica suele utilizarse la notación matricial para describir las
transformaciones lineales de los objetos. La convención más utilizada es que el
punto (vértice) que se va a transformar, se exprese mediante un vector horizontal
multiplicado por la matriz de transformación. Por ejemplo, en la expresión (x’, y’) =
(x, y)·M, la matriz correspondiente a la transformación lineal estaría indicada por
M; el punto inicial (antes de la transformación) sería el (x, y), y el resultado (o sea,
la ubicación del punto en el sistema de referencia después de la transformación
lineal) sería el (x’, y’).

PILAS

es un almacén con funcionamiento LIFO, el último en entrar es el primero en
salir, por lo que suele comparar a una pila de platos en la que sólo se puede dejar uno encima
de la pila o coger el superior que es el último depositado. La pila de matrices tiene el mismo
funcionamiento sustituyendo los platos por matrices. La matriz superior de la pila es sobre la
que se aplican las distintas transformaciones, multiplicándola por la matriz que generan las
disntintas funciones.
Para poder guardar una determinada matriz y posteriormente recuperarla OpenGL
dispone de las dos funciones comentadas: glPushMatrix() "apilar" y glPopMatrix() "desapilar".La función glPushMatrix() realiza una copia de la matriz superior y la pone encima de
la pila, de tal forma que las dos matrices superiores son iguales. En la figura 1 se observa la
pila en la situación inicial con una sola matriz, al llamar a la función glPushMatrix() se
duplica la matriz superior. Las siguientes transformaciones que se realizan se aplican sólo a la
matriz superior de la pila, quedando la anterior con los valores que tenía en el momento de
llamar a la función glPushMatrix().
La función glPopMatrix() elimina la matriz superior, quedando en la parte superior de
la pila la matriz que estaba en el momento de llamar a la función glPushMatrix().



transformaciones geométricas
 


TRANSFORMACIONES
TRANSFORMACIONES GEOMETRICAS
Primero de todo que son las transformaciones, tal y como indica el nombre es una transformación que hacemos a un objeto de nuestra escena por ejemplo darle la vuelta en este caso estamos hacemos una transformación de rotación, también podemos escalar el objeto y trasladarlo de un sitio a otro.
Bueno manos a la obra voy a explicar estos tres tipos de transformaciones Escalar, Trasladar, Rotar. 
ESCALAR
Para escalar un objeto utilizaremos la función glScalef(x,y,z) . Definiremos el escalado de cada uno de los ejes. 
Por ejemplo si queremos escalar un objeto en 2 unidades :

glScalef( 2,2,2)
y aqui dibujaremos el objeto o objetos que queremos que se aplique este escalado.
TRASLADAR
Para trasladar un objeto de nuestra escena lo haremos mediante la función glTranslatef(x,y,z). 
Por ejemplo si queremos desplazar un objeto en el eje de la x 100 unidades, escribiremos:
glTranslatedf(100,0,0)
y ahora dibujaríamos el o los objetos que queremos que se aplique este traslado.
ROTAR
Para poder girar un objeto de nuestra escena lo haremos con la función glrotatef(alpha,x,y,z) donde alpha serán los grados que queremos que se roten respecto el eje x, y,z. 
Por ejemplo si queremos rotar 45 grados respecto el eje de coordenadas z, lo haremos de la siguiente manera:


#include "stdafx.h"
#include <stdlib.h>
#include <GL/glut.h>


GLfloat escala = 1.0f;
GLfloat bandescal = 1.0f;// bandescal=1 aumenta  bandescal=0  disminuye
GLfloat band = 10.0f;
GLfloat angulox = 0.0f;
GLfloat anguloy = 0.0f;

GLfloat traslada= 0.0f;
int bandescala=0; // bandera = 1;- en +X,bandera = 0;- en -X


void spinCube()

{


angulox += 2.0;

 if( angulox > 360.0 ) angulox -= 360.0;
 if( bandescal==1) escala+=0.10f;
  else  escala-=0.10f;
 if( escala==.10) bandescal=1;
  if (escala==3) bandescal=0;

  if (traslada>100) traslada-=100;
  if( band==1) traslada+=10.0f;
  else  traslada-=10.0f;
 if( traslada==10.0f) band=1;
  if (traslada==100) bandescal=0;
      
glutPostRedisplay();
}

void reshape(int width, int height)
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-15,15,-15,15,-15,15);
glMatrixMode(GL_MODELVIEW);
}
void piramide(void)
{
glBegin(GL_TRIANGLES);
glColor3f(1,1,0);
glVertex3f(0.0f,-3.0f,-1.5f);
glVertex3f(-1.5f,0.0f,0.0f);
glVertex3f(1.5f,0.0f,0.0f);
glEnd();
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.6f,1.0f);
glVertex3f(-1.5f,0.0f,0.0f);
glVertex3f(1.5f,0.0f,0.0f);
glVertex3f(0.0f,-1.5f,1.5f);

glBegin(GL_TRIANGLES);
glColor3f(0,0,1);
glVertex3f(0.0f,-3.0f,-1.5f);
glVertex3f(1.5f,0.0f,0.0f);
glVertex3f(0.0f,-1.5f,1.5f);
glEnd();
glBegin(GL_TRIANGLES);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f,-3.0f,-1.5f);
glVertex3f(0.0f,-1.5f,1.5f);
glVertex3f(-1.5f,0.0f,0.0f);
glEnd();
}

void display()
{
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
glTranslatef(traslada,0.0f,0.0f);
glScalef(escala, escala, escala);

glRotatef(angulox, 1.0f, 0.0f, 0.0f);
glRotatef(anguloy, 0.0f, 1.0f, 0.0f);
piramide();
glFlush();
glutSwapBuffers();

angulox+=0.1f;//aserotarmoverse
anguloy+=0.1f;

GLfloat angulox = 0.0f; // variable para el angulo x

}
void init()
{
glClearColor(0,0,0,0);
glEnable(GL_DEPTH_TEST);
}
void idle()
{
display();
}

int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowPosition(500,60);
glutInitWindowSize(600,500);
glutCreateWindow("triangulo piramide");
init();
glutDisplayFunc(display);
glutIdleFunc(spinCube);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}