4676882fe80ec1c061ead0589e7e547714bf3052
[opengl.git] / assignment1.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <iostream>
4 #include <fstream>
5 #include <sstream>
6 #include <array>
7 #include <vector>
8 #ifdef __APPLE__
9 #include <GL/glew.h>
10 #else
11 #include <OpenGL/glew.h>
12 #endif
13 #include <GLUT/glut.h>
14 #include <glm/glm.hpp>
15 #include <glm/ext.hpp>
16 #include <glm/gtc/type_ptr.hpp>
17
18 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
19
20 using namespace std;
21
22 GLuint* vaos;
23 GLuint progId;
24 glm::vec3 camPos   = glm::vec3(0.0f, 0.0f,  -5.0f);
25 glm::vec3 camFront = glm::vec3(0.0f, 0.0f, 1.0f);
26 glm::vec3 camUp    = glm::vec3(0.0f, 1.0f,  0.0f);
27 float yaw = 1.57, pitch = 0;
28 bool doScale, doRotate, doTranslate;
29
30 void display() {
31         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
32         glUseProgram(progId);
33         glBindVertexArray(vaos[0]);
34         for (int i = 0; i < 100; i++) {
35
36                 GLuint projId = glGetUniformLocation(progId, "projection");
37                 glm::mat4 proj = glm::perspective(glm::radians(45.f), 1.33f, 0.01f, 100.f);
38                 glUniformMatrix4fv(projId, 1, GL_FALSE, glm::value_ptr(proj));
39
40                 GLuint viewId = glGetUniformLocation(progId, "view");
41                 glm::mat4 view = glm::lookAt(camPos, camPos + camFront, camUp);
42                 glUniformMatrix4fv(viewId, 1, GL_FALSE, glm::value_ptr(view));
43
44                 GLuint modelId = glGetUniformLocation(progId, "model");
45                 float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f;
46                 glm::mat4 model = glm::mat4(1.f);
47
48                 model = glm::translate(model, glm::vec3(sin(i * 30) * 2, cos(i * 30) * 2, i * 2));
49                 
50                 if (doRotate) {
51                         model = glm::rotate(model, d * glm::radians(30.f), glm::vec3(0.f, 1.f, 0.f));
52                         model = glm::rotate(model, d * glm::radians(20.f), glm::vec3(1.f, 0.f, 0.f));
53                 }
54                 
55                 if (doScale)
56                         model = glm::scale(model, glm::vec3(1.f, 0.3f + 0.7f * (1 + sin(d * (i + 3))), 1.f));
57
58                 if (doTranslate)
59                         model = glm::translate(model, glm::vec3(sin(d), cos(d), sin(d)));
60         
61
62                 glUniformMatrix4fv(modelId, 1, GL_FALSE, glm::value_ptr(model));
63                 
64                 glDrawArrays(GL_TRIANGLES, 0, 12);
65         }
66         glutSwapBuffers();
67 }
68
69 void attachShader(GLuint progId, const char* filePath, GLenum type) {
70         GLuint shader = glCreateShader(type);
71
72         if (!shader) {
73                 fprintf(stderr, "error creating shader\n");
74                 exit(1);
75         }
76
77         ifstream file(filePath);
78         stringstream buffer;
79         buffer << file.rdbuf();
80         string str = buffer.str();
81         const char* contents = str.c_str();
82
83         glShaderSource(shader, 1, (const GLchar**)&contents, NULL);
84         glCompileShader(shader);
85         GLint success;
86         glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
87         if (!success) {
88                 GLchar log[1024];
89                 glGetShaderInfoLog(shader, 1024, NULL, log);
90                 fprintf(stderr, "error: %s\n", log);
91                 exit(1);
92         }
93         glAttachShader(progId, shader);
94 }
95
96 GLuint compileShaders(char* vertexShader, char* fragmentShader) {
97         GLuint progId = glCreateProgram();
98
99         attachShader(progId, vertexShader, GL_VERTEX_SHADER);
100         attachShader(progId, fragmentShader, GL_FRAGMENT_SHADER);
101
102         glLinkProgram(progId);
103         GLint success = 0;
104         glGetProgramiv(progId, GL_LINK_STATUS, &success);
105         if (!success) {
106                 GLchar log[1024];
107                 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
108                 fprintf(stderr, "error linking: %s\n", log);
109                 exit(1);
110         }
111
112         return progId;
113 }
114
115 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
116
117 GLuint setupBuffers(GLfloat* vertices, GLuint progId) {
118
119         GLfloat colors[] = {
120                 0, 1, 0, 1,
121                 1, 0, 0, 1,
122                 0, 0, 1, 1,
123
124                 0, 1, 0, 1,
125                 1, 0, 0, 1,
126                 0, 0, 1, 1,
127
128                 0, 1, 0, 1,
129                 1, 0, 0, 1,
130                 0, 0, 1, 1,
131
132                 0, 1, 0, 1,
133                 1, 0, 0, 1,
134                 0, 0, 1, 1
135         };
136
137         GLuint numVerts = 12;
138
139         GLuint vbo;
140         glGenBuffers(1, &vbo);
141
142         GLuint vao;
143         glGenVertexArrays(1, &vao);
144
145         GLuint posId = glGetAttribLocation(progId, "vPosition");
146         GLuint colorId = glGetAttribLocation(progId, "vColor");
147
148         GLuint vertsLen = numVerts * 3 * sizeof(GLfloat);
149         GLuint colorsLen = numVerts * 4 * sizeof(GLfloat);
150
151         glBindBuffer(GL_ARRAY_BUFFER, vbo);
152         glBufferData(GL_ARRAY_BUFFER, vertsLen + colorsLen, NULL, GL_STATIC_DRAW);
153
154         glBufferSubData(GL_ARRAY_BUFFER, 0, vertsLen, vertices);
155         glBufferSubData(GL_ARRAY_BUFFER, vertsLen, colorsLen, colors);
156         
157         glBindVertexArray(vao);
158         glEnableVertexAttribArray(posId);
159         glVertexAttribPointer(posId, 3, GL_FLOAT, GL_FALSE, 0, 0);
160
161         glEnableVertexAttribArray(colorId);
162         glVertexAttribPointer(colorId, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVerts * 3 * sizeof(GLfloat)));
163
164         return vao;
165 }
166
167 void validateProgram(GLuint progId) {
168         glValidateProgram(progId);
169         
170         GLint success;
171         glGetProgramiv(progId, GL_VALIDATE_STATUS, &success);
172         if (!success) {
173                 GLchar log[1024];
174                 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
175                 fprintf(stderr, "error: %s\n", log);
176                 exit(1);
177         }
178 }
179
180 void init() {
181         GLfloat vertices[9*4] = {
182                 -1.0f, -1.0f, -1.0f,
183                 1.0f, -1.0f, -1.0f,
184                 0.0f, 1.0f, 0.0f,
185
186                 -1.0f, -1.0f, 1.0f,
187                 1.0f, -1.0f, 1.0f,
188                 0.0f, 1.0f, 0.0f,
189
190                 -1.0f, -1.0f, -1.0f,
191                 -1.0f, -1.0f, 1.0f,
192                 0.0f, 1.0f, 0.0f,
193
194                 1.0f, -1.0f, -1.0f,
195                 1.0f, -1.0f, 1.0f,
196                 0.0f, 1.0f, 0.0f
197
198         };
199
200         vaos = new GLuint[2];
201
202         progId = compileShaders((char*)"vertex.glsl", (char*)"fragment.glsl");
203         glUseProgram(progId);
204         vaos[0] = setupBuffers(vertices, progId);
205         validateProgram(progId);
206
207         glEnable(GL_DEPTH_TEST); 
208 }
209
210 void keyboard(unsigned char key, int x, int y) {
211         if (key == 'w')
212                 camPos.z += 0.1f;
213         if (key == 's')
214                 camPos.z -= 0.1f;
215         if (key == 'a')
216                 camPos.x += 0.1f;
217         if (key == 'd')
218                 camPos.x -= 0.1f;
219         if (key == 'q')
220                 camPos.y += 0.1f;
221         if (key == 'e')
222                 camPos.y -= 0.1f;
223         if (key == 'z')
224                 doScale = !doScale;
225         if (key == 'x')
226                 doRotate = !doRotate;
227         if (key == 'c')
228                 doTranslate = !doTranslate;
229         glutPostRedisplay();
230 }
231
232 void idle(int _) {
233         glutPostRedisplay();
234         glutTimerFunc(16, idle, 0);
235 }
236
237 int prevMouseX, prevMouseY;
238 bool firstMouse = true;
239
240 void motion(int x, int y) {
241         if (firstMouse) {
242                 prevMouseX = x;
243                 prevMouseY = y;
244                 firstMouse = false;
245         }
246         int dx = x - prevMouseX, dy = y - prevMouseY;
247
248         prevMouseX = x;
249         prevMouseY = y;
250
251         const float sensitivity = 0.005f;
252         yaw += dx * sensitivity;
253         pitch -= dy * sensitivity;
254
255         glm::vec3 front;
256         front.x = cos(pitch) * cos(yaw);
257         front.y = sin(pitch);
258         front.z = cos(pitch) * sin(yaw);
259         camFront = glm::normalize(front);
260 }
261
262 void mouse(int button, int state, int x, int y) {
263         if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
264                 firstMouse = true;
265 }
266
267 int main(int argc, char** argv) {
268         glutInit(&argc, argv);
269         glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGB|GLUT_3_2_CORE_PROFILE);
270         glutInitWindowSize(800, 600);
271         int win = glutCreateWindow("Hello Triangle");
272         glutDisplayFunc(display);
273
274         glewInit();
275         
276         init();
277
278         glutKeyboardFunc(keyboard);
279         glutTimerFunc(16, idle, 0);
280         glutMotionFunc(motion);
281         glutMouseFunc(mouse);
282
283         glutMainLoop();
284
285         return 0;
286 }
287