[Tutorial] III.7 - Las dos caras del polígono, triángulos STRIP y FAN
2 participantes
Página 1 de 1.
[Tutorial] III.7 - Las dos caras del polígono, triángulos STRIP y FAN
III.7 Las dos caras del polígono, triángulos STRIP y FAN
Novedades:
En realidad, no hay demasiado añadido respecto al código de la lección anterior, pero para no agobiar, lo añadimos ahora. Son pocas pocas, pero influyen mucho. Hay dos caras para todo polígono, delantera y trasera, hasta ahora, por defecto, se pintan ambas, pero podemos definir que solo se pinta una cara (suponiendo que la otra nunca va a ser vista) y ahorrar cálculos. Aquí el código, esta vez es mejor que no lo pruebes hasta leer toda la explicación.
Repasemos las novedades, no vamos a ir en orden según el código, lo haré a mi manera, primero la parte independiente de las caras ocultas, que es más complejo.
Los triángulos FAN son parecidos a los STRIP, el ejemplo común que se dice siempre es que genera abanicos. La explicación es que, los 3 primeros vértices forman un triángulo, y partir de ahí con cada nuevo vértice, se genera un nuevo triángulo con el nuevo vértice, el anterior y el primero. A compartir todos los triángulo un punto, parece una abanico, pero en general se usa para hacer circunferencias. En el ejemplo va en el sentido de las agujas del reloj.
Otra cosa que habrás notado, es un glShadeModel(GL_FLAT) al principio, si ejecutas el programa, verás que entre vértice y vértice no se produce esa gama de color que hay en los otros polígonos de antes. Con esa función puedes desactivar el sombreado, que así se llama, con glShadeModel(GL_SMOOTH) vuelves a activar el sombreado, como antes.
Ahora si, analicemos esto:
Novedades:
- Uso de GL_TRIANGLE_STRIP en glBegin()
- Uso de GL_TRIANGLE_FAN en glBegin()
- Uso de GL_CULL_FACE en glEnable()
- glFrontFace()
- glPolygonMode()
- glShadeModel()
En realidad, no hay demasiado añadido respecto al código de la lección anterior, pero para no agobiar, lo añadimos ahora. Son pocas pocas, pero influyen mucho. Hay dos caras para todo polígono, delantera y trasera, hasta ahora, por defecto, se pintan ambas, pero podemos definir que solo se pinta una cara (suponiendo que la otra nunca va a ser vista) y ahorrar cálculos. Aquí el código, esta vez es mejor que no lo pruebes hasta leer toda la explicación.
- Código:
#include <GL/glut.h>
typedef struct {
GLfloat verticeXYZ[3];
GLfloat colorRGB[3];
} Vertice;
typedef struct {
float x,y;
int izda, dcha;
} EstadoRaton;
Vertice cuadrado[4] = {
{{1,0,0},{1,0,0}},
{{5,-4,0},{1,1,0}},
{{9,0,0},{0,1,0}},
{{5,4,0},{0,0,1}}
};
Vertice triangulo[3] = {
{{-9,4,0},{1,0,0}},
{{-5,-4,0},{0,1,0}},
{{-1,4,0},{0,0,1}}
};
/* El triángulo sigue el sentido CCW, contra el sentido del reloj:
* 0-------2
* \ /
* \ /
* 1
*/
Vertice selector = {{-9,4,0},{1,1,1}};
EstadoRaton raton;
int ventana[2], vertice_sel;
GLfloat formato_global;
int cull, sentido, linear;
void IniciarGLUT() {
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600,600);
glutInitWindowPosition(100,100);
glutCreateWindow("Practica III,7 de OpenGL");
}
void PintarEscena() {
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
if (cull) glEnable(GL_CULL_FACE);
else glDisable(GL_CULL_FACE);
if (sentido) glFrontFace(GL_CW);
else glFrontFace(GL_CCW);
if (linear) glPolygonMode(GL_BACK,GL_LINE);
else glPolygonMode(GL_BACK,GL_FILL);
glShadeModel(GL_FLAT);
glBegin(GL_TRIANGLE_STRIP);
glColor3f(1,0,0);
glVertex3i(-9,9,0);
glVertex3i(-8,8,0);
glVertex3i(-7,9,0);
glColor3f(0,1,0);
glVertex3i(-6,8,0);
glColor3f(0,0,1);
glVertex3i(-5,9,0);
glEnd();
glBegin(GL_TRIANGLE_FAN);
glColor3f(1,0,0);
glVertex3i(8,8,0);
glVertex3i(6,8,0);
glVertex3i(7,9,0);
glColor3f(0,1,0);
glVertex3i(9,9,0);
glColor3f(0,0,1);
glVertex3i(10,8,0);
glEnd();
glShadeModel(GL_SMOOTH);
int i;
glBegin(GL_TRIANGLES);
for (i=0; i<3; i++) {
glColor3fv(triangulo[i].colorRGB);
glVertex3fv(triangulo[i].verticeXYZ);
}
glEnd();
glBegin(GL_QUADS);
for (i=0; i<4; i++) {
glColor3fv(cuadrado[i].colorRGB);
glVertex3fv(cuadrado[i].verticeXYZ);
}
glEnd();
glPointSize(7);
glBegin(GL_POINTS);
glColor3fv(selector.colorRGB);
glVertex3fv(selector.verticeXYZ);
glEnd();
glutSwapBuffers();
}
void ReProyectar(int w, int h) {
GLfloat formato;
ventana[0] = w;
ventana[1] = h;
if(h == 0) h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
formato = (GLfloat)w / (GLfloat)h;
formato_global = formato;
if (w <= h) glOrtho (-10.0f, 10.0f, -10.0f / formato, 10.0f / formato, -1.0f, 1.0f);
else glOrtho (-10.0f * formato, 10.0f * formato, -10.0f, 10.0f, -1.0f, 1.0f);
}
float ObtenerPosPlanoX(float x, int ancho_ventana, int alto_ventana, float pos_x_min, float pos_x_max, float format) {
float pos_x_relativa = ((float)x/ancho_ventana); //La posición relativa de 0 a 1 en X
float pos_plano;
if (ancho_ventana<=alto_ventana) pos_plano = (pos_x_min+((pos_x_max-pos_x_min)*pos_x_relativa));
else pos_plano = ((pos_x_min * format)+(((pos_x_max-pos_x_min) * format)*pos_x_relativa));
return pos_plano;
}
float ObtenerPosPlanoY(float y, int ancho_ventana, int alto_ventana, float pos_y_min, float pos_y_max, float format) {
float pos_y_relativa = ((float)y/alto_ventana); //La posición relativa de 0 a 1 en Y
float pos_plano;
if (ancho_ventana<=alto_ventana) pos_plano = -((pos_y_min / format)+(((pos_y_max-pos_y_min) / format)*pos_y_relativa));
else pos_plano = -(pos_y_min+((pos_y_max-pos_y_min)*pos_y_relativa));
return pos_plano;
}
void ControlRaton(int button, int state, int x, int y) {
if (button==GLUT_LEFT_BUTTON) {
if (state==GLUT_DOWN) raton.izda = 1;
else raton.izda = 0;
}
else if (button==GLUT_RIGHT_BUTTON) {
if (state==GLUT_DOWN) {
raton.dcha = 1;
raton.x = ObtenerPosPlanoX(x,ventana[0],ventana[1],-10,10,formato_global);
raton.y = ObtenerPosPlanoY(y,ventana[0],ventana[1],-10,10,formato_global);
int i;
for (i=0; i<3; i++) {
if (raton.x > triangulo[i].verticeXYZ[0] - 0.5f &&
raton.x < triangulo[i].verticeXYZ[0] + 0.5f &&
raton.y > triangulo[i].verticeXYZ[1] - 0.5f &&
raton.y < triangulo[i].verticeXYZ[1] + 0.5f ) {
vertice_sel = i;
}
}
for (i=0; i<4; i++) {
if (raton.x > cuadrado[i].verticeXYZ[0] - 0.5f &&
raton.x < cuadrado[i].verticeXYZ[0] + 0.5f &&
raton.y > cuadrado[i].verticeXYZ[1] - 0.5f &&
raton.y < cuadrado[i].verticeXYZ[1] + 0.5f ) {
vertice_sel = 3 + i;
}
}
}
else raton.dcha = 0;
}
}
void MovimRaton(int x, int y) {
raton.x = ObtenerPosPlanoX(x,ventana[0],ventana[1],-10,10,formato_global);
raton.y = ObtenerPosPlanoY(y,ventana[0],ventana[1],-10,10,formato_global);
}
void MoverVertice(int value) {
switch (vertice_sel) {
case 0: case 1: case 2:
selector.verticeXYZ[0] = triangulo[vertice_sel].verticeXYZ[0];
selector.verticeXYZ[1] = triangulo[vertice_sel].verticeXYZ[1];
break;
case 3: case 4: case 5: case 6:
selector.verticeXYZ[0] = cuadrado[vertice_sel-3].verticeXYZ[0];
selector.verticeXYZ[1] = cuadrado[vertice_sel-3].verticeXYZ[1];
break;
}
if (raton.izda) {
if (vertice_sel<=2) {
triangulo[vertice_sel].verticeXYZ[0] = selector.verticeXYZ[0] = raton.x;
triangulo[vertice_sel].verticeXYZ[1] = selector.verticeXYZ[1] = raton.y;
}
else {
cuadrado[vertice_sel-3].verticeXYZ[0] = selector.verticeXYZ[0] = raton.x;
cuadrado[vertice_sel-3].verticeXYZ[1] = selector.verticeXYZ[1] = raton.y;
}
}
glutTimerFunc(33,MoverVertice,1);
glutPostRedisplay();
}
void Teclado(unsigned char key, int x, int y) {
switch(key) {
case 99: cull = !cull; break; //Letra c
case 119: sentido = !sentido; break; //Letra w
case 108: linear = !linear; break; //Letra l
}
}
int main(int argc, char **argv) {
glutInit(&argc,argv); //Solo necesario en Linux
IniciarGLUT();
glutReshapeFunc(ReProyectar);
glutDisplayFunc(PintarEscena);
glutIdleFunc(PintarEscena);
glutMouseFunc(ControlRaton);
glutTimerFunc(33,MoverVertice,1);
glutMotionFunc(MovimRaton);
glutKeyboardFunc(Teclado);
glutMainLoop();
return 0;
}
Repasemos las novedades, no vamos a ir en orden según el código, lo haré a mi manera, primero la parte independiente de las caras ocultas, que es más complejo.
- Código:
glShadeModel(GL_FLAT);
glBegin(GL_TRIANGLE_STRIP);
glColor3f(1,0,0);
glVertex3i(-9,9,0);
glVertex3i(-8,8,0);
glVertex3i(-7,9,0);
glColor3f(0,1,0);
glVertex3i(-6,8,0);
glColor3f(0,0,1);
glVertex3i(-5,9,0);
glEnd();
glBegin(GL_TRIANGLE_FAN);
glColor3f(1,0,0);
glVertex3i(8,8,0);
glVertex3i(6,8,0);
glVertex3i(7,9,0);
glColor3f(0,1,0);
glVertex3i(9,9,0);
glColor3f(0,0,1);
glVertex3i(10,8,0);
glEnd();
glShadeModel(GL_SMOOTH);
Los triángulos FAN son parecidos a los STRIP, el ejemplo común que se dice siempre es que genera abanicos. La explicación es que, los 3 primeros vértices forman un triángulo, y partir de ahí con cada nuevo vértice, se genera un nuevo triángulo con el nuevo vértice, el anterior y el primero. A compartir todos los triángulo un punto, parece una abanico, pero en general se usa para hacer circunferencias. En el ejemplo va en el sentido de las agujas del reloj.
Otra cosa que habrás notado, es un glShadeModel(GL_FLAT) al principio, si ejecutas el programa, verás que entre vértice y vértice no se produce esa gama de color que hay en los otros polígonos de antes. Con esa función puedes desactivar el sombreado, que así se llama, con glShadeModel(GL_SMOOTH) vuelves a activar el sombreado, como antes.
Ahora si, analicemos esto:
- Código:
if (cull) glEnable(GL_CULL_FACE);
else glDisable(GL_CULL_FACE);
if (sentido) glFrontFace(GL_CW);
else glFrontFace(GL_CCW);
if (linear) glPolygonMode(GL_BACK,GL_LINE);
else glPolygonMode(GL_BACK,GL_FILL);
Re: [Tutorial] III.7 - Las dos caras del polígono, triángulos STRIP y FAN
todo esto es usando opg y c++ vdd? y no tiene para java?????
ivolk- Cantidad de envíos : 1
Fecha de inscripción : 13/10/2012
Temas similares
» [Tutorial] III.6 - Triangulos, cuadrilateros y glutMotionFunc()
» [Tutorial] III.4 - Lineas STRIP y LOOP, y cambiar el grosor
» [Tutorial] III.6 - Triangulos, cuadrilateros y glutMotionFunc() - Parte 2
» [Tutorial] II.4 - glutKeyboardFunc()
» [Tutorial] II.5 - glutSpecialFunc()
» [Tutorial] III.4 - Lineas STRIP y LOOP, y cambiar el grosor
» [Tutorial] III.6 - Triangulos, cuadrilateros y glutMotionFunc() - Parte 2
» [Tutorial] II.4 - glutKeyboardFunc()
» [Tutorial] II.5 - glutSpecialFunc()
Página 1 de 1.
Permisos de este foro:
No puedes responder a temas en este foro.