Merge remote-tracking branch 'origin/master' into lm_wiping_dialog_colors
|  | @ -18,8 +18,8 @@ AllowShortLoopsOnASingleLine: true | |||
| AlwaysBreakAfterDefinitionReturnType: None | ||||
| AlwaysBreakAfterReturnType: None | ||||
| AlwaysBreakBeforeMultilineStrings: false | ||||
| AlwaysBreakTemplateDeclarations: Yes | ||||
| BinPackArguments: false | ||||
| AlwaysBreakTemplateDeclarations: false | ||||
| BinPackArguments: true | ||||
| BinPackParameters: false | ||||
| BraceWrapping:    | ||||
|   AfterClass:      true | ||||
|  | @ -37,18 +37,18 @@ BraceWrapping: | |||
|   SplitEmptyFunction: false | ||||
|   SplitEmptyRecord: false | ||||
|   SplitEmptyNamespace: false | ||||
| BreakBeforeBinaryOperators: All | ||||
| BreakBeforeBinaryOperators: None | ||||
| BreakBeforeBraces: Custom | ||||
| BreakBeforeInheritanceComma: false | ||||
| BreakInheritanceList: BeforeColon | ||||
| BreakBeforeTernaryOperators: true | ||||
| BreakBeforeTernaryOperators: false | ||||
| BreakConstructorInitializersBeforeComma: false | ||||
| BreakConstructorInitializers: BeforeComma | ||||
| BreakAfterJavaFieldAnnotations: false | ||||
| BreakStringLiterals: true | ||||
| ColumnLimit:     75 | ||||
| ColumnLimit:     78 | ||||
| CommentPragmas:  '^ IWYU pragma:' | ||||
| CompactNamespaces: false | ||||
| CompactNamespaces: true | ||||
| ConstructorInitializerAllOnOneLineOrOnePerLine: true | ||||
| ConstructorInitializerIndentWidth: 4 | ||||
| ContinuationIndentWidth: 4 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								.github/ISSUE_TEMPLATE.md
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -24,3 +24,4 @@ _Is this a new feature request?_ | |||
| 
 | ||||
| #### Project File (.3MF) where problem occurs | ||||
| _Upload a PrusaSlicer Project File (.3MF) (`Plater -> Export plate as 3MF` for Slic3r PE 1.41.2 and older, `File -> Save` / `Save Project` for PrusaSlicer, Slic3r PE 1.42.0-alpha and newer)_ | ||||
| _Images (PNG, GIF, JPEG), PDFs or text files could be drag & dropped to the issue directly, while all other files need to be zipped first (.zip, .gz)_ | ||||
|  |  | |||
							
								
								
									
										2
									
								
								Build.PL
									
										
									
									
									
								
							
							
						
						|  | @ -16,6 +16,8 @@ my %prereqs = qw( | |||
|     ExtUtils::MakeMaker             6.80 | ||||
|     ExtUtils::ParseXS               3.22 | ||||
|     ExtUtils::XSpp                  0 | ||||
|     ExtUtils::XSpp::Cmd             0 | ||||
|     ExtUtils::CppGuess              0 | ||||
|     ExtUtils::Typemaps              0 | ||||
|     ExtUtils::Typemaps::Basic       0 | ||||
|     File::Basename                  0 | ||||
|  |  | |||
							
								
								
									
										152
									
								
								CMakeLists.txt
									
										
									
									
									
								
							
							
						
						|  | @ -13,13 +13,13 @@ if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | |||
| endif() | ||||
| 
 | ||||
| if(DEFINED ENV{SLIC3R_STATIC}) | ||||
| 	set(SLIC3R_STATIC_INITIAL $ENV{SLIC3R_STATIC}) | ||||
|         set(SLIC3R_STATIC_INITIAL $ENV{SLIC3R_STATIC}) | ||||
| else() | ||||
| 	if (MSVC OR MINGW OR APPLE) | ||||
| 		set(SLIC3R_STATIC_INITIAL 1) | ||||
| 	else() | ||||
| 		set(SLIC3R_STATIC_INITIAL 0) | ||||
| 	endif() | ||||
|         if (MSVC OR MINGW OR APPLE) | ||||
|                 set(SLIC3R_STATIC_INITIAL 1) | ||||
|         else() | ||||
|                 set(SLIC3R_STATIC_INITIAL 0) | ||||
|         endif() | ||||
| endif() | ||||
| 
 | ||||
| option(SLIC3R_STATIC 			"Compile PrusaSlicer with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL}) | ||||
|  | @ -32,7 +32,6 @@ option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1) | |||
| option(SLIC3R_MSVC_PDB          "Generate PDB files on MSVC in Release mode" 1) | ||||
| option(SLIC3R_PERL_XS           "Compile XS Perl module and enable Perl unit and integration tests" 0) | ||||
| option(SLIC3R_ASAN              "Enable ASan on Clang and GCC" 0) | ||||
| option(SLIC3R_SYNTAXONLY        "Only perform source code correctness checking, no binary output (UNIX only)" 0) | ||||
| 
 | ||||
| set(SLIC3R_GTK "2" CACHE STRING "GTK version to use with wxWidgets on Linux") | ||||
| 
 | ||||
|  | @ -53,14 +52,30 @@ if (SLIC3R_GUI) | |||
|     add_definitions(-DSLIC3R_GUI) | ||||
| endif () | ||||
| 
 | ||||
| if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) | ||||
|     set(IS_CLANG_CL TRUE) | ||||
| 
 | ||||
|     # clang-cl can interpret SYSTEM header paths if -imsvc is used | ||||
|     set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-imsvc") | ||||
| 
 | ||||
|     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \ | ||||
|         -Wno-old-style-cast -Wno-reserved-id-macro -Wno-c++98-compat-pedantic") | ||||
| else () | ||||
|     set(IS_CLANG_CL FALSE) | ||||
| endif () | ||||
| 
 | ||||
| if (MSVC) | ||||
|     if (SLIC3R_MSVC_COMPILE_PARALLEL) | ||||
| 	   add_compile_options(/MP) | ||||
|     if (SLIC3R_MSVC_COMPILE_PARALLEL AND NOT IS_CLANG_CL) | ||||
|            add_compile_options(/MP) | ||||
|     endif () | ||||
|     # /bigobj (Increase Number of Sections in .Obj file) | ||||
|     # error C3859: virtual memory range for PCH exceeded; please recompile with a command line option of '-Zm90' or greater | ||||
|     # Generate symbols at every build target, even for the release. | ||||
|     add_compile_options(-bigobj -Zm316 /Zi) | ||||
|     add_compile_options(-bigobj -Zm520 /Zi) | ||||
| endif () | ||||
| 
 | ||||
| if (MINGW) | ||||
|     add_compile_options(-Wa,-mbig-obj) | ||||
| endif () | ||||
| 
 | ||||
| # Display and check CMAKE_PREFIX_PATH | ||||
|  | @ -89,8 +104,6 @@ enable_testing () | |||
| # Enable C++11 language standard. | ||||
| set(CMAKE_CXX_STANDARD 11) | ||||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||
| set(CMAKE_C_STANDARD 11) | ||||
| set(CMAKE_C_STANDARD_REQUIRED ON) | ||||
| 
 | ||||
| if(NOT WIN32) | ||||
|     # Add DEBUG flags to debug builds. | ||||
|  | @ -104,17 +117,17 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) | |||
| # WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory. | ||||
| # We pick it from environment if it is not defined in another way | ||||
| if(WIN32) | ||||
| 	if(NOT DEFINED WIN10SDK_PATH) | ||||
| 		if(DEFINED ENV{WIN10SDK_PATH}) | ||||
| 			set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}") | ||||
| 		endif() | ||||
| 	endif() | ||||
| 	if(DEFINED WIN10SDK_PATH AND NOT EXISTS "${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h") | ||||
| 		message("WIN10SDK_PATH is invalid: ${WIN10SDK_PATH}") | ||||
| 		message("${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h was not found") | ||||
| 		message("STL fixing by the Netfabb service will not be compiled") | ||||
| 		unset(WIN10SDK_PATH) | ||||
| 	endif() | ||||
|         if(NOT DEFINED WIN10SDK_PATH) | ||||
|                 if(DEFINED ENV{WIN10SDK_PATH}) | ||||
|                         set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}") | ||||
|                 endif() | ||||
|         endif() | ||||
|         if(DEFINED WIN10SDK_PATH AND NOT EXISTS "${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h") | ||||
|                 message("WIN10SDK_PATH is invalid: ${WIN10SDK_PATH}") | ||||
|                 message("${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h was not found") | ||||
|                 message("STL fixing by the Netfabb service will not be compiled") | ||||
|                 unset(WIN10SDK_PATH) | ||||
|         endif() | ||||
|     if(WIN10SDK_PATH) | ||||
|         message("Building with Win10 Netfabb STL fixing service support") | ||||
|         add_definitions(-DHAS_WIN10SDK) | ||||
|  | @ -149,30 +162,29 @@ endif() | |||
| if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX) | ||||
|     # Adding -fext-numeric-literals to enable GCC extensions on definitions of quad float literals, which are required by Boost. | ||||
|     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals" ) | ||||
| 
 | ||||
|     if (SLIC3R_SYNTAXONLY) | ||||
|         set(CMAKE_CXX_ARCHIVE_CREATE "true") | ||||
|         set(CMAKE_C_ARCHIVE_CREATE "true") | ||||
|         set(CMAKE_CXX_ARCHIVE_APPEND "true") | ||||
|         set(CMAKE_C_ARCHIVE_APPEND "true") | ||||
|         set(CMAKE_RANLIB "true") | ||||
|         set(CMAKE_C_LINK_EXECUTABLE "true") | ||||
|         set(CMAKE_CXX_LINK_EXECUTABLE "true") | ||||
| 
 | ||||
|         set(CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> -fsyntax-only <DEFINES> <INCLUDES> <FLAGS> -c <SOURCE> && touch <OBJECT>") | ||||
|         set(CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> -fsyntax-only <DEFINES> <INCLUDES> <FLAGS> -c <SOURCE> && touch <OBJECT>") | ||||
|     endif () | ||||
| endif() | ||||
| 
 | ||||
| if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") | ||||
|     add_compile_options(-Wall) | ||||
| if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) | ||||
|     if (NOT MINGW) | ||||
|         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" ) | ||||
|     endif () | ||||
|     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder" ) | ||||
| 
 | ||||
|     # On GCC and Clang, no return from a non-void function is a warning only. Here, we make it an error. | ||||
|     add_compile_options(-Werror=return-type) | ||||
| 
 | ||||
|     #removes LOTS of extraneous Eigen warnings | ||||
|     add_compile_options(-Wno-ignored-attributes) | ||||
|     #removes LOTS of extraneous Eigen warnings (GCC only supports it since 6.1) | ||||
|     #if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6.1) | ||||
|         # add_compile_options(-Wno-ignored-attributes) # Tamas: Eigen include dirs are marked as SYSTEM | ||||
|     #endif() | ||||
| 
 | ||||
|     #GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see | ||||
|     # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943 or | ||||
|     # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431 | ||||
|     # We will turn the warning of for GCC for now: | ||||
|     if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") | ||||
|         add_compile_options(-Wno-unknown-pragmas) | ||||
|     endif() | ||||
| 
 | ||||
|     if (SLIC3R_ASAN) | ||||
|         add_compile_options(-fsanitize=address -fno-omit-frame-pointer) | ||||
|  | @ -201,9 +213,12 @@ include_directories(${LIBDIR_BIN}/platform) | |||
| include_directories(${LIBDIR}/clipper ${LIBDIR}/polypartition) | ||||
| 
 | ||||
| if(WIN32) | ||||
|     # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking. | ||||
|     add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) | ||||
| endif() | ||||
|     add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) | ||||
|     if(MSVC) | ||||
|         # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking. | ||||
|         add_definitions(-DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601 ) | ||||
|     endif(MSVC) | ||||
| endif(WIN32) | ||||
| 
 | ||||
| add_definitions(-DwxUSE_UNICODE -D_UNICODE -DUNICODE -DWXINTL_NO_GETTEXT_MACRO) | ||||
| 
 | ||||
|  | @ -234,21 +249,40 @@ if(SLIC3R_STATIC) | |||
|     # set(Boost_USE_STATIC_RUNTIME ON) | ||||
| endif() | ||||
| #set(Boost_DEBUG ON) | ||||
| # set(Boost_COMPILER "-vc120") | ||||
| # set(Boost_COMPILER "-mgw81") | ||||
| if(NOT WIN32) | ||||
|     # boost::process was introduced first in version 1.64.0 | ||||
|     set(MINIMUM_BOOST_VERSION "1.64.0") | ||||
| endif() | ||||
| find_package(Boost ${MINIMUM_BOOST_VERSION} REQUIRED COMPONENTS system filesystem thread log locale regex) | ||||
| if(Boost_FOUND) | ||||
| #    include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) | ||||
|     if (APPLE) | ||||
|         # BOOST_ASIO_DISABLE_KQUEUE : prevents a Boost ASIO bug on OS X: https://svn.boost.org/trac/boost/ticket/5339 | ||||
|         add_definitions(-DBOOST_ASIO_DISABLE_KQUEUE) | ||||
|     endif() | ||||
|     if(NOT SLIC3R_STATIC) | ||||
|         add_definitions(-DBOOST_LOG_DYN_LINK) | ||||
|     endif() | ||||
| 
 | ||||
| add_library(boost_libs INTERFACE) | ||||
| add_library(boost_headeronly INTERFACE) | ||||
| 
 | ||||
| if (APPLE) | ||||
|     # BOOST_ASIO_DISABLE_KQUEUE : prevents a Boost ASIO bug on OS X: https://svn.boost.org/trac/boost/ticket/5339 | ||||
|     target_compile_definitions(boost_headeronly INTERFACE BOOST_ASIO_DISABLE_KQUEUE) | ||||
| endif() | ||||
| 
 | ||||
| if(NOT SLIC3R_STATIC) | ||||
|     target_compile_definitions(boost_headeronly INTERFACE BOOST_LOG_DYN_LINK) | ||||
| endif() | ||||
| 
 | ||||
| if(TARGET Boost::system) | ||||
|     message(STATUS "Boost::boost exists") | ||||
|     target_link_libraries(boost_headeronly INTERFACE Boost::boost) | ||||
|     target_link_libraries(boost_libs INTERFACE | ||||
|         boost_headeronly # includes the custom compile definitions as well | ||||
|         Boost::system | ||||
|         Boost::filesystem | ||||
|         Boost::thread | ||||
|         Boost::log | ||||
|         Boost::locale | ||||
|         Boost::regex | ||||
|         ) | ||||
| else() | ||||
|     target_include_directories(boost_headeronly INTERFACE ${Boost_INCLUDE_DIRS}) | ||||
|     target_link_libraries(boost_libs INTERFACE boost_headeronly ${Boost_LIBRARIES}) | ||||
| endif() | ||||
| 
 | ||||
| # Find and configure intel-tbb | ||||
|  | @ -289,13 +323,13 @@ endif() | |||
| 
 | ||||
| # Find eigen3 or use bundled version | ||||
| if (NOT SLIC3R_STATIC) | ||||
|     find_package(Eigen3 3) | ||||
|     find_package(Eigen3 3.3) | ||||
| endif () | ||||
| if (NOT Eigen3_FOUND) | ||||
|     set(Eigen3_FOUND 1) | ||||
| if (NOT EIGEN3_FOUND) | ||||
|     set(EIGEN3_FOUND 1) | ||||
|     set(EIGEN3_INCLUDE_DIR ${LIBDIR}/eigen/) | ||||
| endif () | ||||
| include_directories(${EIGEN3_INCLUDE_DIR}) | ||||
| include_directories(BEFORE SYSTEM ${EIGEN3_INCLUDE_DIR}) | ||||
| 
 | ||||
| # Find expat or use bundled version | ||||
| # Always use the system libexpat on Linux. | ||||
|  | @ -327,6 +361,10 @@ if (NOT GLEW_FOUND) | |||
| endif () | ||||
| include_directories(${GLEW_INCLUDE_DIRS}) | ||||
| 
 | ||||
| # Find the Cereal serialization library | ||||
| add_library(cereal INTERFACE) | ||||
| target_include_directories(cereal INTERFACE include) | ||||
| 
 | ||||
| # l10n | ||||
| set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization") | ||||
| add_custom_target(pot | ||||
|  |  | |||
|  | @ -105,6 +105,9 @@ function(add_precompiled_header _target _input) | |||
|   cmake_parse_arguments(_PCH "FORCEINCLUDE" "SOURCE_CXX;SOURCE_C" "" ${ARGN}) | ||||
| 
 | ||||
|   get_filename_component(_input_we ${_input} NAME_WE) | ||||
|   get_filename_component(_input_full ${_input} ABSOLUTE) | ||||
|   file(TO_NATIVE_PATH "${_input_full}" _input_fullpath) | ||||
| 
 | ||||
|   if(NOT _PCH_SOURCE_CXX) | ||||
|     set(_PCH_SOURCE_CXX "${_input_we}.cpp") | ||||
|   endif() | ||||
|  | @ -138,16 +141,16 @@ function(add_precompiled_header _target _input) | |||
|           set_source_files_properties("${_source}" PROPERTIES OBJECT_OUTPUTS "${_pch_c_pch}") | ||||
|         else() | ||||
|           if(_source MATCHES \\.\(cpp|cxx|cc\)$) | ||||
|             set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_cxx_pch}\" \"/Yu${_input}\"") | ||||
|             set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_cxx_pch}\" \"/Yu${_input_fullpath}\"") | ||||
|             set(_pch_source_cxx_needed TRUE) | ||||
|             set_source_files_properties("${_source}" PROPERTIES OBJECT_DEPENDS "${_pch_cxx_pch}") | ||||
|           else() | ||||
|             set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_c_pch}\" \"/Yu${_input}\"") | ||||
|             set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_c_pch}\" \"/Yu${_input_fullpath}\"") | ||||
|             set(_pch_source_c_needed TRUE) | ||||
|             set_source_files_properties("${_source}" PROPERTIES OBJECT_DEPENDS "${_pch_c_pch}") | ||||
|           endif() | ||||
|           if(_PCH_FORCEINCLUDE) | ||||
|             set(_pch_compile_flags "${_pch_compile_flags} /FI${_input}") | ||||
|             set(_pch_compile_flags "${_pch_compile_flags} /FI${_input_fullpath}") | ||||
|           endif(_PCH_FORCEINCLUDE) | ||||
|         endif() | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										16
									
								
								deps/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -36,6 +36,12 @@ set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir" CACHE PATH "Destination direct | |||
| option(DEP_DEBUG "Build debug variants (only applicable on Windows)" ON) | ||||
| option(DEP_WX_STABLE "Build against wxWidgets stable 3.0 as opposed to default 3.1 (Linux only)" OFF) | ||||
| 
 | ||||
| # On developer machines, it can be enabled to speed up compilation and suppress warnings coming from IGL.  | ||||
| # FIXME: | ||||
| # Enabling this option is not safe. IGL will compile itself with its own version of Eigen while | ||||
| # Slic3r compiles with a different version which will cause runtime errors. | ||||
| # option(DEP_BUILD_IGL_STATIC "Build IGL as a static library. Might cause link errors and increase binary size." OFF) | ||||
| 
 | ||||
| message(STATUS "PrusaSlicer deps DESTDIR: ${DESTDIR}") | ||||
| message(STATUS "PrusaSlicer deps debug build: ${DEP_DEBUG}") | ||||
| 
 | ||||
|  | @ -70,7 +76,10 @@ elseif (APPLE) | |||
|     endif () | ||||
| 
 | ||||
|     include("deps-macos.cmake") | ||||
| else () | ||||
| elseif (MINGW) | ||||
|     message(STATUS "Building for MinGW...") | ||||
|     include("deps-mingw.cmake") | ||||
| else() | ||||
|     include("deps-linux.cmake") | ||||
| endif() | ||||
| 
 | ||||
|  | @ -83,7 +92,9 @@ if (MSVC) | |||
|         dep_libcurl | ||||
|         dep_wxwidgets | ||||
|         dep_gtest | ||||
|         dep_cereal | ||||
|         dep_nlopt | ||||
|         # dep_qhull # Experimental | ||||
|         dep_zlib    # on Windows we still need zlib | ||||
|     ) | ||||
| 
 | ||||
|  | @ -96,7 +107,10 @@ else() | |||
|         dep_libcurl | ||||
|         dep_wxwidgets | ||||
|         dep_gtest | ||||
|         dep_cereal | ||||
|         dep_nlopt | ||||
|         dep_qhull | ||||
|         # dep_libigl # Not working, static build has different Eigen | ||||
|     ) | ||||
| 
 | ||||
| endif() | ||||
|  |  | |||
							
								
								
									
										2
									
								
								deps/deps-macos.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -111,6 +111,6 @@ ExternalProject_Add(dep_wxwidgets | |||
|         --with-expat=builtin | ||||
|         --disable-debug | ||||
|         --disable-debug_flag | ||||
|     BUILD_COMMAND make "-j${NPROC}" && make -C locale allmo | ||||
|     BUILD_COMMAND make "-j${NPROC}" && PATH=/usr/local/opt/gettext/bin/:$ENV{PATH} make -C locale allmo | ||||
|     INSTALL_COMMAND make install | ||||
| ) | ||||
|  |  | |||
							
								
								
									
										76
									
								
								deps/deps-mingw.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,76 @@ | |||
| set(DEP_CMAKE_OPTS "-DCMAKE_POSITION_INDEPENDENT_CODE=ON") | ||||
| set(DEP_BOOST_TOOLSET "gcc") | ||||
| set(DEP_BITS 64) | ||||
| 
 | ||||
| find_package(Git REQUIRED) | ||||
| 
 | ||||
| # TODO make sure to build tbb with -flifetime-dse=1 | ||||
| include("deps-unix-common.cmake") | ||||
| 
 | ||||
| ExternalProject_Add(dep_boost | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz" | ||||
|     URL_HASH SHA256=882b48708d211a5f48e60b0124cf5863c1534cd544ecd0664bb534a4b5d506e9 | ||||
|     BUILD_IN_SOURCE 1 | ||||
|     CONFIGURE_COMMAND bootstrap.bat | ||||
|     BUILD_COMMAND b2.exe | ||||
|         -j "${NPROC}" | ||||
|         --with-system | ||||
|         --with-filesystem | ||||
|         --with-thread | ||||
|         --with-log | ||||
|         --with-locale | ||||
|         --with-regex | ||||
|         "--prefix=${DESTDIR}/usr/local" | ||||
|         "address-model=${DEPS_BITS}" | ||||
|         "toolset=${DEP_BOOST_TOOLSET}" | ||||
|         link=static | ||||
|         define=BOOST_USE_WINAPI_VERSION=0x0502 | ||||
|         variant=release | ||||
|         threading=multi | ||||
|         boost.locale.icu=off | ||||
|         "${DEP_BOOST_DEBUG}" release install | ||||
|     INSTALL_COMMAND ""   # b2 does that already | ||||
| ) | ||||
| 
 | ||||
| ExternalProject_Add(dep_libcurl | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://curl.haxx.se/download/curl-7.58.0.tar.gz" | ||||
|     URL_HASH SHA256=cc245bf9a1a42a45df491501d97d5593392a03f7b4f07b952793518d97666115 | ||||
|     CMAKE_ARGS | ||||
|         -DBUILD_SHARED_LIBS=OFF | ||||
|         -DBUILD_TESTING=OFF | ||||
|         -DCURL_STATICLIB=ON | ||||
|         -DCURL_STATIC_CRT=ON | ||||
|         -DENABLE_THREADED_RESOLVER=ON | ||||
|         -DCURL_DISABLE_FTP=ON | ||||
|         -DCURL_DISABLE_LDAP=ON | ||||
|         -DCURL_DISABLE_LDAPS=ON | ||||
|         -DCURL_DISABLE_TELNET=ON | ||||
|         -DCURL_DISABLE_DICT=ON | ||||
|         -DCURL_DISABLE_FILE=ON | ||||
|         -DCURL_DISABLE_TFTP=ON | ||||
|         -DCURL_DISABLE_RTSP=ON | ||||
|         -DCURL_DISABLE_POP3=ON | ||||
|         -DCURL_DISABLE_IMAP=ON | ||||
|         -DCURL_DISABLE_SMTP=ON | ||||
|         -DCURL_DISABLE_GOPHER=ON | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         ${DEP_CMAKE_OPTS} | ||||
| ) | ||||
| 
 | ||||
| ExternalProject_Add(dep_wxwidgets | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" | ||||
|     GIT_TAG v3.1.1-patched | ||||
| #    URL "https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.1/wxWidgets-3.1.1.tar.bz2" | ||||
| #    URL_HASH SHA256=c925dfe17e8f8b09eb7ea9bfdcfcc13696a3e14e92750effd839f5e10726159e | ||||
| #    PATCH_COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}\\wxwidgets-pngprefix.h" src\\png\\pngprefix.h | ||||
|     CMAKE_ARGS | ||||
|         -DBUILD_SHARED_LIBS=OFF | ||||
|         -DwxUSE_LIBPNG=builtin | ||||
|         -DwxUSE_ZLIB=builtin | ||||
|         -DwxUSE_OPENGL=ON | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         ${DEP_CMAKE_OPTS} | ||||
| ) | ||||
							
								
								
									
										58
									
								
								deps/deps-unix-common.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,6 +1,12 @@ | |||
| 
 | ||||
| # The unix common part expects DEP_CMAKE_OPTS to be set | ||||
| 
 | ||||
| if (MINGW) | ||||
|     set(TBB_MINGW_WORKAROUND "-flifetime-dse=1") | ||||
| else () | ||||
|     set(TBB_MINGW_WORKAROUND "") | ||||
| endif () | ||||
| 
 | ||||
| ExternalProject_Add(dep_tbb | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" | ||||
|  | @ -8,6 +14,7 @@ ExternalProject_Add(dep_tbb | |||
|     CMAKE_ARGS | ||||
|         -DTBB_BUILD_SHARED=OFF | ||||
|         -DTBB_BUILD_TESTS=OFF | ||||
|         -DCMAKE_CXX_FLAGS=${TBB_MINGW_WORKAROUND} | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         ${DEP_CMAKE_OPTS} | ||||
| ) | ||||
|  | @ -19,6 +26,16 @@ ExternalProject_Add(dep_gtest | |||
|     CMAKE_ARGS -DBUILD_GMOCK=OFF ${DEP_CMAKE_OPTS} -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
| ) | ||||
| 
 | ||||
| ExternalProject_Add(dep_cereal | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/USCiLab/cereal/archive/v1.2.2.tar.gz" | ||||
| #    URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae | ||||
|     CMAKE_ARGS | ||||
|         -DJUST_INSTALL_CEREAL=on | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         ${DEP_CMAKE_OPTS} | ||||
| ) | ||||
| 
 | ||||
| ExternalProject_Add(dep_nlopt | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz" | ||||
|  | @ -32,3 +49,44 @@ ExternalProject_Add(dep_nlopt | |||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         ${DEP_CMAKE_OPTS} | ||||
| ) | ||||
| find_package(Git REQUIRED) | ||||
| 
 | ||||
| ExternalProject_Add(dep_qhull | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/qhull/qhull/archive/v7.2.1.tar.gz" | ||||
|     URL_HASH SHA256=6fc251e0b75467e00943bfb7191e986fce0e1f8f6f0251f9c6ce5a843821ea78 | ||||
|     CMAKE_ARGS | ||||
|         -DBUILD_SHARED_LIBS=OFF | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         ${DEP_CMAKE_OPTS} | ||||
|     PATCH_COMMAND ${GIT_EXECUTABLE} apply --ignore-space-change --ignore-whitespace ${CMAKE_CURRENT_SOURCE_DIR}/qhull-mods.patch | ||||
| ) | ||||
| 
 | ||||
| ExternalProject_Add(dep_libigl | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/libigl/libigl/archive/v2.0.0.tar.gz" | ||||
|     URL_HASH SHA256=42518e6b106c7209c73435fd260ed5d34edeb254852495b4c95dce2d95401328 | ||||
|     CMAKE_ARGS | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         -DLIBIGL_BUILD_PYTHON=OFF | ||||
|         -DLIBIGL_BUILD_TESTS=OFF | ||||
|         -DLIBIGL_BUILD_TUTORIALS=OFF | ||||
|         -DLIBIGL_USE_STATIC_LIBRARY=OFF #${DEP_BUILD_IGL_STATIC} | ||||
|         -DLIBIGL_WITHOUT_COPYLEFT=OFF | ||||
|         -DLIBIGL_WITH_CGAL=OFF | ||||
|         -DLIBIGL_WITH_COMISO=OFF | ||||
|         -DLIBIGL_WITH_CORK=OFF | ||||
|         -DLIBIGL_WITH_EMBREE=OFF | ||||
|         -DLIBIGL_WITH_MATLAB=OFF | ||||
|         -DLIBIGL_WITH_MOSEK=OFF | ||||
|         -DLIBIGL_WITH_OPENGL=OFF | ||||
|         -DLIBIGL_WITH_OPENGL_GLFW=OFF | ||||
|         -DLIBIGL_WITH_OPENGL_GLFW_IMGUI=OFF | ||||
|         -DLIBIGL_WITH_PNG=OFF | ||||
|         -DLIBIGL_WITH_PYTHON=OFF | ||||
|         -DLIBIGL_WITH_TETGEN=OFF | ||||
|         -DLIBIGL_WITH_TRIANGLE=OFF | ||||
|         -DLIBIGL_WITH_XML=OFF | ||||
|     PATCH_COMMAND ${GIT_EXECUTABLE} apply --ignore-space-change --ignore-whitespace ${CMAKE_CURRENT_SOURCE_DIR}/igl-fixes.patch | ||||
| ) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										117
									
								
								deps/deps-windows.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						|  | @ -1,21 +1,38 @@ | |||
| 
 | ||||
| # https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html | ||||
| if (MSVC_VERSION EQUAL 1800) | ||||
| # 1800      = VS 12.0 (v120 toolset) | ||||
|     set(DEP_VS_VER "12") | ||||
|     set(DEP_BOOST_TOOLSET "msvc-12.0") | ||||
| elseif (MSVC_VERSION EQUAL 1900) | ||||
| # 1900      = VS 14.0 (v140 toolset)     | ||||
|     set(DEP_VS_VER "14") | ||||
|     set(DEP_BOOST_TOOLSET "msvc-14.0") | ||||
| elseif (MSVC_VERSION GREATER 1900) | ||||
| elseif (MSVC_VERSION LESS 1920) | ||||
| # 1910-1919 = VS 15.0 (v141 toolset) | ||||
|     set(DEP_VS_VER "15") | ||||
|     set(DEP_BOOST_TOOLSET "msvc-14.1") | ||||
| elseif (MSVC_VERSION LESS 1930) | ||||
| # 1920-1929 = VS 16.0 (v142 toolset) | ||||
|     set(DEP_VS_VER "16") | ||||
|     set(DEP_BOOST_TOOLSET "msvc-14.2") | ||||
| else () | ||||
|     message(FATAL_ERROR "Unsupported MSVC version") | ||||
| endif () | ||||
| 
 | ||||
| if (CMAKE_CXX_COMPILER_ID STREQUAL Clang) | ||||
|     set(DEP_BOOST_TOOLSET "clang-win") | ||||
| endif () | ||||
| 
 | ||||
| if (${DEPS_BITS} EQUAL 32) | ||||
|     set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER}") | ||||
|     set(DEP_PLATFORM "Win32") | ||||
| else () | ||||
|     set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER} Win64") | ||||
|     if (DEP_VS_VER LESS 16) | ||||
|         set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER} Win64") | ||||
|     else () | ||||
|         set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER}") | ||||
|     endif () | ||||
|     set(DEP_PLATFORM "x64") | ||||
| endif () | ||||
| 
 | ||||
| 
 | ||||
|  | @ -28,8 +45,8 @@ endif () | |||
| 
 | ||||
| ExternalProject_Add(dep_boost | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz" | ||||
|     URL_HASH SHA256=bd0df411efd9a585e5a2212275f8762079fed8842264954675a4fddc46cfcf60 | ||||
|     URL "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz" | ||||
|     URL_HASH SHA256=882b48708d211a5f48e60b0124cf5863c1534cd544ecd0664bb534a4b5d506e9 | ||||
|     BUILD_IN_SOURCE 1 | ||||
|     CONFIGURE_COMMAND bootstrap.bat | ||||
|     BUILD_COMMAND b2.exe | ||||
|  | @ -57,6 +74,7 @@ ExternalProject_Add(dep_tbb | |||
|     URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" | ||||
|     URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}" | ||||
|     CMAKE_ARGS | ||||
|         -DCMAKE_DEBUG_POSTFIX=_debug | ||||
|         -DTBB_BUILD_SHARED=OFF | ||||
|  | @ -81,6 +99,7 @@ ExternalProject_Add(dep_gtest | |||
|     URL "https://github.com/google/googletest/archive/release-1.8.1.tar.gz" | ||||
|     URL_HASH SHA256=9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}" | ||||
|     CMAKE_ARGS | ||||
|         -DBUILD_GMOCK=OFF | ||||
|         -Dgtest_force_shared_crt=ON | ||||
|  | @ -100,11 +119,26 @@ if (${DEP_DEBUG}) | |||
| endif () | ||||
| 
 | ||||
| 
 | ||||
| ExternalProject_Add(dep_cereal | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/USCiLab/cereal/archive/v1.2.2.tar.gz" | ||||
| #    URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}" | ||||
|     CMAKE_ARGS | ||||
|         -DJUST_INSTALL_CEREAL=on | ||||
|         "-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local" | ||||
|     BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj | ||||
|     INSTALL_COMMAND "" | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| ExternalProject_Add(dep_nlopt | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz" | ||||
|     URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}" | ||||
|     CMAKE_ARGS | ||||
|         -DBUILD_SHARED_LIBS=OFF | ||||
|         -DNLOPT_PYTHON=OFF | ||||
|  | @ -133,6 +167,7 @@ ExternalProject_Add(dep_zlib | |||
|     URL "https://zlib.net/zlib-1.2.11.tar.xz" | ||||
|     URL_HASH SHA256=4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066 | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}" | ||||
|     CMAKE_ARGS | ||||
|         -DSKIP_INSTALL_FILES=ON                                    # Prevent installation of man pages et al. | ||||
|         "-DINSTALL_BIN_DIR=${CMAKE_CURRENT_BINARY_DIR}\\fallout"   # I found no better way of preventing zlib from creating & installing DLLs :-/ | ||||
|  | @ -199,6 +234,33 @@ if (${DEP_DEBUG}) | |||
|     ) | ||||
| endif () | ||||
| 
 | ||||
| find_package(Git REQUIRED) | ||||
| 
 | ||||
| ExternalProject_Add(dep_qhull | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/qhull/qhull/archive/v7.2.1.tar.gz" | ||||
|     URL_HASH SHA256=6fc251e0b75467e00943bfb7191e986fce0e1f8f6f0251f9c6ce5a843821ea78 | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_ARGS | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         -DBUILD_SHARED_LIBS=OFF | ||||
|         -DCMAKE_POSITION_INDEPENDENT_CODE=ON | ||||
|         -DCMAKE_DEBUG_POSTFIX=d | ||||
|     PATCH_COMMAND ${GIT_EXECUTABLE} apply --ignore-space-change --ignore-whitespace ${CMAKE_CURRENT_SOURCE_DIR}/qhull-mods.patch | ||||
|     BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj | ||||
|     INSTALL_COMMAND "" | ||||
| ) | ||||
| 
 | ||||
| if (${DEP_DEBUG}) | ||||
|     ExternalProject_Get_Property(dep_qhull BINARY_DIR) | ||||
|     ExternalProject_Add_Step(dep_qhull build_debug | ||||
|         DEPENDEES build | ||||
|         DEPENDERS install | ||||
|         COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj | ||||
|         WORKING_DIRECTORY "${BINARY_DIR}" | ||||
|     ) | ||||
| endif () | ||||
| 
 | ||||
| 
 | ||||
| if (${DEPS_BITS} EQUAL 32) | ||||
|     set(DEP_WXWIDGETS_TARGET "") | ||||
|  | @ -208,6 +270,51 @@ else () | |||
|     set(DEP_WXWIDGETS_LIBDIR "vc_x64_lib") | ||||
| endif () | ||||
| 
 | ||||
| find_package(Git REQUIRED) | ||||
| 
 | ||||
| ExternalProject_Add(dep_libigl | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/libigl/libigl/archive/v2.0.0.tar.gz" | ||||
|     URL_HASH SHA256=42518e6b106c7209c73435fd260ed5d34edeb254852495b4c95dce2d95401328 | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_ARGS | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         -DLIBIGL_BUILD_PYTHON=OFF | ||||
|         -DLIBIGL_BUILD_TESTS=OFF | ||||
|         -DLIBIGL_BUILD_TUTORIALS=OFF | ||||
|         -DLIBIGL_USE_STATIC_LIBRARY=OFF #${DEP_BUILD_IGL_STATIC} | ||||
|         -DLIBIGL_WITHOUT_COPYLEFT=OFF | ||||
|         -DLIBIGL_WITH_CGAL=OFF | ||||
|         -DLIBIGL_WITH_COMISO=OFF | ||||
|         -DLIBIGL_WITH_CORK=OFF | ||||
|         -DLIBIGL_WITH_EMBREE=OFF | ||||
|         -DLIBIGL_WITH_MATLAB=OFF | ||||
|         -DLIBIGL_WITH_MOSEK=OFF | ||||
|         -DLIBIGL_WITH_OPENGL=OFF | ||||
|         -DLIBIGL_WITH_OPENGL_GLFW=OFF | ||||
|         -DLIBIGL_WITH_OPENGL_GLFW_IMGUI=OFF | ||||
|         -DLIBIGL_WITH_PNG=OFF | ||||
|         -DLIBIGL_WITH_PYTHON=OFF | ||||
|         -DLIBIGL_WITH_TETGEN=OFF | ||||
|         -DLIBIGL_WITH_TRIANGLE=OFF | ||||
|         -DLIBIGL_WITH_XML=OFF | ||||
|         -DCMAKE_POSITION_INDEPENDENT_CODE=ON | ||||
|         -DCMAKE_DEBUG_POSTFIX=d | ||||
|     PATCH_COMMAND ${GIT_EXECUTABLE} apply --ignore-space-change --ignore-whitespace ${CMAKE_CURRENT_SOURCE_DIR}/igl-fixes.patch | ||||
|     BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj | ||||
|     INSTALL_COMMAND "" | ||||
| ) | ||||
| 
 | ||||
| if (${DEP_DEBUG}) | ||||
|     ExternalProject_Get_Property(dep_libigl BINARY_DIR) | ||||
|     ExternalProject_Add_Step(dep_libigl build_debug | ||||
|         DEPENDEES build | ||||
|         DEPENDERS install | ||||
|         COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj | ||||
|         WORKING_DIRECTORY "${BINARY_DIR}" | ||||
|     ) | ||||
| endif () | ||||
| 
 | ||||
| ExternalProject_Add(dep_wxwidgets | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" | ||||
|  |  | |||
							
								
								
									
										128
									
								
								deps/igl-fixes.patch
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,128 @@ | |||
| diff --git a/cmake/libigl-config.cmake.in b/cmake/libigl-config.cmake.in
 | ||||
| index 317c745c..f9808e1e 100644
 | ||||
| --- a/cmake/libigl-config.cmake.in
 | ||||
| +++ b/cmake/libigl-config.cmake.in
 | ||||
| @@ -2,28 +2,28 @@
 | ||||
|   | ||||
|  include(${CMAKE_CURRENT_LIST_DIR}/libigl-export.cmake) | ||||
|   | ||||
| -if (TARGET igl::core)
 | ||||
| -  if (NOT TARGET Eigen3::Eigen)
 | ||||
| -    find_package(Eigen3 QUIET)
 | ||||
| -    if (NOT Eigen3_FOUND)
 | ||||
| -      # try with PkgCOnfig
 | ||||
| -      find_package(PkgConfig REQUIRED)
 | ||||
| -      pkg_check_modules(Eigen3 QUIET IMPORTED_TARGET eigen3)
 | ||||
| -    endif()
 | ||||
| -
 | ||||
| -    if (NOT Eigen3_FOUND)
 | ||||
| -      message(FATAL_ERROR "Could not find required dependency Eigen3")
 | ||||
| -      set(libigl_core_FOUND FALSE)
 | ||||
| -    else()
 | ||||
| -      target_link_libraries(igl::core INTERFACE PkgConfig::Eigen3)
 | ||||
| -      set(libigl_core_FOUND TRUE)
 | ||||
| -    endif()
 | ||||
| -  else()
 | ||||
| -    target_link_libraries(igl::core INTERFACE Eigen3::Eigen)
 | ||||
| -    set(libigl_core_FOUND TRUE)
 | ||||
| -  endif()
 | ||||
| -
 | ||||
| -endif()
 | ||||
| +# if (TARGET igl::core)
 | ||||
| +#   if (NOT TARGET Eigen3::Eigen)
 | ||||
| +#     find_package(Eigen3 QUIET)
 | ||||
| +#     if (NOT Eigen3_FOUND)
 | ||||
| +#       # try with PkgCOnfig
 | ||||
| +#       find_package(PkgConfig REQUIRED)
 | ||||
| +#       pkg_check_modules(Eigen3 QUIET IMPORTED_TARGET eigen3)
 | ||||
| +#     endif()
 | ||||
| +#
 | ||||
| +#     if (NOT Eigen3_FOUND)
 | ||||
| +#       message(FATAL_ERROR "Could not find required dependency Eigen3")
 | ||||
| +#       set(libigl_core_FOUND FALSE)
 | ||||
| +#     else()
 | ||||
| +#       target_link_libraries(igl::core INTERFACE PkgConfig::Eigen3)
 | ||||
| +#       set(libigl_core_FOUND TRUE)
 | ||||
| +#     endif()
 | ||||
| +#   else()
 | ||||
| +#     target_link_libraries(igl::core INTERFACE Eigen3::Eigen)
 | ||||
| +#     set(libigl_core_FOUND TRUE)
 | ||||
| +#   endif()
 | ||||
| +#
 | ||||
| +# endif()
 | ||||
|   | ||||
|  check_required_components(libigl) | ||||
|   | ||||
| diff --git a/cmake/libigl.cmake b/cmake/libigl.cmake
 | ||||
| index 4b11007a..47e6c395 100644
 | ||||
| --- a/cmake/libigl.cmake
 | ||||
| +++ b/cmake/libigl.cmake
 | ||||
| @@ -445,6 +445,7 @@ function(install_dir_files dir_name)
 | ||||
|    if(NOT LIBIGL_USE_STATIC_LIBRARY) | ||||
|      file(GLOB public_sources | ||||
|        ${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.cpp | ||||
| +      ${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.c
 | ||||
|      ) | ||||
|    endif() | ||||
|    list(APPEND files_to_install ${public_sources}) | ||||
| diff --git a/include/igl/AABB.cpp b/include/igl/AABB.cpp
 | ||||
| index 09537335..92e90cb7 100644
 | ||||
| --- a/include/igl/AABB.cpp
 | ||||
| +++ b/include/igl/AABB.cpp
 | ||||
| @@ -1071,5 +1071,11 @@ template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::init<Eigen
 | ||||
|  // generated by autoexplicit.sh | ||||
|  template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::init<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&); | ||||
|  template double igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, double, int&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&) const; | ||||
| +template float igl::AABB<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >, 3>::squared_distance<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > >(Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::Matrix<float, 1, 3, 1, 1, 3> const&, int&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&) const;
 | ||||
|  template bool igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::intersect_ray<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, igl::Hit&) const; | ||||
| +template bool igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::intersect_ray<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, std::vector<igl::Hit>&) const;
 | ||||
| +
 | ||||
| +template void igl::AABB<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >, 3>::init<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > >(Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&);
 | ||||
| +
 | ||||
| +template bool igl::AABB<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >, 3>::intersect_ray<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > >(Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::Matrix<float, 1, 3, 1, 1, 3> const&, Eigen::Matrix<float, 1, 3, 1, 1, 3> const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&) const;
 | ||||
|  #endif | ||||
| diff --git a/include/igl/barycenter.cpp b/include/igl/barycenter.cpp
 | ||||
| index 065f82aa..ec2d96cd 100644
 | ||||
| --- a/include/igl/barycenter.cpp
 | ||||
| +++ b/include/igl/barycenter.cpp
 | ||||
| @@ -54,4 +54,6 @@ template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::M
 | ||||
|  template void igl::barycenter<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&); | ||||
|  template void igl::barycenter<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&); | ||||
|  template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&); | ||||
| +
 | ||||
| +template void igl::barycenter<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >, Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);
 | ||||
|  #endif | ||||
| diff --git a/include/igl/point_simplex_squared_distance.cpp b/include/igl/point_simplex_squared_distance.cpp
 | ||||
| index 2b98bd28..c66d9ae1 100644
 | ||||
| --- a/include/igl/point_simplex_squared_distance.cpp
 | ||||
| +++ b/include/igl/point_simplex_squared_distance.cpp
 | ||||
| @@ -178,4 +178,6 @@ template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3,
 | ||||
|  template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 1, 1, 3> >&); | ||||
|  template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&); | ||||
|  template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 1, 1, 2> >&); | ||||
| +
 | ||||
| +template void igl::point_simplex_squared_distance<3, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >, Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >::Index, float&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
 | ||||
|  #endif | ||||
| diff --git a/include/igl/ray_box_intersect.cpp b/include/igl/ray_box_intersect.cpp
 | ||||
| index 4a88b89e..b547f8f8 100644
 | ||||
| --- a/include/igl/ray_box_intersect.cpp
 | ||||
| +++ b/include/igl/ray_box_intersect.cpp
 | ||||
| @@ -147,4 +147,6 @@ IGL_INLINE bool igl::ray_box_intersect(
 | ||||
|  #ifdef IGL_STATIC_LIBRARY | ||||
|  // Explicit template instantiation | ||||
|  template bool igl::ray_box_intersect<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::AlignedBox<double, 3> const&, double const&, double const&, double&, double&); | ||||
| +
 | ||||
| +template bool igl::ray_box_intersect<Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, float>(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::AlignedBox<float, 3> const&, float const&, float const&, float&, float&);
 | ||||
|  #endif | ||||
| diff --git a/include/igl/ray_mesh_intersect.cpp b/include/igl/ray_mesh_intersect.cpp
 | ||||
| index 9a70a22b..4233e722 100644
 | ||||
| --- a/include/igl/ray_mesh_intersect.cpp
 | ||||
| +++ b/include/igl/ray_mesh_intersect.cpp
 | ||||
| @@ -83,4 +83,7 @@ IGL_INLINE bool igl::ray_mesh_intersect(
 | ||||
|  template bool igl::ray_mesh_intersect<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&); | ||||
|  template bool igl::ray_mesh_intersect<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::Hit&); | ||||
|  template bool igl::ray_mesh_intersect<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, 1, -1, false> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, igl::Hit&); | ||||
| +template bool igl::ray_mesh_intersect<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, 1, -1, false> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&);
 | ||||
| +
 | ||||
| +template bool igl::ray_mesh_intersect<Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> >, Eigen::Block<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1, -1, true> >(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<float, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Map<Eigen::Matrix<int, -1, -1, 3, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1, -1, true> > const&, std::vector<igl::Hit, std::allocator<igl::Hit> >&);
 | ||||
|  #endif | ||||
							
								
								
									
										121
									
								
								deps/qhull-mods.patch
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,121 @@ | |||
| From a31ae4781a4afa60e21c70e5b4ae784bcd447c8a Mon Sep 17 00:00:00 2001 | ||||
| From: tamasmeszaros <meszaros.q@gmail.com> | ||||
| Date: Thu, 6 Jun 2019 15:41:43 +0200 | ||||
| Subject: [PATCH] prusa-slicer changes | ||||
| 
 | ||||
| ---
 | ||||
|  CMakeLists.txt                     | 44 +++++++++++++++++++++++++++++++++++--- | ||||
|  Config.cmake.in                    |  2 ++ | ||||
|  src/libqhull_r/qhull_r-exports.def |  2 ++ | ||||
|  src/libqhull_r/user_r.h            |  2 +- | ||||
|  4 files changed, 46 insertions(+), 4 deletions(-) | ||||
|  create mode 100644 Config.cmake.in | ||||
| 
 | ||||
| diff --git a/CMakeLists.txt b/CMakeLists.txt
 | ||||
| index 59dff41..20c2ec5 100644
 | ||||
| --- a/CMakeLists.txt
 | ||||
| +++ b/CMakeLists.txt
 | ||||
| @@ -61,7 +61,7 @@
 | ||||
|  # $DateTime: 2016/01/18 19:29:17 $$Author: bbarber $ | ||||
|   | ||||
|  project(qhull) | ||||
| -cmake_minimum_required(VERSION 2.6)
 | ||||
| +cmake_minimum_required(VERSION 3.0)
 | ||||
|   | ||||
|  # Define qhull_VERSION in CMakeLists.txt, Makefile, qhull-exports.def, qhull_p-exports.def, qhull_r-exports.def, qhull-warn.pri | ||||
|  set(qhull_VERSION2 "2015.2 2016/01/18")  # not used, See global.c, global_r.c, rbox.c, rbox_r.c | ||||
| @@ -610,10 +610,48 @@ add_test(NAME user_eg3
 | ||||
|  # Define install | ||||
|  # --------------------------------------- | ||||
|   | ||||
| -install(TARGETS ${qhull_TARGETS_INSTALL}
 | ||||
| +install(TARGETS ${qhull_TARGETS_INSTALL} EXPORT QhullTargets
 | ||||
|          RUNTIME DESTINATION ${BIN_INSTALL_DIR} | ||||
|          LIBRARY DESTINATION ${LIB_INSTALL_DIR} | ||||
| -        ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
 | ||||
| +        ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
 | ||||
| +        INCLUDES DESTINATION include)
 | ||||
| +
 | ||||
| +include(CMakePackageConfigHelpers)
 | ||||
| +
 | ||||
| +write_basic_package_version_file(
 | ||||
| +    "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullConfigVersion.cmake"
 | ||||
| +    VERSION ${qhull_VERSION}
 | ||||
| +    COMPATIBILITY AnyNewerVersion
 | ||||
| +)
 | ||||
| +
 | ||||
| +export(EXPORT QhullTargets
 | ||||
| +  FILE "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullTargets.cmake"
 | ||||
| +  NAMESPACE Qhull::
 | ||||
| +)
 | ||||
| +
 | ||||
| +configure_file(Config.cmake.in
 | ||||
| +  "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullConfig.cmake"
 | ||||
| +  @ONLY
 | ||||
| +)
 | ||||
| +
 | ||||
| +set(ConfigPackageLocation lib/cmake/Qhull)
 | ||||
| +install(EXPORT QhullTargets
 | ||||
| +  FILE
 | ||||
| +    QhullTargets.cmake
 | ||||
| +  NAMESPACE
 | ||||
| +    Qhull::
 | ||||
| +  DESTINATION
 | ||||
| +    ${ConfigPackageLocation}
 | ||||
| +)
 | ||||
| +install(
 | ||||
| +  FILES
 | ||||
| +    "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullConfig.cmake"
 | ||||
| +    "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullConfigVersion.cmake"
 | ||||
| +  DESTINATION
 | ||||
| +    ${ConfigPackageLocation}
 | ||||
| +  COMPONENT
 | ||||
| +    Devel
 | ||||
| +)
 | ||||
|   | ||||
|  install(FILES ${libqhull_HEADERS}    DESTINATION ${INCLUDE_INSTALL_DIR}/libqhull) | ||||
|  install(FILES ${libqhull_DOC}        DESTINATION ${INCLUDE_INSTALL_DIR}/libqhull) | ||||
| diff --git a/Config.cmake.in b/Config.cmake.in
 | ||||
| new file mode 100644 | ||||
| index 0000000..bc92bfe
 | ||||
| --- /dev/null
 | ||||
| +++ b/Config.cmake.in
 | ||||
| @@ -0,0 +1,2 @@
 | ||||
| +include("${CMAKE_CURRENT_LIST_DIR}/QhullTargets.cmake")
 | ||||
| +
 | ||||
| diff --git a/src/libqhull_r/qhull_r-exports.def b/src/libqhull_r/qhull_r-exports.def
 | ||||
| index 325d57c..72f6ad0 100644
 | ||||
| --- a/src/libqhull_r/qhull_r-exports.def
 | ||||
| +++ b/src/libqhull_r/qhull_r-exports.def
 | ||||
| @@ -185,6 +185,7 @@ qh_memsetup
 | ||||
|  qh_memsize | ||||
|  qh_memstatistics | ||||
|  qh_memtotal | ||||
| +qh_memcheck
 | ||||
|  qh_merge_degenredundant | ||||
|  qh_merge_nonconvex | ||||
|  qh_mergecycle | ||||
| @@ -372,6 +373,7 @@ qh_settruncate
 | ||||
|  qh_setunique | ||||
|  qh_setvoronoi_all | ||||
|  qh_setzero | ||||
| +qh_setendpointer
 | ||||
|  qh_sharpnewfacets | ||||
|  qh_skipfacet | ||||
|  qh_skipfilename | ||||
| diff --git a/src/libqhull_r/user_r.h b/src/libqhull_r/user_r.h
 | ||||
| index fc105b9..7cca65a 100644
 | ||||
| --- a/src/libqhull_r/user_r.h
 | ||||
| +++ b/src/libqhull_r/user_r.h
 | ||||
| @@ -139,7 +139,7 @@ Code flags --
 | ||||
|     REALfloat =   1      all numbers are 'float' type | ||||
|               =   0      all numbers are 'double' type | ||||
|  */ | ||||
| -#define REALfloat 0
 | ||||
| +#define REALfloat 1
 | ||||
|   | ||||
|  #if (REALfloat == 1) | ||||
|  #define realT float | ||||
| -- 
 | ||||
| 2.16.2.windows.1 | ||||
| 
 | ||||
|  | @ -1,7 +1,15 @@ | |||
| 
 | ||||
| # Building PrusaSlicer on Mac OS | ||||
| 
 | ||||
| To build PrusaSlicer on Mac OS, you will need to install XCode, [CMake](https://cmake.org/) (available on Brew) and possibly git. | ||||
| To build PrusaSlicer on Mac OS, you will need the following software: | ||||
| 
 | ||||
| - XCode | ||||
| - CMake | ||||
| - git | ||||
| - gettext | ||||
| 
 | ||||
| XCode is available through Apple's App Store, the other three tools are available on | ||||
| [brew](https://brew.sh/) (use `brew install cmake git gettext` to install them). | ||||
| 
 | ||||
| ### Dependencies | ||||
| 
 | ||||
|  | @ -20,6 +28,9 @@ You can also customize the bundle output path using the `-DDESTDIR=<some path>` | |||
| **Warning**: Once the dependency bundle is installed in a destdir, the destdir cannot be moved elsewhere. | ||||
| (This is because wxWidgets hardcodes the installation path.) | ||||
| 
 | ||||
| FIXME The Cereal serialization library needs a tiny patch on some old OSX clang installations | ||||
| https://github.com/USCiLab/cereal/issues/339#issuecomment-246166717 | ||||
| 
 | ||||
| 
 | ||||
| ### Building PrusaSlicer | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,24 +1,37 @@ | |||
| 
 | ||||
| # This how-to is out of date | ||||
| 
 | ||||
| We have switched to MS Visual Studio 2019. | ||||
| 
 | ||||
| We don't use MSVS 2013 any more. At the moment we are in the process of creating new pre-built dependency bundles | ||||
| and updating this document. In the meantime, you will need to compile the dependencies yourself | ||||
| [the same way as before](#building-the-dependencies-package-yourself) | ||||
| except with CMake generators for MSVS 2019 instead of 2013. | ||||
| 
 | ||||
| Thank you for understanding. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| # Building PrusaSlicer on Microsoft Windows | ||||
| 
 | ||||
| The currently supported way of building PrusaSlicer on Windows is with CMake and MS Visual Studio 2013. | ||||
| ~~The currently supported way of building PrusaSlicer on Windows is with CMake and MS Visual Studio 2013. | ||||
| You can use the free [Visual Studio 2013 Community Edition](https://www.visualstudio.com/vs/older-downloads/). | ||||
| CMake installer can be downloaded from [the official website](https://cmake.org/download/). | ||||
| CMake installer can be downloaded from [the official website](https://cmake.org/download/).~~ | ||||
| 
 | ||||
| Building with newer versions of MSVS (2015, 2017) may work too as reported by some of our users. | ||||
| ~~Building with newer versions of MSVS (2015, 2017) may work too as reported by some of our users.~~ | ||||
| 
 | ||||
| _Note:_ Thanks to [**@supermerill**](https://github.com/supermerill) for testing and inspiration for this guide. | ||||
| 
 | ||||
| ### Dependencies | ||||
| 
 | ||||
| On Windows PrusaSlicer is built against statically built libraries. | ||||
| We provide a prebuilt package of all the needed dependencies. This package only works on Visual Studio 2013, so if you are using a newer version of Visual Studio, you need to compile the dependencies yourself as per [below](#building-the-dependencies-package-yourself). | ||||
| ~~We provide a prebuilt package of all the needed dependencies. This package only works on Visual Studio 2013, so~~ if you are using a newer version of Visual Studio, you need to compile the dependencies yourself as per [below](#building-the-dependencies-package-yourself). | ||||
| The package comes in a several variants: | ||||
| 
 | ||||
|   - [64 bit, Release mode only](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-64.7z) (41 MB, 578 MB unpacked) | ||||
|   - [64 bit, Release and Debug mode](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-64-dev.7z) (88 MB, 1.3 GB unpacked) | ||||
|   - [32 bit, Release mode only](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-32.7z) (38 MB, 520 MB unpacked) | ||||
|   - [32 bit, Release and Debug mode](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-32-dev.7z) (74 MB, 1.1 GB unpacked) | ||||
|   - ~~64 bit, Release mode only (41 MB, 578 MB unpacked)~~ | ||||
|   - ~~64 bit, Release and Debug mode (88 MB, 1.3 GB unpacked)~~ | ||||
|   - ~~32 bit, Release mode only (38 MB, 520 MB unpacked)~~ | ||||
|   - ~~32 bit, Release and Debug mode (74 MB, 1.1 GB unpacked)~~ | ||||
| 
 | ||||
| When unsure, use the _Release mode only_ variant, the _Release and Debug_ variant is only needed for debugging & development. | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,7 +50,6 @@ use Slic3r::Point; | |||
| use Slic3r::Polygon; | ||||
| use Slic3r::Polyline; | ||||
| use Slic3r::Print::Object; | ||||
| use Slic3r::Print::Simple; | ||||
| use Slic3r::Surface; | ||||
| our $build = eval "use Slic3r::Build; 1"; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,104 +0,0 @@ | |||
| # A simple wrapper to quickly print a single model without a GUI. | ||||
| # Used by the command line slic3r.pl, by command line utilities pdf-slic3s.pl and view-toolpaths.pl, | ||||
| # and by the quick slice menu of the Slic3r GUI. | ||||
| # | ||||
| # It creates and owns an instance of Slic3r::Print  to perform the slicing | ||||
| # and it accepts an instance of Slic3r::Model from the outside. | ||||
| 
 | ||||
| package Slic3r::Print::Simple; | ||||
| use Moo; | ||||
| 
 | ||||
| use Slic3r::Geometry qw(X Y); | ||||
| 
 | ||||
| has '_print' => ( | ||||
|     is      => 'ro', | ||||
|     default => sub { Slic3r::Print->new }, | ||||
|     handles => [qw(apply_config_perl_tests_only extruders output_filepath | ||||
|                     total_used_filament total_extruded_volume | ||||
|                     placeholder_parser process)], | ||||
| ); | ||||
| 
 | ||||
| has 'duplicate' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { 1 }, | ||||
| ); | ||||
| 
 | ||||
| has 'scale' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { 1 }, | ||||
| ); | ||||
| 
 | ||||
| has 'rotate' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { 0 }, | ||||
| ); | ||||
| 
 | ||||
| has 'duplicate_grid' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { [1,1] }, | ||||
| ); | ||||
| 
 | ||||
| has 'print_center' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { Slic3r::Pointf->new(100,100) }, | ||||
| ); | ||||
| 
 | ||||
| has 'dont_arrange' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { 0 }, | ||||
| ); | ||||
| 
 | ||||
| has 'output_file' => ( | ||||
|     is      => 'rw', | ||||
| ); | ||||
| 
 | ||||
| sub set_model { | ||||
|     # $model is of type Slic3r::Model | ||||
|     my ($self, $model) = @_; | ||||
|      | ||||
|     # make method idempotent so that the object is reusable | ||||
|     $self->_print->clear_objects; | ||||
|      | ||||
|     # make sure all objects have at least one defined instance | ||||
|     my $need_arrange = $model->add_default_instances && ! $self->dont_arrange; | ||||
|      | ||||
|     # apply scaling and rotation supplied from command line if any | ||||
|     foreach my $instance (map @{$_->instances}, @{$model->objects}) { | ||||
|         $instance->set_scaling_factor($instance->scaling_factor * $self->scale); | ||||
|         $instance->set_rotation($instance->rotation + $self->rotate); | ||||
|     } | ||||
|      | ||||
|     if ($self->duplicate_grid->[X] > 1 || $self->duplicate_grid->[Y] > 1) { | ||||
|         $model->duplicate_objects_grid($self->duplicate_grid->[X], $self->duplicate_grid->[Y], $self->_print->config->duplicate_distance); | ||||
|     } elsif ($need_arrange) { | ||||
|         $model->duplicate_objects($self->duplicate, $self->_print->config->min_object_distance); | ||||
|     } elsif ($self->duplicate > 1) { | ||||
|         # if all input objects have defined position(s) apply duplication to the whole model | ||||
|         $model->duplicate($self->duplicate, $self->_print->config->min_object_distance); | ||||
|     } | ||||
|     $_->translate(0,0,-$_->bounding_box->z_min) for @{$model->objects}; | ||||
|     $model->center_instances_around_point($self->print_center) if (! $self->dont_arrange); | ||||
|      | ||||
|     foreach my $model_object (@{$model->objects}) { | ||||
|         $self->_print->auto_assign_extruders($model_object); | ||||
|         $self->_print->add_model_object($model_object); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| sub export_gcode { | ||||
|     my ($self) = @_; | ||||
|     $self->_print->validate; | ||||
|     $self->_print->export_gcode($self->output_file // ''); | ||||
| } | ||||
| 
 | ||||
| sub export_png { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     $self->_before_export; | ||||
|      | ||||
|     $self->_print->export_png(output_file => $self->output_file); | ||||
|      | ||||
|     $self->_after_export; | ||||
| } | ||||
| 
 | ||||
| 1; | ||||
|  | @ -146,60 +146,66 @@ sub mesh { | |||
| } | ||||
| 
 | ||||
| sub model { | ||||
|     my ($model_name, %params) = @_; | ||||
|     my ($model_names, %params) = @_; | ||||
|     $model_names = [ $model_names ] if ! ref($model_names); | ||||
| 
 | ||||
|     my $input_file = "${model_name}.stl"; | ||||
|     my $mesh = mesh($model_name, %params); | ||||
| #    $mesh->write_ascii("out/$input_file"); | ||||
|      | ||||
|     my $model = Slic3r::Model->new; | ||||
|     my $object = $model->add_object(input_file => $input_file); | ||||
|     $model->set_material($model_name); | ||||
|     $object->add_volume(mesh => $mesh, material_id => $model_name); | ||||
|     $object->add_instance( | ||||
|         offset          => Slic3r::Pointf->new(0,0), | ||||
|         # 3D full transform | ||||
|         rotation        => Slic3r::Pointf3->new(0, 0, $params{rotation} // 0), | ||||
|         scaling_factor  => Slic3r::Pointf3->new($params{scale} // 1, $params{scale} // 1, $params{scale} // 1), | ||||
|         # old transform | ||||
| #        rotation        => $params{rotation} // 0, | ||||
| #        scaling_factor  => $params{scale} // 1, | ||||
|     ); | ||||
| 
 | ||||
|     for my $model_name (@$model_names) { | ||||
|         my $input_file = "${model_name}.stl"; | ||||
|         my $mesh = mesh($model_name, %params); | ||||
|     #    $mesh->write_ascii("out/$input_file"); | ||||
|          | ||||
|         my $object = $model->add_object(input_file => $input_file); | ||||
|         $model->set_material($model_name); | ||||
|         $object->add_volume(mesh => $mesh, material_id => $model_name); | ||||
|         $object->add_instance( | ||||
|             offset          => Slic3r::Pointf->new(0,0), | ||||
|             # 3D full transform | ||||
|             rotation        => Slic3r::Pointf3->new(0, 0, $params{rotation} // 0), | ||||
|             scaling_factor  => Slic3r::Pointf3->new($params{scale} // 1, $params{scale} // 1, $params{scale} // 1), | ||||
|             # old transform | ||||
|     #        rotation        => $params{rotation} // 0, | ||||
|     #        scaling_factor  => $params{scale} // 1, | ||||
|         ); | ||||
|     } | ||||
|     return $model; | ||||
| } | ||||
| 
 | ||||
| sub init_print { | ||||
|     my ($models, %params) = @_; | ||||
|     my $model; | ||||
|     if (ref($models) eq 'ARRAY') { | ||||
|         $model = model($models, %params); | ||||
|     } elsif (ref($models)) { | ||||
|         $model = $models; | ||||
|     } else { | ||||
|         $model = model([$models], %params); | ||||
|     } | ||||
|      | ||||
|     my $config = Slic3r::Config->new; | ||||
|     $config->apply($params{config}) if $params{config}; | ||||
|     $config->set('gcode_comments', 1) if $ENV{SLIC3R_TESTS_GCODE}; | ||||
|      | ||||
|     my $print = Slic3r::Print->new; | ||||
|     $print->apply_config_perl_tests_only($config); | ||||
|      | ||||
|     $models = [$models] if ref($models) ne 'ARRAY'; | ||||
|     $models = [ map { ref($_) ? $_ : model($_, %params) } @$models ]; | ||||
|     for my $model (@$models) { | ||||
|         die "Unknown model in test" if !defined $model; | ||||
|         if (defined $params{duplicate} && $params{duplicate} > 1) { | ||||
|             $model->duplicate($params{duplicate} // 1, $print->config->min_object_distance); | ||||
|         } | ||||
|         $model->arrange_objects($print->config->min_object_distance); | ||||
|         $model->center_instances_around_point($params{print_center} ? Slic3r::Pointf->new(@{$params{print_center}}) : Slic3r::Pointf->new(100,100)); | ||||
|         foreach my $model_object (@{$model->objects}) { | ||||
|             $print->auto_assign_extruders($model_object); | ||||
|             $print->add_model_object($model_object); | ||||
|         } | ||||
|     die "Unknown model in test" if !defined $model; | ||||
|     if (defined $params{duplicate} && $params{duplicate} > 1) { | ||||
|         $model->duplicate($params{duplicate} // 1, $config->min_object_distance); | ||||
|     } | ||||
|     # Call apply_config_perl_tests_only one more time, so that the layer height profiles are updated over all PrintObjects. | ||||
|     $print->apply_config_perl_tests_only($config); | ||||
|     $model->arrange_objects($config->min_object_distance); | ||||
|     $model->center_instances_around_point($params{print_center} ? Slic3r::Pointf->new(@{$params{print_center}}) : Slic3r::Pointf->new(100,100)); | ||||
|     foreach my $model_object (@{$model->objects}) { | ||||
|         $model_object->ensure_on_bed; | ||||
|         $print->auto_assign_extruders($model_object); | ||||
|     } | ||||
| 
 | ||||
|     $print->apply($model, $config); | ||||
|     $print->validate; | ||||
|      | ||||
|     # We return a proxy object in order to keep $models alive as required by the Print API. | ||||
|     return Slic3r::Test::Print->new( | ||||
|         print   => $print, | ||||
|         models  => $models, | ||||
|         print  => $print, | ||||
|         model  => $model, | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
|  | @ -250,7 +256,7 @@ sub add_facet { | |||
| package Slic3r::Test::Print; | ||||
| use Moo; | ||||
| 
 | ||||
| has 'print'     => (is => 'ro', required => 1, handles => [qw(process apply_config_perl_tests_only)]); | ||||
| has 'models'    => (is => 'ro', required => 1); | ||||
| has 'print'     => (is => 'ro', required => 1, handles => [qw(process apply)]); | ||||
| has 'model'     => (is => 'ro', required => 1); | ||||
| 
 | ||||
| 1; | ||||
|  |  | |||
							
								
								
									
										15
									
								
								resources/icons/cross_focus.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="cross"> | ||||
| 	<g> | ||||
| 		 | ||||
| 			<line fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" x1="14" y1="2" x2="2" y2="14"/> | ||||
| 	</g> | ||||
| 	<g> | ||||
| 		 | ||||
| 			<line fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="2" x2="14" y2="14"/> | ||||
| 	</g> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 659 B | 
							
								
								
									
										15
									
								
								resources/icons/drop_to_bed.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,15 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="modifer_x5F_bed"> | ||||
| 	 | ||||
| 		<line fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="2" y1="13" x2="13" y2="13"/> | ||||
| 	<path fill="#808080" d="M10.87,7.48c-0.2,0-0.37,0.16-0.37,0.37v1.47v0.74c0,0.2-0.17,0.37-0.37,0.37H4.97 | ||||
| 		c-0.2,0-0.37-0.17-0.37-0.37L4.57,4.91c0-0.1,0.04-0.19,0.11-0.26c0.07-0.07,0.16-0.11,0.26-0.11l2.25,0v0 | ||||
| 		c0.2,0,0.37-0.16,0.37-0.37c0-0.2-0.16-0.37-0.37-0.37H5.71c0,0-0.01,0-0.01,0l-0.76,0c-0.3,0-0.57,0.12-0.78,0.33 | ||||
| 		C3.95,4.34,3.83,4.61,3.83,4.91l0.03,5.15c0,0.61,0.5,1.1,1.11,1.1h5.16c0.61,0,1.11-0.5,1.11-1.11V9.32V7.85 | ||||
| 		C11.24,7.65,11.07,7.48,10.87,7.48z"/> | ||||
| 	<circle fill="#808080" stroke="#808080" stroke-miterlimit="10" cx="10.88" cy="4.12" r="2.12"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										25
									
								
								resources/icons/edit_layers_all.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,25 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="edit_x5F_layers_x5F_all"> | ||||
| 	<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="2" x2="6" y2="2"/> | ||||
| 	<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="6" x2="6" y2="6"/> | ||||
| 	 | ||||
| 		<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="10" x2="14" y2="10"/> | ||||
| 	 | ||||
| 		<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="14" x2="14" y2="14"/> | ||||
| 	<path fill="#ED6B21" d="M14.62,4.37c-0.01-0.14,0.06-0.34,0.15-0.44l0.13-0.15c0.09-0.11,0.12-0.3,0.07-0.43l-0.2-0.49 | ||||
| 		c-0.05-0.13-0.21-0.24-0.35-0.25l-0.2-0.01c-0.14-0.01-0.33-0.1-0.42-0.21c-0.09-0.1-0.37-0.46-0.38-0.6l-0.01-0.2 | ||||
| 		c-0.01-0.14-0.12-0.3-0.25-0.35l-0.49-0.2C12.52,0.97,12.33,1,12.22,1.1l-0.15,0.13c-0.11,0.09-0.31,0.16-0.44,0.15 | ||||
| 		c-0.14-0.01-0.59-0.06-0.69-0.15L10.78,1.1c-0.11-0.09-0.3-0.12-0.43-0.07l-0.49,0.2C9.73,1.28,9.61,1.44,9.6,1.58l-0.01,0.2 | ||||
| 		C9.58,1.92,9.49,2.11,9.38,2.2c-0.1,0.09-0.46,0.37-0.6,0.38L8.58,2.6c-0.14,0.01-0.3,0.12-0.35,0.25l-0.2,0.49 | ||||
| 		C7.97,3.48,8,3.67,8.1,3.78l0.13,0.15c0.09,0.11,0.16,0.31,0.15,0.44C8.37,4.52,8.32,4.96,8.23,5.07L8.1,5.22 | ||||
| 		C8,5.33,7.97,5.52,8.03,5.65l0.2,0.49C8.28,6.27,8.44,6.39,8.58,6.4l0.2,0.01c0.14,0.01,0.33,0.1,0.42,0.21 | ||||
| 		c0.09,0.1,0.37,0.46,0.38,0.6l0.01,0.2c0.01,0.14,0.12,0.3,0.25,0.35l0.49,0.2C10.48,8.03,10.67,8,10.78,7.9l0.15-0.13 | ||||
| 		c0.11-0.09,0.31-0.16,0.44-0.15c0.14,0.01,0.59,0.06,0.69,0.15l0.15,0.13c0.11,0.09,0.3,0.12,0.43,0.07l0.49-0.2 | ||||
| 		c0.13-0.05,0.24-0.21,0.25-0.35l0.01-0.2c0.01-0.14,0.1-0.33,0.21-0.42s0.46-0.37,0.6-0.38l0.2-0.01c0.14-0.01,0.3-0.12,0.35-0.25 | ||||
| 		l0.2-0.49C15.03,5.52,15,5.33,14.9,5.22l-0.13-0.15C14.68,4.96,14.63,4.51,14.62,4.37z M11.5,6.6c-1.16,0-2.1-0.94-2.1-2.1 | ||||
| 		s0.94-2.1,2.1-2.1s2.1,0.94,2.1,2.1S12.66,6.6,11.5,6.6z"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.2 KiB | 
							
								
								
									
										14
									
								
								resources/icons/edit_layers_some.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,14 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="edit_x5F_layers_x5F_some_1_"> | ||||
| 	 | ||||
| 		<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="11" x2="14" y2="11"/> | ||||
| 	 | ||||
| 		<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="14" x2="14" y2="14"/> | ||||
| 	<path fill="#ED6B21" d="M7.68,8.87c0.18,0.18,0.47,0.18,0.64,0L11.19,6c0.18-0.18,0.12-0.32-0.13-0.32H9.62 | ||||
| 		c-0.25,0-0.45-0.2-0.45-0.45V1.45C9.17,1.2,8.97,1,8.71,1H7.29C7.03,1,6.83,1.2,6.83,1.45v3.77c0,0.25-0.2,0.45-0.45,0.45H4.95 | ||||
| 		C4.7,5.68,4.64,5.82,4.81,6L7.68,8.87z"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 931 B | 
							
								
								
									
										13
									
								
								resources/icons/eye_closed.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,13 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="eye_x5F_close"> | ||||
| 	<path fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" | ||||
| 		M2,8c0,0,2,4,6,4s6-4,6-4s-2-4-6-4S2,8,2,8z"/> | ||||
| 	 | ||||
| 		<circle fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" cx="8" cy="8" r="1"/> | ||||
| 	 | ||||
| 		<line fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="2" y1="14" x2="14" y2="2"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 856 B | 
							
								
								
									
										11
									
								
								resources/icons/eye_open.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,11 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="eye_x5F_open"> | ||||
| 	<path fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" | ||||
| 		M2,8c0,0,2,4,6,4s6-4,6-4s-2-4-6-4S2,8,2,8z"/> | ||||
| 	 | ||||
| 		<circle fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" cx="8" cy="8" r="1"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 697 B | 
							
								
								
									
										10
									
								
								resources/icons/lock_closed_f.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,10 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="lock_x5F_closed"> | ||||
| 	<path fill="none" stroke="#808080" stroke-width="3" stroke-miterlimit="9" d="M4,8V4c0,0,0-2,2-2c1,0,3,0,4,0c2,0,2,2,2,2v4"/> | ||||
| 	<path fill="#808080" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91 | ||||
| 		c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 728 B | 
							
								
								
									
										11
									
								
								resources/icons/lock_open_f.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,11 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="lock_x5F_open"> | ||||
| 	<path fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" d="M4,8V4c0,0,0-2,2-2 | ||||
| 		c1,0,3,0,4,0c2,0,2,2,2,2v1"/> | ||||
| 	<path fill="#ED6B21" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91 | ||||
| 		c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 753 B | 
							
								
								
									
										23
									
								
								resources/icons/mirroring_off.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,23 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="mirror_x5F_off"> | ||||
| 	<g> | ||||
| 		<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" | ||||
| 			M10,3.01l3,0c0.55,0,1,0.45,1,1v8c0,0.55-0.45,1-1,1h-3"/> | ||||
| 	</g> | ||||
| 	<g> | ||||
| 		<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" | ||||
| 			M6,3.01L3,3C2.45,3,2,3.45,2,4v8c0,0.55,0.45,1,1,1h3"/> | ||||
| 	</g> | ||||
| 	<g> | ||||
| 		<g> | ||||
| 			<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/> | ||||
| 			 | ||||
| 				<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/> | ||||
| 			<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/> | ||||
| 		</g> | ||||
| 	</g> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										23
									
								
								resources/icons/mirroring_on.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,23 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="mirror_x5F_on"> | ||||
| 	<g> | ||||
| 		<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M10,3.01l3,0 | ||||
| 			c0.55,0,1,0.45,1,1v8c0,0.55-0.45,1-1,1h-3"/> | ||||
| 	</g> | ||||
| 	<g> | ||||
| 		<path fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M6,3.01L3,3 | ||||
| 			C2.45,3,2,3.45,2,4v8c0,0.55,0.45,1,1,1h3"/> | ||||
| 	</g> | ||||
| 	<g> | ||||
| 		<g> | ||||
| 			<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="1" x2="8" y2="3.5"/> | ||||
| 			 | ||||
| 				<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" stroke-dasharray="3,3" x1="8" y1="6.5" x2="8" y2="11"/> | ||||
| 			<line fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12.5" x2="8" y2="15"/> | ||||
| 		</g> | ||||
| 	</g> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/mirroring_transparent.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 93 B | 
							
								
								
									
										12
									
								
								resources/icons/redo.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="redo"> | ||||
| 	<path fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M13.39,11 | ||||
| 		c-0.91,1.78-2.76,3-4.89,3C5.46,14,3,11.54,3,8.5C3,5.46,5.46,3,8.5,3C8.67,3,8.84,3.01,9,3.03"/> | ||||
| 	 | ||||
| 		<polygon fill="#ED6B21" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points=" | ||||
| 		9,1 9,5 12,3 	"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 734 B | 
							
								
								
									
										12
									
								
								resources/icons/redo_toolbar.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="redo"> | ||||
| 	<path fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" d="M13.39,11 | ||||
| 		c-0.91,1.78-2.76,3-4.89,3C5.46,14,3,11.54,3,8.5C3,5.46,5.46,3,8.5,3C8.67,3,8.84,3.01,9,3.03"/> | ||||
| 	 | ||||
| 		<polygon fill="#ED6B21" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points=" | ||||
| 		9,1 9,5 12,3 	"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 734 B | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/row.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/table.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 465 B | 
							
								
								
									
										12
									
								
								resources/icons/undo_toolbar.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="undo"> | ||||
| 	<path fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" d="M3,11 | ||||
| 		c0.91,1.78,2.76,3,4.89,3c3.04,0,5.5-2.46,5.5-5.5c0-3.04-2.46-5.5-5.5-5.5c-0.17,0-0.34,0.01-0.5,0.03"/> | ||||
| 	 | ||||
| 		<polygon fill="#ED6B21" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points=" | ||||
| 		7.39,1 7.39,5 4.39,3 	"/> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 746 B | 
|  | @ -1,4 +1,9 @@ | |||
| min_slic3r_version = 2.1.0-alpha0 | ||||
| 1.0.0-alpha0 Filament specific retract for PET and similar copolymers, and for FLEX | ||||
| min_slic3r_version = 1.42.0-alpha6 | ||||
| 0.8.3 FW version and SL1 materials update | ||||
| 0.8.2 FFF and SL1 settings update | ||||
| 0.8.1 Output settings and SLA materials update | ||||
| 0.8.0 Updated for the PrusaSlicer 2.0.0 final release | ||||
| 0.8.0-rc2 Updated firmware versions for MK2.5/S and MK3/S | ||||
| 0.8.0-rc1 Updated SLA profiles | ||||
|  | @ -18,6 +23,8 @@ min_slic3r_version = 1.42.0-alpha | |||
| 0.4.0-alpha3 Update of SLA profiles | ||||
| 0.4.0-alpha2 First SLA profiles | ||||
| min_slic3r_version = 1.41.3-alpha | ||||
| 0.4.8 MK2.5/3/S FW update | ||||
| 0.4.7 MK2/S/MMU FW update | ||||
| 0.4.6 Updated firmware versions for MK2.5/S and MK3/S | ||||
| 0.4.5 Enabled remaining time support for MK2/S/MMU1 | ||||
| 0.4.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt | ||||
|  | @ -26,6 +33,8 @@ min_slic3r_version = 1.41.3-alpha | |||
| 0.4.1 New MK2.5S and MK3S FW versions | ||||
| 0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt  | ||||
| min_slic3r_version = 1.41.1 | ||||
| 0.3.8 MK2.5/3/S FW update | ||||
| 0.3.7 MK2/S/MMU FW update | ||||
| 0.3.6 Updated firmware versions for MK2.5 and MK3 | ||||
| 0.3.5 New MK2.5 and MK3 FW versions | ||||
| 0.3.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt  | ||||
|  | @ -60,6 +69,8 @@ min_slic3r_version = 1.41.0-alpha | |||
| 0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0 | ||||
| 0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters | ||||
| min_slic3r_version = 1.40.0 | ||||
| 0.1.16 MK2.5/3/S FW update | ||||
| 0.1.15 MK2/S/MMU FW update | ||||
| 0.1.14 Updated firmware versions for MK2.5 and MK3 | ||||
| 0.1.13 New MK2.5 and MK3 FW versions | ||||
| 0.1.12 New MK2.5 and MK3 FW versions | ||||
|  |  | |||
|  | @ -5,16 +5,30 @@ const vec3 back_color_light = vec3(0.365, 0.365, 0.365); | |||
| 
 | ||||
| uniform sampler2D texture; | ||||
| uniform bool transparent_background; | ||||
| uniform bool svg_source; | ||||
| 
 | ||||
| varying vec2 tex_coords; | ||||
| 
 | ||||
| void main() | ||||
| vec4 svg_color() | ||||
| { | ||||
|     // takes foreground from texture | ||||
|     vec4 fore_color = texture2D(texture, tex_coords); | ||||
| 
 | ||||
|     // calculates radial gradient | ||||
|     vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coords.xy) - vec2(0.5))))); | ||||
| 
 | ||||
|     vec4 fore_color = texture2D(texture, tex_coords); | ||||
| 
 | ||||
|     // blends foreground with background | ||||
|     gl_FragColor = vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0); | ||||
|     return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0); | ||||
| } | ||||
| 
 | ||||
| vec4 non_svg_color() | ||||
| { | ||||
|     // takes foreground from texture | ||||
|     vec4 color = texture2D(texture, tex_coords); | ||||
|     return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); | ||||
| } | ||||
| 
 | ||||
| void main() | ||||
| { | ||||
|     gl_FragColor = svg_source ? svg_color() : non_svg_color(); | ||||
| } | ||||
|  | @ -15,6 +15,7 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); | |||
| #define INTENSITY_AMBIENT    0.3 | ||||
| 
 | ||||
| uniform mat4 volume_world_matrix; | ||||
| uniform float object_max_z; | ||||
| 
 | ||||
| // x = tainted, y = specular; | ||||
| varying vec2 intensity; | ||||
|  | @ -42,6 +43,12 @@ void main() | |||
|     intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; | ||||
| 
 | ||||
|     // Scaled to widths of the Z texture. | ||||
|     object_z = (volume_world_matrix * gl_Vertex).z; | ||||
|     if (object_max_z > 0.0) | ||||
|         // when rendering the overlay | ||||
|         object_z = object_max_z * gl_MultiTexCoord0.y; | ||||
|     else | ||||
|         // when rendering the volumes | ||||
|         object_z = (volume_world_matrix * gl_Vertex).z; | ||||
|          | ||||
|     gl_Position = ftransform(); | ||||
| } | ||||
|  |  | |||
|  | @ -1 +1,2 @@ | |||
| add_subdirectory(slabasebed) | ||||
| add_subdirectory(slasupporttree) | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <libslic3r/libslic3r.h> | ||||
| #include <libslic3r/TriangleMesh.hpp> | ||||
| #include <libslic3r/Tesselate.hpp> | ||||
| #include <libslic3r/ClipperUtils.hpp> | ||||
| #include <libslic3r/SLA/SLABasePool.hpp> | ||||
| #include <libslic3r/SLA/SLABoilerPlate.hpp> | ||||
| #include <libnest2d/tools/benchmark.h> | ||||
|  | @ -15,7 +16,8 @@ const std::string USAGE_STR = { | |||
| 
 | ||||
| namespace Slic3r { namespace sla { | ||||
| 
 | ||||
| Contour3D create_base_pool(const ExPolygons &ground_layer,  | ||||
| Contour3D create_base_pool(const Polygons &ground_layer, | ||||
|                            const ExPolygons &holes = {}, | ||||
|                            const PoolConfig& cfg = PoolConfig()); | ||||
| 
 | ||||
| Contour3D walls(const Polygon& floor_plate, const Polygon& ceiling, | ||||
|  | @ -43,36 +45,27 @@ int main(const int argc, const char *argv[]) { | |||
|     model.align_to_origin(); | ||||
| 
 | ||||
|     ExPolygons ground_slice; | ||||
|     sla::Contour3D mesh; | ||||
| //    TriangleMesh basepool;
 | ||||
| 
 | ||||
|     sla::base_plate(model, ground_slice, 0.1f); | ||||
| 
 | ||||
|     if(ground_slice.empty()) return EXIT_FAILURE; | ||||
| 
 | ||||
| //    ExPolygon bottom_plate = ground_slice.front();
 | ||||
| //    ExPolygon top_plate = bottom_plate;
 | ||||
| //    sla::offset(top_plate, coord_t(3.0/SCALING_FACTOR));
 | ||||
| //    sla::offset(bottom_plate, coord_t(1.0/SCALING_FACTOR));
 | ||||
|     ground_slice = offset_ex(ground_slice, 0.5); | ||||
|     ExPolygon gndfirst; gndfirst = ground_slice.front(); | ||||
|     sla::breakstick_holes(gndfirst, 0.5, 10, 0.3); | ||||
| 
 | ||||
|     sla::Contour3D mesh; | ||||
| 
 | ||||
|     bench.start(); | ||||
| 
 | ||||
| //    TriangleMesh pool;
 | ||||
|     sla::PoolConfig cfg; | ||||
|     cfg.min_wall_height_mm = 0; | ||||
|     cfg.edge_radius_mm = 0.2; | ||||
|     mesh = sla::create_base_pool(ground_slice, cfg); | ||||
|      | ||||
| //    mesh.merge(triangulate_expolygon_3d(top_plate, 3.0, false));
 | ||||
| //    mesh.merge(triangulate_expolygon_3d(bottom_plate, 0.0, true));
 | ||||
| //    mesh = sla::walls(bottom_plate.contour, top_plate.contour, 0, 3, 2.0, [](){});
 | ||||
|      | ||||
|     cfg.edge_radius_mm = 0; | ||||
|     mesh = sla::create_base_pool(to_polygons(ground_slice), {}, cfg); | ||||
| 
 | ||||
|     bench.stop(); | ||||
| 
 | ||||
|     cout << "Base pool creation time: " << std::setprecision(10) | ||||
|          << bench.getElapsedSec() << " seconds." << endl; | ||||
|      | ||||
| //    auto point = []()
 | ||||
| 
 | ||||
|     for(auto& trind : mesh.indices) { | ||||
|         Vec3d p0 = mesh.points[size_t(trind[0])]; | ||||
|         Vec3d p1 = mesh.points[size_t(trind[1])]; | ||||
|  | @ -83,7 +76,7 @@ int main(const int argc, const char *argv[]) { | |||
|         if(std::abs(a) < 1e-6) std::cout << "degenerate triangle" << std::endl; | ||||
|     } | ||||
| 
 | ||||
| //    basepool.write_ascii("out.stl");
 | ||||
|     //    basepool.write_ascii("out.stl");
 | ||||
| 
 | ||||
|     std::fstream outstream("out.obj", std::fstream::out); | ||||
|     mesh.to_obj(outstream); | ||||
|  |  | |||
							
								
								
									
										2
									
								
								sandboxes/slasupporttree/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,2 @@ | |||
| add_executable(slasupporttree slasupporttree.cpp) | ||||
| target_link_libraries(slasupporttree libslic3r ${Boost_LIBRARIES} ${TBB_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS}) | ||||
							
								
								
									
										42
									
								
								sandboxes/slasupporttree/slasupporttree.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,42 @@ | |||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <string> | ||||
| 
 | ||||
| #include <libslic3r/libslic3r.h> | ||||
| #include <libslic3r/Model.hpp> | ||||
| #include <libslic3r/Tesselate.hpp> | ||||
| #include <libslic3r/ClipperUtils.hpp> | ||||
| #include <libslic3r/SLA/SLAAutoSupports.hpp> | ||||
| #include <libslic3r/SLA/SLASupportTree.hpp> | ||||
| #include <libslic3r/SLAPrint.hpp> | ||||
| #include <libslic3r/MTUtils.hpp> | ||||
| 
 | ||||
| #include <tbb/parallel_for.h> | ||||
| #include <tbb/mutex.h> | ||||
| #include <future> | ||||
| 
 | ||||
| const std::string USAGE_STR = { | ||||
|     "Usage: slasupporttree stlfilename.stl" | ||||
| }; | ||||
| 
 | ||||
| int main(const int argc, const char *argv[]) { | ||||
|     using namespace Slic3r; | ||||
|     using std::cout; using std::endl; | ||||
| 
 | ||||
|     if(argc < 2) { | ||||
|         cout << USAGE_STR << endl; | ||||
|         return EXIT_SUCCESS; | ||||
|     } | ||||
| 
 | ||||
|     DynamicPrintConfig config; | ||||
| 
 | ||||
|     Model model = Model::read_from_file(argv[1], &config); | ||||
| 
 | ||||
|     SLAPrint print; | ||||
| 
 | ||||
|     print.apply(model, config); | ||||
|     print.process(); | ||||
| 
 | ||||
| 
 | ||||
|     return EXIT_SUCCESS; | ||||
| } | ||||
|  | @ -1,5 +1,6 @@ | |||
| project(PrusaSlicer-native) | ||||
| 
 | ||||
| add_subdirectory(build-utils) | ||||
| add_subdirectory(admesh) | ||||
| add_subdirectory(avrdude) | ||||
| # boost/nowide | ||||
|  | @ -12,14 +13,12 @@ add_subdirectory(poly2tri) | |||
| add_subdirectory(qhull) | ||||
| add_subdirectory(Shiny) | ||||
| add_subdirectory(semver) | ||||
| add_subdirectory(libigl) | ||||
| 
 | ||||
| # Adding libnest2d project for bin packing... | ||||
| set(LIBNEST2D_UNITTESTS ON CACHE BOOL "Force generating unittests for libnest2d") | ||||
| add_subdirectory(libnest2d) | ||||
| 
 | ||||
| include_directories(${LIBDIR}/qhull/src) | ||||
| #message(STATUS ${LIBDIR}/qhull/src) | ||||
| 
 | ||||
| add_subdirectory(libslic3r) | ||||
| 
 | ||||
| if (SLIC3R_GUI) | ||||
|  | @ -49,7 +48,7 @@ if (SLIC3R_GUI) | |||
|             endif () | ||||
|         endif () | ||||
|     else () | ||||
|         find_package(wxWidgets 3.1 REQUIRED COMPONENTS base core adv html gl) | ||||
|         find_package(wxWidgets 3.1 REQUIRED COMPONENTS html adv gl core base) | ||||
|     endif () | ||||
| 
 | ||||
|     if(UNIX) | ||||
|  | @ -58,6 +57,9 @@ if (SLIC3R_GUI) | |||
| 
 | ||||
|     include(${wxWidgets_USE_FILE}) | ||||
| 
 | ||||
| #    list(REMOVE_ITEM wxWidgets_LIBRARIES oleacc) | ||||
|     message(STATUS "wx libs: ${wxWidgets_LIBRARIES}") | ||||
| 
 | ||||
|     add_subdirectory(slic3r) | ||||
| endif() | ||||
| 
 | ||||
|  | @ -67,17 +69,23 @@ endif() | |||
| configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/PrusaSlicer.rc.in ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.rc @ONLY) | ||||
| configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/PrusaSlicer.manifest.in ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.manifest @ONLY) | ||||
| configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/osx/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY) | ||||
| if (MSVC) | ||||
| if (WIN32) | ||||
|     add_library(PrusaSlicer SHARED PrusaSlicer.cpp PrusaSlicer.hpp) | ||||
| else () | ||||
|     add_executable(PrusaSlicer PrusaSlicer.cpp PrusaSlicer.hpp) | ||||
| endif () | ||||
| if (NOT MSVC) | ||||
| 
 | ||||
| if (MINGW) | ||||
|     target_link_options(PrusaSlicer PUBLIC "-Wl,-allow-multiple-definition") | ||||
|     set_target_properties(PrusaSlicer PROPERTIES PREFIX "") | ||||
| endif (MINGW) | ||||
| 
 | ||||
| if (NOT WIN32) | ||||
|     # Binary name on unix like systems (OSX, Linux) | ||||
|     set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer") | ||||
| endif () | ||||
| 
 | ||||
| target_link_libraries(PrusaSlicer libslic3r) | ||||
| target_link_libraries(PrusaSlicer libslic3r cereal) | ||||
| if (APPLE) | ||||
| #    add_compile_options(-stdlib=libc++) | ||||
| #    add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE) | ||||
|  | @ -93,11 +101,12 @@ endif () | |||
| 
 | ||||
| # Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries. | ||||
| if (SLIC3R_GUI) | ||||
|     target_link_libraries(PrusaSlicer libslic3r_gui ${wxWidgets_LIBRARIES}) | ||||
| #    target_link_libraries(PrusaSlicer ws2_32 uxtheme setupapi libslic3r_gui ${wxWidgets_LIBRARIES}) | ||||
| target_link_libraries(PrusaSlicer libslic3r_gui ${wxWidgets_LIBRARIES}) | ||||
| 
 | ||||
|     # Configure libcurl and its dependencies OpenSSL & zlib | ||||
|     find_package(CURL REQUIRED) | ||||
|     if (NOT MSVC) | ||||
|     if (NOT WIN32) | ||||
|         # Required by libcurl | ||||
|         find_package(ZLIB REQUIRED) | ||||
|     endif() | ||||
|  | @ -125,7 +134,7 @@ if (SLIC3R_GUI) | |||
|         target_link_options(PrusaSlicer PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>") | ||||
|         target_link_libraries(PrusaSlicer user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib) | ||||
|     elseif (MINGW) | ||||
|         target_link_libraries(PrusaSlicer -lopengl32) | ||||
|         target_link_libraries(PrusaSlicer opengl32 ws2_32 uxtheme setupapi) | ||||
|     elseif (APPLE) | ||||
|         target_link_libraries(PrusaSlicer "-framework OpenGL") | ||||
|     else () | ||||
|  | @ -135,26 +144,34 @@ endif () | |||
| 
 | ||||
| # On Windows, a shim application is required to produce a console / non console version of the Slic3r application. | ||||
| # Also the shim may load the Mesa software OpenGL renderer if the default renderer does not support OpenGL 2.0 and higher. | ||||
| if (MSVC) | ||||
| if (WIN32) | ||||
|     if (MINGW) | ||||
|         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode") | ||||
|     endif() | ||||
| 
 | ||||
|     add_executable(PrusaSlicer_app_gui WIN32 PrusaSlicer_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.rc) | ||||
|     # Generate debug symbols even in release mode. | ||||
|     target_link_options(PrusaSlicer_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>") | ||||
|     if(MSVC) | ||||
|         target_link_options(PrusaSlicer_app_gui PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>") | ||||
|     endif() | ||||
|     target_compile_definitions(PrusaSlicer_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE) | ||||
|     add_dependencies(PrusaSlicer_app_gui PrusaSlicer) | ||||
|     set_target_properties(PrusaSlicer_app_gui PROPERTIES OUTPUT_NAME "prusa-slicer") | ||||
|     target_include_directories(PrusaSlicer_app_gui SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) | ||||
|     target_link_libraries(PrusaSlicer_app_gui PRIVATE boost_headeronly) | ||||
| 
 | ||||
|     add_executable(PrusaSlicer_app_console PrusaSlicer_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.rc) | ||||
|     # Generate debug symbols even in release mode. | ||||
|     if (MSVC) | ||||
|     target_link_options(PrusaSlicer_app_console PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>") | ||||
|     endif () | ||||
|     target_compile_definitions(PrusaSlicer_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE) | ||||
|     add_dependencies(PrusaSlicer_app_console PrusaSlicer) | ||||
|     set_target_properties(PrusaSlicer_app_console PROPERTIES OUTPUT_NAME "prusa-slicer-console") | ||||
|     target_include_directories(PrusaSlicer_app_console SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) | ||||
|     target_link_libraries(PrusaSlicer_app_console PRIVATE boost_headeronly) | ||||
| endif () | ||||
| 
 | ||||
| # Link the resources dir to where Slic3r GUI expects it | ||||
| if (MSVC) | ||||
| if (WIN32) | ||||
|     if (CMAKE_CONFIGURATION_TYPES) | ||||
|         foreach (CONF ${CMAKE_CONFIGURATION_TYPES}) | ||||
|             file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}" WIN_CONF_OUTPUT_DIR) | ||||
|  |  | |||
|  | @ -7,10 +7,13 @@ | |||
|     #include <Windows.h> | ||||
|     #include <wchar.h> | ||||
|     #ifdef SLIC3R_GUI | ||||
|     extern "C" | ||||
|     { | ||||
|         // Let the NVIDIA and AMD know we want to use their graphics card
 | ||||
|         // on a dual graphics card system.
 | ||||
|         __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; | ||||
|         __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; | ||||
|     } | ||||
|     #endif /* SLIC3R_GUI */ | ||||
| #endif /* WIN32 */ | ||||
| 
 | ||||
|  | @ -23,6 +26,7 @@ | |||
| #include <boost/nowide/args.hpp> | ||||
| #include <boost/nowide/cenv.hpp> | ||||
| #include <boost/nowide/iostream.hpp> | ||||
| #include <boost/nowide/integration/filesystem.hpp> | ||||
| 
 | ||||
| #include "unix/fhs.hpp"  // Generated by CMake from ../platform/unix/fhs.hpp.in
 | ||||
| 
 | ||||
|  | @ -44,18 +48,39 @@ | |||
| #ifdef SLIC3R_GUI | ||||
|     #include "slic3r/GUI/GUI.hpp" | ||||
|     #include "slic3r/GUI/GUI_App.hpp" | ||||
|     #include "slic3r/GUI/3DScene.hpp" | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| using namespace Slic3r; | ||||
| 
 | ||||
| PrinterTechnology get_printer_technology(const DynamicConfig &config) | ||||
| { | ||||
| 	const ConfigOptionEnum<PrinterTechnology> *opt = config.option<ConfigOptionEnum<PrinterTechnology>>("printer_technology"); | ||||
|     const ConfigOptionEnum<PrinterTechnology> *opt = config.option<ConfigOptionEnum<PrinterTechnology>>("printer_technology"); | ||||
|     return (opt == nullptr) ? ptUnknown : opt->value; | ||||
| } | ||||
| 
 | ||||
| int CLI::run(int argc, char **argv)  | ||||
| int CLI::run(int argc, char **argv) | ||||
| { | ||||
| 	// Switch boost::filesystem to utf8.
 | ||||
|     try { | ||||
|         boost::nowide::nowide_filesystem(); | ||||
|     } catch (const std::runtime_error& ex) { | ||||
|         std::string caption = std::string(SLIC3R_APP_NAME) + " Error"; | ||||
|         std::string text = std::string("An error occured while setting up locale.\n") + ( | ||||
| #if !defined(_WIN32) && !defined(__APPLE__) | ||||
|         	// likely some linux system
 | ||||
|         	"You may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n" | ||||
| #endif | ||||
|         	SLIC3R_APP_NAME " will now terminate.\n\n") + ex.what(); | ||||
|     #if defined(_WIN32) && defined(SLIC3R_GUI) | ||||
|         if (m_actions.empty()) | ||||
|         	// Empty actions means Slicer is executed in the GUI mode. Show a GUI message.
 | ||||
|             MessageBoxA(NULL, text.c_str(), caption.c_str(), MB_OK | MB_ICONERROR); | ||||
|     #endif | ||||
|         boost::nowide::cerr << text.c_str() << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
| 	if (! this->setup(argc, argv)) | ||||
| 		return 1; | ||||
| 
 | ||||
|  | @ -64,14 +89,14 @@ int CLI::run(int argc, char **argv) | |||
| 
 | ||||
|     bool							start_gui			= m_actions.empty() && | ||||
|         // cutting transformations are setting an "export" action.
 | ||||
| 		std::find(m_transforms.begin(), m_transforms.end(), "cut") == m_transforms.end() && | ||||
| 		std::find(m_transforms.begin(), m_transforms.end(), "cut_x") == m_transforms.end() && | ||||
| 		std::find(m_transforms.begin(), m_transforms.end(), "cut_y") == m_transforms.end(); | ||||
|         std::find(m_transforms.begin(), m_transforms.end(), "cut") == m_transforms.end() && | ||||
|         std::find(m_transforms.begin(), m_transforms.end(), "cut_x") == m_transforms.end() && | ||||
|         std::find(m_transforms.begin(), m_transforms.end(), "cut_y") == m_transforms.end(); | ||||
|     PrinterTechnology				printer_technology	= get_printer_technology(m_extra_config); | ||||
| 	const std::vector<std::string> &load_configs		= m_config.option<ConfigOptionStrings>("load", true)->values; | ||||
|      | ||||
|     const std::vector<std::string> &load_configs		= m_config.option<ConfigOptionStrings>("load", true)->values; | ||||
| 
 | ||||
|     // load config files supplied via --load
 | ||||
| 	for (auto const &file : load_configs) { | ||||
|     for (auto const &file : load_configs) { | ||||
|         if (! boost::filesystem::exists(file)) { | ||||
|             if (m_config.opt_bool("ignore_nonexistent_config")) { | ||||
|                 continue; | ||||
|  | @ -91,13 +116,13 @@ int CLI::run(int argc, char **argv) | |||
|         PrinterTechnology other_printer_technology = get_printer_technology(config); | ||||
|         if (printer_technology == ptUnknown) { | ||||
|             printer_technology = other_printer_technology; | ||||
|         } else if (printer_technology != other_printer_technology) { | ||||
|         } else if (printer_technology != other_printer_technology && other_printer_technology != ptUnknown) { | ||||
|             boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl; | ||||
|             return 1; | ||||
|         } | ||||
|         m_print_config.apply(config); | ||||
|     } | ||||
|          | ||||
| 
 | ||||
|     // Read input file(s) if any.
 | ||||
|     for (const std::string &file : m_input_files) { | ||||
|         if (! boost::filesystem::exists(file)) { | ||||
|  | @ -111,7 +136,7 @@ int CLI::run(int argc, char **argv) | |||
|             PrinterTechnology other_printer_technology = get_printer_technology(m_print_config); | ||||
|             if (printer_technology == ptUnknown) { | ||||
|                 printer_technology = other_printer_technology; | ||||
|             } else if (printer_technology != other_printer_technology) { | ||||
|             } else if (printer_technology != other_printer_technology && other_printer_technology != ptUnknown) { | ||||
|                 boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl; | ||||
|                 return 1; | ||||
|             } | ||||
|  | @ -133,21 +158,21 @@ int CLI::run(int argc, char **argv) | |||
|     m_print_config.normalize(); | ||||
| 
 | ||||
|     if (printer_technology == ptUnknown) | ||||
| 		printer_technology = std::find(m_actions.begin(), m_actions.end(), "export_sla") == m_actions.end() ? ptFFF : ptSLA; | ||||
|         printer_technology = std::find(m_actions.begin(), m_actions.end(), "export_sla") == m_actions.end() ? ptFFF : ptSLA; | ||||
| 
 | ||||
|     // Initialize full print configs for both the FFF and SLA technologies.
 | ||||
|     FullPrintConfig    fff_print_config; | ||||
| //    SLAFullPrintConfig sla_print_config;
 | ||||
|     fff_print_config.apply(m_print_config, true); | ||||
| //    sla_print_config.apply(m_print_config, true);
 | ||||
|      | ||||
| 
 | ||||
|     // Loop through transform options.
 | ||||
|     for (auto const &opt_key : m_transforms) { | ||||
|         if (opt_key == "merge") { | ||||
|             Model m; | ||||
|             for (auto &model : m_models) | ||||
| 				for (ModelObject *o : model.objects) | ||||
| 					m.add_object(*o); | ||||
|                 for (ModelObject *o : model.objects) | ||||
|                     m.add_object(*o); | ||||
|             // Rearrange instances unless --dont-arrange is supplied
 | ||||
|             if (! m_config.opt_bool("dont_arrange")) { | ||||
|                 m.add_default_instances(); | ||||
|  | @ -159,8 +184,8 @@ int CLI::run(int argc, char **argv) | |||
|                     this->has_print_action() ? &bb : nullptr | ||||
|                 ); | ||||
|             } | ||||
| 			m_models.clear(); | ||||
| 			m_models.emplace_back(std::move(m)); | ||||
|             m_models.clear(); | ||||
|             m_models.emplace_back(std::move(m)); | ||||
|         } else if (opt_key == "duplicate") { | ||||
|             const BoundingBoxf &bb = fff_print_config.bed_shape.values; | ||||
|             for (auto &model : m_models) { | ||||
|  | @ -189,11 +214,11 @@ int CLI::run(int argc, char **argv) | |||
|                 // this affects instances:
 | ||||
|                 model.center_instances_around_point(m_config.option<ConfigOptionPoint>("center")->value); | ||||
|                 // this affects volumes:
 | ||||
| 				//FIXME Vojtech: Who knows why the complete model should be aligned with Z as a single rigid body?
 | ||||
|                 //FIXME Vojtech: Who knows why the complete model should be aligned with Z as a single rigid body?
 | ||||
|                 //model.align_to_ground();
 | ||||
|                 BoundingBoxf3 bbox; | ||||
|                 for (ModelObject *model_object : model.objects) | ||||
| 					// We are interested into the Z span only, therefore it is sufficient to measure the bounding box of the 1st instance only.
 | ||||
|                     // We are interested into the Z span only, therefore it is sufficient to measure the bounding box of the 1st instance only.
 | ||||
|                     bbox.merge(model_object->instance_bounding_box(0, false)); | ||||
|                 for (ModelObject *model_object : model.objects) | ||||
|                     for (ModelInstance *model_instance : model_object->instances) | ||||
|  | @ -204,7 +229,7 @@ int CLI::run(int argc, char **argv) | |||
|             for (auto &model : m_models) { | ||||
|                 BoundingBoxf3 bb = model.bounding_box(); | ||||
|                 // this affects volumes:
 | ||||
| 				model.translate(-(bb.min.x() - p.x()), -(bb.min.y() - p.y()), -bb.min.z()); | ||||
|                 model.translate(-(bb.min.x() - p.x()), -(bb.min.y() - p.y()), -bb.min.z()); | ||||
|             } | ||||
|         } else if (opt_key == "dont_arrange") { | ||||
|             // do nothing - this option alters other transform options
 | ||||
|  | @ -241,10 +266,9 @@ int CLI::run(int argc, char **argv) | |||
|         } else if (opt_key == "cut" || opt_key == "cut_x" || opt_key == "cut_y") { | ||||
|             std::vector<Model> new_models; | ||||
|             for (auto &model : m_models) { | ||||
|                 model.repair(); | ||||
|                 model.translate(0, 0, -model.bounding_box().min.z());  // align to z = 0                
 | ||||
| 				size_t num_objects = model.objects.size(); | ||||
| 				for (size_t i = 0; i < num_objects; ++ i) { | ||||
|                 model.translate(0, 0, -model.bounding_box().min.z());  // align to z = 0
 | ||||
|                 size_t num_objects = model.objects.size(); | ||||
|                 for (size_t i = 0; i < num_objects; ++ i) { | ||||
| 
 | ||||
| #if 0 | ||||
|                     if (opt_key == "cut_x") { | ||||
|  | @ -255,15 +279,15 @@ int CLI::run(int argc, char **argv) | |||
|                         o->cut(Z, m_config.opt_float("cut"), &out); | ||||
|                     } | ||||
| #else | ||||
| 					model.objects.front()->cut(0, m_config.opt_float("cut"), true, true, true); | ||||
|                     model.objects.front()->cut(0, m_config.opt_float("cut"), true, true, true); | ||||
| #endif | ||||
| 					model.delete_object(size_t(0)); | ||||
|                     model.delete_object(size_t(0)); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
| 
 | ||||
|             // TODO: copy less stuff around using pointers
 | ||||
|             m_models = new_models; | ||||
|              | ||||
| 
 | ||||
|             if (m_actions.empty()) | ||||
|                 m_actions.push_back("export_stl"); | ||||
|         } | ||||
|  | @ -273,7 +297,7 @@ int CLI::run(int argc, char **argv) | |||
|             for (auto &model : m_models) { | ||||
|                 TriangleMesh mesh = model.mesh(); | ||||
|                 mesh.repair(); | ||||
|              | ||||
| 
 | ||||
|                 TriangleMeshPtrs meshes = mesh.cut_by_grid(m_config.option<ConfigOptionPoint>("cut_grid")->value); | ||||
|                 size_t i = 0; | ||||
|                 for (TriangleMesh* m : meshes) { | ||||
|  | @ -284,10 +308,10 @@ int CLI::run(int argc, char **argv) | |||
|                     delete m; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
| 
 | ||||
|             // TODO: copy less stuff around using pointers
 | ||||
|             m_models = new_models; | ||||
|              | ||||
| 
 | ||||
|             if (m_actions.empty()) | ||||
|                 m_actions.push_back("export_stl"); | ||||
|         } | ||||
|  | @ -301,14 +325,15 @@ int CLI::run(int argc, char **argv) | |||
|                 } | ||||
|             } | ||||
|         } else if (opt_key == "repair") { | ||||
|             for (auto &model : m_models) | ||||
|                 model.repair(); | ||||
|             // Models are repaired by default.
 | ||||
|             //for (auto &model : m_models)
 | ||||
|             //    model.repair();
 | ||||
|         } else { | ||||
|             boost::nowide::cerr << "error: option not implemented yet: " << opt_key << std::endl; | ||||
|             return 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     // loop through action options
 | ||||
|     for (auto const &opt_key : m_actions) { | ||||
|         if (opt_key == "help") { | ||||
|  | @ -351,14 +376,14 @@ int CLI::run(int argc, char **argv) | |||
|                 boost::nowide::cerr << "error: cannot export SLA slices for a SLA configuration" << std::endl; | ||||
|                 return 1; | ||||
|             } | ||||
| 			// Make a copy of the model if the current action is not the last action, as the model may be
 | ||||
| 			// modified by the centering and such.
 | ||||
| 			Model model_copy; | ||||
| 			bool  make_copy = &opt_key != &m_actions.back(); | ||||
|             // Make a copy of the model if the current action is not the last action, as the model may be
 | ||||
|             // modified by the centering and such.
 | ||||
|             Model model_copy; | ||||
|             bool  make_copy = &opt_key != &m_actions.back(); | ||||
|             for (Model &model_in : m_models) { | ||||
| 				if (make_copy) | ||||
| 					model_copy = model_in; | ||||
| 				Model &model = make_copy ? model_copy : model_in; | ||||
|                 if (make_copy) | ||||
|                     model_copy = model_in; | ||||
|                 Model &model = make_copy ? model_copy : model_in; | ||||
|                 // If all objects have defined instances, their relative positions will be
 | ||||
|                 // honored when printing (they will be only centered, unless --dont-arrange
 | ||||
|                 // is supplied); if any object has no instances, it will get a default one
 | ||||
|  | @ -378,7 +403,7 @@ int CLI::run(int argc, char **argv) | |||
|                 if (! m_config.opt_bool("dont_arrange")) { | ||||
|                     //FIXME make the min_object_distance configurable.
 | ||||
|                     model.arrange_objects(fff_print.config().min_object_distance()); | ||||
| 					model.center_instances_around_point(m_config.option<ConfigOptionPoint>("center")->value); | ||||
|                     model.center_instances_around_point(m_config.option<ConfigOptionPoint>("center")->value); | ||||
|                 } | ||||
|                 if (printer_technology == ptFFF) { | ||||
|                     for (auto* mo : model.objects) | ||||
|  | @ -392,40 +417,40 @@ int CLI::run(int argc, char **argv) | |||
|                 } | ||||
|                 if (print->empty()) | ||||
|                     boost::nowide::cout << "Nothing to print for " << outfile << " . Either the print is empty or no object is fully inside the print volume." << std::endl; | ||||
|                 else  | ||||
|                 else | ||||
|                     try { | ||||
|                         std::string outfile_final; | ||||
| 						print->process(); | ||||
|                         print->process(); | ||||
|                         if (printer_technology == ptFFF) { | ||||
|                             // The outfile is processed by a PlaceholderParser.
 | ||||
|                             outfile = fff_print.export_gcode(outfile, nullptr); | ||||
|                             outfile_final = fff_print.print_statistics().finalize_output_path(outfile); | ||||
|                         } else { | ||||
| 							outfile = sla_print.output_filepath(outfile); | ||||
|                             outfile = sla_print.output_filepath(outfile); | ||||
|                             // We need to finalize the filename beforehand because the export function sets the filename inside the zip metadata
 | ||||
|                             outfile_final = sla_print.print_statistics().finalize_output_path(outfile); | ||||
| 							sla_print.export_raster(outfile_final); | ||||
|                             sla_print.export_raster(outfile_final); | ||||
|                         } | ||||
|                         if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final) != 0) { | ||||
| 							boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl; | ||||
|                         if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final)) { | ||||
|                             boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl; | ||||
|                             return 1; | ||||
|                         } | ||||
|                         boost::nowide::cout << "Slicing result exported to " << outfile << std::endl; | ||||
|                     } catch (const std::exception &ex) { | ||||
| 						boost::nowide::cerr << ex.what() << std::endl; | ||||
|                         return 1;                         | ||||
|                         boost::nowide::cerr << ex.what() << std::endl; | ||||
|                         return 1; | ||||
|                     } | ||||
| /*
 | ||||
|                 print.center = ! m_config.has("center") | ||||
|                     && ! m_config.has("align_xy") | ||||
|                     && ! m_config.opt_bool("dont_arrange"); | ||||
|                 print.set_model(model); | ||||
|                  | ||||
| 
 | ||||
|                 // start chronometer
 | ||||
|                 typedef std::chrono::high_resolution_clock clock_; | ||||
|                 typedef std::chrono::duration<double, std::ratio<1> > second_; | ||||
|                 std::chrono::time_point<clock_> t0{ clock_::now() }; | ||||
|                  | ||||
| 
 | ||||
|                 const std::string outfile = this->output_filepath(model, IO::Gcode); | ||||
|                 try { | ||||
|                     print.export_gcode(outfile); | ||||
|  | @ -434,7 +459,7 @@ int CLI::run(int argc, char **argv) | |||
|                     return 1; | ||||
|                 } | ||||
|                 boost::nowide::cout << "G-code exported to " << outfile << std::endl; | ||||
|                  | ||||
| 
 | ||||
|                 // output some statistics
 | ||||
|                 double duration { std::chrono::duration_cast<second_>(clock_::now() - t0).count() }; | ||||
|                 boost::nowide::cout << std::fixed << std::setprecision(0) | ||||
|  | @ -451,51 +476,55 @@ int CLI::run(int argc, char **argv) | |||
|             return 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
| 	if (start_gui) { | ||||
| 
 | ||||
|     if (start_gui) { | ||||
| #ifdef SLIC3R_GUI | ||||
| // #ifdef USE_WX
 | ||||
| 		GUI::GUI_App *gui = new GUI::GUI_App(); | ||||
|         GUI::GUI_App *gui = new GUI::GUI_App(); | ||||
| //		gui->autosave = m_config.opt_string("autosave");
 | ||||
| 		GUI::GUI_App::SetInstance(gui); | ||||
| 		gui->CallAfter([gui, this, &load_configs] { | ||||
| 			if (!gui->initialized()) { | ||||
| 				return; | ||||
| 			} | ||||
|         GUI::GUI_App::SetInstance(gui); | ||||
|         gui->CallAfter([gui, this, &load_configs] { | ||||
|             if (!gui->initialized()) { | ||||
|                 return; | ||||
|             } | ||||
| #if 0 | ||||
| 			// Load the cummulative config over the currently active profiles.
 | ||||
| 			//FIXME if multiple configs are loaded, only the last one will have an effect.
 | ||||
| 			// We need to decide what to do about loading of separate presets (just print preset, just filament preset etc).
 | ||||
| 			// As of now only the full configs are supported here.
 | ||||
| 			if (!m_print_config.empty()) | ||||
| 				gui->mainframe->load_config(m_print_config); | ||||
|             // Load the cummulative config over the currently active profiles.
 | ||||
|             //FIXME if multiple configs are loaded, only the last one will have an effect.
 | ||||
|             // We need to decide what to do about loading of separate presets (just print preset, just filament preset etc).
 | ||||
|             // As of now only the full configs are supported here.
 | ||||
|             if (!m_print_config.empty()) | ||||
|                 gui->mainframe->load_config(m_print_config); | ||||
| #endif | ||||
| 			if (! load_configs.empty()) | ||||
| 				// Load the last config to give it a name at the UI. The name of the preset may be later
 | ||||
| 				// changed by loading an AMF or 3MF.
 | ||||
| 				//FIXME this is not strictly correct, as one may pass a print/filament/printer profile here instead of a full config.
 | ||||
| 				gui->mainframe->load_config_file(load_configs.back()); | ||||
| 			// If loading a 3MF file, the config is loaded from the last one.
 | ||||
| 			if (! m_input_files.empty()) | ||||
| 				gui->plater()->load_files(m_input_files, true, true); | ||||
| 			if (! m_extra_config.empty()) | ||||
| 				gui->mainframe->load_config(m_extra_config); | ||||
| 		}); | ||||
| 		return wxEntry(argc, argv); | ||||
|             if (! load_configs.empty()) | ||||
|                 // Load the last config to give it a name at the UI. The name of the preset may be later
 | ||||
|                 // changed by loading an AMF or 3MF.
 | ||||
|                 //FIXME this is not strictly correct, as one may pass a print/filament/printer profile here instead of a full config.
 | ||||
|                 gui->mainframe->load_config_file(load_configs.back()); | ||||
|             // If loading a 3MF file, the config is loaded from the last one.
 | ||||
|             if (! m_input_files.empty()) | ||||
|                 gui->plater()->load_files(m_input_files, true, true); | ||||
|             if (! m_extra_config.empty()) | ||||
|                 gui->mainframe->load_config(m_extra_config); | ||||
|         }); | ||||
|         int result = wxEntry(argc, argv); | ||||
|         //FIXME this is a workaround for the PrusaSlicer 2.1 release.
 | ||||
| 		_3DScene::destroy(); | ||||
|         return result; | ||||
| #else /* SLIC3R_GUI */ | ||||
| 		// No GUI support. Just print out a help.
 | ||||
| 		this->print_help(false); | ||||
| 		// If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
 | ||||
| 		return (argc == 0) ? 0 : 1; | ||||
|         // No GUI support. Just print out a help.
 | ||||
|         this->print_help(false); | ||||
|         // If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
 | ||||
|         return (argc == 0) ? 0 : 1; | ||||
| #endif /* SLIC3R_GUI */ | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| bool CLI::setup(int argc, char **argv) | ||||
| { | ||||
|     { | ||||
| 	    Slic3r::set_logging_level(1); | ||||
|         const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL"); | ||||
|         if (loglevel != nullptr) { | ||||
|             if (loglevel[0] >= '0' && loglevel[0] <= '9' && loglevel[1] == 0) | ||||
|  | @ -536,18 +565,18 @@ bool CLI::setup(int argc, char **argv) | |||
|     // If any option is unsupported, print usage and abort immediately.
 | ||||
|     t_config_option_keys opt_order; | ||||
|     if (! m_config.read_cli(argc, argv, &m_input_files, &opt_order)) { | ||||
| 		// Separate error message reported by the CLI parser from the help.
 | ||||
| 		boost::nowide::cerr << std::endl; | ||||
|         // Separate error message reported by the CLI parser from the help.
 | ||||
|         boost::nowide::cerr << std::endl; | ||||
|         this->print_help(); | ||||
| 		return false; | ||||
|         return false; | ||||
|     } | ||||
|     // Parse actions and transform options.
 | ||||
|     for (auto const &opt_key : opt_order) { | ||||
|         if (cli_actions_config_def.has(opt_key)) | ||||
|             m_actions.emplace_back(opt_key); | ||||
|         else if (cli_transform_config_def.has(opt_key)) | ||||
|             m_transforms.emplace_back(opt_key); | ||||
|     } | ||||
| 	// Parse actions and transform options.
 | ||||
| 	for (auto const &opt_key : opt_order) { | ||||
| 		if (cli_actions_config_def.has(opt_key)) | ||||
| 			m_actions.emplace_back(opt_key); | ||||
| 		else if (cli_transform_config_def.has(opt_key)) | ||||
| 			m_transforms.emplace_back(opt_key); | ||||
| 	} | ||||
| 
 | ||||
|     { | ||||
|         const ConfigOptionInt *opt_loglevel = m_config.opt<ConfigOptionInt>("loglevel"); | ||||
|  | @ -560,15 +589,15 @@ bool CLI::setup(int argc, char **argv) | |||
|         for (const std::pair<t_config_option_key, ConfigOptionDef> &optdef : *options) | ||||
|             m_config.optptr(optdef.first, true); | ||||
| 
 | ||||
| 	set_data_dir(m_config.opt_string("datadir")); | ||||
|     set_data_dir(m_config.opt_string("datadir")); | ||||
| 
 | ||||
| 	return true; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void CLI::print_help(bool include_print_options, PrinterTechnology printer_technology) const  | ||||
| void CLI::print_help(bool include_print_options, PrinterTechnology printer_technology) const | ||||
| { | ||||
|     boost::nowide::cout | ||||
| 		<< SLIC3R_BUILD_ID << " " << "based on Slic3r" | ||||
|         << SLIC3R_BUILD_ID << " " << "based on Slic3r" | ||||
| #ifdef SLIC3R_GUI | ||||
|         << " (with GUI support)" | ||||
| #else /* SLIC3R_GUI */ | ||||
|  | @ -576,24 +605,24 @@ void CLI::print_help(bool include_print_options, PrinterTechnology printer_techn | |||
| #endif /* SLIC3R_GUI */ | ||||
|         << std::endl | ||||
|         << "https://github.com/prusa3d/PrusaSlicer" << std::endl << std::endl | ||||
|         << "Usage: slic3r [ ACTIONS ] [ TRANSFORM ] [ OPTIONS ] [ file.stl ... ]" << std::endl | ||||
|         << "Usage: prusa-slicer [ ACTIONS ] [ TRANSFORM ] [ OPTIONS ] [ file.stl ... ]" << std::endl | ||||
|         << std::endl | ||||
|         << "Actions:" << std::endl; | ||||
|     cli_actions_config_def.print_cli_help(boost::nowide::cout, false); | ||||
|      | ||||
| 
 | ||||
|     boost::nowide::cout | ||||
|         << std::endl | ||||
|         << "Transform options:" << std::endl; | ||||
|         cli_transform_config_def.print_cli_help(boost::nowide::cout, false); | ||||
|      | ||||
| 
 | ||||
|     boost::nowide::cout | ||||
|         << std::endl | ||||
|         << "Other options:" << std::endl; | ||||
|         cli_misc_config_def.print_cli_help(boost::nowide::cout, false); | ||||
|      | ||||
| 
 | ||||
|     if (include_print_options) { | ||||
|         boost::nowide::cout << std::endl; | ||||
| 		print_config_def.print_cli_help(boost::nowide::cout, true, [printer_technology](const ConfigOptionDef &def) | ||||
|         print_config_def.print_cli_help(boost::nowide::cout, true, [printer_technology](const ConfigOptionDef &def) | ||||
|             { return printer_technology == ptAny || def.printer_technology == ptAny || printer_technology == def.printer_technology; }); | ||||
|     } else { | ||||
|         boost::nowide::cout | ||||
|  | @ -610,14 +639,14 @@ bool CLI::export_models(IO::ExportFormat format) | |||
|         switch (format) { | ||||
|             case IO::AMF: success = Slic3r::store_amf(path.c_str(), &model, nullptr); break; | ||||
|             case IO::OBJ: success = Slic3r::store_obj(path.c_str(), &model);          break; | ||||
| 			case IO::STL: success = Slic3r::store_stl(path.c_str(), &model, true);    break; | ||||
| 			case IO::TMF: success = Slic3r::store_3mf(path.c_str(), &model, nullptr); break; | ||||
|             case IO::STL: success = Slic3r::store_stl(path.c_str(), &model, true);    break; | ||||
|             case IO::TMF: success = Slic3r::store_3mf(path.c_str(), &model, nullptr); break; | ||||
|             default: assert(false); break; | ||||
|         } | ||||
|         if (success) | ||||
| 			std::cout << "File exported to " << path << std::endl; | ||||
|             std::cout << "File exported to " << path << std::endl; | ||||
|         else { | ||||
| 			std::cerr << "File export to " << path << " failed" << std::endl; | ||||
|             std::cerr << "File export to " << path << " failed" << std::endl; | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | @ -631,12 +660,12 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co | |||
|         case IO::AMF: ext = ".zip.amf"; break; | ||||
|         case IO::OBJ: ext = ".obj"; break; | ||||
|         case IO::STL: ext = ".stl"; break; | ||||
| 		case IO::TMF: ext = ".3mf"; break; | ||||
|         case IO::TMF: ext = ".3mf"; break; | ||||
|         default: assert(false); break; | ||||
|     }; | ||||
|     auto proposed_path = boost::filesystem::path(model.propose_export_file_name_and_path(ext)); | ||||
|     // use --output when available
 | ||||
| 	std::string cmdline_param = m_config.opt_string("output"); | ||||
|     std::string cmdline_param = m_config.opt_string("output"); | ||||
|     if (! cmdline_param.empty()) { | ||||
|         // if we were supplied a directory, use it and append our automatically generated filename
 | ||||
|         boost::filesystem::path cmdline_path(cmdline_param); | ||||
|  | @ -648,20 +677,20 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co | |||
|     return proposed_path.string(); | ||||
| } | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
| #if defined(_MSC_VER) || defined(__MINGW32__) | ||||
| extern "C" { | ||||
| 	__declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv) | ||||
| 	{ | ||||
| 		// Convert wchar_t arguments to UTF8.
 | ||||
| 		std::vector<std::string> 	argv_narrow; | ||||
| 		std::vector<char*>			argv_ptrs(argc + 1, nullptr); | ||||
| 		for (size_t i = 0; i < argc; ++ i) | ||||
| 			argv_narrow.emplace_back(boost::nowide::narrow(argv[i])); | ||||
| 		for (size_t i = 0; i < argc; ++ i) | ||||
| 			argv_ptrs[i] = const_cast<char*>(argv_narrow[i].data()); | ||||
| 		// Call the UTF8 main.
 | ||||
| 		return CLI().run(argc, argv_ptrs.data()); | ||||
| 	} | ||||
|     __declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv) | ||||
|     { | ||||
|         // Convert wchar_t arguments to UTF8.
 | ||||
|         std::vector<std::string> 	argv_narrow; | ||||
|         std::vector<char*>			argv_ptrs(argc + 1, nullptr); | ||||
|         for (size_t i = 0; i < argc; ++ i) | ||||
|             argv_narrow.emplace_back(boost::nowide::narrow(argv[i])); | ||||
|         for (size_t i = 0; i < argc; ++ i) | ||||
|             argv_ptrs[i] = const_cast<char*>(argv_narrow[i].data()); | ||||
|         // Call the UTF8 main.
 | ||||
|         return CLI().run(argc, argv_ptrs.data()); | ||||
|     } | ||||
| } | ||||
| #else /* _MSC_VER */ | ||||
| int main(int argc, char **argv) | ||||
|  |  | |||
|  | @ -8,17 +8,20 @@ | |||
| #include <wchar.h> | ||||
| 
 | ||||
| #ifdef SLIC3R_GUI | ||||
| 	// Let the NVIDIA and AMD know we want to use their graphics card
 | ||||
| 	// on a dual graphics card system.
 | ||||
| 	__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; | ||||
| 	__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; | ||||
| extern "C" | ||||
| { | ||||
|     // Let the NVIDIA and AMD know we want to use their graphics card
 | ||||
|     // on a dual graphics card system.
 | ||||
|     __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; | ||||
|     __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; | ||||
| } | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #ifdef SLIC3R_GUI | ||||
| 	#include <GL/GL.h> | ||||
|     #include <GL/GL.h> | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| #include <string> | ||||
|  | @ -33,97 +36,97 @@ | |||
| class OpenGLVersionCheck | ||||
| { | ||||
| public: | ||||
| 	std::string version; | ||||
| 	std::string glsl_version; | ||||
| 	std::string vendor; | ||||
| 	std::string renderer; | ||||
|     std::string version; | ||||
|     std::string glsl_version; | ||||
|     std::string vendor; | ||||
|     std::string renderer; | ||||
| 
 | ||||
| 	HINSTANCE   hOpenGL = nullptr; | ||||
| 	bool 		success = false; | ||||
|     HINSTANCE   hOpenGL = nullptr; | ||||
|     bool 		success = false; | ||||
| 
 | ||||
| 	bool load_opengl_dll() | ||||
| 	{ | ||||
| 	    MSG      msg     = {0}; | ||||
| 	    WNDCLASS wc      = {0};  | ||||
| 	    wc.lpfnWndProc   = OpenGLVersionCheck::supports_opengl2_wndproc; | ||||
| 	    wc.hInstance     = (HINSTANCE)GetModuleHandle(nullptr); | ||||
| 	    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); | ||||
| 	    wc.lpszClassName = L"PrusaSlicer_opengl_version_check"; | ||||
| 	    wc.style = CS_OWNDC; | ||||
| 	    if (RegisterClass(&wc)) { | ||||
| 			HWND hwnd = CreateWindowW(wc.lpszClassName, L"PrusaSlicer_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this); | ||||
| 			if (hwnd) { | ||||
| 				message_pump_exit = false; | ||||
| 			    while (GetMessage(&msg, NULL, 0, 0 ) > 0 && ! message_pump_exit) | ||||
| 			        DispatchMessage(&msg); | ||||
| 			} | ||||
| 		} | ||||
| 	    return this->success; | ||||
| 	} | ||||
|     bool load_opengl_dll() | ||||
|     { | ||||
|         MSG      msg     = {0}; | ||||
|         WNDCLASS wc      = {0}; | ||||
|         wc.lpfnWndProc   = OpenGLVersionCheck::supports_opengl2_wndproc; | ||||
|         wc.hInstance     = (HINSTANCE)GetModuleHandle(nullptr); | ||||
|         wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); | ||||
|         wc.lpszClassName = L"PrusaSlicer_opengl_version_check"; | ||||
|         wc.style = CS_OWNDC; | ||||
|         if (RegisterClass(&wc)) { | ||||
|             HWND hwnd = CreateWindowW(wc.lpszClassName, L"PrusaSlicer_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this); | ||||
|             if (hwnd) { | ||||
|                 message_pump_exit = false; | ||||
|                 while (GetMessage(&msg, NULL, 0, 0 ) > 0 && ! message_pump_exit) | ||||
|                     DispatchMessage(&msg); | ||||
|             } | ||||
|         } | ||||
|         return this->success; | ||||
|     } | ||||
| 
 | ||||
| 	void unload_opengl_dll()  | ||||
| 	{ | ||||
| 		if (this->hOpenGL) { | ||||
| 			BOOL released = FreeLibrary(this->hOpenGL); | ||||
| 			if (released) | ||||
| 				printf("System OpenGL library released\n"); | ||||
| 			else | ||||
| 				printf("System OpenGL library NOT released\n"); | ||||
| 			this->hOpenGL = nullptr; | ||||
| 		} | ||||
| 	} | ||||
|     void unload_opengl_dll() | ||||
|     { | ||||
|         if (this->hOpenGL) { | ||||
|             BOOL released = FreeLibrary(this->hOpenGL); | ||||
|             if (released) | ||||
|                 printf("System OpenGL library released\n"); | ||||
|             else | ||||
|                 printf("System OpenGL library NOT released\n"); | ||||
|             this->hOpenGL = nullptr; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const | ||||
| 	{ | ||||
| 		// printf("is_version_greater_or_equal_to, version: %s\n", version.c_str());
 | ||||
| 	    std::vector<std::string> tokens; | ||||
| 	    boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on); | ||||
| 	    if (tokens.empty()) | ||||
| 	        return false; | ||||
|     bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const | ||||
|     { | ||||
|         // printf("is_version_greater_or_equal_to, version: %s\n", version.c_str());
 | ||||
|         std::vector<std::string> tokens; | ||||
|         boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on); | ||||
|         if (tokens.empty()) | ||||
|             return false; | ||||
| 
 | ||||
| 	    std::vector<std::string> numbers; | ||||
| 	    boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); | ||||
|         std::vector<std::string> numbers; | ||||
|         boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); | ||||
| 
 | ||||
| 	    unsigned int gl_major = 0; | ||||
| 	    unsigned int gl_minor = 0; | ||||
| 	    if (numbers.size() > 0) | ||||
| 	        gl_major = ::atoi(numbers[0].c_str()); | ||||
| 	    if (numbers.size() > 1) | ||||
| 	        gl_minor = ::atoi(numbers[1].c_str()); | ||||
| 	    // printf("Major: %d, minor: %d\n", gl_major, gl_minor);
 | ||||
| 	    if (gl_major < major) | ||||
| 	        return false; | ||||
| 	    else if (gl_major > major) | ||||
| 	        return true; | ||||
| 	    else | ||||
| 	        return gl_minor >= minor; | ||||
| 	} | ||||
|         unsigned int gl_major = 0; | ||||
|         unsigned int gl_minor = 0; | ||||
|         if (numbers.size() > 0) | ||||
|             gl_major = ::atoi(numbers[0].c_str()); | ||||
|         if (numbers.size() > 1) | ||||
|             gl_minor = ::atoi(numbers[1].c_str()); | ||||
|         // printf("Major: %d, minor: %d\n", gl_major, gl_minor);
 | ||||
|         if (gl_major < major) | ||||
|             return false; | ||||
|         else if (gl_major > major) | ||||
|             return true; | ||||
|         else | ||||
|             return gl_minor >= minor; | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
| 	static bool message_pump_exit; | ||||
|     static bool message_pump_exit; | ||||
| 
 | ||||
| 	void check(HWND hWnd) | ||||
| 	{ | ||||
| 		hOpenGL = LoadLibraryExW(L"opengl32.dll", nullptr, 0); | ||||
| 		if (hOpenGL == nullptr) { | ||||
| 			printf("Failed loading the system opengl32.dll\n"); | ||||
| 			return; | ||||
| 		} | ||||
|     void check(HWND hWnd) | ||||
|     { | ||||
|         hOpenGL = LoadLibraryExW(L"opengl32.dll", nullptr, 0); | ||||
|         if (hOpenGL == nullptr) { | ||||
|             printf("Failed loading the system opengl32.dll\n"); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
| 		typedef HGLRC 		(WINAPI *Func_wglCreateContext)(HDC); | ||||
| 		typedef BOOL 		(WINAPI *Func_wglMakeCurrent  )(HDC, HGLRC); | ||||
| 		typedef BOOL     	(WINAPI *Func_wglDeleteContext)(HGLRC); | ||||
| 		typedef GLubyte* 	(WINAPI *Func_glGetString     )(GLenum); | ||||
|         typedef HGLRC 		(WINAPI *Func_wglCreateContext)(HDC); | ||||
|         typedef BOOL 		(WINAPI *Func_wglMakeCurrent  )(HDC, HGLRC); | ||||
|         typedef BOOL     	(WINAPI *Func_wglDeleteContext)(HGLRC); | ||||
|         typedef GLubyte* 	(WINAPI *Func_glGetString     )(GLenum); | ||||
| 
 | ||||
| 		Func_wglCreateContext 	wglCreateContext = (Func_wglCreateContext)GetProcAddress(hOpenGL, "wglCreateContext"); | ||||
| 		Func_wglMakeCurrent 	wglMakeCurrent 	 = (Func_wglMakeCurrent)  GetProcAddress(hOpenGL, "wglMakeCurrent"); | ||||
| 		Func_wglDeleteContext 	wglDeleteContext = (Func_wglDeleteContext)GetProcAddress(hOpenGL, "wglDeleteContext"); | ||||
| 		Func_glGetString 		glGetString 	 = (Func_glGetString)	  GetProcAddress(hOpenGL, "glGetString"); | ||||
|         Func_wglCreateContext 	wglCreateContext = (Func_wglCreateContext)GetProcAddress(hOpenGL, "wglCreateContext"); | ||||
|         Func_wglMakeCurrent 	wglMakeCurrent 	 = (Func_wglMakeCurrent)  GetProcAddress(hOpenGL, "wglMakeCurrent"); | ||||
|         Func_wglDeleteContext 	wglDeleteContext = (Func_wglDeleteContext)GetProcAddress(hOpenGL, "wglDeleteContext"); | ||||
|         Func_glGetString 		glGetString 	 = (Func_glGetString)	  GetProcAddress(hOpenGL, "glGetString"); | ||||
| 
 | ||||
| 		if (wglCreateContext == nullptr || wglMakeCurrent == nullptr || wglDeleteContext == nullptr || glGetString == nullptr) { | ||||
| 			printf("Failed loading the system opengl32.dll: The library is invalid.\n"); | ||||
| 			return; | ||||
| 		} | ||||
|         if (wglCreateContext == nullptr || wglMakeCurrent == nullptr || wglDeleteContext == nullptr || glGetString == nullptr) { | ||||
|             printf("Failed loading the system opengl32.dll: The library is invalid.\n"); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         PIXELFORMATDESCRIPTOR pfd = | ||||
|         { | ||||
|  | @ -146,152 +149,155 @@ protected: | |||
|         }; | ||||
| 
 | ||||
|         HDC ourWindowHandleToDeviceContext = ::GetDC(hWnd); | ||||
| 		// Gdi32.dll
 | ||||
|         int letWindowsChooseThisPixelFormat = ::ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd);  | ||||
| 		// Gdi32.dll
 | ||||
|         // Gdi32.dll
 | ||||
|         int letWindowsChooseThisPixelFormat = ::ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd); | ||||
|         // Gdi32.dll
 | ||||
|         SetPixelFormat(ourWindowHandleToDeviceContext, letWindowsChooseThisPixelFormat, &pfd); | ||||
| 		// Opengl32.dll
 | ||||
|         // Opengl32.dll
 | ||||
|         HGLRC glcontext = wglCreateContext(ourWindowHandleToDeviceContext); | ||||
|         wglMakeCurrent(ourWindowHandleToDeviceContext, glcontext); | ||||
|         // Opengl32.dll
 | ||||
| 	    const char *data = (const char*)glGetString(GL_VERSION); | ||||
| 	    if (data != nullptr) | ||||
| 	        this->version = data; | ||||
| 		// printf("check -version: %s\n", version.c_str());
 | ||||
| 		data = (const char*)glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION
 | ||||
|     	if (data != nullptr) | ||||
|         	this->glsl_version = data; | ||||
|     	data = (const char*)glGetString(GL_VENDOR); | ||||
|     	if (data != nullptr) | ||||
|         	this->vendor = data; | ||||
|     	data = (const char*)glGetString(GL_RENDERER); | ||||
|     	if (data != nullptr) | ||||
|         	this->renderer = data; | ||||
|         const char *data = (const char*)glGetString(GL_VERSION); | ||||
|         if (data != nullptr) | ||||
|             this->version = data; | ||||
|         // printf("check -version: %s\n", version.c_str());
 | ||||
|         data = (const char*)glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION
 | ||||
|         if (data != nullptr) | ||||
|             this->glsl_version = data; | ||||
|         data = (const char*)glGetString(GL_VENDOR); | ||||
|         if (data != nullptr) | ||||
|             this->vendor = data; | ||||
|         data = (const char*)glGetString(GL_RENDERER); | ||||
|         if (data != nullptr) | ||||
|             this->renderer = data; | ||||
|         // Opengl32.dll
 | ||||
|         wglDeleteContext(glcontext); | ||||
| 		::ReleaseDC(hWnd, ourWindowHandleToDeviceContext); | ||||
|         ::ReleaseDC(hWnd, ourWindowHandleToDeviceContext); | ||||
|         this->success = true; | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
| 	static LRESULT CALLBACK supports_opengl2_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | ||||
| 	{ | ||||
| 	    switch(message) | ||||
| 	    { | ||||
| 	    case WM_CREATE: | ||||
| 		{ | ||||
| 			CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam); | ||||
| 			OpenGLVersionCheck *ogl_data = reinterpret_cast<OpenGLVersionCheck*>(pCreate->lpCreateParams); | ||||
| 			ogl_data->check(hWnd); | ||||
| 			DestroyWindow(hWnd); | ||||
| 			return 0; | ||||
| 	    } | ||||
| 		case WM_NCDESTROY: | ||||
| 			message_pump_exit = true; | ||||
| 			return 0; | ||||
| 	    default: | ||||
| 	        return DefWindowProc(hWnd, message, wParam, lParam); | ||||
| 	    } | ||||
| 	} | ||||
|     static LRESULT CALLBACK supports_opengl2_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | ||||
|     { | ||||
|         switch(message) | ||||
|         { | ||||
|         case WM_CREATE: | ||||
|         { | ||||
|             CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam); | ||||
|             OpenGLVersionCheck *ogl_data = reinterpret_cast<OpenGLVersionCheck*>(pCreate->lpCreateParams); | ||||
|             ogl_data->check(hWnd); | ||||
|             DestroyWindow(hWnd); | ||||
|             return 0; | ||||
|         } | ||||
|         case WM_NCDESTROY: | ||||
|             message_pump_exit = true; | ||||
|             return 0; | ||||
|         default: | ||||
|             return DefWindowProc(hWnd, message, wParam, lParam); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| bool OpenGLVersionCheck::message_pump_exit = false; | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| extern "C" { | ||||
| 	typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv); | ||||
| 	Slic3rMainFunc slic3r_main = nullptr; | ||||
|     typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv); | ||||
|     Slic3rMainFunc slic3r_main = nullptr; | ||||
| } | ||||
| 
 | ||||
| extern "C" { | ||||
| 
 | ||||
| #ifdef SLIC3R_WRAPPER_NOCONSOLE | ||||
| int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */) | ||||
| { | ||||
| 	int 	  argc; | ||||
| 	wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); | ||||
|     int 	  argc; | ||||
|     wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); | ||||
| #else | ||||
| int wmain(int argc, wchar_t **argv) | ||||
| { | ||||
| #endif | ||||
| 
 | ||||
| 	std::vector<wchar_t*> argv_extended; | ||||
| 	argv_extended.emplace_back(argv[0]); | ||||
|     std::vector<wchar_t*> argv_extended; | ||||
|     argv_extended.emplace_back(argv[0]); | ||||
| 
 | ||||
| #ifdef SLIC3R_GUI | ||||
| 	// Here one may push some additional parameters based on the wrapper type.
 | ||||
| 	bool force_mesa = false; | ||||
|     // Here one may push some additional parameters based on the wrapper type.
 | ||||
|     bool force_mesa = false; | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 	for (int i = 1; i < argc; ++ i) { | ||||
|     for (int i = 1; i < argc; ++ i) { | ||||
| #ifdef SLIC3R_GUI | ||||
| 		if (wcscmp(argv[i], L"--sw-renderer") == 0) | ||||
| 			force_mesa = true; | ||||
| 		else if (wcscmp(argv[i], L"--no-sw-renderer") == 0) | ||||
| 			force_mesa = false; | ||||
|         if (wcscmp(argv[i], L"--sw-renderer") == 0) | ||||
|             force_mesa = true; | ||||
|         else if (wcscmp(argv[i], L"--no-sw-renderer") == 0) | ||||
|             force_mesa = false; | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 		argv_extended.emplace_back(argv[i]); | ||||
| 	} | ||||
| 	argv_extended.emplace_back(nullptr); | ||||
|         argv_extended.emplace_back(argv[i]); | ||||
|     } | ||||
|     argv_extended.emplace_back(nullptr); | ||||
| 
 | ||||
| #ifdef SLIC3R_GUI | ||||
| 	OpenGLVersionCheck opengl_version_check; | ||||
| 	bool load_mesa =  | ||||
| 		// Forced from the command line.
 | ||||
| 		force_mesa || | ||||
| 		// Running over a rempote desktop, and the RemoteFX is not enabled, therefore Windows will only provide SW OpenGL 1.1 context.
 | ||||
| 		// In that case, use Mesa.
 | ||||
| 		::GetSystemMetrics(SM_REMOTESESSION) || | ||||
| 		// Try to load the default OpenGL driver and test its context version.
 | ||||
| 		! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0); | ||||
|     OpenGLVersionCheck opengl_version_check; | ||||
|     bool load_mesa = | ||||
|         // Forced from the command line.
 | ||||
|         force_mesa || | ||||
|         // Running over a rempote desktop, and the RemoteFX is not enabled, therefore Windows will only provide SW OpenGL 1.1 context.
 | ||||
|         // In that case, use Mesa.
 | ||||
|         ::GetSystemMetrics(SM_REMOTESESSION) || | ||||
|         // Try to load the default OpenGL driver and test its context version.
 | ||||
|         ! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0); | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| 	wchar_t path_to_exe[MAX_PATH + 1] = { 0 }; | ||||
| 	::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH); | ||||
| 	wchar_t drive[_MAX_DRIVE]; | ||||
| 	wchar_t dir[_MAX_DIR]; | ||||
| 	wchar_t fname[_MAX_FNAME]; | ||||
| 	wchar_t ext[_MAX_EXT]; | ||||
| 	_wsplitpath(path_to_exe, drive, dir, fname, ext); | ||||
| 	_wmakepath(path_to_exe, drive, dir, nullptr, nullptr); | ||||
|     wchar_t path_to_exe[MAX_PATH + 1] = { 0 }; | ||||
|     ::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH); | ||||
|     wchar_t drive[_MAX_DRIVE]; | ||||
|     wchar_t dir[_MAX_DIR]; | ||||
|     wchar_t fname[_MAX_FNAME]; | ||||
|     wchar_t ext[_MAX_EXT]; | ||||
|     _wsplitpath(path_to_exe, drive, dir, fname, ext); | ||||
|     _wmakepath(path_to_exe, drive, dir, nullptr, nullptr); | ||||
| 
 | ||||
| #ifdef SLIC3R_GUI | ||||
| // https://wiki.qt.io/Cross_compiling_Mesa_for_Windows
 | ||||
| // http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/
 | ||||
| 	if (load_mesa) { | ||||
| 		opengl_version_check.unload_opengl_dll(); | ||||
| 		wchar_t path_to_mesa[MAX_PATH + 1] = { 0 }; | ||||
| 		wcscpy(path_to_mesa, path_to_exe); | ||||
| 		wcscat(path_to_mesa, L"mesa\\opengl32.dll"); | ||||
| 		printf("Loading MESA OpenGL library: %S\n", path_to_mesa); | ||||
| 		HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0); | ||||
| 		if (hInstance_OpenGL == nullptr) { | ||||
| 			printf("MESA OpenGL library was not loaded\n"); | ||||
| 		} else | ||||
| 			printf("MESA OpenGL library was loaded sucessfully\n");		 | ||||
| 	} | ||||
|     if (load_mesa) { | ||||
|         opengl_version_check.unload_opengl_dll(); | ||||
|         wchar_t path_to_mesa[MAX_PATH + 1] = { 0 }; | ||||
|         wcscpy(path_to_mesa, path_to_exe); | ||||
|         wcscat(path_to_mesa, L"mesa\\opengl32.dll"); | ||||
|         printf("Loading MESA OpenGL library: %S\n", path_to_mesa); | ||||
|         HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0); | ||||
|         if (hInstance_OpenGL == nullptr) { | ||||
|             printf("MESA OpenGL library was not loaded\n"); | ||||
|         } else | ||||
|             printf("MESA OpenGL library was loaded sucessfully\n"); | ||||
|     } | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| 
 | ||||
| 	wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 }; | ||||
| 	wcscpy(path_to_slic3r, path_to_exe); | ||||
| 	wcscat(path_to_slic3r, L"PrusaSlicer.dll"); | ||||
|     wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 }; | ||||
|     wcscpy(path_to_slic3r, path_to_exe); | ||||
|     wcscat(path_to_slic3r, L"PrusaSlicer.dll"); | ||||
| //	printf("Loading Slic3r library: %S\n", path_to_slic3r);
 | ||||
| 	HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0); | ||||
| 	if (hInstance_Slic3r == nullptr) { | ||||
| 		printf("PrusaSlicer.dll was not loaded\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
|     HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0); | ||||
|     if (hInstance_Slic3r == nullptr) { | ||||
|         printf("PrusaSlicer.dll was not loaded\n"); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
| 	// resolve function address here
 | ||||
| 	slic3r_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r,  | ||||
|     // resolve function address here
 | ||||
|     slic3r_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r, | ||||
| #ifdef _WIN64 | ||||
| 		// there is just a single calling conversion, therefore no mangling of the function name.
 | ||||
| 		"slic3r_main" | ||||
|         // there is just a single calling conversion, therefore no mangling of the function name.
 | ||||
|         "slic3r_main" | ||||
| #else	// stdcall calling convention declaration
 | ||||
| 		"_slic3r_main@8" | ||||
|         "_slic3r_main@8" | ||||
| #endif | ||||
| 		); | ||||
| 	if (slic3r_main == nullptr) { | ||||
| 		printf("could not locate the function slic3r_main in PrusaSlicer.dll\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	// argc minus the trailing nullptr of the argv
 | ||||
| 	return slic3r_main((int)argv_extended.size() - 1, argv_extended.data()); | ||||
|         ); | ||||
|     if (slic3r_main == nullptr) { | ||||
|         printf("could not locate the function slic3r_main in PrusaSlicer.dll\n"); | ||||
|         return -1; | ||||
|     } | ||||
|     // argc minus the trailing nullptr of the argv
 | ||||
|     return slic3r_main((int)argv_extended.size() - 1, argv_extended.data()); | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -11,4 +11,4 @@ add_library(admesh STATIC | |||
|     util.cpp | ||||
| ) | ||||
| 
 | ||||
| target_include_directories(admesh SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) | ||||
| target_link_libraries(admesh PRIVATE boost_headeronly) | ||||
|  |  | |||
|  | @ -25,271 +25,214 @@ | |||
| #include <string.h> | ||||
| #include <math.h> | ||||
| 
 | ||||
| // Boost pool: Don't use mutexes to synchronize memory allocation.
 | ||||
| #define BOOST_POOL_NO_MT | ||||
| #include <boost/pool/object_pool.hpp> | ||||
| 
 | ||||
| #include "stl.h" | ||||
| 
 | ||||
| static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag); | ||||
| static void reverse_facet(stl_file *stl, int facet_num) | ||||
| { | ||||
| 	++ stl->stats.facets_reversed; | ||||
| 
 | ||||
| static void | ||||
| stl_reverse_facet(stl_file *stl, int facet_num) { | ||||
|   stl_vertex tmp_vertex; | ||||
|   /*  int tmp_neighbor;*/ | ||||
|   int neighbor[3]; | ||||
|   int vnot[3]; | ||||
| 	int neighbor[3] = { stl->neighbors_start[facet_num].neighbor[0], stl->neighbors_start[facet_num].neighbor[1], stl->neighbors_start[facet_num].neighbor[2] }; | ||||
| 	int vnot[3] = { stl->neighbors_start[facet_num].which_vertex_not[0], stl->neighbors_start[facet_num].which_vertex_not[1], stl->neighbors_start[facet_num].which_vertex_not[2] }; | ||||
| 
 | ||||
|   stl->stats.facets_reversed += 1; | ||||
| 	// reverse the facet
 | ||||
| 	stl_vertex tmp_vertex = stl->facet_start[facet_num].vertex[0]; | ||||
| 	stl->facet_start[facet_num].vertex[0] = stl->facet_start[facet_num].vertex[1]; | ||||
| 	stl->facet_start[facet_num].vertex[1] = tmp_vertex; | ||||
| 
 | ||||
|   neighbor[0] = stl->neighbors_start[facet_num].neighbor[0]; | ||||
|   neighbor[1] = stl->neighbors_start[facet_num].neighbor[1]; | ||||
|   neighbor[2] = stl->neighbors_start[facet_num].neighbor[2]; | ||||
|   vnot[0] = stl->neighbors_start[facet_num].which_vertex_not[0]; | ||||
|   vnot[1] = stl->neighbors_start[facet_num].which_vertex_not[1]; | ||||
|   vnot[2] = stl->neighbors_start[facet_num].which_vertex_not[2]; | ||||
| 	// fix the vnots of the neighboring facets
 | ||||
| 	if (neighbor[0] != -1) | ||||
| 		stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] = (stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] + 3) % 6; | ||||
| 	if (neighbor[1] != -1) | ||||
| 		stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] = (stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] + 4) % 6; | ||||
| 	if (neighbor[2] != -1) | ||||
| 		stl->neighbors_start[neighbor[2]].which_vertex_not[(vnot[2] + 1) % 3] = (stl->neighbors_start[neighbor[2]].which_vertex_not[(vnot[2] + 1) % 3] + 2) % 6; | ||||
| 
 | ||||
|   /* reverse the facet */ | ||||
|   tmp_vertex = stl->facet_start[facet_num].vertex[0]; | ||||
|   stl->facet_start[facet_num].vertex[0] = | ||||
|     stl->facet_start[facet_num].vertex[1]; | ||||
|   stl->facet_start[facet_num].vertex[1] = tmp_vertex; | ||||
| 	// swap the neighbors of the facet that is being reversed
 | ||||
| 	stl->neighbors_start[facet_num].neighbor[1] = neighbor[2]; | ||||
| 	stl->neighbors_start[facet_num].neighbor[2] = neighbor[1]; | ||||
| 
 | ||||
|   /* fix the vnots of the neighboring facets */ | ||||
|   if(neighbor[0] != -1) | ||||
|     stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] = | ||||
|       (stl->neighbors_start[neighbor[0]]. | ||||
|        which_vertex_not[(vnot[0] + 1) % 3] + 3) % 6; | ||||
|   if(neighbor[1] != -1) | ||||
|     stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] = | ||||
|       (stl->neighbors_start[neighbor[1]]. | ||||
|        which_vertex_not[(vnot[1] + 1) % 3] + 4) % 6; | ||||
|   if(neighbor[2] != -1) | ||||
|     stl->neighbors_start[neighbor[2]].which_vertex_not[(vnot[2] + 1) % 3] = | ||||
|       (stl->neighbors_start[neighbor[2]]. | ||||
|        which_vertex_not[(vnot[2] + 1) % 3] + 2) % 6; | ||||
| 	// swap the vnots of the facet that is being reversed 
 | ||||
| 	stl->neighbors_start[facet_num].which_vertex_not[1] = vnot[2]; | ||||
| 	stl->neighbors_start[facet_num].which_vertex_not[2] = vnot[1]; | ||||
| 
 | ||||
|   /* swap the neighbors of the facet that is being reversed */ | ||||
|   stl->neighbors_start[facet_num].neighbor[1] = neighbor[2]; | ||||
|   stl->neighbors_start[facet_num].neighbor[2] = neighbor[1]; | ||||
| 
 | ||||
|   /* swap the vnots of the facet that is being reversed */ | ||||
|   stl->neighbors_start[facet_num].which_vertex_not[1] = vnot[2]; | ||||
|   stl->neighbors_start[facet_num].which_vertex_not[2] = vnot[1]; | ||||
| 
 | ||||
|   /* reverse the values of the vnots of the facet that is being reversed */ | ||||
|   stl->neighbors_start[facet_num].which_vertex_not[0] = | ||||
|     (stl->neighbors_start[facet_num].which_vertex_not[0] + 3) % 6; | ||||
|   stl->neighbors_start[facet_num].which_vertex_not[1] = | ||||
|     (stl->neighbors_start[facet_num].which_vertex_not[1] + 3) % 6; | ||||
|   stl->neighbors_start[facet_num].which_vertex_not[2] = | ||||
|     (stl->neighbors_start[facet_num].which_vertex_not[2] + 3) % 6; | ||||
| 	// reverse the values of the vnots of the facet that is being reversed
 | ||||
| 	stl->neighbors_start[facet_num].which_vertex_not[0] = (stl->neighbors_start[facet_num].which_vertex_not[0] + 3) % 6; | ||||
| 	stl->neighbors_start[facet_num].which_vertex_not[1] = (stl->neighbors_start[facet_num].which_vertex_not[1] + 3) % 6; | ||||
| 	stl->neighbors_start[facet_num].which_vertex_not[2] = (stl->neighbors_start[facet_num].which_vertex_not[2] + 3) % 6; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_fix_normal_directions(stl_file *stl) { | ||||
|   char *norm_sw; | ||||
|   /*  int edge_num;*/ | ||||
|   /*  int vnot;*/ | ||||
|   int checked = 0; | ||||
|   int facet_num; | ||||
|   /*  int next_facet;*/ | ||||
|   int i; | ||||
|   int j; | ||||
|   struct stl_normal { | ||||
|     int               facet_num; | ||||
|     struct stl_normal *next; | ||||
|   }; | ||||
|   struct stl_normal *head; | ||||
|   struct stl_normal *tail; | ||||
|   struct stl_normal *newn; | ||||
|   struct stl_normal *temp; | ||||
| // Returns true if the normal was flipped.
 | ||||
| static bool check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) | ||||
| { | ||||
| 	stl_facet *facet = &stl->facet_start[facet_num]; | ||||
| 
 | ||||
|   int* reversed_ids; | ||||
|   int reversed_count = 0; | ||||
|   int id; | ||||
|   int force_exit = 0; | ||||
| 	stl_normal normal; | ||||
| 	stl_calculate_normal(normal, facet); | ||||
| 	stl_normalize_vector(normal); | ||||
| 	stl_normal normal_dif = (normal - facet->normal).cwiseAbs(); | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 	const float eps = 0.001f; | ||||
| 	if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { | ||||
| 		// Normal is within tolerance. It is not really necessary to change the values here, but just for consistency, I will.
 | ||||
| 		facet->normal = normal; | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
|   // this may happen for malformed models, see: https://github.com/prusa3d/PrusaSlicer/issues/2209
 | ||||
|   if (stl->stats.number_of_facets == 0) return; | ||||
| 	stl_normal test_norm = facet->normal; | ||||
| 	stl_normalize_vector(test_norm); | ||||
| 	normal_dif = (normal - test_norm).cwiseAbs(); | ||||
| 	if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { | ||||
| 		// The normal is not within tolerance, but direction is OK.
 | ||||
| 		if (normal_fix_flag) { | ||||
| 	  		facet->normal = normal; | ||||
| 	  		++ stl->stats.normals_fixed; | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
|   /* Initialize linked list. */ | ||||
|   head = (struct stl_normal*)malloc(sizeof(struct stl_normal)); | ||||
|   if(head == NULL) perror("stl_fix_normal_directions"); | ||||
|   tail = (struct stl_normal*)malloc(sizeof(struct stl_normal)); | ||||
|   if(tail == NULL) perror("stl_fix_normal_directions"); | ||||
|   head->next = tail; | ||||
|   tail->next = tail; | ||||
| 
 | ||||
|   /* Initialize list that keeps track of already fixed facets. */ | ||||
|   norm_sw = (char*)calloc(stl->stats.number_of_facets, sizeof(char)); | ||||
|   if(norm_sw == NULL) perror("stl_fix_normal_directions"); | ||||
| 
 | ||||
|   /* Initialize list that keeps track of reversed facets. */ | ||||
|   reversed_ids = (int*)calloc(stl->stats.number_of_facets, sizeof(int)); | ||||
|   if (reversed_ids == NULL) perror("stl_fix_normal_directions reversed_ids"); | ||||
| 
 | ||||
|   facet_num = 0; | ||||
|   /* If normal vector is not within tolerance and backwards:
 | ||||
|      Arbitrarily starts at face 0.  If this one is wrong, we're screwed.  Thankfully, the chances | ||||
|      of it being wrong randomly are low if most of the triangles are right: */ | ||||
|   if (stl_check_normal_vector(stl, 0, 0) == 2) { | ||||
|       stl_reverse_facet(stl, 0); | ||||
|       reversed_ids[reversed_count++] = 0; | ||||
|   } | ||||
| 
 | ||||
|   /* Say that we've fixed this facet: */ | ||||
|   norm_sw[facet_num] = 1; | ||||
|   checked++; | ||||
| 
 | ||||
|   for(;;) { | ||||
|     /* Add neighbors_to_list.
 | ||||
|        Add unconnected neighbors to the list:a  */ | ||||
|     for(j = 0; j < 3; j++) { | ||||
|       /* Reverse the neighboring facets if necessary. */ | ||||
|       if(stl->neighbors_start[facet_num].which_vertex_not[j] > 2) { | ||||
|         /* If the facet has a neighbor that is -1, it means that edge isn't shared by another facet */ | ||||
|         if(stl->neighbors_start[facet_num].neighbor[j] != -1) { | ||||
|             if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] == 1) { | ||||
|                 /* trying to modify a facet already marked as fixed, revert all changes made until now and exit (fixes: #716, #574, #413, #269, #262, #259, #230, #228, #206) */ | ||||
|                 for (id = reversed_count - 1; id >= 0; --id) { | ||||
|                     stl_reverse_facet(stl, reversed_ids[id]); | ||||
|                 } | ||||
|                 force_exit = 1; | ||||
|                 break; | ||||
|             } else { | ||||
|                 stl_reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]); | ||||
|                 reversed_ids[reversed_count++] = stl->neighbors_start[facet_num].neighbor[j]; | ||||
|             } | ||||
|         } | ||||
|       } | ||||
|       /* If this edge of the facet is connected: */ | ||||
|       if(stl->neighbors_start[facet_num].neighbor[j] != -1) { | ||||
|         /* If we haven't fixed this facet yet, add it to the list: */ | ||||
|         if(norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) { | ||||
|           /* Add node to beginning of list. */ | ||||
|           newn = (struct stl_normal*)malloc(sizeof(struct stl_normal)); | ||||
|           if(newn == NULL) perror("stl_fix_normal_directions"); | ||||
|           newn->facet_num = stl->neighbors_start[facet_num].neighbor[j]; | ||||
|           newn->next = head->next; | ||||
|           head->next = newn; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     /* an error occourred, quit the for loop and exit */ | ||||
|     if (force_exit) break; | ||||
| 
 | ||||
|     /* Get next facet to fix from top of list. */ | ||||
|     if(head->next != tail) { | ||||
|       facet_num = head->next->facet_num; | ||||
|       if(norm_sw[facet_num] != 1) { /* If facet is in list mutiple times */ | ||||
|         norm_sw[facet_num] = 1; /* Record this one as being fixed. */ | ||||
|         checked++; | ||||
|       } | ||||
|       temp = head->next;	/* Delete this facet from the list. */ | ||||
|       head->next = head->next->next; | ||||
|       free(temp); | ||||
|     } else { /* if we ran out of facets to fix: */ | ||||
|       /* All of the facets in this part have been fixed. */ | ||||
|       stl->stats.number_of_parts += 1; | ||||
|       if(checked >= stl->stats.number_of_facets) { | ||||
|         /* All of the facets have been checked.  Bail out. */ | ||||
|         break; | ||||
|       } else { | ||||
|         /* There is another part here.  Find it and continue. */ | ||||
|         for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|           if(norm_sw[i] == 0) { | ||||
|             /* This is the first facet of the next part. */ | ||||
|             facet_num = i; | ||||
|             if(stl_check_normal_vector(stl, i, 0) == 2) { | ||||
|                 stl_reverse_facet(stl, i); | ||||
|                 reversed_ids[reversed_count++] = i; | ||||
|             } | ||||
| 
 | ||||
|             norm_sw[facet_num] = 1; | ||||
|             checked++; | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   free(head); | ||||
|   free(tail); | ||||
|   free(reversed_ids); | ||||
|   free(norm_sw); | ||||
| 	test_norm *= -1.f; | ||||
| 	normal_dif = (normal - test_norm).cwiseAbs(); | ||||
| 	if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { | ||||
| 		// The normal is not within tolerance and backwards.
 | ||||
| 		if (normal_fix_flag) { | ||||
| 	  		facet->normal = normal; | ||||
| 	  		++ stl->stats.normals_fixed; | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
| 	if (normal_fix_flag) { | ||||
| 		facet->normal = normal; | ||||
| 		++ stl->stats.normals_fixed; | ||||
| 	} | ||||
| 	// Status is unknown.
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) { | ||||
|   /* Returns 0 if the normal is within tolerance */ | ||||
|   /* Returns 1 if the normal is not within tolerance, but direction is OK */ | ||||
|   /* Returns 2 if the normal is not within tolerance and backwards */ | ||||
|   /* Returns 4 if the status is unknown. */ | ||||
| void stl_fix_normal_directions(stl_file *stl) | ||||
| { | ||||
|  	// This may happen for malformed models, see: https://github.com/prusa3d/PrusaSlicer/issues/2209
 | ||||
|   	if (stl->stats.number_of_facets == 0) | ||||
|   		return; | ||||
| 
 | ||||
|   stl_facet *facet; | ||||
| 	struct stl_normal { | ||||
|     	int         facet_num; | ||||
|     	stl_normal *next; | ||||
|   	}; | ||||
| 
 | ||||
|   facet = &stl->facet_start[facet_num]; | ||||
|   	// Initialize linked list.
 | ||||
|   	boost::object_pool<stl_normal> pool; | ||||
|    	stl_normal *head = pool.construct(); | ||||
|   	stl_normal *tail = pool.construct(); | ||||
| 	head->next = tail; | ||||
| 	tail->next = tail; | ||||
| 
 | ||||
|   stl_normal normal; | ||||
|   stl_calculate_normal(normal, facet); | ||||
|   stl_normalize_vector(normal); | ||||
|   stl_normal normal_dif = (normal - facet->normal).cwiseAbs(); | ||||
| 	// Initialize list that keeps track of already fixed facets.
 | ||||
| 	std::vector<char> norm_sw(stl->stats.number_of_facets, 0); | ||||
| 	// Initialize list that keeps track of reversed facets.
 | ||||
| 	std::vector<int>  reversed_ids(stl->stats.number_of_facets, 0); | ||||
| 
 | ||||
|   const float eps = 0.001f; | ||||
|   if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { | ||||
|     /* It is not really necessary to change the values here */ | ||||
|     /* but just for consistency, I will. */ | ||||
|     facet->normal = normal; | ||||
|     return 0; | ||||
|   } | ||||
|   	int facet_num = 0; | ||||
|   	int reversed_count = 0; | ||||
|   	// If normal vector is not within tolerance and backwards:
 | ||||
|     // Arbitrarily starts at face 0.  If this one is wrong, we're screwed. Thankfully, the chances
 | ||||
|     // of it being wrong randomly are low if most of the triangles are right:
 | ||||
|   	if (check_normal_vector(stl, 0, 0)) { | ||||
|     	reverse_facet(stl, 0); | ||||
|       	reversed_ids[reversed_count ++] = 0; | ||||
|   	} | ||||
| 
 | ||||
|   stl_normal test_norm = facet->normal; | ||||
|   stl_normalize_vector(test_norm); | ||||
|   normal_dif = (normal - test_norm).cwiseAbs(); | ||||
|   if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { | ||||
|     if(normal_fix_flag) { | ||||
|       facet->normal = normal; | ||||
|       stl->stats.normals_fixed += 1; | ||||
|     } | ||||
|     return 1; | ||||
|   } | ||||
|   	// Say that we've fixed this facet:
 | ||||
|   	norm_sw[facet_num] = 1; | ||||
| 	int checked = 1; | ||||
| 
 | ||||
|   test_norm *= -1.f; | ||||
|   normal_dif = (normal - test_norm).cwiseAbs(); | ||||
|   if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) { | ||||
|     // Facet is backwards.
 | ||||
|     if(normal_fix_flag) { | ||||
|       facet->normal = normal; | ||||
|       stl->stats.normals_fixed += 1; | ||||
|     } | ||||
|     return 2; | ||||
|   } | ||||
|   if(normal_fix_flag) { | ||||
|     facet->normal = normal; | ||||
|     stl->stats.normals_fixed += 1; | ||||
|   } | ||||
|   return 4; | ||||
|   	for (;;) { | ||||
|     	// Add neighbors_to_list. Add unconnected neighbors to the list.
 | ||||
|     	bool force_exit = false; | ||||
|     	for (int j = 0; j < 3; ++ j) { | ||||
|       		// Reverse the neighboring facets if necessary.
 | ||||
|       		if (stl->neighbors_start[facet_num].which_vertex_not[j] > 2) { | ||||
|         		// If the facet has a neighbor that is -1, it means that edge isn't shared by another facet
 | ||||
|         		if (stl->neighbors_start[facet_num].neighbor[j] != -1) { | ||||
|             		if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] == 1) { | ||||
|                 		// trying to modify a facet already marked as fixed, revert all changes made until now and exit (fixes: #716, #574, #413, #269, #262, #259, #230, #228, #206)
 | ||||
|                 		for (int id = reversed_count - 1; id >= 0; -- id) | ||||
|                     		reverse_facet(stl, reversed_ids[id]); | ||||
|                 		force_exit = true; | ||||
|                 		break; | ||||
|             		} | ||||
|             		reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]); | ||||
|             		reversed_ids[reversed_count ++] = stl->neighbors_start[facet_num].neighbor[j]; | ||||
|         		} | ||||
|       		} | ||||
|       		// If this edge of the facet is connected:
 | ||||
|       		if (stl->neighbors_start[facet_num].neighbor[j] != -1) { | ||||
|         		// If we haven't fixed this facet yet, add it to the list:
 | ||||
|         		if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) { | ||||
| 	          		// Add node to beginning of list.
 | ||||
| 	          		stl_normal *newn = pool.construct(); | ||||
| 	          		newn->facet_num = stl->neighbors_start[facet_num].neighbor[j]; | ||||
| 	          		newn->next = head->next; | ||||
| 	          		head->next = newn; | ||||
| 	        	} | ||||
| 	      	} | ||||
| 	    } | ||||
| 
 | ||||
|     	// an error occourred, quit the for loop and exit
 | ||||
|     	if (force_exit) | ||||
|     		break; | ||||
| 
 | ||||
|     	// Get next facet to fix from top of list.
 | ||||
|     	if (head->next != tail) { | ||||
|       		facet_num = head->next->facet_num; | ||||
|       		if (norm_sw[facet_num] != 1) { // If facet is in list mutiple times
 | ||||
|         		norm_sw[facet_num] = 1; // Record this one as being fixed.
 | ||||
|         		++ checked; | ||||
|       		} | ||||
|       		stl_normal *temp = head->next;	// Delete this facet from the list.
 | ||||
|       		head->next = head->next->next; | ||||
|       		// pool.destroy(temp);
 | ||||
|     	} else { // If we ran out of facets to fix: All of the facets in this part have been fixed.
 | ||||
|       		++ stl->stats.number_of_parts; | ||||
|       		if (checked >= stl->stats.number_of_facets) | ||||
|         		// All of the facets have been checked.  Bail out.
 | ||||
|         		break; | ||||
|     		// There is another part here.  Find it and continue.
 | ||||
|     		for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|       			if (norm_sw[i] == 0) { | ||||
|         			// This is the first facet of the next part.
 | ||||
|         			facet_num = i; | ||||
|         			if (check_normal_vector(stl, i, 0)) { | ||||
|             			reverse_facet(stl, i); | ||||
|             			reversed_ids[reversed_count++] = i; | ||||
|         			} | ||||
|         			norm_sw[facet_num] = 1; | ||||
|         			++ checked; | ||||
|         			break; | ||||
|       			} | ||||
|     	} | ||||
|   	} | ||||
| 
 | ||||
| 	// pool.destroy(head);
 | ||||
| 	// pool.destroy(tail);
 | ||||
| } | ||||
| 
 | ||||
| void stl_fix_normal_values(stl_file *stl) { | ||||
|   int i; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     stl_check_normal_vector(stl, i, 1); | ||||
|   } | ||||
| void stl_fix_normal_values(stl_file *stl) | ||||
| { | ||||
| 	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     	check_normal_vector(stl, i, 1); | ||||
| } | ||||
| 
 | ||||
| void stl_reverse_all_facets(stl_file *stl) | ||||
| { | ||||
|   if (stl->error) | ||||
|   	return; | ||||
| 
 | ||||
|   stl_normal normal; | ||||
|   for(int i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     stl_reverse_facet(stl, i); | ||||
|     stl_calculate_normal(normal, &stl->facet_start[i]); | ||||
|     stl_normalize_vector(normal); | ||||
|     stl->facet_start[i].normal = normal; | ||||
|   } | ||||
| 	stl_normal normal; | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|     	reverse_facet(stl, i); | ||||
|     	stl_calculate_normal(normal, &stl->facet_start[i]); | ||||
|     	stl_normalize_vector(normal); | ||||
|     	stl->facet_start[i].normal = normal; | ||||
|   	} | ||||
| } | ||||
|  |  | |||
|  | @ -23,242 +23,237 @@ | |||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include <vector> | ||||
| 
 | ||||
| #include <boost/log/trivial.hpp> | ||||
| #include <boost/nowide/cstdio.hpp> | ||||
| 
 | ||||
| #include "stl.h" | ||||
| 
 | ||||
| void | ||||
| stl_invalidate_shared_vertices(stl_file *stl) { | ||||
|   if (stl->error) return; | ||||
| void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its) | ||||
| { | ||||
| 	// 3 indices to vertex per face
 | ||||
| 	its.indices.assign(stl->stats.number_of_facets, stl_triangle_vertex_indices(-1, -1, -1)); | ||||
| 	// Shared vertices (3D coordinates)
 | ||||
| 	its.vertices.clear(); | ||||
| 	its.vertices.reserve(stl->stats.number_of_facets / 2); | ||||
| 
 | ||||
|   if (stl->v_indices != NULL) { | ||||
|     free(stl->v_indices); | ||||
|     stl->v_indices = NULL; | ||||
|   } | ||||
|   if (stl->v_shared != NULL) { | ||||
|     free(stl->v_shared); | ||||
|     stl->v_shared = NULL; | ||||
|   } | ||||
| 	// A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop
 | ||||
| 	// while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal
 | ||||
| 	// are marked with a unique fan_traversal_stamp.
 | ||||
| 	unsigned int			  fan_traversal_stamp = 0; | ||||
| 	std::vector<unsigned int> fan_traversal_facet_visited(stl->stats.number_of_facets, 0); | ||||
| 
 | ||||
| 	for (uint32_t facet_idx = 0; facet_idx < stl->stats.number_of_facets; ++ facet_idx) { | ||||
| 		for (int j = 0; j < 3; ++ j) { | ||||
| 			if (its.indices[facet_idx][j] != -1) | ||||
| 				// Shared vertex was already assigned.
 | ||||
| 				continue; | ||||
| 			// Create a new shared vertex.
 | ||||
| 			its.vertices.emplace_back(stl->facet_start[facet_idx].vertex[j]); | ||||
| 			// Traverse the fan around the j-th vertex of the i-th face, assign the newly created shared vertex index to all the neighboring triangles in the triangle fan.
 | ||||
| 			int  facet_in_fan_idx 	= facet_idx; | ||||
| 			bool edge_direction 	= false; | ||||
| 			bool traversal_reversed = false; | ||||
| 			int  vnot      			= (j + 2) % 3; | ||||
| 			// Increase the 
 | ||||
| 			++ fan_traversal_stamp; | ||||
| 			for (;;) { | ||||
| 				// Next edge on facet_in_fan_idx to be traversed. The edge is indexed by its starting vertex index.
 | ||||
| 				int next_edge    = 0; | ||||
| 				// Vertex index in facet_in_fan_idx, which is being pivoted around, and which is being assigned a new shared vertex.
 | ||||
| 				int pivot_vertex = 0; | ||||
| 				if (vnot > 2) { | ||||
| 					// The edge of facet_in_fan_idx opposite to vnot is equally oriented, therefore
 | ||||
| 					// the neighboring facet is flipped.
 | ||||
| 			  		if (! edge_direction) { | ||||
| 			    		pivot_vertex = (vnot + 2) % 3; | ||||
| 			    		next_edge    = pivot_vertex;			    		 | ||||
| 			  		} else { | ||||
| 			    		pivot_vertex = (vnot + 1) % 3; | ||||
| 			    		next_edge    = vnot % 3; | ||||
| 			  		} | ||||
| 			  		edge_direction = ! edge_direction; | ||||
| 				} else { | ||||
| 					// The neighboring facet is correctly oriented.
 | ||||
| 			  		if (! edge_direction) { | ||||
| 			    		pivot_vertex = (vnot + 1) % 3; | ||||
| 			    		next_edge    = vnot; | ||||
| 			  		} else { | ||||
| 			    		pivot_vertex = (vnot + 2) % 3; | ||||
| 			    		next_edge    = pivot_vertex; | ||||
| 			  		} | ||||
| 				} | ||||
| 				its.indices[facet_in_fan_idx][pivot_vertex] = its.vertices.size() - 1; | ||||
| 				fan_traversal_facet_visited[facet_in_fan_idx] = fan_traversal_stamp; | ||||
| 
 | ||||
| 				// next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
 | ||||
| 				int next_facet = stl->neighbors_start[facet_in_fan_idx].neighbor[next_edge]; | ||||
| 				if (next_facet == -1) { | ||||
| 					// No neighbor going in the current direction.
 | ||||
| 					if (traversal_reversed) { | ||||
| 						// Went to one limit, then turned back and reached the other limit. Quit the fan traversal.
 | ||||
| 					    break; | ||||
| 					} else { | ||||
| 						// Reached the first limit. Now try to reverse and traverse up to the other limit.
 | ||||
| 					    edge_direction        = true; | ||||
| 					    vnot 	         	  = (j + 1) % 3; | ||||
| 					    traversal_reversed    = true; | ||||
| 				    	facet_in_fan_idx      = facet_idx; | ||||
| 					} | ||||
| 				} else if (next_facet == facet_idx) { | ||||
| 					// Traversed a closed fan all around.
 | ||||
| //					assert(! traversal_reversed);
 | ||||
| 					break; | ||||
| 				} else if (next_facet >= (int)stl->stats.number_of_facets) { | ||||
| 					// The mesh is not valid!
 | ||||
| 					// assert(false);
 | ||||
| 					break; | ||||
| 				} else if (fan_traversal_facet_visited[next_facet] == fan_traversal_stamp) { | ||||
| 					// Traversed a closed fan all around, but did not reach the starting face.
 | ||||
| 					// This indicates an invalid geometry (non-manifold).
 | ||||
| 					//assert(false);
 | ||||
| 					break; | ||||
| 				} else { | ||||
| 					// Continue traversal.
 | ||||
| 					// next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
 | ||||
| 					vnot = stl->neighbors_start[facet_in_fan_idx].which_vertex_not[next_edge]; | ||||
| 					facet_in_fan_idx = next_facet; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_generate_shared_vertices(stl_file *stl) { | ||||
|   int i; | ||||
|   int j; | ||||
|   int first_facet; | ||||
|   int direction; | ||||
|   int facet_num; | ||||
|   int vnot; | ||||
|   int next_edge; | ||||
|   int pivot_vertex; | ||||
|   int next_facet; | ||||
|   int reversed; | ||||
| bool its_write_off(const indexed_triangle_set &its, const char *file) | ||||
| { | ||||
| 	/* Open the file */ | ||||
| 	FILE *fp = boost::nowide::fopen(file, "w"); | ||||
| 	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing"; | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 	fprintf(fp, "OFF\n"); | ||||
| 	fprintf(fp, "%d %d 0\n", (int)its.vertices.size(), (int)its.indices.size()); | ||||
| 	for (int i = 0; i < its.vertices.size(); ++ i) | ||||
| 		fprintf(fp, "\t%f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2)); | ||||
| 	for (uint32_t i = 0; i < its.indices.size(); ++ i) | ||||
| 		fprintf(fp, "\t3 %d %d %d\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]); | ||||
| 	fclose(fp); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
|   /* make sure this function is idempotent and does not leak memory */ | ||||
|   stl_invalidate_shared_vertices(stl); | ||||
| bool its_write_vrml(const indexed_triangle_set &its, const char *file) | ||||
| { | ||||
| 	/* Open the file */ | ||||
|   	FILE *fp = boost::nowide::fopen(file, "w"); | ||||
| 	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_write_vrml: Couldn't open " << file << " for writing"; | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
|   stl->v_indices = (v_indices_struct*) | ||||
|                    calloc(stl->stats.number_of_facets, sizeof(v_indices_struct)); | ||||
|   if(stl->v_indices == NULL) perror("stl_generate_shared_vertices"); | ||||
|   stl->v_shared = (stl_vertex*) | ||||
|                   calloc((stl->stats.number_of_facets / 2), sizeof(stl_vertex)); | ||||
|   if(stl->v_shared == NULL) perror("stl_generate_shared_vertices"); | ||||
|   stl->stats.shared_malloced = stl->stats.number_of_facets / 2; | ||||
|   stl->stats.shared_vertices = 0; | ||||
| 	fprintf(fp, "#VRML V1.0 ascii\n\n"); | ||||
| 	fprintf(fp, "Separator {\n"); | ||||
| 	fprintf(fp, "\tDEF STLShape ShapeHints {\n"); | ||||
| 	fprintf(fp, "\t\tvertexOrdering COUNTERCLOCKWISE\n"); | ||||
| 	fprintf(fp, "\t\tfaceType CONVEX\n"); | ||||
| 	fprintf(fp, "\t\tshapeType SOLID\n"); | ||||
| 	fprintf(fp, "\t\tcreaseAngle 0.0\n"); | ||||
| 	fprintf(fp, "\t}\n"); | ||||
| 	fprintf(fp, "\tDEF STLModel Separator {\n"); | ||||
| 	fprintf(fp, "\t\tDEF STLColor Material {\n"); | ||||
| 	fprintf(fp, "\t\t\temissiveColor 0.700000 0.700000 0.000000\n"); | ||||
| 	fprintf(fp, "\t\t}\n"); | ||||
| 	fprintf(fp, "\t\tDEF STLVertices Coordinate3 {\n"); | ||||
| 	fprintf(fp, "\t\t\tpoint [\n"); | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     stl->v_indices[i].vertex[0] = -1; | ||||
|     stl->v_indices[i].vertex[1] = -1; | ||||
|     stl->v_indices[i].vertex[2] = -1; | ||||
|   } | ||||
| 	int i = 0; | ||||
| 	for (; i + 1 < its.vertices.size(); ++ i) | ||||
| 		fprintf(fp, "\t\t\t\t%f %f %f,\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2)); | ||||
| 	fprintf(fp, "\t\t\t\t%f %f %f]\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2)); | ||||
| 	fprintf(fp, "\t\t}\n"); | ||||
| 	fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n"); | ||||
| 	fprintf(fp, "\t\t\tcoordIndex [\n"); | ||||
| 
 | ||||
| 	for (size_t i = 0; i + 1 < its.indices.size(); ++ i) | ||||
| 		fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]); | ||||
| 	fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]); | ||||
| 	fprintf(fp, "\t\t}\n"); | ||||
| 	fprintf(fp, "\t}\n"); | ||||
| 	fprintf(fp, "}\n"); | ||||
| 	fclose(fp); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool its_write_obj(const indexed_triangle_set &its, const char *file) | ||||
| { | ||||
| 
 | ||||
|   	FILE *fp = boost::nowide::fopen(file, "w"); | ||||
|   	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_write_obj: Couldn't open " << file << " for writing"; | ||||
|     	return false; | ||||
|   	} | ||||
| 
 | ||||
| 	for (size_t i = 0; i < its.vertices.size(); ++ i) | ||||
|     	fprintf(fp, "v %f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2)); | ||||
|   	for (size_t i = 0; i < its.indices.size(); ++ i) | ||||
|     	fprintf(fp, "f %d %d %d\n", its.indices[i][0]+1, its.indices[i][1]+1, its.indices[i][2]+1); | ||||
|   	fclose(fp); | ||||
|   	return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     first_facet = i; | ||||
|     for(j = 0; j < 3; j++) { | ||||
|       if(stl->v_indices[i].vertex[j] != -1) { | ||||
|         continue; | ||||
|       } | ||||
|       if(stl->stats.shared_vertices == stl->stats.shared_malloced) { | ||||
|         stl->stats.shared_malloced += 1024; | ||||
|         stl->v_shared = (stl_vertex*)realloc(stl->v_shared, | ||||
|                                              stl->stats.shared_malloced * sizeof(stl_vertex)); | ||||
|         if(stl->v_shared == NULL) perror("stl_generate_shared_vertices"); | ||||
|       } | ||||
| // Check validity of the mesh, assert on error.
 | ||||
| bool stl_validate(const stl_file *stl, const indexed_triangle_set &its) | ||||
| { | ||||
| 	assert(! stl->facet_start.empty()); | ||||
| 	assert(stl->facet_start.size() == stl->stats.number_of_facets); | ||||
| 	assert(stl->neighbors_start.size() == stl->stats.number_of_facets); | ||||
| 	assert(stl->facet_start.size() == stl->neighbors_start.size()); | ||||
| 	assert(! stl->neighbors_start.empty()); | ||||
| 	assert((its.indices.empty()) == (its.vertices.empty())); | ||||
| 	assert(stl->stats.number_of_facets > 0); | ||||
| 	assert(its.vertices.empty() || its.indices.size() == stl->stats.number_of_facets); | ||||
| 
 | ||||
|       stl->v_shared[stl->stats.shared_vertices] = | ||||
|         stl->facet_start[i].vertex[j]; | ||||
| 
 | ||||
|       direction = 0; | ||||
|       reversed = 0; | ||||
|       facet_num = i; | ||||
|       vnot = (j + 2) % 3; | ||||
| 
 | ||||
|       for(;;) { | ||||
|         if(vnot > 2) { | ||||
|           if(direction == 0) { | ||||
|             pivot_vertex = (vnot + 2) % 3; | ||||
|             next_edge = pivot_vertex; | ||||
|             direction = 1; | ||||
|           } else { | ||||
|             pivot_vertex = (vnot + 1) % 3; | ||||
|             next_edge = vnot % 3; | ||||
|             direction = 0; | ||||
|           } | ||||
|         } else { | ||||
|           if(direction == 0) { | ||||
|             pivot_vertex = (vnot + 1) % 3; | ||||
|             next_edge = vnot; | ||||
|           } else { | ||||
|             pivot_vertex = (vnot + 2) % 3; | ||||
|             next_edge = pivot_vertex; | ||||
|           } | ||||
| #ifdef _DEBUG | ||||
|     // Verify validity of neighborship data.
 | ||||
|     for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) { | ||||
|         const stl_neighbors &nbr 		= stl->neighbors_start[facet_idx]; | ||||
|         const int 			*vertices 	= its.indices.empty() ? nullptr : its.indices[facet_idx].data(); | ||||
|         for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) { | ||||
|             int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx]; | ||||
|             assert(nbr_face < (int)stl->stats.number_of_facets); | ||||
|             if (nbr_face != -1) { | ||||
|             	int nbr_vnot = nbr.which_vertex_not[nbr_idx]; | ||||
| 				assert(nbr_vnot >= 0 && nbr_vnot < 6); | ||||
| 				// Neighbor of the neighbor is the original face.
 | ||||
| 				assert(stl->neighbors_start[nbr_face].neighbor[(nbr_vnot + 1) % 3] == facet_idx); | ||||
| 				int vnot_back = stl->neighbors_start[nbr_face].which_vertex_not[(nbr_vnot + 1) % 3]; | ||||
| 				assert(vnot_back >= 0 && vnot_back < 6); | ||||
| 				assert((nbr_vnot < 3) == (vnot_back < 3)); | ||||
| 				assert(vnot_back % 3 == (nbr_idx + 2) % 3); | ||||
| 				if (vertices != nullptr) { | ||||
| 					// Has shared vertices.
 | ||||
| 	            	if (nbr_vnot < 3) { | ||||
| 	            		// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are correctly oriented.
 | ||||
| 						assert((its.indices[nbr_face][(nbr_vnot + 1) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face][(nbr_vnot + 2) % 3] == vertices[nbr_idx])); | ||||
| 					} else { | ||||
| 	            		// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are incorrectly oriented, one of them is flipped.
 | ||||
| 						assert((its.indices[nbr_face][(nbr_vnot + 2) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face][(nbr_vnot + 1) % 3] == vertices[nbr_idx])); | ||||
| 					} | ||||
| 				} | ||||
|             } | ||||
|         } | ||||
|         stl->v_indices[facet_num].vertex[pivot_vertex] = | ||||
|           stl->stats.shared_vertices; | ||||
| 
 | ||||
|         next_facet = stl->neighbors_start[facet_num].neighbor[next_edge]; | ||||
|         if(next_facet == -1) { | ||||
|           if(reversed) { | ||||
|             break; | ||||
|           } else { | ||||
|             direction = 1; | ||||
|             vnot = (j + 1) % 3; | ||||
|             reversed = 1; | ||||
|             facet_num = first_facet; | ||||
|           } | ||||
|         } else if(next_facet != first_facet) { | ||||
|           vnot = stl->neighbors_start[facet_num]. | ||||
|                  which_vertex_not[next_edge]; | ||||
|           facet_num = next_facet; | ||||
|         } else { | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       stl->stats.shared_vertices += 1; | ||||
|     } | ||||
|   } | ||||
| #endif /* _DEBUG */ | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_write_off(stl_file *stl, const char *file) { | ||||
|   int i; | ||||
|   FILE      *fp; | ||||
|   char      *error_msg; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /* Open the file */ | ||||
|   fp = boost::nowide::fopen(file, "w"); | ||||
|   if(fp == NULL) { | ||||
|     error_msg = (char*) | ||||
|                 malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", | ||||
|             file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   fprintf(fp, "OFF\n"); | ||||
|   fprintf(fp, "%d %d 0\n", | ||||
|           stl->stats.shared_vertices, stl->stats.number_of_facets); | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.shared_vertices; i++) { | ||||
|     fprintf(fp, "\t%f %f %f\n", | ||||
|             stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2)); | ||||
|   } | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0], | ||||
|             stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]); | ||||
|   } | ||||
|   fclose(fp); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_write_vrml(stl_file *stl, const char *file) { | ||||
|   int i; | ||||
|   FILE      *fp; | ||||
|   char      *error_msg; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /* Open the file */ | ||||
|   fp = boost::nowide::fopen(file, "w"); | ||||
|   if(fp == NULL) { | ||||
|     error_msg = (char*) | ||||
|                 malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", | ||||
|             file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   fprintf(fp, "#VRML V1.0 ascii\n\n"); | ||||
|   fprintf(fp, "Separator {\n"); | ||||
|   fprintf(fp, "\tDEF STLShape ShapeHints {\n"); | ||||
|   fprintf(fp, "\t\tvertexOrdering COUNTERCLOCKWISE\n"); | ||||
|   fprintf(fp, "\t\tfaceType CONVEX\n"); | ||||
|   fprintf(fp, "\t\tshapeType SOLID\n"); | ||||
|   fprintf(fp, "\t\tcreaseAngle 0.0\n"); | ||||
|   fprintf(fp, "\t}\n"); | ||||
|   fprintf(fp, "\tDEF STLModel Separator {\n"); | ||||
|   fprintf(fp, "\t\tDEF STLColor Material {\n"); | ||||
|   fprintf(fp, "\t\t\temissiveColor 0.700000 0.700000 0.000000\n"); | ||||
|   fprintf(fp, "\t\t}\n"); | ||||
|   fprintf(fp, "\t\tDEF STLVertices Coordinate3 {\n"); | ||||
|   fprintf(fp, "\t\t\tpoint [\n"); | ||||
| 
 | ||||
|   for(i = 0; i < (stl->stats.shared_vertices - 1); i++) { | ||||
|     fprintf(fp, "\t\t\t\t%f %f %f,\n", | ||||
|             stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2)); | ||||
|   } | ||||
|   fprintf(fp, "\t\t\t\t%f %f %f]\n", | ||||
|           stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2)); | ||||
|   fprintf(fp, "\t\t}\n"); | ||||
|   fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n"); | ||||
|   fprintf(fp, "\t\t\tcoordIndex [\n"); | ||||
| 
 | ||||
|   for(i = 0; i < (stl->stats.number_of_facets - 1); i++) { | ||||
|     fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", stl->v_indices[i].vertex[0], | ||||
|             stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]); | ||||
|   } | ||||
|   fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", stl->v_indices[i].vertex[0], | ||||
|           stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]); | ||||
|   fprintf(fp, "\t\t}\n"); | ||||
|   fprintf(fp, "\t}\n"); | ||||
|   fprintf(fp, "}\n"); | ||||
|   fclose(fp); | ||||
| } | ||||
| 
 | ||||
| void stl_write_obj (stl_file *stl, const char *file) { | ||||
|   int i; | ||||
|   FILE* fp; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /* Open the file */ | ||||
|   fp = boost::nowide::fopen(file, "w"); | ||||
|   if (fp == NULL) { | ||||
|     char* error_msg = (char*)malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   for (i = 0; i < stl->stats.shared_vertices; i++) { | ||||
|     fprintf(fp, "v %f %f %f\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2)); | ||||
|   } | ||||
|   for (i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     fprintf(fp, "f %d %d %d\n", stl->v_indices[i].vertex[0]+1, stl->v_indices[i].vertex[1]+1, stl->v_indices[i].vertex[2]+1); | ||||
|   } | ||||
| 
 | ||||
|   fclose(fp); | ||||
| // Check validity of the mesh, assert on error.
 | ||||
| bool stl_validate(const stl_file *stl) | ||||
| { | ||||
| 	indexed_triangle_set its; | ||||
| 	return stl_validate(stl, its); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										295
									
								
								src/admesh/stl.h
									
										
									
									
									
								
							
							
						
						|  | @ -27,6 +27,7 @@ | |||
| #include <stdint.h> | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| #include <vector> | ||||
| #include <Eigen/Geometry>  | ||||
| 
 | ||||
| // Size of the binary STL header, free form.
 | ||||
|  | @ -40,22 +41,23 @@ | |||
| 
 | ||||
| typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_vertex; | ||||
| typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_normal; | ||||
| typedef Eigen::Matrix<int,   3, 1, Eigen::DontAlign> stl_triangle_vertex_indices; | ||||
| static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect"); | ||||
| static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect"); | ||||
| 
 | ||||
| struct stl_facet { | ||||
|   stl_normal normal; | ||||
|   stl_vertex vertex[3]; | ||||
|   char       extra[2]; | ||||
| 	stl_normal normal; | ||||
| 	stl_vertex vertex[3]; | ||||
| 	char       extra[2]; | ||||
| 
 | ||||
|   stl_facet  rotated(const Eigen::Quaternion<float, Eigen::DontAlign> &rot) { | ||||
|     stl_facet out; | ||||
|     out.normal    = rot * this->normal; | ||||
|     out.vertex[0] = rot * this->vertex[0]; | ||||
|     out.vertex[1] = rot * this->vertex[1]; | ||||
|     out.vertex[2] = rot * this->vertex[2]; | ||||
|     return out; | ||||
|   } | ||||
| 	stl_facet  rotated(const Eigen::Quaternion<float, Eigen::DontAlign> &rot) const { | ||||
| 		stl_facet out; | ||||
| 		out.normal    = rot * this->normal; | ||||
| 		out.vertex[0] = rot * this->vertex[0]; | ||||
| 		out.vertex[1] = rot * this->vertex[1]; | ||||
| 		out.vertex[2] = rot * this->vertex[2]; | ||||
| 		return out; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| #define SIZEOF_STL_FACET       50 | ||||
|  | @ -67,104 +69,102 @@ static_assert(sizeof(stl_facet) >= SIZEOF_STL_FACET, "size of stl_facet incorrec | |||
| 
 | ||||
| typedef enum {binary, ascii, inmemory} stl_type; | ||||
| 
 | ||||
| typedef struct { | ||||
|   stl_vertex p1; | ||||
|   stl_vertex p2; | ||||
|   int        facet_number; | ||||
| } stl_edge; | ||||
| struct stl_neighbors { | ||||
|   	stl_neighbors() { reset(); } | ||||
|   	void reset() { | ||||
|   		neighbor[0] = -1; | ||||
|   		neighbor[1] = -1; | ||||
|   		neighbor[2] = -1; | ||||
|   		which_vertex_not[0] = -1; | ||||
|   		which_vertex_not[1] = -1; | ||||
|   		which_vertex_not[2] = -1; | ||||
|   	} | ||||
|   	int num_neighbors_missing() const { return (this->neighbor[0] == -1) + (this->neighbor[1] == -1) + (this->neighbor[2] == -1); } | ||||
|   	int num_neighbors() const { return 3 - this->num_neighbors_missing(); } | ||||
| 
 | ||||
| typedef struct stl_hash_edge { | ||||
|   // Key of a hash edge: sorted vertices of the edge.
 | ||||
|   uint32_t       key[6]; | ||||
|   // Compare two keys.
 | ||||
|   bool operator==(const stl_hash_edge &rhs) { return memcmp(key, rhs.key, sizeof(key)) == 0; } | ||||
|   bool operator!=(const stl_hash_edge &rhs) { return ! (*this == rhs); } | ||||
|   int  hash(int M) const { return ((key[0] / 11 + key[1] / 7 + key[2] / 3) ^ (key[3] / 11  + key[4] / 7 + key[5] / 3)) % M; } | ||||
|   // Index of a facet owning this edge.
 | ||||
|   int            facet_number; | ||||
|   // Index of this edge inside the facet with an index of facet_number.
 | ||||
|   // If this edge is stored backwards, which_edge is increased by 3.
 | ||||
|   int            which_edge; | ||||
|   struct stl_hash_edge  *next; | ||||
| } stl_hash_edge; | ||||
|   	// Index of a neighbor facet.
 | ||||
|   	int   neighbor[3]; | ||||
|   	// Index of an opposite vertex at the neighbor face.
 | ||||
|   	char  which_vertex_not[3]; | ||||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
|   // Index of a neighbor facet.
 | ||||
|   int   neighbor[3]; | ||||
|   // Index of an opposite vertex at the neighbor face.
 | ||||
|   char  which_vertex_not[3]; | ||||
| } stl_neighbors; | ||||
| struct stl_stats { | ||||
| 	stl_stats() { this->reset(); } | ||||
| 	void reset() { memset(this, 0, sizeof(stl_stats)); this->volume = -1.0; } | ||||
| 	char          header[81]; | ||||
| 	stl_type      type; | ||||
| 	uint32_t      number_of_facets; | ||||
| 	stl_vertex    max; | ||||
| 	stl_vertex    min; | ||||
| 	stl_vertex    size; | ||||
| 	float         bounding_diameter; | ||||
| 	float         shortest_edge; | ||||
| 	float         volume; | ||||
| 	int           connected_edges; | ||||
| 	int           connected_facets_1_edge; | ||||
| 	int           connected_facets_2_edge; | ||||
| 	int           connected_facets_3_edge; | ||||
| 	int           facets_w_1_bad_edge; | ||||
| 	int           facets_w_2_bad_edge; | ||||
| 	int           facets_w_3_bad_edge; | ||||
| 	int           original_num_facets; | ||||
| 	int           edges_fixed; | ||||
| 	int           degenerate_facets; | ||||
| 	int           facets_removed; | ||||
| 	int           facets_added; | ||||
| 	int           facets_reversed; | ||||
| 	int           backwards_edges; | ||||
| 	int           normals_fixed; | ||||
| 	int           number_of_parts; | ||||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
|   int   vertex[3]; | ||||
| } v_indices_struct; | ||||
| struct stl_file { | ||||
| 	stl_file() {} | ||||
| 
 | ||||
| typedef struct { | ||||
|   char          header[81]; | ||||
|   stl_type      type; | ||||
|   uint32_t      number_of_facets; | ||||
|   stl_vertex    max; | ||||
|   stl_vertex    min; | ||||
|   stl_vertex    size; | ||||
|   float         bounding_diameter; | ||||
|   float         shortest_edge; | ||||
|   float         volume; | ||||
|   unsigned      number_of_blocks; | ||||
|   int           connected_edges; | ||||
|   int           connected_facets_1_edge; | ||||
|   int           connected_facets_2_edge; | ||||
|   int           connected_facets_3_edge; | ||||
|   int           facets_w_1_bad_edge; | ||||
|   int           facets_w_2_bad_edge; | ||||
|   int           facets_w_3_bad_edge; | ||||
|   int           original_num_facets; | ||||
|   int           edges_fixed; | ||||
|   int           degenerate_facets; | ||||
|   int           facets_removed; | ||||
|   int           facets_added; | ||||
|   int           facets_reversed; | ||||
|   int           backwards_edges; | ||||
|   int           normals_fixed; | ||||
|   int           number_of_parts; | ||||
|   int           malloced; | ||||
|   int           freed; | ||||
|   int           facets_malloced; | ||||
|   int           collisions; | ||||
|   int           shared_vertices; | ||||
|   int           shared_malloced; | ||||
| } stl_stats; | ||||
| 	void clear() { | ||||
| 		this->facet_start.clear(); | ||||
| 		this->neighbors_start.clear(); | ||||
| 		this->stats.reset(); | ||||
| 	} | ||||
| 
 | ||||
| typedef struct { | ||||
|   FILE          *fp; | ||||
|   stl_facet     *facet_start; | ||||
|   stl_hash_edge **heads; | ||||
|   stl_hash_edge *tail; | ||||
|   int           M; | ||||
|   stl_neighbors *neighbors_start; | ||||
|   v_indices_struct *v_indices; | ||||
|   stl_vertex    *v_shared; | ||||
|   stl_stats     stats; | ||||
|   char          error; | ||||
| } stl_file; | ||||
| 	size_t memsize() const { | ||||
| 		return sizeof(*this) + sizeof(stl_facet) * facet_start.size() + sizeof(stl_neighbors) * neighbors_start.size(); | ||||
| 	} | ||||
| 
 | ||||
| 	std::vector<stl_facet>     		facet_start; | ||||
| 	std::vector<stl_neighbors> 		neighbors_start; | ||||
| 	// Statistics
 | ||||
| 	stl_stats     					stats; | ||||
| }; | ||||
| 
 | ||||
| extern void stl_open(stl_file *stl, const char *file); | ||||
| extern void stl_close(stl_file *stl); | ||||
| struct indexed_triangle_set | ||||
| { | ||||
| 	indexed_triangle_set() {} | ||||
| 
 | ||||
| 	void clear() { indices.clear(); vertices.clear(); } | ||||
| 
 | ||||
| 	size_t memsize() const { | ||||
| 		return sizeof(*this) + sizeof(stl_triangle_vertex_indices) * indices.size() + sizeof(stl_vertex) * vertices.size(); | ||||
| 	} | ||||
| 
 | ||||
| 	std::vector<stl_triangle_vertex_indices> 	indices; | ||||
| 	std::vector<stl_vertex>       				vertices; | ||||
| 	//FIXME add normals once we get rid of the stl_file from TriangleMesh completely.
 | ||||
| 	//std::vector<stl_normal> 					normals
 | ||||
| }; | ||||
| 
 | ||||
| extern bool stl_open(stl_file *stl, const char *file); | ||||
| extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file); | ||||
| extern void stl_print_neighbors(stl_file *stl, char *file); | ||||
| extern void stl_put_little_int(FILE *fp, int value_in); | ||||
| extern void stl_put_little_float(FILE *fp, float value_in); | ||||
| extern void stl_write_ascii(stl_file *stl, const char *file, const char *label); | ||||
| extern void stl_write_binary(stl_file *stl, const char *file, const char *label); | ||||
| extern void stl_write_binary_block(stl_file *stl, FILE *fp); | ||||
| extern bool stl_print_neighbors(stl_file *stl, char *file); | ||||
| extern bool stl_write_ascii(stl_file *stl, const char *file, const char *label); | ||||
| extern bool stl_write_binary(stl_file *stl, const char *file, const char *label); | ||||
| extern void stl_check_facets_exact(stl_file *stl); | ||||
| extern void stl_check_facets_nearby(stl_file *stl, float tolerance); | ||||
| extern void stl_remove_unconnected_facets(stl_file *stl); | ||||
| extern void stl_write_vertex(stl_file *stl, int facet, int vertex); | ||||
| extern void stl_write_facet(stl_file *stl, char *label, int facet); | ||||
| extern void stl_write_edge(stl_file *stl, char *label, stl_hash_edge edge); | ||||
| extern void stl_write_neighbor(stl_file *stl, int facet); | ||||
| extern void stl_write_quad_object(stl_file *stl, char *file); | ||||
| extern bool stl_write_quad_object(stl_file *stl, char *file); | ||||
| extern void stl_verify_neighbors(stl_file *stl); | ||||
| extern void stl_fill_holes(stl_file *stl); | ||||
| extern void stl_fix_normal_directions(stl_file *stl); | ||||
|  | @ -186,36 +186,30 @@ extern void stl_get_size(stl_file *stl); | |||
| template<typename T> | ||||
| extern void stl_transform(stl_file *stl, T *trafo3x4) | ||||
| { | ||||
|   if (stl->error) | ||||
|     return; | ||||
| 	for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { | ||||
| 		stl_facet &face = stl->facet_start[i_face]; | ||||
| 		for (int i_vertex = 0; i_vertex < 3; ++ i_vertex) { | ||||
| 			stl_vertex &v_dst = face.vertex[i_vertex]; | ||||
| 			stl_vertex  v_src = v_dst; | ||||
| 			v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2]  * v_src(2) + trafo3x4[3]); | ||||
| 			v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6]  * v_src(2) + trafo3x4[7]); | ||||
| 			v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]); | ||||
| 		} | ||||
| 		stl_vertex &v_dst = face.normal; | ||||
| 		stl_vertex  v_src = v_dst; | ||||
| 		v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2]  * v_src(2)); | ||||
| 		v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6]  * v_src(2)); | ||||
| 		v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2)); | ||||
| 	} | ||||
| 
 | ||||
|   for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { | ||||
|     stl_facet &face = stl->facet_start[i_face]; | ||||
|     for (int i_vertex = 0; i_vertex < 3; ++ i_vertex) { | ||||
|       stl_vertex &v_dst = face.vertex[i_vertex]; | ||||
|       stl_vertex  v_src = v_dst; | ||||
|       v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2]  * v_src(2) + trafo3x4[3]); | ||||
|       v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6]  * v_src(2) + trafo3x4[7]); | ||||
|       v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]); | ||||
|     } | ||||
|     stl_vertex &v_dst = face.normal; | ||||
|     stl_vertex  v_src = v_dst; | ||||
|     v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2]  * v_src(2)); | ||||
|     v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6]  * v_src(2)); | ||||
|     v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2)); | ||||
|   } | ||||
| 
 | ||||
|   stl_get_size(stl); | ||||
| 	stl_get_size(stl); | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| inline void stl_transform(stl_file *stl, const Eigen::Transform<T, 3, Eigen::Affine, Eigen::DontAlign>& t) | ||||
| { | ||||
| 	if (stl->error) | ||||
| 		return; | ||||
| 
 | ||||
| 	const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0); | ||||
| 	for (size_t i = 0; i < stl->stats.number_of_facets; ++i) { | ||||
| 	for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		stl_facet &f = stl->facet_start[i]; | ||||
| 		for (size_t j = 0; j < 3; ++j) | ||||
| 			f.vertex[j] = (t * f.vertex[j].template cast<T>()).template cast<float>().eval(); | ||||
|  | @ -228,10 +222,7 @@ inline void stl_transform(stl_file *stl, const Eigen::Transform<T, 3, Eigen::Aff | |||
| template<typename T> | ||||
| inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::DontAlign>& m) | ||||
| { | ||||
| 	if (stl->error) | ||||
| 		return; | ||||
| 
 | ||||
| 	for (size_t i = 0; i < stl->stats.number_of_facets; ++i) { | ||||
| 	for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		stl_facet &f = stl->facet_start[i]; | ||||
| 		for (size_t j = 0; j < 3; ++j) | ||||
| 			f.vertex[j] = (m * f.vertex[j].template cast<T>()).template cast<float>().eval(); | ||||
|  | @ -241,13 +232,43 @@ inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::Don | |||
| 	stl_get_size(stl); | ||||
| } | ||||
| 
 | ||||
| extern void stl_open_merge(stl_file *stl, char *file); | ||||
| extern void stl_invalidate_shared_vertices(stl_file *stl); | ||||
| extern void stl_generate_shared_vertices(stl_file *stl); | ||||
| extern void stl_write_obj(stl_file *stl, const char *file); | ||||
| extern void stl_write_off(stl_file *stl, const char *file); | ||||
| extern void stl_write_dxf(stl_file *stl, const char *file, char *label); | ||||
| extern void stl_write_vrml(stl_file *stl, const char *file); | ||||
| 
 | ||||
| template<typename T> | ||||
| extern void its_transform(indexed_triangle_set &its, T *trafo3x4) | ||||
| { | ||||
| 	for (stl_vertex &v_dst : its.vertices) { | ||||
| 		stl_vertex  v_src = v_dst; | ||||
| 		v_dst(0) = T(trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2]  * v_src(2) + trafo3x4[3]); | ||||
| 		v_dst(1) = T(trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6]  * v_src(2) + trafo3x4[7]); | ||||
| 		v_dst(2) = T(trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| inline void its_transform(indexed_triangle_set &its, const Eigen::Transform<T, 3, Eigen::Affine, Eigen::DontAlign>& t) | ||||
| { | ||||
| 	const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0); | ||||
| 	for (stl_vertex &v : its.vertices) | ||||
| 		v = (t * v.template cast<T>()).template cast<float>().eval(); | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| inline void its_transform(indexed_triangle_set &its, const Eigen::Matrix<T, 3, 3, Eigen::DontAlign>& m) | ||||
| { | ||||
| 	for (stl_vertex &v : its.vertices) | ||||
| 		v = (m * v.template cast<T>()).template cast<float>().eval(); | ||||
| } | ||||
| 
 | ||||
| extern void its_rotate_x(indexed_triangle_set &its, float angle); | ||||
| extern void its_rotate_y(indexed_triangle_set &its, float angle); | ||||
| extern void its_rotate_z(indexed_triangle_set &its, float angle); | ||||
| 
 | ||||
| extern void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its); | ||||
| extern bool its_write_obj(const indexed_triangle_set &its, const char *file); | ||||
| extern bool its_write_off(const indexed_triangle_set &its, const char *file); | ||||
| extern bool its_write_vrml(const indexed_triangle_set &its, const char *file); | ||||
| 
 | ||||
| extern bool stl_write_dxf(stl_file *stl, const char *file, char *label); | ||||
| inline void stl_calculate_normal(stl_normal &normal, stl_facet *facet) { | ||||
|   normal = (facet->vertex[1] - facet->vertex[0]).cross(facet->vertex[2] - facet->vertex[0]); | ||||
| } | ||||
|  | @ -258,24 +279,18 @@ inline void stl_normalize_vector(stl_normal &normal) { | |||
|   else | ||||
|     normal *= float(1.0 / length); | ||||
| } | ||||
| inline bool stl_vertex_lower(const stl_vertex &a, const stl_vertex &b) { | ||||
|   return (a(0) != b(0)) ? (a(0) < b(0)) : | ||||
|         ((a(1) != b(1)) ? (a(1) < b(1)) : (a(2) < b(2))); | ||||
| } | ||||
| extern void stl_calculate_volume(stl_file *stl); | ||||
| 
 | ||||
| extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int tolerance_flag, float tolerance, int increment_flag, float increment, int nearby_flag, int iterations, int remove_unconnected_flag, int fill_holes_flag, int normal_directions_flag, int normal_values_flag, int reverse_all_flag, int verbose_flag); | ||||
| extern void stl_repair(stl_file *stl, bool fixall_flag, bool exact_flag, bool tolerance_flag, float tolerance, bool increment_flag, float increment, bool nearby_flag, int iterations, bool remove_unconnected_flag, bool fill_holes_flag, bool normal_directions_flag, bool normal_values_flag, bool reverse_all_flag, bool verbose_flag); | ||||
| 
 | ||||
| extern void stl_initialize(stl_file *stl); | ||||
| extern void stl_count_facets(stl_file *stl, const char *file); | ||||
| extern void stl_allocate(stl_file *stl); | ||||
| extern void stl_read(stl_file *stl, int first_facet, bool first); | ||||
| extern void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first); | ||||
| extern void stl_reallocate(stl_file *stl); | ||||
| extern void stl_add_facet(stl_file *stl, stl_facet *new_facet); | ||||
| extern void stl_add_facet(stl_file *stl, const stl_facet *new_facet); | ||||
| 
 | ||||
| extern void stl_clear_error(stl_file *stl); | ||||
| extern int stl_get_error(stl_file *stl); | ||||
| extern void stl_exit_on_error(stl_file *stl); | ||||
| // Validate the mesh, assert on error.
 | ||||
| extern bool stl_validate(const stl_file *stl); | ||||
| extern bool stl_validate(const stl_file *stl, const indexed_triangle_set &its); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -22,159 +22,86 @@ | |||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include <boost/log/trivial.hpp> | ||||
| #include <boost/nowide/cstdio.hpp> | ||||
| #include <boost/predef/other/endian.h> | ||||
| 
 | ||||
| #include "stl.h" | ||||
| 
 | ||||
| #include <boost/nowide/cstdio.hpp> | ||||
| #include <boost/detail/endian.hpp> | ||||
| 
 | ||||
| #if !defined(SEEK_SET) | ||||
| #define SEEK_SET 0 | ||||
| #define SEEK_CUR 1 | ||||
| #define SEEK_END 2 | ||||
| #endif | ||||
| 
 | ||||
| void | ||||
| stl_stats_out(stl_file *stl, FILE *file, char *input_file) { | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /* this is here for Slic3r, without our config.h
 | ||||
|      it won't use this part of the code anyway */ | ||||
| void stl_stats_out(stl_file *stl, FILE *file, char *input_file) | ||||
| { | ||||
|   	// This is here for Slic3r, without our config.h it won't use this part of the code anyway.
 | ||||
| #ifndef VERSION | ||||
| #define VERSION "unknown" | ||||
| #endif | ||||
|   fprintf(file, "\n\
 | ||||
| ================= Results produced by ADMesh version " VERSION " ================\n"); | ||||
|   fprintf(file, "\
 | ||||
| Input file         : %s\n", input_file); | ||||
|   if(stl->stats.type == binary) { | ||||
|     fprintf(file, "\
 | ||||
| File type          : Binary STL file\n"); | ||||
|   } else { | ||||
|     fprintf(file, "\
 | ||||
| File type          : ASCII STL file\n"); | ||||
|   } | ||||
|   fprintf(file, "\
 | ||||
| Header             : %s\n", stl->stats.header); | ||||
|   fprintf(file, "============== Size ==============\n"); | ||||
|   fprintf(file, "Min X = % f, Max X = % f\n", | ||||
|           stl->stats.min(0), stl->stats.max(0)); | ||||
|   fprintf(file, "Min Y = % f, Max Y = % f\n", | ||||
|           stl->stats.min(1), stl->stats.max(1)); | ||||
|   fprintf(file, "Min Z = % f, Max Z = % f\n", | ||||
|           stl->stats.min(2), stl->stats.max(2)); | ||||
| 
 | ||||
|   fprintf(file, "\
 | ||||
| ========= Facet Status ========== Original ============ Final ====\n"); | ||||
|   fprintf(file, "\
 | ||||
| Number of facets                 : %5d               %5d\n", | ||||
|           stl->stats.original_num_facets, stl->stats.number_of_facets); | ||||
|   fprintf(file, "\
 | ||||
| Facets with 1 disconnected edge  : %5d               %5d\n", | ||||
|           stl->stats.facets_w_1_bad_edge, stl->stats.connected_facets_2_edge - | ||||
|           stl->stats.connected_facets_3_edge); | ||||
|   fprintf(file, "\
 | ||||
| Facets with 2 disconnected edges : %5d               %5d\n", | ||||
|           stl->stats.facets_w_2_bad_edge, stl->stats.connected_facets_1_edge - | ||||
|           stl->stats.connected_facets_2_edge); | ||||
|   fprintf(file, "\
 | ||||
| Facets with 3 disconnected edges : %5d               %5d\n", | ||||
|           stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets - | ||||
|           stl->stats.connected_facets_1_edge); | ||||
|   fprintf(file, "\
 | ||||
| Total disconnected facets        : %5d               %5d\n", | ||||
|           stl->stats.facets_w_1_bad_edge + stl->stats.facets_w_2_bad_edge + | ||||
|           stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets - | ||||
|           stl->stats.connected_facets_3_edge); | ||||
| 
 | ||||
|   fprintf(file, | ||||
|           "=== Processing Statistics ===     ===== Other Statistics =====\n"); | ||||
|   fprintf(file, "\
 | ||||
| Number of parts       : %5d        Volume   : % f\n", | ||||
|           stl->stats.number_of_parts, stl->stats.volume); | ||||
|   fprintf(file, "\
 | ||||
| Degenerate facets     : %5d\n", stl->stats.degenerate_facets); | ||||
|   fprintf(file, "\
 | ||||
| Edges fixed           : %5d\n", stl->stats.edges_fixed); | ||||
|   fprintf(file, "\
 | ||||
| Facets removed        : %5d\n", stl->stats.facets_removed); | ||||
|   fprintf(file, "\
 | ||||
| Facets added          : %5d\n", stl->stats.facets_added); | ||||
|   fprintf(file, "\
 | ||||
| Facets reversed       : %5d\n", stl->stats.facets_reversed); | ||||
|   fprintf(file, "\
 | ||||
| Backwards edges       : %5d\n", stl->stats.backwards_edges); | ||||
|   fprintf(file, "\
 | ||||
| Normals fixed         : %5d\n", stl->stats.normals_fixed); | ||||
|   	fprintf(file, "\n================= Results produced by ADMesh version " VERSION " ================\n"); | ||||
|   	fprintf(file, "Input file         : %s\n", input_file); | ||||
|   	if (stl->stats.type == binary) | ||||
|     	fprintf(file, "File type          : Binary STL file\n"); | ||||
|   	else | ||||
|     	fprintf(file, "File type          : ASCII STL file\n"); | ||||
|   	fprintf(file, "Header             : %s\n", stl->stats.header); | ||||
|   	fprintf(file, "============== Size ==============\n"); | ||||
|   	fprintf(file, "Min X = % f, Max X = % f\n", stl->stats.min(0), stl->stats.max(0)); | ||||
|   	fprintf(file, "Min Y = % f, Max Y = % f\n", stl->stats.min(1), stl->stats.max(1)); | ||||
|   	fprintf(file, "Min Z = % f, Max Z = % f\n", stl->stats.min(2), stl->stats.max(2)); | ||||
|   	fprintf(file, "========= Facet Status ========== Original ============ Final ====\n"); | ||||
|   	fprintf(file, "Number of facets                 : %5d               %5d\n", stl->stats.original_num_facets, stl->stats.number_of_facets); | ||||
|   	fprintf(file, "Facets with 1 disconnected edge  : %5d               %5d\n",  | ||||
|   		stl->stats.facets_w_1_bad_edge, stl->stats.connected_facets_2_edge - stl->stats.connected_facets_3_edge); | ||||
|   	fprintf(file, "Facets with 2 disconnected edges : %5d               %5d\n", | ||||
|     	stl->stats.facets_w_2_bad_edge, stl->stats.connected_facets_1_edge - stl->stats.connected_facets_2_edge); | ||||
|   	fprintf(file, "Facets with 3 disconnected edges : %5d               %5d\n", | ||||
|         stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets - stl->stats.connected_facets_1_edge); | ||||
|   	fprintf(file, "Total disconnected facets        : %5d               %5d\n", | ||||
| 		stl->stats.facets_w_1_bad_edge + stl->stats.facets_w_2_bad_edge + stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets - stl->stats.connected_facets_3_edge); | ||||
|   	fprintf(file, "=== Processing Statistics ===     ===== Other Statistics =====\n"); | ||||
|   	fprintf(file, "Number of parts       : %5d        Volume   : %f\n", stl->stats.number_of_parts, stl->stats.volume); | ||||
|   	fprintf(file, "Degenerate facets     : %5d\n", stl->stats.degenerate_facets); | ||||
|   	fprintf(file, "Edges fixed           : %5d\n", stl->stats.edges_fixed); | ||||
|   	fprintf(file, "Facets removed        : %5d\n", stl->stats.facets_removed); | ||||
|   	fprintf(file, "Facets added          : %5d\n", stl->stats.facets_added); | ||||
|   	fprintf(file, "Facets reversed       : %5d\n", stl->stats.facets_reversed); | ||||
|   	fprintf(file, "Backwards edges       : %5d\n", stl->stats.backwards_edges); | ||||
|   	fprintf(file, "Normals fixed         : %5d\n", stl->stats.normals_fixed); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_write_ascii(stl_file *stl, const char *file, const char *label) { | ||||
|   int       i; | ||||
|   char      *error_msg; | ||||
| bool stl_write_ascii(stl_file *stl, const char *file, const char *label) | ||||
| { | ||||
| 	FILE *fp = boost::nowide::fopen(file, "w"); | ||||
|   	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing"; | ||||
|     	return false; | ||||
|   	} | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 	fprintf(fp, "solid  %s\n", label); | ||||
| 
 | ||||
|   /* Open the file */ | ||||
|   FILE *fp = boost::nowide::fopen(file, "w"); | ||||
|   if(fp == NULL) { | ||||
|     error_msg = (char*) | ||||
|                 malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", | ||||
|             file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
| 	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		fprintf(fp, "  facet normal % .8E % .8E % .8E\n", stl->facet_start[i].normal(0), stl->facet_start[i].normal(1), stl->facet_start[i].normal(2)); | ||||
| 		fprintf(fp, "    outer loop\n"); | ||||
| 		fprintf(fp, "      vertex % .8E % .8E % .8E\n", stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), stl->facet_start[i].vertex[0](2)); | ||||
| 		fprintf(fp, "      vertex % .8E % .8E % .8E\n", stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), stl->facet_start[i].vertex[1](2)); | ||||
| 		fprintf(fp, "      vertex % .8E % .8E % .8E\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2)); | ||||
| 		fprintf(fp, "    endloop\n"); | ||||
| 		fprintf(fp, "  endfacet\n"); | ||||
| 	} | ||||
| 
 | ||||
|   fprintf(fp, "solid  %s\n", label); | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     fprintf(fp, "  facet normal % .8E % .8E % .8E\n", | ||||
|             stl->facet_start[i].normal(0), stl->facet_start[i].normal(1), | ||||
|             stl->facet_start[i].normal(2)); | ||||
|     fprintf(fp, "    outer loop\n"); | ||||
|     fprintf(fp, "      vertex % .8E % .8E % .8E\n", | ||||
|             stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), | ||||
|             stl->facet_start[i].vertex[0](2)); | ||||
|     fprintf(fp, "      vertex % .8E % .8E % .8E\n", | ||||
|             stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), | ||||
|             stl->facet_start[i].vertex[1](2)); | ||||
|     fprintf(fp, "      vertex % .8E % .8E % .8E\n", | ||||
|             stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), | ||||
|             stl->facet_start[i].vertex[2](2)); | ||||
|     fprintf(fp, "    endloop\n"); | ||||
|     fprintf(fp, "  endfacet\n"); | ||||
|   } | ||||
| 
 | ||||
|   fprintf(fp, "endsolid  %s\n", label); | ||||
| 
 | ||||
|   fclose(fp); | ||||
|   	fprintf(fp, "endsolid  %s\n", label); | ||||
|   	fclose(fp); | ||||
|   	return true; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_print_neighbors(stl_file *stl, char *file) { | ||||
|   int i; | ||||
|   FILE *fp; | ||||
|   char *error_msg; | ||||
| bool stl_print_neighbors(stl_file *stl, char *file) | ||||
| { | ||||
| 	FILE *fp = boost::nowide::fopen(file, "w"); | ||||
| 	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_print_neighbors: Couldn't open " << file << " for writing"; | ||||
|     	return false; | ||||
|   	} | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /* Open the file */ | ||||
|   fp = boost::nowide::fopen(file, "w"); | ||||
|   if(fp == NULL) { | ||||
|     error_msg = (char*) | ||||
|                 malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_print_neighbors: Couldn't open %s for writing", | ||||
|             file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n", | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|     	fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n", | ||||
|             i, | ||||
|             stl->neighbors_start[i].neighbor[0], | ||||
|             (int)stl->neighbors_start[i].which_vertex_not[0], | ||||
|  | @ -182,234 +109,142 @@ stl_print_neighbors(stl_file *stl, char *file) { | |||
|             (int)stl->neighbors_start[i].which_vertex_not[1], | ||||
|             stl->neighbors_start[i].neighbor[2], | ||||
|             (int)stl->neighbors_start[i].which_vertex_not[2]); | ||||
|   } | ||||
|   fclose(fp); | ||||
|   	} | ||||
|   	fclose(fp); | ||||
|   	return true; | ||||
| } | ||||
| 
 | ||||
| #ifndef BOOST_LITTLE_ENDIAN | ||||
| #if BOOST_ENDIAN_BIG_BYTE | ||||
| // Swap a buffer of 32bit data from little endian to big endian and vice versa.
 | ||||
| void stl_internal_reverse_quads(char *buf, size_t cnt) | ||||
| { | ||||
|   for (size_t i = 0; i < cnt; i += 4) { | ||||
|     std::swap(buf[i], buf[i+3]); | ||||
|     std::swap(buf[i+1], buf[i+2]); | ||||
|   } | ||||
| 	for (size_t i = 0; i < cnt; i += 4) { | ||||
| 		std::swap(buf[i], buf[i+3]); | ||||
| 		std::swap(buf[i+1], buf[i+2]); | ||||
| 	} | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| void | ||||
| stl_write_binary(stl_file *stl, const char *file, const char *label) { | ||||
|   FILE      *fp; | ||||
|   int       i; | ||||
|   char      *error_msg; | ||||
| bool stl_write_binary(stl_file *stl, const char *file, const char *label) | ||||
| { | ||||
| 	FILE *fp = boost::nowide::fopen(file, "wb"); | ||||
| 	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_write_binary: Couldn't open " << file << " for writing"; | ||||
|     	return false; | ||||
|   	} | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 	fprintf(fp, "%s", label); | ||||
| 	for (size_t i = strlen(label); i < LABEL_SIZE; ++ i) | ||||
| 		putc(0, fp); | ||||
| 
 | ||||
|   /* Open the file */ | ||||
|   fp = boost::nowide::fopen(file, "wb"); | ||||
|   if(fp == NULL) { | ||||
|     error_msg = (char*) | ||||
|                 malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_write_binary: Couldn't open %s for writing", | ||||
|             file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   fprintf(fp, "%s", label); | ||||
|   for(i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp); | ||||
| 
 | ||||
|   fseek(fp, LABEL_SIZE, SEEK_SET); | ||||
| #ifdef BOOST_LITTLE_ENDIAN | ||||
|   fwrite(&stl->stats.number_of_facets, 4, 1, fp); | ||||
|   for (i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     fwrite(stl->facet_start + i, SIZEOF_STL_FACET, 1, fp); | ||||
| #else /* BOOST_LITTLE_ENDIAN */ | ||||
|   char buffer[50]; | ||||
|   // Convert the number of facets to little endian.
 | ||||
|   memcpy(buffer, &stl->stats.number_of_facets, 4); | ||||
|   stl_internal_reverse_quads(buffer, 4); | ||||
|   fwrite(buffer, 4, 1, fp); | ||||
|   for (i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|     memcpy(buffer, stl->facet_start + i, 50); | ||||
|     // Convert to little endian.
 | ||||
|     stl_internal_reverse_quads(buffer, 48); | ||||
|     fwrite(buffer, SIZEOF_STL_FACET, 1, fp); | ||||
|   } | ||||
| #endif /* BOOST_LITTLE_ENDIAN */ | ||||
|   fclose(fp); | ||||
| #if !defined(SEEK_SET) | ||||
| 	#define SEEK_SET 0 | ||||
| #endif | ||||
| 	fseek(fp, LABEL_SIZE, SEEK_SET); | ||||
| #if BOOST_ENDIAN_LITTLE_BYTE | ||||
| 	fwrite(&stl->stats.number_of_facets, 4, 1, fp); | ||||
| 	for (const stl_facet &facet : stl->facet_start) | ||||
| 	  	fwrite(&facet, SIZEOF_STL_FACET, 1, fp); | ||||
| #else /* BOOST_ENDIAN_LITTLE_BYTE */ | ||||
| 	char buffer[50]; | ||||
| 	// Convert the number of facets to little endian.
 | ||||
| 	memcpy(buffer, &stl->stats.number_of_facets, 4); | ||||
| 	stl_internal_reverse_quads(buffer, 4); | ||||
| 	fwrite(buffer, 4, 1, fp); | ||||
| 	for (i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		memcpy(buffer, stl->facet_start + i, 50); | ||||
| 		// Convert to little endian.
 | ||||
| 		stl_internal_reverse_quads(buffer, 48); | ||||
| 		fwrite(buffer, SIZEOF_STL_FACET, 1, fp); | ||||
| 	} | ||||
| #endif /* BOOST_ENDIAN_LITTLE_BYTE */ | ||||
| 	fclose(fp); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_write_vertex(stl_file *stl, int facet, int vertex) { | ||||
|   if (stl->error) return; | ||||
|   printf("  vertex %d/%d % .8E % .8E % .8E\n", vertex, facet, | ||||
| void stl_write_vertex(stl_file *stl, int facet, int vertex) | ||||
| { | ||||
|   	printf("  vertex %d/%d % .8E % .8E % .8E\n", vertex, facet, | ||||
|          stl->facet_start[facet].vertex[vertex](0), | ||||
|          stl->facet_start[facet].vertex[vertex](1), | ||||
|          stl->facet_start[facet].vertex[vertex](2)); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_write_facet(stl_file *stl, char *label, int facet) { | ||||
|   if (stl->error) return; | ||||
|   printf("facet (%d)/ %s\n", facet, label); | ||||
|   stl_write_vertex(stl, facet, 0); | ||||
|   stl_write_vertex(stl, facet, 1); | ||||
|   stl_write_vertex(stl, facet, 2); | ||||
| void stl_write_facet(stl_file *stl, char *label, int facet) | ||||
| { | ||||
| 	printf("facet (%d)/ %s\n", facet, label); | ||||
| 	stl_write_vertex(stl, facet, 0); | ||||
| 	stl_write_vertex(stl, facet, 1); | ||||
| 	stl_write_vertex(stl, facet, 2); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_write_edge(stl_file *stl, char *label, stl_hash_edge edge) { | ||||
|   if (stl->error) return; | ||||
|   printf("edge (%d)/(%d) %s\n", edge.facet_number, edge.which_edge, label); | ||||
|   if(edge.which_edge < 3) { | ||||
|     stl_write_vertex(stl, edge.facet_number, edge.which_edge % 3); | ||||
|     stl_write_vertex(stl, edge.facet_number, (edge.which_edge + 1) % 3); | ||||
|   } else { | ||||
|     stl_write_vertex(stl, edge.facet_number, (edge.which_edge + 1) % 3); | ||||
|     stl_write_vertex(stl, edge.facet_number, edge.which_edge % 3); | ||||
|   } | ||||
| void stl_write_neighbor(stl_file *stl, int facet) | ||||
| { | ||||
| 	printf("Neighbors %d: %d, %d, %d ;  %d, %d, %d\n", facet, | ||||
| 		stl->neighbors_start[facet].neighbor[0], | ||||
| 		stl->neighbors_start[facet].neighbor[1], | ||||
| 		stl->neighbors_start[facet].neighbor[2], | ||||
| 		stl->neighbors_start[facet].which_vertex_not[0], | ||||
| 		stl->neighbors_start[facet].which_vertex_not[1], | ||||
| 		stl->neighbors_start[facet].which_vertex_not[2]); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_write_neighbor(stl_file *stl, int facet) { | ||||
|   if (stl->error) return; | ||||
|   printf("Neighbors %d: %d, %d, %d ;  %d, %d, %d\n", facet, | ||||
|          stl->neighbors_start[facet].neighbor[0], | ||||
|          stl->neighbors_start[facet].neighbor[1], | ||||
|          stl->neighbors_start[facet].neighbor[2], | ||||
|          stl->neighbors_start[facet].which_vertex_not[0], | ||||
|          stl->neighbors_start[facet].which_vertex_not[1], | ||||
|          stl->neighbors_start[facet].which_vertex_not[2]); | ||||
| } | ||||
| bool stl_write_quad_object(stl_file *stl, char *file) | ||||
| { | ||||
| 	stl_vertex connect_color = stl_vertex::Zero(); | ||||
| 	stl_vertex uncon_1_color = stl_vertex::Zero(); | ||||
| 	stl_vertex uncon_2_color = stl_vertex::Zero(); | ||||
| 	stl_vertex uncon_3_color = stl_vertex::Zero(); | ||||
| 	stl_vertex color; | ||||
| 
 | ||||
| void | ||||
| stl_write_quad_object(stl_file *stl, char *file) { | ||||
|   FILE      *fp; | ||||
|   int       i; | ||||
|   int       j; | ||||
|   char      *error_msg; | ||||
|   stl_vertex connect_color = stl_vertex::Zero(); | ||||
|   stl_vertex uncon_1_color = stl_vertex::Zero(); | ||||
|   stl_vertex uncon_2_color = stl_vertex::Zero(); | ||||
|   stl_vertex uncon_3_color = stl_vertex::Zero(); | ||||
|   stl_vertex color; | ||||
| 	FILE *fp = boost::nowide::fopen(file, "w"); | ||||
| 	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing"; | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /* Open the file */ | ||||
|   fp = boost::nowide::fopen(file, "w"); | ||||
|   if(fp == NULL) { | ||||
|     error_msg = (char*) | ||||
|                 malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_write_quad_object: Couldn't open %s for writing", | ||||
|             file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   fprintf(fp, "CQUAD\n"); | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     j = ((stl->neighbors_start[i].neighbor[0] == -1) + | ||||
|          (stl->neighbors_start[i].neighbor[1] == -1) + | ||||
|          (stl->neighbors_start[i].neighbor[2] == -1)); | ||||
|     if(j == 0) { | ||||
|       color = connect_color; | ||||
|     } else if(j == 1) { | ||||
|       color = uncon_1_color; | ||||
|     } else if(j == 2) { | ||||
|       color = uncon_2_color; | ||||
|     } else { | ||||
|       color = uncon_3_color; | ||||
|     } | ||||
|     fprintf(fp, "%f %f %f    %1.1f %1.1f %1.1f 1\n", | ||||
|             stl->facet_start[i].vertex[0](0), | ||||
|             stl->facet_start[i].vertex[0](1), | ||||
|             stl->facet_start[i].vertex[0](2), color(0), color(1), color(2)); | ||||
|     fprintf(fp, "%f %f %f    %1.1f %1.1f %1.1f 1\n", | ||||
|             stl->facet_start[i].vertex[1](0), | ||||
|             stl->facet_start[i].vertex[1](1), | ||||
|             stl->facet_start[i].vertex[1](2), color(0), color(1), color(2)); | ||||
|     fprintf(fp, "%f %f %f    %1.1f %1.1f %1.1f 1\n", | ||||
|             stl->facet_start[i].vertex[2](0), | ||||
|             stl->facet_start[i].vertex[2](1), | ||||
|             stl->facet_start[i].vertex[2](2), color(0), color(1), color(2)); | ||||
|     fprintf(fp, "%f %f %f    %1.1f %1.1f %1.1f 1\n", | ||||
|             stl->facet_start[i].vertex[2](0), | ||||
|             stl->facet_start[i].vertex[2](1), | ||||
|             stl->facet_start[i].vertex[2](2), color(0), color(1), color(2)); | ||||
|   	fprintf(fp, "CQUAD\n"); | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|   		switch (stl->neighbors_start[i].num_neighbors_missing()) { | ||||
|   		case 0: color = connect_color; break; | ||||
|     	case 1: color = uncon_1_color; break; | ||||
|     	case 2: color = uncon_2_color; break; | ||||
|     	default: color = uncon_3_color; | ||||
| 	    } | ||||
| 	    fprintf(fp, "%f %f %f    %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), stl->facet_start[i].vertex[0](2), color(0), color(1), color(2)); | ||||
|     	fprintf(fp, "%f %f %f    %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), stl->facet_start[i].vertex[1](2), color(0), color(1), color(2)); | ||||
|     	fprintf(fp, "%f %f %f    %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2), color(0), color(1), color(2)); | ||||
|     	fprintf(fp, "%f %f %f    %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2), color(0), color(1), color(2)); | ||||
|   } | ||||
|   fclose(fp); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_write_dxf(stl_file *stl, const char *file, char *label) { | ||||
|   int       i; | ||||
|   FILE      *fp; | ||||
|   char      *error_msg; | ||||
| bool stl_write_dxf(stl_file *stl, const char *file, char *label)  | ||||
| { | ||||
| 	FILE *fp = boost::nowide::fopen(file, "w"); | ||||
| 	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing"; | ||||
|     	return false; | ||||
|   	} | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 	fprintf(fp, "999\n%s\n", label); | ||||
| 	fprintf(fp, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n"); | ||||
| 	fprintf(fp, "0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLAYER\n70\n1\n\
 | ||||
| 	0\nLAYER\n2\n0\n70\n0\n62\n7\n6\nCONTINUOUS\n0\nENDTAB\n0\nENDSEC\n"); | ||||
| 	fprintf(fp, "0\nSECTION\n2\nBLOCKS\n0\nENDSEC\n"); | ||||
| 
 | ||||
|   /* Open the file */ | ||||
|   fp = boost::nowide::fopen(file, "w"); | ||||
|   if(fp == NULL) { | ||||
|     error_msg = (char*) | ||||
|                 malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing", | ||||
|             file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
| 	fprintf(fp, "0\nSECTION\n2\nENTITIES\n"); | ||||
| 
 | ||||
|   fprintf(fp, "999\n%s\n", label); | ||||
|   fprintf(fp, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n"); | ||||
|   fprintf(fp, "0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLAYER\n70\n1\n\
 | ||||
| 0\nLAYER\n2\n0\n70\n0\n62\n7\n6\nCONTINUOUS\n0\nENDTAB\n0\nENDSEC\n"); | ||||
|   fprintf(fp, "0\nSECTION\n2\nBLOCKS\n0\nENDSEC\n"); | ||||
| 	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		fprintf(fp, "0\n3DFACE\n8\n0\n"); | ||||
| 		fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n", stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), stl->facet_start[i].vertex[0](2)); | ||||
| 		fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n", stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), stl->facet_start[i].vertex[1](2)); | ||||
| 		fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2)); | ||||
| 		fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2)); | ||||
| 	} | ||||
| 
 | ||||
|   fprintf(fp, "0\nSECTION\n2\nENTITIES\n"); | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     fprintf(fp, "0\n3DFACE\n8\n0\n"); | ||||
|     fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n", | ||||
|             stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), | ||||
|             stl->facet_start[i].vertex[0](2)); | ||||
|     fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n", | ||||
|             stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), | ||||
|             stl->facet_start[i].vertex[1](2)); | ||||
|     fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n", | ||||
|             stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), | ||||
|             stl->facet_start[i].vertex[2](2)); | ||||
|     fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n", | ||||
|             stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), | ||||
|             stl->facet_start[i].vertex[2](2)); | ||||
|   } | ||||
| 
 | ||||
|   fprintf(fp, "0\nENDSEC\n0\nEOF\n"); | ||||
| 
 | ||||
|   fclose(fp); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_clear_error(stl_file *stl) { | ||||
|   stl->error = 0; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_exit_on_error(stl_file *stl) { | ||||
|   if (!stl->error) return; | ||||
|   stl->error = 0; | ||||
|   stl_close(stl); | ||||
|   exit(1); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| stl_get_error(stl_file *stl) { | ||||
|   return stl->error; | ||||
|   	fprintf(fp, "0\nENDSEC\n0\nEOF\n"); | ||||
|   	fclose(fp); | ||||
|   	return true; | ||||
| } | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ | |||
| #include <math.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #include <boost/log/trivial.hpp> | ||||
| #include <boost/nowide/cstdio.hpp> | ||||
| #include <boost/detail/endian.hpp> | ||||
| 
 | ||||
|  | @ -35,351 +36,236 @@ | |||
| #error "SEEK_SET not defined" | ||||
| #endif | ||||
| 
 | ||||
| void | ||||
| stl_open(stl_file *stl, const char *file) { | ||||
|   stl_initialize(stl); | ||||
|   stl_count_facets(stl, file); | ||||
|   stl_allocate(stl); | ||||
|   stl_read(stl, 0, true); | ||||
|   if (stl->fp != nullptr) { | ||||
| 	  fclose(stl->fp); | ||||
| 	  stl->fp = nullptr; | ||||
|   } | ||||
| static FILE* stl_open_count_facets(stl_file *stl, const char *file)  | ||||
| { | ||||
|   	// Open the file in binary mode first.
 | ||||
|   	FILE *fp = boost::nowide::fopen(file, "rb"); | ||||
|   	if (fp == nullptr) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: Couldn't open " << file << " for reading"; | ||||
|     	return nullptr; | ||||
|   	} | ||||
|   	// Find size of file.
 | ||||
|   	fseek(fp, 0, SEEK_END); | ||||
|   	long file_size = ftell(fp); | ||||
| 
 | ||||
|   	// Check for binary or ASCII file.
 | ||||
|   	fseek(fp, HEADER_SIZE, SEEK_SET); | ||||
| 	unsigned char chtest[128]; | ||||
|   	if (! fread(chtest, sizeof(chtest), 1, fp)) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: The input is an empty file: " << file; | ||||
|     	fclose(fp); | ||||
|     	return nullptr; | ||||
|   	} | ||||
|   	stl->stats.type = ascii; | ||||
|   	for (size_t s = 0; s < sizeof(chtest); s++) { | ||||
|     	if (chtest[s] > 127) { | ||||
|       		stl->stats.type = binary; | ||||
|       		break; | ||||
|     	} | ||||
|   	} | ||||
|   	rewind(fp); | ||||
| 
 | ||||
|   	uint32_t num_facets = 0; | ||||
| 
 | ||||
|   	// Get the header and the number of facets in the .STL file.
 | ||||
|   	// If the .STL file is binary, then do the following:
 | ||||
|   	if (stl->stats.type == binary) { | ||||
|     	// Test if the STL file has the right size.
 | ||||
|     	if (((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0) || (file_size < STL_MIN_FILE_SIZE)) { | ||||
| 			BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: The file " << file << " has the wrong size."; | ||||
|       		fclose(fp); | ||||
|       		return nullptr; | ||||
|     	} | ||||
|     	num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET; | ||||
| 
 | ||||
|     	// Read the header.
 | ||||
|     	if (fread(stl->stats.header, LABEL_SIZE, 1, fp) > 79) | ||||
|       		stl->stats.header[80] = '\0'; | ||||
| 
 | ||||
|     	// Read the int following the header.  This should contain # of facets.
 | ||||
| 	  	uint32_t header_num_facets; | ||||
|     	bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, fp) != 0; | ||||
| #ifndef BOOST_LITTLE_ENDIAN | ||||
|     	// Convert from little endian to big endian.
 | ||||
|     	stl_internal_reverse_quads((char*)&header_num_facets, 4); | ||||
| #endif /* BOOST_LITTLE_ENDIAN */ | ||||
|     	if (! header_num_faces_read || num_facets != header_num_facets) | ||||
| 			BOOST_LOG_TRIVIAL(info) << "stl_open_count_facets: Warning: File size doesn't match number of facets in the header: " << file; | ||||
|   	} | ||||
|   	// Otherwise, if the .STL file is ASCII, then do the following:
 | ||||
|   	else | ||||
|   	{ | ||||
|     	// Reopen the file in text mode (for getting correct newlines on Windows)
 | ||||
|     	// fix to silence a warning about unused return value.
 | ||||
|     	// obviously if it fails we have problems....
 | ||||
|     	fp = boost::nowide::freopen(file, "r", fp); | ||||
| 
 | ||||
| 		// do another null check to be safe
 | ||||
|     	if (fp == nullptr) { | ||||
| 			BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: Couldn't open " << file << " for reading"; | ||||
|       		fclose(fp); | ||||
|       		return nullptr; | ||||
|     	} | ||||
|      | ||||
|     	// Find the number of facets.
 | ||||
| 		char linebuf[100]; | ||||
| 		int num_lines = 1; | ||||
| 		while (fgets(linebuf, 100, fp) != nullptr) { | ||||
| 		    // Don't count short lines.
 | ||||
| 		    if (strlen(linebuf) <= 4) | ||||
| 		    	continue; | ||||
| 		    // Skip solid/endsolid lines as broken STL file generators may put several of them.
 | ||||
| 		    if (strncmp(linebuf, "solid", 5) == 0 || strncmp(linebuf, "endsolid", 8) == 0) | ||||
| 		    	continue; | ||||
| 		    ++ num_lines; | ||||
| 		} | ||||
| 
 | ||||
|     	rewind(fp); | ||||
|      | ||||
|     	// Get the header.
 | ||||
| 		int i = 0; | ||||
|     	for (; i < 80 && (stl->stats.header[i] = getc(fp)) != '\n'; ++ i) ; | ||||
|     	stl->stats.header[i] = '\0'; // Lose the '\n'
 | ||||
|     	stl->stats.header[80] = '\0'; | ||||
| 
 | ||||
|     	num_facets = num_lines / ASCII_LINES_PER_FACET; | ||||
|   	} | ||||
| 
 | ||||
|   	stl->stats.number_of_facets += num_facets; | ||||
|   	stl->stats.original_num_facets = stl->stats.number_of_facets; | ||||
|   	return fp; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_initialize(stl_file *stl) { | ||||
|   memset(stl, 0, sizeof(stl_file)); | ||||
|   stl->stats.volume = -1.0; | ||||
| /* Reads the contents of the file pointed to by fp into the stl structure,
 | ||||
|    starting at facet first_facet.  The second argument says if it's our first | ||||
|    time running this for the stl and therefore we should reset our max and min stats. */ | ||||
| static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first) | ||||
| { | ||||
| 	if (stl->stats.type == binary) | ||||
|     	fseek(fp, HEADER_SIZE, SEEK_SET); | ||||
|   	else | ||||
|     	rewind(fp); | ||||
| 
 | ||||
|   	char normal_buf[3][32]; | ||||
|   	for (uint32_t i = first_facet; i < stl->stats.number_of_facets; ++ i) { | ||||
|   	  	stl_facet facet; | ||||
| 
 | ||||
|     	if (stl->stats.type == binary) { | ||||
|       		// Read a single facet from a binary .STL file. We assume little-endian architecture!
 | ||||
|       		if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET) | ||||
|       			return false; | ||||
| #ifndef BOOST_LITTLE_ENDIAN | ||||
|       		// Convert the loaded little endian data to big endian.
 | ||||
|       		stl_internal_reverse_quads((char*)&facet, 48); | ||||
| #endif /* BOOST_LITTLE_ENDIAN */ | ||||
|     	} else { | ||||
| 			// Read a single facet from an ASCII .STL file
 | ||||
| 			// skip solid/endsolid
 | ||||
| 			// (in this order, otherwise it won't work when they are paired in the middle of a file)
 | ||||
| 			fscanf(fp, "endsolid%*[^\n]\n"); | ||||
| 			fscanf(fp, "solid%*[^\n]\n");  // name might contain spaces so %*s doesn't work and it also can be empty (just "solid")
 | ||||
| 			// Leading space in the fscanf format skips all leading white spaces including numerous new lines and tabs.
 | ||||
| 			int res_normal     = fscanf(fp, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]); | ||||
| 			assert(res_normal == 3); | ||||
| 			int res_outer_loop = fscanf(fp, " outer loop"); | ||||
| 			assert(res_outer_loop == 0); | ||||
| 			int res_vertex1    = fscanf(fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); | ||||
| 			assert(res_vertex1 == 3); | ||||
| 			int res_vertex2    = fscanf(fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); | ||||
| 			assert(res_vertex2 == 3); | ||||
| 			int res_vertex3    = fscanf(fp, " vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); | ||||
| 			assert(res_vertex3 == 3); | ||||
| 			int res_endloop    = fscanf(fp, " endloop"); | ||||
| 			assert(res_endloop == 0); | ||||
| 			// There is a leading and trailing white space around endfacet to eat up all leading and trailing white spaces including numerous tabs and new lines.
 | ||||
| 			int res_endfacet   = fscanf(fp, " endfacet "); | ||||
| 			if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) { | ||||
| 				BOOST_LOG_TRIVIAL(error) << "Something is syntactically very wrong with this ASCII STL! "; | ||||
| 				return false; | ||||
| 			} | ||||
| 
 | ||||
| 			// The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition.
 | ||||
| 			if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 || | ||||
| 			    sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 || | ||||
| 			    sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { | ||||
| 			    // Normal was mangled. Maybe denormals or "not a number" were stored?
 | ||||
| 			  	// Just reset the normal and silently ignore it.
 | ||||
| 			  	memset(&facet.normal, 0, sizeof(facet.normal)); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| #if 0 | ||||
| 		// Report close to zero vertex coordinates. Due to the nature of the floating point numbers,
 | ||||
| 		// close to zero values may be represented with singificantly higher precision than the rest of the vertices.
 | ||||
| 		// It may be worth to round these numbers to zero during loading to reduce the number of errors reported
 | ||||
| 		// during the STL import.
 | ||||
| 		for (size_t j = 0; j < 3; ++ j) { | ||||
| 		if (facet.vertex[j](0) > -1e-12f && facet.vertex[j](0) < 1e-12f) | ||||
| 		    printf("stl_read: facet %d(0) = %e\r\n", j, facet.vertex[j](0)); | ||||
| 		if (facet.vertex[j](1) > -1e-12f && facet.vertex[j](1) < 1e-12f) | ||||
| 		    printf("stl_read: facet %d(1) = %e\r\n", j, facet.vertex[j](1)); | ||||
| 		if (facet.vertex[j](2) > -1e-12f && facet.vertex[j](2) < 1e-12f) | ||||
| 		    printf("stl_read: facet %d(2) = %e\r\n", j, facet.vertex[j](2)); | ||||
| 		} | ||||
| #endif | ||||
| 
 | ||||
| 		// Write the facet into memory.
 | ||||
| 		stl->facet_start[i] = facet; | ||||
| 		stl_facet_stats(stl, facet, first); | ||||
|   	} | ||||
|    | ||||
|   	stl->stats.size = stl->stats.max - stl->stats.min; | ||||
|   	stl->stats.bounding_diameter = stl->stats.size.norm(); | ||||
|   	return true; | ||||
| } | ||||
| 
 | ||||
| bool stl_open(stl_file *stl, const char *file) | ||||
| { | ||||
| 	stl->clear(); | ||||
| 	FILE *fp = stl_open_count_facets(stl, file); | ||||
| 	if (fp == nullptr) | ||||
| 		return false; | ||||
| 	stl_allocate(stl); | ||||
| 	bool result = stl_read(stl, fp, 0, true); | ||||
|   	fclose(fp); | ||||
|   	return result; | ||||
| } | ||||
| 
 | ||||
| #ifndef BOOST_LITTLE_ENDIAN | ||||
| extern void stl_internal_reverse_quads(char *buf, size_t cnt); | ||||
| #endif /* BOOST_LITTLE_ENDIAN */ | ||||
| 
 | ||||
| void | ||||
| stl_count_facets(stl_file *stl, const char *file) { | ||||
|   long           file_size; | ||||
|   uint32_t       header_num_facets; | ||||
|   uint32_t       num_facets; | ||||
|   int            i; | ||||
|   size_t         s; | ||||
|   unsigned char  chtest[128]; | ||||
|   int            num_lines = 1; | ||||
|   char           *error_msg; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /* Open the file in binary mode first */ | ||||
|   stl->fp = boost::nowide::fopen(file, "rb"); | ||||
|   if(stl->fp == NULL) { | ||||
|     error_msg = (char*) | ||||
|                 malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|     sprintf(error_msg, "stl_initialize: Couldn't open %s for reading", | ||||
|             file); | ||||
|     perror(error_msg); | ||||
|     free(error_msg); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
|   /* Find size of file */ | ||||
|   fseek(stl->fp, 0, SEEK_END); | ||||
|   file_size = ftell(stl->fp); | ||||
| 
 | ||||
|   /* Check for binary or ASCII file */ | ||||
|   fseek(stl->fp, HEADER_SIZE, SEEK_SET); | ||||
|   if (!fread(chtest, sizeof(chtest), 1, stl->fp)) { | ||||
|     perror("The input is an empty file"); | ||||
|     stl->error = 1; | ||||
|     return; | ||||
|   } | ||||
|   stl->stats.type = ascii; | ||||
|   for(s = 0; s < sizeof(chtest); s++) { | ||||
|     if(chtest[s] > 127) { | ||||
|       stl->stats.type = binary; | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   rewind(stl->fp); | ||||
| 
 | ||||
|   /* Get the header and the number of facets in the .STL file */ | ||||
|   /* If the .STL file is binary, then do the following */ | ||||
|   if(stl->stats.type == binary) { | ||||
|     /* Test if the STL file has the right size  */ | ||||
|     if(((file_size - HEADER_SIZE) % SIZEOF_STL_FACET != 0) | ||||
|         || (file_size < STL_MIN_FILE_SIZE)) { | ||||
|       fprintf(stderr, "The file %s has the wrong size.\n", file); | ||||
|       stl->error = 1; | ||||
|       return; | ||||
|     } | ||||
|     num_facets = (file_size - HEADER_SIZE) / SIZEOF_STL_FACET; | ||||
| 
 | ||||
|     /* Read the header */ | ||||
|     if (fread(stl->stats.header, LABEL_SIZE, 1, stl->fp) > 79) { | ||||
|       stl->stats.header[80] = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     /* Read the int following the header.  This should contain # of facets */ | ||||
|     bool header_num_faces_read = fread(&header_num_facets, sizeof(uint32_t), 1, stl->fp) != 0; | ||||
| #ifndef BOOST_LITTLE_ENDIAN | ||||
|     // Convert from little endian to big endian.
 | ||||
|     stl_internal_reverse_quads((char*)&header_num_facets, 4); | ||||
| #endif /* BOOST_LITTLE_ENDIAN */ | ||||
|     if (! header_num_faces_read || num_facets != header_num_facets) { | ||||
|       fprintf(stderr, | ||||
|               "Warning: File size doesn't match number of facets in the header\n"); | ||||
|     } | ||||
|   } | ||||
|   /* Otherwise, if the .STL file is ASCII, then do the following */ | ||||
|   else { | ||||
|     /* Reopen the file in text mode (for getting correct newlines on Windows) */ | ||||
|     // fix to silence a warning about unused return value.
 | ||||
|     // obviously if it fails we have problems....
 | ||||
|     stl->fp = boost::nowide::freopen(file, "r", stl->fp); | ||||
| 
 | ||||
|     // do another null check to be safe
 | ||||
|     if(stl->fp == NULL) { | ||||
|       error_msg = (char*) | ||||
|         malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ | ||||
|       sprintf(error_msg, "stl_initialize: Couldn't open %s for reading", | ||||
|           file); | ||||
|       perror(error_msg); | ||||
|       free(error_msg); | ||||
|       stl->error = 1; | ||||
|       return; | ||||
|     } | ||||
|      | ||||
|     /* Find the number of facets */ | ||||
|     char linebuf[100]; | ||||
|     while (fgets(linebuf, 100, stl->fp) != NULL) { | ||||
|         /* don't count short lines */ | ||||
|         if (strlen(linebuf) <= 4) continue; | ||||
|          | ||||
|         /* skip solid/endsolid lines as broken STL file generators may put several of them */ | ||||
|         if (strncmp(linebuf, "solid", 5) == 0 || strncmp(linebuf, "endsolid", 8) == 0) continue; | ||||
|          | ||||
|         ++num_lines; | ||||
|     } | ||||
|      | ||||
|     rewind(stl->fp); | ||||
|      | ||||
|     /* Get the header */ | ||||
|     for(i = 0; | ||||
|         (i < 80) && (stl->stats.header[i] = getc(stl->fp)) != '\n'; i++); | ||||
|     stl->stats.header[i] = '\0'; /* Lose the '\n' */ | ||||
|     stl->stats.header[80] = '\0'; | ||||
| 
 | ||||
|     num_facets = num_lines / ASCII_LINES_PER_FACET; | ||||
|   } | ||||
|   stl->stats.number_of_facets += num_facets; | ||||
|   stl->stats.original_num_facets = stl->stats.number_of_facets; | ||||
| void stl_allocate(stl_file *stl)  | ||||
| { | ||||
|   	//  Allocate memory for the entire .STL file.
 | ||||
|   	stl->facet_start.assign(stl->stats.number_of_facets, stl_facet()); | ||||
|   	// Allocate memory for the neighbors list.
 | ||||
|   	stl->neighbors_start.assign(stl->stats.number_of_facets, stl_neighbors()); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_allocate(stl_file *stl) { | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /*  Allocate memory for the entire .STL file */ | ||||
|   stl->facet_start = (stl_facet*)calloc(stl->stats.number_of_facets, | ||||
|                                         sizeof(stl_facet)); | ||||
|   if(stl->facet_start == NULL) perror("stl_initialize"); | ||||
|   stl->stats.facets_malloced = stl->stats.number_of_facets; | ||||
| 
 | ||||
|   /* Allocate memory for the neighbors list */ | ||||
|   stl->neighbors_start = (stl_neighbors*) | ||||
|                          calloc(stl->stats.number_of_facets, sizeof(stl_neighbors)); | ||||
|   if(stl->facet_start == NULL) perror("stl_initialize"); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_open_merge(stl_file *stl, char *file_to_merge) { | ||||
|   int num_facets_so_far; | ||||
|   stl_type origStlType; | ||||
|   FILE *origFp; | ||||
|   stl_file stl_to_merge; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   /* Record how many facets we have so far from the first file.  We will start putting
 | ||||
|      facets in the next position.  Since we're 0-indexed, it'l be the same position. */ | ||||
|   num_facets_so_far = stl->stats.number_of_facets; | ||||
| 
 | ||||
|   /* Record the file type we started with: */ | ||||
|   origStlType=stl->stats.type; | ||||
|   /* Record the file pointer too: */ | ||||
|   origFp=stl->fp; | ||||
| 
 | ||||
|   /* Initialize the sturucture with zero stats, header info and sizes: */ | ||||
|   stl_initialize(&stl_to_merge); | ||||
|   stl_count_facets(&stl_to_merge, file_to_merge); | ||||
| 
 | ||||
|   /* Copy what we need to into stl so that we can read the file_to_merge directly into it
 | ||||
|      using stl_read:  Save the rest of the valuable info: */ | ||||
|   stl->stats.type=stl_to_merge.stats.type; | ||||
|   stl->fp=stl_to_merge.fp; | ||||
| 
 | ||||
|   /* Add the number of facets we already have in stl with what we we found in stl_to_merge but
 | ||||
|      haven't read yet. */ | ||||
|   stl->stats.number_of_facets=num_facets_so_far+stl_to_merge.stats.number_of_facets; | ||||
| 
 | ||||
|   /* Allocate enough room for stl->stats.number_of_facets facets and neighbors: */ | ||||
|   stl_reallocate(stl); | ||||
| 
 | ||||
|   /* Read the file to merge directly into stl, adding it to what we have already.
 | ||||
|      Start at num_facets_so_far, the index to the first unused facet.  Also say | ||||
|      that this isn't our first time so we should augment stats like min and max | ||||
|      instead of erasing them. */ | ||||
|   stl_read(stl, num_facets_so_far, false); | ||||
| 
 | ||||
|   /* Restore the stl information we overwrote (for stl_read) so that it still accurately
 | ||||
|      reflects the subject part: */ | ||||
|   stl->stats.type=origStlType; | ||||
|   stl->fp=origFp; | ||||
| } | ||||
| 
 | ||||
| extern void | ||||
| stl_reallocate(stl_file *stl) { | ||||
|   if (stl->error) return; | ||||
|   /*  Reallocate more memory for the .STL file(s) */ | ||||
|   stl->facet_start = (stl_facet*)realloc(stl->facet_start, stl->stats.number_of_facets * | ||||
|                                          sizeof(stl_facet)); | ||||
|   if(stl->facet_start == NULL) perror("stl_initialize"); | ||||
|   stl->stats.facets_malloced = stl->stats.number_of_facets; | ||||
| 
 | ||||
|   /* Reallocate more memory for the neighbors list */ | ||||
|   stl->neighbors_start = (stl_neighbors*) | ||||
|                          realloc(stl->neighbors_start, stl->stats.number_of_facets * | ||||
|                                  sizeof(stl_neighbors)); | ||||
|   if(stl->facet_start == NULL) perror("stl_initialize"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Reads the contents of the file pointed to by stl->fp into the stl structure,
 | ||||
|    starting at facet first_facet.  The second argument says if it's our first | ||||
|    time running this for the stl and therefore we should reset our max and min stats. */ | ||||
| void stl_read(stl_file *stl, int first_facet, bool first) { | ||||
|   stl_facet facet; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   if(stl->stats.type == binary) { | ||||
|     fseek(stl->fp, HEADER_SIZE, SEEK_SET); | ||||
|   } else { | ||||
|     rewind(stl->fp); | ||||
|   } | ||||
| 
 | ||||
|   char normal_buf[3][32]; | ||||
|   for(uint32_t i = first_facet; i < stl->stats.number_of_facets; i++) { | ||||
|     if(stl->stats.type == binary) | ||||
|       /* Read a single facet from a binary .STL file */ | ||||
|     { | ||||
|       /* we assume little-endian architecture! */ | ||||
|       if (fread(&facet, 1, SIZEOF_STL_FACET, stl->fp) != SIZEOF_STL_FACET) { | ||||
|         stl->error = 1; | ||||
|         return; | ||||
|       } | ||||
| #ifndef BOOST_LITTLE_ENDIAN | ||||
|       // Convert the loaded little endian data to big endian.
 | ||||
|       stl_internal_reverse_quads((char*)&facet, 48); | ||||
| #endif /* BOOST_LITTLE_ENDIAN */ | ||||
|     } else | ||||
|       /* Read a single facet from an ASCII .STL file */ | ||||
|     { | ||||
|       // skip solid/endsolid
 | ||||
|       // (in this order, otherwise it won't work when they are paired in the middle of a file)
 | ||||
|       fscanf(stl->fp, "endsolid%*[^\n]\n"); | ||||
|       fscanf(stl->fp, "solid%*[^\n]\n");  // name might contain spaces so %*s doesn't work and it also can be empty (just "solid")
 | ||||
|       // Leading space in the fscanf format skips all leading white spaces including numerous new lines and tabs.
 | ||||
|       int res_normal     = fscanf(stl->fp, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]); | ||||
|       assert(res_normal == 3); | ||||
|       int res_outer_loop = fscanf(stl->fp, " outer loop"); | ||||
|       assert(res_outer_loop == 0); | ||||
|       int res_vertex1    = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); | ||||
|       assert(res_vertex1 == 3); | ||||
|       int res_vertex2    = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); | ||||
|       assert(res_vertex2 == 3); | ||||
|       int res_vertex3    = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); | ||||
|       assert(res_vertex3 == 3); | ||||
|       int res_endloop    = fscanf(stl->fp, " endloop"); | ||||
|       assert(res_endloop == 0); | ||||
|       // There is a leading and trailing white space around endfacet to eat up all leading and trailing white spaces including numerous tabs and new lines.
 | ||||
|       int res_endfacet   = fscanf(stl->fp, " endfacet "); | ||||
|       if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) { | ||||
|         perror("Something is syntactically very wrong with this ASCII STL!"); | ||||
|         stl->error = 1; | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition.
 | ||||
| 	  if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 || | ||||
| 		  sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 || | ||||
| 		  sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { | ||||
| 		  // Normal was mangled. Maybe denormals or "not a number" were stored?
 | ||||
| 		  // Just reset the normal and silently ignore it.
 | ||||
| 		  memset(&facet.normal, 0, sizeof(facet.normal)); | ||||
| 	  } | ||||
|     } | ||||
| 
 | ||||
| #if 0 | ||||
|       // Report close to zero vertex coordinates. Due to the nature of the floating point numbers,
 | ||||
|       // close to zero values may be represented with singificantly higher precision than the rest of the vertices.
 | ||||
|       // It may be worth to round these numbers to zero during loading to reduce the number of errors reported
 | ||||
|       // during the STL import.
 | ||||
|       for (size_t j = 0; j < 3; ++ j) { | ||||
|         if (facet.vertex[j](0) > -1e-12f && facet.vertex[j](0) < 1e-12f) | ||||
|             printf("stl_read: facet %d(0) = %e\r\n", j, facet.vertex[j](0)); | ||||
|         if (facet.vertex[j](1) > -1e-12f && facet.vertex[j](1) < 1e-12f) | ||||
|             printf("stl_read: facet %d(1) = %e\r\n", j, facet.vertex[j](1)); | ||||
|         if (facet.vertex[j](2) > -1e-12f && facet.vertex[j](2) < 1e-12f) | ||||
|             printf("stl_read: facet %d(2) = %e\r\n", j, facet.vertex[j](2)); | ||||
|       } | ||||
| #endif | ||||
| 
 | ||||
|     /* Write the facet into memory. */ | ||||
|     stl->facet_start[i] = facet; | ||||
|     stl_facet_stats(stl, facet, first); | ||||
|   } | ||||
|   stl->stats.size = stl->stats.max - stl->stats.min; | ||||
|   stl->stats.bounding_diameter = stl->stats.size.norm(); | ||||
| void stl_reallocate(stl_file *stl)  | ||||
| { | ||||
| 	stl->facet_start.resize(stl->stats.number_of_facets); | ||||
| 	stl->neighbors_start.resize(stl->stats.number_of_facets); | ||||
| } | ||||
| 
 | ||||
| void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first) | ||||
| { | ||||
|   if (stl->error) | ||||
|   	return; | ||||
| 	// While we are going through all of the facets, let's find the
 | ||||
| 	// maximum and minimum values for x, y, and z
 | ||||
| 
 | ||||
|   // While we are going through all of the facets, let's find the
 | ||||
|   // maximum and minimum values for x, y, and z
 | ||||
| 	if (first) { | ||||
| 		// Initialize the max and min values the first time through
 | ||||
| 		stl->stats.min = facet.vertex[0]; | ||||
| 		stl->stats.max = facet.vertex[0]; | ||||
| 		stl_vertex diff = (facet.vertex[1] - facet.vertex[0]).cwiseAbs(); | ||||
| 		stl->stats.shortest_edge = std::max(diff(0), std::max(diff(1), diff(2))); | ||||
| 		first = false; | ||||
| 	} | ||||
| 
 | ||||
|   if (first) { | ||||
| 	// Initialize the max and min values the first time through
 | ||||
|     stl->stats.min = facet.vertex[0]; | ||||
|     stl->stats.max = facet.vertex[0]; | ||||
|     stl_vertex diff = (facet.vertex[1] - facet.vertex[0]).cwiseAbs(); | ||||
|     stl->stats.shortest_edge = std::max(diff(0), std::max(diff(1), diff(2))); | ||||
|     first = false; | ||||
|   } | ||||
| 
 | ||||
|   // Now find the max and min values.
 | ||||
|   for (size_t i = 0; i < 3; ++ i) { | ||||
|   	stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]); | ||||
|   	stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void stl_close(stl_file *stl) | ||||
| { | ||||
| 	assert(stl->fp == nullptr); | ||||
| 	assert(stl->heads == nullptr); | ||||
| 	assert(stl->tail == nullptr); | ||||
| 
 | ||||
| 	if (stl->facet_start != NULL) | ||||
| 		free(stl->facet_start); | ||||
| 	if (stl->neighbors_start != NULL) | ||||
| 		free(stl->neighbors_start); | ||||
| 	if (stl->v_indices != NULL) | ||||
| 		free(stl->v_indices); | ||||
| 	if (stl->v_shared != NULL) | ||||
| 		free(stl->v_shared); | ||||
| 	memset(stl, 0, sizeof(stl_file)); | ||||
| 	// Now find the max and min values.
 | ||||
| 	for (size_t i = 0; i < 3; ++ i) { | ||||
| 		stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]); | ||||
| 		stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -25,435 +25,375 @@ | |||
| #include <string.h> | ||||
| #include <math.h> | ||||
| 
 | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| #include "stl.h" | ||||
| 
 | ||||
| static void stl_rotate(float *x, float *y, const double c, const double s); | ||||
| static float get_area(stl_facet *facet); | ||||
| static float get_volume(stl_file *stl); | ||||
| void stl_verify_neighbors(stl_file *stl) | ||||
| { | ||||
| 	stl->stats.backwards_edges = 0; | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| stl_verify_neighbors(stl_file *stl) { | ||||
|   int i; | ||||
|   int j; | ||||
|   stl_edge edge_a; | ||||
|   stl_edge edge_b; | ||||
|   int neighbor; | ||||
|   int vnot; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   stl->stats.backwards_edges = 0; | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     for(j = 0; j < 3; j++) { | ||||
|       edge_a.p1 = stl->facet_start[i].vertex[j]; | ||||
|       edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3]; | ||||
|       neighbor = stl->neighbors_start[i].neighbor[j]; | ||||
|       vnot = stl->neighbors_start[i].which_vertex_not[j]; | ||||
| 
 | ||||
|       if(neighbor == -1) | ||||
|         continue;		/* this edge has no neighbor... Continue. */ | ||||
|       if(vnot < 3) { | ||||
|         edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; | ||||
|         edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; | ||||
|       } else { | ||||
|         stl->stats.backwards_edges += 1; | ||||
|         edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; | ||||
|         edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; | ||||
|       } | ||||
|       if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) { | ||||
|         /* These edges should match but they don't.  Print results. */ | ||||
|         printf("edge %d of facet %d doesn't match edge %d of facet %d\n", | ||||
|                j, i, vnot + 1, neighbor); | ||||
|         stl_write_facet(stl, (char*)"first facet", i); | ||||
|         stl_write_facet(stl, (char*)"second facet", neighbor); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		for (int j = 0; j < 3; ++ j) { | ||||
| 			struct stl_edge { | ||||
| 				stl_vertex p1; | ||||
| 				stl_vertex p2; | ||||
| 				int        facet_number; | ||||
| 			}; | ||||
| 			stl_edge edge_a; | ||||
| 			edge_a.p1 = stl->facet_start[i].vertex[j]; | ||||
| 			edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3]; | ||||
| 			int neighbor = stl->neighbors_start[i].neighbor[j]; | ||||
| 			if (neighbor == -1) | ||||
| 				continue; // this edge has no neighbor... Continue.
 | ||||
| 			int vnot = stl->neighbors_start[i].which_vertex_not[j]; | ||||
| 			stl_edge edge_b; | ||||
| 			if (vnot < 3) { | ||||
| 				edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; | ||||
| 				edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; | ||||
| 			} else { | ||||
| 				stl->stats.backwards_edges += 1; | ||||
| 				edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; | ||||
| 				edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; | ||||
| 			} | ||||
| 			if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) { | ||||
| 				// These edges should match but they don't.  Print results.
 | ||||
| 				BOOST_LOG_TRIVIAL(info) << "edge " << j << " of facet " << i << " doesn't match edge " << (vnot + 1) << " of facet " << neighbor; | ||||
| 				stl_write_facet(stl, (char*)"first facet", i); | ||||
| 				stl_write_facet(stl, (char*)"second facet", neighbor); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void stl_translate(stl_file *stl, float x, float y, float z) | ||||
| { | ||||
|   if (stl->error) | ||||
|   	return; | ||||
| 
 | ||||
|   stl_vertex new_min(x, y, z); | ||||
|   stl_vertex shift = new_min - stl->stats.min; | ||||
|   for (int i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     for (int j = 0; j < 3; ++ j) | ||||
|       stl->facet_start[i].vertex[j] += shift; | ||||
|   stl->stats.min = new_min; | ||||
|   stl->stats.max += shift; | ||||
|   stl_invalidate_shared_vertices(stl); | ||||
| 	stl_vertex new_min(x, y, z); | ||||
| 	stl_vertex shift = new_min - stl->stats.min; | ||||
| 	for (int i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
| 		for (int j = 0; j < 3; ++ j) | ||||
| 	  		stl->facet_start[i].vertex[j] += shift; | ||||
| 	stl->stats.min = new_min; | ||||
| 	stl->stats.max += shift; | ||||
| } | ||||
| 
 | ||||
| /* Translates the stl by x,y,z, relatively from wherever it is currently */ | ||||
| void stl_translate_relative(stl_file *stl, float x, float y, float z) | ||||
| { | ||||
|   if (stl->error) | ||||
|   	return; | ||||
| 
 | ||||
|   stl_vertex shift(x, y, z); | ||||
|   for (int i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     for (int j = 0; j < 3; ++ j) | ||||
|       stl->facet_start[i].vertex[j] += shift; | ||||
|   stl->stats.min += shift; | ||||
|   stl->stats.max += shift; | ||||
|   stl_invalidate_shared_vertices(stl); | ||||
| 	stl_vertex shift(x, y, z); | ||||
| 	for (int i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
| 		for (int j = 0; j < 3; ++ j) | ||||
| 	  		stl->facet_start[i].vertex[j] += shift; | ||||
| 	stl->stats.min += shift; | ||||
| 	stl->stats.max += shift; | ||||
| } | ||||
| 
 | ||||
| void stl_scale_versor(stl_file *stl, const stl_vertex &versor) | ||||
| { | ||||
|   if (stl->error) | ||||
|   	return; | ||||
| 
 | ||||
|   // Scale extents.
 | ||||
|   auto s = versor.array(); | ||||
|   stl->stats.min.array() *= s; | ||||
|   stl->stats.max.array() *= s; | ||||
|   // Scale size.
 | ||||
|   stl->stats.size.array() *= s; | ||||
|   // Scale volume.
 | ||||
|   if (stl->stats.volume > 0.0) | ||||
|     stl->stats.volume *= versor(0) * versor(1) * versor(2); | ||||
|   // Scale the mesh.
 | ||||
|   for (int i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     for (int j = 0; j < 3; ++ j) | ||||
|       stl->facet_start[i].vertex[j].array() *= s; | ||||
|   stl_invalidate_shared_vertices(stl); | ||||
| 	// Scale extents.
 | ||||
| 	auto s = versor.array(); | ||||
| 	stl->stats.min.array() *= s; | ||||
| 	stl->stats.max.array() *= s; | ||||
| 	// Scale size.
 | ||||
| 	stl->stats.size.array() *= s; | ||||
| 	// Scale volume.
 | ||||
| 	if (stl->stats.volume > 0.0) | ||||
| 		stl->stats.volume *= versor(0) * versor(1) * versor(2); | ||||
| 	// Scale the mesh.
 | ||||
| 	for (int i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
| 		for (int j = 0; j < 3; ++ j) | ||||
| 	  		stl->facet_start[i].vertex[j].array() *= s; | ||||
| } | ||||
| 
 | ||||
| static void calculate_normals(stl_file *stl)  | ||||
| { | ||||
|   if (stl->error) | ||||
|   	return; | ||||
| 
 | ||||
|   stl_normal normal; | ||||
|   for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     stl_calculate_normal(normal, &stl->facet_start[i]); | ||||
|     stl_normalize_vector(normal); | ||||
|     stl->facet_start[i].normal = normal; | ||||
|   } | ||||
| 	stl_normal normal; | ||||
| 	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
| 		stl_calculate_normal(normal, &stl->facet_start[i]); | ||||
| 		stl_normalize_vector(normal); | ||||
| 		stl->facet_start[i].normal = normal; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_rotate_x(stl_file *stl, float angle) { | ||||
|   int i; | ||||
|   int j; | ||||
|   double radian_angle = (angle / 180.0) * M_PI; | ||||
|   double c = cos(radian_angle); | ||||
|   double s = sin(radian_angle); | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     for(j = 0; j < 3; j++) { | ||||
|       stl_rotate(&stl->facet_start[i].vertex[j](1), | ||||
|                  &stl->facet_start[i].vertex[j](2), c, s); | ||||
|     } | ||||
|   } | ||||
|   stl_get_size(stl); | ||||
|   calculate_normals(stl); | ||||
| static inline void rotate_point_2d(float &x, float &y, const double c, const double s) | ||||
| { | ||||
| 	double xold = x; | ||||
| 	double yold = y; | ||||
| 	x = float(c * xold - s * yold); | ||||
| 	y = float(s * xold + c * yold); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_rotate_y(stl_file *stl, float angle) { | ||||
|   int i; | ||||
|   int j; | ||||
|   double radian_angle = (angle / 180.0) * M_PI; | ||||
|   double c = cos(radian_angle); | ||||
|   double s = sin(radian_angle); | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     for(j = 0; j < 3; j++) { | ||||
|       stl_rotate(&stl->facet_start[i].vertex[j](2), | ||||
|                  &stl->facet_start[i].vertex[j](0), c, s); | ||||
|     } | ||||
|   } | ||||
|   stl_get_size(stl); | ||||
|   calculate_normals(stl); | ||||
| void stl_rotate_x(stl_file *stl, float angle) | ||||
| { | ||||
| 	double radian_angle = (angle / 180.0) * M_PI; | ||||
| 	double c = cos(radian_angle); | ||||
| 	double s = sin(radian_angle); | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     	for (int j = 0; j < 3; ++ j) | ||||
|       		rotate_point_2d(stl->facet_start[i].vertex[j](1), stl->facet_start[i].vertex[j](2), c, s); | ||||
|   	stl_get_size(stl); | ||||
|   	calculate_normals(stl); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| stl_rotate_z(stl_file *stl, float angle) { | ||||
|   int i; | ||||
|   int j; | ||||
|   double radian_angle = (angle / 180.0) * M_PI; | ||||
|   double c = cos(radian_angle); | ||||
|   double s = sin(radian_angle); | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   for(i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     for(j = 0; j < 3; j++) { | ||||
|       stl_rotate(&stl->facet_start[i].vertex[j](0), | ||||
|                  &stl->facet_start[i].vertex[j](1), c, s); | ||||
|     } | ||||
|   } | ||||
|   stl_get_size(stl); | ||||
|   calculate_normals(stl); | ||||
| void stl_rotate_y(stl_file *stl, float angle) | ||||
| { | ||||
| 	double radian_angle = (angle / 180.0) * M_PI; | ||||
| 	double c = cos(radian_angle); | ||||
| 	double s = sin(radian_angle); | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     	for (int j = 0; j < 3; ++ j) | ||||
| 			rotate_point_2d(stl->facet_start[i].vertex[j](2), stl->facet_start[i].vertex[j](0), c, s); | ||||
|   	stl_get_size(stl); | ||||
|   	calculate_normals(stl); | ||||
| } | ||||
| 
 | ||||
| void stl_rotate_z(stl_file *stl, float angle) | ||||
| { | ||||
| 	double radian_angle = (angle / 180.0) * M_PI; | ||||
| 	double c = cos(radian_angle); | ||||
| 	double s = sin(radian_angle); | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     	for (int j = 0; j < 3; ++ j) | ||||
|       		rotate_point_2d(stl->facet_start[i].vertex[j](0), stl->facet_start[i].vertex[j](1), c, s); | ||||
|   	stl_get_size(stl); | ||||
|   	calculate_normals(stl); | ||||
| } | ||||
| 
 | ||||
| void its_rotate_x(indexed_triangle_set &its, float angle) | ||||
| { | ||||
| 	double radian_angle = (angle / 180.0) * M_PI; | ||||
| 	double c = cos(radian_angle); | ||||
| 	double s = sin(radian_angle); | ||||
| 	for (stl_vertex &v : its.vertices) | ||||
| 		rotate_point_2d(v(1), v(2), c, s); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| stl_rotate(float *x, float *y, const double c, const double s) { | ||||
|   double xold = *x; | ||||
|   double yold = *y; | ||||
|   *x = float(c * xold - s * yold); | ||||
|   *y = float(s * xold + c * yold); | ||||
| void its_rotate_y(indexed_triangle_set& its, float angle) | ||||
| { | ||||
| 	double radian_angle = (angle / 180.0) * M_PI; | ||||
| 	double c = cos(radian_angle); | ||||
| 	double s = sin(radian_angle); | ||||
| 	for (stl_vertex& v : its.vertices) | ||||
| 		rotate_point_2d(v(2), v(0), c, s); | ||||
| } | ||||
| 
 | ||||
| void its_rotate_z(indexed_triangle_set& its, float angle) | ||||
| { | ||||
| 	double radian_angle = (angle / 180.0) * M_PI; | ||||
| 	double c = cos(radian_angle); | ||||
| 	double s = sin(radian_angle); | ||||
| 	for (stl_vertex& v : its.vertices) | ||||
| 		rotate_point_2d(v(0), v(1), c, s); | ||||
| } | ||||
| 
 | ||||
| void stl_get_size(stl_file *stl) | ||||
| { | ||||
|   if (stl->error || stl->stats.number_of_facets == 0) | ||||
|   	return; | ||||
|   stl->stats.min = stl->facet_start[0].vertex[0]; | ||||
|   stl->stats.max = stl->stats.min; | ||||
|   for (int i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|   	const stl_facet &face = stl->facet_start[i]; | ||||
|     for (int j = 0; j < 3; ++ j) { | ||||
|       stl->stats.min = stl->stats.min.cwiseMin(face.vertex[j]); | ||||
|       stl->stats.max = stl->stats.max.cwiseMax(face.vertex[j]); | ||||
|     } | ||||
|   } | ||||
|   stl->stats.size = stl->stats.max - stl->stats.min; | ||||
|   stl->stats.bounding_diameter = stl->stats.size.norm(); | ||||
|   	if (stl->stats.number_of_facets == 0) | ||||
|   		return; | ||||
|   	stl->stats.min = stl->facet_start[0].vertex[0]; | ||||
|   	stl->stats.max = stl->stats.min; | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|   		const stl_facet &face = stl->facet_start[i]; | ||||
|     	for (int j = 0; j < 3; ++ j) { | ||||
|       		stl->stats.min = stl->stats.min.cwiseMin(face.vertex[j]); | ||||
|       		stl->stats.max = stl->stats.max.cwiseMax(face.vertex[j]); | ||||
|     	} | ||||
|   	} | ||||
|   	stl->stats.size = stl->stats.max - stl->stats.min; | ||||
|   	stl->stats.bounding_diameter = stl->stats.size.norm(); | ||||
| } | ||||
| 
 | ||||
| void stl_mirror_xy(stl_file *stl) | ||||
| { | ||||
|   if (stl->error)  | ||||
|   	return; | ||||
| 
 | ||||
|   for(int i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     for(int j = 0; j < 3; j++) { | ||||
|       stl->facet_start[i].vertex[j](2) *= -1.0; | ||||
|     } | ||||
|   } | ||||
|   float temp_size = stl->stats.min(2); | ||||
|   stl->stats.min(2) = stl->stats.max(2); | ||||
|   stl->stats.max(2) = temp_size; | ||||
|   stl->stats.min(2) *= -1.0; | ||||
|   stl->stats.max(2) *= -1.0; | ||||
|   stl_reverse_all_facets(stl); | ||||
|   stl->stats.facets_reversed -= stl->stats.number_of_facets;  /* for not altering stats */ | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     	for (int j = 0; j < 3; ++ j) | ||||
|       		stl->facet_start[i].vertex[j](2) *= -1.0; | ||||
| 	float temp_size = stl->stats.min(2); | ||||
| 	stl->stats.min(2) = stl->stats.max(2); | ||||
| 	stl->stats.max(2) = temp_size; | ||||
| 	stl->stats.min(2) *= -1.0; | ||||
| 	stl->stats.max(2) *= -1.0; | ||||
| 	stl_reverse_all_facets(stl); | ||||
| 	stl->stats.facets_reversed -= stl->stats.number_of_facets;  /* for not altering stats */ | ||||
| } | ||||
| 
 | ||||
| void stl_mirror_yz(stl_file *stl) | ||||
| { | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   for (int i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     for (int j = 0; j < 3; j++) { | ||||
|       stl->facet_start[i].vertex[j](0) *= -1.0; | ||||
|     } | ||||
|   } | ||||
|   float temp_size = stl->stats.min(0); | ||||
|   stl->stats.min(0) = stl->stats.max(0); | ||||
|   stl->stats.max(0) = temp_size; | ||||
|   stl->stats.min(0) *= -1.0; | ||||
|   stl->stats.max(0) *= -1.0; | ||||
|   stl_reverse_all_facets(stl); | ||||
|   stl->stats.facets_reversed -= stl->stats.number_of_facets;  /* for not altering stats */ | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
|     	for (int j = 0; j < 3; j++) | ||||
|       		stl->facet_start[i].vertex[j](0) *= -1.0; | ||||
| 	float temp_size = stl->stats.min(0); | ||||
| 	stl->stats.min(0) = stl->stats.max(0); | ||||
| 	stl->stats.max(0) = temp_size; | ||||
| 	stl->stats.min(0) *= -1.0; | ||||
| 	stl->stats.max(0) *= -1.0; | ||||
| 	stl_reverse_all_facets(stl); | ||||
| 	stl->stats.facets_reversed -= stl->stats.number_of_facets;  /* for not altering stats */ | ||||
| } | ||||
| 
 | ||||
| void stl_mirror_xz(stl_file *stl) | ||||
| { | ||||
|   if (stl->error) | ||||
|   	return; | ||||
| 
 | ||||
|   for (int i = 0; i < stl->stats.number_of_facets; i++) { | ||||
|     for (int j = 0; j < 3; j++) { | ||||
|       stl->facet_start[i].vertex[j](1) *= -1.0; | ||||
|     } | ||||
|   } | ||||
|   float temp_size = stl->stats.min(1); | ||||
|   stl->stats.min(1) = stl->stats.max(1); | ||||
|   stl->stats.max(1) = temp_size; | ||||
|   stl->stats.min(1) *= -1.0; | ||||
|   stl->stats.max(1) *= -1.0; | ||||
|   stl_reverse_all_facets(stl); | ||||
|   stl->stats.facets_reversed -= stl->stats.number_of_facets;  /* for not altering stats */ | ||||
| } | ||||
| 
 | ||||
| static float get_volume(stl_file *stl) | ||||
| { | ||||
|   if (stl->error) | ||||
|   	return 0; | ||||
| 
 | ||||
|   // Choose a point, any point as the reference.
 | ||||
|   stl_vertex p0 = stl->facet_start[0].vertex[0]; | ||||
|   float volume = 0.f; | ||||
|   for(uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|     // Do dot product to get distance from point to plane.
 | ||||
|     float height = stl->facet_start[i].normal.dot(stl->facet_start[i].vertex[0] - p0); | ||||
|     float area   = get_area(&stl->facet_start[i]); | ||||
|     volume += (area * height) / 3.0f; | ||||
|   } | ||||
|   return volume; | ||||
| } | ||||
| 
 | ||||
| void stl_calculate_volume(stl_file *stl) | ||||
| { | ||||
|   if (stl->error) return; | ||||
|   stl->stats.volume = get_volume(stl); | ||||
|   if(stl->stats.volume < 0.0) { | ||||
|     stl_reverse_all_facets(stl); | ||||
|     stl->stats.volume = -stl->stats.volume; | ||||
|   } | ||||
| 	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) | ||||
| 		for (int j = 0; j < 3; ++ j) | ||||
| 			stl->facet_start[i].vertex[j](1) *= -1.0; | ||||
| 	float temp_size = stl->stats.min(1); | ||||
| 	stl->stats.min(1) = stl->stats.max(1); | ||||
| 	stl->stats.max(1) = temp_size; | ||||
| 	stl->stats.min(1) *= -1.0; | ||||
| 	stl->stats.max(1) *= -1.0; | ||||
| 	stl_reverse_all_facets(stl); | ||||
| 	stl->stats.facets_reversed -= stl->stats.number_of_facets;  // for not altering stats
 | ||||
| } | ||||
| 
 | ||||
| static float get_area(stl_facet *facet) | ||||
| { | ||||
|   /* cast to double before calculating cross product because large coordinates
 | ||||
|      can result in overflowing product | ||||
|     (bad area is responsible for bad volume and bad facets reversal) */ | ||||
|   double cross[3][3]; | ||||
|   for (int i = 0; i < 3; i++) { | ||||
|     cross[i][0]=(((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](2)) - | ||||
|                  ((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](1))); | ||||
|     cross[i][1]=(((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](0)) - | ||||
|                  ((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](2))); | ||||
|     cross[i][2]=(((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](1)) - | ||||
|                  ((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](0))); | ||||
|   } | ||||
| 	/* cast to double before calculating cross product because large coordinates
 | ||||
| 	 can result in overflowing product | ||||
| 	(bad area is responsible for bad volume and bad facets reversal) */ | ||||
| 	double cross[3][3]; | ||||
| 	for (int i = 0; i < 3; i++) { | ||||
| 		cross[i][0]=(((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](2)) - | ||||
| 	             	 ((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](1))); | ||||
| 		cross[i][1]=(((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](0)) - | ||||
| 	             	 ((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](2))); | ||||
| 		cross[i][2]=(((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](1)) - | ||||
| 	             	 ((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](0))); | ||||
| 	} | ||||
| 
 | ||||
|   stl_normal sum; | ||||
|   sum(0) = cross[0][0] + cross[1][0] + cross[2][0]; | ||||
|   sum(1) = cross[0][1] + cross[1][1] + cross[2][1]; | ||||
|   sum(2) = cross[0][2] + cross[1][2] + cross[2][2]; | ||||
| 	stl_normal sum; | ||||
| 	sum(0) = cross[0][0] + cross[1][0] + cross[2][0]; | ||||
| 	sum(1) = cross[0][1] + cross[1][1] + cross[2][1]; | ||||
| 	sum(2) = cross[0][2] + cross[1][2] + cross[2][2]; | ||||
| 
 | ||||
|   // This should already be done.  But just in case, let's do it again.
 | ||||
|   //FIXME this is questionable. the "sum" normal should be accurate, while the normal "n" may be calculated with a low accuracy.
 | ||||
|   stl_normal n; | ||||
|   stl_calculate_normal(n, facet); | ||||
|   stl_normalize_vector(n); | ||||
|   return 0.5f * n.dot(sum); | ||||
| 	// This should already be done.  But just in case, let's do it again.
 | ||||
| 	//FIXME this is questionable. the "sum" normal should be accurate, while the normal "n" may be calculated with a low accuracy.
 | ||||
| 	stl_normal n; | ||||
| 	stl_calculate_normal(n, facet); | ||||
| 	stl_normalize_vector(n); | ||||
| 	return 0.5f * n.dot(sum); | ||||
| } | ||||
| 
 | ||||
| void stl_repair(stl_file *stl, | ||||
|                 int fixall_flag, | ||||
|                 int exact_flag, | ||||
|                 int tolerance_flag, | ||||
|                 float tolerance, | ||||
|                 int increment_flag, | ||||
|                 float increment, | ||||
|                 int nearby_flag, | ||||
|                 int iterations, | ||||
|                 int remove_unconnected_flag, | ||||
|                 int fill_holes_flag, | ||||
|                 int normal_directions_flag, | ||||
|                 int normal_values_flag, | ||||
|                 int reverse_all_flag, | ||||
|                 int verbose_flag) { | ||||
|    | ||||
|   int i; | ||||
|   int last_edges_fixed = 0; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   if(exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag | ||||
|       || fill_holes_flag || normal_directions_flag) { | ||||
|     if (verbose_flag) | ||||
|       printf("Checking exact...\n"); | ||||
|     exact_flag = 1; | ||||
|     stl_check_facets_exact(stl); | ||||
|     stl->stats.facets_w_1_bad_edge = | ||||
|       (stl->stats.connected_facets_2_edge - | ||||
|        stl->stats.connected_facets_3_edge); | ||||
|     stl->stats.facets_w_2_bad_edge = | ||||
|       (stl->stats.connected_facets_1_edge - | ||||
|        stl->stats.connected_facets_2_edge); | ||||
|     stl->stats.facets_w_3_bad_edge = | ||||
|       (stl->stats.number_of_facets - | ||||
|        stl->stats.connected_facets_1_edge); | ||||
|   } | ||||
| 
 | ||||
|   if(nearby_flag || fixall_flag) { | ||||
|     if(!tolerance_flag) { | ||||
|       tolerance = stl->stats.shortest_edge; | ||||
|     } | ||||
|     if(!increment_flag) { | ||||
|       increment = stl->stats.bounding_diameter / 10000.0; | ||||
|     } | ||||
| 
 | ||||
|     if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { | ||||
|       for(i = 0; i < iterations; i++) { | ||||
|         if(stl->stats.connected_facets_3_edge < | ||||
|             stl->stats.number_of_facets) { | ||||
|           if (verbose_flag) | ||||
|             printf("\
 | ||||
| Checking nearby. Tolerance= %f Iteration=%d of %d...", | ||||
|                  tolerance, i + 1, iterations); | ||||
|           stl_check_facets_nearby(stl, tolerance); | ||||
|           if (verbose_flag) | ||||
|             printf("  Fixed %d edges.\n", | ||||
|                  stl->stats.edges_fixed - last_edges_fixed); | ||||
|           last_edges_fixed = stl->stats.edges_fixed; | ||||
|           tolerance += increment; | ||||
|         } else { | ||||
|           if (verbose_flag) | ||||
|             printf("\
 | ||||
| All facets connected.  No further nearby check necessary.\n"); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       if (verbose_flag) | ||||
|         printf("All facets connected.  No nearby check necessary.\n"); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if(remove_unconnected_flag || fixall_flag || fill_holes_flag) { | ||||
|     if(stl->stats.connected_facets_3_edge <  stl->stats.number_of_facets) { | ||||
|       if (verbose_flag) | ||||
|         printf("Removing unconnected facets...\n"); | ||||
|       stl_remove_unconnected_facets(stl); | ||||
|     } else | ||||
|       if (verbose_flag) | ||||
|         printf("No unconnected need to be removed.\n"); | ||||
|   } | ||||
| 
 | ||||
|   if(fill_holes_flag || fixall_flag) { | ||||
|     if(stl->stats.connected_facets_3_edge <  stl->stats.number_of_facets) { | ||||
|       if (verbose_flag) | ||||
|         printf("Filling holes...\n"); | ||||
|       stl_fill_holes(stl); | ||||
|     } else | ||||
|       if (verbose_flag) | ||||
|         printf("No holes need to be filled.\n"); | ||||
|   } | ||||
| 
 | ||||
|   if(reverse_all_flag) { | ||||
|     if (verbose_flag) | ||||
|       printf("Reversing all facets...\n"); | ||||
|     stl_reverse_all_facets(stl); | ||||
|   } | ||||
| 
 | ||||
|   if(normal_directions_flag || fixall_flag) { | ||||
|     if (verbose_flag) | ||||
|       printf("Checking normal directions...\n"); | ||||
|     stl_fix_normal_directions(stl); | ||||
|   } | ||||
| 
 | ||||
|   if(normal_values_flag || fixall_flag) { | ||||
|     if (verbose_flag) | ||||
|       printf("Checking normal values...\n"); | ||||
|     stl_fix_normal_values(stl); | ||||
|   } | ||||
| 
 | ||||
|   /* Always calculate the volume.  It shouldn't take too long */ | ||||
|   if (verbose_flag) | ||||
|     printf("Calculating volume...\n"); | ||||
|   stl_calculate_volume(stl); | ||||
| 
 | ||||
|   if(exact_flag) { | ||||
|     if (verbose_flag) | ||||
|       printf("Verifying neighbors...\n"); | ||||
|     stl_verify_neighbors(stl); | ||||
|   } | ||||
| static float get_volume(stl_file *stl) | ||||
| { | ||||
|   	// Choose a point, any point as the reference.
 | ||||
|   	stl_vertex p0 = stl->facet_start[0].vertex[0]; | ||||
|   	float volume = 0.f; | ||||
|   	for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { | ||||
|     	// Do dot product to get distance from point to plane.
 | ||||
|     	float height = stl->facet_start[i].normal.dot(stl->facet_start[i].vertex[0] - p0); | ||||
|     	float area   = get_area(&stl->facet_start[i]); | ||||
|     	volume += (area * height) / 3.0f; | ||||
|   	} | ||||
|   	return volume; | ||||
| } | ||||
| 
 | ||||
| void stl_calculate_volume(stl_file *stl) | ||||
| { | ||||
|   	stl->stats.volume = get_volume(stl); | ||||
|   	if (stl->stats.volume < 0.0) { | ||||
|     	stl_reverse_all_facets(stl); | ||||
|     	stl->stats.volume = -stl->stats.volume; | ||||
|   	} | ||||
| } | ||||
| 
 | ||||
| void stl_repair( | ||||
| 	stl_file *stl, | ||||
| 	bool fixall_flag, | ||||
| 	bool exact_flag, | ||||
| 	bool tolerance_flag, | ||||
| 	float tolerance, | ||||
| 	bool increment_flag, | ||||
| 	float increment, | ||||
| 	bool nearby_flag, | ||||
| 	int iterations, | ||||
| 	bool remove_unconnected_flag, | ||||
| 	bool fill_holes_flag, | ||||
| 	bool normal_directions_flag, | ||||
| 	bool normal_values_flag, | ||||
| 	bool reverse_all_flag, | ||||
| 	bool verbose_flag) | ||||
| { | ||||
| 	if (exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag || fill_holes_flag || normal_directions_flag) { | ||||
| 		if (verbose_flag) | ||||
| 		  	printf("Checking exact...\n"); | ||||
| 		exact_flag = true; | ||||
| 		stl_check_facets_exact(stl); | ||||
| 		stl->stats.facets_w_1_bad_edge = (stl->stats.connected_facets_2_edge - stl->stats.connected_facets_3_edge); | ||||
| 		stl->stats.facets_w_2_bad_edge = (stl->stats.connected_facets_1_edge - stl->stats.connected_facets_2_edge); | ||||
| 		stl->stats.facets_w_3_bad_edge = (stl->stats.number_of_facets - stl->stats.connected_facets_1_edge); | ||||
| 	} | ||||
| 
 | ||||
|   	if (nearby_flag || fixall_flag) { | ||||
|     	if (! tolerance_flag) | ||||
|       		tolerance = stl->stats.shortest_edge; | ||||
|  	   	if (! increment_flag) | ||||
|       		increment = stl->stats.bounding_diameter / 10000.0; | ||||
|     } | ||||
| 
 | ||||
| 	if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { | ||||
| 	  	int last_edges_fixed = 0; | ||||
| 	  	for (int i = 0; i < iterations; ++ i) { | ||||
| 	    	if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) { | ||||
| 	      		if (verbose_flag) | ||||
| 	        		printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations); | ||||
| 	      		stl_check_facets_nearby(stl, tolerance); | ||||
| 	      		if (verbose_flag) | ||||
| 	        		printf("  Fixed %d edges.\n", stl->stats.edges_fixed - last_edges_fixed); | ||||
| 	      		last_edges_fixed = stl->stats.edges_fixed; | ||||
| 	      		tolerance += increment; | ||||
| 	    	} else { | ||||
| 	    		if (verbose_flag) | ||||
| 	        		printf("All facets connected.  No further nearby check necessary.\n"); | ||||
| 		      	break; | ||||
| 		    } | ||||
| 	  	} | ||||
| 	} else if (verbose_flag) | ||||
| 	    printf("All facets connected.  No nearby check necessary.\n"); | ||||
| 
 | ||||
| 	if (remove_unconnected_flag || fixall_flag || fill_holes_flag) { | ||||
| 		if (stl->stats.connected_facets_3_edge <  stl->stats.number_of_facets) { | ||||
| 	  		if (verbose_flag) | ||||
| 	    		printf("Removing unconnected facets...\n"); | ||||
| 	  		stl_remove_unconnected_facets(stl); | ||||
| 		} else if (verbose_flag) | ||||
| 	    	printf("No unconnected need to be removed.\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (fill_holes_flag || fixall_flag) { | ||||
| 		if (stl->stats.connected_facets_3_edge <  stl->stats.number_of_facets) { | ||||
| 	  		if (verbose_flag) | ||||
| 	    		printf("Filling holes...\n"); | ||||
| 	  		stl_fill_holes(stl); | ||||
| 		} else if (verbose_flag) | ||||
| 	    	printf("No holes need to be filled.\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (reverse_all_flag) { | ||||
| 		if (verbose_flag) | ||||
| 	  		printf("Reversing all facets...\n"); | ||||
| 		stl_reverse_all_facets(stl); | ||||
| 	} | ||||
| 
 | ||||
| 	if (normal_directions_flag || fixall_flag) { | ||||
| 		if (verbose_flag) | ||||
| 	  		printf("Checking normal directions...\n"); | ||||
| 		stl_fix_normal_directions(stl); | ||||
| 	} | ||||
| 
 | ||||
| 	if (normal_values_flag || fixall_flag) { | ||||
| 		if (verbose_flag) | ||||
| 	  		printf("Checking normal values...\n"); | ||||
| 		stl_fix_normal_values(stl); | ||||
| 	} | ||||
| 
 | ||||
|   	// Always calculate the volume.  It shouldn't take too long.
 | ||||
| 	if (verbose_flag) | ||||
| 		printf("Calculating volume...\n"); | ||||
| 	stl_calculate_volume(stl); | ||||
| 
 | ||||
| 	if (exact_flag) { | ||||
| 		if (verbose_flag) | ||||
| 	  		printf("Verifying neighbors...\n"); | ||||
| 		stl_verify_neighbors(stl); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -74,6 +74,10 @@ if (MSVC) | |||
|         windows/unistd.cpp | ||||
|         windows/getopt.c | ||||
|     ) | ||||
| elseif (MINGW) | ||||
|     set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES} | ||||
|         windows/utf8.c | ||||
|     ) | ||||
| endif() | ||||
| 
 | ||||
| add_executable(avrdude-conf-gen conf-generate.cpp) | ||||
|  | @ -81,13 +85,13 @@ add_executable(avrdude-conf-gen conf-generate.cpp) | |||
| # Config file embedding | ||||
| add_custom_command( | ||||
|     DEPENDS avrdude-conf-gen ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf | ||||
|     OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h | ||||
|     COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf > avrdude-slic3r.conf.h | ||||
|     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h | ||||
|     COMMAND $<TARGET_FILE:avrdude-conf-gen> avrdude-slic3r.conf avrdude_slic3r_conf ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h | ||||
|     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||||
| ) | ||||
| 
 | ||||
| add_custom_target(gen_conf_h | ||||
|    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf.h | ||||
|    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/avrdude-slic3r.conf.h | ||||
| ) | ||||
| 
 | ||||
| add_library(avrdude STATIC ${AVRDUDE_SOURCES}) | ||||
|  | @ -96,7 +100,15 @@ add_dependencies(avrdude gen_conf_h) | |||
| add_executable(avrdude-slic3r main-standalone.cpp) | ||||
| target_link_libraries(avrdude-slic3r avrdude) | ||||
| 
 | ||||
| encoding_check(avrdude) | ||||
| encoding_check(avrdude-slic3r) | ||||
| 
 | ||||
| # Make avrdude-slic3r.conf.h includable: | ||||
| target_include_directories(avrdude SYSTEM PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) | ||||
| 
 | ||||
| if (WIN32) | ||||
|     target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1) | ||||
|     target_include_directories(avrdude SYSTEM PRIVATE windows)    # So that sources find the getopt.h windows drop-in | ||||
|     if(MSVC) | ||||
|         target_include_directories(avrdude SYSTEM PRIVATE windows)    # So that sources find the getopt.h windows drop-in | ||||
|     endif(MSVC) | ||||
| endif() | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ | |||
| static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) | ||||
| { | ||||
|   unsigned char buf[32]; | ||||
|   (void)p; | ||||
| 
 | ||||
|   /* Signature byte reads are always 3 bytes. */ | ||||
| 
 | ||||
|  | @ -83,9 +84,9 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) | |||
| static int prusa_init_external_flash(PROGRAMMER * pgm) | ||||
| { | ||||
|   // Note: send/receive as in _the firmare_ send & receives
 | ||||
|   const char entry_magic_send   [] = "start\n"; | ||||
|   const char entry_magic_receive[] = "w25x20cl_enter\n"; | ||||
|   const char entry_magic_cfm    [] = "w25x20cl_cfm\n"; | ||||
|   const char entry_magic_send[]             = "start\n"; | ||||
|   const unsigned char entry_magic_receive[] = "w25x20cl_enter\n"; | ||||
|   const char entry_magic_cfm[]              = "w25x20cl_cfm\n"; | ||||
|   const size_t buffer_len = 32;     // Should be large enough for the above messages
 | ||||
| 
 | ||||
|   int res; | ||||
|  | @ -94,7 +95,7 @@ static int prusa_init_external_flash(PROGRAMMER * pgm) | |||
| 
 | ||||
|   // 1. receive the "start" command
 | ||||
|   recv_size = sizeof(entry_magic_send) - 1; | ||||
|   res = serial_recv(&pgm->fd, buffer, recv_size); | ||||
|   res = serial_recv(&pgm->fd, (unsigned char *)buffer, recv_size); | ||||
|   if (res < 0) { | ||||
|     avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname); | ||||
|     return -1; | ||||
|  | @ -111,7 +112,7 @@ static int prusa_init_external_flash(PROGRAMMER * pgm) | |||
| 
 | ||||
|   // 3. Receive the entry confirmation command
 | ||||
|   recv_size = sizeof(entry_magic_cfm) - 1; | ||||
|   res = serial_recv(&pgm->fd, buffer, recv_size); | ||||
|   res = serial_recv(&pgm->fd, (unsigned char *)buffer, recv_size); | ||||
|   if (res < 0) { | ||||
|     avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname); | ||||
|     return -1; | ||||
|  | @ -142,7 +143,7 @@ static int arduino_open(PROGRAMMER * pgm, char * port) | |||
| 
 | ||||
|   // Sometimes there may be line noise generating input on the printer's USB-to-serial IC
 | ||||
|   // Here we try to clean its input buffer with a sequence of newlines (a minimum of 9 is needed):
 | ||||
|   const char cleanup_newlines[] = "\n\n\n\n\n\n\n\n\n\n"; | ||||
|   const unsigned char cleanup_newlines[] = "\n\n\n\n\n\n\n\n\n\n"; | ||||
|   if (serial_send(&pgm->fd, cleanup_newlines, sizeof(cleanup_newlines) - 1) < 0) { | ||||
|     return -1; | ||||
|   } | ||||
|  |  | |||
|  | @ -341,7 +341,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, | |||
|     avr_tpi_setup_rw(pgm, mem, 0, TPI_NVMCMD_NO_OPERATION); | ||||
| 
 | ||||
|     /* load bytes */ | ||||
|     for (lastaddr = i = 0; i < mem->size; i++) { | ||||
|     for (lastaddr = i = 0; i < (unsigned)mem->size; i++) { | ||||
|       RETURN_IF_CANCEL(); | ||||
|       if (vmem == NULL || | ||||
|           (vmem->tags[i] & TAG_ALLOCATED) != 0) | ||||
|  | @ -374,7 +374,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, | |||
| 
 | ||||
|     /* quickly scan number of pages to be written to first */ | ||||
|     for (pageaddr = 0, npages = 0; | ||||
|          pageaddr < mem->size; | ||||
|          pageaddr < (unsigned)mem->size; | ||||
|          pageaddr += mem->page_size) { | ||||
|       /* check whether this page must be read */ | ||||
|       for (i = pageaddr; | ||||
|  | @ -391,7 +391,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, | |||
|     } | ||||
| 
 | ||||
|     for (pageaddr = 0, failure = 0, nread = 0; | ||||
|          !failure && pageaddr < mem->size; | ||||
|          !failure && pageaddr < (unsigned)mem->size; | ||||
|          pageaddr += mem->page_size) { | ||||
|       RETURN_IF_CANCEL(); | ||||
|       /* check whether this page must be read */ | ||||
|  | @ -437,7 +437,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   for (i=0; i < mem->size; i++) { | ||||
|   for (i = 0; i < (unsigned)mem->size; i++) { | ||||
|     RETURN_IF_CANCEL(); | ||||
|     if (vmem == NULL || | ||||
| 	(vmem->tags[i] & TAG_ALLOCATED) != 0) | ||||
|  | @ -634,18 +634,18 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, | |||
|       writeop = mem->op[AVR_OP_WRITE_HI]; | ||||
|     else | ||||
|       writeop = mem->op[AVR_OP_WRITE_LO]; | ||||
|     caddr = addr / 2; | ||||
|     caddr = (unsigned short)(addr / 2); | ||||
|   } | ||||
|   else if (mem->paged && mem->op[AVR_OP_LOADPAGE_LO]) { | ||||
|     if (addr & 0x01) | ||||
|       writeop = mem->op[AVR_OP_LOADPAGE_HI]; | ||||
|     else | ||||
|       writeop = mem->op[AVR_OP_LOADPAGE_LO]; | ||||
|     caddr = addr / 2; | ||||
|     caddr = (unsigned short)(addr / 2); | ||||
|   } | ||||
|   else { | ||||
|     writeop = mem->op[AVR_OP_WRITE]; | ||||
|     caddr = addr; | ||||
|     caddr = (unsigned short)addr; | ||||
|   } | ||||
| 
 | ||||
|   if (writeop == NULL) { | ||||
|  | @ -723,7 +723,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, | |||
|         gettimeofday (&tv, NULL); | ||||
|         prog_time = (tv.tv_sec * 1000000) + tv.tv_usec; | ||||
|       } while ((r != data) && | ||||
|                ((prog_time-start_time) < mem->max_write_delay)); | ||||
|                ((prog_time - start_time) < (unsigned long)mem->max_write_delay)); | ||||
|     } | ||||
| 
 | ||||
|     /*
 | ||||
|  | @ -878,7 +878,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, | |||
|     } | ||||
| 
 | ||||
|     /* write words, low byte first */ | ||||
|     for (lastaddr = i = 0; i < wsize; i += 2) { | ||||
|     for (lastaddr = i = 0; i < (unsigned)wsize; i += 2) { | ||||
|       RETURN_IF_CANCEL(); | ||||
|       if ((m->tags[i] & TAG_ALLOCATED) != 0 || | ||||
|           (m->tags[i + 1] & TAG_ALLOCATED) != 0) { | ||||
|  | @ -915,7 +915,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, | |||
| 
 | ||||
|     /* quickly scan number of pages to be written to first */ | ||||
|     for (pageaddr = 0, npages = 0; | ||||
|          pageaddr < wsize; | ||||
|          pageaddr < (unsigned)wsize; | ||||
|          pageaddr += m->page_size) { | ||||
|       /* check whether this page must be written to */ | ||||
|       for (i = pageaddr; | ||||
|  | @ -928,7 +928,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, | |||
|     } | ||||
| 
 | ||||
|     for (pageaddr = 0, failure = 0, nwritten = 0; | ||||
|          !failure && pageaddr < wsize; | ||||
|          !failure && pageaddr < (unsigned)wsize; | ||||
|          pageaddr += m->page_size) { | ||||
|       RETURN_IF_CANCEL(); | ||||
|       /* check whether this page must be written to */ | ||||
|  | @ -968,7 +968,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, | |||
|   page_tainted = 0; | ||||
|   flush_page = 0; | ||||
| 
 | ||||
|   for (i=0; i<wsize; i++) { | ||||
|   for (i = 0; i < (unsigned)wsize; i++) { | ||||
|     RETURN_IF_CANCEL(); | ||||
|     data = m->buf[i]; | ||||
|     report_progress(i, wsize, NULL); | ||||
|  |  | |||
|  | @ -676,7 +676,7 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, | |||
|     avr910_set_addr(pgm, addr / rd_size); | ||||
| 
 | ||||
|     while (addr < max_addr) { | ||||
|       if ((max_addr - addr) < blocksize) { | ||||
|       if ((max_addr - addr) < (unsigned)blocksize) { | ||||
|         blocksize = max_addr - addr; | ||||
|       } | ||||
|       cmd[1] = (blocksize >> 8) & 0xff; | ||||
|  |  | |||
|  | @ -93,7 +93,7 @@ void AvrDude::priv::unset_handlers() | |||
| 
 | ||||
| 
 | ||||
| int AvrDude::priv::run_one(const std::vector<std::string> &args) { | ||||
| 	std::vector<char*> c_args {{ const_cast<char*>(PACKAGE) }}; | ||||
| 	std::vector<char*> c_args { const_cast<char*>(PACKAGE) }; | ||||
| 	std::string command_line { PACKAGE }; | ||||
| 
 | ||||
| 	for (const auto &arg : args) { | ||||
|  | @ -105,7 +105,7 @@ int AvrDude::priv::run_one(const std::vector<std::string> &args) { | |||
| 
 | ||||
| 	HandlerGuard guard(*this); | ||||
| 
 | ||||
| 	message_fn(command_line.c_str(), command_line.size()); | ||||
| 	message_fn(command_line.c_str(), (unsigned)command_line.size()); | ||||
| 
 | ||||
| 	const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data()); | ||||
| 
 | ||||
|  | @ -200,7 +200,7 @@ AvrDude::Ptr AvrDude::run() | |||
| 				auto &message_fn = self->p->message_fn; | ||||
| 				if (message_fn) { | ||||
| 					message_fn(msg, sizeof(msg)); | ||||
| 					message_fn(what, std::strlen(what)); | ||||
| 					message_fn(what, (unsigned)std::strlen(what)); | ||||
| 					message_fn("\n", 1); | ||||
| 				} | ||||
| 
 | ||||
|  |  | |||
|  | @ -64,6 +64,8 @@ int avrdude_main(int argc, char * argv []); | |||
| #include <windows.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #define strdup _strdup | ||||
| 
 | ||||
| #ifdef UNICODE | ||||
| #error "UNICODE should not be defined for avrdude bits on Windows" | ||||
| #endif | ||||
|  |  | |||
|  | @ -358,7 +358,7 @@ AVRMEM * avr_locate_mem(AVRPART * p, char * desc) | |||
|   int matches; | ||||
|   int l; | ||||
| 
 | ||||
|   l = strlen(desc); | ||||
|   l = (int)strlen(desc); | ||||
|   matches = 0; | ||||
|   match = NULL; | ||||
|   for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { | ||||
|  | @ -662,7 +662,7 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose) | |||
|           prefix); | ||||
| 
 | ||||
|   px = prefix; | ||||
|   i = strlen(prefix) + 5; | ||||
|   i = (int)strlen(prefix) + 5; | ||||
|   buf = (char *)malloc(i); | ||||
|   if (buf == NULL) { | ||||
|     /* ugh, this is not important enough to bail, just ignore it */ | ||||
|  |  | |||
|  | @ -128,7 +128,7 @@ static int buspirate_recv_bin(struct programmer_t *pgm, unsigned char *buf, size | |||
| 	avrdude_message(MSG_DEBUG, "%s: buspirate_recv_bin():\n", progname); | ||||
| 	dump_mem(MSG_DEBUG, buf, len); | ||||
| 
 | ||||
| 	return len; | ||||
| 	return (int)len; | ||||
| } | ||||
| 
 | ||||
| static int buspirate_expect_bin(struct programmer_t *pgm, | ||||
|  | @ -249,7 +249,7 @@ static int buspirate_send(struct programmer_t *pgm, const char *str) | |||
| 
 | ||||
| static int buspirate_is_prompt(const char *str) | ||||
| { | ||||
| 	int strlen_str = strlen(str); | ||||
| 	int strlen_str = (int)strlen(str); | ||||
| 	/* Prompt ends with '>' or '> '
 | ||||
| 	 * all other input probably ends with '\n' */ | ||||
| 	return (str[strlen_str - 1] == '>' || str[strlen_str - 2] == '>'); | ||||
|  |  | |||
|  | @ -675,7 +675,7 @@ static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, | |||
|       butterfly_set_addr(pgm, addr / rd_size); | ||||
|     } | ||||
|     while (addr < max_addr) { | ||||
|       if ((max_addr - addr) < blocksize) { | ||||
|       if ((max_addr - addr) < (unsigned)blocksize) { | ||||
|         blocksize = max_addr - addr; | ||||
|       }; | ||||
|       cmd[1] = (blocksize >> 8) & 0xff; | ||||
|  |  | |||
|  | @ -6,36 +6,42 @@ | |||
| 
 | ||||
| int main(int argc, char const *argv[]) | ||||
| { | ||||
|     if (argc != 3) { | ||||
|         std::cerr << "Usage: " << argv[0] << " <file> <symbol name>" << std::endl; | ||||
|     if (argc != 4) { | ||||
|         std::cerr << "Usage: " << argv[0] << " <file> <symbol name> <output file>" << std::endl; | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     const char* filename = argv[1]; | ||||
|     const char* filename_in = argv[1]; | ||||
|     const char* symbol = argv[2]; | ||||
|     const char* filename_out = argv[3]; | ||||
| 
 | ||||
|     size_t size = 0; | ||||
|     std::fstream file(filename); | ||||
|     std::fstream file(filename_in, std::ios::in | std::ios::binary); | ||||
|     if (!file.good()) { | ||||
|         std::cerr << "Cannot read file: " << filename << std::endl; | ||||
|         std::cerr << "Cannot read file: " << filename_in << std::endl; | ||||
|     } | ||||
| 
 | ||||
|     std::cout << "/* WARN: This file is auto-generated from `" << filename << "` */" << std::endl; | ||||
|     std::cout << "unsigned char " << symbol << "[] = {"; | ||||
|     std::fstream output(filename_out, std::ios::out | std::ios::trunc); | ||||
|     if (!output.good()) { | ||||
|         std::cerr << "Cannot open output file: " << filename_out << std::endl; | ||||
|     } | ||||
| 
 | ||||
|     output << "/* WARN: This file is auto-generated from `" << filename_in << "` */" << std::endl; | ||||
|     output << "const unsigned char " << symbol << "[] = {"; | ||||
| 
 | ||||
|     char c; | ||||
|     std::cout << std::hex; | ||||
|     std::cout.fill('0'); | ||||
|     output << std::hex; | ||||
|     output.fill('0'); | ||||
|     for (file.get(c); !file.eof(); size++, file.get(c)) { | ||||
|         if (size % 12 == 0) { std::cout << "\n    "; } | ||||
|         std::cout << "0x" << std::setw(2) << (unsigned)c << ", "; | ||||
|         if (size % 12 == 0) { output << "\n    "; } | ||||
|         output << "0x" << std::setw(2) << (unsigned)c << ", "; | ||||
|     } | ||||
| 
 | ||||
|     std::cout << "\n    0, 0\n};\n"; | ||||
|     output << "\n    0, 0\n};\n"; | ||||
| 
 | ||||
|     std::cout << std::dec; | ||||
|     std::cout << "size_t " << symbol << "_size = " << size << ";" << std::endl; | ||||
|     std::cout << "size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl; | ||||
|     output << std::dec; | ||||
|     output << "const size_t " << symbol << "_size = " << size << ";" << std::endl; | ||||
|     output << "const size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl; | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -240,7 +240,7 @@ TOKEN * string(char * text) | |||
|       return NULL; /* yyerror already called */ | ||||
|   } | ||||
| 
 | ||||
|   len = strlen(text); | ||||
|   len = (int)strlen(text); | ||||
| 
 | ||||
|   tkn->value.type   = V_STR; | ||||
|   tkn->value.string = (char *) malloc(len+1); | ||||
|  | @ -351,7 +351,7 @@ int read_config(const char * file) | |||
| } | ||||
| 
 | ||||
| typedef struct yy_buffer_state *YY_BUFFER_STATE; | ||||
| extern YY_BUFFER_STATE yy_scan_bytes(char *base, size_t size); | ||||
| extern YY_BUFFER_STATE yy_scan_bytes(const char *base, size_t size); | ||||
| extern void yy_delete_buffer(YY_BUFFER_STATE b); | ||||
| 
 | ||||
| int read_config_builtin() | ||||
|  | @ -363,7 +363,7 @@ int read_config_builtin() | |||
| 
 | ||||
|   // Note: Can't use yy_scan_buffer, it's buggy (?), leads to fread from a null FILE*
 | ||||
|   // and so unfortunatelly we have to use the copying variant here
 | ||||
|   YY_BUFFER_STATE buffer = yy_scan_bytes(avrdude_slic3r_conf, avrdude_slic3r_conf_size); | ||||
|   YY_BUFFER_STATE buffer = yy_scan_bytes((const char *)avrdude_slic3r_conf, avrdude_slic3r_conf_size); | ||||
|   if (buffer == NULL) { | ||||
|     avrdude_message(MSG_INFO, "%s: read_config_builtin: Failed to initialize parsing buffer\n", progname); | ||||
|     return -1; | ||||
|  |  | |||
|  | @ -3640,7 +3640,7 @@ static int parse_cmdbits(OPCODE * op) | |||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       len = strlen(s); | ||||
|       len = (int)strlen(s); | ||||
| 
 | ||||
|       if (len == 0) { | ||||
|         yyerror("invalid bit specifier \"\""); | ||||
|  |  | |||
|  | @ -1493,7 +1493,7 @@ static int parse_cmdbits(OPCODE * op) | |||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       len = strlen(s); | ||||
|       len = (int)strlen(s); | ||||
| 
 | ||||
|       if (len == 0) { | ||||
|         yyerror("invalid bit specifier \"\""); | ||||
|  |  | |||
|  | @ -264,7 +264,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) | |||
|   unsigned char cksum; | ||||
|   int rc; | ||||
| 
 | ||||
|   len    = strlen(rec); | ||||
|   len    = (int)strlen(rec); | ||||
|   offset = 1; | ||||
|   cksum  = 0; | ||||
| 
 | ||||
|  | @ -274,7 +274,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) | |||
|   for (i=0; i<2; i++) | ||||
|     buf[i] = rec[offset++]; | ||||
|   buf[i] = 0; | ||||
|   ihex->reclen = strtoul(buf, &e, 16); | ||||
|   ihex->reclen = (unsigned char)strtoul(buf, &e, 16); | ||||
|   if (e == buf || *e != 0) | ||||
|     return -1; | ||||
| 
 | ||||
|  | @ -294,7 +294,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) | |||
|   for (i=0; i<2; i++) | ||||
|     buf[i] = rec[offset++]; | ||||
|   buf[i] = 0; | ||||
|   ihex->rectyp = strtoul(buf, &e, 16); | ||||
|   ihex->rectyp = (unsigned char)strtoul(buf, &e, 16); | ||||
|   if (e == buf || *e != 0) | ||||
|     return -1; | ||||
| 
 | ||||
|  | @ -308,7 +308,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) | |||
|     for (i=0; i<2; i++) | ||||
|       buf[i] = rec[offset++]; | ||||
|     buf[i] = 0; | ||||
|     ihex->data[j] = strtoul(buf, &e, 16); | ||||
|     ihex->data[j] = (char)strtoul(buf, &e, 16); | ||||
|     if (e == buf || *e != 0) | ||||
|       return -1; | ||||
|     cksum += ihex->data[j]; | ||||
|  | @ -320,7 +320,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) | |||
|   for (i=0; i<2; i++) | ||||
|     buf[i] = rec[offset++]; | ||||
|   buf[i] = 0; | ||||
|   ihex->cksum = strtoul(buf, &e, 16); | ||||
|   ihex->cksum = (char)strtoul(buf, &e, 16); | ||||
|   if (e == buf || *e != 0) | ||||
|     return -1; | ||||
| 
 | ||||
|  | @ -361,7 +361,7 @@ static int ihex2b(char * infile, FILE * inf, | |||
| 
 | ||||
|   while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { | ||||
|     lineno++; | ||||
|     len = strlen(buffer); | ||||
|     len = (int)strlen(buffer); | ||||
|     if (buffer[len-1] == '\n')  | ||||
|       buffer[--len] = 0; | ||||
|     if (buffer[0] != ':') | ||||
|  | @ -388,7 +388,7 @@ static int ihex2b(char * infile, FILE * inf, | |||
|           return -1; | ||||
|         } | ||||
|         nextaddr = ihex.loadofs + baseaddr - fileoffset; | ||||
|         if (nextaddr + ihex.reclen > bufsize) { | ||||
|         if (nextaddr + ihex.reclen > (unsigned)bufsize) { | ||||
|           avrdude_message(MSG_INFO, "%s: ERROR: address 0x%04x out of range at line %d of %s\n", | ||||
|                           progname, nextaddr+ihex.reclen, lineno, infile); | ||||
|           return -1; | ||||
|  | @ -502,10 +502,11 @@ static int b2srec(unsigned char * inbuf, int bufsize, | |||
| 
 | ||||
|       cksum += n + addr_width + 1; | ||||
| 
 | ||||
|       for (i=addr_width; i>0; i--)  | ||||
|       for (i = addr_width; i>0; i--) { | ||||
|         cksum += (nextaddr >> (i-1) * 8) & 0xff; | ||||
|       } | ||||
| 
 | ||||
|       for (i=nextaddr; i<nextaddr + n; i++) { | ||||
|       for (unsigned i = nextaddr; i < nextaddr + n; i++) { | ||||
|         fprintf(outf, "%02X", buf[i]); | ||||
|         cksum += buf[i]; | ||||
|       } | ||||
|  | @ -562,7 +563,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec) | |||
|   unsigned char cksum; | ||||
|   int rc; | ||||
| 
 | ||||
|   len = strlen(rec); | ||||
|   len = (int)strlen(rec); | ||||
|   offset = 1; | ||||
|   cksum = 0; | ||||
|   addr_width = 2; | ||||
|  | @ -582,7 +583,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec) | |||
|   for (i=0; i<2; i++)  | ||||
|     buf[i] = rec[offset++]; | ||||
|   buf[i] = 0; | ||||
|   srec->reclen = strtoul(buf, &e, 16); | ||||
|   srec->reclen = (char)strtoul(buf, &e, 16); | ||||
|   cksum += srec->reclen; | ||||
|   srec->reclen -= (addr_width+1); | ||||
|   if (e == buf || *e != 0)  | ||||
|  | @ -594,7 +595,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec) | |||
|   for (i=0; i<addr_width*2; i++)  | ||||
|     buf[i] = rec[offset++]; | ||||
|   buf[i] = 0; | ||||
|   srec->loadofs = strtoull(buf, &e, 16); | ||||
|   srec->loadofs = strtoul(buf, &e, 16); | ||||
|   if (e == buf || *e != 0)  | ||||
|     return -1; | ||||
| 
 | ||||
|  | @ -608,7 +609,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec) | |||
|     for (i=0; i<2; i++)  | ||||
|       buf[i] = rec[offset++]; | ||||
|     buf[i] = 0; | ||||
|     srec->data[j] = strtoul(buf, &e, 16); | ||||
|     srec->data[j] = (char)strtoul(buf, &e, 16); | ||||
|     if (e == buf || *e != 0)  | ||||
|       return -1; | ||||
|     cksum += srec->data[j]; | ||||
|  | @ -620,7 +621,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec) | |||
|   for (i=0; i<2; i++)  | ||||
|     buf[i] = rec[offset++]; | ||||
|   buf[i] = 0; | ||||
|   srec->cksum = strtoul(buf, &e, 16); | ||||
|   srec->cksum = (char)strtoul(buf, &e, 16); | ||||
|   if (e == buf || *e != 0)  | ||||
|     return -1; | ||||
| 
 | ||||
|  | @ -650,7 +651,7 @@ static int srec2b(char * infile, FILE * inf, | |||
| 
 | ||||
|   while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { | ||||
|     lineno++; | ||||
|     len = strlen(buffer); | ||||
|     len = (int)strlen(buffer); | ||||
|     if (buffer[len-1] == '\n')  | ||||
|       buffer[--len] = 0; | ||||
|     if (buffer[0] != 0x53) | ||||
|  | @ -729,7 +730,7 @@ static int srec2b(char * infile, FILE * inf, | |||
|         return -1; | ||||
|       } | ||||
|       nextaddr -= fileoffset; | ||||
|       if (nextaddr + srec.reclen > bufsize) { | ||||
|       if (nextaddr + srec.reclen > (unsigned)bufsize) { | ||||
|         avrdude_message(MSG_INFO, msg, progname, nextaddr+srec.reclen, "", | ||||
|                 lineno, infile); | ||||
|         return -1; | ||||
|  | @ -740,7 +741,7 @@ static int srec2b(char * infile, FILE * inf, | |||
|       } | ||||
|       if (nextaddr+srec.reclen > maxaddr) | ||||
|         maxaddr = nextaddr+srec.reclen; | ||||
|       reccount++;       | ||||
|       reccount++; | ||||
|     } | ||||
| 
 | ||||
|   } | ||||
|  | @ -1143,12 +1144,12 @@ static int fileio_rbin(struct fioparms * fio, | |||
| 
 | ||||
|   switch (fio->op) { | ||||
|     case FIO_READ: | ||||
|       rc = fread(buf, 1, size, f); | ||||
|       rc = (int)fread(buf, 1, size, f); | ||||
|       if (rc > 0) | ||||
|         memset(mem->tags, TAG_ALLOCATED, rc); | ||||
|       break; | ||||
|     case FIO_WRITE: | ||||
|       rc = fwrite(buf, 1, size, f); | ||||
|       rc = (int)fwrite(buf, 1, size, f); | ||||
|       break; | ||||
|     default: | ||||
|       avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n", | ||||
|  | @ -1190,7 +1191,7 @@ static int fileio_imm(struct fioparms * fio, | |||
|                           progname, p); | ||||
|           return -1; | ||||
|         } | ||||
|         mem->buf[loc] = b; | ||||
|         mem->buf[loc] = (char)b; | ||||
|         mem->tags[loc++] = TAG_ALLOCATED; | ||||
|         p = strtok(NULL, " ,"); | ||||
|         rc = loc; | ||||
|  | @ -1452,7 +1453,7 @@ static int fmt_autodetect(char * fname, unsigned section) | |||
|     } | ||||
| 
 | ||||
|     buf[MAX_LINE_LEN-1] = 0; | ||||
|     len = strlen((char *)buf); | ||||
|     len = (int)strlen((char *)buf); | ||||
|     if (buf[len-1] == '\n') | ||||
|       buf[--len] = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
| 
 | ||||
| /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ | ||||
| 
 | ||||
| #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L | ||||
| #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(_MSC_VER) | ||||
| 
 | ||||
| /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
 | ||||
|  * if you want the limit (max/min) macros for int types.  | ||||
|  |  | |||
|  | @ -444,7 +444,7 @@ lcreat ( void * liststruct, int elements ) | |||
|     l->poolsize = DEFAULT_POOLSIZE; | ||||
|   } | ||||
|   else { | ||||
|     l->poolsize = elements*sizeof(LISTNODE)+sizeof(NODEPOOL); | ||||
|     l->poolsize = (short)(elements*sizeof(LISTNODE)+sizeof(NODEPOOL)); | ||||
|   } | ||||
| 
 | ||||
|   l->n_ln_pool = (l->poolsize-sizeof(NODEPOOL))/sizeof(LISTNODE); | ||||
|  | @ -803,7 +803,7 @@ lget_n ( LISTID lid, unsigned int n ) | |||
| 
 | ||||
|   CKLMAGIC(l); | ||||
| 
 | ||||
|   if ((n<1)||(n>lsize(l))) { | ||||
|   if ((n < 1) || (n > (unsigned)lsize(l))) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|  | @ -844,7 +844,7 @@ lget_ln ( LISTID lid, unsigned int n ) | |||
| 
 | ||||
|   CKLMAGIC(l); | ||||
| 
 | ||||
|   if ((n<1)||(n>lsize(l))) { | ||||
|   if ((n < 1) || (n > (unsigned)lsize(l))) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|  | @ -941,7 +941,7 @@ insert_ln ( LIST * l, LISTNODE * ln, void * data_ptr ) | |||
| | | ||||
| |  Insert data before the nth item in the list. | ||||
|  -----------------------------------------------------------------*/ | ||||
| int  | ||||
| int | ||||
| lins_n ( LISTID lid, void * data_ptr, unsigned int n ) | ||||
| { | ||||
|   int i; | ||||
|  | @ -952,7 +952,7 @@ lins_n ( LISTID lid, void * data_ptr, unsigned int n ) | |||
| 
 | ||||
|   CKLMAGIC(l); | ||||
| 
 | ||||
|   if ((n<1)||(n>(l->num+1))) { | ||||
|   if ((n < 1) || (n > (unsigned)(l->num+1))) { | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|  | @ -1193,7 +1193,7 @@ lrmv_n ( LISTID lid, unsigned int n ) | |||
| 
 | ||||
|   CKLMAGIC(l); | ||||
| 
 | ||||
|   if ((n<1)||(n>l->num)) { | ||||
|   if ((n < 1) || (n > (unsigned)l->num)) { | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,6 +38,10 @@ struct ArgvUtf8 : std::vector<char*> | |||
| 	} | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
| 
 | ||||
| int wmain(int argc_w, wchar_t *argv_w[]) | ||||
| { | ||||
| 	ArgvUtf8 argv_utf8(argc_w, argv_w); | ||||
|  |  | |||
|  | @ -107,7 +107,7 @@ int avrdude_message(const int msglvl, const char *format, ...) | |||
|             if (rc > 0 && rc < MSGBUFFER_SIZE) { | ||||
|                 avrdude_message_handler(msgbuffer, rc, avrdude_message_handler_user_p); | ||||
|             } else { | ||||
|                 avrdude_message_handler(format_error, strlen(format_error), avrdude_message_handler_user_p); | ||||
|                 avrdude_message_handler(format_error, (unsigned)strlen(format_error), avrdude_message_handler_user_p); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -567,7 +567,7 @@ int avrdude_main(int argc, char * argv []) | |||
| 
 | ||||
| // #endif
 | ||||
| 
 | ||||
|   len = strlen(progname) + 2; | ||||
|   len = (int)strlen(progname) + 2; | ||||
|   for (i=0; i<len; i++) | ||||
|     progbuf[i] = ' '; | ||||
|   progbuf[i] = 0; | ||||
|  | @ -601,7 +601,7 @@ int avrdude_main(int argc, char * argv []) | |||
| 	bitclock = strtod(optarg, &e); | ||||
| 	if (*e != 0) { | ||||
| 	  /* trailing unit of measure present */ | ||||
| 	  int suffixlen = strlen(e); | ||||
| 	  size_t suffixlen = strlen(e); | ||||
| 	  switch (suffixlen) { | ||||
| 	  case 2: | ||||
| 	    if ((e[0] != 'h' && e[0] != 'H') || e[1] != 'z') | ||||
|  |  | |||
|  | @ -217,7 +217,7 @@ const char * pinmask_to_str(const pinmask_t * const pinmask) { | |||
|  * @param[in] size the number of entries in checklist | ||||
|  * @returns 0 if all pin definitions are valid, -1 otherwise | ||||
|  */ | ||||
| int pins_check(const struct programmer_t * const pgm, const struct pin_checklist_t * const checklist, const int size, bool output) { | ||||
| int pins_check(const struct programmer_t *const pgm, const struct pin_checklist_t *const checklist, const int size, const bool output) { | ||||
|   static const struct pindef_t no_valid_pins = {{0}, {0}}; // default value if check list does not contain anything else
 | ||||
|   int rv = 0; // return value
 | ||||
|   int pinname; // loop counter through pinnames
 | ||||
|  |  | |||
|  | @ -292,7 +292,7 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp) | |||
| 	if (hComPort == INVALID_HANDLE_VALUE) { | ||||
| 		const char *error = last_error_string(0); | ||||
| 		avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n", progname, port, error); | ||||
| 		free(error); | ||||
| 		free((char *)error); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -460,10 +460,10 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t | |||
| 
 | ||||
| 	serial_w32SetTimeOut(hComPort,500); | ||||
| 
 | ||||
| 	if (!WriteFile(hComPort, buf, buflen, &written, NULL)) { | ||||
| 	if (!WriteFile(hComPort, buf, (DWORD)buflen, &written, NULL)) { | ||||
| 		const char *error = last_error_string(0); | ||||
| 		avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, error); | ||||
| 		free(error); | ||||
| 		free((char *)error); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -576,10 +576,10 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen | |||
| 
 | ||||
| 	serial_w32SetTimeOut(hComPort, serial_recv_timeout); | ||||
| 
 | ||||
| 	if (!ReadFile(hComPort, buf, buflen, &read, NULL)) { | ||||
| 	if (!ReadFile(hComPort, buf, (DWORD)buflen, &read, NULL)) { | ||||
| 		const char *error = last_error_string(0); | ||||
| 		avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error); | ||||
| 		free(error); | ||||
| 		free((char *)error); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -642,7 +642,7 @@ static int ser_drain(union filedescriptor *fd, int display) | |||
| 		if (!readres) { | ||||
| 			const char *error = last_error_string(0); | ||||
| 			avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, error); | ||||
| 			free(error); | ||||
| 			free((char *)error); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -308,8 +308,8 @@ static int serbb_open(PROGRAMMER *pgm, char *port) | |||
|                         progname, port); | ||||
|                 return -1; | ||||
| 	} | ||||
|         avrdude_message(MSG_DEBUG, "%s: ser_open(): opened comm port \"%s\", handle 0x%x\n", | ||||
|                         progname, port, (int)hComPort); | ||||
|         avrdude_message(MSG_DEBUG, "%s: ser_open(): opened comm port \"%s\", handle %p\n", | ||||
|                         progname, port, (void *)hComPort); | ||||
| 
 | ||||
|         pgm->fd.pfd = (void *)hComPort; | ||||
| 
 | ||||
|  | @ -326,8 +326,8 @@ static void serbb_close(PROGRAMMER *pgm) | |||
| 		pgm->setpin(pgm, PIN_AVR_RESET, 1); | ||||
| 		CloseHandle (hComPort); | ||||
| 	} | ||||
|         avrdude_message(MSG_DEBUG, "%s: ser_close(): closed comm port handle 0x%x\n", | ||||
|                                 progname, (int)hComPort); | ||||
|         avrdude_message(MSG_DEBUG, "%s: ser_close(): closed comm port handle %p\n", | ||||
|                                 progname, (void *)hComPort); | ||||
| 
 | ||||
| 	hComPort = INVALID_HANDLE_VALUE; | ||||
| } | ||||
|  |  | |||
|  | @ -504,7 +504,7 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p) | |||
|   } | ||||
|   else { | ||||
|     buf[9]  = 0xff; | ||||
|     buf[10]  = 0xff; | ||||
|     buf[10] = 0xff; | ||||
|     buf[13] = 0; | ||||
|     buf[14] = 0; | ||||
|     buf[17] = 0; | ||||
|  | @ -821,7 +821,7 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, | |||
|         break; | ||||
|       } | ||||
| 
 | ||||
|     for (prusa3d_semicolon_workaround_round = 0; prusa3d_semicolon_workaround_round < (has_semicolon ? 2 : 1); ++ prusa3d_semicolon_workaround_round) { | ||||
|     for (prusa3d_semicolon_workaround_round = 0; prusa3d_semicolon_workaround_round < (has_semicolon ? 2u : 1u); prusa3d_semicolon_workaround_round++) { | ||||
|       /* build command block and avoid multiple send commands as it leads to a crash
 | ||||
|           of the silabs usb serial driver on mac os x */ | ||||
|       i = 0; | ||||
|  | @ -834,7 +834,7 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, | |||
|       buf[i++] = block_size & 0x0f; | ||||
|       buf[i++] = memtype; | ||||
|       if (has_semicolon) { | ||||
|         for (j = 0; j < block_size; ++i, ++ j) { | ||||
|         for (j = 0; j < (unsigned)block_size; ++i, ++ j) { | ||||
|           buf[i] = m->buf[addr + j]; | ||||
|           if (buf[i] == ';') | ||||
|             buf[i] |= (prusa3d_semicolon_workaround_round ? 0xf0 : 0x0f); | ||||
|  | @ -1088,8 +1088,8 @@ static int stk500_set_sck_period(PROGRAMMER * pgm, double v) | |||
| 
 | ||||
|   min = 8.0 / STK500_XTAL; | ||||
|   max = 255 * min; | ||||
|   dur = v / min + 0.5; | ||||
|    | ||||
|   dur = (int)(v / min + 0.5); | ||||
| 
 | ||||
|   if (v < min) { | ||||
|       dur = 1; | ||||
|       avrdude_message(MSG_INFO, "%s: stk500_set_sck_period(): p = %.1f us too small, using %.1f us\n", | ||||
|  | @ -1099,7 +1099,7 @@ static int stk500_set_sck_period(PROGRAMMER * pgm, double v) | |||
|       avrdude_message(MSG_INFO, "%s: stk500_set_sck_period(): p = %.1f us too large, using %.1f us\n", | ||||
|                       progname, v / 1e-6, dur * min / 1e-6); | ||||
|   } | ||||
|    | ||||
| 
 | ||||
|   return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -130,58 +130,58 @@ struct jtagispentry | |||
| #define SZ_SPI_MULTI     (USHRT_MAX - 1) | ||||
| }; | ||||
| 
 | ||||
| static const struct jtagispentry jtagispcmds[] = { | ||||
|   /* generic */ | ||||
|   { CMD_SET_PARAMETER, 2 }, | ||||
|   { CMD_GET_PARAMETER, 3 }, | ||||
|   { CMD_OSCCAL, 2 }, | ||||
|   { CMD_LOAD_ADDRESS, 2 }, | ||||
|   /* ISP mode */ | ||||
|   { CMD_ENTER_PROGMODE_ISP, 2 }, | ||||
|   { CMD_LEAVE_PROGMODE_ISP, 2 }, | ||||
|   { CMD_CHIP_ERASE_ISP, 2 }, | ||||
|   { CMD_PROGRAM_FLASH_ISP, 2 }, | ||||
|   { CMD_READ_FLASH_ISP, SZ_READ_FLASH_EE }, | ||||
|   { CMD_PROGRAM_EEPROM_ISP, 2 }, | ||||
|   { CMD_READ_EEPROM_ISP, SZ_READ_FLASH_EE }, | ||||
|   { CMD_PROGRAM_FUSE_ISP, 3 }, | ||||
|   { CMD_READ_FUSE_ISP, 4 }, | ||||
|   { CMD_PROGRAM_LOCK_ISP, 3 }, | ||||
|   { CMD_READ_LOCK_ISP, 4 }, | ||||
|   { CMD_READ_SIGNATURE_ISP, 4 }, | ||||
|   { CMD_READ_OSCCAL_ISP, 4 }, | ||||
|   { CMD_SPI_MULTI, SZ_SPI_MULTI }, | ||||
|   /* all HV modes */ | ||||
|   { CMD_SET_CONTROL_STACK, 2 }, | ||||
|   /* HVSP mode */ | ||||
|   { CMD_ENTER_PROGMODE_HVSP, 2 }, | ||||
|   { CMD_LEAVE_PROGMODE_HVSP, 2 }, | ||||
|   { CMD_CHIP_ERASE_HVSP, 2 }, | ||||
|   { CMD_PROGRAM_FLASH_HVSP, 2 }, | ||||
|   { CMD_READ_FLASH_HVSP, SZ_READ_FLASH_EE }, | ||||
|   { CMD_PROGRAM_EEPROM_HVSP, 2 }, | ||||
|   { CMD_READ_EEPROM_HVSP, SZ_READ_FLASH_EE }, | ||||
|   { CMD_PROGRAM_FUSE_HVSP, 2 }, | ||||
|   { CMD_READ_FUSE_HVSP, 3 }, | ||||
|   { CMD_PROGRAM_LOCK_HVSP, 2 }, | ||||
|   { CMD_READ_LOCK_HVSP, 3 }, | ||||
|   { CMD_READ_SIGNATURE_HVSP, 3 }, | ||||
|   { CMD_READ_OSCCAL_HVSP, 3 }, | ||||
|   /* PP mode */ | ||||
|   { CMD_ENTER_PROGMODE_PP, 2 }, | ||||
|   { CMD_LEAVE_PROGMODE_PP, 2 }, | ||||
|   { CMD_CHIP_ERASE_PP, 2 }, | ||||
|   { CMD_PROGRAM_FLASH_PP, 2 }, | ||||
|   { CMD_READ_FLASH_PP, SZ_READ_FLASH_EE }, | ||||
|   { CMD_PROGRAM_EEPROM_PP, 2 }, | ||||
|   { CMD_READ_EEPROM_PP, SZ_READ_FLASH_EE }, | ||||
|   { CMD_PROGRAM_FUSE_PP, 2 }, | ||||
|   { CMD_READ_FUSE_PP, 3 }, | ||||
|   { CMD_PROGRAM_LOCK_PP, 2 }, | ||||
|   { CMD_READ_LOCK_PP, 3 }, | ||||
|   { CMD_READ_SIGNATURE_PP, 3 }, | ||||
|   { CMD_READ_OSCCAL_PP, 3 }, | ||||
| }; | ||||
| // static const struct jtagispentry jtagispcmds[] = {
 | ||||
| //   /* generic */
 | ||||
| //   { CMD_SET_PARAMETER, 2 },
 | ||||
| //   { CMD_GET_PARAMETER, 3 },
 | ||||
| //   { CMD_OSCCAL, 2 },
 | ||||
| //   { CMD_LOAD_ADDRESS, 2 },
 | ||||
| //   /* ISP mode */
 | ||||
| //   { CMD_ENTER_PROGMODE_ISP, 2 },
 | ||||
| //   { CMD_LEAVE_PROGMODE_ISP, 2 },
 | ||||
| //   { CMD_CHIP_ERASE_ISP, 2 },
 | ||||
| //   { CMD_PROGRAM_FLASH_ISP, 2 },
 | ||||
| //   { CMD_READ_FLASH_ISP, SZ_READ_FLASH_EE },
 | ||||
| //   { CMD_PROGRAM_EEPROM_ISP, 2 },
 | ||||
| //   { CMD_READ_EEPROM_ISP, SZ_READ_FLASH_EE },
 | ||||
| //   { CMD_PROGRAM_FUSE_ISP, 3 },
 | ||||
| //   { CMD_READ_FUSE_ISP, 4 },
 | ||||
| //   { CMD_PROGRAM_LOCK_ISP, 3 },
 | ||||
| //   { CMD_READ_LOCK_ISP, 4 },
 | ||||
| //   { CMD_READ_SIGNATURE_ISP, 4 },
 | ||||
| //   { CMD_READ_OSCCAL_ISP, 4 },
 | ||||
| //   { CMD_SPI_MULTI, SZ_SPI_MULTI },
 | ||||
| //   /* all HV modes */
 | ||||
| //   { CMD_SET_CONTROL_STACK, 2 },
 | ||||
| //   /* HVSP mode */
 | ||||
| //   { CMD_ENTER_PROGMODE_HVSP, 2 },
 | ||||
| //   { CMD_LEAVE_PROGMODE_HVSP, 2 },
 | ||||
| //   { CMD_CHIP_ERASE_HVSP, 2 },
 | ||||
| //   { CMD_PROGRAM_FLASH_HVSP, 2 },
 | ||||
| //   { CMD_READ_FLASH_HVSP, SZ_READ_FLASH_EE },
 | ||||
| //   { CMD_PROGRAM_EEPROM_HVSP, 2 },
 | ||||
| //   { CMD_READ_EEPROM_HVSP, SZ_READ_FLASH_EE },
 | ||||
| //   { CMD_PROGRAM_FUSE_HVSP, 2 },
 | ||||
| //   { CMD_READ_FUSE_HVSP, 3 },
 | ||||
| //   { CMD_PROGRAM_LOCK_HVSP, 2 },
 | ||||
| //   { CMD_READ_LOCK_HVSP, 3 },
 | ||||
| //   { CMD_READ_SIGNATURE_HVSP, 3 },
 | ||||
| //   { CMD_READ_OSCCAL_HVSP, 3 },
 | ||||
| //   /* PP mode */
 | ||||
| //   { CMD_ENTER_PROGMODE_PP, 2 },
 | ||||
| //   { CMD_LEAVE_PROGMODE_PP, 2 },
 | ||||
| //   { CMD_CHIP_ERASE_PP, 2 },
 | ||||
| //   { CMD_PROGRAM_FLASH_PP, 2 },
 | ||||
| //   { CMD_READ_FLASH_PP, SZ_READ_FLASH_EE },
 | ||||
| //   { CMD_PROGRAM_EEPROM_PP, 2 },
 | ||||
| //   { CMD_READ_EEPROM_PP, SZ_READ_FLASH_EE },
 | ||||
| //   { CMD_PROGRAM_FUSE_PP, 2 },
 | ||||
| //   { CMD_READ_FUSE_PP, 3 },
 | ||||
| //   { CMD_PROGRAM_LOCK_PP, 2 },
 | ||||
| //   { CMD_READ_LOCK_PP, 3 },
 | ||||
| //   { CMD_READ_SIGNATURE_PP, 3 },
 | ||||
| //   { CMD_READ_OSCCAL_PP, 3 },
 | ||||
| // };
 | ||||
| 
 | ||||
| /*
 | ||||
|  * From XML file: | ||||
|  | @ -379,15 +379,15 @@ static void stk500v2_jtag3_teardown(PROGRAMMER * pgm) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| static unsigned short | ||||
| b2_to_u16(unsigned char *b) | ||||
| { | ||||
|   unsigned short l; | ||||
|   l = b[0]; | ||||
|   l += (unsigned)b[1] << 8; | ||||
| // static unsigned short
 | ||||
| // b2_to_u16(unsigned char *b)
 | ||||
| // {
 | ||||
| //   unsigned short l;
 | ||||
| //   l = b[0];
 | ||||
| //   l += (unsigned)b[1] << 8;
 | ||||
| 
 | ||||
|   return l; | ||||
| } | ||||
| //   return l;
 | ||||
| // }
 | ||||
| 
 | ||||
| static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len) | ||||
| { | ||||
|  | @ -399,16 +399,16 @@ static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len) | |||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| static unsigned short get_jtagisp_return_size(unsigned char cmd) | ||||
| { | ||||
|   int i; | ||||
| // static unsigned short get_jtagisp_return_size(unsigned char cmd)
 | ||||
| // {
 | ||||
| //   int i;
 | ||||
| 
 | ||||
|   for (i = 0; i < sizeof jtagispcmds / sizeof jtagispcmds[0]; i++) | ||||
|     if (jtagispcmds[i].cmd == cmd) | ||||
|       return jtagispcmds[i].size; | ||||
| //   for (i = 0; i < sizeof jtagispcmds / sizeof jtagispcmds[0]; i++)
 | ||||
| //     if (jtagispcmds[i].cmd == cmd)
 | ||||
| //       return jtagispcmds[i].size;
 | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| //   return 0;
 | ||||
| // }
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Send the data as a JTAG ICE mkII encapsulated ISP packet. | ||||
|  | @ -504,7 +504,7 @@ static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len) | |||
| 
 | ||||
|   buf[0] = MESSAGE_START; | ||||
|   buf[1] = PDATA(pgm)->command_sequence; | ||||
|   buf[2] = len / 256; | ||||
|   buf[2] = (char)(len / 256); | ||||
|   buf[3] = len % 256; | ||||
|   buf[4] = TOKEN; | ||||
|   memcpy(buf+5, data, len); | ||||
|  | @ -1128,7 +1128,8 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p) | |||
| { | ||||
|   unsigned char buf[16]; | ||||
|   char msg[100];             /* see remarks above about size needed */ | ||||
|   int rv, tries; | ||||
|   int rv; | ||||
|   // int tries;
 | ||||
| 
 | ||||
|   PDATA(pgm)->lastpart = p; | ||||
| 
 | ||||
|  | @ -1143,7 +1144,7 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p) | |||
|       /* Activate AVR-style (low active) RESET */ | ||||
|       stk500v2_setparm_real(pgm, PARAM_RESET_POLARITY, 0x01); | ||||
| 
 | ||||
|   tries = 0; | ||||
|   // tries = 0;
 | ||||
| // retry:
 | ||||
|   buf[0] = CMD_ENTER_PROGMODE_ISP; | ||||
|   buf[1] = p->timeout; | ||||
|  | @ -1882,7 +1883,7 @@ static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, | |||
|     if (stk500v2_loadaddr(pgm, use_ext_addr | (paddr >> addrshift)) < 0) | ||||
|         return -1; | ||||
|   } else { | ||||
|     buf[1] = addr; | ||||
|     buf[1] = (char)addr; | ||||
|   } | ||||
| 
 | ||||
|   avrdude_message(MSG_NOTICE2, "%s: stk500hv_read_byte(): Sending read memory command: ", | ||||
|  | @ -2137,7 +2138,7 @@ static int stk500hv_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, | |||
|     if (stk500v2_loadaddr(pgm, use_ext_addr | (paddr >> addrshift)) < 0) | ||||
|         return -1; | ||||
|   } else { | ||||
|     buf[1] = addr; | ||||
|     buf[1] = (char)addr; | ||||
|     buf[2] = data; | ||||
|     if (mode == PPMODE) { | ||||
|       buf[3] = pulsewidth; | ||||
|  | @ -2298,7 +2299,7 @@ static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, | |||
|                                 unsigned int page_size, | ||||
|                                 unsigned int addr, unsigned int n_bytes) | ||||
| { | ||||
| static int page = 0; | ||||
| // static int page = 0;
 | ||||
|   unsigned int block_size, last_addr, addrshift, use_ext_addr; | ||||
|   unsigned int maxaddr = addr + n_bytes; | ||||
|   unsigned char commandbuf[10]; | ||||
|  | @ -2833,10 +2834,10 @@ static int stk500v2_set_fosc(PROGRAMMER * pgm, double v) | |||
|                       progname, v, unit, STK500V2_XTAL / 2e6); | ||||
|       fosc = STK500V2_XTAL / 2; | ||||
|     } else | ||||
|       fosc = (unsigned)v; | ||||
|       fosc = (int)v; | ||||
| 
 | ||||
|     for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) { | ||||
|       if (fosc >= STK500V2_XTAL / (256 * ps[idx] * 2)) { | ||||
|       if (fosc >= (int)(STK500V2_XTAL / (256 * ps[idx] * 2))) { | ||||
|         /* this prescaler value can handle our frequency */ | ||||
|         prescale = idx + 1; | ||||
|         cmatch = (unsigned)(STK500V2_XTAL / (2 * fosc * ps[idx])) - 1; | ||||
|  | @ -3065,8 +3066,8 @@ static int stk600_set_fosc(PROGRAMMER * pgm, double v) | |||
| { | ||||
|   unsigned int oct, dac; | ||||
| 
 | ||||
|   oct = 1.443 * log(v / 1039.0); | ||||
|   dac = 2048 - (2078.0 * pow(2, (double)(10 + oct))) / v; | ||||
|   oct = (unsigned)(1.443 * log(v / 1039.0)); | ||||
|   dac = (unsigned)(2048.0 - (2078.0 * pow(2, (double)(10 + oct))) / v); | ||||
| 
 | ||||
|   return stk500v2_setparm2(pgm, PARAM2_CLOCK_CONF, (oct << 12) | (dac << 2)); | ||||
| } | ||||
|  | @ -3075,7 +3076,7 @@ static int stk600_set_sck_period(PROGRAMMER * pgm, double v) | |||
| { | ||||
|   unsigned int sck; | ||||
| 
 | ||||
|   sck = ceil((16e6 / (2 * 1.0 / v)) - 1); | ||||
|   sck = (unsigned)ceil((16e6 / (2 * 1.0 / v)) - 1); | ||||
| 
 | ||||
|   if (sck >= 4096) | ||||
|     sck = 4095; | ||||
|  | @ -3093,7 +3094,7 @@ static int stk500v2_jtag3_set_sck_period(PROGRAMMER * pgm, double v) | |||
|   else if (v > 1E-3) | ||||
|     sck = 1; | ||||
|   else | ||||
|     sck = 1.0 / (1000.0 * v); | ||||
|     sck = (unsigned)(1.0 / (1000.0 * v)); | ||||
| 
 | ||||
|   value[0] = CMD_SET_SCK; | ||||
|   value[1] = sck & 0xff; | ||||
|  | @ -3143,7 +3144,7 @@ static int stk500v2_setparm_real(PROGRAMMER * pgm, unsigned char parm, unsigned | |||
| 
 | ||||
| static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value) | ||||
| { | ||||
|   unsigned char current_value; | ||||
|   unsigned char current_value = 0; | ||||
|   int res; | ||||
| 
 | ||||
|   res = stk500v2_getparm(pgm, parm, ¤t_value); | ||||
|  | @ -3214,8 +3215,15 @@ static const char *stk600_get_cardname(const struct carddata *table, | |||
| 
 | ||||
| static void stk500v2_display(PROGRAMMER * pgm, const char * p) | ||||
| { | ||||
|   unsigned char maj, min, hdw, topcard, maj_s1, min_s1, maj_s2, min_s2; | ||||
|   unsigned int rev; | ||||
|   unsigned char maj = 0; | ||||
|   unsigned char min = 0; | ||||
|   unsigned char hdw = 0; | ||||
|   unsigned char topcard = 0; | ||||
|   unsigned char maj_s1 = 0; | ||||
|   unsigned char min_s1 = 0; | ||||
|   unsigned char maj_s2 = 0; | ||||
|   unsigned char min_s2 = 0; | ||||
|   unsigned int rev = 0; | ||||
|   const char *topcard_name, *pgmname; | ||||
| 
 | ||||
|   switch (PDATA(pgm)->pgmtype) { | ||||
|  | @ -3294,13 +3302,20 @@ f_to_kHz_MHz(double f, const char **unit) | |||
| 
 | ||||
| static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p) | ||||
| { | ||||
|   unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration =0; //XXX 0 is not correct, check caller
 | ||||
|   unsigned int sck_stk600, clock_conf, dac, oct, varef; | ||||
|   unsigned char vtarget_jtag[4]; | ||||
|   unsigned char vtarget = 0; | ||||
|   unsigned char vadjust = 0; | ||||
|   unsigned char sck_duration = 0; | ||||
|   unsigned char osc_pscale = 0; | ||||
|   unsigned char osc_cmatch = 0; | ||||
|   unsigned varef = 0; | ||||
|   unsigned sck_stk600 = 0; | ||||
|   unsigned clock_conf = 0; | ||||
|   unsigned dac, oct; | ||||
|   // unsigned char vtarget_jtag[4];
 | ||||
|   int prescale; | ||||
|   double f; | ||||
|   const char *unit; | ||||
|   void *mycookie; | ||||
|   // void *mycookie;
 | ||||
| 
 | ||||
|   if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) { | ||||
|     return; | ||||
|  | @ -3963,10 +3978,10 @@ static int stk600_xprog_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, | |||
|     b[0] = XPRG_CMD_WRITE_MEM; | ||||
|     b[1] = memcode; | ||||
|     b[2] = 0;			/* pagemode: non-paged write */ | ||||
|     b[3] = addr >> 24; | ||||
|     b[4] = addr >> 16; | ||||
|     b[5] = addr >> 8; | ||||
|     b[6] = addr; | ||||
|     b[3] = (char)(addr >> 24); | ||||
|     b[4] = (char)(addr >> 16); | ||||
|     b[5] = (char)(addr >> 8); | ||||
|     b[6] = (char)addr; | ||||
|     b[7] = 0; | ||||
|     b[8] = write_size; | ||||
|     b[9] = data; | ||||
|  | @ -4011,10 +4026,10 @@ static int stk600_xprog_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, | |||
|     addr += mem->offset; | ||||
| 
 | ||||
|     b[0] = XPRG_CMD_READ_MEM; | ||||
|     b[2] = addr >> 24; | ||||
|     b[3] = addr >> 16; | ||||
|     b[4] = addr >> 8; | ||||
|     b[5] = addr; | ||||
|     b[2] = (char)(addr >> 24); | ||||
|     b[3] = (char)(addr >> 16); | ||||
|     b[4] = (char)(addr >> 8); | ||||
|     b[5] = (char)addr; | ||||
|     b[6] = 0; | ||||
|     b[7] = 1; | ||||
|     if (stk600_xprog_command(pgm, b, 8, 3) < 0) { | ||||
|  |  | |||
|  | @ -281,7 +281,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, | |||
| 
 | ||||
|   maxsize = mem->size; | ||||
| 
 | ||||
|   if (addr >= maxsize) { | ||||
|   if (addr >= (unsigned long)maxsize) { | ||||
|     if (argc == 2) { | ||||
|       /* wrap around */ | ||||
|       addr = 0; | ||||
|  | @ -294,7 +294,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, | |||
|   } | ||||
| 
 | ||||
|   /* trim len if nessary to not read past the end of memory */ | ||||
|   if ((addr + len) > maxsize) | ||||
|   if ((addr + len) > (unsigned long)maxsize) | ||||
|     len = maxsize - addr; | ||||
| 
 | ||||
|   buf = malloc(len); | ||||
|  | @ -303,7 +303,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, | |||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   for (i=0; i<len; i++) { | ||||
|   for (i = 0; i < (unsigned long)len; i++) { | ||||
|     rc = pgm->read_byte(pgm, p, mem, addr+i, &buf[i]); | ||||
|     if (rc != 0) { | ||||
|       avrdude_message(MSG_INFO, "error reading %s address 0x%05lx of part %s\n", | ||||
|  | @ -364,7 +364,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, | |||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   if (addr > maxsize) { | ||||
|   if (addr > (unsigned long)maxsize) { | ||||
|     avrdude_message(MSG_INFO, "%s (write): address 0x%05lx is out of range for %s memory\n", | ||||
|                     progname, addr, memtype); | ||||
|     return -1; | ||||
|  | @ -373,7 +373,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, | |||
|   /* number of bytes to write at the specified address */ | ||||
|   len = argc - 3; | ||||
| 
 | ||||
|   if ((addr + len) > maxsize) { | ||||
|   if ((addr + len) > (unsigned long)maxsize) { | ||||
|     avrdude_message(MSG_INFO, "%s (write): selected address and # bytes exceed " | ||||
|                     "range for %s memory\n", | ||||
|                     progname, memtype); | ||||
|  | @ -386,8 +386,8 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, | |||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   for (i=3; i<argc; i++) { | ||||
|     buf[i-3] = strtoul(argv[i], &e, 0); | ||||
|   for (i = 3; i < (unsigned long)argc; i++) { | ||||
|     buf[i-3] = (char)strtoul(argv[i], &e, 0); | ||||
|     if (*e || (e == argv[i])) { | ||||
|       avrdude_message(MSG_INFO, "%s (write): can't parse byte \"%s\"\n", | ||||
|               progname, argv[i]); | ||||
|  | @ -397,7 +397,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, | |||
|   } | ||||
| 
 | ||||
|   pgm->err_led(pgm, OFF); | ||||
|   for (werror=0, i=0; i<len; i++) { | ||||
|   for (werror = 0, i = 0; i < (unsigned long)len; i++) { | ||||
| 
 | ||||
|     rc = avr_write_byte(pgm, p, mem, addr+i, buf[i]); | ||||
|     if (rc) { | ||||
|  | @ -462,7 +462,7 @@ static int cmd_send(PROGRAMMER * pgm, struct avrpart * p, | |||
| 
 | ||||
|   /* load command bytes */ | ||||
|   for (i=1; i<argc; i++) { | ||||
|     cmd[i-1] = strtoul(argv[i], &e, 0); | ||||
|     cmd[i-1] = (char)strtoul(argv[i], &e, 0); | ||||
|     if (*e || (e == argv[i])) { | ||||
|       avrdude_message(MSG_INFO, "%s (send): can't parse byte \"%s\"\n", | ||||
|               progname, argv[i]); | ||||
|  | @ -789,7 +789,7 @@ static int tokenize(char * s, char *** argv) | |||
|   char  * nbuf; | ||||
|   char ** av; | ||||
| 
 | ||||
|   slen = strlen(s); | ||||
|   slen = (int)strlen(s); | ||||
| 
 | ||||
|   /* 
 | ||||
|    * initialize allow for 20 arguments, use realloc to grow this if | ||||
|  | @ -812,7 +812,7 @@ static int tokenize(char * s, char *** argv) | |||
|     nexttok(r, &q, &r); | ||||
|     strcpy(nbuf, q); | ||||
|     bufv[n]  = nbuf; | ||||
|     len      = strlen(q); | ||||
|     len      = (int)strlen(q); | ||||
|     l       += len + 1; | ||||
|     nbuf    += len + 1; | ||||
|     nbuf[0]  = 0; | ||||
|  | @ -841,7 +841,7 @@ static int tokenize(char * s, char *** argv) | |||
|   q  = (char *)&av[n+1]; | ||||
|   memcpy(q, buf, l); | ||||
|   for (i=0; i<n; i++) { | ||||
|     offset = bufv[i] - buf; | ||||
|     offset = (int)(bufv[i] - buf); | ||||
|     av[i] = q + offset; | ||||
|   } | ||||
|   av[i] = NULL; | ||||
|  | @ -862,7 +862,7 @@ static int do_cmd(PROGRAMMER * pgm, struct avrpart * p, | |||
|   int hold; | ||||
|   int len; | ||||
| 
 | ||||
|   len = strlen(argv[0]); | ||||
|   len = (int)strlen(argv[0]); | ||||
|   hold = -1; | ||||
|   for (i=0; i<NCMDS; i++) { | ||||
|     if (strcasecmp(argv[0], cmd[i].name) == 0) { | ||||
|  |  | |||
|  | @ -63,10 +63,15 @@ extern "C" { | |||
| #define STDOUT_FILENO 1 | ||||
| #define STDERR_FILENO 2 | ||||
| 
 | ||||
| #if defined(_MSC_VER) && defined(__clang__) | ||||
| #include <stdint.h> | ||||
| struct timezone; | ||||
| struct timeval; | ||||
| #else | ||||
| #ifndef __cplusplus | ||||
| /* should be in some equivalent to <sys/types.h> */ | ||||
| typedef __int8            int8_t; | ||||
| typedef __int16           int16_t;  | ||||
| typedef __int16           int16_t; | ||||
| typedef __int32           int32_t; | ||||
| typedef __int64           int64_t; | ||||
| typedef unsigned __int8   uint8_t; | ||||
|  | @ -74,6 +79,7 @@ typedef unsigned __int16  uint16_t; | |||
| typedef unsigned __int32  uint32_t; | ||||
| typedef unsigned __int64  uint64_t; | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| int usleep(unsigned usec); | ||||
|  |  | |||
|  | @ -19,6 +19,6 @@ add_library(nowide STATIC | |||
|     nowide/windows.hpp | ||||
| ) | ||||
| 
 | ||||
| target_include_directories(nowide SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) | ||||
| target_link_libraries(nowide PUBLIC boost_headeronly) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -102,7 +102,7 @@ protected: | |||
|         #ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST | ||||
|         return from - save_from; | ||||
|         #else | ||||
|         return save_max - max; | ||||
|         return int(save_max - max); | ||||
|         #endif | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										39
									
								
								src/build-utils/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,39 @@ | |||
| 
 | ||||
| add_executable(encoding-check encoding-check.cpp) | ||||
| 
 | ||||
| # A global no-op target which depends on all encodings checks, | ||||
| # and on which in turn all checked targets depend. | ||||
| # This is done to make encoding checks the first thing to be | ||||
| # performed before actually compiling any sources of the checked targets | ||||
| # to make the check fail as early as possible. | ||||
| add_custom_target(global-encoding-check | ||||
|     ALL | ||||
|     DEPENDS encoding-check | ||||
| ) | ||||
| 
 | ||||
| # Function that adds source file encoding check to a target | ||||
| # using the above encoding-check binary | ||||
| 
 | ||||
| function(encoding_check TARGET) | ||||
|     # Obtain target source files | ||||
|     get_target_property(T_SOURCES ${TARGET} SOURCES) | ||||
| 
 | ||||
|     # Define top-level encoding check target for this ${TARGET} | ||||
|     add_custom_target(encoding-check-${TARGET} | ||||
|         DEPENDS encoding-check ${T_SOURCES} | ||||
|         COMMENT "Checking source files encodings for target ${TARGET}" | ||||
|     ) | ||||
| 
 | ||||
|     # Add checking of each source file as a subcommand of encoding-check-${TARGET} | ||||
|     foreach(file ${T_SOURCES}) | ||||
|         add_custom_command(TARGET encoding-check-${TARGET} | ||||
|             COMMAND $<TARGET_FILE:encoding-check> ${TARGET} ${file} | ||||
|             WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | ||||
|         ) | ||||
|     endforeach() | ||||
| 
 | ||||
|     # This adds dependency on encoding-check-${TARGET} to ${TARET} | ||||
|     # via the global-encoding-check | ||||
|     add_dependencies(global-encoding-check encoding-check-${TARGET}) | ||||
|     add_dependencies(${TARGET} global-encoding-check) | ||||
| endfunction() | ||||
							
								
								
									
										119
									
								
								src/build-utils/encoding-check.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,119 @@ | |||
| #include <vector> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <cstdlib> | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * The utf8_check() function scans the '\0'-terminated string starting | ||||
|  * at s. It returns a pointer to the first byte of the first malformed | ||||
|  * or overlong UTF-8 sequence found, or NULL if the string contains | ||||
|  * only correct UTF-8. It also spots UTF-8 sequences that could cause | ||||
|  * trouble if converted to UTF-16, namely surrogate characters | ||||
|  * (U+D800..U+DFFF) and non-Unicode positions (U+FFFE..U+FFFF). This | ||||
|  * routine is very likely to find a malformed sequence if the input | ||||
|  * uses any other encoding than UTF-8. It therefore can be used as a | ||||
|  * very effective heuristic for distinguishing between UTF-8 and other | ||||
|  * encodings. | ||||
|  * | ||||
|  * I wrote this code mainly as a specification of functionality; there | ||||
|  * are no doubt performance optimizations possible for certain CPUs. | ||||
|  * | ||||
|  * Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> -- 2005-03-30
 | ||||
|  * License: http://www.cl.cam.ac.uk/~mgk25/short-license.html
 | ||||
|  */ | ||||
| 
 | ||||
| unsigned char *utf8_check(unsigned char *s) | ||||
| { | ||||
|     while (*s) { | ||||
|         if (*s < 0x80) { | ||||
|             // 0xxxxxxx
 | ||||
|             s++; | ||||
|         } else if ((s[0] & 0xe0) == 0xc0) { | ||||
|             // 110xxxxx 10xxxxxx
 | ||||
|             if ((s[1] & 0xc0) != 0x80 || | ||||
|                 (s[0] & 0xfe) == 0xc0) {         // overlong?
 | ||||
|                 return s; | ||||
|             } else { | ||||
|                 s += 2; | ||||
|             } | ||||
|         } else if ((s[0] & 0xf0) == 0xe0) { | ||||
|             // 1110xxxx 10xxxxxx 10xxxxxx
 | ||||
|             if ((s[1] & 0xc0) != 0x80 || | ||||
|                 (s[2] & 0xc0) != 0x80 || | ||||
|                 (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || // overlong?
 | ||||
|                 (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || // surrogate?
 | ||||
|                 (s[0] == 0xef && s[1] == 0xbf && | ||||
|                 (s[2] & 0xfe) == 0xbe)) {                  // U+FFFE or U+FFFF?
 | ||||
|                 return s; | ||||
|             } else { | ||||
|                 s += 3; | ||||
|             } | ||||
|         } else if ((s[0] & 0xf8) == 0xf0) { | ||||
|             // 11110xxX 10xxxxxx 10xxxxxx 10xxxxxx
 | ||||
|             if ((s[1] & 0xc0) != 0x80 || | ||||
|                 (s[2] & 0xc0) != 0x80 || | ||||
|                 (s[3] & 0xc0) != 0x80 || | ||||
|                 (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) ||      // overlong?
 | ||||
|                 (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) { // > U+10FFFF?
 | ||||
|                 return s; | ||||
|             } else { | ||||
|                 s += 4; | ||||
|             } | ||||
|         } else { | ||||
|             return s; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main(int argc, char const *argv[]) | ||||
| { | ||||
|     if (argc != 3) { | ||||
|         std::cerr << "Usage: " << argv[0] << " <program/library> <file>" << std::endl; | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     const char* target = argv[1]; | ||||
|     const char* filename = argv[2]; | ||||
| 
 | ||||
|     const auto error_exit = [=](const char* error) { | ||||
|         std::cerr << "\n\tError: " << error << ": " << filename << "\n" | ||||
|             << "\tTarget: " << target << "\n" | ||||
|             << std::endl; | ||||
|         std::exit(-2); | ||||
|     }; | ||||
| 
 | ||||
|     std::ifstream file(filename, std::ios::binary | std::ios::ate); | ||||
|     const auto size = file.tellg(); | ||||
| 
 | ||||
|     if (size == 0) { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     file.seekg(0, std::ios::beg); | ||||
|     std::vector<char> buffer(size); | ||||
| 
 | ||||
|     if (file.read(buffer.data(), size)) { | ||||
|         buffer.push_back('\0'); | ||||
| 
 | ||||
|         // Check UTF-8 validity
 | ||||
|         if (utf8_check(reinterpret_cast<unsigned char*>(buffer.data())) != nullptr) { | ||||
|             error_exit("Source file does not contain (valid) UTF-8"); | ||||
|         } | ||||
| 
 | ||||
|         // Check against a BOM mark
 | ||||
|         if (buffer.size() >= 3 | ||||
|             && buffer[0] == '\xef' | ||||
|             && buffer[1] == '\xbb' | ||||
|             && buffer[2] == '\xbf') { | ||||
|             error_exit("Source file is valid UTF-8 but contains a BOM mark"); | ||||
|         } | ||||
|     } else { | ||||
|         error_exit("Could not read source file"); | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  | @ -1,70 +0,0 @@ | |||
| // This file is part of libigl, a simple c++ geometry processing library.
 | ||||
| // 
 | ||||
| // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
 | ||||
| // 
 | ||||
| // This Source Code Form is subject to the terms of the Mozilla Public License 
 | ||||
| // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 | ||||
| // obtain one at http://mozilla.org/MPL/2.0/.
 | ||||
| #ifndef IGL_SORTABLE_ROW_H | ||||
| #define IGL_SORTABLE_ROW_H | ||||
| 
 | ||||
| // Simple class to contain a rowvector which allows rowwise sorting and
 | ||||
| // reordering
 | ||||
| #include <Eigen/Core> | ||||
| 
 | ||||
| namespace igl | ||||
| { | ||||
|   // Templates:
 | ||||
|   //   T  should be a matrix that implements .size(), and operator(int i)
 | ||||
|   template <typename T> | ||||
|   class SortableRow | ||||
|   { | ||||
|     public: | ||||
|       T data; | ||||
|     public: | ||||
|       SortableRow():data(){}; | ||||
|       SortableRow(const T & data):data(data){}; | ||||
|       bool operator<(const SortableRow & that) const | ||||
|       { | ||||
|         // Get reference so that I can use parenthesis
 | ||||
|         const SortableRow<T> & THIS = *this; | ||||
|         // Lexicographical
 | ||||
|         int minc = (THIS.data.size() < that.data.size()?  | ||||
|             THIS.data.size() : that.data.size()); | ||||
|         // loop over columns
 | ||||
|         for(int i = 0;i<minc;i++) | ||||
|         { | ||||
|           if(THIS.data(i) == that.data(i)) | ||||
|           { | ||||
|             continue; | ||||
|           } | ||||
|           return THIS.data(i) < that.data(i); | ||||
|         } | ||||
|         // All characters the same, comes done to length
 | ||||
|         return THIS.data.size()<that.data.size(); | ||||
|       }; | ||||
|       bool operator==(const SortableRow & that) const | ||||
|       { | ||||
|         // Get reference so that I can use parenthesis
 | ||||
|         const SortableRow<T> & THIS = *this; | ||||
|         if(THIS.data.size() != that.data.size()) | ||||
|         { | ||||
|           return false; | ||||
|         } | ||||
|         for(int i = 0;i<THIS.data.size();i++) | ||||
|         { | ||||
|           if(THIS.data(i) != that.data(i)) | ||||
|           { | ||||
|             return false; | ||||
|           } | ||||
|         } | ||||
|         return true; | ||||
|       }; | ||||
|       bool operator!=(const SortableRow & that) const | ||||
|       { | ||||
|         return !(*this == that); | ||||
|       }; | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										14
									
								
								src/libigl/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,14 @@ | |||
| project(libigl) | ||||
| cmake_minimum_required(VERSION 3.0) | ||||
| 
 | ||||
| add_library(libigl INTERFACE) | ||||
| 
 | ||||
| find_package(libigl QUIET) | ||||
| 
 | ||||
| if(libigl_FOUND) | ||||
|     message(STATUS "IGL found, using system version...") | ||||
|     target_link_libraries(libigl INTERFACE igl::core) | ||||
| else() | ||||
|     message(STATUS "IGL NOT found, using bundled version...") | ||||
|     target_include_directories(libigl SYSTEM BEFORE INTERFACE ${LIBDIR}/libigl) | ||||
| endif() | ||||
 YuSanka
						YuSanka