diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8c5db5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +.ycm_extra_conf.py diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..aca2065 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "dependencies/stb"] + path = dependencies/stb + url = https://github.com/nothings/stb +[submodule "dependencies/glm"] + path = dependencies/glm + url = https://github.com/g-truc/glm diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..bf82815 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.8) +project(ltc_fitter) + +find_package( + Boost 1.63.0 REQUIRED COMPONENTS program_options +) + +include_directories(${PROJECT_SOURCE_DIR}/dependencies/glm) +include_directories(${PROJECT_SOURCE_DIR}/dependencies/stb) + +add_executable( + ${PROJECT_NAME} + src/main.cpp + src/fitting_settings.cpp + src/ltc_fitting.cpp + src/result_saving.cpp + src/stb_implementation.c +) + +target_link_libraries( + ${PROJECT_NAME} PUBLIC ${Boost_LIBRARIES} +) +target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_14) diff --git a/dependencies/glm b/dependencies/glm new file mode 160000 index 0000000..40398d6 --- /dev/null +++ b/dependencies/glm @@ -0,0 +1 @@ +Subproject commit 40398d67cd3e4f74b08649eda428dc411d801fd5 diff --git a/dependencies/stb b/dependencies/stb new file mode 160000 index 0000000..c711058 --- /dev/null +++ b/dependencies/stb @@ -0,0 +1 @@ +Subproject commit c7110588a4d24c4bb5155c184fbb77dd90b3116e diff --git a/src/fitting_settings.cpp b/src/fitting_settings.cpp new file mode 100644 index 0000000..0cf62d7 --- /dev/null +++ b/src/fitting_settings.cpp @@ -0,0 +1,88 @@ +#include +#include "boost/program_options.hpp" +#include "fitting_settings.hpp" + +namespace po = boost::program_options; + +bool get_fitting_settings_from_command_line( + fitting_settings &output, + int argc, + const char *argv[] +) +{ + output = fitting_settings(); + + po::options_description description("Allowed options"); + description.add_options() + ("help", "help message") + ( + "resolution,r", + po::value(&output.resolution)->default_value(64), + "resolution of output image" + ) + ( + "minroughness,m", + po::value(&output.min_roughness)->default_value(0.0001f), + "minimal roughness, should be greater than 0" + ) + ( + "maxroughness,M", + po::value(&output.max_roughness)->default_value(1.0f), + "maximum roughness" + ) + ( + "errorsamples,E", + po::value( + &output.num_error_estimate_samples + )->default_value(64), + "number of samples during error estimation" + ) + ( + "threads,j", + po::value( + &output.num_threads + )->default_value(1), + "number of threads" + ) + ( + "output,o", + po::value(&output.output_file), + "output file" + ) + ; + + po::variables_map var_map; + po::store(po::parse_command_line(argc, argv, description), var_map); + po::notify(var_map); + + if (var_map.count("help")) + { + std::cout << "LTC Fitter" << std::endl + << "Part of Master's thesis by Kamil Sienkiewicz" << std::endl + << "Based on work of Heitz et al: \"Linearly Transformed Cosines\"" + << std::endl; + std::cout << description << std::endl; + return false; + } + + if (!var_map.count("output")) + { + std::cout << "Output file is not set." << std::endl + << description << std::endl; + return false; + } + + return true; +} + +void print_fitting_settings(const fitting_settings& settings) +{ + std::cout << "Current fitting settings: " << std::endl + << "\tImage resolution:\t" << settings.resolution << "x" + << settings.resolution << std::endl + << "\tMinimum roughness:\t" << settings.min_roughness << std::endl + << "\tMaximum roughness:\t" << settings.max_roughness << std::endl + << "\tError est. samples:\t" << settings.num_error_estimate_samples + << std::endl << "\tLookup output file:\t" << settings.output_file + << std::endl; +} diff --git a/src/fitting_settings.hpp b/src/fitting_settings.hpp new file mode 100644 index 0000000..e939486 --- /dev/null +++ b/src/fitting_settings.hpp @@ -0,0 +1,22 @@ +#pragma once +#include + +struct fitting_settings +{ + fitting_settings() {} + + int resolution; + float min_roughness; + float max_roughness; + int num_error_estimate_samples; + int num_threads; + std::string output_file; +}; + +bool get_fitting_settings_from_command_line( + fitting_settings &output, + int argc, + const char *argv[] +); + +void print_fitting_settings(const fitting_settings& settings); diff --git a/src/ltc_fitting.cpp b/src/ltc_fitting.cpp new file mode 100644 index 0000000..45e9a0e --- /dev/null +++ b/src/ltc_fitting.cpp @@ -0,0 +1,17 @@ +#include "ltc_fitting.hpp" + +fitting_result ltc_fit(fitting_settings settings) +{ + fitting_result result; + result.settings = settings; + + for (auto i = 0; i < settings.resolution; ++i) + { + for (auto j = 0; j < settings.resolution; ++j) + { + result.transformations.push_back(glm::vec4{1.0f, 0.0f, 0.0f, 1.0f}); + } + } + + return result; +} diff --git a/src/ltc_fitting.hpp b/src/ltc_fitting.hpp new file mode 100644 index 0000000..81bd5e0 --- /dev/null +++ b/src/ltc_fitting.hpp @@ -0,0 +1,12 @@ +#pragma once +#include +#include "glm/glm.hpp" +#include "fitting_settings.hpp" + +struct fitting_result +{ + fitting_settings settings; + std::vector transformations; +}; + +fitting_result ltc_fit(fitting_settings settings); diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..564efd6 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,21 @@ +#include +#include +#include "fitting_settings.hpp" +#include "ltc_fitting.hpp" +#include "result_saving.hpp" + +int main(int argc, const char* argv[]) +{ + fitting_settings settings; + if (!get_fitting_settings_from_command_line(settings, argc, argv)) + { + std::cout << "failed to set fitting settings" << std::endl; + return EXIT_FAILURE; + } + + print_fitting_settings(settings); + auto result = ltc_fit(settings); + save_fitting_result(result); + + return EXIT_SUCCESS; +} diff --git a/src/result_saving.cpp b/src/result_saving.cpp new file mode 100644 index 0000000..39e107c --- /dev/null +++ b/src/result_saving.cpp @@ -0,0 +1,36 @@ +#include "ltc_fitting.hpp" +#include "stb_image_write.h" + +static std::vector discretize_color_vector( + const std::vector& colors_floating +) +{ + std::vector discretized; + discretized.reserve(4 * colors_floating.size()); + + for (auto i = 0; i < colors_floating.size(); ++i) + { + auto color = colors_floating[i]; + for (auto j = 0; j < 4; ++j) + { + auto clamped = std::max(0.0f, std::min(1.0f, color[j])); + auto discr_channel = static_cast(clamped * 255); + discretized.push_back(discr_channel); + } + } + return discretized; +} + +void save_fitting_result(fitting_result result) +{ + auto discretized_texture = discretize_color_vector(result.transformations); + + stbi_write_png( + result.settings.output_file.c_str(), + result.settings.resolution, + result.settings.resolution, + 4, + discretized_texture.data(), + 4 * sizeof(unsigned char) + ); +} diff --git a/src/result_saving.hpp b/src/result_saving.hpp new file mode 100644 index 0000000..c497e38 --- /dev/null +++ b/src/result_saving.hpp @@ -0,0 +1,4 @@ +#pragma once +#include "ltc_fitting.hpp" + +void save_fitting_result(fitting_result result); diff --git a/src/stb_implementation.c b/src/stb_implementation.c new file mode 100644 index 0000000..498b2e8 --- /dev/null +++ b/src/stb_implementation.c @@ -0,0 +1,7 @@ +#define STB_DEFINE +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb.h" +#include "stb_image.h" +#include "stb_image_write.h" +#include "stb_image_resize.h"