Skip to content

Commit f76e615

Browse files
committed
Update README.md
1 parent 1a7d9fe commit f76e615

File tree

1 file changed

+213
-0
lines changed

1 file changed

+213
-0
lines changed

chapter-2/README.md

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,217 @@
11
# Capítulo 2
2+
En este capítulo se abordan diversos temas enfocados al despliegue 3D y se explican las funciones de OpenGL para poder llevar este proceso a cabo. Sin embargo, muchas de estas funciones se encuentran obsoletas, en el siguiente capitulos se verán las más recientes.
3+
4+
### Despliegue
5+
6+
En informática gráfica, el despliegue se define como un proceso de generación de una imagen que representa a una escena, bien sea 2D o 3D, en un dispositivo de salida. Este proceso también se conoce con el nombre de *rendering*. Generalmente, las escenas están compuestas por un conjunto de modelos, estos se definen mediante archivos o por algoritmos que los generen. Dichas escenas suelen contener información de geometría, material, movimiento, ubicación espacial, entre otros, que lo describen. El conjunto de etapas que se realizan en dicho proceso es conocido como *pipeline gráfico*.
7+
8+
### Pipeline gráfico
9+
10+
La denominación pipeline hace referencia a que las etapas se encuentran secuenciadas y que el conjunto de ellas puede verse como una línea de producción de una fábrica. Cada operación corresponde a una estación de trabajo. Cada estación, o etapa, toma como entradas las salidas de la estación anterior, y produce salidas que sirven de entradas para la subsiguiente. Esta relación permite cierto grado de paralelismo. Las estaciones pueden estar todas trabajando simultáneamente si el pipeline es correctamente alimentado; claro esta, cada etapa sobre un conjunto de datos diferente.
11+
12+
El pipeline gráfico puede modelarse de manera genérica en tres etapas descritas a continuación:
13+
* Transformaciones
14+
* Mundo
15+
* Vista
16+
* Proyección
17+
* Ensamblado, recorte y mapeo a pantalla
18+
* Rasterización
19+
20+
### Matrices
21+
22+
#### Modelo
23+
24+
Se pueden aplicar varias transformaciones geométricas a un objeto utilizando matrices. Si se tiene que girar un objeto, se multiplican sus coordenadas por una matriz de rotación, lo mismo ocurre con la traslación y el escalamiento. El orden en que se aplican estas transformaciones es esencial. Se consiguen diferentes resultados si trasladamos y rotamos a un objeto, que si se empieza haciendo girar el objeto y luego se traslada el resultado.
25+
26+
Desde un punto de vista matemático, aplicar dos o más transformaciones a un objeto se puede hacer multiplicando las coordenadas del objeto con las matrices elementales una por una. Alternativamente, se puede utilizar una sola matriz, que contiene todas las transformaciones anteriores.
27+
28+
Las transformaciones básicas son:
29+
30+
##### Traslación (T)
31+
##### Rotación (R)
32+
##### Escalamiento (S)
33+
34+
Para generar la matriz de modelo correcta, se tendria que multiplicar en el siguiente orden las matrices anteriormente expuestas (M = T * R * S)
35+
36+
Tenga en cuenta que las matrices anteriores son 4x4 y no 3x3. Esto es porque la matriz de traslación no se puede escribir como una matriz 3x3 y usamos un truco matemático para expresar las transformaciones anteriores como multiplicaciones de matrices. Una consecuencia interesante de trabajar con matrices 4x4 en lugar de 3x3, es que no podemos multiplicar un vértice 3D, expresado como un vector columna 3x1, con las matrices anteriores. En su lugar vamos a utilizar las llamadas *coordenadas homogéneas*, donde un vértice 3D se puede expresar como un vector columna de 4x1. Desde nuestro punto de vista, esto simplemente significa que vamos a escribir un vértice 3D como:
37+
38+
#### Vista
39+
40+
Por defecto, en OpenGL, el espectador se coloca en el eje z, es como usar una cámara para tomar una foto. La cámara apunta al origen del sistema cartesiano. La dirección hacia arriba es paralela al eje Oy y en el sentido positivo de Oy.
41+
42+
La matriz de vista controla la manera en que vemos una escena. En este capítulo vamos a utilizar una matriz que simula una cámara en movimiento, por lo general llamado lookAt. Esta matriz es determinada por 3 parámetros:
43+
44+
* El ojo, o la posición del espectador;
45+
* El centro, o el punto en el que la cámara tiene como objetivo;
46+
* El up, que define la dirección de up para el espectador.
47+
48+
Los valores por defecto en OpenGL son: el ojo en (0, 0, -1); el centro en (0, 0, 0) y el up está dada por la dirección positiva del eje Oy (0, 1, 0).
49+
50+
La matriz de vista V, multiplica la matriz de modelo y, básicamente, se alinea el mundo (los objetos de una escena) a la cámara (MV = V * M)
51+
52+
```c++
53+
int main(void)
54+
{
55+
// ...
56+
glMatrixMode(GL_MODELVIEW);
57+
glLoadIdentity();
58+
gluLookAt(3.0f, 3.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
59+
// ...
60+
}
61+
```
62+
63+
#### Proyección
64+
65+
Por defecto, en OpenGL, un objeto parecera tener el mismo tamaño, sin importar dónde se coloca la cámara. Esto va en contra de la experiencia cotidiana, donde un objeto más cercano a nosotros (a la cámara) se ve más grande que un objeto que se encuentra a una distancia mayor.
66+
67+
Sin embargo, se puede ampliar o reducir el volumen de recorte a través del uso de una matriz de proyección, cuando el volumen de recorte tiene la forma de un paralelepípedo, o una caja, se dice que se emplea una proyección ortográfica. La proyección ortográfica no modificará el tamaño de los objetos, sin importar dónde se coloca la cámara. Esta es una característica deseable para los programas de CAD o para juegos 2D.
68+
69+
Otra matriz de proyección, que puede mejorar la sensación de mundo real, es la matriz de proyección en perspectiva, en este caso el volumen es un *frustum* y no un paralelepípedo.
70+
71+
La matriz de proyección de perspectiva se especifica generalmente a través de cuatro parámetros:
72+
73+
* Campo de visión (generalmente abreviado como *FOV*)
74+
* Relación de aspecto
75+
* Planos cerca y lejos (recorte)
76+
77+
La matriz de proyección P, multiplica el producto de la matriz de vista y la de modelo de modelo (MVP = P * V * M)
78+
79+
```c++
80+
void reshape(GLFWwindow *window, int width, int height)
81+
{
82+
// ...
83+
glMatrixMode(GL_PROJECTION);
84+
glLoadIdentity();
85+
gluPerspective(45.0f, (float)gWidth / (float)gHeight, 1.0f, 1000.0f);
86+
87+
glMatrixMode(GL_MODELVIEW);
88+
// ...
89+
}
90+
```
91+
92+
### Modelos 3D
93+
94+
Un modelo 3D es la representación tridimensional de uno o varios objetos, el cual contiene información de geometría, conmumente vertices y caras. Adicionalmente un modelo 3D puede contener normales, coordenadas de texturas, tipo de material, etc. Dichos modelos pueden ser generador por algún algoritmo o estar distinguidos por un archivo. Existen varios formatos de archivo para representar modelos 3D. Unos de los formatos más conocidos y sencillos son el OFF y el OBJ.
95+
96+
En este tutorial se empleara una simplifación del formato OFF, llamado SOFF (creado para propositos de este tutorial). En el cual las caras siempre están compuestas por tres vertices que se encuentran especificados directamente, es decir, se podrian repetir.
97+
98+
A continuación se presenta un cubo en formato SOFF
99+
100+
```
101+
SOFF
102+
36
103+
-1.0f -1.0f -1.0
104+
-1.0f -1.0f 1.0f
105+
-1.0f 1.0f 1.0f
106+
1.0f 1.0f -1.0f
107+
-1.0f -1.0f -1.0f
108+
-1.0f 1.0f -1.0f
109+
1.0f -1.0f 1.0f
110+
-1.0f -1.0f -1.0f
111+
1.0f -1.0f -1.0f
112+
1.0f 1.0f -1.0f
113+
1.0f -1.0f -1.0f
114+
-1.0f -1.0f -1.0f
115+
-1.0f -1.0f -1.0f
116+
-1.0f 1.0f 1.0f
117+
-1.0f 1.0f -1.0f
118+
1.0f -1.0f 1.0f
119+
-1.0f -1.0f 1.0f
120+
-1.0f -1.0f -1.0f
121+
-1.0f 1.0f 1.0f
122+
-1.0f -1.0f 1.0f
123+
1.0f -1.0f 1.0f
124+
1.0f 1.0f 1.0f
125+
1.0f -1.0f -1.0f
126+
1.0f 1.0f -1.0f
127+
1.0f -1.0f -1.0f
128+
1.0f 1.0f 1.0f
129+
1.0f -1.0f 1.0f
130+
1.0f 1.0f 1.0f
131+
1.0f 1.0f -1.0f
132+
-1.0f 1.0f -1.0f
133+
1.0f 1.0f 1.0f
134+
-1.0f 1.0f -1.0f
135+
-1.0f 1.0f 1.0f
136+
1.0f 1.0f 1.0f
137+
-1.0f 1.0f 1.0f
138+
1.0f -1.0f 1.0f
139+
```
140+
141+
Y su cargador
142+
143+
```c++
144+
bool CSOff::load(string path)
145+
{
146+
fstream file;
147+
string token;
148+
149+
file.open(path, std::ios::in);
150+
151+
file >> token;
152+
153+
if (token != "SOFF")
154+
{
155+
file.close();
156+
return false;
157+
}
158+
else
159+
{
160+
file >> token;
161+
mNumOfVertices = 3 * atoi(token.c_str());
162+
163+
mVertices = new float[mNumOfVertices];
164+
165+
for (int i = 0; i < mNumOfVertices; i++)
166+
{
167+
file >> token;
168+
mVertices[i] = float(atof(token.c_str()));
169+
}
170+
171+
file.close();
172+
return true;
173+
}
174+
}
175+
```
176+
177+
De forma similar al anterior cápitulo con las figuras, se puede crear la clase modelo `CModel`, de esta pueden heredar un cojunto de formatos de modelos (OFF, OBJ, 3DS, MDL, MD2, MD3, MD5, Collada, etc) ya que todas estas tienen atributos y metodos en común. De este modo se podrian agrupar todos los modelos en un vector `vector <CModel *> models` facilitando su manipulación. Como el metodo de carga varía según el formato, la clase modelo tiene un metodo virtual puro `load`. Sin embargo, el despliegue `display` suele ser el mismo, por lo tanto podría implementar en modelo.
178+
179+
```c++
180+
void CModel::display()
181+
{
182+
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
183+
184+
for (int i = 0; i < mNumOfVertices; i += 9)
185+
{
186+
glBegin(GL_TRIANGLES);
187+
glVertex3f(mVertices[i], mVertices[i + 1], mVertices[i + 2]);
188+
glVertex3f(mVertices[i + 3], mVertices[i + 4], mVertices[i + 5]);
189+
glVertex3f(mVertices[i + 6], mVertices[i + 7], mVertices[i + 8]);
190+
glEnd();
191+
}
192+
}
193+
```
194+
195+
En el metodo de despliegue se itera por cada cara del modelo, que se encuentra compuesta por tres vertices, que a su vez cada vertices se encuentra compuesto por tres coordenadas, y se dibuja empleando como primitiva triángulos.
196+
197+
Ahora en la funció de despliegue principal se debe hacer lo siguiente
198+
199+
```c++
200+
glClearColor(0.0f, 0.0f, 0.0f, 1.0);
201+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
202+
203+
for (int i = 0; i < models.size(); i++)
204+
{
205+
float *translation = models[i]->getTranslation();
206+
207+
glPushMatrix();
208+
glTranslatef(translation[0], translation[1], translation[2]);
209+
models[i]->display();
210+
glPopMatrix();
211+
}
212+
```
213+
214+
En donde se recorre el vector de modelos, y por cada uno de ellos, se obtienen sus transformaciones asociadas, que van a ser aplicadas, en este caso se tiene unicamente traslanción, pero se podria tener tambien rotación y escalamiento. Como actualmente se tiene la matriz de modelo-vista asociada y adicionalmente la matriz de vista cargada en ésta, se debe salvaguardar el estado, ya que todos los modelos comparten la misma matriz de vista, para esto, empleamos la función `glPushMatrix()` que guarda en una pila el estado de la matriz asociada al momento de ser invocada. Una vez hecho esto, se aplican todas las transformaciones en el orden explicado anteriormente y luego se reestable el estado de la matriz `glPopMatrix()`, para continuar con el proceso.
2215
3216
### Requerimientos
4217
* GLFW

0 commit comments

Comments
 (0)