Merge remote-tracking branch 'origin/master' into lm_wiping_dialog_colors
|
@ -18,8 +18,8 @@ AllowShortLoopsOnASingleLine: true
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
AlwaysBreakAfterReturnType: None
|
AlwaysBreakAfterReturnType: None
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
AlwaysBreakTemplateDeclarations: false
|
||||||
BinPackArguments: false
|
BinPackArguments: true
|
||||||
BinPackParameters: false
|
BinPackParameters: false
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterClass: true
|
AfterClass: true
|
||||||
|
@ -37,18 +37,18 @@ BraceWrapping:
|
||||||
SplitEmptyFunction: false
|
SplitEmptyFunction: false
|
||||||
SplitEmptyRecord: false
|
SplitEmptyRecord: false
|
||||||
SplitEmptyNamespace: false
|
SplitEmptyNamespace: false
|
||||||
BreakBeforeBinaryOperators: All
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeBraces: Custom
|
BreakBeforeBraces: Custom
|
||||||
BreakBeforeInheritanceComma: false
|
BreakBeforeInheritanceComma: false
|
||||||
BreakInheritanceList: BeforeColon
|
BreakInheritanceList: BeforeColon
|
||||||
BreakBeforeTernaryOperators: true
|
BreakBeforeTernaryOperators: false
|
||||||
BreakConstructorInitializersBeforeComma: false
|
BreakConstructorInitializersBeforeComma: false
|
||||||
BreakConstructorInitializers: BeforeComma
|
BreakConstructorInitializers: BeforeComma
|
||||||
BreakAfterJavaFieldAnnotations: false
|
BreakAfterJavaFieldAnnotations: false
|
||||||
BreakStringLiterals: true
|
BreakStringLiterals: true
|
||||||
ColumnLimit: 75
|
ColumnLimit: 78
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
CompactNamespaces: false
|
CompactNamespaces: true
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
ConstructorInitializerIndentWidth: 4
|
ConstructorInitializerIndentWidth: 4
|
||||||
ContinuationIndentWidth: 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
|
#### 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)_
|
_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::MakeMaker 6.80
|
||||||
ExtUtils::ParseXS 3.22
|
ExtUtils::ParseXS 3.22
|
||||||
ExtUtils::XSpp 0
|
ExtUtils::XSpp 0
|
||||||
|
ExtUtils::XSpp::Cmd 0
|
||||||
|
ExtUtils::CppGuess 0
|
||||||
ExtUtils::Typemaps 0
|
ExtUtils::Typemaps 0
|
||||||
ExtUtils::Typemaps::Basic 0
|
ExtUtils::Typemaps::Basic 0
|
||||||
File::Basename 0
|
File::Basename 0
|
||||||
|
|
152
CMakeLists.txt
|
@ -13,13 +13,13 @@ if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(DEFINED ENV{SLIC3R_STATIC})
|
if(DEFINED ENV{SLIC3R_STATIC})
|
||||||
set(SLIC3R_STATIC_INITIAL $ENV{SLIC3R_STATIC})
|
set(SLIC3R_STATIC_INITIAL $ENV{SLIC3R_STATIC})
|
||||||
else()
|
else()
|
||||||
if (MSVC OR MINGW OR APPLE)
|
if (MSVC OR MINGW OR APPLE)
|
||||||
set(SLIC3R_STATIC_INITIAL 1)
|
set(SLIC3R_STATIC_INITIAL 1)
|
||||||
else()
|
else()
|
||||||
set(SLIC3R_STATIC_INITIAL 0)
|
set(SLIC3R_STATIC_INITIAL 0)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(SLIC3R_STATIC "Compile PrusaSlicer with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL})
|
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_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_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_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")
|
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)
|
add_definitions(-DSLIC3R_GUI)
|
||||||
endif ()
|
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 (MSVC)
|
||||||
if (SLIC3R_MSVC_COMPILE_PARALLEL)
|
if (SLIC3R_MSVC_COMPILE_PARALLEL AND NOT IS_CLANG_CL)
|
||||||
add_compile_options(/MP)
|
add_compile_options(/MP)
|
||||||
endif ()
|
endif ()
|
||||||
# /bigobj (Increase Number of Sections in .Obj file)
|
# /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
|
# 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.
|
# 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 ()
|
endif ()
|
||||||
|
|
||||||
# Display and check CMAKE_PREFIX_PATH
|
# Display and check CMAKE_PREFIX_PATH
|
||||||
|
@ -89,8 +104,6 @@ enable_testing ()
|
||||||
# Enable C++11 language standard.
|
# Enable C++11 language standard.
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_C_STANDARD 11)
|
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
# Add DEBUG flags to debug builds.
|
# 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.
|
# 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
|
# We pick it from environment if it is not defined in another way
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
if(NOT DEFINED WIN10SDK_PATH)
|
if(NOT DEFINED WIN10SDK_PATH)
|
||||||
if(DEFINED ENV{WIN10SDK_PATH})
|
if(DEFINED ENV{WIN10SDK_PATH})
|
||||||
set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}")
|
set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(DEFINED WIN10SDK_PATH AND NOT EXISTS "${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h")
|
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 is invalid: ${WIN10SDK_PATH}")
|
||||||
message("${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h was not found")
|
message("${WIN10SDK_PATH}/include/winrt/windows.graphics.printing3d.h was not found")
|
||||||
message("STL fixing by the Netfabb service will not be compiled")
|
message("STL fixing by the Netfabb service will not be compiled")
|
||||||
unset(WIN10SDK_PATH)
|
unset(WIN10SDK_PATH)
|
||||||
endif()
|
endif()
|
||||||
if(WIN10SDK_PATH)
|
if(WIN10SDK_PATH)
|
||||||
message("Building with Win10 Netfabb STL fixing service support")
|
message("Building with Win10 Netfabb STL fixing service support")
|
||||||
add_definitions(-DHAS_WIN10SDK)
|
add_definitions(-DHAS_WIN10SDK)
|
||||||
|
@ -149,30 +162,29 @@ endif()
|
||||||
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX)
|
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.
|
# 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" )
|
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()
|
endif()
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||||
add_compile_options(-Wall)
|
if (NOT MINGW)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
|
||||||
|
endif ()
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder" )
|
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.
|
# 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)
|
add_compile_options(-Werror=return-type)
|
||||||
|
|
||||||
#removes LOTS of extraneous Eigen warnings
|
#removes LOTS of extraneous Eigen warnings (GCC only supports it since 6.1)
|
||||||
add_compile_options(-Wno-ignored-attributes)
|
#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)
|
if (SLIC3R_ASAN)
|
||||||
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
|
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
|
||||||
|
@ -201,9 +213,12 @@ include_directories(${LIBDIR_BIN}/platform)
|
||||||
include_directories(${LIBDIR}/clipper ${LIBDIR}/polypartition)
|
include_directories(${LIBDIR}/clipper ${LIBDIR}/polypartition)
|
||||||
|
|
||||||
if(WIN32)
|
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 -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS)
|
||||||
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)
|
if(MSVC)
|
||||||
endif()
|
# 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)
|
add_definitions(-DwxUSE_UNICODE -D_UNICODE -DUNICODE -DWXINTL_NO_GETTEXT_MACRO)
|
||||||
|
|
||||||
|
@ -234,21 +249,40 @@ if(SLIC3R_STATIC)
|
||||||
# set(Boost_USE_STATIC_RUNTIME ON)
|
# set(Boost_USE_STATIC_RUNTIME ON)
|
||||||
endif()
|
endif()
|
||||||
#set(Boost_DEBUG ON)
|
#set(Boost_DEBUG ON)
|
||||||
# set(Boost_COMPILER "-vc120")
|
# set(Boost_COMPILER "-mgw81")
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
# boost::process was introduced first in version 1.64.0
|
# boost::process was introduced first in version 1.64.0
|
||||||
set(MINIMUM_BOOST_VERSION "1.64.0")
|
set(MINIMUM_BOOST_VERSION "1.64.0")
|
||||||
endif()
|
endif()
|
||||||
find_package(Boost ${MINIMUM_BOOST_VERSION} REQUIRED COMPONENTS system filesystem thread log locale regex)
|
find_package(Boost ${MINIMUM_BOOST_VERSION} REQUIRED COMPONENTS system filesystem thread log locale regex)
|
||||||
if(Boost_FOUND)
|
|
||||||
# include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
add_library(boost_libs INTERFACE)
|
||||||
if (APPLE)
|
add_library(boost_headeronly INTERFACE)
|
||||||
# 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)
|
if (APPLE)
|
||||||
endif()
|
# BOOST_ASIO_DISABLE_KQUEUE : prevents a Boost ASIO bug on OS X: https://svn.boost.org/trac/boost/ticket/5339
|
||||||
if(NOT SLIC3R_STATIC)
|
target_compile_definitions(boost_headeronly INTERFACE BOOST_ASIO_DISABLE_KQUEUE)
|
||||||
add_definitions(-DBOOST_LOG_DYN_LINK)
|
endif()
|
||||||
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()
|
endif()
|
||||||
|
|
||||||
# Find and configure intel-tbb
|
# Find and configure intel-tbb
|
||||||
|
@ -289,13 +323,13 @@ endif()
|
||||||
|
|
||||||
# Find eigen3 or use bundled version
|
# Find eigen3 or use bundled version
|
||||||
if (NOT SLIC3R_STATIC)
|
if (NOT SLIC3R_STATIC)
|
||||||
find_package(Eigen3 3)
|
find_package(Eigen3 3.3)
|
||||||
endif ()
|
endif ()
|
||||||
if (NOT Eigen3_FOUND)
|
if (NOT EIGEN3_FOUND)
|
||||||
set(Eigen3_FOUND 1)
|
set(EIGEN3_FOUND 1)
|
||||||
set(EIGEN3_INCLUDE_DIR ${LIBDIR}/eigen/)
|
set(EIGEN3_INCLUDE_DIR ${LIBDIR}/eigen/)
|
||||||
endif ()
|
endif ()
|
||||||
include_directories(${EIGEN3_INCLUDE_DIR})
|
include_directories(BEFORE SYSTEM ${EIGEN3_INCLUDE_DIR})
|
||||||
|
|
||||||
# Find expat or use bundled version
|
# Find expat or use bundled version
|
||||||
# Always use the system libexpat on Linux.
|
# Always use the system libexpat on Linux.
|
||||||
|
@ -327,6 +361,10 @@ if (NOT GLEW_FOUND)
|
||||||
endif ()
|
endif ()
|
||||||
include_directories(${GLEW_INCLUDE_DIRS})
|
include_directories(${GLEW_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# Find the Cereal serialization library
|
||||||
|
add_library(cereal INTERFACE)
|
||||||
|
target_include_directories(cereal INTERFACE include)
|
||||||
|
|
||||||
# l10n
|
# l10n
|
||||||
set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization")
|
set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization")
|
||||||
add_custom_target(pot
|
add_custom_target(pot
|
||||||
|
|
|
@ -105,6 +105,9 @@ function(add_precompiled_header _target _input)
|
||||||
cmake_parse_arguments(_PCH "FORCEINCLUDE" "SOURCE_CXX;SOURCE_C" "" ${ARGN})
|
cmake_parse_arguments(_PCH "FORCEINCLUDE" "SOURCE_CXX;SOURCE_C" "" ${ARGN})
|
||||||
|
|
||||||
get_filename_component(_input_we ${_input} NAME_WE)
|
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)
|
if(NOT _PCH_SOURCE_CXX)
|
||||||
set(_PCH_SOURCE_CXX "${_input_we}.cpp")
|
set(_PCH_SOURCE_CXX "${_input_we}.cpp")
|
||||||
endif()
|
endif()
|
||||||
|
@ -138,16 +141,16 @@ function(add_precompiled_header _target _input)
|
||||||
set_source_files_properties("${_source}" PROPERTIES OBJECT_OUTPUTS "${_pch_c_pch}")
|
set_source_files_properties("${_source}" PROPERTIES OBJECT_OUTPUTS "${_pch_c_pch}")
|
||||||
else()
|
else()
|
||||||
if(_source MATCHES \\.\(cpp|cxx|cc\)$)
|
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(_pch_source_cxx_needed TRUE)
|
||||||
set_source_files_properties("${_source}" PROPERTIES OBJECT_DEPENDS "${_pch_cxx_pch}")
|
set_source_files_properties("${_source}" PROPERTIES OBJECT_DEPENDS "${_pch_cxx_pch}")
|
||||||
else()
|
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(_pch_source_c_needed TRUE)
|
||||||
set_source_files_properties("${_source}" PROPERTIES OBJECT_DEPENDS "${_pch_c_pch}")
|
set_source_files_properties("${_source}" PROPERTIES OBJECT_DEPENDS "${_pch_c_pch}")
|
||||||
endif()
|
endif()
|
||||||
if(_PCH_FORCEINCLUDE)
|
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(_PCH_FORCEINCLUDE)
|
||||||
endif()
|
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_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)
|
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 DESTDIR: ${DESTDIR}")
|
||||||
message(STATUS "PrusaSlicer deps debug build: ${DEP_DEBUG}")
|
message(STATUS "PrusaSlicer deps debug build: ${DEP_DEBUG}")
|
||||||
|
|
||||||
|
@ -70,7 +76,10 @@ elseif (APPLE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
include("deps-macos.cmake")
|
include("deps-macos.cmake")
|
||||||
else ()
|
elseif (MINGW)
|
||||||
|
message(STATUS "Building for MinGW...")
|
||||||
|
include("deps-mingw.cmake")
|
||||||
|
else()
|
||||||
include("deps-linux.cmake")
|
include("deps-linux.cmake")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -83,7 +92,9 @@ if (MSVC)
|
||||||
dep_libcurl
|
dep_libcurl
|
||||||
dep_wxwidgets
|
dep_wxwidgets
|
||||||
dep_gtest
|
dep_gtest
|
||||||
|
dep_cereal
|
||||||
dep_nlopt
|
dep_nlopt
|
||||||
|
# dep_qhull # Experimental
|
||||||
dep_zlib # on Windows we still need zlib
|
dep_zlib # on Windows we still need zlib
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -96,7 +107,10 @@ else()
|
||||||
dep_libcurl
|
dep_libcurl
|
||||||
dep_wxwidgets
|
dep_wxwidgets
|
||||||
dep_gtest
|
dep_gtest
|
||||||
|
dep_cereal
|
||||||
dep_nlopt
|
dep_nlopt
|
||||||
|
dep_qhull
|
||||||
|
# dep_libigl # Not working, static build has different Eigen
|
||||||
)
|
)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
2
deps/deps-macos.cmake
vendored
|
@ -111,6 +111,6 @@ ExternalProject_Add(dep_wxwidgets
|
||||||
--with-expat=builtin
|
--with-expat=builtin
|
||||||
--disable-debug
|
--disable-debug
|
||||||
--disable-debug_flag
|
--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
|
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
|
# 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
|
ExternalProject_Add(dep_tbb
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz"
|
URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz"
|
||||||
|
@ -8,6 +14,7 @@ ExternalProject_Add(dep_tbb
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DTBB_BUILD_SHARED=OFF
|
-DTBB_BUILD_SHARED=OFF
|
||||||
-DTBB_BUILD_TESTS=OFF
|
-DTBB_BUILD_TESTS=OFF
|
||||||
|
-DCMAKE_CXX_FLAGS=${TBB_MINGW_WORKAROUND}
|
||||||
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
${DEP_CMAKE_OPTS}
|
${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
|
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
|
ExternalProject_Add(dep_nlopt
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz"
|
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
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
${DEP_CMAKE_OPTS}
|
${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)
|
if (MSVC_VERSION EQUAL 1800)
|
||||||
|
# 1800 = VS 12.0 (v120 toolset)
|
||||||
set(DEP_VS_VER "12")
|
set(DEP_VS_VER "12")
|
||||||
set(DEP_BOOST_TOOLSET "msvc-12.0")
|
set(DEP_BOOST_TOOLSET "msvc-12.0")
|
||||||
elseif (MSVC_VERSION EQUAL 1900)
|
elseif (MSVC_VERSION EQUAL 1900)
|
||||||
|
# 1900 = VS 14.0 (v140 toolset)
|
||||||
set(DEP_VS_VER "14")
|
set(DEP_VS_VER "14")
|
||||||
set(DEP_BOOST_TOOLSET "msvc-14.0")
|
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_VS_VER "15")
|
||||||
set(DEP_BOOST_TOOLSET "msvc-14.1")
|
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 ()
|
else ()
|
||||||
message(FATAL_ERROR "Unsupported MSVC version")
|
message(FATAL_ERROR "Unsupported MSVC version")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||||
|
set(DEP_BOOST_TOOLSET "clang-win")
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (${DEPS_BITS} EQUAL 32)
|
if (${DEPS_BITS} EQUAL 32)
|
||||||
set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER}")
|
set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER}")
|
||||||
|
set(DEP_PLATFORM "Win32")
|
||||||
else ()
|
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 ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,8 +45,8 @@ endif ()
|
||||||
|
|
||||||
ExternalProject_Add(dep_boost
|
ExternalProject_Add(dep_boost
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
URL "https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz"
|
URL "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz"
|
||||||
URL_HASH SHA256=bd0df411efd9a585e5a2212275f8762079fed8842264954675a4fddc46cfcf60
|
URL_HASH SHA256=882b48708d211a5f48e60b0124cf5863c1534cd544ecd0664bb534a4b5d506e9
|
||||||
BUILD_IN_SOURCE 1
|
BUILD_IN_SOURCE 1
|
||||||
CONFIGURE_COMMAND bootstrap.bat
|
CONFIGURE_COMMAND bootstrap.bat
|
||||||
BUILD_COMMAND b2.exe
|
BUILD_COMMAND b2.exe
|
||||||
|
@ -57,6 +74,7 @@ ExternalProject_Add(dep_tbb
|
||||||
URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz"
|
URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz"
|
||||||
URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe
|
URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe
|
||||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
|
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DCMAKE_DEBUG_POSTFIX=_debug
|
-DCMAKE_DEBUG_POSTFIX=_debug
|
||||||
-DTBB_BUILD_SHARED=OFF
|
-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 "https://github.com/google/googletest/archive/release-1.8.1.tar.gz"
|
||||||
URL_HASH SHA256=9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c
|
URL_HASH SHA256=9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c
|
||||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
|
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DBUILD_GMOCK=OFF
|
-DBUILD_GMOCK=OFF
|
||||||
-Dgtest_force_shared_crt=ON
|
-Dgtest_force_shared_crt=ON
|
||||||
|
@ -100,11 +119,26 @@ if (${DEP_DEBUG})
|
||||||
endif ()
|
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
|
ExternalProject_Add(dep_nlopt
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz"
|
URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz"
|
||||||
URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae
|
URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae
|
||||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
|
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DBUILD_SHARED_LIBS=OFF
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
-DNLOPT_PYTHON=OFF
|
-DNLOPT_PYTHON=OFF
|
||||||
|
@ -133,6 +167,7 @@ ExternalProject_Add(dep_zlib
|
||||||
URL "https://zlib.net/zlib-1.2.11.tar.xz"
|
URL "https://zlib.net/zlib-1.2.11.tar.xz"
|
||||||
URL_HASH SHA256=4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066
|
URL_HASH SHA256=4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066
|
||||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
|
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DSKIP_INSTALL_FILES=ON # Prevent installation of man pages et al.
|
-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 :-/
|
"-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 ()
|
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)
|
if (${DEPS_BITS} EQUAL 32)
|
||||||
set(DEP_WXWIDGETS_TARGET "")
|
set(DEP_WXWIDGETS_TARGET "")
|
||||||
|
@ -208,6 +270,51 @@ else ()
|
||||||
set(DEP_WXWIDGETS_LIBDIR "vc_x64_lib")
|
set(DEP_WXWIDGETS_LIBDIR "vc_x64_lib")
|
||||||
endif ()
|
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
|
ExternalProject_Add(dep_wxwidgets
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets"
|
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
|
# 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
|
### 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.
|
**Warning**: Once the dependency bundle is installed in a destdir, the destdir cannot be moved elsewhere.
|
||||||
(This is because wxWidgets hardcodes the installation path.)
|
(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
|
### 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
|
# 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/).
|
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.
|
_Note:_ Thanks to [**@supermerill**](https://github.com/supermerill) for testing and inspiration for this guide.
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
On Windows PrusaSlicer is built against statically built libraries.
|
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:
|
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 mode only (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)
|
- ~~64 bit, Release and Debug mode (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 mode only (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)
|
- ~~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.
|
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::Polygon;
|
||||||
use Slic3r::Polyline;
|
use Slic3r::Polyline;
|
||||||
use Slic3r::Print::Object;
|
use Slic3r::Print::Object;
|
||||||
use Slic3r::Print::Simple;
|
|
||||||
use Slic3r::Surface;
|
use Slic3r::Surface;
|
||||||
our $build = eval "use Slic3r::Build; 1";
|
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 {
|
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 $model = Slic3r::Model->new;
|
||||||
my $object = $model->add_object(input_file => $input_file);
|
|
||||||
$model->set_material($model_name);
|
for my $model_name (@$model_names) {
|
||||||
$object->add_volume(mesh => $mesh, material_id => $model_name);
|
my $input_file = "${model_name}.stl";
|
||||||
$object->add_instance(
|
my $mesh = mesh($model_name, %params);
|
||||||
offset => Slic3r::Pointf->new(0,0),
|
# $mesh->write_ascii("out/$input_file");
|
||||||
# 3D full transform
|
|
||||||
rotation => Slic3r::Pointf3->new(0, 0, $params{rotation} // 0),
|
my $object = $model->add_object(input_file => $input_file);
|
||||||
scaling_factor => Slic3r::Pointf3->new($params{scale} // 1, $params{scale} // 1, $params{scale} // 1),
|
$model->set_material($model_name);
|
||||||
# old transform
|
$object->add_volume(mesh => $mesh, material_id => $model_name);
|
||||||
# rotation => $params{rotation} // 0,
|
$object->add_instance(
|
||||||
# scaling_factor => $params{scale} // 1,
|
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;
|
return $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub init_print {
|
sub init_print {
|
||||||
my ($models, %params) = @_;
|
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;
|
my $config = Slic3r::Config->new;
|
||||||
$config->apply($params{config}) if $params{config};
|
$config->apply($params{config}) if $params{config};
|
||||||
$config->set('gcode_comments', 1) if $ENV{SLIC3R_TESTS_GCODE};
|
$config->set('gcode_comments', 1) if $ENV{SLIC3R_TESTS_GCODE};
|
||||||
|
|
||||||
my $print = Slic3r::Print->new;
|
my $print = Slic3r::Print->new;
|
||||||
$print->apply_config_perl_tests_only($config);
|
die "Unknown model in test" if !defined $model;
|
||||||
|
if (defined $params{duplicate} && $params{duplicate} > 1) {
|
||||||
$models = [$models] if ref($models) ne 'ARRAY';
|
$model->duplicate($params{duplicate} // 1, $config->min_object_distance);
|
||||||
$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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
# Call apply_config_perl_tests_only one more time, so that the layer height profiles are updated over all PrintObjects.
|
$model->arrange_objects($config->min_object_distance);
|
||||||
$print->apply_config_perl_tests_only($config);
|
$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;
|
$print->validate;
|
||||||
|
|
||||||
# We return a proxy object in order to keep $models alive as required by the Print API.
|
# We return a proxy object in order to keep $models alive as required by the Print API.
|
||||||
return Slic3r::Test::Print->new(
|
return Slic3r::Test::Print->new(
|
||||||
print => $print,
|
print => $print,
|
||||||
models => $models,
|
model => $model,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +256,7 @@ sub add_facet {
|
||||||
package Slic3r::Test::Print;
|
package Slic3r::Test::Print;
|
||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
has 'print' => (is => 'ro', required => 1, handles => [qw(process apply_config_perl_tests_only)]);
|
has 'print' => (is => 'ro', required => 1, handles => [qw(process apply)]);
|
||||||
has 'models' => (is => 'ro', required => 1);
|
has 'model' => (is => 'ro', required => 1);
|
||||||
|
|
||||||
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
|
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 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-rc2 Updated firmware versions for MK2.5/S and MK3/S
|
||||||
0.8.0-rc1 Updated SLA profiles
|
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-alpha3 Update of SLA profiles
|
||||||
0.4.0-alpha2 First SLA profiles
|
0.4.0-alpha2 First SLA profiles
|
||||||
min_slic3r_version = 1.41.3-alpha
|
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.6 Updated firmware versions for MK2.5/S and MK3/S
|
||||||
0.4.5 Enabled remaining time support for MK2/S/MMU1
|
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
|
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.1 New MK2.5S and MK3S FW versions
|
||||||
0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||||
min_slic3r_version = 1.41.1
|
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.6 Updated firmware versions for MK2.5 and MK3
|
||||||
0.3.5 New MK2.5 and MK3 FW versions
|
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
|
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-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
|
0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters
|
||||||
min_slic3r_version = 1.40.0
|
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.14 Updated firmware versions for MK2.5 and MK3
|
||||||
0.1.13 New MK2.5 and MK3 FW versions
|
0.1.13 New MK2.5 and MK3 FW versions
|
||||||
0.1.12 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 sampler2D texture;
|
||||||
uniform bool transparent_background;
|
uniform bool transparent_background;
|
||||||
|
uniform bool svg_source;
|
||||||
|
|
||||||
varying vec2 tex_coords;
|
varying vec2 tex_coords;
|
||||||
|
|
||||||
void main()
|
vec4 svg_color()
|
||||||
{
|
{
|
||||||
|
// takes foreground from texture
|
||||||
|
vec4 fore_color = texture2D(texture, tex_coords);
|
||||||
|
|
||||||
// calculates radial gradient
|
// 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)))));
|
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
|
// 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
|
#define INTENSITY_AMBIENT 0.3
|
||||||
|
|
||||||
uniform mat4 volume_world_matrix;
|
uniform mat4 volume_world_matrix;
|
||||||
|
uniform float object_max_z;
|
||||||
|
|
||||||
// x = tainted, y = specular;
|
// x = tainted, y = specular;
|
||||||
varying vec2 intensity;
|
varying vec2 intensity;
|
||||||
|
@ -42,6 +43,12 @@ void main()
|
||||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||||
|
|
||||||
// Scaled to widths of the Z texture.
|
// 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();
|
gl_Position = ftransform();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
add_subdirectory(slabasebed)
|
add_subdirectory(slabasebed)
|
||||||
|
add_subdirectory(slasupporttree)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <libslic3r/libslic3r.h>
|
#include <libslic3r/libslic3r.h>
|
||||||
#include <libslic3r/TriangleMesh.hpp>
|
#include <libslic3r/TriangleMesh.hpp>
|
||||||
#include <libslic3r/Tesselate.hpp>
|
#include <libslic3r/Tesselate.hpp>
|
||||||
|
#include <libslic3r/ClipperUtils.hpp>
|
||||||
#include <libslic3r/SLA/SLABasePool.hpp>
|
#include <libslic3r/SLA/SLABasePool.hpp>
|
||||||
#include <libslic3r/SLA/SLABoilerPlate.hpp>
|
#include <libslic3r/SLA/SLABoilerPlate.hpp>
|
||||||
#include <libnest2d/tools/benchmark.h>
|
#include <libnest2d/tools/benchmark.h>
|
||||||
|
@ -15,7 +16,8 @@ const std::string USAGE_STR = {
|
||||||
|
|
||||||
namespace Slic3r { namespace sla {
|
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());
|
const PoolConfig& cfg = PoolConfig());
|
||||||
|
|
||||||
Contour3D walls(const Polygon& floor_plate, const Polygon& ceiling,
|
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();
|
model.align_to_origin();
|
||||||
|
|
||||||
ExPolygons ground_slice;
|
ExPolygons ground_slice;
|
||||||
sla::Contour3D mesh;
|
|
||||||
// TriangleMesh basepool;
|
|
||||||
|
|
||||||
sla::base_plate(model, ground_slice, 0.1f);
|
sla::base_plate(model, ground_slice, 0.1f);
|
||||||
|
|
||||||
if(ground_slice.empty()) return EXIT_FAILURE;
|
if(ground_slice.empty()) return EXIT_FAILURE;
|
||||||
|
|
||||||
// ExPolygon bottom_plate = ground_slice.front();
|
ground_slice = offset_ex(ground_slice, 0.5);
|
||||||
// ExPolygon top_plate = bottom_plate;
|
ExPolygon gndfirst; gndfirst = ground_slice.front();
|
||||||
// sla::offset(top_plate, coord_t(3.0/SCALING_FACTOR));
|
sla::breakstick_holes(gndfirst, 0.5, 10, 0.3);
|
||||||
// sla::offset(bottom_plate, coord_t(1.0/SCALING_FACTOR));
|
|
||||||
|
sla::Contour3D mesh;
|
||||||
|
|
||||||
bench.start();
|
bench.start();
|
||||||
|
|
||||||
// TriangleMesh pool;
|
|
||||||
sla::PoolConfig cfg;
|
sla::PoolConfig cfg;
|
||||||
cfg.min_wall_height_mm = 0;
|
cfg.min_wall_height_mm = 0;
|
||||||
cfg.edge_radius_mm = 0.2;
|
cfg.edge_radius_mm = 0;
|
||||||
mesh = sla::create_base_pool(ground_slice, cfg);
|
mesh = sla::create_base_pool(to_polygons(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, [](){});
|
|
||||||
|
|
||||||
bench.stop();
|
bench.stop();
|
||||||
|
|
||||||
cout << "Base pool creation time: " << std::setprecision(10)
|
cout << "Base pool creation time: " << std::setprecision(10)
|
||||||
<< bench.getElapsedSec() << " seconds." << endl;
|
<< bench.getElapsedSec() << " seconds." << endl;
|
||||||
|
|
||||||
// auto point = []()
|
|
||||||
for(auto& trind : mesh.indices) {
|
for(auto& trind : mesh.indices) {
|
||||||
Vec3d p0 = mesh.points[size_t(trind[0])];
|
Vec3d p0 = mesh.points[size_t(trind[0])];
|
||||||
Vec3d p1 = mesh.points[size_t(trind[1])];
|
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;
|
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);
|
std::fstream outstream("out.obj", std::fstream::out);
|
||||||
mesh.to_obj(outstream);
|
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)
|
project(PrusaSlicer-native)
|
||||||
|
|
||||||
|
add_subdirectory(build-utils)
|
||||||
add_subdirectory(admesh)
|
add_subdirectory(admesh)
|
||||||
add_subdirectory(avrdude)
|
add_subdirectory(avrdude)
|
||||||
# boost/nowide
|
# boost/nowide
|
||||||
|
@ -12,14 +13,12 @@ add_subdirectory(poly2tri)
|
||||||
add_subdirectory(qhull)
|
add_subdirectory(qhull)
|
||||||
add_subdirectory(Shiny)
|
add_subdirectory(Shiny)
|
||||||
add_subdirectory(semver)
|
add_subdirectory(semver)
|
||||||
|
add_subdirectory(libigl)
|
||||||
|
|
||||||
# Adding libnest2d project for bin packing...
|
# Adding libnest2d project for bin packing...
|
||||||
set(LIBNEST2D_UNITTESTS ON CACHE BOOL "Force generating unittests for libnest2d")
|
set(LIBNEST2D_UNITTESTS ON CACHE BOOL "Force generating unittests for libnest2d")
|
||||||
add_subdirectory(libnest2d)
|
add_subdirectory(libnest2d)
|
||||||
|
|
||||||
include_directories(${LIBDIR}/qhull/src)
|
|
||||||
#message(STATUS ${LIBDIR}/qhull/src)
|
|
||||||
|
|
||||||
add_subdirectory(libslic3r)
|
add_subdirectory(libslic3r)
|
||||||
|
|
||||||
if (SLIC3R_GUI)
|
if (SLIC3R_GUI)
|
||||||
|
@ -49,7 +48,7 @@ if (SLIC3R_GUI)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
else ()
|
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 ()
|
endif ()
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
|
@ -58,6 +57,9 @@ if (SLIC3R_GUI)
|
||||||
|
|
||||||
include(${wxWidgets_USE_FILE})
|
include(${wxWidgets_USE_FILE})
|
||||||
|
|
||||||
|
# list(REMOVE_ITEM wxWidgets_LIBRARIES oleacc)
|
||||||
|
message(STATUS "wx libs: ${wxWidgets_LIBRARIES}")
|
||||||
|
|
||||||
add_subdirectory(slic3r)
|
add_subdirectory(slic3r)
|
||||||
endif()
|
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.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/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)
|
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)
|
add_library(PrusaSlicer SHARED PrusaSlicer.cpp PrusaSlicer.hpp)
|
||||||
else ()
|
else ()
|
||||||
add_executable(PrusaSlicer PrusaSlicer.cpp PrusaSlicer.hpp)
|
add_executable(PrusaSlicer PrusaSlicer.cpp PrusaSlicer.hpp)
|
||||||
endif ()
|
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)
|
# Binary name on unix like systems (OSX, Linux)
|
||||||
set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer")
|
set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
target_link_libraries(PrusaSlicer libslic3r)
|
target_link_libraries(PrusaSlicer libslic3r cereal)
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# add_compile_options(-stdlib=libc++)
|
# add_compile_options(-stdlib=libc++)
|
||||||
# add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE)
|
# 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.
|
# Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries.
|
||||||
if (SLIC3R_GUI)
|
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
|
# Configure libcurl and its dependencies OpenSSL & zlib
|
||||||
find_package(CURL REQUIRED)
|
find_package(CURL REQUIRED)
|
||||||
if (NOT MSVC)
|
if (NOT WIN32)
|
||||||
# Required by libcurl
|
# Required by libcurl
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
@ -125,7 +134,7 @@ if (SLIC3R_GUI)
|
||||||
target_link_options(PrusaSlicer PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
target_link_options(PrusaSlicer PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||||
target_link_libraries(PrusaSlicer user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib)
|
target_link_libraries(PrusaSlicer user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib)
|
||||||
elseif (MINGW)
|
elseif (MINGW)
|
||||||
target_link_libraries(PrusaSlicer -lopengl32)
|
target_link_libraries(PrusaSlicer opengl32 ws2_32 uxtheme setupapi)
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
target_link_libraries(PrusaSlicer "-framework OpenGL")
|
target_link_libraries(PrusaSlicer "-framework OpenGL")
|
||||||
else ()
|
else ()
|
||||||
|
@ -135,26 +144,34 @@ endif ()
|
||||||
|
|
||||||
# On Windows, a shim application is required to produce a console / non console version of the Slic3r application.
|
# 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.
|
# 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)
|
add_executable(PrusaSlicer_app_gui WIN32 PrusaSlicer_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.rc)
|
||||||
# Generate debug symbols even in release mode.
|
# 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)
|
target_compile_definitions(PrusaSlicer_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE)
|
||||||
add_dependencies(PrusaSlicer_app_gui PrusaSlicer)
|
add_dependencies(PrusaSlicer_app_gui PrusaSlicer)
|
||||||
set_target_properties(PrusaSlicer_app_gui PROPERTIES OUTPUT_NAME "prusa-slicer")
|
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)
|
add_executable(PrusaSlicer_app_console PrusaSlicer_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/PrusaSlicer.rc)
|
||||||
# Generate debug symbols even in release mode.
|
# Generate debug symbols even in release mode.
|
||||||
|
if (MSVC)
|
||||||
target_link_options(PrusaSlicer_app_console PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
target_link_options(PrusaSlicer_app_console PUBLIC "$<$<CONFIG:RELEASE>:/DEBUG>")
|
||||||
|
endif ()
|
||||||
target_compile_definitions(PrusaSlicer_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE)
|
target_compile_definitions(PrusaSlicer_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE)
|
||||||
add_dependencies(PrusaSlicer_app_console PrusaSlicer)
|
add_dependencies(PrusaSlicer_app_console PrusaSlicer)
|
||||||
set_target_properties(PrusaSlicer_app_console PROPERTIES OUTPUT_NAME "prusa-slicer-console")
|
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 ()
|
endif ()
|
||||||
|
|
||||||
# Link the resources dir to where Slic3r GUI expects it
|
# Link the resources dir to where Slic3r GUI expects it
|
||||||
if (MSVC)
|
if (WIN32)
|
||||||
if (CMAKE_CONFIGURATION_TYPES)
|
if (CMAKE_CONFIGURATION_TYPES)
|
||||||
foreach (CONF ${CMAKE_CONFIGURATION_TYPES})
|
foreach (CONF ${CMAKE_CONFIGURATION_TYPES})
|
||||||
file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}" WIN_CONF_OUTPUT_DIR)
|
file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}" WIN_CONF_OUTPUT_DIR)
|
||||||
|
|
|
@ -7,10 +7,13 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
// Let the NVIDIA and AMD know we want to use their graphics card
|
// Let the NVIDIA and AMD know we want to use their graphics card
|
||||||
// on a dual graphics card system.
|
// on a dual graphics card system.
|
||||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
|
}
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
@ -23,6 +26,7 @@
|
||||||
#include <boost/nowide/args.hpp>
|
#include <boost/nowide/args.hpp>
|
||||||
#include <boost/nowide/cenv.hpp>
|
#include <boost/nowide/cenv.hpp>
|
||||||
#include <boost/nowide/iostream.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
|
#include "unix/fhs.hpp" // Generated by CMake from ../platform/unix/fhs.hpp.in
|
||||||
|
|
||||||
|
@ -44,18 +48,39 @@
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
|
#include "slic3r/GUI/3DScene.hpp"
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
|
|
||||||
PrinterTechnology get_printer_technology(const DynamicConfig &config)
|
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;
|
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))
|
if (! this->setup(argc, argv))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -64,14 +89,14 @@ int CLI::run(int argc, char **argv)
|
||||||
|
|
||||||
bool start_gui = m_actions.empty() &&
|
bool start_gui = m_actions.empty() &&
|
||||||
// cutting transformations are setting an "export" action.
|
// 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") == 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_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_y") == m_transforms.end();
|
||||||
PrinterTechnology printer_technology = get_printer_technology(m_extra_config);
|
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
|
// load config files supplied via --load
|
||||||
for (auto const &file : load_configs) {
|
for (auto const &file : load_configs) {
|
||||||
if (! boost::filesystem::exists(file)) {
|
if (! boost::filesystem::exists(file)) {
|
||||||
if (m_config.opt_bool("ignore_nonexistent_config")) {
|
if (m_config.opt_bool("ignore_nonexistent_config")) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -91,13 +116,13 @@ int CLI::run(int argc, char **argv)
|
||||||
PrinterTechnology other_printer_technology = get_printer_technology(config);
|
PrinterTechnology other_printer_technology = get_printer_technology(config);
|
||||||
if (printer_technology == ptUnknown) {
|
if (printer_technology == ptUnknown) {
|
||||||
printer_technology = other_printer_technology;
|
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;
|
boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
m_print_config.apply(config);
|
m_print_config.apply(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read input file(s) if any.
|
// Read input file(s) if any.
|
||||||
for (const std::string &file : m_input_files) {
|
for (const std::string &file : m_input_files) {
|
||||||
if (! boost::filesystem::exists(file)) {
|
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);
|
PrinterTechnology other_printer_technology = get_printer_technology(m_print_config);
|
||||||
if (printer_technology == ptUnknown) {
|
if (printer_technology == ptUnknown) {
|
||||||
printer_technology = other_printer_technology;
|
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;
|
boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -133,21 +158,21 @@ int CLI::run(int argc, char **argv)
|
||||||
m_print_config.normalize();
|
m_print_config.normalize();
|
||||||
|
|
||||||
if (printer_technology == ptUnknown)
|
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.
|
// Initialize full print configs for both the FFF and SLA technologies.
|
||||||
FullPrintConfig fff_print_config;
|
FullPrintConfig fff_print_config;
|
||||||
// SLAFullPrintConfig sla_print_config;
|
// SLAFullPrintConfig sla_print_config;
|
||||||
fff_print_config.apply(m_print_config, true);
|
fff_print_config.apply(m_print_config, true);
|
||||||
// sla_print_config.apply(m_print_config, true);
|
// sla_print_config.apply(m_print_config, true);
|
||||||
|
|
||||||
// Loop through transform options.
|
// Loop through transform options.
|
||||||
for (auto const &opt_key : m_transforms) {
|
for (auto const &opt_key : m_transforms) {
|
||||||
if (opt_key == "merge") {
|
if (opt_key == "merge") {
|
||||||
Model m;
|
Model m;
|
||||||
for (auto &model : m_models)
|
for (auto &model : m_models)
|
||||||
for (ModelObject *o : model.objects)
|
for (ModelObject *o : model.objects)
|
||||||
m.add_object(*o);
|
m.add_object(*o);
|
||||||
// Rearrange instances unless --dont-arrange is supplied
|
// Rearrange instances unless --dont-arrange is supplied
|
||||||
if (! m_config.opt_bool("dont_arrange")) {
|
if (! m_config.opt_bool("dont_arrange")) {
|
||||||
m.add_default_instances();
|
m.add_default_instances();
|
||||||
|
@ -159,8 +184,8 @@ int CLI::run(int argc, char **argv)
|
||||||
this->has_print_action() ? &bb : nullptr
|
this->has_print_action() ? &bb : nullptr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
m_models.clear();
|
m_models.clear();
|
||||||
m_models.emplace_back(std::move(m));
|
m_models.emplace_back(std::move(m));
|
||||||
} else if (opt_key == "duplicate") {
|
} else if (opt_key == "duplicate") {
|
||||||
const BoundingBoxf &bb = fff_print_config.bed_shape.values;
|
const BoundingBoxf &bb = fff_print_config.bed_shape.values;
|
||||||
for (auto &model : m_models) {
|
for (auto &model : m_models) {
|
||||||
|
@ -189,11 +214,11 @@ int CLI::run(int argc, char **argv)
|
||||||
// this affects instances:
|
// this affects instances:
|
||||||
model.center_instances_around_point(m_config.option<ConfigOptionPoint>("center")->value);
|
model.center_instances_around_point(m_config.option<ConfigOptionPoint>("center")->value);
|
||||||
// this affects volumes:
|
// 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();
|
//model.align_to_ground();
|
||||||
BoundingBoxf3 bbox;
|
BoundingBoxf3 bbox;
|
||||||
for (ModelObject *model_object : model.objects)
|
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));
|
bbox.merge(model_object->instance_bounding_box(0, false));
|
||||||
for (ModelObject *model_object : model.objects)
|
for (ModelObject *model_object : model.objects)
|
||||||
for (ModelInstance *model_instance : model_object->instances)
|
for (ModelInstance *model_instance : model_object->instances)
|
||||||
|
@ -204,7 +229,7 @@ int CLI::run(int argc, char **argv)
|
||||||
for (auto &model : m_models) {
|
for (auto &model : m_models) {
|
||||||
BoundingBoxf3 bb = model.bounding_box();
|
BoundingBoxf3 bb = model.bounding_box();
|
||||||
// this affects volumes:
|
// 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") {
|
} else if (opt_key == "dont_arrange") {
|
||||||
// do nothing - this option alters other transform options
|
// 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") {
|
} else if (opt_key == "cut" || opt_key == "cut_x" || opt_key == "cut_y") {
|
||||||
std::vector<Model> new_models;
|
std::vector<Model> new_models;
|
||||||
for (auto &model : m_models) {
|
for (auto &model : m_models) {
|
||||||
model.repair();
|
model.translate(0, 0, -model.bounding_box().min.z()); // align to z = 0
|
||||||
model.translate(0, 0, -model.bounding_box().min.z()); // align to z = 0
|
size_t num_objects = model.objects.size();
|
||||||
size_t num_objects = model.objects.size();
|
for (size_t i = 0; i < num_objects; ++ i) {
|
||||||
for (size_t i = 0; i < num_objects; ++ i) {
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (opt_key == "cut_x") {
|
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);
|
o->cut(Z, m_config.opt_float("cut"), &out);
|
||||||
}
|
}
|
||||||
#else
|
#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
|
#endif
|
||||||
model.delete_object(size_t(0));
|
model.delete_object(size_t(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: copy less stuff around using pointers
|
// TODO: copy less stuff around using pointers
|
||||||
m_models = new_models;
|
m_models = new_models;
|
||||||
|
|
||||||
if (m_actions.empty())
|
if (m_actions.empty())
|
||||||
m_actions.push_back("export_stl");
|
m_actions.push_back("export_stl");
|
||||||
}
|
}
|
||||||
|
@ -273,7 +297,7 @@ int CLI::run(int argc, char **argv)
|
||||||
for (auto &model : m_models) {
|
for (auto &model : m_models) {
|
||||||
TriangleMesh mesh = model.mesh();
|
TriangleMesh mesh = model.mesh();
|
||||||
mesh.repair();
|
mesh.repair();
|
||||||
|
|
||||||
TriangleMeshPtrs meshes = mesh.cut_by_grid(m_config.option<ConfigOptionPoint>("cut_grid")->value);
|
TriangleMeshPtrs meshes = mesh.cut_by_grid(m_config.option<ConfigOptionPoint>("cut_grid")->value);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (TriangleMesh* m : meshes) {
|
for (TriangleMesh* m : meshes) {
|
||||||
|
@ -284,10 +308,10 @@ int CLI::run(int argc, char **argv)
|
||||||
delete m;
|
delete m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: copy less stuff around using pointers
|
// TODO: copy less stuff around using pointers
|
||||||
m_models = new_models;
|
m_models = new_models;
|
||||||
|
|
||||||
if (m_actions.empty())
|
if (m_actions.empty())
|
||||||
m_actions.push_back("export_stl");
|
m_actions.push_back("export_stl");
|
||||||
}
|
}
|
||||||
|
@ -301,14 +325,15 @@ int CLI::run(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (opt_key == "repair") {
|
} else if (opt_key == "repair") {
|
||||||
for (auto &model : m_models)
|
// Models are repaired by default.
|
||||||
model.repair();
|
//for (auto &model : m_models)
|
||||||
|
// model.repair();
|
||||||
} else {
|
} else {
|
||||||
boost::nowide::cerr << "error: option not implemented yet: " << opt_key << std::endl;
|
boost::nowide::cerr << "error: option not implemented yet: " << opt_key << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through action options
|
// loop through action options
|
||||||
for (auto const &opt_key : m_actions) {
|
for (auto const &opt_key : m_actions) {
|
||||||
if (opt_key == "help") {
|
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;
|
boost::nowide::cerr << "error: cannot export SLA slices for a SLA configuration" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// Make a copy of the model if the current action is not the last action, as the model may be
|
// 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.
|
// modified by the centering and such.
|
||||||
Model model_copy;
|
Model model_copy;
|
||||||
bool make_copy = &opt_key != &m_actions.back();
|
bool make_copy = &opt_key != &m_actions.back();
|
||||||
for (Model &model_in : m_models) {
|
for (Model &model_in : m_models) {
|
||||||
if (make_copy)
|
if (make_copy)
|
||||||
model_copy = model_in;
|
model_copy = model_in;
|
||||||
Model &model = 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
|
// If all objects have defined instances, their relative positions will be
|
||||||
// honored when printing (they will be only centered, unless --dont-arrange
|
// 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
|
// 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")) {
|
if (! m_config.opt_bool("dont_arrange")) {
|
||||||
//FIXME make the min_object_distance configurable.
|
//FIXME make the min_object_distance configurable.
|
||||||
model.arrange_objects(fff_print.config().min_object_distance());
|
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) {
|
if (printer_technology == ptFFF) {
|
||||||
for (auto* mo : model.objects)
|
for (auto* mo : model.objects)
|
||||||
|
@ -392,40 +417,40 @@ int CLI::run(int argc, char **argv)
|
||||||
}
|
}
|
||||||
if (print->empty())
|
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;
|
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 {
|
try {
|
||||||
std::string outfile_final;
|
std::string outfile_final;
|
||||||
print->process();
|
print->process();
|
||||||
if (printer_technology == ptFFF) {
|
if (printer_technology == ptFFF) {
|
||||||
// The outfile is processed by a PlaceholderParser.
|
// The outfile is processed by a PlaceholderParser.
|
||||||
outfile = fff_print.export_gcode(outfile, nullptr);
|
outfile = fff_print.export_gcode(outfile, nullptr);
|
||||||
outfile_final = fff_print.print_statistics().finalize_output_path(outfile);
|
outfile_final = fff_print.print_statistics().finalize_output_path(outfile);
|
||||||
} else {
|
} 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
|
// 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);
|
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) {
|
if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final)) {
|
||||||
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
|
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
boost::nowide::cout << "Slicing result exported to " << outfile << std::endl;
|
boost::nowide::cout << "Slicing result exported to " << outfile << std::endl;
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
boost::nowide::cerr << ex.what() << std::endl;
|
boost::nowide::cerr << ex.what() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
print.center = ! m_config.has("center")
|
print.center = ! m_config.has("center")
|
||||||
&& ! m_config.has("align_xy")
|
&& ! m_config.has("align_xy")
|
||||||
&& ! m_config.opt_bool("dont_arrange");
|
&& ! m_config.opt_bool("dont_arrange");
|
||||||
print.set_model(model);
|
print.set_model(model);
|
||||||
|
|
||||||
// start chronometer
|
// start chronometer
|
||||||
typedef std::chrono::high_resolution_clock clock_;
|
typedef std::chrono::high_resolution_clock clock_;
|
||||||
typedef std::chrono::duration<double, std::ratio<1> > second_;
|
typedef std::chrono::duration<double, std::ratio<1> > second_;
|
||||||
std::chrono::time_point<clock_> t0{ clock_::now() };
|
std::chrono::time_point<clock_> t0{ clock_::now() };
|
||||||
|
|
||||||
const std::string outfile = this->output_filepath(model, IO::Gcode);
|
const std::string outfile = this->output_filepath(model, IO::Gcode);
|
||||||
try {
|
try {
|
||||||
print.export_gcode(outfile);
|
print.export_gcode(outfile);
|
||||||
|
@ -434,7 +459,7 @@ int CLI::run(int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
boost::nowide::cout << "G-code exported to " << outfile << std::endl;
|
boost::nowide::cout << "G-code exported to " << outfile << std::endl;
|
||||||
|
|
||||||
// output some statistics
|
// output some statistics
|
||||||
double duration { std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
|
double duration { std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
|
||||||
boost::nowide::cout << std::fixed << std::setprecision(0)
|
boost::nowide::cout << std::fixed << std::setprecision(0)
|
||||||
|
@ -451,51 +476,55 @@ int CLI::run(int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start_gui) {
|
if (start_gui) {
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
// #ifdef USE_WX
|
// #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->autosave = m_config.opt_string("autosave");
|
||||||
GUI::GUI_App::SetInstance(gui);
|
GUI::GUI_App::SetInstance(gui);
|
||||||
gui->CallAfter([gui, this, &load_configs] {
|
gui->CallAfter([gui, this, &load_configs] {
|
||||||
if (!gui->initialized()) {
|
if (!gui->initialized()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
// Load the cummulative config over the currently active profiles.
|
// Load the cummulative config over the currently active profiles.
|
||||||
//FIXME if multiple configs are loaded, only the last one will have an effect.
|
//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).
|
// 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.
|
// As of now only the full configs are supported here.
|
||||||
if (!m_print_config.empty())
|
if (!m_print_config.empty())
|
||||||
gui->mainframe->load_config(m_print_config);
|
gui->mainframe->load_config(m_print_config);
|
||||||
#endif
|
#endif
|
||||||
if (! load_configs.empty())
|
if (! load_configs.empty())
|
||||||
// Load the last config to give it a name at the UI. The name of the preset may be later
|
// 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.
|
// 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.
|
//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());
|
gui->mainframe->load_config_file(load_configs.back());
|
||||||
// If loading a 3MF file, the config is loaded from the last one.
|
// If loading a 3MF file, the config is loaded from the last one.
|
||||||
if (! m_input_files.empty())
|
if (! m_input_files.empty())
|
||||||
gui->plater()->load_files(m_input_files, true, true);
|
gui->plater()->load_files(m_input_files, true, true);
|
||||||
if (! m_extra_config.empty())
|
if (! m_extra_config.empty())
|
||||||
gui->mainframe->load_config(m_extra_config);
|
gui->mainframe->load_config(m_extra_config);
|
||||||
});
|
});
|
||||||
return wxEntry(argc, argv);
|
int result = wxEntry(argc, argv);
|
||||||
|
//FIXME this is a workaround for the PrusaSlicer 2.1 release.
|
||||||
|
_3DScene::destroy();
|
||||||
|
return result;
|
||||||
#else /* SLIC3R_GUI */
|
#else /* SLIC3R_GUI */
|
||||||
// No GUI support. Just print out a help.
|
// No GUI support. Just print out a help.
|
||||||
this->print_help(false);
|
this->print_help(false);
|
||||||
// If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
|
// If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
|
||||||
return (argc == 0) ? 0 : 1;
|
return (argc == 0) ? 0 : 1;
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CLI::setup(int argc, char **argv)
|
bool CLI::setup(int argc, char **argv)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
Slic3r::set_logging_level(1);
|
||||||
const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL");
|
const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL");
|
||||||
if (loglevel != nullptr) {
|
if (loglevel != nullptr) {
|
||||||
if (loglevel[0] >= '0' && loglevel[0] <= '9' && loglevel[1] == 0)
|
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.
|
// If any option is unsupported, print usage and abort immediately.
|
||||||
t_config_option_keys opt_order;
|
t_config_option_keys opt_order;
|
||||||
if (! m_config.read_cli(argc, argv, &m_input_files, &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.
|
// Separate error message reported by the CLI parser from the help.
|
||||||
boost::nowide::cerr << std::endl;
|
boost::nowide::cerr << std::endl;
|
||||||
this->print_help();
|
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");
|
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)
|
for (const std::pair<t_config_option_key, ConfigOptionDef> &optdef : *options)
|
||||||
m_config.optptr(optdef.first, true);
|
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
|
boost::nowide::cout
|
||||||
<< SLIC3R_BUILD_ID << " " << "based on Slic3r"
|
<< SLIC3R_BUILD_ID << " " << "based on Slic3r"
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
<< " (with GUI support)"
|
<< " (with GUI support)"
|
||||||
#else /* SLIC3R_GUI */
|
#else /* SLIC3R_GUI */
|
||||||
|
@ -576,24 +605,24 @@ void CLI::print_help(bool include_print_options, PrinterTechnology printer_techn
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< "https://github.com/prusa3d/PrusaSlicer" << std::endl << 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
|
<< std::endl
|
||||||
<< "Actions:" << std::endl;
|
<< "Actions:" << std::endl;
|
||||||
cli_actions_config_def.print_cli_help(boost::nowide::cout, false);
|
cli_actions_config_def.print_cli_help(boost::nowide::cout, false);
|
||||||
|
|
||||||
boost::nowide::cout
|
boost::nowide::cout
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< "Transform options:" << std::endl;
|
<< "Transform options:" << std::endl;
|
||||||
cli_transform_config_def.print_cli_help(boost::nowide::cout, false);
|
cli_transform_config_def.print_cli_help(boost::nowide::cout, false);
|
||||||
|
|
||||||
boost::nowide::cout
|
boost::nowide::cout
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< "Other options:" << std::endl;
|
<< "Other options:" << std::endl;
|
||||||
cli_misc_config_def.print_cli_help(boost::nowide::cout, false);
|
cli_misc_config_def.print_cli_help(boost::nowide::cout, false);
|
||||||
|
|
||||||
if (include_print_options) {
|
if (include_print_options) {
|
||||||
boost::nowide::cout << std::endl;
|
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; });
|
{ return printer_technology == ptAny || def.printer_technology == ptAny || printer_technology == def.printer_technology; });
|
||||||
} else {
|
} else {
|
||||||
boost::nowide::cout
|
boost::nowide::cout
|
||||||
|
@ -610,14 +639,14 @@ bool CLI::export_models(IO::ExportFormat format)
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case IO::AMF: success = Slic3r::store_amf(path.c_str(), &model, nullptr); break;
|
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::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::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::TMF: success = Slic3r::store_3mf(path.c_str(), &model, nullptr); break;
|
||||||
default: assert(false); break;
|
default: assert(false); break;
|
||||||
}
|
}
|
||||||
if (success)
|
if (success)
|
||||||
std::cout << "File exported to " << path << std::endl;
|
std::cout << "File exported to " << path << std::endl;
|
||||||
else {
|
else {
|
||||||
std::cerr << "File export to " << path << " failed" << std::endl;
|
std::cerr << "File export to " << path << " failed" << std::endl;
|
||||||
return false;
|
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::AMF: ext = ".zip.amf"; break;
|
||||||
case IO::OBJ: ext = ".obj"; break;
|
case IO::OBJ: ext = ".obj"; break;
|
||||||
case IO::STL: ext = ".stl"; break;
|
case IO::STL: ext = ".stl"; break;
|
||||||
case IO::TMF: ext = ".3mf"; break;
|
case IO::TMF: ext = ".3mf"; break;
|
||||||
default: assert(false); break;
|
default: assert(false); break;
|
||||||
};
|
};
|
||||||
auto proposed_path = boost::filesystem::path(model.propose_export_file_name_and_path(ext));
|
auto proposed_path = boost::filesystem::path(model.propose_export_file_name_and_path(ext));
|
||||||
// use --output when available
|
// 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 (! cmdline_param.empty()) {
|
||||||
// if we were supplied a directory, use it and append our automatically generated filename
|
// if we were supplied a directory, use it and append our automatically generated filename
|
||||||
boost::filesystem::path cmdline_path(cmdline_param);
|
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();
|
return proposed_path.string();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv)
|
__declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv)
|
||||||
{
|
{
|
||||||
// Convert wchar_t arguments to UTF8.
|
// Convert wchar_t arguments to UTF8.
|
||||||
std::vector<std::string> argv_narrow;
|
std::vector<std::string> argv_narrow;
|
||||||
std::vector<char*> argv_ptrs(argc + 1, nullptr);
|
std::vector<char*> argv_ptrs(argc + 1, nullptr);
|
||||||
for (size_t i = 0; i < argc; ++ i)
|
for (size_t i = 0; i < argc; ++ i)
|
||||||
argv_narrow.emplace_back(boost::nowide::narrow(argv[i]));
|
argv_narrow.emplace_back(boost::nowide::narrow(argv[i]));
|
||||||
for (size_t i = 0; i < argc; ++ i)
|
for (size_t i = 0; i < argc; ++ i)
|
||||||
argv_ptrs[i] = const_cast<char*>(argv_narrow[i].data());
|
argv_ptrs[i] = const_cast<char*>(argv_narrow[i].data());
|
||||||
// Call the UTF8 main.
|
// Call the UTF8 main.
|
||||||
return CLI().run(argc, argv_ptrs.data());
|
return CLI().run(argc, argv_ptrs.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* _MSC_VER */
|
#else /* _MSC_VER */
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
|
|
@ -8,17 +8,20 @@
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
// Let the NVIDIA and AMD know we want to use their graphics card
|
extern "C"
|
||||||
// on a dual graphics card system.
|
{
|
||||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
// Let the NVIDIA and AMD know we want to use their graphics card
|
||||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
// on a dual graphics card system.
|
||||||
|
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||||
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
|
}
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
#include <GL/GL.h>
|
#include <GL/GL.h>
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -33,97 +36,97 @@
|
||||||
class OpenGLVersionCheck
|
class OpenGLVersionCheck
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string version;
|
std::string version;
|
||||||
std::string glsl_version;
|
std::string glsl_version;
|
||||||
std::string vendor;
|
std::string vendor;
|
||||||
std::string renderer;
|
std::string renderer;
|
||||||
|
|
||||||
HINSTANCE hOpenGL = nullptr;
|
HINSTANCE hOpenGL = nullptr;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
bool load_opengl_dll()
|
bool load_opengl_dll()
|
||||||
{
|
{
|
||||||
MSG msg = {0};
|
MSG msg = {0};
|
||||||
WNDCLASS wc = {0};
|
WNDCLASS wc = {0};
|
||||||
wc.lpfnWndProc = OpenGLVersionCheck::supports_opengl2_wndproc;
|
wc.lpfnWndProc = OpenGLVersionCheck::supports_opengl2_wndproc;
|
||||||
wc.hInstance = (HINSTANCE)GetModuleHandle(nullptr);
|
wc.hInstance = (HINSTANCE)GetModuleHandle(nullptr);
|
||||||
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
|
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
|
||||||
wc.lpszClassName = L"PrusaSlicer_opengl_version_check";
|
wc.lpszClassName = L"PrusaSlicer_opengl_version_check";
|
||||||
wc.style = CS_OWNDC;
|
wc.style = CS_OWNDC;
|
||||||
if (RegisterClass(&wc)) {
|
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);
|
HWND hwnd = CreateWindowW(wc.lpszClassName, L"PrusaSlicer_opengl_version_check", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, wc.hInstance, (LPVOID)this);
|
||||||
if (hwnd) {
|
if (hwnd) {
|
||||||
message_pump_exit = false;
|
message_pump_exit = false;
|
||||||
while (GetMessage(&msg, NULL, 0, 0 ) > 0 && ! message_pump_exit)
|
while (GetMessage(&msg, NULL, 0, 0 ) > 0 && ! message_pump_exit)
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this->success;
|
return this->success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unload_opengl_dll()
|
void unload_opengl_dll()
|
||||||
{
|
{
|
||||||
if (this->hOpenGL) {
|
if (this->hOpenGL) {
|
||||||
BOOL released = FreeLibrary(this->hOpenGL);
|
BOOL released = FreeLibrary(this->hOpenGL);
|
||||||
if (released)
|
if (released)
|
||||||
printf("System OpenGL library released\n");
|
printf("System OpenGL library released\n");
|
||||||
else
|
else
|
||||||
printf("System OpenGL library NOT released\n");
|
printf("System OpenGL library NOT released\n");
|
||||||
this->hOpenGL = nullptr;
|
this->hOpenGL = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
|
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());
|
// printf("is_version_greater_or_equal_to, version: %s\n", version.c_str());
|
||||||
std::vector<std::string> tokens;
|
std::vector<std::string> tokens;
|
||||||
boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on);
|
boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on);
|
||||||
if (tokens.empty())
|
if (tokens.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::vector<std::string> numbers;
|
std::vector<std::string> numbers;
|
||||||
boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on);
|
boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on);
|
||||||
|
|
||||||
unsigned int gl_major = 0;
|
unsigned int gl_major = 0;
|
||||||
unsigned int gl_minor = 0;
|
unsigned int gl_minor = 0;
|
||||||
if (numbers.size() > 0)
|
if (numbers.size() > 0)
|
||||||
gl_major = ::atoi(numbers[0].c_str());
|
gl_major = ::atoi(numbers[0].c_str());
|
||||||
if (numbers.size() > 1)
|
if (numbers.size() > 1)
|
||||||
gl_minor = ::atoi(numbers[1].c_str());
|
gl_minor = ::atoi(numbers[1].c_str());
|
||||||
// printf("Major: %d, minor: %d\n", gl_major, gl_minor);
|
// printf("Major: %d, minor: %d\n", gl_major, gl_minor);
|
||||||
if (gl_major < major)
|
if (gl_major < major)
|
||||||
return false;
|
return false;
|
||||||
else if (gl_major > major)
|
else if (gl_major > major)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return gl_minor >= minor;
|
return gl_minor >= minor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static bool message_pump_exit;
|
static bool message_pump_exit;
|
||||||
|
|
||||||
void check(HWND hWnd)
|
void check(HWND hWnd)
|
||||||
{
|
{
|
||||||
hOpenGL = LoadLibraryExW(L"opengl32.dll", nullptr, 0);
|
hOpenGL = LoadLibraryExW(L"opengl32.dll", nullptr, 0);
|
||||||
if (hOpenGL == nullptr) {
|
if (hOpenGL == nullptr) {
|
||||||
printf("Failed loading the system opengl32.dll\n");
|
printf("Failed loading the system opengl32.dll\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef HGLRC (WINAPI *Func_wglCreateContext)(HDC);
|
typedef HGLRC (WINAPI *Func_wglCreateContext)(HDC);
|
||||||
typedef BOOL (WINAPI *Func_wglMakeCurrent )(HDC, HGLRC);
|
typedef BOOL (WINAPI *Func_wglMakeCurrent )(HDC, HGLRC);
|
||||||
typedef BOOL (WINAPI *Func_wglDeleteContext)(HGLRC);
|
typedef BOOL (WINAPI *Func_wglDeleteContext)(HGLRC);
|
||||||
typedef GLubyte* (WINAPI *Func_glGetString )(GLenum);
|
typedef GLubyte* (WINAPI *Func_glGetString )(GLenum);
|
||||||
|
|
||||||
Func_wglCreateContext wglCreateContext = (Func_wglCreateContext)GetProcAddress(hOpenGL, "wglCreateContext");
|
Func_wglCreateContext wglCreateContext = (Func_wglCreateContext)GetProcAddress(hOpenGL, "wglCreateContext");
|
||||||
Func_wglMakeCurrent wglMakeCurrent = (Func_wglMakeCurrent) GetProcAddress(hOpenGL, "wglMakeCurrent");
|
Func_wglMakeCurrent wglMakeCurrent = (Func_wglMakeCurrent) GetProcAddress(hOpenGL, "wglMakeCurrent");
|
||||||
Func_wglDeleteContext wglDeleteContext = (Func_wglDeleteContext)GetProcAddress(hOpenGL, "wglDeleteContext");
|
Func_wglDeleteContext wglDeleteContext = (Func_wglDeleteContext)GetProcAddress(hOpenGL, "wglDeleteContext");
|
||||||
Func_glGetString glGetString = (Func_glGetString) GetProcAddress(hOpenGL, "glGetString");
|
Func_glGetString glGetString = (Func_glGetString) GetProcAddress(hOpenGL, "glGetString");
|
||||||
|
|
||||||
if (wglCreateContext == nullptr || wglMakeCurrent == nullptr || wglDeleteContext == nullptr || glGetString == nullptr) {
|
if (wglCreateContext == nullptr || wglMakeCurrent == nullptr || wglDeleteContext == nullptr || glGetString == nullptr) {
|
||||||
printf("Failed loading the system opengl32.dll: The library is invalid.\n");
|
printf("Failed loading the system opengl32.dll: The library is invalid.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR pfd =
|
PIXELFORMATDESCRIPTOR pfd =
|
||||||
{
|
{
|
||||||
|
@ -146,152 +149,155 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
HDC ourWindowHandleToDeviceContext = ::GetDC(hWnd);
|
HDC ourWindowHandleToDeviceContext = ::GetDC(hWnd);
|
||||||
// Gdi32.dll
|
// Gdi32.dll
|
||||||
int letWindowsChooseThisPixelFormat = ::ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd);
|
int letWindowsChooseThisPixelFormat = ::ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd);
|
||||||
// Gdi32.dll
|
// Gdi32.dll
|
||||||
SetPixelFormat(ourWindowHandleToDeviceContext, letWindowsChooseThisPixelFormat, &pfd);
|
SetPixelFormat(ourWindowHandleToDeviceContext, letWindowsChooseThisPixelFormat, &pfd);
|
||||||
// Opengl32.dll
|
// Opengl32.dll
|
||||||
HGLRC glcontext = wglCreateContext(ourWindowHandleToDeviceContext);
|
HGLRC glcontext = wglCreateContext(ourWindowHandleToDeviceContext);
|
||||||
wglMakeCurrent(ourWindowHandleToDeviceContext, glcontext);
|
wglMakeCurrent(ourWindowHandleToDeviceContext, glcontext);
|
||||||
// Opengl32.dll
|
// Opengl32.dll
|
||||||
const char *data = (const char*)glGetString(GL_VERSION);
|
const char *data = (const char*)glGetString(GL_VERSION);
|
||||||
if (data != nullptr)
|
if (data != nullptr)
|
||||||
this->version = data;
|
this->version = data;
|
||||||
// printf("check -version: %s\n", version.c_str());
|
// printf("check -version: %s\n", version.c_str());
|
||||||
data = (const char*)glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION
|
data = (const char*)glGetString(0x8B8C); // GL_SHADING_LANGUAGE_VERSION
|
||||||
if (data != nullptr)
|
if (data != nullptr)
|
||||||
this->glsl_version = data;
|
this->glsl_version = data;
|
||||||
data = (const char*)glGetString(GL_VENDOR);
|
data = (const char*)glGetString(GL_VENDOR);
|
||||||
if (data != nullptr)
|
if (data != nullptr)
|
||||||
this->vendor = data;
|
this->vendor = data;
|
||||||
data = (const char*)glGetString(GL_RENDERER);
|
data = (const char*)glGetString(GL_RENDERER);
|
||||||
if (data != nullptr)
|
if (data != nullptr)
|
||||||
this->renderer = data;
|
this->renderer = data;
|
||||||
// Opengl32.dll
|
// Opengl32.dll
|
||||||
wglDeleteContext(glcontext);
|
wglDeleteContext(glcontext);
|
||||||
::ReleaseDC(hWnd, ourWindowHandleToDeviceContext);
|
::ReleaseDC(hWnd, ourWindowHandleToDeviceContext);
|
||||||
this->success = true;
|
this->success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK supports_opengl2_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK supports_opengl2_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
switch(message)
|
switch(message)
|
||||||
{
|
{
|
||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
{
|
{
|
||||||
CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
|
CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
|
||||||
OpenGLVersionCheck *ogl_data = reinterpret_cast<OpenGLVersionCheck*>(pCreate->lpCreateParams);
|
OpenGLVersionCheck *ogl_data = reinterpret_cast<OpenGLVersionCheck*>(pCreate->lpCreateParams);
|
||||||
ogl_data->check(hWnd);
|
ogl_data->check(hWnd);
|
||||||
DestroyWindow(hWnd);
|
DestroyWindow(hWnd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case WM_NCDESTROY:
|
case WM_NCDESTROY:
|
||||||
message_pump_exit = true;
|
message_pump_exit = true;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool OpenGLVersionCheck::message_pump_exit = false;
|
bool OpenGLVersionCheck::message_pump_exit = false;
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv);
|
typedef int (__stdcall *Slic3rMainFunc)(int argc, wchar_t **argv);
|
||||||
Slic3rMainFunc slic3r_main = nullptr;
|
Slic3rMainFunc slic3r_main = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
#ifdef SLIC3R_WRAPPER_NOCONSOLE
|
#ifdef SLIC3R_WRAPPER_NOCONSOLE
|
||||||
int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */)
|
int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */)
|
||||||
{
|
{
|
||||||
int argc;
|
int argc;
|
||||||
wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||||
#else
|
#else
|
||||||
int wmain(int argc, wchar_t **argv)
|
int wmain(int argc, wchar_t **argv)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::vector<wchar_t*> argv_extended;
|
std::vector<wchar_t*> argv_extended;
|
||||||
argv_extended.emplace_back(argv[0]);
|
argv_extended.emplace_back(argv[0]);
|
||||||
|
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
// Here one may push some additional parameters based on the wrapper type.
|
// Here one may push some additional parameters based on the wrapper type.
|
||||||
bool force_mesa = false;
|
bool force_mesa = false;
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
for (int i = 1; i < argc; ++ i) {
|
for (int i = 1; i < argc; ++ i) {
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
if (wcscmp(argv[i], L"--sw-renderer") == 0)
|
if (wcscmp(argv[i], L"--sw-renderer") == 0)
|
||||||
force_mesa = true;
|
force_mesa = true;
|
||||||
else if (wcscmp(argv[i], L"--no-sw-renderer") == 0)
|
else if (wcscmp(argv[i], L"--no-sw-renderer") == 0)
|
||||||
force_mesa = false;
|
force_mesa = false;
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
argv_extended.emplace_back(argv[i]);
|
argv_extended.emplace_back(argv[i]);
|
||||||
}
|
}
|
||||||
argv_extended.emplace_back(nullptr);
|
argv_extended.emplace_back(nullptr);
|
||||||
|
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
OpenGLVersionCheck opengl_version_check;
|
OpenGLVersionCheck opengl_version_check;
|
||||||
bool load_mesa =
|
bool load_mesa =
|
||||||
// Forced from the command line.
|
// Forced from the command line.
|
||||||
force_mesa ||
|
force_mesa ||
|
||||||
// Running over a rempote desktop, and the RemoteFX is not enabled, therefore Windows will only provide SW OpenGL 1.1 context.
|
// 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.
|
// In that case, use Mesa.
|
||||||
::GetSystemMetrics(SM_REMOTESESSION) ||
|
::GetSystemMetrics(SM_REMOTESESSION) ||
|
||||||
// Try to load the default OpenGL driver and test its context version.
|
// 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);
|
! opengl_version_check.load_opengl_dll() || ! opengl_version_check.is_version_greater_or_equal_to(2, 0);
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
|
|
||||||
wchar_t path_to_exe[MAX_PATH + 1] = { 0 };
|
wchar_t path_to_exe[MAX_PATH + 1] = { 0 };
|
||||||
::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH);
|
::GetModuleFileNameW(nullptr, path_to_exe, MAX_PATH);
|
||||||
wchar_t drive[_MAX_DRIVE];
|
wchar_t drive[_MAX_DRIVE];
|
||||||
wchar_t dir[_MAX_DIR];
|
wchar_t dir[_MAX_DIR];
|
||||||
wchar_t fname[_MAX_FNAME];
|
wchar_t fname[_MAX_FNAME];
|
||||||
wchar_t ext[_MAX_EXT];
|
wchar_t ext[_MAX_EXT];
|
||||||
_wsplitpath(path_to_exe, drive, dir, fname, ext);
|
_wsplitpath(path_to_exe, drive, dir, fname, ext);
|
||||||
_wmakepath(path_to_exe, drive, dir, nullptr, nullptr);
|
_wmakepath(path_to_exe, drive, dir, nullptr, nullptr);
|
||||||
|
|
||||||
#ifdef SLIC3R_GUI
|
#ifdef SLIC3R_GUI
|
||||||
// https://wiki.qt.io/Cross_compiling_Mesa_for_Windows
|
// https://wiki.qt.io/Cross_compiling_Mesa_for_Windows
|
||||||
// http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/
|
// http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/
|
||||||
if (load_mesa) {
|
if (load_mesa) {
|
||||||
opengl_version_check.unload_opengl_dll();
|
opengl_version_check.unload_opengl_dll();
|
||||||
wchar_t path_to_mesa[MAX_PATH + 1] = { 0 };
|
wchar_t path_to_mesa[MAX_PATH + 1] = { 0 };
|
||||||
wcscpy(path_to_mesa, path_to_exe);
|
wcscpy(path_to_mesa, path_to_exe);
|
||||||
wcscat(path_to_mesa, L"mesa\\opengl32.dll");
|
wcscat(path_to_mesa, L"mesa\\opengl32.dll");
|
||||||
printf("Loading MESA OpenGL library: %S\n", path_to_mesa);
|
printf("Loading MESA OpenGL library: %S\n", path_to_mesa);
|
||||||
HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0);
|
HINSTANCE hInstance_OpenGL = LoadLibraryExW(path_to_mesa, nullptr, 0);
|
||||||
if (hInstance_OpenGL == nullptr) {
|
if (hInstance_OpenGL == nullptr) {
|
||||||
printf("MESA OpenGL library was not loaded\n");
|
printf("MESA OpenGL library was not loaded\n");
|
||||||
} else
|
} else
|
||||||
printf("MESA OpenGL library was loaded sucessfully\n");
|
printf("MESA OpenGL library was loaded sucessfully\n");
|
||||||
}
|
}
|
||||||
#endif /* SLIC3R_GUI */
|
#endif /* SLIC3R_GUI */
|
||||||
|
|
||||||
|
|
||||||
wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 };
|
wchar_t path_to_slic3r[MAX_PATH + 1] = { 0 };
|
||||||
wcscpy(path_to_slic3r, path_to_exe);
|
wcscpy(path_to_slic3r, path_to_exe);
|
||||||
wcscat(path_to_slic3r, L"PrusaSlicer.dll");
|
wcscat(path_to_slic3r, L"PrusaSlicer.dll");
|
||||||
// printf("Loading Slic3r library: %S\n", path_to_slic3r);
|
// printf("Loading Slic3r library: %S\n", path_to_slic3r);
|
||||||
HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0);
|
HINSTANCE hInstance_Slic3r = LoadLibraryExW(path_to_slic3r, nullptr, 0);
|
||||||
if (hInstance_Slic3r == nullptr) {
|
if (hInstance_Slic3r == nullptr) {
|
||||||
printf("PrusaSlicer.dll was not loaded\n");
|
printf("PrusaSlicer.dll was not loaded\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve function address here
|
// resolve function address here
|
||||||
slic3r_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r,
|
slic3r_main = (Slic3rMainFunc)GetProcAddress(hInstance_Slic3r,
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
// there is just a single calling conversion, therefore no mangling of the function name.
|
// there is just a single calling conversion, therefore no mangling of the function name.
|
||||||
"slic3r_main"
|
"slic3r_main"
|
||||||
#else // stdcall calling convention declaration
|
#else // stdcall calling convention declaration
|
||||||
"_slic3r_main@8"
|
"_slic3r_main@8"
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
if (slic3r_main == nullptr) {
|
if (slic3r_main == nullptr) {
|
||||||
printf("could not locate the function slic3r_main in PrusaSlicer.dll\n");
|
printf("could not locate the function slic3r_main in PrusaSlicer.dll\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// argc minus the trailing nullptr of the argv
|
// argc minus the trailing nullptr of the argv
|
||||||
return slic3r_main((int)argv_extended.size() - 1, argv_extended.data());
|
return slic3r_main((int)argv_extended.size() - 1, argv_extended.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,4 +11,4 @@ add_library(admesh STATIC
|
||||||
util.cpp
|
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 <string.h>
|
||||||
#include <math.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"
|
#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
|
int neighbor[3] = { stl->neighbors_start[facet_num].neighbor[0], stl->neighbors_start[facet_num].neighbor[1], stl->neighbors_start[facet_num].neighbor[2] };
|
||||||
stl_reverse_facet(stl_file *stl, int facet_num) {
|
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_vertex tmp_vertex;
|
|
||||||
/* int tmp_neighbor;*/
|
|
||||||
int neighbor[3];
|
|
||||||
int vnot[3];
|
|
||||||
|
|
||||||
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];
|
// fix the vnots of the neighboring facets
|
||||||
neighbor[1] = stl->neighbors_start[facet_num].neighbor[1];
|
if (neighbor[0] != -1)
|
||||||
neighbor[2] = stl->neighbors_start[facet_num].neighbor[2];
|
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;
|
||||||
vnot[0] = stl->neighbors_start[facet_num].which_vertex_not[0];
|
if (neighbor[1] != -1)
|
||||||
vnot[1] = stl->neighbors_start[facet_num].which_vertex_not[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;
|
||||||
vnot[2] = stl->neighbors_start[facet_num].which_vertex_not[2];
|
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 */
|
// swap the neighbors of the facet that is being reversed
|
||||||
tmp_vertex = stl->facet_start[facet_num].vertex[0];
|
stl->neighbors_start[facet_num].neighbor[1] = neighbor[2];
|
||||||
stl->facet_start[facet_num].vertex[0] =
|
stl->neighbors_start[facet_num].neighbor[2] = neighbor[1];
|
||||||
stl->facet_start[facet_num].vertex[1];
|
|
||||||
stl->facet_start[facet_num].vertex[1] = tmp_vertex;
|
|
||||||
|
|
||||||
/* fix the vnots of the neighboring facets */
|
// swap the vnots of the facet that is being reversed
|
||||||
if(neighbor[0] != -1)
|
stl->neighbors_start[facet_num].which_vertex_not[1] = vnot[2];
|
||||||
stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] =
|
stl->neighbors_start[facet_num].which_vertex_not[2] = vnot[1];
|
||||||
(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 neighbors of the facet that is being reversed */
|
// reverse the values of the vnots of the facet that is being reversed
|
||||||
stl->neighbors_start[facet_num].neighbor[1] = neighbor[2];
|
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].neighbor[2] = neighbor[1];
|
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;
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
// Returns true if the normal was flipped.
|
||||||
stl_fix_normal_directions(stl_file *stl) {
|
static bool check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
||||||
char *norm_sw;
|
{
|
||||||
/* int edge_num;*/
|
stl_facet *facet = &stl->facet_start[facet_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;
|
|
||||||
|
|
||||||
int* reversed_ids;
|
stl_normal normal;
|
||||||
int reversed_count = 0;
|
stl_calculate_normal(normal, facet);
|
||||||
int id;
|
stl_normalize_vector(normal);
|
||||||
int force_exit = 0;
|
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
|
stl_normal test_norm = facet->normal;
|
||||||
if (stl->stats.number_of_facets == 0) return;
|
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. */
|
test_norm *= -1.f;
|
||||||
head = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
normal_dif = (normal - test_norm).cwiseAbs();
|
||||||
if(head == NULL) perror("stl_fix_normal_directions");
|
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
||||||
tail = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
// The normal is not within tolerance and backwards.
|
||||||
if(tail == NULL) perror("stl_fix_normal_directions");
|
if (normal_fix_flag) {
|
||||||
head->next = tail;
|
facet->normal = normal;
|
||||||
tail->next = tail;
|
++ stl->stats.normals_fixed;
|
||||||
|
}
|
||||||
/* Initialize list that keeps track of already fixed facets. */
|
return true;
|
||||||
norm_sw = (char*)calloc(stl->stats.number_of_facets, sizeof(char));
|
}
|
||||||
if(norm_sw == NULL) perror("stl_fix_normal_directions");
|
if (normal_fix_flag) {
|
||||||
|
facet->normal = normal;
|
||||||
/* Initialize list that keeps track of reversed facets. */
|
++ stl->stats.normals_fixed;
|
||||||
reversed_ids = (int*)calloc(stl->stats.number_of_facets, sizeof(int));
|
}
|
||||||
if (reversed_ids == NULL) perror("stl_fix_normal_directions reversed_ids");
|
// Status is unknown.
|
||||||
|
return false;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
|
void stl_fix_normal_directions(stl_file *stl)
|
||||||
/* Returns 0 if the normal is within tolerance */
|
{
|
||||||
/* Returns 1 if the normal is not within tolerance, but direction is OK */
|
// This may happen for malformed models, see: https://github.com/prusa3d/PrusaSlicer/issues/2209
|
||||||
/* Returns 2 if the normal is not within tolerance and backwards */
|
if (stl->stats.number_of_facets == 0)
|
||||||
/* Returns 4 if the status is unknown. */
|
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;
|
// Initialize list that keeps track of already fixed facets.
|
||||||
stl_calculate_normal(normal, facet);
|
std::vector<char> norm_sw(stl->stats.number_of_facets, 0);
|
||||||
stl_normalize_vector(normal);
|
// Initialize list that keeps track of reversed facets.
|
||||||
stl_normal normal_dif = (normal - facet->normal).cwiseAbs();
|
std::vector<int> reversed_ids(stl->stats.number_of_facets, 0);
|
||||||
|
|
||||||
const float eps = 0.001f;
|
int facet_num = 0;
|
||||||
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
int reversed_count = 0;
|
||||||
/* It is not really necessary to change the values here */
|
// If normal vector is not within tolerance and backwards:
|
||||||
/* but just for consistency, I will. */
|
// Arbitrarily starts at face 0. If this one is wrong, we're screwed. Thankfully, the chances
|
||||||
facet->normal = normal;
|
// of it being wrong randomly are low if most of the triangles are right:
|
||||||
return 0;
|
if (check_normal_vector(stl, 0, 0)) {
|
||||||
}
|
reverse_facet(stl, 0);
|
||||||
|
reversed_ids[reversed_count ++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
stl_normal test_norm = facet->normal;
|
// Say that we've fixed this facet:
|
||||||
stl_normalize_vector(test_norm);
|
norm_sw[facet_num] = 1;
|
||||||
normal_dif = (normal - test_norm).cwiseAbs();
|
int checked = 1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
test_norm *= -1.f;
|
for (;;) {
|
||||||
normal_dif = (normal - test_norm).cwiseAbs();
|
// Add neighbors_to_list. Add unconnected neighbors to the list.
|
||||||
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
bool force_exit = false;
|
||||||
// Facet is backwards.
|
for (int j = 0; j < 3; ++ j) {
|
||||||
if(normal_fix_flag) {
|
// Reverse the neighboring facets if necessary.
|
||||||
facet->normal = normal;
|
if (stl->neighbors_start[facet_num].which_vertex_not[j] > 2) {
|
||||||
stl->stats.normals_fixed += 1;
|
// 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) {
|
||||||
return 2;
|
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)
|
||||||
if(normal_fix_flag) {
|
for (int id = reversed_count - 1; id >= 0; -- id)
|
||||||
facet->normal = normal;
|
reverse_facet(stl, reversed_ids[id]);
|
||||||
stl->stats.normals_fixed += 1;
|
force_exit = true;
|
||||||
}
|
break;
|
||||||
return 4;
|
}
|
||||||
|
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) {
|
void stl_fix_normal_values(stl_file *stl)
|
||||||
int i;
|
{
|
||||||
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
if (stl->error) return;
|
check_normal_vector(stl, i, 1);
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
|
||||||
stl_check_normal_vector(stl, i, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_reverse_all_facets(stl_file *stl)
|
void stl_reverse_all_facets(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
stl_normal normal;
|
||||||
return;
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
|
reverse_facet(stl, i);
|
||||||
stl_normal normal;
|
stl_calculate_normal(normal, &stl->facet_start[i]);
|
||||||
for(int i = 0; i < stl->stats.number_of_facets; i++) {
|
stl_normalize_vector(normal);
|
||||||
stl_reverse_facet(stl, i);
|
stl->facet_start[i].normal = normal;
|
||||||
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 <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
void
|
void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its)
|
||||||
stl_invalidate_shared_vertices(stl_file *stl) {
|
{
|
||||||
if (stl->error) return;
|
// 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) {
|
// A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop
|
||||||
free(stl->v_indices);
|
// while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal
|
||||||
stl->v_indices = NULL;
|
// are marked with a unique fan_traversal_stamp.
|
||||||
}
|
unsigned int fan_traversal_stamp = 0;
|
||||||
if (stl->v_shared != NULL) {
|
std::vector<unsigned int> fan_traversal_facet_visited(stl->stats.number_of_facets, 0);
|
||||||
free(stl->v_shared);
|
|
||||||
stl->v_shared = NULL;
|
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
|
bool its_write_off(const indexed_triangle_set &its, const char *file)
|
||||||
stl_generate_shared_vertices(stl_file *stl) {
|
{
|
||||||
int i;
|
/* Open the file */
|
||||||
int j;
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
int first_facet;
|
if (fp == nullptr) {
|
||||||
int direction;
|
BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing";
|
||||||
int facet_num;
|
return false;
|
||||||
int vnot;
|
}
|
||||||
int next_edge;
|
|
||||||
int pivot_vertex;
|
|
||||||
int next_facet;
|
|
||||||
int reversed;
|
|
||||||
|
|
||||||
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 */
|
bool its_write_vrml(const indexed_triangle_set &its, const char *file)
|
||||||
stl_invalidate_shared_vertices(stl);
|
{
|
||||||
|
/* 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*)
|
fprintf(fp, "#VRML V1.0 ascii\n\n");
|
||||||
calloc(stl->stats.number_of_facets, sizeof(v_indices_struct));
|
fprintf(fp, "Separator {\n");
|
||||||
if(stl->v_indices == NULL) perror("stl_generate_shared_vertices");
|
fprintf(fp, "\tDEF STLShape ShapeHints {\n");
|
||||||
stl->v_shared = (stl_vertex*)
|
fprintf(fp, "\t\tvertexOrdering COUNTERCLOCKWISE\n");
|
||||||
calloc((stl->stats.number_of_facets / 2), sizeof(stl_vertex));
|
fprintf(fp, "\t\tfaceType CONVEX\n");
|
||||||
if(stl->v_shared == NULL) perror("stl_generate_shared_vertices");
|
fprintf(fp, "\t\tshapeType SOLID\n");
|
||||||
stl->stats.shared_malloced = stl->stats.number_of_facets / 2;
|
fprintf(fp, "\t\tcreaseAngle 0.0\n");
|
||||||
stl->stats.shared_vertices = 0;
|
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++) {
|
int i = 0;
|
||||||
stl->v_indices[i].vertex[0] = -1;
|
for (; i + 1 < its.vertices.size(); ++ i)
|
||||||
stl->v_indices[i].vertex[1] = -1;
|
fprintf(fp, "\t\t\t\t%f %f %f,\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
|
||||||
stl->v_indices[i].vertex[2] = -1;
|
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++) {
|
// Check validity of the mesh, assert on error.
|
||||||
first_facet = i;
|
bool stl_validate(const stl_file *stl, const indexed_triangle_set &its)
|
||||||
for(j = 0; j < 3; j++) {
|
{
|
||||||
if(stl->v_indices[i].vertex[j] != -1) {
|
assert(! stl->facet_start.empty());
|
||||||
continue;
|
assert(stl->facet_start.size() == stl->stats.number_of_facets);
|
||||||
}
|
assert(stl->neighbors_start.size() == stl->stats.number_of_facets);
|
||||||
if(stl->stats.shared_vertices == stl->stats.shared_malloced) {
|
assert(stl->facet_start.size() == stl->neighbors_start.size());
|
||||||
stl->stats.shared_malloced += 1024;
|
assert(! stl->neighbors_start.empty());
|
||||||
stl->v_shared = (stl_vertex*)realloc(stl->v_shared,
|
assert((its.indices.empty()) == (its.vertices.empty()));
|
||||||
stl->stats.shared_malloced * sizeof(stl_vertex));
|
assert(stl->stats.number_of_facets > 0);
|
||||||
if(stl->v_shared == NULL) perror("stl_generate_shared_vertices");
|
assert(its.vertices.empty() || its.indices.size() == stl->stats.number_of_facets);
|
||||||
}
|
|
||||||
|
|
||||||
stl->v_shared[stl->stats.shared_vertices] =
|
#ifdef _DEBUG
|
||||||
stl->facet_start[i].vertex[j];
|
// Verify validity of neighborship data.
|
||||||
|
for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) {
|
||||||
direction = 0;
|
const stl_neighbors &nbr = stl->neighbors_start[facet_idx];
|
||||||
reversed = 0;
|
const int *vertices = its.indices.empty() ? nullptr : its.indices[facet_idx].data();
|
||||||
facet_num = i;
|
for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) {
|
||||||
vnot = (j + 2) % 3;
|
int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx];
|
||||||
|
assert(nbr_face < (int)stl->stats.number_of_facets);
|
||||||
for(;;) {
|
if (nbr_face != -1) {
|
||||||
if(vnot > 2) {
|
int nbr_vnot = nbr.which_vertex_not[nbr_idx];
|
||||||
if(direction == 0) {
|
assert(nbr_vnot >= 0 && nbr_vnot < 6);
|
||||||
pivot_vertex = (vnot + 2) % 3;
|
// Neighbor of the neighbor is the original face.
|
||||||
next_edge = pivot_vertex;
|
assert(stl->neighbors_start[nbr_face].neighbor[(nbr_vnot + 1) % 3] == facet_idx);
|
||||||
direction = 1;
|
int vnot_back = stl->neighbors_start[nbr_face].which_vertex_not[(nbr_vnot + 1) % 3];
|
||||||
} else {
|
assert(vnot_back >= 0 && vnot_back < 6);
|
||||||
pivot_vertex = (vnot + 1) % 3;
|
assert((nbr_vnot < 3) == (vnot_back < 3));
|
||||||
next_edge = vnot % 3;
|
assert(vnot_back % 3 == (nbr_idx + 2) % 3);
|
||||||
direction = 0;
|
if (vertices != nullptr) {
|
||||||
}
|
// Has shared vertices.
|
||||||
} else {
|
if (nbr_vnot < 3) {
|
||||||
if(direction == 0) {
|
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are correctly oriented.
|
||||||
pivot_vertex = (vnot + 1) % 3;
|
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]));
|
||||||
next_edge = vnot;
|
} else {
|
||||||
} else {
|
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are incorrectly oriented, one of them is flipped.
|
||||||
pivot_vertex = (vnot + 2) % 3;
|
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]));
|
||||||
next_edge = pivot_vertex;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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
|
// Check validity of the mesh, assert on error.
|
||||||
stl_write_off(stl_file *stl, const char *file) {
|
bool stl_validate(const stl_file *stl)
|
||||||
int i;
|
{
|
||||||
FILE *fp;
|
indexed_triangle_set its;
|
||||||
char *error_msg;
|
return stl_validate(stl, its);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
295
src/admesh/stl.h
|
@ -27,6 +27,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include <Eigen/Geometry>
|
#include <Eigen/Geometry>
|
||||||
|
|
||||||
// Size of the binary STL header, free form.
|
// 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_vertex;
|
||||||
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_normal;
|
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_vertex) == 12, "size of stl_vertex incorrect");
|
||||||
static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect");
|
static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect");
|
||||||
|
|
||||||
struct stl_facet {
|
struct stl_facet {
|
||||||
stl_normal normal;
|
stl_normal normal;
|
||||||
stl_vertex vertex[3];
|
stl_vertex vertex[3];
|
||||||
char extra[2];
|
char extra[2];
|
||||||
|
|
||||||
stl_facet rotated(const Eigen::Quaternion<float, Eigen::DontAlign> &rot) {
|
stl_facet rotated(const Eigen::Quaternion<float, Eigen::DontAlign> &rot) const {
|
||||||
stl_facet out;
|
stl_facet out;
|
||||||
out.normal = rot * this->normal;
|
out.normal = rot * this->normal;
|
||||||
out.vertex[0] = rot * this->vertex[0];
|
out.vertex[0] = rot * this->vertex[0];
|
||||||
out.vertex[1] = rot * this->vertex[1];
|
out.vertex[1] = rot * this->vertex[1];
|
||||||
out.vertex[2] = rot * this->vertex[2];
|
out.vertex[2] = rot * this->vertex[2];
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SIZEOF_STL_FACET 50
|
#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 enum {binary, ascii, inmemory} stl_type;
|
||||||
|
|
||||||
typedef struct {
|
struct stl_neighbors {
|
||||||
stl_vertex p1;
|
stl_neighbors() { reset(); }
|
||||||
stl_vertex p2;
|
void reset() {
|
||||||
int facet_number;
|
neighbor[0] = -1;
|
||||||
} stl_edge;
|
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 {
|
// Index of a neighbor facet.
|
||||||
// Key of a hash edge: sorted vertices of the edge.
|
int neighbor[3];
|
||||||
uint32_t key[6];
|
// Index of an opposite vertex at the neighbor face.
|
||||||
// Compare two keys.
|
char which_vertex_not[3];
|
||||||
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;
|
|
||||||
|
|
||||||
typedef struct {
|
struct stl_stats {
|
||||||
// Index of a neighbor facet.
|
stl_stats() { this->reset(); }
|
||||||
int neighbor[3];
|
void reset() { memset(this, 0, sizeof(stl_stats)); this->volume = -1.0; }
|
||||||
// Index of an opposite vertex at the neighbor face.
|
char header[81];
|
||||||
char which_vertex_not[3];
|
stl_type type;
|
||||||
} stl_neighbors;
|
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 {
|
struct stl_file {
|
||||||
int vertex[3];
|
stl_file() {}
|
||||||
} v_indices_struct;
|
|
||||||
|
|
||||||
typedef struct {
|
void clear() {
|
||||||
char header[81];
|
this->facet_start.clear();
|
||||||
stl_type type;
|
this->neighbors_start.clear();
|
||||||
uint32_t number_of_facets;
|
this->stats.reset();
|
||||||
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;
|
|
||||||
|
|
||||||
typedef struct {
|
size_t memsize() const {
|
||||||
FILE *fp;
|
return sizeof(*this) + sizeof(stl_facet) * facet_start.size() + sizeof(stl_neighbors) * neighbors_start.size();
|
||||||
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;
|
|
||||||
|
|
||||||
|
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);
|
struct indexed_triangle_set
|
||||||
extern void stl_close(stl_file *stl);
|
{
|
||||||
|
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_stats_out(stl_file *stl, FILE *file, char *input_file);
|
||||||
extern void stl_print_neighbors(stl_file *stl, char *file);
|
extern bool stl_print_neighbors(stl_file *stl, char *file);
|
||||||
extern void stl_put_little_int(FILE *fp, int value_in);
|
extern bool stl_write_ascii(stl_file *stl, const char *file, const char *label);
|
||||||
extern void stl_put_little_float(FILE *fp, float value_in);
|
extern bool stl_write_binary(stl_file *stl, const char *file, const char *label);
|
||||||
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 void stl_check_facets_exact(stl_file *stl);
|
extern void stl_check_facets_exact(stl_file *stl);
|
||||||
extern void stl_check_facets_nearby(stl_file *stl, float tolerance);
|
extern void stl_check_facets_nearby(stl_file *stl, float tolerance);
|
||||||
extern void stl_remove_unconnected_facets(stl_file *stl);
|
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_vertex(stl_file *stl, int facet, int vertex);
|
||||||
extern void stl_write_facet(stl_file *stl, char *label, int facet);
|
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_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_verify_neighbors(stl_file *stl);
|
||||||
extern void stl_fill_holes(stl_file *stl);
|
extern void stl_fill_holes(stl_file *stl);
|
||||||
extern void stl_fix_normal_directions(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>
|
template<typename T>
|
||||||
extern void stl_transform(stl_file *stl, T *trafo3x4)
|
extern void stl_transform(stl_file *stl, T *trafo3x4)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
for (uint32_t i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) {
|
||||||
return;
|
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_get_size(stl);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void stl_transform(stl_file *stl, const Eigen::Transform<T, 3, Eigen::Affine, Eigen::DontAlign>& 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);
|
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];
|
stl_facet &f = stl->facet_start[i];
|
||||||
for (size_t j = 0; j < 3; ++j)
|
for (size_t j = 0; j < 3; ++j)
|
||||||
f.vertex[j] = (t * f.vertex[j].template cast<T>()).template cast<float>().eval();
|
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>
|
template<typename T>
|
||||||
inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::DontAlign>& m)
|
inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::DontAlign>& m)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
for (size_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
return;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < stl->stats.number_of_facets; ++i) {
|
|
||||||
stl_facet &f = stl->facet_start[i];
|
stl_facet &f = stl->facet_start[i];
|
||||||
for (size_t j = 0; j < 3; ++j)
|
for (size_t j = 0; j < 3; ++j)
|
||||||
f.vertex[j] = (m * f.vertex[j].template cast<T>()).template cast<float>().eval();
|
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);
|
stl_get_size(stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void stl_open_merge(stl_file *stl, char *file);
|
|
||||||
extern void stl_invalidate_shared_vertices(stl_file *stl);
|
template<typename T>
|
||||||
extern void stl_generate_shared_vertices(stl_file *stl);
|
extern void its_transform(indexed_triangle_set &its, T *trafo3x4)
|
||||||
extern void stl_write_obj(stl_file *stl, const char *file);
|
{
|
||||||
extern void stl_write_off(stl_file *stl, const char *file);
|
for (stl_vertex &v_dst : its.vertices) {
|
||||||
extern void stl_write_dxf(stl_file *stl, const char *file, char *label);
|
stl_vertex v_src = v_dst;
|
||||||
extern void stl_write_vrml(stl_file *stl, const char *file);
|
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) {
|
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]);
|
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
|
else
|
||||||
normal *= float(1.0 / length);
|
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_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_allocate(stl_file *stl);
|
||||||
extern void stl_read(stl_file *stl, int first_facet, bool first);
|
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_facet_stats(stl_file *stl, stl_facet facet, bool &first);
|
||||||
extern void stl_reallocate(stl_file *stl);
|
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);
|
// Validate the mesh, assert on error.
|
||||||
extern int stl_get_error(stl_file *stl);
|
extern bool stl_validate(const stl_file *stl);
|
||||||
extern void stl_exit_on_error(stl_file *stl);
|
extern bool stl_validate(const stl_file *stl, const indexed_triangle_set &its);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,159 +22,86 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
#include <boost/predef/other/endian.h>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
#include <boost/nowide/cstdio.hpp>
|
void stl_stats_out(stl_file *stl, FILE *file, char *input_file)
|
||||||
#include <boost/detail/endian.hpp>
|
{
|
||||||
|
// This is here for Slic3r, without our config.h it won't use this part of the code anyway.
|
||||||
#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 */
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
#define VERSION "unknown"
|
#define VERSION "unknown"
|
||||||
#endif
|
#endif
|
||||||
fprintf(file, "\n\
|
fprintf(file, "\n================= Results produced by ADMesh version " VERSION " ================\n");
|
||||||
================= Results produced by ADMesh version " VERSION " ================\n");
|
fprintf(file, "Input file : %s\n", input_file);
|
||||||
fprintf(file, "\
|
if (stl->stats.type == binary)
|
||||||
Input file : %s\n", input_file);
|
fprintf(file, "File type : Binary STL file\n");
|
||||||
if(stl->stats.type == binary) {
|
else
|
||||||
fprintf(file, "\
|
fprintf(file, "File type : ASCII STL file\n");
|
||||||
File type : Binary STL file\n");
|
fprintf(file, "Header : %s\n", stl->stats.header);
|
||||||
} else {
|
fprintf(file, "============== Size ==============\n");
|
||||||
fprintf(file, "\
|
fprintf(file, "Min X = % f, Max X = % f\n", stl->stats.min(0), stl->stats.max(0));
|
||||||
File type : ASCII STL file\n");
|
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, "\
|
fprintf(file, "========= Facet Status ========== Original ============ Final ====\n");
|
||||||
Header : %s\n", stl->stats.header);
|
fprintf(file, "Number of facets : %5d %5d\n", stl->stats.original_num_facets, stl->stats.number_of_facets);
|
||||||
fprintf(file, "============== Size ==============\n");
|
fprintf(file, "Facets with 1 disconnected edge : %5d %5d\n",
|
||||||
fprintf(file, "Min X = % f, Max X = % f\n",
|
stl->stats.facets_w_1_bad_edge, stl->stats.connected_facets_2_edge - stl->stats.connected_facets_3_edge);
|
||||||
stl->stats.min(0), stl->stats.max(0));
|
fprintf(file, "Facets with 2 disconnected edges : %5d %5d\n",
|
||||||
fprintf(file, "Min Y = % f, Max Y = % f\n",
|
stl->stats.facets_w_2_bad_edge, stl->stats.connected_facets_1_edge - stl->stats.connected_facets_2_edge);
|
||||||
stl->stats.min(1), stl->stats.max(1));
|
fprintf(file, "Facets with 3 disconnected edges : %5d %5d\n",
|
||||||
fprintf(file, "Min Z = % f, Max Z = % f\n",
|
stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets - stl->stats.connected_facets_1_edge);
|
||||||
stl->stats.min(2), stl->stats.max(2));
|
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, "\
|
fprintf(file, "=== Processing Statistics === ===== Other Statistics =====\n");
|
||||||
========= Facet Status ========== Original ============ Final ====\n");
|
fprintf(file, "Number of parts : %5d Volume : %f\n", stl->stats.number_of_parts, stl->stats.volume);
|
||||||
fprintf(file, "\
|
fprintf(file, "Degenerate facets : %5d\n", stl->stats.degenerate_facets);
|
||||||
Number of facets : %5d %5d\n",
|
fprintf(file, "Edges fixed : %5d\n", stl->stats.edges_fixed);
|
||||||
stl->stats.original_num_facets, stl->stats.number_of_facets);
|
fprintf(file, "Facets removed : %5d\n", stl->stats.facets_removed);
|
||||||
fprintf(file, "\
|
fprintf(file, "Facets added : %5d\n", stl->stats.facets_added);
|
||||||
Facets with 1 disconnected edge : %5d %5d\n",
|
fprintf(file, "Facets reversed : %5d\n", stl->stats.facets_reversed);
|
||||||
stl->stats.facets_w_1_bad_edge, stl->stats.connected_facets_2_edge -
|
fprintf(file, "Backwards edges : %5d\n", stl->stats.backwards_edges);
|
||||||
stl->stats.connected_facets_3_edge);
|
fprintf(file, "Normals fixed : %5d\n", stl->stats.normals_fixed);
|
||||||
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
|
bool stl_write_ascii(stl_file *stl, const char *file, const char *label)
|
||||||
stl_write_ascii(stl_file *stl, const char *file, const char *label) {
|
{
|
||||||
int i;
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
char *error_msg;
|
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 */
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
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));
|
||||||
if(fp == NULL) {
|
fprintf(fp, " outer loop\n");
|
||||||
error_msg = (char*)
|
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));
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
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));
|
||||||
sprintf(error_msg, "stl_write_ascii: Couldn't open %s for writing",
|
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));
|
||||||
file);
|
fprintf(fp, " endloop\n");
|
||||||
perror(error_msg);
|
fprintf(fp, " endfacet\n");
|
||||||
free(error_msg);
|
}
|
||||||
stl->error = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "solid %s\n", label);
|
fprintf(fp, "endsolid %s\n", label);
|
||||||
|
fclose(fp);
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
return true;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool stl_print_neighbors(stl_file *stl, char *file)
|
||||||
stl_print_neighbors(stl_file *stl, char *file) {
|
{
|
||||||
int i;
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
FILE *fp;
|
if (fp == nullptr) {
|
||||||
char *error_msg;
|
BOOST_LOG_TRIVIAL(error) << "stl_print_neighbors: Couldn't open " << file << " for writing";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (stl->error) return;
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
|
fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\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_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",
|
|
||||||
i,
|
i,
|
||||||
stl->neighbors_start[i].neighbor[0],
|
stl->neighbors_start[i].neighbor[0],
|
||||||
(int)stl->neighbors_start[i].which_vertex_not[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],
|
(int)stl->neighbors_start[i].which_vertex_not[1],
|
||||||
stl->neighbors_start[i].neighbor[2],
|
stl->neighbors_start[i].neighbor[2],
|
||||||
(int)stl->neighbors_start[i].which_vertex_not[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.
|
// 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)
|
void stl_internal_reverse_quads(char *buf, size_t cnt)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < cnt; i += 4) {
|
for (size_t i = 0; i < cnt; i += 4) {
|
||||||
std::swap(buf[i], buf[i+3]);
|
std::swap(buf[i], buf[i+3]);
|
||||||
std::swap(buf[i+1], buf[i+2]);
|
std::swap(buf[i+1], buf[i+2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
||||||
stl_write_binary(stl_file *stl, const char *file, const char *label) {
|
{
|
||||||
FILE *fp;
|
FILE *fp = boost::nowide::fopen(file, "wb");
|
||||||
int i;
|
if (fp == nullptr) {
|
||||||
char *error_msg;
|
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 */
|
#if !defined(SEEK_SET)
|
||||||
fp = boost::nowide::fopen(file, "wb");
|
#define SEEK_SET 0
|
||||||
if(fp == NULL) {
|
#endif
|
||||||
error_msg = (char*)
|
fseek(fp, LABEL_SIZE, SEEK_SET);
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
#if BOOST_ENDIAN_LITTLE_BYTE
|
||||||
sprintf(error_msg, "stl_write_binary: Couldn't open %s for writing",
|
fwrite(&stl->stats.number_of_facets, 4, 1, fp);
|
||||||
file);
|
for (const stl_facet &facet : stl->facet_start)
|
||||||
perror(error_msg);
|
fwrite(&facet, SIZEOF_STL_FACET, 1, fp);
|
||||||
free(error_msg);
|
#else /* BOOST_ENDIAN_LITTLE_BYTE */
|
||||||
stl->error = 1;
|
char buffer[50];
|
||||||
return;
|
// Convert the number of facets to little endian.
|
||||||
}
|
memcpy(buffer, &stl->stats.number_of_facets, 4);
|
||||||
|
stl_internal_reverse_quads(buffer, 4);
|
||||||
fprintf(fp, "%s", label);
|
fwrite(buffer, 4, 1, fp);
|
||||||
for(i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp);
|
for (i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
|
memcpy(buffer, stl->facet_start + i, 50);
|
||||||
fseek(fp, LABEL_SIZE, SEEK_SET);
|
// Convert to little endian.
|
||||||
#ifdef BOOST_LITTLE_ENDIAN
|
stl_internal_reverse_quads(buffer, 48);
|
||||||
fwrite(&stl->stats.number_of_facets, 4, 1, fp);
|
fwrite(buffer, SIZEOF_STL_FACET, 1, fp);
|
||||||
for (i = 0; i < stl->stats.number_of_facets; ++ i)
|
}
|
||||||
fwrite(stl->facet_start + i, SIZEOF_STL_FACET, 1, fp);
|
#endif /* BOOST_ENDIAN_LITTLE_BYTE */
|
||||||
#else /* BOOST_LITTLE_ENDIAN */
|
fclose(fp);
|
||||||
char buffer[50];
|
return true;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_write_vertex(stl_file *stl, int facet, int vertex)
|
||||||
stl_write_vertex(stl_file *stl, int facet, int vertex) {
|
{
|
||||||
if (stl->error) return;
|
printf(" vertex %d/%d % .8E % .8E % .8E\n", vertex, facet,
|
||||||
printf(" vertex %d/%d % .8E % .8E % .8E\n", vertex, facet,
|
|
||||||
stl->facet_start[facet].vertex[vertex](0),
|
stl->facet_start[facet].vertex[vertex](0),
|
||||||
stl->facet_start[facet].vertex[vertex](1),
|
stl->facet_start[facet].vertex[vertex](1),
|
||||||
stl->facet_start[facet].vertex[vertex](2));
|
stl->facet_start[facet].vertex[vertex](2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_write_facet(stl_file *stl, char *label, int facet)
|
||||||
stl_write_facet(stl_file *stl, char *label, int facet) {
|
{
|
||||||
if (stl->error) return;
|
printf("facet (%d)/ %s\n", facet, label);
|
||||||
printf("facet (%d)/ %s\n", facet, label);
|
stl_write_vertex(stl, facet, 0);
|
||||||
stl_write_vertex(stl, facet, 0);
|
stl_write_vertex(stl, facet, 1);
|
||||||
stl_write_vertex(stl, facet, 1);
|
stl_write_vertex(stl, facet, 2);
|
||||||
stl_write_vertex(stl, facet, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_write_neighbor(stl_file *stl, int facet)
|
||||||
stl_write_edge(stl_file *stl, char *label, stl_hash_edge edge) {
|
{
|
||||||
if (stl->error) return;
|
printf("Neighbors %d: %d, %d, %d ; %d, %d, %d\n", facet,
|
||||||
printf("edge (%d)/(%d) %s\n", edge.facet_number, edge.which_edge, label);
|
stl->neighbors_start[facet].neighbor[0],
|
||||||
if(edge.which_edge < 3) {
|
stl->neighbors_start[facet].neighbor[1],
|
||||||
stl_write_vertex(stl, edge.facet_number, edge.which_edge % 3);
|
stl->neighbors_start[facet].neighbor[2],
|
||||||
stl_write_vertex(stl, edge.facet_number, (edge.which_edge + 1) % 3);
|
stl->neighbors_start[facet].which_vertex_not[0],
|
||||||
} else {
|
stl->neighbors_start[facet].which_vertex_not[1],
|
||||||
stl_write_vertex(stl, edge.facet_number, (edge.which_edge + 1) % 3);
|
stl->neighbors_start[facet].which_vertex_not[2]);
|
||||||
stl_write_vertex(stl, edge.facet_number, edge.which_edge % 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool stl_write_quad_object(stl_file *stl, char *file)
|
||||||
stl_write_neighbor(stl_file *stl, int facet) {
|
{
|
||||||
if (stl->error) return;
|
stl_vertex connect_color = stl_vertex::Zero();
|
||||||
printf("Neighbors %d: %d, %d, %d ; %d, %d, %d\n", facet,
|
stl_vertex uncon_1_color = stl_vertex::Zero();
|
||||||
stl->neighbors_start[facet].neighbor[0],
|
stl_vertex uncon_2_color = stl_vertex::Zero();
|
||||||
stl->neighbors_start[facet].neighbor[1],
|
stl_vertex uncon_3_color = stl_vertex::Zero();
|
||||||
stl->neighbors_start[facet].neighbor[2],
|
stl_vertex color;
|
||||||
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
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
stl_write_quad_object(stl_file *stl, char *file) {
|
if (fp == nullptr) {
|
||||||
FILE *fp;
|
BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing";
|
||||||
int i;
|
return false;
|
||||||
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;
|
|
||||||
|
|
||||||
if (stl->error) return;
|
fprintf(fp, "CQUAD\n");
|
||||||
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
/* Open the file */
|
switch (stl->neighbors_start[i].num_neighbors_missing()) {
|
||||||
fp = boost::nowide::fopen(file, "w");
|
case 0: color = connect_color; break;
|
||||||
if(fp == NULL) {
|
case 1: color = uncon_1_color; break;
|
||||||
error_msg = (char*)
|
case 2: color = uncon_2_color; break;
|
||||||
malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */
|
default: color = uncon_3_color;
|
||||||
sprintf(error_msg, "stl_write_quad_object: Couldn't open %s for writing",
|
}
|
||||||
file);
|
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));
|
||||||
perror(error_msg);
|
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));
|
||||||
free(error_msg);
|
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));
|
||||||
stl->error = 1;
|
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));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool stl_write_dxf(stl_file *stl, const char *file, char *label)
|
||||||
stl_write_dxf(stl_file *stl, const char *file, char *label) {
|
{
|
||||||
int i;
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
FILE *fp;
|
if (fp == nullptr) {
|
||||||
char *error_msg;
|
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 */
|
fprintf(fp, "0\nSECTION\n2\nENTITIES\n");
|
||||||
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, "999\n%s\n", label);
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
fprintf(fp, "0\nSECTION\n2\nHEADER\n0\nENDSEC\n");
|
fprintf(fp, "0\n3DFACE\n8\n0\n");
|
||||||
fprintf(fp, "0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLAYER\n70\n1\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));
|
||||||
0\nLAYER\n2\n0\n70\n0\n62\n7\n6\nCONTINUOUS\n0\nENDTAB\n0\nENDSEC\n");
|
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, "0\nSECTION\n2\nBLOCKS\n0\nENDSEC\n");
|
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");
|
fprintf(fp, "0\nENDSEC\n0\nEOF\n");
|
||||||
|
fclose(fp);
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
return true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
#include <boost/detail/endian.hpp>
|
#include <boost/detail/endian.hpp>
|
||||||
|
|
||||||
|
@ -35,351 +36,236 @@
|
||||||
#error "SEEK_SET not defined"
|
#error "SEEK_SET not defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
static FILE* stl_open_count_facets(stl_file *stl, const char *file)
|
||||||
stl_open(stl_file *stl, const char *file) {
|
{
|
||||||
stl_initialize(stl);
|
// Open the file in binary mode first.
|
||||||
stl_count_facets(stl, file);
|
FILE *fp = boost::nowide::fopen(file, "rb");
|
||||||
stl_allocate(stl);
|
if (fp == nullptr) {
|
||||||
stl_read(stl, 0, true);
|
BOOST_LOG_TRIVIAL(error) << "stl_open_count_facets: Couldn't open " << file << " for reading";
|
||||||
if (stl->fp != nullptr) {
|
return nullptr;
|
||||||
fclose(stl->fp);
|
}
|
||||||
stl->fp = 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
|
/* Reads the contents of the file pointed to by fp into the stl structure,
|
||||||
stl_initialize(stl_file *stl) {
|
starting at facet first_facet. The second argument says if it's our first
|
||||||
memset(stl, 0, sizeof(stl_file));
|
time running this for the stl and therefore we should reset our max and min stats. */
|
||||||
stl->stats.volume = -1.0;
|
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
|
#ifndef BOOST_LITTLE_ENDIAN
|
||||||
extern void stl_internal_reverse_quads(char *buf, size_t cnt);
|
extern void stl_internal_reverse_quads(char *buf, size_t cnt);
|
||||||
#endif /* BOOST_LITTLE_ENDIAN */
|
#endif /* BOOST_LITTLE_ENDIAN */
|
||||||
|
|
||||||
void
|
void stl_allocate(stl_file *stl)
|
||||||
stl_count_facets(stl_file *stl, const char *file) {
|
{
|
||||||
long file_size;
|
// Allocate memory for the entire .STL file.
|
||||||
uint32_t header_num_facets;
|
stl->facet_start.assign(stl->stats.number_of_facets, stl_facet());
|
||||||
uint32_t num_facets;
|
// Allocate memory for the neighbors list.
|
||||||
int i;
|
stl->neighbors_start.assign(stl->stats.number_of_facets, stl_neighbors());
|
||||||
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
|
void stl_reallocate(stl_file *stl)
|
||||||
stl_allocate(stl_file *stl) {
|
{
|
||||||
if (stl->error) return;
|
stl->facet_start.resize(stl->stats.number_of_facets);
|
||||||
|
stl->neighbors_start.resize(stl->stats.number_of_facets);
|
||||||
/* 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_facet_stats(stl_file *stl, stl_facet facet, bool &first)
|
void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
// While we are going through all of the facets, let's find the
|
||||||
return;
|
// maximum and minimum values for x, y, and z
|
||||||
|
|
||||||
// While we are going through all of the facets, let's find the
|
if (first) {
|
||||||
// maximum and minimum values for x, y, and z
|
// 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) {
|
// Now find the max and min values.
|
||||||
// Initialize the max and min values the first time through
|
for (size_t i = 0; i < 3; ++ i) {
|
||||||
stl->stats.min = facet.vertex[0];
|
stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]);
|
||||||
stl->stats.max = facet.vertex[0];
|
stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,435 +25,375 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
static void stl_rotate(float *x, float *y, const double c, const double s);
|
void stl_verify_neighbors(stl_file *stl)
|
||||||
static float get_area(stl_facet *facet);
|
{
|
||||||
static float get_volume(stl_file *stl);
|
stl->stats.backwards_edges = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
void
|
for (int j = 0; j < 3; ++ j) {
|
||||||
stl_verify_neighbors(stl_file *stl) {
|
struct stl_edge {
|
||||||
int i;
|
stl_vertex p1;
|
||||||
int j;
|
stl_vertex p2;
|
||||||
stl_edge edge_a;
|
int facet_number;
|
||||||
stl_edge edge_b;
|
};
|
||||||
int neighbor;
|
stl_edge edge_a;
|
||||||
int vnot;
|
edge_a.p1 = stl->facet_start[i].vertex[j];
|
||||||
|
edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3];
|
||||||
if (stl->error) return;
|
int neighbor = stl->neighbors_start[i].neighbor[j];
|
||||||
|
if (neighbor == -1)
|
||||||
stl->stats.backwards_edges = 0;
|
continue; // this edge has no neighbor... Continue.
|
||||||
|
int vnot = stl->neighbors_start[i].which_vertex_not[j];
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
stl_edge edge_b;
|
||||||
for(j = 0; j < 3; j++) {
|
if (vnot < 3) {
|
||||||
edge_a.p1 = stl->facet_start[i].vertex[j];
|
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
||||||
edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3];
|
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
||||||
neighbor = stl->neighbors_start[i].neighbor[j];
|
} else {
|
||||||
vnot = stl->neighbors_start[i].which_vertex_not[j];
|
stl->stats.backwards_edges += 1;
|
||||||
|
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
||||||
if(neighbor == -1)
|
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
||||||
continue; /* this edge has no neighbor... Continue. */
|
}
|
||||||
if(vnot < 3) {
|
if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) {
|
||||||
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
// These edges should match but they don't. Print results.
|
||||||
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
BOOST_LOG_TRIVIAL(info) << "edge " << j << " of facet " << i << " doesn't match edge " << (vnot + 1) << " of facet " << neighbor;
|
||||||
} else {
|
stl_write_facet(stl, (char*)"first facet", i);
|
||||||
stl->stats.backwards_edges += 1;
|
stl_write_facet(stl, (char*)"second facet", neighbor);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_translate(stl_file *stl, float x, float y, float z)
|
void stl_translate(stl_file *stl, float x, float y, float z)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
stl_vertex new_min(x, y, z);
|
||||||
return;
|
stl_vertex shift = new_min - stl->stats.min;
|
||||||
|
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
stl_vertex new_min(x, y, z);
|
for (int j = 0; j < 3; ++ j)
|
||||||
stl_vertex shift = new_min - stl->stats.min;
|
stl->facet_start[i].vertex[j] += shift;
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
stl->stats.min = new_min;
|
||||||
for (int j = 0; j < 3; ++ j)
|
stl->stats.max += shift;
|
||||||
stl->facet_start[i].vertex[j] += shift;
|
|
||||||
stl->stats.min = new_min;
|
|
||||||
stl->stats.max += shift;
|
|
||||||
stl_invalidate_shared_vertices(stl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translates the stl by x,y,z, relatively from wherever it is currently */
|
/* 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)
|
void stl_translate_relative(stl_file *stl, float x, float y, float z)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
stl_vertex shift(x, y, z);
|
||||||
return;
|
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
|
for (int j = 0; j < 3; ++ j)
|
||||||
stl_vertex shift(x, y, z);
|
stl->facet_start[i].vertex[j] += shift;
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
stl->stats.min += shift;
|
||||||
for (int j = 0; j < 3; ++ j)
|
stl->stats.max += shift;
|
||||||
stl->facet_start[i].vertex[j] += shift;
|
|
||||||
stl->stats.min += shift;
|
|
||||||
stl->stats.max += shift;
|
|
||||||
stl_invalidate_shared_vertices(stl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
|
void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
// Scale extents.
|
||||||
return;
|
auto s = versor.array();
|
||||||
|
stl->stats.min.array() *= s;
|
||||||
// Scale extents.
|
stl->stats.max.array() *= s;
|
||||||
auto s = versor.array();
|
// Scale size.
|
||||||
stl->stats.min.array() *= s;
|
stl->stats.size.array() *= s;
|
||||||
stl->stats.max.array() *= s;
|
// Scale volume.
|
||||||
// Scale size.
|
if (stl->stats.volume > 0.0)
|
||||||
stl->stats.size.array() *= s;
|
stl->stats.volume *= versor(0) * versor(1) * versor(2);
|
||||||
// Scale volume.
|
// Scale the mesh.
|
||||||
if (stl->stats.volume > 0.0)
|
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
stl->stats.volume *= versor(0) * versor(1) * versor(2);
|
for (int j = 0; j < 3; ++ j)
|
||||||
// Scale the mesh.
|
stl->facet_start[i].vertex[j].array() *= s;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calculate_normals(stl_file *stl)
|
static void calculate_normals(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
stl_normal normal;
|
||||||
return;
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
|
stl_calculate_normal(normal, &stl->facet_start[i]);
|
||||||
stl_normal normal;
|
stl_normalize_vector(normal);
|
||||||
for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
|
stl->facet_start[i].normal = normal;
|
||||||
stl_calculate_normal(normal, &stl->facet_start[i]);
|
}
|
||||||
stl_normalize_vector(normal);
|
|
||||||
stl->facet_start[i].normal = normal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static inline void rotate_point_2d(float &x, float &y, const double c, const double s)
|
||||||
stl_rotate_x(stl_file *stl, float angle) {
|
{
|
||||||
int i;
|
double xold = x;
|
||||||
int j;
|
double yold = y;
|
||||||
double radian_angle = (angle / 180.0) * M_PI;
|
x = float(c * xold - s * yold);
|
||||||
double c = cos(radian_angle);
|
y = float(s * xold + c * yold);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_rotate_x(stl_file *stl, float angle)
|
||||||
stl_rotate_y(stl_file *stl, float angle) {
|
{
|
||||||
int i;
|
double radian_angle = (angle / 180.0) * M_PI;
|
||||||
int j;
|
double c = cos(radian_angle);
|
||||||
double radian_angle = (angle / 180.0) * M_PI;
|
double s = sin(radian_angle);
|
||||||
double c = cos(radian_angle);
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
double s = sin(radian_angle);
|
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);
|
||||||
if (stl->error) return;
|
stl_get_size(stl);
|
||||||
|
calculate_normals(stl);
|
||||||
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
|
void stl_rotate_y(stl_file *stl, float angle)
|
||||||
stl_rotate_z(stl_file *stl, float angle) {
|
{
|
||||||
int i;
|
double radian_angle = (angle / 180.0) * M_PI;
|
||||||
int j;
|
double c = cos(radian_angle);
|
||||||
double radian_angle = (angle / 180.0) * M_PI;
|
double s = sin(radian_angle);
|
||||||
double c = cos(radian_angle);
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
double s = sin(radian_angle);
|
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);
|
||||||
if (stl->error) return;
|
stl_get_size(stl);
|
||||||
|
calculate_normals(stl);
|
||||||
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_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
|
void its_rotate_y(indexed_triangle_set& its, float angle)
|
||||||
stl_rotate(float *x, float *y, const double c, const double s) {
|
{
|
||||||
double xold = *x;
|
double radian_angle = (angle / 180.0) * M_PI;
|
||||||
double yold = *y;
|
double c = cos(radian_angle);
|
||||||
*x = float(c * xold - s * yold);
|
double s = sin(radian_angle);
|
||||||
*y = float(s * xold + c * yold);
|
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)
|
void stl_get_size(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->error || stl->stats.number_of_facets == 0)
|
if (stl->stats.number_of_facets == 0)
|
||||||
return;
|
return;
|
||||||
stl->stats.min = stl->facet_start[0].vertex[0];
|
stl->stats.min = stl->facet_start[0].vertex[0];
|
||||||
stl->stats.max = stl->stats.min;
|
stl->stats.max = stl->stats.min;
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
const stl_facet &face = stl->facet_start[i];
|
const stl_facet &face = stl->facet_start[i];
|
||||||
for (int j = 0; j < 3; ++ j) {
|
for (int j = 0; j < 3; ++ j) {
|
||||||
stl->stats.min = stl->stats.min.cwiseMin(face.vertex[j]);
|
stl->stats.min = stl->stats.min.cwiseMin(face.vertex[j]);
|
||||||
stl->stats.max = stl->stats.max.cwiseMax(face.vertex[j]);
|
stl->stats.max = stl->stats.max.cwiseMax(face.vertex[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stl->stats.size = stl->stats.max - stl->stats.min;
|
stl->stats.size = stl->stats.max - stl->stats.min;
|
||||||
stl->stats.bounding_diameter = stl->stats.size.norm();
|
stl->stats.bounding_diameter = stl->stats.size.norm();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_mirror_xy(stl_file *stl)
|
void stl_mirror_xy(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
return;
|
for (int j = 0; j < 3; ++ j)
|
||||||
|
stl->facet_start[i].vertex[j](2) *= -1.0;
|
||||||
for(int i = 0; i < stl->stats.number_of_facets; i++) {
|
float temp_size = stl->stats.min(2);
|
||||||
for(int j = 0; j < 3; j++) {
|
stl->stats.min(2) = stl->stats.max(2);
|
||||||
stl->facet_start[i].vertex[j](2) *= -1.0;
|
stl->stats.max(2) = temp_size;
|
||||||
}
|
stl->stats.min(2) *= -1.0;
|
||||||
}
|
stl->stats.max(2) *= -1.0;
|
||||||
float temp_size = stl->stats.min(2);
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.min(2) = stl->stats.max(2);
|
stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */
|
||||||
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)
|
void stl_mirror_yz(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->error) return;
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; i++) {
|
stl->facet_start[i].vertex[j](0) *= -1.0;
|
||||||
for (int j = 0; j < 3; j++) {
|
float temp_size = stl->stats.min(0);
|
||||||
stl->facet_start[i].vertex[j](0) *= -1.0;
|
stl->stats.min(0) = stl->stats.max(0);
|
||||||
}
|
stl->stats.max(0) = temp_size;
|
||||||
}
|
stl->stats.min(0) *= -1.0;
|
||||||
float temp_size = stl->stats.min(0);
|
stl->stats.max(0) *= -1.0;
|
||||||
stl->stats.min(0) = stl->stats.max(0);
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.max(0) = temp_size;
|
stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */
|
||||||
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)
|
void stl_mirror_xz(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
return;
|
for (int j = 0; j < 3; ++ j)
|
||||||
|
stl->facet_start[i].vertex[j](1) *= -1.0;
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; i++) {
|
float temp_size = stl->stats.min(1);
|
||||||
for (int j = 0; j < 3; j++) {
|
stl->stats.min(1) = stl->stats.max(1);
|
||||||
stl->facet_start[i].vertex[j](1) *= -1.0;
|
stl->stats.max(1) = temp_size;
|
||||||
}
|
stl->stats.min(1) *= -1.0;
|
||||||
}
|
stl->stats.max(1) *= -1.0;
|
||||||
float temp_size = stl->stats.min(1);
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.min(1) = stl->stats.max(1);
|
stl->stats.facets_reversed -= stl->stats.number_of_facets; // for not altering stats
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float get_area(stl_facet *facet)
|
static float get_area(stl_facet *facet)
|
||||||
{
|
{
|
||||||
/* cast to double before calculating cross product because large coordinates
|
/* cast to double before calculating cross product because large coordinates
|
||||||
can result in overflowing product
|
can result in overflowing product
|
||||||
(bad area is responsible for bad volume and bad facets reversal) */
|
(bad area is responsible for bad volume and bad facets reversal) */
|
||||||
double cross[3][3];
|
double cross[3][3];
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
cross[i][0]=(((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](2)) -
|
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)));
|
((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)) -
|
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)));
|
((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)) -
|
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)));
|
((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
stl_normal sum;
|
stl_normal sum;
|
||||||
sum(0) = cross[0][0] + cross[1][0] + cross[2][0];
|
sum(0) = cross[0][0] + cross[1][0] + cross[2][0];
|
||||||
sum(1) = cross[0][1] + cross[1][1] + cross[2][1];
|
sum(1) = cross[0][1] + cross[1][1] + cross[2][1];
|
||||||
sum(2) = cross[0][2] + cross[1][2] + cross[2][2];
|
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.
|
// 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.
|
//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_normal n;
|
||||||
stl_calculate_normal(n, facet);
|
stl_calculate_normal(n, facet);
|
||||||
stl_normalize_vector(n);
|
stl_normalize_vector(n);
|
||||||
return 0.5f * n.dot(sum);
|
return 0.5f * n.dot(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_repair(stl_file *stl,
|
static float get_volume(stl_file *stl)
|
||||||
int fixall_flag,
|
{
|
||||||
int exact_flag,
|
// Choose a point, any point as the reference.
|
||||||
int tolerance_flag,
|
stl_vertex p0 = stl->facet_start[0].vertex[0];
|
||||||
float tolerance,
|
float volume = 0.f;
|
||||||
int increment_flag,
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
float increment,
|
// Do dot product to get distance from point to plane.
|
||||||
int nearby_flag,
|
float height = stl->facet_start[i].normal.dot(stl->facet_start[i].vertex[0] - p0);
|
||||||
int iterations,
|
float area = get_area(&stl->facet_start[i]);
|
||||||
int remove_unconnected_flag,
|
volume += (area * height) / 3.0f;
|
||||||
int fill_holes_flag,
|
}
|
||||||
int normal_directions_flag,
|
return volume;
|
||||||
int normal_values_flag,
|
}
|
||||||
int reverse_all_flag,
|
|
||||||
int verbose_flag) {
|
void stl_calculate_volume(stl_file *stl)
|
||||||
|
{
|
||||||
int i;
|
stl->stats.volume = get_volume(stl);
|
||||||
int last_edges_fixed = 0;
|
if (stl->stats.volume < 0.0) {
|
||||||
|
stl_reverse_all_facets(stl);
|
||||||
if (stl->error) return;
|
stl->stats.volume = -stl->stats.volume;
|
||||||
|
}
|
||||||
if(exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag
|
}
|
||||||
|| fill_holes_flag || normal_directions_flag) {
|
|
||||||
if (verbose_flag)
|
void stl_repair(
|
||||||
printf("Checking exact...\n");
|
stl_file *stl,
|
||||||
exact_flag = 1;
|
bool fixall_flag,
|
||||||
stl_check_facets_exact(stl);
|
bool exact_flag,
|
||||||
stl->stats.facets_w_1_bad_edge =
|
bool tolerance_flag,
|
||||||
(stl->stats.connected_facets_2_edge -
|
float tolerance,
|
||||||
stl->stats.connected_facets_3_edge);
|
bool increment_flag,
|
||||||
stl->stats.facets_w_2_bad_edge =
|
float increment,
|
||||||
(stl->stats.connected_facets_1_edge -
|
bool nearby_flag,
|
||||||
stl->stats.connected_facets_2_edge);
|
int iterations,
|
||||||
stl->stats.facets_w_3_bad_edge =
|
bool remove_unconnected_flag,
|
||||||
(stl->stats.number_of_facets -
|
bool fill_holes_flag,
|
||||||
stl->stats.connected_facets_1_edge);
|
bool normal_directions_flag,
|
||||||
}
|
bool normal_values_flag,
|
||||||
|
bool reverse_all_flag,
|
||||||
if(nearby_flag || fixall_flag) {
|
bool verbose_flag)
|
||||||
if(!tolerance_flag) {
|
{
|
||||||
tolerance = stl->stats.shortest_edge;
|
if (exact_flag || fixall_flag || nearby_flag || remove_unconnected_flag || fill_holes_flag || normal_directions_flag) {
|
||||||
}
|
if (verbose_flag)
|
||||||
if(!increment_flag) {
|
printf("Checking exact...\n");
|
||||||
increment = stl->stats.bounding_diameter / 10000.0;
|
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);
|
||||||
if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
stl->stats.facets_w_2_bad_edge = (stl->stats.connected_facets_1_edge - stl->stats.connected_facets_2_edge);
|
||||||
for(i = 0; i < iterations; i++) {
|
stl->stats.facets_w_3_bad_edge = (stl->stats.number_of_facets - stl->stats.connected_facets_1_edge);
|
||||||
if(stl->stats.connected_facets_3_edge <
|
}
|
||||||
stl->stats.number_of_facets) {
|
|
||||||
if (verbose_flag)
|
if (nearby_flag || fixall_flag) {
|
||||||
printf("\
|
if (! tolerance_flag)
|
||||||
Checking nearby. Tolerance= %f Iteration=%d of %d...",
|
tolerance = stl->stats.shortest_edge;
|
||||||
tolerance, i + 1, iterations);
|
if (! increment_flag)
|
||||||
stl_check_facets_nearby(stl, tolerance);
|
increment = stl->stats.bounding_diameter / 10000.0;
|
||||||
if (verbose_flag)
|
}
|
||||||
printf(" Fixed %d edges.\n",
|
|
||||||
stl->stats.edges_fixed - last_edges_fixed);
|
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
last_edges_fixed = stl->stats.edges_fixed;
|
int last_edges_fixed = 0;
|
||||||
tolerance += increment;
|
for (int i = 0; i < iterations; ++ i) {
|
||||||
} else {
|
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("\
|
printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
|
||||||
All facets connected. No further nearby check necessary.\n");
|
stl_check_facets_nearby(stl, tolerance);
|
||||||
break;
|
if (verbose_flag)
|
||||||
}
|
printf(" Fixed %d edges.\n", stl->stats.edges_fixed - last_edges_fixed);
|
||||||
}
|
last_edges_fixed = stl->stats.edges_fixed;
|
||||||
} else {
|
tolerance += increment;
|
||||||
if (verbose_flag)
|
} else {
|
||||||
printf("All facets connected. No nearby check necessary.\n");
|
if (verbose_flag)
|
||||||
}
|
printf("All facets connected. No further nearby check necessary.\n");
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
if(remove_unconnected_flag || fixall_flag || fill_holes_flag) {
|
}
|
||||||
if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
} else if (verbose_flag)
|
||||||
if (verbose_flag)
|
printf("All facets connected. No nearby check necessary.\n");
|
||||||
printf("Removing unconnected facets...\n");
|
|
||||||
stl_remove_unconnected_facets(stl);
|
if (remove_unconnected_flag || fixall_flag || fill_holes_flag) {
|
||||||
} else
|
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
if (verbose_flag)
|
if (verbose_flag)
|
||||||
printf("No unconnected need to be removed.\n");
|
printf("Removing unconnected facets...\n");
|
||||||
}
|
stl_remove_unconnected_facets(stl);
|
||||||
|
} else if (verbose_flag)
|
||||||
if(fill_holes_flag || fixall_flag) {
|
printf("No unconnected need to be removed.\n");
|
||||||
if(stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
}
|
||||||
if (verbose_flag)
|
|
||||||
printf("Filling holes...\n");
|
if (fill_holes_flag || fixall_flag) {
|
||||||
stl_fill_holes(stl);
|
if (stl->stats.connected_facets_3_edge < stl->stats.number_of_facets) {
|
||||||
} else
|
if (verbose_flag)
|
||||||
if (verbose_flag)
|
printf("Filling holes...\n");
|
||||||
printf("No holes need to be filled.\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");
|
if (reverse_all_flag) {
|
||||||
stl_reverse_all_facets(stl);
|
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");
|
if (normal_directions_flag || fixall_flag) {
|
||||||
stl_fix_normal_directions(stl);
|
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");
|
if (normal_values_flag || fixall_flag) {
|
||||||
stl_fix_normal_values(stl);
|
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");
|
// Always calculate the volume. It shouldn't take too long.
|
||||||
stl_calculate_volume(stl);
|
if (verbose_flag)
|
||||||
|
printf("Calculating volume...\n");
|
||||||
if(exact_flag) {
|
stl_calculate_volume(stl);
|
||||||
if (verbose_flag)
|
|
||||||
printf("Verifying neighbors...\n");
|
if (exact_flag) {
|
||||||
stl_verify_neighbors(stl);
|
if (verbose_flag)
|
||||||
}
|
printf("Verifying neighbors...\n");
|
||||||
|
stl_verify_neighbors(stl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,10 @@ if (MSVC)
|
||||||
windows/unistd.cpp
|
windows/unistd.cpp
|
||||||
windows/getopt.c
|
windows/getopt.c
|
||||||
)
|
)
|
||||||
|
elseif (MINGW)
|
||||||
|
set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
|
||||||
|
windows/utf8.c
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(avrdude-conf-gen conf-generate.cpp)
|
add_executable(avrdude-conf-gen conf-generate.cpp)
|
||||||
|
@ -81,13 +85,13 @@ add_executable(avrdude-conf-gen conf-generate.cpp)
|
||||||
# Config file embedding
|
# Config file embedding
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
DEPENDS avrdude-conf-gen ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf
|
DEPENDS avrdude-conf-gen ${CMAKE_CURRENT_SOURCE_DIR}/avrdude-slic3r.conf
|
||||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/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 > 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}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(gen_conf_h
|
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})
|
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
|
||||||
|
@ -96,7 +100,15 @@ add_dependencies(avrdude gen_conf_h)
|
||||||
add_executable(avrdude-slic3r main-standalone.cpp)
|
add_executable(avrdude-slic3r main-standalone.cpp)
|
||||||
target_link_libraries(avrdude-slic3r avrdude)
|
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)
|
if (WIN32)
|
||||||
target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1)
|
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()
|
endif()
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||||
{
|
{
|
||||||
unsigned char buf[32];
|
unsigned char buf[32];
|
||||||
|
(void)p;
|
||||||
|
|
||||||
/* Signature byte reads are always 3 bytes. */
|
/* 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)
|
static int prusa_init_external_flash(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
// Note: send/receive as in _the firmare_ send & receives
|
// Note: send/receive as in _the firmare_ send & receives
|
||||||
const char entry_magic_send [] = "start\n";
|
const char entry_magic_send[] = "start\n";
|
||||||
const char entry_magic_receive[] = "w25x20cl_enter\n";
|
const unsigned char entry_magic_receive[] = "w25x20cl_enter\n";
|
||||||
const char entry_magic_cfm [] = "w25x20cl_cfm\n";
|
const char entry_magic_cfm[] = "w25x20cl_cfm\n";
|
||||||
const size_t buffer_len = 32; // Should be large enough for the above messages
|
const size_t buffer_len = 32; // Should be large enough for the above messages
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
|
@ -94,7 +95,7 @@ static int prusa_init_external_flash(PROGRAMMER * pgm)
|
||||||
|
|
||||||
// 1. receive the "start" command
|
// 1. receive the "start" command
|
||||||
recv_size = sizeof(entry_magic_send) - 1;
|
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) {
|
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);
|
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;
|
return -1;
|
||||||
|
@ -111,7 +112,7 @@ static int prusa_init_external_flash(PROGRAMMER * pgm)
|
||||||
|
|
||||||
// 3. Receive the entry confirmation command
|
// 3. Receive the entry confirmation command
|
||||||
recv_size = sizeof(entry_magic_cfm) - 1;
|
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) {
|
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);
|
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;
|
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
|
// 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):
|
// 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) {
|
if (serial_send(&pgm->fd, cleanup_newlines, sizeof(cleanup_newlines) - 1) < 0) {
|
||||||
return -1;
|
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);
|
avr_tpi_setup_rw(pgm, mem, 0, TPI_NVMCMD_NO_OPERATION);
|
||||||
|
|
||||||
/* load bytes */
|
/* load bytes */
|
||||||
for (lastaddr = i = 0; i < mem->size; i++) {
|
for (lastaddr = i = 0; i < (unsigned)mem->size; i++) {
|
||||||
RETURN_IF_CANCEL();
|
RETURN_IF_CANCEL();
|
||||||
if (vmem == NULL ||
|
if (vmem == NULL ||
|
||||||
(vmem->tags[i] & TAG_ALLOCATED) != 0)
|
(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 */
|
/* quickly scan number of pages to be written to first */
|
||||||
for (pageaddr = 0, npages = 0;
|
for (pageaddr = 0, npages = 0;
|
||||||
pageaddr < mem->size;
|
pageaddr < (unsigned)mem->size;
|
||||||
pageaddr += mem->page_size) {
|
pageaddr += mem->page_size) {
|
||||||
/* check whether this page must be read */
|
/* check whether this page must be read */
|
||||||
for (i = pageaddr;
|
for (i = pageaddr;
|
||||||
|
@ -391,7 +391,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pageaddr = 0, failure = 0, nread = 0;
|
for (pageaddr = 0, failure = 0, nread = 0;
|
||||||
!failure && pageaddr < mem->size;
|
!failure && pageaddr < (unsigned)mem->size;
|
||||||
pageaddr += mem->page_size) {
|
pageaddr += mem->page_size) {
|
||||||
RETURN_IF_CANCEL();
|
RETURN_IF_CANCEL();
|
||||||
/* check whether this page must be read */
|
/* 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();
|
RETURN_IF_CANCEL();
|
||||||
if (vmem == NULL ||
|
if (vmem == NULL ||
|
||||||
(vmem->tags[i] & TAG_ALLOCATED) != 0)
|
(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];
|
writeop = mem->op[AVR_OP_WRITE_HI];
|
||||||
else
|
else
|
||||||
writeop = mem->op[AVR_OP_WRITE_LO];
|
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]) {
|
else if (mem->paged && mem->op[AVR_OP_LOADPAGE_LO]) {
|
||||||
if (addr & 0x01)
|
if (addr & 0x01)
|
||||||
writeop = mem->op[AVR_OP_LOADPAGE_HI];
|
writeop = mem->op[AVR_OP_LOADPAGE_HI];
|
||||||
else
|
else
|
||||||
writeop = mem->op[AVR_OP_LOADPAGE_LO];
|
writeop = mem->op[AVR_OP_LOADPAGE_LO];
|
||||||
caddr = addr / 2;
|
caddr = (unsigned short)(addr / 2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
writeop = mem->op[AVR_OP_WRITE];
|
writeop = mem->op[AVR_OP_WRITE];
|
||||||
caddr = addr;
|
caddr = (unsigned short)addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writeop == NULL) {
|
if (writeop == NULL) {
|
||||||
|
@ -723,7 +723,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
gettimeofday (&tv, NULL);
|
gettimeofday (&tv, NULL);
|
||||||
prog_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
prog_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||||
} while ((r != data) &&
|
} 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 */
|
/* 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();
|
RETURN_IF_CANCEL();
|
||||||
if ((m->tags[i] & TAG_ALLOCATED) != 0 ||
|
if ((m->tags[i] & TAG_ALLOCATED) != 0 ||
|
||||||
(m->tags[i + 1] & 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 */
|
/* quickly scan number of pages to be written to first */
|
||||||
for (pageaddr = 0, npages = 0;
|
for (pageaddr = 0, npages = 0;
|
||||||
pageaddr < wsize;
|
pageaddr < (unsigned)wsize;
|
||||||
pageaddr += m->page_size) {
|
pageaddr += m->page_size) {
|
||||||
/* check whether this page must be written to */
|
/* check whether this page must be written to */
|
||||||
for (i = pageaddr;
|
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;
|
for (pageaddr = 0, failure = 0, nwritten = 0;
|
||||||
!failure && pageaddr < wsize;
|
!failure && pageaddr < (unsigned)wsize;
|
||||||
pageaddr += m->page_size) {
|
pageaddr += m->page_size) {
|
||||||
RETURN_IF_CANCEL();
|
RETURN_IF_CANCEL();
|
||||||
/* check whether this page must be written to */
|
/* 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;
|
page_tainted = 0;
|
||||||
flush_page = 0;
|
flush_page = 0;
|
||||||
|
|
||||||
for (i=0; i<wsize; i++) {
|
for (i = 0; i < (unsigned)wsize; i++) {
|
||||||
RETURN_IF_CANCEL();
|
RETURN_IF_CANCEL();
|
||||||
data = m->buf[i];
|
data = m->buf[i];
|
||||||
report_progress(i, wsize, NULL);
|
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);
|
avr910_set_addr(pgm, addr / rd_size);
|
||||||
|
|
||||||
while (addr < max_addr) {
|
while (addr < max_addr) {
|
||||||
if ((max_addr - addr) < blocksize) {
|
if ((max_addr - addr) < (unsigned)blocksize) {
|
||||||
blocksize = max_addr - addr;
|
blocksize = max_addr - addr;
|
||||||
}
|
}
|
||||||
cmd[1] = (blocksize >> 8) & 0xff;
|
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) {
|
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 };
|
std::string command_line { PACKAGE };
|
||||||
|
|
||||||
for (const auto &arg : args) {
|
for (const auto &arg : args) {
|
||||||
|
@ -105,7 +105,7 @@ int AvrDude::priv::run_one(const std::vector<std::string> &args) {
|
||||||
|
|
||||||
HandlerGuard guard(*this);
|
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());
|
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;
|
auto &message_fn = self->p->message_fn;
|
||||||
if (message_fn) {
|
if (message_fn) {
|
||||||
message_fn(msg, sizeof(msg));
|
message_fn(msg, sizeof(msg));
|
||||||
message_fn(what, std::strlen(what));
|
message_fn(what, (unsigned)std::strlen(what));
|
||||||
message_fn("\n", 1);
|
message_fn("\n", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ int avrdude_main(int argc, char * argv []);
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define strdup _strdup
|
||||||
|
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
#error "UNICODE should not be defined for avrdude bits on Windows"
|
#error "UNICODE should not be defined for avrdude bits on Windows"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -358,7 +358,7 @@ AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
||||||
int matches;
|
int matches;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
l = strlen(desc);
|
l = (int)strlen(desc);
|
||||||
matches = 0;
|
matches = 0;
|
||||||
match = NULL;
|
match = NULL;
|
||||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
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);
|
prefix);
|
||||||
|
|
||||||
px = prefix;
|
px = prefix;
|
||||||
i = strlen(prefix) + 5;
|
i = (int)strlen(prefix) + 5;
|
||||||
buf = (char *)malloc(i);
|
buf = (char *)malloc(i);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
/* ugh, this is not important enough to bail, just ignore it */
|
/* 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);
|
avrdude_message(MSG_DEBUG, "%s: buspirate_recv_bin():\n", progname);
|
||||||
dump_mem(MSG_DEBUG, buf, len);
|
dump_mem(MSG_DEBUG, buf, len);
|
||||||
|
|
||||||
return len;
|
return (int)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int buspirate_expect_bin(struct programmer_t *pgm,
|
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)
|
static int buspirate_is_prompt(const char *str)
|
||||||
{
|
{
|
||||||
int strlen_str = strlen(str);
|
int strlen_str = (int)strlen(str);
|
||||||
/* Prompt ends with '>' or '> '
|
/* Prompt ends with '>' or '> '
|
||||||
* all other input probably ends with '\n' */
|
* all other input probably ends with '\n' */
|
||||||
return (str[strlen_str - 1] == '>' || str[strlen_str - 2] == '>');
|
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);
|
butterfly_set_addr(pgm, addr / rd_size);
|
||||||
}
|
}
|
||||||
while (addr < max_addr) {
|
while (addr < max_addr) {
|
||||||
if ((max_addr - addr) < blocksize) {
|
if ((max_addr - addr) < (unsigned)blocksize) {
|
||||||
blocksize = max_addr - addr;
|
blocksize = max_addr - addr;
|
||||||
};
|
};
|
||||||
cmd[1] = (blocksize >> 8) & 0xff;
|
cmd[1] = (blocksize >> 8) & 0xff;
|
||||||
|
|
|
@ -6,36 +6,42 @@
|
||||||
|
|
||||||
int main(int argc, char const *argv[])
|
int main(int argc, char const *argv[])
|
||||||
{
|
{
|
||||||
if (argc != 3) {
|
if (argc != 4) {
|
||||||
std::cerr << "Usage: " << argv[0] << " <file> <symbol name>" << std::endl;
|
std::cerr << "Usage: " << argv[0] << " <file> <symbol name> <output file>" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* filename = argv[1];
|
const char* filename_in = argv[1];
|
||||||
const char* symbol = argv[2];
|
const char* symbol = argv[2];
|
||||||
|
const char* filename_out = argv[3];
|
||||||
|
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
std::fstream file(filename);
|
std::fstream file(filename_in, std::ios::in | std::ios::binary);
|
||||||
if (!file.good()) {
|
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::fstream output(filename_out, std::ios::out | std::ios::trunc);
|
||||||
std::cout << "unsigned char " << symbol << "[] = {";
|
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;
|
char c;
|
||||||
std::cout << std::hex;
|
output << std::hex;
|
||||||
std::cout.fill('0');
|
output.fill('0');
|
||||||
for (file.get(c); !file.eof(); size++, file.get(c)) {
|
for (file.get(c); !file.eof(); size++, file.get(c)) {
|
||||||
if (size % 12 == 0) { std::cout << "\n "; }
|
if (size % 12 == 0) { output << "\n "; }
|
||||||
std::cout << "0x" << std::setw(2) << (unsigned)c << ", ";
|
output << "0x" << std::setw(2) << (unsigned)c << ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "\n 0, 0\n};\n";
|
output << "\n 0, 0\n};\n";
|
||||||
|
|
||||||
std::cout << std::dec;
|
output << std::dec;
|
||||||
std::cout << "size_t " << symbol << "_size = " << size << ";" << std::endl;
|
output << "const size_t " << symbol << "_size = " << size << ";" << std::endl;
|
||||||
std::cout << "size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl;
|
output << "const size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,7 +240,7 @@ TOKEN * string(char * text)
|
||||||
return NULL; /* yyerror already called */
|
return NULL; /* yyerror already called */
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(text);
|
len = (int)strlen(text);
|
||||||
|
|
||||||
tkn->value.type = V_STR;
|
tkn->value.type = V_STR;
|
||||||
tkn->value.string = (char *) malloc(len+1);
|
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;
|
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);
|
extern void yy_delete_buffer(YY_BUFFER_STATE b);
|
||||||
|
|
||||||
int read_config_builtin()
|
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*
|
// 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
|
// 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) {
|
if (buffer == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: read_config_builtin: Failed to initialize parsing buffer\n", progname);
|
avrdude_message(MSG_INFO, "%s: read_config_builtin: Failed to initialize parsing buffer\n", progname);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -3640,7 +3640,7 @@ static int parse_cmdbits(OPCODE * op)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(s);
|
len = (int)strlen(s);
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
yyerror("invalid bit specifier \"\"");
|
yyerror("invalid bit specifier \"\"");
|
||||||
|
|
|
@ -1493,7 +1493,7 @@ static int parse_cmdbits(OPCODE * op)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(s);
|
len = (int)strlen(s);
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
yyerror("invalid bit specifier \"\"");
|
yyerror("invalid bit specifier \"\"");
|
||||||
|
|
|
@ -264,7 +264,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec)
|
||||||
unsigned char cksum;
|
unsigned char cksum;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
len = strlen(rec);
|
len = (int)strlen(rec);
|
||||||
offset = 1;
|
offset = 1;
|
||||||
cksum = 0;
|
cksum = 0;
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec)
|
||||||
for (i=0; i<2; i++)
|
for (i=0; i<2; i++)
|
||||||
buf[i] = rec[offset++];
|
buf[i] = rec[offset++];
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
ihex->reclen = strtoul(buf, &e, 16);
|
ihex->reclen = (unsigned char)strtoul(buf, &e, 16);
|
||||||
if (e == buf || *e != 0)
|
if (e == buf || *e != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec)
|
||||||
for (i=0; i<2; i++)
|
for (i=0; i<2; i++)
|
||||||
buf[i] = rec[offset++];
|
buf[i] = rec[offset++];
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
ihex->rectyp = strtoul(buf, &e, 16);
|
ihex->rectyp = (unsigned char)strtoul(buf, &e, 16);
|
||||||
if (e == buf || *e != 0)
|
if (e == buf || *e != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -308,7 +308,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec)
|
||||||
for (i=0; i<2; i++)
|
for (i=0; i<2; i++)
|
||||||
buf[i] = rec[offset++];
|
buf[i] = rec[offset++];
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
ihex->data[j] = strtoul(buf, &e, 16);
|
ihex->data[j] = (char)strtoul(buf, &e, 16);
|
||||||
if (e == buf || *e != 0)
|
if (e == buf || *e != 0)
|
||||||
return -1;
|
return -1;
|
||||||
cksum += ihex->data[j];
|
cksum += ihex->data[j];
|
||||||
|
@ -320,7 +320,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec)
|
||||||
for (i=0; i<2; i++)
|
for (i=0; i<2; i++)
|
||||||
buf[i] = rec[offset++];
|
buf[i] = rec[offset++];
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
ihex->cksum = strtoul(buf, &e, 16);
|
ihex->cksum = (char)strtoul(buf, &e, 16);
|
||||||
if (e == buf || *e != 0)
|
if (e == buf || *e != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -361,7 +361,7 @@ static int ihex2b(char * infile, FILE * inf,
|
||||||
|
|
||||||
while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) {
|
while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) {
|
||||||
lineno++;
|
lineno++;
|
||||||
len = strlen(buffer);
|
len = (int)strlen(buffer);
|
||||||
if (buffer[len-1] == '\n')
|
if (buffer[len-1] == '\n')
|
||||||
buffer[--len] = 0;
|
buffer[--len] = 0;
|
||||||
if (buffer[0] != ':')
|
if (buffer[0] != ':')
|
||||||
|
@ -388,7 +388,7 @@ static int ihex2b(char * infile, FILE * inf,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nextaddr = ihex.loadofs + baseaddr - fileoffset;
|
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",
|
avrdude_message(MSG_INFO, "%s: ERROR: address 0x%04x out of range at line %d of %s\n",
|
||||||
progname, nextaddr+ihex.reclen, lineno, infile);
|
progname, nextaddr+ihex.reclen, lineno, infile);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -502,10 +502,11 @@ static int b2srec(unsigned char * inbuf, int bufsize,
|
||||||
|
|
||||||
cksum += n + addr_width + 1;
|
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;
|
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]);
|
fprintf(outf, "%02X", buf[i]);
|
||||||
cksum += buf[i];
|
cksum += buf[i];
|
||||||
}
|
}
|
||||||
|
@ -562,7 +563,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec)
|
||||||
unsigned char cksum;
|
unsigned char cksum;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
len = strlen(rec);
|
len = (int)strlen(rec);
|
||||||
offset = 1;
|
offset = 1;
|
||||||
cksum = 0;
|
cksum = 0;
|
||||||
addr_width = 2;
|
addr_width = 2;
|
||||||
|
@ -582,7 +583,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec)
|
||||||
for (i=0; i<2; i++)
|
for (i=0; i<2; i++)
|
||||||
buf[i] = rec[offset++];
|
buf[i] = rec[offset++];
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
srec->reclen = strtoul(buf, &e, 16);
|
srec->reclen = (char)strtoul(buf, &e, 16);
|
||||||
cksum += srec->reclen;
|
cksum += srec->reclen;
|
||||||
srec->reclen -= (addr_width+1);
|
srec->reclen -= (addr_width+1);
|
||||||
if (e == buf || *e != 0)
|
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++)
|
for (i=0; i<addr_width*2; i++)
|
||||||
buf[i] = rec[offset++];
|
buf[i] = rec[offset++];
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
srec->loadofs = strtoull(buf, &e, 16);
|
srec->loadofs = strtoul(buf, &e, 16);
|
||||||
if (e == buf || *e != 0)
|
if (e == buf || *e != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -608,7 +609,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec)
|
||||||
for (i=0; i<2; i++)
|
for (i=0; i<2; i++)
|
||||||
buf[i] = rec[offset++];
|
buf[i] = rec[offset++];
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
srec->data[j] = strtoul(buf, &e, 16);
|
srec->data[j] = (char)strtoul(buf, &e, 16);
|
||||||
if (e == buf || *e != 0)
|
if (e == buf || *e != 0)
|
||||||
return -1;
|
return -1;
|
||||||
cksum += srec->data[j];
|
cksum += srec->data[j];
|
||||||
|
@ -620,7 +621,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec)
|
||||||
for (i=0; i<2; i++)
|
for (i=0; i<2; i++)
|
||||||
buf[i] = rec[offset++];
|
buf[i] = rec[offset++];
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
srec->cksum = strtoul(buf, &e, 16);
|
srec->cksum = (char)strtoul(buf, &e, 16);
|
||||||
if (e == buf || *e != 0)
|
if (e == buf || *e != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -650,7 +651,7 @@ static int srec2b(char * infile, FILE * inf,
|
||||||
|
|
||||||
while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) {
|
while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) {
|
||||||
lineno++;
|
lineno++;
|
||||||
len = strlen(buffer);
|
len = (int)strlen(buffer);
|
||||||
if (buffer[len-1] == '\n')
|
if (buffer[len-1] == '\n')
|
||||||
buffer[--len] = 0;
|
buffer[--len] = 0;
|
||||||
if (buffer[0] != 0x53)
|
if (buffer[0] != 0x53)
|
||||||
|
@ -729,7 +730,7 @@ static int srec2b(char * infile, FILE * inf,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nextaddr -= fileoffset;
|
nextaddr -= fileoffset;
|
||||||
if (nextaddr + srec.reclen > bufsize) {
|
if (nextaddr + srec.reclen > (unsigned)bufsize) {
|
||||||
avrdude_message(MSG_INFO, msg, progname, nextaddr+srec.reclen, "",
|
avrdude_message(MSG_INFO, msg, progname, nextaddr+srec.reclen, "",
|
||||||
lineno, infile);
|
lineno, infile);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -740,7 +741,7 @@ static int srec2b(char * infile, FILE * inf,
|
||||||
}
|
}
|
||||||
if (nextaddr+srec.reclen > maxaddr)
|
if (nextaddr+srec.reclen > maxaddr)
|
||||||
maxaddr = nextaddr+srec.reclen;
|
maxaddr = nextaddr+srec.reclen;
|
||||||
reccount++;
|
reccount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1143,12 +1144,12 @@ static int fileio_rbin(struct fioparms * fio,
|
||||||
|
|
||||||
switch (fio->op) {
|
switch (fio->op) {
|
||||||
case FIO_READ:
|
case FIO_READ:
|
||||||
rc = fread(buf, 1, size, f);
|
rc = (int)fread(buf, 1, size, f);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
memset(mem->tags, TAG_ALLOCATED, rc);
|
memset(mem->tags, TAG_ALLOCATED, rc);
|
||||||
break;
|
break;
|
||||||
case FIO_WRITE:
|
case FIO_WRITE:
|
||||||
rc = fwrite(buf, 1, size, f);
|
rc = (int)fwrite(buf, 1, size, f);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n",
|
avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n",
|
||||||
|
@ -1190,7 +1191,7 @@ static int fileio_imm(struct fioparms * fio,
|
||||||
progname, p);
|
progname, p);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mem->buf[loc] = b;
|
mem->buf[loc] = (char)b;
|
||||||
mem->tags[loc++] = TAG_ALLOCATED;
|
mem->tags[loc++] = TAG_ALLOCATED;
|
||||||
p = strtok(NULL, " ,");
|
p = strtok(NULL, " ,");
|
||||||
rc = loc;
|
rc = loc;
|
||||||
|
@ -1452,7 +1453,7 @@ static int fmt_autodetect(char * fname, unsigned section)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[MAX_LINE_LEN-1] = 0;
|
buf[MAX_LINE_LEN-1] = 0;
|
||||||
len = strlen((char *)buf);
|
len = (int)strlen((char *)buf);
|
||||||
if (buf[len-1] == '\n')
|
if (buf[len-1] == '\n')
|
||||||
buf[--len] = 0;
|
buf[--len] = 0;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
|
/* 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,
|
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
|
||||||
* if you want the limit (max/min) macros for int types.
|
* if you want the limit (max/min) macros for int types.
|
||||||
|
|
|
@ -444,7 +444,7 @@ lcreat ( void * liststruct, int elements )
|
||||||
l->poolsize = DEFAULT_POOLSIZE;
|
l->poolsize = DEFAULT_POOLSIZE;
|
||||||
}
|
}
|
||||||
else {
|
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);
|
l->n_ln_pool = (l->poolsize-sizeof(NODEPOOL))/sizeof(LISTNODE);
|
||||||
|
@ -803,7 +803,7 @@ lget_n ( LISTID lid, unsigned int n )
|
||||||
|
|
||||||
CKLMAGIC(l);
|
CKLMAGIC(l);
|
||||||
|
|
||||||
if ((n<1)||(n>lsize(l))) {
|
if ((n < 1) || (n > (unsigned)lsize(l))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,7 +844,7 @@ lget_ln ( LISTID lid, unsigned int n )
|
||||||
|
|
||||||
CKLMAGIC(l);
|
CKLMAGIC(l);
|
||||||
|
|
||||||
if ((n<1)||(n>lsize(l))) {
|
if ((n < 1) || (n > (unsigned)lsize(l))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,7 +941,7 @@ insert_ln ( LIST * l, LISTNODE * ln, void * data_ptr )
|
||||||
|
|
|
|
||||||
| Insert data before the nth item in the list.
|
| Insert data before the nth item in the list.
|
||||||
-----------------------------------------------------------------*/
|
-----------------------------------------------------------------*/
|
||||||
int
|
int
|
||||||
lins_n ( LISTID lid, void * data_ptr, unsigned int n )
|
lins_n ( LISTID lid, void * data_ptr, unsigned int n )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -952,7 +952,7 @@ lins_n ( LISTID lid, void * data_ptr, unsigned int n )
|
||||||
|
|
||||||
CKLMAGIC(l);
|
CKLMAGIC(l);
|
||||||
|
|
||||||
if ((n<1)||(n>(l->num+1))) {
|
if ((n < 1) || (n > (unsigned)(l->num+1))) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1193,7 +1193,7 @@ lrmv_n ( LISTID lid, unsigned int n )
|
||||||
|
|
||||||
CKLMAGIC(l);
|
CKLMAGIC(l);
|
||||||
|
|
||||||
if ((n<1)||(n>l->num)) {
|
if ((n < 1) || (n > (unsigned)l->num)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,10 @@ struct ArgvUtf8 : std::vector<char*>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
int wmain(int argc_w, wchar_t *argv_w[])
|
int wmain(int argc_w, wchar_t *argv_w[])
|
||||||
{
|
{
|
||||||
ArgvUtf8 argv_utf8(argc_w, 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) {
|
if (rc > 0 && rc < MSGBUFFER_SIZE) {
|
||||||
avrdude_message_handler(msgbuffer, rc, avrdude_message_handler_user_p);
|
avrdude_message_handler(msgbuffer, rc, avrdude_message_handler_user_p);
|
||||||
} else {
|
} 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
|
// #endif
|
||||||
|
|
||||||
len = strlen(progname) + 2;
|
len = (int)strlen(progname) + 2;
|
||||||
for (i=0; i<len; i++)
|
for (i=0; i<len; i++)
|
||||||
progbuf[i] = ' ';
|
progbuf[i] = ' ';
|
||||||
progbuf[i] = 0;
|
progbuf[i] = 0;
|
||||||
|
@ -601,7 +601,7 @@ int avrdude_main(int argc, char * argv [])
|
||||||
bitclock = strtod(optarg, &e);
|
bitclock = strtod(optarg, &e);
|
||||||
if (*e != 0) {
|
if (*e != 0) {
|
||||||
/* trailing unit of measure present */
|
/* trailing unit of measure present */
|
||||||
int suffixlen = strlen(e);
|
size_t suffixlen = strlen(e);
|
||||||
switch (suffixlen) {
|
switch (suffixlen) {
|
||||||
case 2:
|
case 2:
|
||||||
if ((e[0] != 'h' && e[0] != 'H') || e[1] != 'z')
|
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
|
* @param[in] size the number of entries in checklist
|
||||||
* @returns 0 if all pin definitions are valid, -1 otherwise
|
* @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
|
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 rv = 0; // return value
|
||||||
int pinname; // loop counter through pinnames
|
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) {
|
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||||
const char *error = last_error_string(0);
|
const char *error = last_error_string(0);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n", progname, port, error);
|
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n", progname, port, error);
|
||||||
free(error);
|
free((char *)error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,10 +460,10 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
|
|
||||||
serial_w32SetTimeOut(hComPort,500);
|
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);
|
const char *error = last_error_string(0);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, error);
|
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, error);
|
||||||
free(error);
|
free((char *)error);
|
||||||
return -1;
|
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);
|
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);
|
const char *error = last_error_string(0);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
|
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
|
||||||
free(error);
|
free((char *)error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +642,7 @@ static int ser_drain(union filedescriptor *fd, int display)
|
||||||
if (!readres) {
|
if (!readres) {
|
||||||
const char *error = last_error_string(0);
|
const char *error = last_error_string(0);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, error);
|
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, error);
|
||||||
free(error);
|
free((char *)error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -308,8 +308,8 @@ static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||||
progname, port);
|
progname, port);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_DEBUG, "%s: ser_open(): opened comm port \"%s\", handle 0x%x\n",
|
avrdude_message(MSG_DEBUG, "%s: ser_open(): opened comm port \"%s\", handle %p\n",
|
||||||
progname, port, (int)hComPort);
|
progname, port, (void *)hComPort);
|
||||||
|
|
||||||
pgm->fd.pfd = (void *)hComPort;
|
pgm->fd.pfd = (void *)hComPort;
|
||||||
|
|
||||||
|
@ -326,8 +326,8 @@ static void serbb_close(PROGRAMMER *pgm)
|
||||||
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
||||||
CloseHandle (hComPort);
|
CloseHandle (hComPort);
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_DEBUG, "%s: ser_close(): closed comm port handle 0x%x\n",
|
avrdude_message(MSG_DEBUG, "%s: ser_close(): closed comm port handle %p\n",
|
||||||
progname, (int)hComPort);
|
progname, (void *)hComPort);
|
||||||
|
|
||||||
hComPort = INVALID_HANDLE_VALUE;
|
hComPort = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -504,7 +504,7 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buf[9] = 0xff;
|
buf[9] = 0xff;
|
||||||
buf[10] = 0xff;
|
buf[10] = 0xff;
|
||||||
buf[13] = 0;
|
buf[13] = 0;
|
||||||
buf[14] = 0;
|
buf[14] = 0;
|
||||||
buf[17] = 0;
|
buf[17] = 0;
|
||||||
|
@ -821,7 +821,7 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
break;
|
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
|
/* build command block and avoid multiple send commands as it leads to a crash
|
||||||
of the silabs usb serial driver on mac os x */
|
of the silabs usb serial driver on mac os x */
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -834,7 +834,7 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
buf[i++] = block_size & 0x0f;
|
buf[i++] = block_size & 0x0f;
|
||||||
buf[i++] = memtype;
|
buf[i++] = memtype;
|
||||||
if (has_semicolon) {
|
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];
|
buf[i] = m->buf[addr + j];
|
||||||
if (buf[i] == ';')
|
if (buf[i] == ';')
|
||||||
buf[i] |= (prusa3d_semicolon_workaround_round ? 0xf0 : 0x0f);
|
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;
|
min = 8.0 / STK500_XTAL;
|
||||||
max = 255 * min;
|
max = 255 * min;
|
||||||
dur = v / min + 0.5;
|
dur = (int)(v / min + 0.5);
|
||||||
|
|
||||||
if (v < min) {
|
if (v < min) {
|
||||||
dur = 1;
|
dur = 1;
|
||||||
avrdude_message(MSG_INFO, "%s: stk500_set_sck_period(): p = %.1f us too small, using %.1f us\n",
|
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",
|
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);
|
progname, v / 1e-6, dur * min / 1e-6);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur);
|
return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,58 +130,58 @@ struct jtagispentry
|
||||||
#define SZ_SPI_MULTI (USHRT_MAX - 1)
|
#define SZ_SPI_MULTI (USHRT_MAX - 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct jtagispentry jtagispcmds[] = {
|
// static const struct jtagispentry jtagispcmds[] = {
|
||||||
/* generic */
|
// /* generic */
|
||||||
{ CMD_SET_PARAMETER, 2 },
|
// { CMD_SET_PARAMETER, 2 },
|
||||||
{ CMD_GET_PARAMETER, 3 },
|
// { CMD_GET_PARAMETER, 3 },
|
||||||
{ CMD_OSCCAL, 2 },
|
// { CMD_OSCCAL, 2 },
|
||||||
{ CMD_LOAD_ADDRESS, 2 },
|
// { CMD_LOAD_ADDRESS, 2 },
|
||||||
/* ISP mode */
|
// /* ISP mode */
|
||||||
{ CMD_ENTER_PROGMODE_ISP, 2 },
|
// { CMD_ENTER_PROGMODE_ISP, 2 },
|
||||||
{ CMD_LEAVE_PROGMODE_ISP, 2 },
|
// { CMD_LEAVE_PROGMODE_ISP, 2 },
|
||||||
{ CMD_CHIP_ERASE_ISP, 2 },
|
// { CMD_CHIP_ERASE_ISP, 2 },
|
||||||
{ CMD_PROGRAM_FLASH_ISP, 2 },
|
// { CMD_PROGRAM_FLASH_ISP, 2 },
|
||||||
{ CMD_READ_FLASH_ISP, SZ_READ_FLASH_EE },
|
// { CMD_READ_FLASH_ISP, SZ_READ_FLASH_EE },
|
||||||
{ CMD_PROGRAM_EEPROM_ISP, 2 },
|
// { CMD_PROGRAM_EEPROM_ISP, 2 },
|
||||||
{ CMD_READ_EEPROM_ISP, SZ_READ_FLASH_EE },
|
// { CMD_READ_EEPROM_ISP, SZ_READ_FLASH_EE },
|
||||||
{ CMD_PROGRAM_FUSE_ISP, 3 },
|
// { CMD_PROGRAM_FUSE_ISP, 3 },
|
||||||
{ CMD_READ_FUSE_ISP, 4 },
|
// { CMD_READ_FUSE_ISP, 4 },
|
||||||
{ CMD_PROGRAM_LOCK_ISP, 3 },
|
// { CMD_PROGRAM_LOCK_ISP, 3 },
|
||||||
{ CMD_READ_LOCK_ISP, 4 },
|
// { CMD_READ_LOCK_ISP, 4 },
|
||||||
{ CMD_READ_SIGNATURE_ISP, 4 },
|
// { CMD_READ_SIGNATURE_ISP, 4 },
|
||||||
{ CMD_READ_OSCCAL_ISP, 4 },
|
// { CMD_READ_OSCCAL_ISP, 4 },
|
||||||
{ CMD_SPI_MULTI, SZ_SPI_MULTI },
|
// { CMD_SPI_MULTI, SZ_SPI_MULTI },
|
||||||
/* all HV modes */
|
// /* all HV modes */
|
||||||
{ CMD_SET_CONTROL_STACK, 2 },
|
// { CMD_SET_CONTROL_STACK, 2 },
|
||||||
/* HVSP mode */
|
// /* HVSP mode */
|
||||||
{ CMD_ENTER_PROGMODE_HVSP, 2 },
|
// { CMD_ENTER_PROGMODE_HVSP, 2 },
|
||||||
{ CMD_LEAVE_PROGMODE_HVSP, 2 },
|
// { CMD_LEAVE_PROGMODE_HVSP, 2 },
|
||||||
{ CMD_CHIP_ERASE_HVSP, 2 },
|
// { CMD_CHIP_ERASE_HVSP, 2 },
|
||||||
{ CMD_PROGRAM_FLASH_HVSP, 2 },
|
// { CMD_PROGRAM_FLASH_HVSP, 2 },
|
||||||
{ CMD_READ_FLASH_HVSP, SZ_READ_FLASH_EE },
|
// { CMD_READ_FLASH_HVSP, SZ_READ_FLASH_EE },
|
||||||
{ CMD_PROGRAM_EEPROM_HVSP, 2 },
|
// { CMD_PROGRAM_EEPROM_HVSP, 2 },
|
||||||
{ CMD_READ_EEPROM_HVSP, SZ_READ_FLASH_EE },
|
// { CMD_READ_EEPROM_HVSP, SZ_READ_FLASH_EE },
|
||||||
{ CMD_PROGRAM_FUSE_HVSP, 2 },
|
// { CMD_PROGRAM_FUSE_HVSP, 2 },
|
||||||
{ CMD_READ_FUSE_HVSP, 3 },
|
// { CMD_READ_FUSE_HVSP, 3 },
|
||||||
{ CMD_PROGRAM_LOCK_HVSP, 2 },
|
// { CMD_PROGRAM_LOCK_HVSP, 2 },
|
||||||
{ CMD_READ_LOCK_HVSP, 3 },
|
// { CMD_READ_LOCK_HVSP, 3 },
|
||||||
{ CMD_READ_SIGNATURE_HVSP, 3 },
|
// { CMD_READ_SIGNATURE_HVSP, 3 },
|
||||||
{ CMD_READ_OSCCAL_HVSP, 3 },
|
// { CMD_READ_OSCCAL_HVSP, 3 },
|
||||||
/* PP mode */
|
// /* PP mode */
|
||||||
{ CMD_ENTER_PROGMODE_PP, 2 },
|
// { CMD_ENTER_PROGMODE_PP, 2 },
|
||||||
{ CMD_LEAVE_PROGMODE_PP, 2 },
|
// { CMD_LEAVE_PROGMODE_PP, 2 },
|
||||||
{ CMD_CHIP_ERASE_PP, 2 },
|
// { CMD_CHIP_ERASE_PP, 2 },
|
||||||
{ CMD_PROGRAM_FLASH_PP, 2 },
|
// { CMD_PROGRAM_FLASH_PP, 2 },
|
||||||
{ CMD_READ_FLASH_PP, SZ_READ_FLASH_EE },
|
// { CMD_READ_FLASH_PP, SZ_READ_FLASH_EE },
|
||||||
{ CMD_PROGRAM_EEPROM_PP, 2 },
|
// { CMD_PROGRAM_EEPROM_PP, 2 },
|
||||||
{ CMD_READ_EEPROM_PP, SZ_READ_FLASH_EE },
|
// { CMD_READ_EEPROM_PP, SZ_READ_FLASH_EE },
|
||||||
{ CMD_PROGRAM_FUSE_PP, 2 },
|
// { CMD_PROGRAM_FUSE_PP, 2 },
|
||||||
{ CMD_READ_FUSE_PP, 3 },
|
// { CMD_READ_FUSE_PP, 3 },
|
||||||
{ CMD_PROGRAM_LOCK_PP, 2 },
|
// { CMD_PROGRAM_LOCK_PP, 2 },
|
||||||
{ CMD_READ_LOCK_PP, 3 },
|
// { CMD_READ_LOCK_PP, 3 },
|
||||||
{ CMD_READ_SIGNATURE_PP, 3 },
|
// { CMD_READ_SIGNATURE_PP, 3 },
|
||||||
{ CMD_READ_OSCCAL_PP, 3 },
|
// { CMD_READ_OSCCAL_PP, 3 },
|
||||||
};
|
// };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From XML file:
|
* From XML file:
|
||||||
|
@ -379,15 +379,15 @@ static void stk500v2_jtag3_teardown(PROGRAMMER * pgm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned short
|
// static unsigned short
|
||||||
b2_to_u16(unsigned char *b)
|
// b2_to_u16(unsigned char *b)
|
||||||
{
|
// {
|
||||||
unsigned short l;
|
// unsigned short l;
|
||||||
l = b[0];
|
// l = b[0];
|
||||||
l += (unsigned)b[1] << 8;
|
// l += (unsigned)b[1] << 8;
|
||||||
|
|
||||||
return l;
|
// return l;
|
||||||
}
|
// }
|
||||||
|
|
||||||
static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned short get_jtagisp_return_size(unsigned char cmd)
|
// static unsigned short get_jtagisp_return_size(unsigned char cmd)
|
||||||
{
|
// {
|
||||||
int i;
|
// int i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof jtagispcmds / sizeof jtagispcmds[0]; i++)
|
// for (i = 0; i < sizeof jtagispcmds / sizeof jtagispcmds[0]; i++)
|
||||||
if (jtagispcmds[i].cmd == cmd)
|
// if (jtagispcmds[i].cmd == cmd)
|
||||||
return jtagispcmds[i].size;
|
// return jtagispcmds[i].size;
|
||||||
|
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send the data as a JTAG ICE mkII encapsulated ISP packet.
|
* 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[0] = MESSAGE_START;
|
||||||
buf[1] = PDATA(pgm)->command_sequence;
|
buf[1] = PDATA(pgm)->command_sequence;
|
||||||
buf[2] = len / 256;
|
buf[2] = (char)(len / 256);
|
||||||
buf[3] = len % 256;
|
buf[3] = len % 256;
|
||||||
buf[4] = TOKEN;
|
buf[4] = TOKEN;
|
||||||
memcpy(buf+5, data, len);
|
memcpy(buf+5, data, len);
|
||||||
|
@ -1128,7 +1128,8 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
{
|
{
|
||||||
unsigned char buf[16];
|
unsigned char buf[16];
|
||||||
char msg[100]; /* see remarks above about size needed */
|
char msg[100]; /* see remarks above about size needed */
|
||||||
int rv, tries;
|
int rv;
|
||||||
|
// int tries;
|
||||||
|
|
||||||
PDATA(pgm)->lastpart = p;
|
PDATA(pgm)->lastpart = p;
|
||||||
|
|
||||||
|
@ -1143,7 +1144,7 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
/* Activate AVR-style (low active) RESET */
|
/* Activate AVR-style (low active) RESET */
|
||||||
stk500v2_setparm_real(pgm, PARAM_RESET_POLARITY, 0x01);
|
stk500v2_setparm_real(pgm, PARAM_RESET_POLARITY, 0x01);
|
||||||
|
|
||||||
tries = 0;
|
// tries = 0;
|
||||||
// retry:
|
// retry:
|
||||||
buf[0] = CMD_ENTER_PROGMODE_ISP;
|
buf[0] = CMD_ENTER_PROGMODE_ISP;
|
||||||
buf[1] = p->timeout;
|
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)
|
if (stk500v2_loadaddr(pgm, use_ext_addr | (paddr >> addrshift)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
buf[1] = addr;
|
buf[1] = (char)addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: stk500hv_read_byte(): Sending read memory command: ",
|
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)
|
if (stk500v2_loadaddr(pgm, use_ext_addr | (paddr >> addrshift)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
buf[1] = addr;
|
buf[1] = (char)addr;
|
||||||
buf[2] = data;
|
buf[2] = data;
|
||||||
if (mode == PPMODE) {
|
if (mode == PPMODE) {
|
||||||
buf[3] = pulsewidth;
|
buf[3] = pulsewidth;
|
||||||
|
@ -2298,7 +2299,7 @@ static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
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 block_size, last_addr, addrshift, use_ext_addr;
|
||||||
unsigned int maxaddr = addr + n_bytes;
|
unsigned int maxaddr = addr + n_bytes;
|
||||||
unsigned char commandbuf[10];
|
unsigned char commandbuf[10];
|
||||||
|
@ -2833,10 +2834,10 @@ static int stk500v2_set_fosc(PROGRAMMER * pgm, double v)
|
||||||
progname, v, unit, STK500V2_XTAL / 2e6);
|
progname, v, unit, STK500V2_XTAL / 2e6);
|
||||||
fosc = STK500V2_XTAL / 2;
|
fosc = STK500V2_XTAL / 2;
|
||||||
} else
|
} else
|
||||||
fosc = (unsigned)v;
|
fosc = (int)v;
|
||||||
|
|
||||||
for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) {
|
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 */
|
/* this prescaler value can handle our frequency */
|
||||||
prescale = idx + 1;
|
prescale = idx + 1;
|
||||||
cmatch = (unsigned)(STK500V2_XTAL / (2 * fosc * ps[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;
|
unsigned int oct, dac;
|
||||||
|
|
||||||
oct = 1.443 * log(v / 1039.0);
|
oct = (unsigned)(1.443 * log(v / 1039.0));
|
||||||
dac = 2048 - (2078.0 * pow(2, (double)(10 + oct))) / v;
|
dac = (unsigned)(2048.0 - (2078.0 * pow(2, (double)(10 + oct))) / v);
|
||||||
|
|
||||||
return stk500v2_setparm2(pgm, PARAM2_CLOCK_CONF, (oct << 12) | (dac << 2));
|
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;
|
unsigned int sck;
|
||||||
|
|
||||||
sck = ceil((16e6 / (2 * 1.0 / v)) - 1);
|
sck = (unsigned)ceil((16e6 / (2 * 1.0 / v)) - 1);
|
||||||
|
|
||||||
if (sck >= 4096)
|
if (sck >= 4096)
|
||||||
sck = 4095;
|
sck = 4095;
|
||||||
|
@ -3093,7 +3094,7 @@ static int stk500v2_jtag3_set_sck_period(PROGRAMMER * pgm, double v)
|
||||||
else if (v > 1E-3)
|
else if (v > 1E-3)
|
||||||
sck = 1;
|
sck = 1;
|
||||||
else
|
else
|
||||||
sck = 1.0 / (1000.0 * v);
|
sck = (unsigned)(1.0 / (1000.0 * v));
|
||||||
|
|
||||||
value[0] = CMD_SET_SCK;
|
value[0] = CMD_SET_SCK;
|
||||||
value[1] = sck & 0xff;
|
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)
|
static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value)
|
||||||
{
|
{
|
||||||
unsigned char current_value;
|
unsigned char current_value = 0;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = stk500v2_getparm(pgm, parm, ¤t_value);
|
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)
|
static void stk500v2_display(PROGRAMMER * pgm, const char * p)
|
||||||
{
|
{
|
||||||
unsigned char maj, min, hdw, topcard, maj_s1, min_s1, maj_s2, min_s2;
|
unsigned char maj = 0;
|
||||||
unsigned int rev;
|
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;
|
const char *topcard_name, *pgmname;
|
||||||
|
|
||||||
switch (PDATA(pgm)->pgmtype) {
|
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)
|
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 char vtarget = 0;
|
||||||
unsigned int sck_stk600, clock_conf, dac, oct, varef;
|
unsigned char vadjust = 0;
|
||||||
unsigned char vtarget_jtag[4];
|
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;
|
int prescale;
|
||||||
double f;
|
double f;
|
||||||
const char *unit;
|
const char *unit;
|
||||||
void *mycookie;
|
// void *mycookie;
|
||||||
|
|
||||||
if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) {
|
if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) {
|
||||||
return;
|
return;
|
||||||
|
@ -3963,10 +3978,10 @@ static int stk600_xprog_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
b[0] = XPRG_CMD_WRITE_MEM;
|
b[0] = XPRG_CMD_WRITE_MEM;
|
||||||
b[1] = memcode;
|
b[1] = memcode;
|
||||||
b[2] = 0; /* pagemode: non-paged write */
|
b[2] = 0; /* pagemode: non-paged write */
|
||||||
b[3] = addr >> 24;
|
b[3] = (char)(addr >> 24);
|
||||||
b[4] = addr >> 16;
|
b[4] = (char)(addr >> 16);
|
||||||
b[5] = addr >> 8;
|
b[5] = (char)(addr >> 8);
|
||||||
b[6] = addr;
|
b[6] = (char)addr;
|
||||||
b[7] = 0;
|
b[7] = 0;
|
||||||
b[8] = write_size;
|
b[8] = write_size;
|
||||||
b[9] = data;
|
b[9] = data;
|
||||||
|
@ -4011,10 +4026,10 @@ static int stk600_xprog_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
addr += mem->offset;
|
addr += mem->offset;
|
||||||
|
|
||||||
b[0] = XPRG_CMD_READ_MEM;
|
b[0] = XPRG_CMD_READ_MEM;
|
||||||
b[2] = addr >> 24;
|
b[2] = (char)(addr >> 24);
|
||||||
b[3] = addr >> 16;
|
b[3] = (char)(addr >> 16);
|
||||||
b[4] = addr >> 8;
|
b[4] = (char)(addr >> 8);
|
||||||
b[5] = addr;
|
b[5] = (char)addr;
|
||||||
b[6] = 0;
|
b[6] = 0;
|
||||||
b[7] = 1;
|
b[7] = 1;
|
||||||
if (stk600_xprog_command(pgm, b, 8, 3) < 0) {
|
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;
|
maxsize = mem->size;
|
||||||
|
|
||||||
if (addr >= maxsize) {
|
if (addr >= (unsigned long)maxsize) {
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
/* wrap around */
|
/* wrap around */
|
||||||
addr = 0;
|
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 */
|
/* 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;
|
len = maxsize - addr;
|
||||||
|
|
||||||
buf = malloc(len);
|
buf = malloc(len);
|
||||||
|
@ -303,7 +303,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
|
||||||
return -1;
|
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]);
|
rc = pgm->read_byte(pgm, p, mem, addr+i, &buf[i]);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
avrdude_message(MSG_INFO, "error reading %s address 0x%05lx of part %s\n",
|
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;
|
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",
|
avrdude_message(MSG_INFO, "%s (write): address 0x%05lx is out of range for %s memory\n",
|
||||||
progname, addr, memtype);
|
progname, addr, memtype);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -373,7 +373,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
||||||
/* number of bytes to write at the specified address */
|
/* number of bytes to write at the specified address */
|
||||||
len = argc - 3;
|
len = argc - 3;
|
||||||
|
|
||||||
if ((addr + len) > maxsize) {
|
if ((addr + len) > (unsigned long)maxsize) {
|
||||||
avrdude_message(MSG_INFO, "%s (write): selected address and # bytes exceed "
|
avrdude_message(MSG_INFO, "%s (write): selected address and # bytes exceed "
|
||||||
"range for %s memory\n",
|
"range for %s memory\n",
|
||||||
progname, memtype);
|
progname, memtype);
|
||||||
|
@ -386,8 +386,8 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=3; i<argc; i++) {
|
for (i = 3; i < (unsigned long)argc; i++) {
|
||||||
buf[i-3] = strtoul(argv[i], &e, 0);
|
buf[i-3] = (char)strtoul(argv[i], &e, 0);
|
||||||
if (*e || (e == argv[i])) {
|
if (*e || (e == argv[i])) {
|
||||||
avrdude_message(MSG_INFO, "%s (write): can't parse byte \"%s\"\n",
|
avrdude_message(MSG_INFO, "%s (write): can't parse byte \"%s\"\n",
|
||||||
progname, argv[i]);
|
progname, argv[i]);
|
||||||
|
@ -397,7 +397,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
||||||
}
|
}
|
||||||
|
|
||||||
pgm->err_led(pgm, OFF);
|
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]);
|
rc = avr_write_byte(pgm, p, mem, addr+i, buf[i]);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -462,7 +462,7 @@ static int cmd_send(PROGRAMMER * pgm, struct avrpart * p,
|
||||||
|
|
||||||
/* load command bytes */
|
/* load command bytes */
|
||||||
for (i=1; i<argc; i++) {
|
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])) {
|
if (*e || (e == argv[i])) {
|
||||||
avrdude_message(MSG_INFO, "%s (send): can't parse byte \"%s\"\n",
|
avrdude_message(MSG_INFO, "%s (send): can't parse byte \"%s\"\n",
|
||||||
progname, argv[i]);
|
progname, argv[i]);
|
||||||
|
@ -789,7 +789,7 @@ static int tokenize(char * s, char *** argv)
|
||||||
char * nbuf;
|
char * nbuf;
|
||||||
char ** av;
|
char ** av;
|
||||||
|
|
||||||
slen = strlen(s);
|
slen = (int)strlen(s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize allow for 20 arguments, use realloc to grow this if
|
* 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);
|
nexttok(r, &q, &r);
|
||||||
strcpy(nbuf, q);
|
strcpy(nbuf, q);
|
||||||
bufv[n] = nbuf;
|
bufv[n] = nbuf;
|
||||||
len = strlen(q);
|
len = (int)strlen(q);
|
||||||
l += len + 1;
|
l += len + 1;
|
||||||
nbuf += len + 1;
|
nbuf += len + 1;
|
||||||
nbuf[0] = 0;
|
nbuf[0] = 0;
|
||||||
|
@ -841,7 +841,7 @@ static int tokenize(char * s, char *** argv)
|
||||||
q = (char *)&av[n+1];
|
q = (char *)&av[n+1];
|
||||||
memcpy(q, buf, l);
|
memcpy(q, buf, l);
|
||||||
for (i=0; i<n; i++) {
|
for (i=0; i<n; i++) {
|
||||||
offset = bufv[i] - buf;
|
offset = (int)(bufv[i] - buf);
|
||||||
av[i] = q + offset;
|
av[i] = q + offset;
|
||||||
}
|
}
|
||||||
av[i] = NULL;
|
av[i] = NULL;
|
||||||
|
@ -862,7 +862,7 @@ static int do_cmd(PROGRAMMER * pgm, struct avrpart * p,
|
||||||
int hold;
|
int hold;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = strlen(argv[0]);
|
len = (int)strlen(argv[0]);
|
||||||
hold = -1;
|
hold = -1;
|
||||||
for (i=0; i<NCMDS; i++) {
|
for (i=0; i<NCMDS; i++) {
|
||||||
if (strcasecmp(argv[0], cmd[i].name) == 0) {
|
if (strcasecmp(argv[0], cmd[i].name) == 0) {
|
||||||
|
|
|
@ -63,10 +63,15 @@ extern "C" {
|
||||||
#define STDOUT_FILENO 1
|
#define STDOUT_FILENO 1
|
||||||
#define STDERR_FILENO 2
|
#define STDERR_FILENO 2
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(__clang__)
|
||||||
|
#include <stdint.h>
|
||||||
|
struct timezone;
|
||||||
|
struct timeval;
|
||||||
|
#else
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
/* should be in some equivalent to <sys/types.h> */
|
/* should be in some equivalent to <sys/types.h> */
|
||||||
typedef __int8 int8_t;
|
typedef __int8 int8_t;
|
||||||
typedef __int16 int16_t;
|
typedef __int16 int16_t;
|
||||||
typedef __int32 int32_t;
|
typedef __int32 int32_t;
|
||||||
typedef __int64 int64_t;
|
typedef __int64 int64_t;
|
||||||
typedef unsigned __int8 uint8_t;
|
typedef unsigned __int8 uint8_t;
|
||||||
|
@ -74,6 +79,7 @@ typedef unsigned __int16 uint16_t;
|
||||||
typedef unsigned __int32 uint32_t;
|
typedef unsigned __int32 uint32_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int usleep(unsigned usec);
|
int usleep(unsigned usec);
|
||||||
|
|
|
@ -19,6 +19,6 @@ add_library(nowide STATIC
|
||||||
nowide/windows.hpp
|
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
|
#ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
|
||||||
return from - save_from;
|
return from - save_from;
|
||||||
#else
|
#else
|
||||||
return save_max - max;
|
return int(save_max - max);
|
||||||
#endif
|
#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()
|