Fix typo
[opengl.git] / main.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, 10000.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                 glm::mat4 model = glm::mat4(1.f);
46
47                 float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f;
48                 model = glm::translate(model, glm::vec3(sin(i * 30) * 10, cos(i * 30) * 10, 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.7f + 0.7f * (1 + sin(d + (i + 3))), 1.f));
57
58                 if (doTranslate)
59                         model = glm::translate(model, glm::vec3(sin(d + (i + 1)), cos(d + (i + -3)), sin(d + (i + 4))));
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 bool* keyStates = new bool[256];
211
212 void keyboard(unsigned char key, int x, int y) {
213         keyStates[key] = true;
214         if (key == 'z')
215                 doScale = !doScale;
216         if (key == 'x')
217                 doRotate = !doRotate;
218         if (key == 'c')
219                 doTranslate = !doTranslate;
220 }
221
222 void keyboardUp(unsigned char key, int x, int y) {
223         keyStates[key] = false;
224 }
225
226 void timer(int _) {
227         float xSpeed = 0.f, ySpeed = 0.f, zSpeed = 0.f;
228         if (keyStates['w'])
229                 zSpeed = 0.1f;
230         if (keyStates['s'])
231                 zSpeed = -0.1f;
232         if (keyStates['a'])
233                 xSpeed = 0.1f;
234         if (keyStates['d'])
235                 xSpeed = -0.1f;
236         if (keyStates['q'])
237                 ySpeed = 0.1f;
238         if (keyStates['e'])
239                 ySpeed = -0.1f;
240
241         camPos.x += xSpeed * sin(yaw) + zSpeed * cos(yaw);
242         camPos.y += ySpeed;
243         camPos.z += zSpeed * sin(yaw) - xSpeed * cos(yaw);
244         glutPostRedisplay();
245         glutTimerFunc(16, timer, 0);
246 }
247
248 int prevMouseX, prevMouseY;
249 bool firstMouse = true;
250
251 void motion(int x, int y) {
252         if (firstMouse) {
253                 prevMouseX = x;
254                 prevMouseY = y;
255                 firstMouse = false;
256         }
257         int dx = x - prevMouseX, dy = y - prevMouseY;
258
259         prevMouseX = x;
260         prevMouseY = y;
261
262         const float sensitivity = 0.005f;
263         yaw += dx * sensitivity;
264         pitch -= dy * sensitivity;
265
266         glm::vec3 front;
267         front.x = cos(pitch) * cos(yaw);
268         front.y = sin(pitch);
269         front.z = cos(pitch) * sin(yaw);
270         camFront = glm::normalize(front);
271 }
272
273 void mouse(int button, int state, int x, int y) {
274         if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
275                 firstMouse = true;
276 }
277
278 int main(int argc, char** argv) {
279         glutInit(&argc, argv);
280         glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGB|GLUT_3_2_CORE_PROFILE);
281         glutInitWindowSize(800, 600);
282         int win = glutCreateWindow("Hello Triangle");
283         glutDisplayFunc(display);
284
285         glewInit();
286         
287         init();
288
289         glutKeyboardFunc(keyboard);
290         glutKeyboardUpFunc(keyboardUp);
291         glutTimerFunc(16, timer, 0);
292         glutMotionFunc(motion);
293         glutMouseFunc(mouse);
294
295         glutMainLoop();
296
297         return 0;
298 }
299