Skip to content

Commit 0d2589b

Browse files
committed
Tutorial OpenGL Cámara
Creación de una cámara móvil o cámara en primera persona.
1 parent f5875f3 commit 0d2589b

File tree

6 files changed

+395
-0
lines changed

6 files changed

+395
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ add_subdirectory(Tutorial-05)
2626
add_subdirectory(Tutorial-06)
2727
add_subdirectory(Tutorial-07)
2828
add_subdirectory(Tutorial-08)
29+
add_subdirectory(Tutorial-09)

Tutorial-09/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
file(COPY phong.vertex_shader phong.fragment_shader DESTINATION shaders)
2+
file(COPY grid.assbin DESTINATION model)
3+
4+
set(ASSIMP_DIR $ENV{ASSIMP_DIR} CACHE PATH "Assimp Directory")
5+
6+
find_package(ASSIMP REQUIRED)
7+
8+
link_directories(${ASSIMP_LIBRARY_DIRS})
9+
include_directories(${ASSIMP_INCLUDE_DIRS})
10+
11+
add_executable( 09-Camara camara.cpp
12+
shaders/phong.vertex_shader
13+
shaders/phong.fragment_shader
14+
../common/openglwindow.hpp
15+
../common/openglshader.hpp )
16+
17+
target_link_libraries( 09-Camara ${GRAPHIC_LIBS} ${ASSIMP_LIBRARIES})

