├── .gitattributes ├── .gitignore ├── CMakeLists.txt ├── README.md ├── cmake ├── FindGLM.cmake ├── FindSFML.cmake ├── UseGLM.cmake └── UseSFML.cmake ├── external ├── glm │ └── CMakeLists.txt └── sfml │ └── CMakeLists.txt ├── screenshot └── 2014-12-12.png └── src ├── blocks.cpp ├── blocks.h ├── draw.cpp ├── draw.h ├── field.cpp ├── field.h ├── main.cpp ├── points.cpp └── points.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Line endings 2 | * text eol=lf 3 | 4 | # Text files 5 | *.md text 6 | *.hpp text 7 | *.inl text 8 | *.cpp text 9 | *.cmake text 10 | 11 | # Binary files 12 | *.png binary 13 | *.jpg binary 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /external/*/* 3 | !/external/*/CMakeLists.txt 4 | 5 | # CMake 6 | CMakeCache.txt 7 | CMakeFiles 8 | Makefile 9 | cmake_install.cmake 10 | install_manifest.txt 11 | 12 | # Build 13 | [Dd]ebug/ 14 | [Rr]elease/ 15 | *.exe 16 | *.ilk 17 | *.pdb 18 | /modurale 19 | /tests 20 | 21 | # CLion 22 | .idea 23 | 24 | # Visual Studio 25 | *.sln 26 | *.sdf 27 | *.opensdf 28 | *.suo 29 | *.vcxproj 30 | *.vcxproj.filters 31 | *.vcxproj.user 32 | 33 | # Windows 34 | Thumbs.db 35 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | # General 3 | ################################################################ 4 | 5 | # CMake version 6 | cmake_minimum_required(VERSION 2.8.8) 7 | 8 | # Declare project name 9 | project(SFML_APP) 10 | 11 | # Version information 12 | set(${PROJECT_NAME}_VERSION_MAJOR 0) 13 | set(${PROJECT_NAME}_VERSION_MINOR 1) 14 | set(${PROJECT_NAME}_VERSION_PATCH 0) 15 | 16 | # Include scripts 17 | set(CMAKE_MODULE_PATH cmake ${CMAKE_MODULE_PATH}) 18 | include(ExternalProject) 19 | 20 | ################################################################ 21 | # Configure tool chain 22 | ################################################################ 23 | 24 | # Enable modern C++ features 25 | if (UNIX OR MINGW) 26 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") 27 | endif() 28 | 29 | # Build variants, default to release 30 | set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) 31 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") 32 | set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING 33 | "Whether to build Debug or Release builds." FORCE) 34 | 35 | # Library linkage, default to static 36 | if (UNIX) 37 | set(BUILD_SHARED_LIBS TRUE CACHE BOOL "") 38 | else() 39 | set(BUILD_SHARED_LIBS FALSE CACHE BOOL "") 40 | endif() 41 | set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS} CACHE BOOL 42 | "Whether to build static or dynamic libraries." FORCE) 43 | 44 | # Runtime linkage, default to static 45 | if (BUILD_SHARED_LIBS) 46 | set(USE_STATIC_STD_LIBS FALSE CACHE BOOL "") 47 | else() 48 | set(USE_STATIC_STD_LIBS TRUE CACHE BOOL "") 49 | endif() 50 | set(USE_STATIC_STD_LIBS ${USE_STATIC_STD_LIBS} CACHE BOOL 51 | "Whether to use statically or dynamically link to the runtime library." FORCE) 52 | if (USE_STATIC_STD_LIBS) 53 | if (UNIX OR MINGW) 54 | set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") 55 | elseif (MSVC) 56 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") 57 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") 58 | else() 59 | message(ERROR "Unsupported compiler.") 60 | endif() 61 | endif() 62 | 63 | # Find correct file extension for libraries 64 | if (UNIX) 65 | if (BUILD_SHARED_LIBS) 66 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".so") 67 | else() 68 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 69 | endif() 70 | endif() 71 | 72 | # Linkage options are mutually exclusive 73 | if (BUILD_SHARED_LIBS AND USE_STATIC_STD_LIBS) 74 | message(FATAL_ERROR "Can't link libraries dynamically but runtime " 75 | "statically. BUILD_SHARED_LIBS and USE_STATIC_STD_LIBS are mutually " 76 | "exclusive.") 77 | endif() 78 | 79 | ################################################################ 80 | # External settings 81 | ################################################################ 82 | 83 | # Make GIT_EXECUTABLE show up in the graphical user interface 84 | set(GIT_EXECUTABLE "git" CACHE FILEPATH "") 85 | set(GIT_EXECUTABLE ${GIT_EXECUTABLE} CACHE FILEPATH 86 | "Path to the git executable used to download dependencies." FORCE) 87 | 88 | ################################################################ 89 | # Project and test target 90 | ################################################################ 91 | 92 | # create_target( [directories...]) 93 | # Create executable from all code inside the given directories 94 | function(create_target NAME) 95 | set(HEADERS) 96 | set(SOURCES) 97 | # Collect files inside project directories 98 | foreach(ROOT ${ARGV}) 99 | file(GLOB_RECURSE HEADERS_CURRENT ${ROOT}/*.hpp ${ROOT}/*.inl) 100 | file(GLOB_RECURSE SOURCES_CURRENT ${ROOT}/*.cpp) 101 | list(APPEND HEADERS ${HEADERS_CURRENT}) 102 | list(APPEND SOURCES ${SOURCES_CURRENT}) 103 | include_directories(${ROOT}) 104 | endforeach() 105 | # Add the collected files and add root as include directory 106 | add_executable(${NAME} ${HEADERS} ${SOURCES}) 107 | # Display status message 108 | list(LENGTH HEADERS HEADERS_COUNT) 109 | list(LENGTH SOURCES SOURCES_COUNT) 110 | message(STATUS "Added project " ${NAME} " with " ${HEADERS_COUNT} " " 111 | "headers and " ${SOURCES_COUNT} " source files.") 112 | endfunction() 113 | 114 | # Use function above 115 | create_target(${PROJECT_NAME} 116 | ${CMAKE_SOURCE_DIR}/src) 117 | 118 | ################################################################ 119 | # Library dependencies 120 | ################################################################ 121 | 122 | # Add another project and build it at configure time 123 | function(add_subdirectory_and_build DIRECTORY) 124 | # Configure project 125 | exec_program(${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/external/${DIRECTORY} ARGS 126 | -G\"${CMAKE_GENERATOR}\" 127 | -DCMAKE_CONFIGURATION_TYPES:STRING="Debug\;Release" 128 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 129 | -DBUILD_SHARED_LIBS:BOOL=${BUILD_SHARED_LIBS} 130 | -DUSE_STATIC_STD_LIBS:BOOL=${USE_STATIC_STD_LIBS} 131 | -DGIT_EXECUTABLE:FILEPATH=${GIT_EXECUTABLE}) 132 | # Force build at compile time 133 | exec_program(${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/external/${DIRECTORY} ARGS 134 | --build . 135 | --config ${CMAKE_BUILD_TYPE}) 136 | # Clean up CMake files 137 | # ... 138 | endfunction() 139 | 140 | # Use function above 141 | add_subdirectory_and_build(sfml) 142 | add_subdirectory_and_build(glm) 143 | 144 | # Find and include headers and binaries of dependencies that match the 145 | # configuration and link them against the requiring targets 146 | include(UseSFML) 147 | include(UseGLM) 148 | use_sfml(${PROJECT_NAME}) 149 | use_glm(${PROJECT_NAME}) 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Voxel Smoothing 2D 2 | ================== 3 | 4 | This is the implementation of an algorithm for smoothing voxel structures, I 5 | designed. Even though this is a 3D problem, solving it in 2D is a first step. 6 | This application displays a grid where you can add or remove blocks with the 7 | mouse. The smoothed shape outline is rendered ontop. 8 | 9 | ![Screenshot](screenshot/2014-12-12.png?raw=true) 10 | 11 | Instructions 12 | ------------ 13 | 14 | To generate build files, run `cmake` with these command line options. Only the 15 | first option is required if you stick with the default configuration and have 16 | Git globally available. 17 | 18 | Option | Usage 19 | ------------------------------------------ | ----------------------------------------------- 20 | `-G""` | E.g. `Visual Studio 12` or `Unix Makefiles`. 21 | `-DGIT_EXECUTABLE:FILEPATH=` | Path to `git.exe` if not globally available. 22 | `-DCMAKE_BUILD_TYPE:STRING=""` | `Debug` or `Release`, defaults to release. 23 | `-DBUILD_SHARED_LIBS:BOOL=` | What type to build, `TRUE` or `FALSE`. 24 | `-DUSE_STATIC_STD_LIBS:BOOL=` | Advanced option, defaults to opposite of above. 25 | 26 | To build the project, it's recommended that you use your selected toolchain. 27 | It's also possible to use `cmake --build . --config `. 28 | 29 | When using Visual Studio, you have to manually set the startup project to your 30 | own one, since it's `ALL_BUILD` by default. Moreover, make sure to select the 31 | build type you chose above when running the application. 32 | 33 | In case you want to clean up build files later on, run `git clean -xffd` from 34 | the repository root. 35 | -------------------------------------------------------------------------------- /cmake/FindGLM.cmake: -------------------------------------------------------------------------------- 1 | # - Find GLM 2 | # Find the GLM include and library 3 | # 4 | # GLM_INCLUDE_DIR - The include directory 5 | # GLM_FOUND - True if GLM has been found 6 | 7 | find_path(GLM_INCLUDE_DIR 8 | glm/glm.hpp 9 | HINTS ${GLM_ROOT} 10 | PATH_SUFFIXES 11 | ) 12 | 13 | include(FindPackageHandleStandardArgs) 14 | find_package_handle_standard_args(GLM DEFAULT_MSG GLM_INCLUDE_DIR) 15 | 16 | mark_as_advanced(GLM_INCLUDE_DIR) 17 | -------------------------------------------------------------------------------- /cmake/FindSFML.cmake: -------------------------------------------------------------------------------- 1 | # This script locates the SFML library 2 | # ------------------------------------ 3 | # 4 | # Usage 5 | # ----- 6 | # 7 | # When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main). 8 | # If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing. 9 | # example: 10 | # find_package(SFML COMPONENTS graphics window system) // find the graphics, window and system modules 11 | # 12 | # You can enforce a specific version, either MAJOR.MINOR or only MAJOR. 13 | # If nothing is specified, the version won't be checked (ie. any version will be accepted). 14 | # example: 15 | # find_package(SFML COMPONENTS ...) // no specific version required 16 | # find_package(SFML 2 COMPONENTS ...) // any 2.x version 17 | # find_package(SFML 2.4 COMPONENTS ...) // version 2.4 or greater 18 | # 19 | # By default, the dynamic libraries of SFML will be found. To find the static ones instead, 20 | # you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...). 21 | # Since you have to link yourself all the SFML dependencies when you link it statically, the following 22 | # additional variables are defined: SFML_XXX_DEPENDENCIES and SFML_DEPENDENCIES (see their detailed 23 | # description below). 24 | # In case of static linking, the SFML_STATIC macro will also be defined by this script. 25 | # example: 26 | # set(SFML_STATIC_LIBRARIES TRUE) 27 | # find_package(SFML 2 COMPONENTS network system) 28 | # 29 | # On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless 30 | # CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details. 31 | # Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which 32 | # are available for both release and debug modes. 33 | # 34 | # If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable 35 | # to tell CMake where SFML is. 36 | # 37 | # Output 38 | # ------ 39 | # 40 | # This script defines the following variables: 41 | # - For each specified module XXX (system, window, graphics, network, audio, main): 42 | # - SFML_XXX_LIBRARY_DEBUG: the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found) 43 | # - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found) 44 | # - SFML_XXX_LIBRARY: the name of the library to link to for the xxx module (includes both debug and optimized names if necessary) 45 | # - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found 46 | # - SFML_XXX_DEPENDENCIES: the list of libraries the module depends on, in case of static linking 47 | # - SFML_LIBRARIES: the list of all libraries corresponding to the required modules 48 | # - SFML_FOUND: true if all the required modules are found 49 | # - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file) 50 | # - SFML_DEPENDENCIES: the list of libraries SFML depends on, in case of static linking 51 | # 52 | # example: 53 | # find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED) 54 | # include_directories(${SFML_INCLUDE_DIR}) 55 | # add_executable(myapp ...) 56 | # target_link_libraries(myapp ${SFML_LIBRARIES}) 57 | 58 | # define the SFML_STATIC macro if static build was chosen 59 | if(SFML_STATIC_LIBRARIES) 60 | add_definitions(-DSFML_STATIC) 61 | endif() 62 | 63 | # define the list of search paths for headers and libraries 64 | set(FIND_SFML_PATHS 65 | ${SFML_ROOT} 66 | $ENV{SFML_ROOT} 67 | ~/Library/Frameworks 68 | /Library/Frameworks 69 | /usr/local 70 | /usr 71 | /sw 72 | /opt/local 73 | /opt/csw 74 | /opt) 75 | 76 | # find the SFML include directory 77 | find_path(SFML_INCLUDE_DIR SFML/Config.hpp 78 | PATH_SUFFIXES include 79 | PATHS ${FIND_SFML_PATHS}) 80 | 81 | # check the version number 82 | set(SFML_VERSION_OK TRUE) 83 | if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR) 84 | # extract the major and minor version numbers from SFML/Config.hpp 85 | # we have to handle framework a little bit differently: 86 | if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework") 87 | set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp") 88 | else() 89 | set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp") 90 | endif() 91 | FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS) 92 | STRING(REGEX MATCH ".*#define SFML_VERSION_MAJOR ([0-9]+).*#define SFML_VERSION_MINOR ([0-9]+).*" SFML_CONFIG_HPP_CONTENTS "${SFML_CONFIG_HPP_CONTENTS}") 93 | STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}") 94 | STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}") 95 | math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10 + ${SFML_FIND_VERSION_MINOR}") 96 | 97 | # if we could extract them, compare with the requested version number 98 | if (SFML_VERSION_MAJOR) 99 | # transform version numbers to an integer 100 | math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10 + ${SFML_VERSION_MINOR}") 101 | 102 | # compare them 103 | if(SFML_VERSION LESS SFML_REQUESTED_VERSION) 104 | set(SFML_VERSION_OK FALSE) 105 | endif() 106 | else() 107 | # SFML version is < 2.0 108 | if (SFML_REQUESTED_VERSION GREATER 19) 109 | set(SFML_VERSION_OK FALSE) 110 | set(SFML_VERSION_MAJOR 1) 111 | set(SFML_VERSION_MINOR x) 112 | endif() 113 | endif() 114 | endif() 115 | 116 | # find the requested modules 117 | set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found 118 | foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS}) 119 | string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER) 120 | string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER) 121 | set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER}) 122 | 123 | # no suffix for sfml-main, it is always a static library 124 | if(FIND_SFML_COMPONENT_LOWER STREQUAL "main") 125 | # release library 126 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE 127 | NAMES ${FIND_SFML_COMPONENT_NAME} 128 | PATH_SUFFIXES lib64 lib 129 | PATHS ${FIND_SFML_PATHS}) 130 | 131 | # debug library 132 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG 133 | NAMES ${FIND_SFML_COMPONENT_NAME}-d 134 | PATH_SUFFIXES lib64 lib 135 | PATHS ${FIND_SFML_PATHS}) 136 | else() 137 | # static release library 138 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE 139 | NAMES ${FIND_SFML_COMPONENT_NAME}-s 140 | PATH_SUFFIXES lib64 lib 141 | PATHS ${FIND_SFML_PATHS}) 142 | 143 | # static debug library 144 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG 145 | NAMES ${FIND_SFML_COMPONENT_NAME}-s-d 146 | PATH_SUFFIXES lib64 lib 147 | PATHS ${FIND_SFML_PATHS}) 148 | 149 | # dynamic release library 150 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE 151 | NAMES ${FIND_SFML_COMPONENT_NAME} 152 | PATH_SUFFIXES lib64 lib 153 | PATHS ${FIND_SFML_PATHS}) 154 | 155 | # dynamic debug library 156 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG 157 | NAMES ${FIND_SFML_COMPONENT_NAME}-d 158 | PATH_SUFFIXES lib64 lib 159 | PATHS ${FIND_SFML_PATHS}) 160 | 161 | # choose the entries that fit the requested link type 162 | if(SFML_STATIC_LIBRARIES) 163 | if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE) 164 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE}) 165 | endif() 166 | if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG) 167 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG}) 168 | endif() 169 | else() 170 | if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE) 171 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE}) 172 | endif() 173 | if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) 174 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG}) 175 | endif() 176 | endif() 177 | endif() 178 | 179 | if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) 180 | # library found 181 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE) 182 | 183 | # if both are found, set SFML_XXX_LIBRARY to contain both 184 | if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) 185 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG} 186 | optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) 187 | endif() 188 | 189 | # if only one debug/release variant is found, set the other to be equal to the found one 190 | if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) 191 | # debug and not release 192 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) 193 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) 194 | endif() 195 | if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG) 196 | # release and not debug 197 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) 198 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) 199 | endif() 200 | else() 201 | # library not found 202 | set(SFML_FOUND FALSE) 203 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE) 204 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "") 205 | set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY") 206 | endif() 207 | 208 | # mark as advanced 209 | MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY 210 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE 211 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG 212 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE 213 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG 214 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE 215 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) 216 | 217 | # add to the global list of libraries 218 | set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}") 219 | endforeach() 220 | 221 | # in case of static linking, we must also define the list of all the dependencies of SFML libraries 222 | if(SFML_STATIC_LIBRARIES) 223 | 224 | # detect the OS 225 | if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") 226 | set(FIND_SFML_OS_WINDOWS 1) 227 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") 228 | set(FIND_SFML_OS_LINUX 1) 229 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") 230 | set(FIND_SFML_OS_FREEBSD 1) 231 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 232 | set(FIND_SFML_OS_MACOSX 1) 233 | endif() 234 | 235 | # start with an empty list 236 | set(SFML_DEPENDENCIES) 237 | set(FIND_SFML_DEPENDENCIES_NOTFOUND) 238 | 239 | # macro that searches for a 3rd-party library 240 | macro(find_sfml_dependency output friendlyname) 241 | find_library(${output} NAMES ${ARGN} PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib) 242 | if(${${output}} STREQUAL "${output}-NOTFOUND") 243 | unset(output) 244 | set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${friendlyname}") 245 | endif() 246 | endmacro() 247 | 248 | # sfml-system 249 | list(FIND SFML_FIND_COMPONENTS "system" FIND_SFML_SYSTEM_COMPONENT) 250 | if(NOT ${FIND_SFML_SYSTEM_COMPONENT} EQUAL -1) 251 | 252 | # update the list -- these are only system libraries, no need to find them 253 | if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD OR FIND_SFML_OS_MACOSX) 254 | set(SFML_SYSTEM_DEPENDENCIES "pthread") 255 | endif() 256 | if(FIND_SFML_OS_LINUX) 257 | set(SFML_SYSTEM_DEPENDENCIES "rt") 258 | endif() 259 | if(FIND_SFML_OS_WINDOWS) 260 | set(SFML_SYSTEM_DEPENDENCIES "winmm") 261 | endif() 262 | set(SFML_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} ${SFML_DEPENDENCIES}) 263 | endif() 264 | 265 | # sfml-network 266 | list(FIND SFML_FIND_COMPONENTS "network" FIND_SFML_NETWORK_COMPONENT) 267 | if(NOT ${FIND_SFML_NETWORK_COMPONENT} EQUAL -1) 268 | 269 | # update the list -- these are only system libraries, no need to find them 270 | if(FIND_SFML_OS_WINDOWS) 271 | set(SFML_NETWORK_DEPENDENCIES "ws2_32") 272 | endif() 273 | set(SFML_DEPENDENCIES ${SFML_NETWORK_DEPENDENCIES} ${SFML_DEPENDENCIES}) 274 | endif() 275 | 276 | # sfml-window 277 | list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT) 278 | if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1) 279 | 280 | # find libraries 281 | if(FIND_SFML_OS_LINUX) 282 | find_sfml_dependency(X11_LIBRARY "X11" X11) 283 | find_sfml_dependency(XRANDR_LIBRARY "Xrandr" Xrandr) 284 | find_sfml_dependency(UDEV_LIBRARY "UDev" udev) 285 | endif() 286 | 287 | # update the list 288 | if(FIND_SFML_OS_WINDOWS) 289 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32") 290 | elseif(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD) 291 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY}) 292 | if(FIND_SFML_OS_FREEBSD) 293 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "usbhid") 294 | else() 295 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${UDEV_LIBRARY}) 296 | endif() 297 | elseif(FIND_SFML_OS_MACOSX) 298 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon") 299 | endif() 300 | set(SFML_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${SFML_DEPENDENCIES}) 301 | endif() 302 | 303 | # sfml-graphics 304 | list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT) 305 | if(NOT ${FIND_SFML_GRAPHICS_COMPONENT} EQUAL -1) 306 | 307 | # find libraries 308 | find_sfml_dependency(FREETYPE_LIBRARY "FreeType" freetype) 309 | find_sfml_dependency(GLEW_LIBRARY "GLEW" glew GLEW glew32 glew32s glew64 glew64s) 310 | find_sfml_dependency(JPEG_LIBRARY "libjpeg" jpeg) 311 | 312 | # update the list 313 | set(SFML_GRAPHICS_DEPENDENCIES ${FREETYPE_LIBRARY} ${GLEW_LIBRARY} ${JPEG_LIBRARY}) 314 | set(SFML_DEPENDENCIES ${SFML_GRAPHICS_DEPENDENCIES} ${SFML_DEPENDENCIES}) 315 | endif() 316 | 317 | # sfml-audio 318 | list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT) 319 | if(NOT ${FIND_SFML_AUDIO_COMPONENT} EQUAL -1) 320 | 321 | # find libraries 322 | find_sfml_dependency(OPENAL_LIBRARY "OpenAL" openal openal32) 323 | find_sfml_dependency(SNDFILE_LIBRARY "libsndfile" sndfile) 324 | 325 | # update the list 326 | set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY}) 327 | set(SFML_DEPENDENCIES ${SFML_AUDIO_DEPENDENCIES} ${SFML_DEPENDENCIES}) 328 | endif() 329 | 330 | endif() 331 | 332 | # handle errors 333 | if(NOT SFML_VERSION_OK) 334 | # SFML version not ok 335 | set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR})") 336 | set(SFML_FOUND FALSE) 337 | elseif(SFML_STATIC_LIBRARIES AND FIND_SFML_DEPENDENCIES_NOTFOUND) 338 | set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})") 339 | set(SFML_FOUND FALSE) 340 | elseif(NOT SFML_FOUND) 341 | # include directory or library not found 342 | set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})") 343 | endif() 344 | if (NOT SFML_FOUND) 345 | if(SFML_FIND_REQUIRED) 346 | # fatal error 347 | message(FATAL_ERROR ${FIND_SFML_ERROR}) 348 | elseif(NOT SFML_FIND_QUIETLY) 349 | # error but continue 350 | message("${FIND_SFML_ERROR}") 351 | endif() 352 | endif() 353 | 354 | # handle success 355 | if(SFML_FOUND) 356 | message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR} in ${SFML_INCLUDE_DIR}") 357 | endif() -------------------------------------------------------------------------------- /cmake/UseGLM.cmake: -------------------------------------------------------------------------------- 1 | # CMake version 2 | cmake_minimum_required(VERSION 2.8.8) 3 | 4 | # use_glm([targets...]) 5 | # Try to find GLM add it as the include directoy 6 | function(use_glm) 7 | # GLM 8 | set(GLM_ROOT ${CMAKE_SOURCE_DIR}/external/glm/install CACHE FILEPATH "") 9 | set(GLM_ROOT ${GLM_ROOT} CACHE FILEPATH "Path to GLM installation." FORCE) 10 | 11 | # Find package and include headers and libraries 12 | find_package(GLM) 13 | if (GLM_FOUND) 14 | include_directories(${GLM_INCLUDE_DIR}) 15 | message(STATUS "Found dependency GLM at " ${GLM_ROOT} ".") 16 | else() 17 | message(SEND_ERROR "Dependency GLM not found. Please set GLM_ROOT to " 18 | "the installation directory.") 19 | endif() 20 | endfunction() 21 | -------------------------------------------------------------------------------- /cmake/UseSFML.cmake: -------------------------------------------------------------------------------- 1 | # CMake version 2 | cmake_minimum_required(VERSION 2.8.8) 3 | 4 | # use_sfml([targets...]) 5 | # Try to find SFML of correct configuration and link it to all targets passed 6 | # as arguments 7 | function(use_sfml) 8 | # SFML 9 | set(SFML_ROOT ${CMAKE_SOURCE_DIR}/external/sfml/install CACHE FILEPATH "") 10 | set(SFML_ROOT ${SFML_ROOT} CACHE FILEPATH "Path to SFML installation." FORCE) 11 | 12 | # Linkage 13 | if (BUILD_SHARED_LIBS) 14 | set(SFML_STATIC_LIBRARIES FALSE) 15 | else() 16 | set(SFML_STATIC_LIBRARIES TRUE) 17 | endif() 18 | 19 | # Find package and include headers and libraries 20 | find_package(SFML 2 QUIET COMPONENTS graphics window system) 21 | if (SFML_FOUND) 22 | include_directories(${SFML_INCLUDE_DIR}) 23 | foreach(TARGET ${ARGN}) 24 | target_link_libraries(${TARGET} ${SFML_LIBRARIES} ${SFML_DEPENDENCIES}) 25 | endforeach() 26 | message(STATUS "Found dependency SFML at " ${SFML_ROOT} ".") 27 | else() 28 | message(SEND_ERROR "Dependency SFML not found. Please set SFML_ROOT to the " 29 | "installation directory.") 30 | endif() 31 | endfunction() 32 | -------------------------------------------------------------------------------- /external/glm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # GLM 2 | cmake_minimum_required(VERSION 2.8.8) 3 | include(ExternalProject) 4 | 5 | # Download, configure, build and install 6 | ExternalProject_Add(GLM 7 | # DEPENDS 8 | PREFIX ${CMAKE_SOURCE_DIR} 9 | TMP_DIR ${CMAKE_SOURCE_DIR}/temp 10 | STAMP_DIR ${CMAKE_SOURCE_DIR}/stamp 11 | #--Download step-------------- 12 | DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/source 13 | GIT_REPOSITORY https://github.com/g-truc/glm.git 14 | GIT_TAG 2ac05f11e0 15 | #--Update/Patch step---------- 16 | UPDATE_COMMAND "" 17 | #--Configure step------------- 18 | CONFIGURE_COMMAND "" 19 | SOURCE_DIR ${CMAKE_SOURCE_DIR}/source 20 | #--Build step----------------- 21 | BUILD_COMMAND "" 22 | BINARY_DIR ${CMAKE_SOURCE_DIR} 23 | #--Install step--------------- 24 | INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory source/glm install/glm 25 | INSTALL_DIR ${CMAKE_SOURCE_DIR}/install 26 | ) 27 | -------------------------------------------------------------------------------- /external/sfml/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SFML 2 | cmake_minimum_required(VERSION 2.8.8) 3 | include(ExternalProject) 4 | 5 | # Download, configure, build and install 6 | ExternalProject_Add(SFML 7 | # DEPENDS 8 | PREFIX ${CMAKE_SOURCE_DIR} 9 | TMP_DIR ${CMAKE_SOURCE_DIR}/temp 10 | STAMP_DIR ${CMAKE_SOURCE_DIR}/stamp 11 | #--Download step-------------- 12 | DOWNLOAD_DIR ${CMAKE_SOURCE_DIR}/source 13 | GIT_REPOSITORY https://github.com/LaurentGomila/SFML.git 14 | GIT_TAG e257909 15 | #--Update/Patch step---------- 16 | UPDATE_COMMAND "" 17 | #--Configure step------------- 18 | SOURCE_DIR ${CMAKE_SOURCE_DIR}/source 19 | CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_SOURCE_DIR}/install 20 | -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} 21 | -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} 22 | -DSFML_USE_STATIC_STD_LIBS=${USE_STATIC_STD_LIBS} 23 | #--Build step----------------- 24 | BINARY_DIR ${CMAKE_SOURCE_DIR}/build 25 | #--Install step--------------- 26 | INSTALL_DIR ${CMAKE_SOURCE_DIR}/install 27 | ) 28 | -------------------------------------------------------------------------------- /screenshot/2014-12-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danijar/voxel-smoothing-2d/705c91e32a851f56eef763543a36886268c66e7d/screenshot/2014-12-12.png -------------------------------------------------------------------------------- /src/blocks.cpp: -------------------------------------------------------------------------------- 1 | #include "blocks.h" 2 | 3 | #include 4 | 5 | using namespace std; 6 | using namespace glm; 7 | 8 | Blocks::Blocks(ivec2 max) : m_max(max) 9 | { 10 | // Allocate memory for blocks 11 | m_data = new uint8_t[m_max.x * m_max.y]; 12 | m_blocks = new uint8_t*[m_max.x]; 13 | for (int i = 0; i < m_max.x; ++i) 14 | m_blocks[i] = m_data + m_max.y * i; 15 | 16 | // Initialize to zero 17 | memset(m_data, 0, m_max.x * m_max.y * sizeof uint8_t); 18 | } 19 | 20 | Blocks::~Blocks() 21 | { 22 | // Free memory for blocks 23 | delete[] m_blocks; 24 | delete[] m_data; 25 | } 26 | 27 | void Blocks::set(glm::ivec2 block, uint8_t value) 28 | { 29 | // Set block if in range 30 | if (in_range(block)) 31 | m_blocks[block.x][block.y] = value; 32 | } 33 | 34 | uint8_t Blocks::get(ivec2 block, uint8_t fallback) 35 | { 36 | // Return value if in range 37 | if (in_range(block)) 38 | return m_blocks[block.x][block.y]; 39 | return fallback; 40 | } 41 | 42 | bool Blocks::is(ivec2 block, bool fallback) 43 | { 44 | // Return whether value if not zero if in range 45 | if (in_range(block)) 46 | return (m_blocks[block.x][block.y] > 0); 47 | return fallback; 48 | } 49 | 50 | uint8_t **Blocks::get_pointer() 51 | { 52 | return m_blocks; 53 | } 54 | 55 | bool Blocks::in_range(ivec2 block) 56 | { 57 | // Check bounds 58 | bool inside_x = (0 <= block.x && block.x < static_cast(m_max.x)); 59 | bool inside_y = (0 <= block.y && block.y < static_cast(m_max.y)); 60 | return inside_x && inside_y; 61 | } 62 | 63 | ivec2 Blocks::get_size() 64 | { 65 | return m_max; 66 | } 67 | 68 | void Blocks::fill_randomly() 69 | { 70 | // loop over all blocks 71 | for (int i = 0; i < m_max.x; ++i) 72 | for (int j = 0; j < m_max.y; ++j) 73 | m_blocks[i][j] = rand() % 100 < 25; 74 | } 75 | -------------------------------------------------------------------------------- /src/blocks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class Blocks 8 | { 9 | public: 10 | Blocks(glm::ivec2 max); 11 | ~Blocks(); 12 | void set(glm::ivec2 block, uint8_t value = 1); 13 | uint8_t get(glm::ivec2 block, uint8_t fallback = 1); 14 | bool is(glm::ivec2 block, bool fallback = 1); 15 | uint8_t **get_pointer(); 16 | bool in_range(glm::ivec2 block); 17 | glm::ivec2 get_size(); 18 | void fill_randomly(); 19 | private: 20 | const glm::ivec2 m_max; 21 | uint8_t *m_data; 22 | uint8_t **m_blocks; 23 | }; 24 | -------------------------------------------------------------------------------- /src/draw.cpp: -------------------------------------------------------------------------------- 1 | #include "draw.h" 2 | 3 | #include 4 | 5 | using namespace std; 6 | using namespace glm; 7 | 8 | 9 | namespace draw { 10 | 11 | void pixel(sf::Image &image, int x, int y, sf::Color color) 12 | { 13 | // Check bounds 14 | if (x < 0) return; 15 | if (y < 0) return; 16 | sf::Vector2u size = image.getSize(); 17 | if (x >= (int)size.x) return; 18 | if (y >= (int)size.y) return; 19 | 20 | // Set pixel 21 | image.setPixel(x, y, color); 22 | } 23 | 24 | void dot(sf::Image &image, int x, int y, int radius, sf::Color color) 25 | { 26 | // Loop over a circle 27 | for (int i = -radius; i <= radius; ++i) 28 | for (int j = -radius; j <= radius; ++j) { 29 | // Skip pixels out of circle 30 | if (i * i + j * j > radius * radius) 31 | continue; 32 | 33 | // Set pixel 34 | pixel(image, x + i, y + j, color); 35 | } 36 | } 37 | 38 | void square(sf::Image &image, int x, int y, int radius, sf::Color color) 39 | { 40 | // Loop over a square 41 | for (int i = -radius; i <= radius; ++i) 42 | for (int j = -radius; j <= radius; ++j) { 43 | // Set pixel 44 | pixel(image, x + i, y + j, color); 45 | } 46 | } 47 | 48 | void line(sf::Image &image, int fromx, int fromy, int tox, int toy, sf::Color color) 49 | { 50 | // Optimized bresenham line algorithm 51 | int dx = abs(tox - fromx); 52 | int dy = abs(toy - fromy); 53 | int sx = detail::sign(fromx, tox); 54 | int sy = detail::sign(fromy, toy); 55 | int error = dx - dy; 56 | for (;;) { 57 | pixel(image, fromx, fromy, color); 58 | bool fx = sx > 0 ? fromx >= tox : fromx <= tox; 59 | bool fy = sy > 0 ? fromy >= toy : fromy <= toy; 60 | if (fx && fy) 61 | break; 62 | if (2 * error > -dy) { 63 | error -= dy; 64 | fromx += sx; 65 | } 66 | if (2 * error < dx) { 67 | error += dx; 68 | fromy += sy; 69 | } 70 | } 71 | } 72 | 73 | void bezier(sf::Image &image, list &points, int resolution, sf::Color color) 74 | { 75 | // Sample curve points 76 | list samples; 77 | double step = 1.0 / resolution; 78 | for (double time = 0.0; time <= 1.0; time += step) { 79 | list sliders = points; 80 | while (sliders.size() > 1) 81 | sliders = detail::slide(sliders, time); 82 | samples.push_back(sliders.front()); 83 | } 84 | 85 | // Draw curve by connection samples with small lines 86 | auto i = samples.begin(); 87 | dvec2 last = *i++; 88 | for (; i != samples.end(); ++i) { 89 | int fromx = static_cast(last.x); 90 | int fromy = static_cast(last.y); 91 | int tox = static_cast(i->x); 92 | int toy = static_cast(i->y); 93 | line(image, fromx, fromy, tox, toy, color); 94 | last = *i; 95 | } 96 | } 97 | 98 | void grid(sf::Image &image, int resolution, sf::Color color) 99 | { 100 | // Get dimensions 101 | sf::Vector2u size = image.getSize(); 102 | 103 | // Draw rows 104 | for (size_t j = 0; j < size.y; j += resolution) 105 | for (size_t i = 0; i < size.x; ++i) 106 | image.setPixel(i, j, color); 107 | 108 | // Draw columns 109 | for (size_t i = 0; i < size.x; i += resolution) 110 | for (size_t j = 0; j < size.y; ++j) 111 | image.setPixel(i, j, color); 112 | } 113 | 114 | namespace detail { 115 | 116 | int sign(int from, int to) 117 | { 118 | int difference = to - from; 119 | return (difference < 0) ? -1 : (difference > 0) ? 1 : 0; 120 | } 121 | 122 | list slide(list &points, double time) 123 | { 124 | list result; 125 | auto current = points.begin(); 126 | dvec2 last = *current; 127 | for (++current; current != points.end(); ++current) { 128 | result.push_back(last * time + *current * (1.0 - time)); 129 | last = *current; 130 | } 131 | return result; 132 | } 133 | 134 | } // namespace detail 135 | } // namespace draw 136 | -------------------------------------------------------------------------------- /src/draw.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace draw { 9 | 10 | void pixel(sf::Image &image, int x, int y, sf::Color color); 11 | void dot(sf::Image &image, int left, int top, int radius = 4, sf::Color color = sf::Color::White); 12 | void square(sf::Image &image, int left, int top, int radius = 3, sf::Color color = sf::Color::White); 13 | void line(sf::Image &image, int fromx, int fromy, int tox, int toy, sf::Color color = sf::Color(127, 127, 127)); 14 | void bezier(sf::Image &image, std::list &points, int resolution = 15, sf::Color color = sf::Color::White); 15 | void grid(sf::Image &image, int resolution, sf::Color color = sf::Color(127, 127, 127)); 16 | 17 | namespace detail { 18 | 19 | int sign(int From, int To); 20 | std::list slide(std::list &points, double time); 21 | 22 | } // namespace detail 23 | } // namespace draw 24 | -------------------------------------------------------------------------------- /src/field.cpp: -------------------------------------------------------------------------------- 1 | #include "field.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "draw.h" 7 | #include "points.h" 8 | 9 | using namespace std; 10 | using namespace glm; 11 | using namespace sf; 12 | 13 | Field::Field(Blocks* blocks, int resolution) : m_blocks(blocks), m_points(m_blocks), m_resolution(resolution) 14 | { 15 | // Initialize data 16 | clear(); 17 | m_texture.loadFromImage(m_image); 18 | m_sprite.setTexture(m_texture); 19 | } 20 | 21 | void Field::clear() 22 | { 23 | m_image.create(m_blocks->get_size().x * m_resolution + 1, m_blocks->get_size().y * m_resolution + 1, Color::White); 24 | } 25 | 26 | void Field::draw() 27 | { 28 | // Clear texture 29 | clear(); 30 | 31 | // Draw grid 32 | draw::grid(m_image, m_resolution, Color(230, 230, 230)); 33 | 34 | // Loop over blocks 35 | ivec2 index; 36 | for (index.x = 0; index.x < m_blocks->get_size().x; index.x++) { 37 | for (index.y = 0; index.y < m_blocks->get_size().y; index.y++) { 38 | // Draw blocks 39 | //if (m_blocks->get(index)) 40 | // draw::square(m_image, coordinates(index).x, coordinates(index).y, 4); 41 | 42 | // Fetch points 43 | auto lines = m_points.find(index); 44 | 45 | // Draw pts 46 | Color controls_color(60, 200, 60); 47 | for (auto line : lines) { 48 | auto i = line.begin(); 49 | ivec2 last_point = coordinates(index, *i); 50 | ivec2 current_point; 51 | draw::dot(m_image, last_point.x, last_point.y, 4, controls_color); 52 | for (++i; i != line.end(); ++i) { 53 | current_point = coordinates(index, *i); 54 | draw::line(m_image, last_point.x, last_point.y, current_point.x, current_point.y, controls_color); 55 | draw::dot(m_image, current_point.x, current_point.y, 4, controls_color); 56 | last_point = current_point; 57 | } 58 | list points; 59 | double spread = 1.0; 60 | for (auto i : line) 61 | points.push_back(coordinates(index, i * spread)); 62 | draw::bezier(m_image, points, 30, Color::Black); 63 | } 64 | } 65 | } 66 | 67 | // Update texture 68 | m_texture.loadFromImage(m_image); 69 | } 70 | 71 | void Field::click(int X, int Y) 72 | { 73 | // Calculate block from coordinates 74 | ivec2 block; 75 | Vector2f offset = m_sprite.getPosition(); 76 | Vector2f size = static_cast(m_resolution)* m_sprite.getScale(); 77 | block.x = static_cast((X - offset.x) / size.x); 78 | block.y = static_cast((Y - offset.y) / size.y); 79 | 80 | // Toggle block 81 | m_blocks->set(block, m_blocks->get(block) ? 0 : 1); 82 | } 83 | 84 | Sprite* Field::sprite() 85 | { 86 | return &m_sprite; 87 | } 88 | 89 | ivec2 Field::coordinates(ivec2 block, dvec2 offset) 90 | { 91 | return block * m_resolution + ivec2(offset * dvec2(m_resolution)); 92 | } 93 | -------------------------------------------------------------------------------- /src/field.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "sfml/Graphics.hpp" 6 | #include "blocks.h" 7 | #include "points.h" 8 | 9 | class Field { 10 | public: 11 | Field(Blocks* blocks, int resolution = 64); 12 | void clear(); 13 | void draw(); 14 | void click(int X, int Y); 15 | sf::Sprite* sprite(); 16 | private: 17 | glm::ivec2 coordinates(glm::ivec2 block, glm::dvec2 offset = glm::dvec2(0.5)); 18 | 19 | Blocks* m_blocks; 20 | ::Points m_points; 21 | int m_resolution; 22 | sf::Image m_image; 23 | sf::Texture m_texture; 24 | sf::Sprite m_sprite; 25 | }; 26 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "sfml/Window.hpp" 2 | #include "blocks.h" 3 | #include "points.h" 4 | #include "field.h" 5 | 6 | using namespace sf; 7 | 8 | 9 | int main() 10 | { 11 | // Open window 12 | RenderWindow window(VideoMode(1290, 650), "Voxel Smoothing 2D"); 13 | 14 | // Intialization 15 | Blocks blocks(glm::ivec2(20, 10)); 16 | blocks.fill_randomly(); 17 | Field field(&blocks); 18 | field.sprite()->setPosition(5, 5); 19 | field.draw(); 20 | 21 | // main loop 22 | while (window.isOpen()) { 23 | // Handle events 24 | Event event; 25 | while (window.pollEvent(event)) { 26 | switch (event.type) { 27 | case Event::Closed: 28 | window.close(); 29 | break; 30 | case Event::KeyPressed: 31 | switch (event.key.code) { 32 | case Keyboard::Escape: 33 | window.close(); 34 | break; 35 | } 36 | break; 37 | case Event::MouseButtonPressed: 38 | Vector2f target = window.mapPixelToCoords(Vector2i(event.mouseButton.x, event.mouseButton.y)); 39 | field.click(static_cast(target.x), static_cast(target.y)); 40 | field.draw(); 41 | break; 42 | } 43 | } 44 | 45 | // Draw sprite 46 | window.clear(Color::White); 47 | window.draw(*field.sprite()); 48 | window.display(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/points.cpp: -------------------------------------------------------------------------------- 1 | #include "points.h" 2 | 3 | #include 4 | 5 | using namespace std; 6 | using namespace glm; 7 | 8 | 9 | Points::Points(Blocks *blocks) : m_blocks(blocks) 10 | { 11 | 12 | } 13 | 14 | list> Points::find(ivec2 block) 15 | { 16 | // Control points 17 | list> lines; 18 | list *line = nullptr; 19 | 20 | // Fetch blocks, neighbours start top left and count 21 | // around the center block clock wise 22 | int center = m_blocks->get(block); 23 | int neighs[8]; 24 | for (int i = 0; i < 8; i++) { 25 | auto coord = blockFromIndex(i); 26 | neighs[i] = m_blocks->get(block + coord); 27 | } 28 | 29 | // Iterate over neighbour blocks 30 | for (int i = 0; i < 8; i++) { 31 | int current = neighs[i]; 32 | int next = neighs[(i + 1) % 8]; 33 | bool is_side = (((i + 1) % 2) == 0); 34 | bool is_corner = (((i + 1) % 2) == 1); 35 | 36 | if (line) { 37 | // Border between air and ground needs a line 38 | if (current != center) { 39 | // Sides are cool, but corners get skipped when they don't 40 | // stop a line 41 | if (is_side || next == center) 42 | line->push_back(blockFromIndex(i)); 43 | } else if (center || is_side || next == center) { 44 | // Stop line since we found an end of the border. Always 45 | // stop for ground blocks here, since they connect over 46 | // corners so there must be open docking sites 47 | line = nullptr; 48 | } 49 | } else { 50 | // Start a new line for the border between air and ground that 51 | // just appeared. However, corners get skipped if they don't 52 | // end a line. 53 | if (current != center) { 54 | lines.emplace_back(); 55 | line = &lines.back(); 56 | line->push_back(blockFromIndex(i)); 57 | } 58 | } 59 | } 60 | 61 | // Merge last line with first if touching. Only close around a differing corner for air 62 | // blocks. 63 | if (neighs[7] != center && (neighs[0] != center || (!center && neighs[1] != center))) { 64 | // Skip first corner if enclosed 65 | if (neighs[0] != center && neighs[1] != center) 66 | lines.front().pop_front(); 67 | if (lines.size() == 1) { 68 | // Close circle 69 | auto first_point = lines.front().front(); 70 | lines.front().push_back(first_point); 71 | } else { 72 | // Insert last line into first one 73 | lines.front().insert(lines.front().begin(), line->begin(), line->end()); 74 | lines.pop_back(); 75 | } 76 | } 77 | 78 | // Discard lines with too few points 79 | auto i = lines.begin(); 80 | while (i != lines.end()) { 81 | if (i->size() < 2) 82 | lines.erase(i++); 83 | else 84 | ++i; 85 | } 86 | 87 | // Convert to concrete points for output 88 | list> points; 89 | for (auto &line : lines) { 90 | points.emplace_back(); 91 | for (auto &neighbour : line) 92 | points.back().push_back(pointTowards(neighbour)); 93 | } 94 | return points; 95 | } 96 | 97 | glm::ivec2 Points::blockFromIndex(int i) 98 | { 99 | // Returns first positive representant, we need this so that the 100 | // conditions below "wrap around" 101 | auto modulo = [](int i, int n) { return (i % n + n) % n; }; 102 | 103 | ivec2 block(0, 0); 104 | // For two indices, zero is right so skip 105 | if (modulo(i - 1, 4)) 106 | // The others are either 1 or -1 107 | block.x = modulo(i - 1, 8) / 4 ? -1 : 1; 108 | // Other axis is same sequence but shifted 109 | if (modulo(i - 3, 4)) 110 | block.y = modulo(i - 3, 8) / 4 ? -1 : 1; 111 | return block; 112 | } 113 | 114 | dvec2 Points::pointTowards(ivec2 neighbour) 115 | { 116 | dvec2 point; 117 | point.x = static_cast(neighbour.x); 118 | point.y = static_cast(neighbour.y); 119 | 120 | // Convert from neighbour space into 121 | // drawing space of the block 122 | point *= 0.5; 123 | point += dvec2(.5); 124 | 125 | return point; 126 | } -------------------------------------------------------------------------------- /src/points.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "blocks.h" 7 | 8 | class Points 9 | { 10 | public: 11 | Points(Blocks *blocks); 12 | std::list> find(glm::ivec2 block); 13 | private: 14 | glm::ivec2 blockFromIndex(int i); 15 | glm::dvec2 pointTowards(glm::ivec2 neighbour); 16 | 17 | Blocks *m_blocks; 18 | }; 19 | --------------------------------------------------------------------------------