diff --git a/CMakeLists.txt b/CMakeLists.txt index d9fca8c..7c9477c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,3 +48,4 @@ add_subdirectory(exercise1) add_subdirectory(exercise2) add_subdirectory(exercise3) add_subdirectory(exercise4) +add_subdirectory(exercise5) diff --git a/common/include/gui/Camera.h b/common/include/gui/Camera.h index 20dd595..8cb7b34 100644 --- a/common/include/gui/Camera.h +++ b/common/include/gui/Camera.h @@ -33,7 +33,7 @@ namespace nse { Eigen::Matrix4f &proj, float customAspectRatio = 0) const; - //Applies a zoom by scaling the scene. Positive values of amount increase object sizes. + //Applies a zoom by changing the view distance. Positive values of amount decrease the distance. void Zoom(float amount); //Sets the extent of the scene, which is kept between znear/zfar. @@ -64,6 +64,8 @@ namespace nse { //Forwarded resize event. void resize(const Eigen::Vector2i & s); + void FixClippingPlanes(float znear, float zfar); + //Returns the point that the camera focuses on const Eigen::Vector3f& GetFocusPoint() const; @@ -99,6 +101,8 @@ namespace nse { Eigen::Vector3f modelTranslation_start = Eigen::Vector3f::Zero(); Eigen::Vector2i translation_start; //mouse position on the screen where translation started + + float fixedZNear, fixedZFar; }; } } \ No newline at end of file diff --git a/common/src/gui/Camera.cpp b/common/src/gui/Camera.cpp index 77eff96..1f14a58 100644 --- a/common/src/gui/Camera.cpp +++ b/common/src/gui/Camera.cpp @@ -14,7 +14,7 @@ using namespace nse::gui; Camera::Camera(const nanogui::Widget & parent) - : parent(parent) + : parent(parent), fixedZNear(std::numeric_limits::quiet_NaN()) { params.arcball.setSize(parent.size()); } @@ -27,8 +27,17 @@ void Camera::ComputeCameraMatrices(Eigen::Matrix4f & view, Eigen::Matrix4f & pro float depthOfSceneCenter = (params.sceneCenter - cameraPosition).dot(viewDirection); float minZNear = 0.001f * params.sceneRadius; - float znear = std::max(minZNear, depthOfSceneCenter - params.sceneRadius); - float zfar = std::max(znear + minZNear, depthOfSceneCenter + params.sceneRadius); + float znear, zfar; + if (std::isnan(fixedZNear)) + { + znear = std::max(minZNear, depthOfSceneCenter - params.sceneRadius); + zfar = std::max(znear + minZNear, depthOfSceneCenter + params.sceneRadius); + } + else + { + znear = fixedZNear; + zfar = fixedZFar; + } float fH = std::tan(params.fovy / 360.0f * (float)M_PI) * znear; float aspectRatio = customAspectRatio == 0 ? (float)parent.width() / parent.height() : customAspectRatio; @@ -46,6 +55,7 @@ void Camera::Zoom(float amount) void Camera::SetSceneExtent(const nse::math::BoundingBox& bbox) { + fixedZNear = std::numeric_limits::quiet_NaN(); params.sceneCenter = 0.5f * (bbox.min + bbox.max); params.sceneRadius = bbox.diagonal().norm() / 2.0f; } @@ -174,4 +184,10 @@ bool Camera::HandleMouseMove(const Eigen::Vector2i & p, const Eigen::Vector2i & void Camera::resize(const Eigen::Vector2i & s) { params.arcball.setSize(s); +} + +void Camera::FixClippingPlanes(float znear, float zfar) +{ + fixedZNear = znear; + fixedZFar = zfar; } \ No newline at end of file diff --git a/exercise2/CMakeLists.txt b/exercise2/CMakeLists.txt new file mode 100644 index 0000000..0df7f7e --- /dev/null +++ b/exercise2/CMakeLists.txt @@ -0,0 +1,31 @@ +set(GLSL_FILES sky.vert sky.frag + terrain.vert terrain.frag) + +ProcessGLSLFiles(GLSL_FILES) + +set(TEXTURE_FILES grass.jpg rock.jpg roadColor.jpg roadNormals.jpg roadSpecular.jpg alpha.jpg) +PREPEND(TEXTURE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/resources/" ${TEXTURE_FILES}) +JOIN("${TEXTURE_FILES}" "," texture_string) +set(bin2c_cmdline + -DOUTPUT_C=textures.cpp + -DOUTPUT_H=textures.h + "-DINPUT_FILES=${texture_string}" + -P "${NANOGUI_DIR}/resources/bin2c.cmake") + + add_custom_command( + OUTPUT textures.cpp textures.h + COMMAND ${CMAKE_COMMAND} ARGS ${bin2c_cmdline} + DEPENDS ${TEXTURE_FILES} + COMMENT "Running bin2c" + PRE_BUILD VERBATIM) + +include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ) + +add_executable(Exercise2 MACOSX_BUNDLE + glsl.cpp + textures.cpp + src/main.cpp + src/Viewer.cpp include/Viewer.h + ${GLSL_FILES}) + +target_link_libraries(Exercise2 CG1Common ${LIBS}) \ No newline at end of file diff --git a/exercise2/glsl/sky.frag b/exercise2/glsl/sky.frag new file mode 100644 index 0000000..839a02e --- /dev/null +++ b/exercise2/glsl/sky.frag @@ -0,0 +1,21 @@ +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! +// Copyright (C) CGV TU Dresden - All Rights Reserved +#version 330 + +out vec4 color; + +in vec4 clipPos; + +const vec4 horizon = vec4(0.85, 0.85, 0.8, 1.0); +const vec4 floor = vec4(0.1, 0.1, 0.1, 1.0); +const vec4 sky = vec4(0.5, 0.6, 0.8, 1.0); + +void main() +{ + float h = normalize(clipPos.xyz).y; + if(h < 0) + color = mix(horizon, floor, pow(-h, 0.5)); + else + color = mix(horizon, sky, pow(h, 0.9)); +} \ No newline at end of file diff --git a/exercise2/glsl/sky.vert b/exercise2/glsl/sky.vert new file mode 100644 index 0000000..b154cce --- /dev/null +++ b/exercise2/glsl/sky.vert @@ -0,0 +1,19 @@ +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! +// Copyright (C) CGV TU Dresden - All Rights Reserved +#version 330 + +uniform mat4 mvp; + +out vec4 clipPos; + +void main() +{ + clipPos = vec4( float((gl_VertexID << 1) & 2) - 1.0, + float((gl_VertexID + 1) & 2) - 1.0, + float( gl_VertexID & 2) - 1.0, + 1.0); + + gl_Position = mvp * clipPos; + gl_Position.z = 0.5 * gl_Position.w; +} \ No newline at end of file diff --git a/exercise2/glsl/terrain.frag b/exercise2/glsl/terrain.frag new file mode 100644 index 0000000..68e8105 --- /dev/null +++ b/exercise2/glsl/terrain.frag @@ -0,0 +1,49 @@ +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! +// Copyright (C) CGV TU Dresden - All Rights Reserved +#version 330 + + + +out vec4 color; + +uniform vec3 cameraPos; + + +uniform sampler2D background; +uniform vec2 screenSize; + +const vec3 dirToLight = normalize(vec3(1, 3, 1)); + +//Calculates the visible surface color based on the Blinn-Phong illumination model +vec4 calculateLighting(vec4 materialColor, float specularIntensity, vec3 normalizedNormal, vec3 directionToViewer) +{ + vec4 color = materialColor; + vec3 h = normalize(dirToLight + directionToViewer); + color.xyz *= 0.9 * max(dot(normalizedNormal, dirToLight), 0) + 0.1; + color.xyz += specularIntensity * pow(max(dot(h, normalizedNormal), 0), 50); + return color; +} + +vec4 getBackgroundColor() +{ + return texture(background, gl_FragCoord.xy / screenSize); +} + +void main() +{ + //surface geometry + vec3 n = vec3(0, 1, 0); + vec3 dirToViewer = vec3(0, 1, 0); + + //material properties + color = vec4(0.6, 0.6, 0.6, 1); + float specular = 0; + + + + //Calculate light + color = calculateLighting(color, specular, n, dirToViewer); + + +} \ No newline at end of file diff --git a/exercise2/glsl/terrain.vert b/exercise2/glsl/terrain.vert new file mode 100644 index 0000000..79f3139 --- /dev/null +++ b/exercise2/glsl/terrain.vert @@ -0,0 +1,58 @@ +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! +// Copyright (C) CGV TU Dresden - All Rights Reserved +#version 330 + +in vec4 position; + + + +uniform mat4 mvp; + +//Returns the height of the procedural terrain at a given xz position +float getTerrainHeight(vec2 p); + + + +void main() +{ + gl_Position = mvp * position; +} + +//source: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83 +float rand(vec2 c) +{ + return 2 * fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453) - 1; +} + +float perlinNoise(vec2 p ) +{ + vec2 ij = floor(p); + vec2 xy = p - ij; + //xy = 3.*xy*xy-2.*xy*xy*xy; + xy = .5*(1.-cos(3.1415926 * xy)); + float a = rand((ij+vec2(0.,0.))); + float b = rand((ij+vec2(1.,0.))); + float c = rand((ij+vec2(0.,1.))); + float d = rand((ij+vec2(1.,1.))); + float x1 = mix(a, b, xy.x); + float x2 = mix(c, d, xy.x); + return mix(x1, x2, xy.y); +} + +//based on https://www.seedofandromeda.com/blogs/58-procedural-heightmap-terrain-generation +float getTerrainHeight(vec2 p) +{ + float total = 0.0; + float maxAmplitude = 0.0; + float amplitude = 1.0; + float frequency = 0.02; + for (int i = 0; i < 11; i++) + { + total += ((1.0 - abs(perlinNoise(p * frequency))) * 2.0 - 1.0) * amplitude; + frequency *= 2.0; + maxAmplitude += amplitude; + amplitude *= 0.45; + } + return 15 * total / maxAmplitude; +} \ No newline at end of file diff --git a/exercise2/include/Viewer.h b/exercise2/include/Viewer.h new file mode 100644 index 0000000..0a17718 --- /dev/null +++ b/exercise2/include/Viewer.h @@ -0,0 +1,42 @@ +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! +// Copyright (C) CGV TU Dresden - All Rights Reserved + +#pragma once + +#include +#include +#include +#include + +class Viewer : public nse::gui::AbstractViewer +{ +public: + Viewer(); + + void LoadShaders(); + void CreateGeometry(); + + void drawContents(); + bool resizeEvent(const Eigen::Vector2i&); + +private: + + void RenderSky(); + + Eigen::Matrix4f view, proj; + + nse::gui::GLShader skyShader; + nse::gui::GLVertexArray emptyVAO; + + nse::gui::GLShader terrainShader; + nse::gui::GLVertexArray terrainVAO; + nse::gui::GLBuffer terrainPositions; + nse::gui::GLBuffer terrainIndices; + + GLuint grassTexture, rockTexture, roadColorTexture, roadNormalMap, roadSpecularMap, alphaMap; + + nse::gui::GLBuffer offsetBuffer; + + GLuint backgroundFBO, backgroundTexture; +}; diff --git a/exercise2/resources/alpha.jpg b/exercise2/resources/alpha.jpg new file mode 100644 index 0000000..938c697 Binary files /dev/null and b/exercise2/resources/alpha.jpg differ diff --git a/exercise2/resources/grass.jpg b/exercise2/resources/grass.jpg new file mode 100644 index 0000000..eb972b6 Binary files /dev/null and b/exercise2/resources/grass.jpg differ diff --git a/exercise2/resources/roadColor.jpg b/exercise2/resources/roadColor.jpg new file mode 100644 index 0000000..4c7a7d2 Binary files /dev/null and b/exercise2/resources/roadColor.jpg differ diff --git a/exercise2/resources/roadNormals.jpg b/exercise2/resources/roadNormals.jpg new file mode 100644 index 0000000..204fa93 Binary files /dev/null and b/exercise2/resources/roadNormals.jpg differ diff --git a/exercise2/resources/roadSpecular.jpg b/exercise2/resources/roadSpecular.jpg new file mode 100644 index 0000000..67b3b02 Binary files /dev/null and b/exercise2/resources/roadSpecular.jpg differ diff --git a/exercise2/resources/rock.jpg b/exercise2/resources/rock.jpg new file mode 100644 index 0000000..002e01f Binary files /dev/null and b/exercise2/resources/rock.jpg differ diff --git a/exercise2/src/Viewer.cpp b/exercise2/src/Viewer.cpp new file mode 100644 index 0000000..fb7accd --- /dev/null +++ b/exercise2/src/Viewer.cpp @@ -0,0 +1,186 @@ +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! +// Copyright (C) CGV TU Dresden - All Rights Reserved + +#include "Viewer.h" + +#include +#include +#include + +#include + +#include + +#include + +#include "glsl.h" +#include "textures.h" + +const uint32_t PATCH_SIZE = 256; //number of vertices along one side of the terrain patch + +Viewer::Viewer() + : AbstractViewer("CG1 Exercise 2"), + terrainPositions(nse::gui::VertexBuffer), terrainIndices(nse::gui::IndexBuffer), + offsetBuffer(nse::gui::VertexBuffer) +{ + LoadShaders(); + CreateGeometry(); + + //Create a texture and framebuffer for the background + glGenFramebuffers(1, &backgroundFBO); + glGenTextures(1, &backgroundTexture); + + //Align camera to view a reasonable part of the terrain + camera().SetSceneExtent(nse::math::BoundingBox(Eigen::Vector3f(0, 0, 0), Eigen::Vector3f(PATCH_SIZE - 1, 0, PATCH_SIZE - 1))); + camera().FocusOnPoint(0.5f * Eigen::Vector3f(PATCH_SIZE - 1, 15, PATCH_SIZE - 1)); + camera().Zoom(-30); + camera().RotateAroundFocusPointLocal(Eigen::AngleAxisf(-0.5f, Eigen::Vector3f::UnitY()) * Eigen::AngleAxisf(-0.05f, Eigen::Vector3f::UnitX())); + camera().FixClippingPlanes(0.1, 1000); +} + +bool Viewer::resizeEvent(const Eigen::Vector2i&) +{ + //Re-generate the texture and FBO for the background + glBindFramebuffer(GL_FRAMEBUFFER, backgroundFBO); + glBindTexture(GL_TEXTURE_2D, backgroundTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width(), height(), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, backgroundTexture, 0); + auto fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (fboStatus != GL_FRAMEBUFFER_COMPLETE) + std::cout << "Warning: Background framebuffer is not complete: " << fboStatus << std::endl; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return false; +} + +void Viewer::LoadShaders() +{ + skyShader.init("Sky Shader", std::string((const char*)sky_vert, sky_vert_size), std::string((const char*)sky_frag, sky_frag_size)); + terrainShader.init("Terrain Shader", std::string((const char*)terrain_vert, terrain_vert_size), std::string((const char*)terrain_frag, terrain_frag_size)); +} + +GLuint CreateTexture(const unsigned char* fileData, size_t fileLength, bool repeat = true) +{ + GLuint textureName; + int textureWidth, textureHeight, textureChannels; + auto pixelData = stbi_load_from_memory(fileData, fileLength, &textureWidth, &textureHeight, &textureChannels, 3); + textureName = 0; + stbi_image_free(pixelData); + return textureName; +} + +void Viewer::CreateGeometry() +{ + //empty VAO for sky + emptyVAO.generate(); + + //terrain VAO + terrainVAO.generate(); + terrainVAO.bind(); + + std::vector positions; + std::vector indices; + + /*Generate positions and indices for a terrain patch with a + single triangle strip */ + + terrainShader.bind(); + terrainPositions.uploadData(positions).bindToAttribute("position"); + terrainIndices.uploadData(indices.size() * sizeof(uint32_t), indices.data()); + + + + //textures + grassTexture = CreateTexture((unsigned char*)grass_jpg, grass_jpg_size); + rockTexture = CreateTexture((unsigned char*)rock_jpg, rock_jpg_size); + roadColorTexture = CreateTexture((unsigned char*)roadcolor_jpg, roadcolor_jpg_size); + roadNormalMap = CreateTexture((unsigned char*)roadnormals_jpg, roadnormals_jpg_size); + roadSpecularMap = CreateTexture((unsigned char*)roadspecular_jpg, roadspecular_jpg_size); + alphaMap = CreateTexture((unsigned char*)alpha_jpg, alpha_jpg_size, false); +} + +void Viewer::RenderSky() +{ + Eigen::Matrix4f skyView = view; + for (int i = 0; i < 3; ++i) + skyView.col(i).normalize(); + skyView.col(3).head<3>().setZero(); + Eigen::Matrix4f skyMvp = proj * skyView; + glDepthMask(GL_FALSE); + glEnable(GL_DEPTH_CLAMP); + emptyVAO.bind(); + skyShader.bind(); + skyShader.setUniform("mvp", skyMvp); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 6); + glDisable(GL_DEPTH_CLAMP); + glDepthMask(GL_TRUE); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, backgroundFBO); + glBlitFramebuffer(0, 0, width(), height(), 0, 0, width(), height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} + +void CalculateViewFrustum(const Eigen::Matrix4f& mvp, Eigen::Vector4f* frustumPlanes, nse::math::BoundingBox& bbox) +{ + frustumPlanes[0] = (mvp.row(3) + mvp.row(0)).transpose(); + frustumPlanes[1] = (mvp.row(3) - mvp.row(0)).transpose(); + frustumPlanes[2] = (mvp.row(3) + mvp.row(1)).transpose(); + frustumPlanes[3] = (mvp.row(3) - mvp.row(1)).transpose(); + frustumPlanes[4] = (mvp.row(3) + mvp.row(2)).transpose(); + frustumPlanes[5] = (mvp.row(3) - mvp.row(2)).transpose(); + + Eigen::Matrix4f invMvp = mvp.inverse(); + bbox.reset(); + for(int x = -1; x <= 1; x += 2) + for(int y = -1; y <= 1; y += 2) + for (int z = -1; z <= 1; z += 2) + { + Eigen::Vector4f corner = invMvp * Eigen::Vector4f(x, y, z, 1); + corner /= corner.w(); + bbox.expand(corner.head<3>()); + } +} + +bool IsBoxCompletelyBehindPlane(const Eigen::Vector3f& boxMin, const Eigen::Vector3f& boxMax, const Eigen::Vector4f& plane) +{ + return + plane.dot(Eigen::Vector4f(boxMin.x(), boxMin.y(), boxMin.z(), 1)) < 0 && + plane.dot(Eigen::Vector4f(boxMin.x(), boxMin.y(), boxMax.z(), 1)) < 0 && + plane.dot(Eigen::Vector4f(boxMin.x(), boxMax.y(), boxMin.z(), 1)) < 0 && + plane.dot(Eigen::Vector4f(boxMin.x(), boxMax.y(), boxMin.z(), 1)) < 0 && + plane.dot(Eigen::Vector4f(boxMax.x(), boxMin.y(), boxMin.z(), 1)) < 0 && + plane.dot(Eigen::Vector4f(boxMax.x(), boxMin.y(), boxMax.z(), 1)) < 0 && + plane.dot(Eigen::Vector4f(boxMax.x(), boxMax.y(), boxMin.z(), 1)) < 0 && + plane.dot(Eigen::Vector4f(boxMax.x(), boxMax.y(), boxMin.z(), 1)) < 0; +} + +void Viewer::drawContents() +{ + camera().ComputeCameraMatrices(view, proj); + + Eigen::Matrix4f mvp = proj * view; + Eigen::Vector3f cameraPosition = view.inverse().col(3).head<3>(); + int visiblePatches = 0; + + RenderSky(); + + //render terrain + glEnable(GL_DEPTH_TEST); + terrainVAO.bind(); + terrainShader.bind(); + + terrainShader.setUniform("screenSize", Eigen::Vector2f(width(), height()), false); + terrainShader.setUniform("mvp", mvp); + terrainShader.setUniform("cameraPos", cameraPosition, false); + + /* Task: Render the terrain */ + + + //Render text + nvgBeginFrame(mNVGContext, width(), height(), mPixelRatio); + std::string text = "Patches visible: " + std::to_string(visiblePatches); + nvgText(mNVGContext, 10, 20, text.c_str(), nullptr); + nvgEndFrame(mNVGContext); +} \ No newline at end of file diff --git a/exercise2/src/main.cpp b/exercise2/src/main.cpp new file mode 100644 index 0000000..e01821b --- /dev/null +++ b/exercise2/src/main.cpp @@ -0,0 +1,36 @@ +// This source code is property of the Computer Graphics and Visualization +// chair of the TU Dresden. Do not distribute! +// Copyright (C) CGV TU Dresden - All Rights Reserved + +#include + +#include + +#include "Viewer.h" + +int main(int argc, char* argv[]) +{ + nanogui::init(); + + { + nanogui::ref viewer = new Viewer(); + viewer->setVisible(true); + + nse::util::GLDebug::SetupDebugCallback(); + nse::util::GLDebug::IgnoreGLError(131185); //buffer usage info + + try + { + nanogui::mainloop(); + } + catch (std::runtime_error& e) + { + std::cerr << e.what() << std::endl; + } + + } + + nanogui::shutdown(); + + return 0; +} \ No newline at end of file diff --git a/exercise3/CMakeLists.txt b/exercise3/CMakeLists.txt index 6c9fb4d..f83db3f 100644 --- a/exercise3/CMakeLists.txt +++ b/exercise3/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ) -add_executable(Exercise2 MACOSX_BUNDLE +add_executable(Exercise3 MACOSX_BUNDLE src/main.cpp src/Viewer.cpp include/Viewer.h src/Primitives.cpp include/Primitives.h @@ -11,4 +11,4 @@ add_executable(Exercise2 MACOSX_BUNDLE src/Stripification.cpp include/Stripification.h include/sample_set.h) -target_link_libraries(Exercise2 CG1Common ${LIBS}) \ No newline at end of file +target_link_libraries(Exercise3 CG1Common ${LIBS}) \ No newline at end of file diff --git a/exercise4/CMakeLists.txt b/exercise4/CMakeLists.txt index 4d0a509..dc2f1b1 100644 --- a/exercise4/CMakeLists.txt +++ b/exercise4/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ) -add_executable(Exercise3 MACOSX_BUNDLE +add_executable(Exercise4 MACOSX_BUNDLE src/main.cpp src/Viewer.cpp include/Viewer.h src/AABBTree.cpp include/AABBTree.h @@ -13,4 +13,4 @@ add_executable(Exercise3 MACOSX_BUNDLE src/GridTraverser.cpp include/GridTraverser.h ) -target_link_libraries(Exercise3 CG1Common ${LIBS}) \ No newline at end of file +target_link_libraries(Exercise4 CG1Common ${LIBS}) \ No newline at end of file diff --git a/exercise5/CMakeLists.txt b/exercise5/CMakeLists.txt index dc3fd08..c2e52b1 100644 --- a/exercise5/CMakeLists.txt +++ b/exercise5/CMakeLists.txt @@ -1,10 +1,10 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ) -add_executable(Exercise4 MACOSX_BUNDLE +add_executable(Exercise5 MACOSX_BUNDLE src/main.cpp src/Viewer.cpp include/Viewer.h src/Parametrization.cpp include/Parametrization.h src/Registration.cpp include/Registration.h ) -target_link_libraries(Exercise4 CG1Common ${LIBS}) \ No newline at end of file +target_link_libraries(Exercise5 CG1Common ${LIBS}) \ No newline at end of file diff --git a/solution/linux/Exercise2 b/solution/linux/Exercise2 new file mode 100644 index 0000000..369df2c Binary files /dev/null and b/solution/linux/Exercise2 differ diff --git a/solution/win/Exercise2.exe b/solution/win/Exercise2.exe new file mode 100644 index 0000000..03e057f Binary files /dev/null and b/solution/win/Exercise2.exe differ