Tutorial-09/camara.cpp

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
#include "OpenGLWindow.hpp"
2+
#include "OpenGLShader.hpp"
3+
4+
#include <glm\gtc\matrix_inverse.hpp>
5+
#include <glm\gtc\matrix_transform.hpp>
6+
#include <glm\gtc\type_ptr.hpp>
7+
#include <glm\gtx\euler_angles.hpp>
8+
#include <glm\gtx\matrix_cross_product.hpp>
9+
10+
#include <string>
11+
#include <vector>
12+
#include <memory>
13+
14+
#include <assimp/Importer.hpp> // C++ importer interface
15+
#include <assimp/scene.h> // Output data structure
16+
#include <assimp/postprocess.h> // Post processing flags
17+
18+
using namespace std;
19+
20+
class Mesh {
21+
22+
public:
23+
Mesh(const aiMesh* mesh) {
24+
load(mesh);
25+
create();
26+
}
27+
28+
~Mesh() {
29+
glDeleteBuffers(4, buffer);
30+
glDeleteVertexArrays(1, &vao);
31+
}
32+
33+
// dibujar el mesh
34+
void draw() {
35+
glBindVertexArray(vao);
36+
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, NULL);
37+
glBindVertexArray(0);
38+
};
39+
40+
// inicializar el mesh
41+
void init(const aiMesh* mesh) {
42+
load(mesh);
43+
create();
44+
};
45+
46+
private:
47+
vector<glm::vec3> vertex;
48+
vector<glm::vec3> normal;
49+
vector<glm::vec2> uv;
50+
vector<unsigned int> indices;
51+
52+
GLuint buffer[4];
53+
GLuint vao;
54+
55+
// obtener los datos de cada mesh
56+
void load(const aiMesh* mesh) {
57+
58+
vertex.reserve(mesh->mNumVertices);
59+
uv.reserve(mesh->mNumVertices);
60+
normal.reserve(mesh->mNumVertices);
61+
indices.reserve(3 * mesh->mNumFaces);
62+
63+
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
64+
65+
// Obtener la posicion de cada vertice
66+
aiVector3D pos = mesh->mVertices[i];
67+
vertex.push_back(glm::vec3(pos.x, pos.y, pos.z));
68+
69+
// Obtener las coordenadas de textura
70+
if (mesh->HasTextureCoords(0)) {
71+
aiVector3D UVW = mesh->mTextureCoords[0][i];
72+
uv.push_back(glm::vec2(UVW.x, UVW.y));
73+
}
74+
75+
// Obtener los vectores normales
76+
if (mesh->HasNormals()) {
77+
aiVector3D n = mesh->mNormals[i];
78+
normal.push_back(glm::vec3(n.x, n.y, n.z));
79+
}
80+
}
81+
82+
// Obtener los indices
83+
for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
84+
indices.push_back(mesh->mFaces[i].mIndices[0]);
85+
indices.push_back(mesh->mFaces[i].mIndices[1]);
86+
indices.push_back(mesh->mFaces[i].mIndices[2]);
87+
}
88+
}
89+
90+
void create() {
91+
// generar y activar el VAO
92+
glGenVertexArrays(1, &vao);
93+
glBindVertexArray(vao);
94+
95+
// generar dos ids para los buffer
96+
glGenBuffers(4, buffer);
97+
98+
// buffer de vertices
99+
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
100+
glBufferData(GL_ARRAY_BUFFER, vertex.size() * sizeof(glm::vec3), &vertex[0], GL_STATIC_DRAW);
101+
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
102+
glEnableVertexAttribArray(0);
103+
104+
// buffer de textura
105+
if (!uv.empty()) {
106+
glBindBuffer(GL_ARRAY_BUFFER, buffer[1]);
107+
glBufferData(GL_ARRAY_BUFFER, uv.size() * sizeof(glm::vec2), &uv[0], GL_STATIC_DRAW);
108+
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
109+
glEnableVertexAttribArray(1);
110+
}
111+
112+
// buffer de normales
113+
if (!normal.empty()) {
114+
glBindBuffer(GL_ARRAY_BUFFER, buffer[2]);
115+
glBufferData(GL_ARRAY_BUFFER, normal.size() * sizeof(glm::vec3), &normal[0], GL_STATIC_DRAW);
116+
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
117+
glEnableVertexAttribArray(2);
118+
}
119+
120+
// buffer de indices
121+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer[3]);
122+
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
123+
124+
// desactivar el VAO
125+
glBindVertexArray(0);
126+
}
127+
128+
};
129+
130+
class Model {
131+
132+
private:
133+
vector<shared_ptr<Mesh>> meshes;
134+
135+
// procesar recusivamente cada nodo de la escena
136+
void processNode(const aiNode* node, const aiScene* scene)
137+
{
138+
// obtener los mesh de esta escena
139+
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
140+
shared_ptr<Mesh> mesh(new Mesh(scene->mMeshes[node->mMeshes[i]]));
141+
meshes.push_back(mesh);
142+
}
143+
144+
// procesar los hijos del nodo
145+
for (unsigned int i = 0; i < node->mNumChildren; i++)
146+
this->processNode(node->mChildren[i], scene);
147+
}
148+
149+
public:
150+
// cargar el archivo deseado
151+
void init(const std::string& file_name) {
152+
Assimp::Importer importer;
153+
const aiScene* scene = importer.ReadFile(file_name, aiProcess_Triangulate);
154+
155+
if (scene && scene->mRootNode)
156+
processNode(scene->mRootNode, scene);
157+
else cout << importer.GetErrorString() << endl;
158+
}
159+
160+
// dibujar la escena completa
161+
void draw() {
162+
for (auto m : meshes) m->draw();
163+
}
164+
};
165+
166+
class Tutorial_09 : public OpenGLWindow {
167+
168+
public:
169+
Tutorial_09() {
170+
mv_matrix = 0;
171+
view_matrix = 0;
172+
proj_matrix = 0;
173+
}
174+
175+
private:
176+
void onstart() override {
177+
glEnable(GL_DEPTH_TEST);
178+
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
179+
180+
glClearColor(0.25f, 0.80f, 0.75f, 1.0f);
181+
182+
GLuint program = shader_simple.compile("shaders/phong.vertex_shader", "shaders/phong.fragment_shader");
183+
184+
mv_matrix = glGetUniformLocation(program, "mv_matrix");
185+
view_matrix = glGetUniformLocation(program, "view_matrix");
186+
proj_matrix = glGetUniformLocation(program, "proj_matrix");
187+
188+
model.init("model/grid.assbin");
189+
}
190+
191+
void onrender(double time) override {
192+
193+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
194+
195+
// Usar el shader
196+
shader_simple.use();
197+
198+
// obtener los parametros de visualizacion
199+
glm::mat4 R = glm::yawPitchRoll(glm::radians(yaw), glm::radians(pitch), 0.0f);
200+
cameraFront = glm::vec3(R * glm::vec4(0, 0, -1, 0));
201+
cameraUp = glm::vec3(R * glm::vec4(0, 1, 0, 0));
202+
203+
// craer la matriz de vista
204+
glm::mat4 View = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
205+
206+
// Matriz de modelo, se aplica una rotacion sobre el eje Y
207+
glm::mat4 Model;
208+
Model = glm::scale(Model, glm::vec3(0.5f));
209+
210+
// Matriz de proyeccion y visualizacion
211+
glm::mat4 Projection = glm::perspective(45.0f, aspect_ratio, 0.1f, 100.0f);
212+
213+
//Establecer las matrices
214+
glUniformMatrix4fv(mv_matrix, 1, GL_FALSE, glm::value_ptr(View * Model));
215+
glUniformMatrix4fv(view_matrix, 1, GL_FALSE, glm::value_ptr(View));
216+
glUniformMatrix4fv(proj_matrix, 1, GL_FALSE, glm::value_ptr(Projection));
217+
218+
// dibujar el modelo
219+
model.draw();
220+
221+
// desactivar el uso del shader
222+
shader_simple.unUse();
223+
224+
// actualizar el desplazamiento y ratacion de la camara
225+
chechKeys();
226+
}
227+
228+
void chechKeys() {
229+
if (isKeyPress(GLFW_KEY_W))
230+
cameraPos += cameraSpeed * cameraFront;
231+
if (isKeyPress(GLFW_KEY_S))
232+
cameraPos -= cameraSpeed * cameraFront;
233+
if (isKeyPress(GLFW_KEY_A))
234+
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
235+
if (isKeyPress(GLFW_KEY_D))
236+
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
237+
}
238+
239+
inline bool isKeyPress(int key) {
240+
return (glfwGetKey(window, key) == GLFW_PRESS);
241+
}
242+
243+
void onkey(int key, int scancode, int action, int mods) override {
244+
245+
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
246+
glfwSetWindowShouldClose(window, GL_TRUE);
247+
248+
//if (key == GLFW_KEY_W)
249+
// cameraPos += cameraSpeed * cameraFront;
250+
//if (key == GLFW_KEY_S)
251+
// cameraPos -= cameraSpeed * cameraFront;
252+
//if (key == GLFW_KEY_A)
253+
// cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
254+
//if (key == GLFW_KEY_D)
255+
// cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
256+
257+
//if (key == GLFW_KEY_E)
258+
// yaw += cameraSpeed / 2.0f;
259+
//if (key == GLFW_KEY_R)
260+
// yaw -= cameraSpeed / 2.0f;
261+
262+
//if (key == GLFW_KEY_Q)
263+
// pitch += cameraSpeed / 2.0f;
264+
//if (key == GLFW_KEY_Z)
265+
// pitch -= cameraSpeed / 2.0f;
266+
}
267+
268+
void onmouse(double xpos, double ypos) override {
269+
270+
int width, height;
271+
glfwGetWindowSize(window, &width, &height);
272+
glfwSetCursorPos(window, width / 2.0, height / 2.0);
273+
274+
GLfloat xoffset = ((width / 2.0) - xpos) * mouseSensitive;
275+
GLfloat yoffset = ((height / 2.0) - ypos) * mouseSensitive;
276+
277+
yaw += xoffset;
278+
pitch += yoffset;
279+
}
280+
281+
Model model;
282+
OpenGLShader shader_simple;
283+
GLuint mv_matrix, view_matrix, proj_matrix;
284+
285+
// variables utilizadas para la camara
286+
287+
glm::vec3 cameraPos = glm::vec3(0.0f, 0.5f, 3.0f); // posicion inicial de la camara
288+
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
289+
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
290+
291+
float yaw = 0, pitch = 0;
292+
293+
GLfloat cameraSpeed = 0.05f; // velocidad de movimiento
294+
GLfloat mouseSensitive = 0.15f; // velocidad de rotacion
295+
};
296+
297+
int main() {
298+
Tutorial_09 win_app;
299+
300+
if (win_app.init("OpenGL Moderno - Camara", 1280, 720)) {
301+
302+
// ocultar el cursor y ubicarlo en el centro de la ventana
303+
glfwSetInputMode(win_app.getGLFWwindow(), GLFW_CURSOR, GLFW_CURSOR_DISABLED);
304+
glfwSetCursorPos(win_app.getGLFWwindow(), 1280 / 2, 720 / 2);
305+
306+
win_app.info();
307+
win_app.run();
308+
}
309+
310+
return 0;
311+
}

