6 #define GLM_ENABLE_EXPERIMENTAL
\r
8 #include <glm/glm.hpp>
\r
9 #include <glm/gtx/rotate_vector.hpp>
\r
10 #include <glm/gtc/matrix_transform.hpp>
\r
11 #include <glm/gtc/type_ptr.hpp>
\r
13 #include <SFML/OpenGL.hpp>
\r
14 #include <SFML/Graphics.hpp>
\r
17 #include <imgui-SFML.h>
\r
19 #include <assimp/Importer.hpp>
\r
20 #include <assimp/postprocess.h>
\r
21 #include <assimp/scene.h>
\r
24 std::vector<float> vertices;
\r
25 std::vector<GLuint> indices;
\r
28 if (VAO == 0) initVAO();
\r
29 glBindVertexArray(VAO);
\r
30 glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
\r
31 glBindVertexArray(0);
\r
37 glGenBuffers(1, &VBO);
\r
40 glGenBuffers(1, &EBO);
\r
42 glGenVertexArrays(1, &VAO);
\r
44 glBindVertexArray(VAO);
\r
46 glBindBuffer(GL_ARRAY_BUFFER, VBO);
\r
47 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(),
\r
48 vertices.data(), GL_STATIC_DRAW);
\r
50 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
\r
51 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(),
\r
52 indices.data(), GL_STATIC_DRAW);
\r
54 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(0));
\r
55 glEnableVertexAttribArray(0);
\r
56 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
\r
57 glEnableVertexAttribArray(1);
\r
59 glBindVertexArray(0);
\r
66 glm::vec3 pos = glm::vec3(0, 0, -1);
\r
69 void update(sf::Window &window) {
\r
70 int mouseDeltaX = sf::Mouse::getPosition(window).x - window.getSize().x / 2;
\r
71 int mouseDeltaY = sf::Mouse::getPosition(window).y - window.getSize().y / 2;
\r
73 rot.x += mouseDeltaX;
\r
74 rot.y += mouseDeltaY;
\r
76 forward = glm::rotate(glm::vec3(0, 0, 1), rot.y / angleFactor, glm::vec3(1, 0, 0));
\r
77 forward = glm::rotate(forward, -rot.x / angleFactor, glm::vec3(0, 1, 0));
\r
79 glm::vec3 left = glm::rotate(glm::vec3(0, 0, 1), -rot.x / angleFactor + glm::radians(90.0f), glm::vec3(0, 1, 0));
\r
81 if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::LShift))
\r
86 if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
\r
87 pos += forward / moveFactor;
\r
88 if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
\r
89 pos -= forward / moveFactor;
\r
90 if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
\r
91 pos += left / moveFactor;
\r
92 if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
\r
93 pos -= left / moveFactor;
\r
99 rot.x = fmod(rot.x, glm::radians(360.0f) * angleFactor);
\r
100 rot.y = fmod(rot.y, glm::radians(360.0f) * angleFactor);
\r
103 glm::mat4 getViewMatrix() {
\r
104 forward = glm::rotate(glm::vec3(0, 0, 1), rot.y / angleFactor, glm::vec3(1, 0, 0));
\r
105 forward = glm::rotate(forward, -rot.x / angleFactor, glm::vec3(0, 1, 0));
\r
106 glm::mat4 result = glm::lookAt(pos, pos + forward, up);
\r
112 glm::vec3 up = glm::vec3(0, 1, 0);
\r
114 const float angleFactor = 200;
\r
115 float moveFactor = 20;
\r
123 void update(sf::Window &window) {
\r
124 int mouseDeltaX = sf::Mouse::getPosition(window).x - window.getSize().x / 2;
\r
125 int mouseDeltaY = sf::Mouse::getPosition(window).y - window.getSize().y / 2;
\r
127 rot.x += mouseDeltaX;
\r
128 rot.y += mouseDeltaY;
\r
133 void limit(float minY, float maxY) {
\r
134 float angleX = rot.x / angleFactor;
\r
135 float angleY = rot.y / angleFactor;
\r
137 rot.x = fmod(rot.x, glm::radians(360.0f) * angleFactor);
\r
139 if (angleY > glm::radians(maxY))
\r
140 rot.y = glm::radians(maxY) * angleFactor;
\r
141 if (angleY < glm::radians(minY))
\r
142 rot.y = glm::radians(minY) * angleFactor;
\r
145 glm::mat4 getViewMatrix() {
\r
146 float angle = rot.y / angleFactor;
\r
148 float camY = sin(angle) * exp(radius);
\r
149 float camZ = cos(angle) * exp(radius);
\r
150 glm::mat4 result = glm::lookAt(glm::vec3(0.0, camY, camZ), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
\r
151 result = glm::rotate(result, rot.x / angleFactor, glm::vec3(0, 1, 0));
\r
157 const float angleFactor = 200;
\r
161 std::string readFile(std::string filename) {
\r
162 std::ifstream ifs(filename, std::ios::binary);
\r
163 ifs.seekg(0, ifs.end);
\r
164 long length = ifs.tellg();
\r
165 ifs.seekg(0, ifs.beg);
\r
166 char *buffer = (char*)malloc(length);
\r
167 ifs.read(buffer, length);
\r
169 std::string result(buffer);
\r
174 model loadModel(const std::string &filename) {
\r
175 Assimp::Importer importer;
\r
177 const aiScene *scene = importer.ReadFile(
\r
178 filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate |
\r
179 aiProcess_SortByPType | aiProcess_GenSmoothNormals);
\r
183 for (int i = 0; i < scene->mMeshes[0]->mNumVertices; i++) {
\r
184 aiVector3D v = scene->mMeshes[0]->mVertices[i];
\r
185 aiVector3D n = scene->mMeshes[0]->mNormals[i];
\r
186 result.vertices.push_back(v.x);
\r
187 result.vertices.push_back(v.y);
\r
188 result.vertices.push_back(v.z);
\r
189 result.vertices.push_back(n.x);
\r
190 result.vertices.push_back(n.y);
\r
191 result.vertices.push_back(n.z);
\r
194 for (int i = 0; i < scene->mMeshes[0]->mNumFaces; i++) {
\r
195 aiFace f = scene->mMeshes[0]->mFaces[i];
\r
196 for (int j = 0; j < f.mNumIndices; j++) {
\r
197 result.indices.push_back(f.mIndices[j]);
\r
204 GLuint compileShaders(const char *vertFilename, const char *fragFilename) {
\r
205 GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
\r
206 std::string vertSource = readFile(vertFilename);
\r
207 const char *vertAddr = vertSource.c_str();
\r
208 glShaderSource(vertShader, 1, &vertAddr, NULL);
\r
209 glCompileShader(vertShader);
\r
213 glGetShaderiv(vertShader, GL_COMPILE_STATUS, &success);
\r
215 glGetShaderInfoLog(vertShader, 512, NULL, infoLog);
\r
216 printf("Error compiling vertex shader: %s\n", infoLog);
\r
219 GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
\r
220 std::string fragSource = readFile(fragFilename);
\r
221 const char *fragAddr = fragSource.c_str();
\r
222 glShaderSource(fragShader, 1, &fragAddr, NULL);
\r
223 glCompileShader(fragShader);
\r
225 glGetShaderiv(fragShader, GL_COMPILE_STATUS, &success);
\r
227 glGetShaderInfoLog(fragShader, 512, NULL, infoLog);
\r
228 printf("Error compiling fragment shader: %s\n", infoLog);
\r
231 // Link Shader Program
\r
233 GLuint shaderProgram = glCreateProgram();
\r
234 glAttachShader(shaderProgram, vertShader);
\r
235 glAttachShader(shaderProgram, fragShader);
\r
236 glLinkProgram(shaderProgram);
\r
238 glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
\r
240 glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
\r
241 printf("Error linking shader program: %s\n", infoLog);
\r
244 glDeleteShader(vertShader);
\r
245 glDeleteShader(fragShader);
\r
247 return shaderProgram;
\r
254 sf::ContextSettings settings;
\r
255 settings.depthBits = 24;
\r
256 settings.antialiasingLevel = 0;
\r
257 settings.majorVersion = 4;
\r
258 settings.minorVersion = 6;
\r
260 sf::RenderWindow window(sf::VideoMode(1600, 900), "Subsurface Scattering",
\r
261 sf::Style::Default, settings);
\r
262 window.setVerticalSyncEnabled(true);
\r
264 ImGui::SFML::Init(window);
\r
268 if (glewInit() != GLEW_OK) {
\r
271 GLuint shaderProgram = compileShaders("shaders/vert.glsl", "shaders/frag.glsl");
\r
273 model m = loadModel("models/Isotrop-upperjaw.ply");
\r
278 glm::vec3 lightPos(1.2f, 5.0f, 2.0f);
\r
282 glm::mat4 model = glm::scale(glm::mat4(1.0f), glm::vec3(0.01f, 0.01f, 0.01f));
\r
286 glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);
\r
289 bool wireframe = false;
\r
290 bool freecam = false;
\r
293 sf::Clock deltaClock;
\r
295 bool prevMouse = false;
\r
297 bool running = true;
\r
302 while (window.pollEvent(event)) {
\r
303 ImGui::SFML::ProcessEvent(event);
\r
305 if (event.type == sf::Event::EventType::Closed) {
\r
307 } else if (event.type == sf::Event::EventType::Resized) {
\r
308 glViewport(0, 0, event.size.width, event.size.height);
\r
309 } else if (event.type == sf::Event::EventType::KeyReleased) {
\r
310 using keys = sf::Keyboard;
\r
311 switch (event.key.code) {
\r
316 options.freecam = !options.freecam;
\r
319 if (options.freecam) {
\r
320 freeCam.pos = glm::vec3(0, 0, -1);
\r
321 freeCam.rot = glm::vec2(0);
\r
324 arcCam.rot = glm::vec2(0);
\r
329 } else if (event.type == sf::Event::EventType::MouseWheelScrolled) {
\r
330 if (! options.freecam) {
\r
331 arcCam.radius -= event.mouseWheelScroll.delta / 5.0f;
\r
338 if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {
\r
339 window.setMouseCursorVisible(false);
\r
342 if (options.freecam)
\r
343 freeCam.update(window);
\r
345 arcCam.update(window);
\r
349 sf::Mouse::setPosition(sf::Vector2i(
\r
350 window.getSize().x / 2,
\r
351 window.getSize().y / 2
\r
354 window.setMouseCursorVisible(true);
\r
357 prevMouse = sf::Mouse::isButtonPressed(sf::Mouse::Right);
\r
361 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
\r
363 glEnable(GL_DEPTH_TEST);
\r
365 if (options.wireframe)
\r
366 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
\r
368 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
\r
370 glUseProgram(shaderProgram);
\r
372 if (options.freecam)
\r
373 view = freeCam.getViewMatrix();
\r
375 view = arcCam.getViewMatrix();
\r
377 glUniformMatrix4fv(
\r
378 glGetUniformLocation(shaderProgram, "model"),
\r
379 1, GL_FALSE, glm::value_ptr(model));
\r
380 glUniformMatrix4fv(
\r
381 glGetUniformLocation(shaderProgram, "view"),
\r
382 1, GL_FALSE, glm::value_ptr(view));
\r
383 glUniformMatrix4fv(
\r
384 glGetUniformLocation(shaderProgram, "projection"),
\r
385 1, GL_FALSE, glm::value_ptr(proj));
\r
388 glGetUniformLocation(shaderProgram, "objectColor"),
\r
389 1.0f, 0.5f, 0.31f);
\r
391 glGetUniformLocation(shaderProgram, "lightColor"),
\r
394 glGetUniformLocation(shaderProgram, "lightPos"),
\r
395 1, glm::value_ptr(lightPos));
\r
399 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
\r
401 ImGui::SFML::Update(window, deltaClock.restart());
\r
403 ImGui::Begin("Options");
\r
404 ImGui::Checkbox("Wireframe", &options.wireframe);
\r
405 ImGui::Checkbox("Free Cam (F)", &options.freecam);
\r
406 if (options.freecam) {
\r
407 ImGui::LabelText("Position", "%f %f %f", freeCam.pos.x, freeCam.pos.y, freeCam.pos.z);
\r
408 ImGui::LabelText("Rotation", "%f %f", freeCam.rot.x, freeCam.rot.y);
\r
410 ImGui::LabelText("Rotation", "%f %f", arcCam.rot.x, arcCam.rot.y);
\r
411 ImGui::InputFloat("Radius", &arcCam.radius);
\r
415 ImGui::SFML::Render(window);
\r