Tutorial-09/grid.assbin

5.59 KB
Binary file not shown.

Tutorial-09/phong.fragment_shader

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#version 330 core
2+
3+
out vec4 color;
4+
5+
in vec3 N1;
6+
in vec3 L1;
7+
in vec3 V1;
8+
9+
uniform vec3 light_color = vec3(0.75, 0.75, 0.75);
10+
uniform vec3 ambient_color = vec3(0.1);
11+
12+
uniform float ka = 0.10;
13+
uniform float kd = 0.55;
14+
uniform float ks = 0.80;
15+
uniform float n = 32;
16+
17+
void main()
18+
{
19+
// Normalize the incoming N, L, and V vectors
20+
vec3 N = normalize(N1);
21+
vec3 L = normalize(L1);
22+
vec3 V = normalize(V1);
23+
// Calculate R by reflecting -L around the plane defined by N
24+
vec3 R = reflect(-L, N);
25+
26+
// Calculate ambient, difusse, specular contribution
27+
vec3 ambient = ka * ambient_color;
28+
vec3 diffuse = kd * light_color * max(0.0, dot(N, L));
29+
vec3 specular = ks * light_color * pow(max(0.0, dot(R, V)), n);
30+
31+
// Send the color output to the fragment shader
32+
vec3 f_color = ambient + diffuse + specular;
33+
color = vec4(f_color, 1.0);
34+
}

0 commit comments

Comments
 (0)