mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 00:37:51 -06:00
Fixed conflicts after merge with master
This commit is contained in:
commit
a624590b36
117 changed files with 6769 additions and 1131 deletions
|
@ -191,6 +191,7 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP
|
||||||
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
|
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
|
||||||
|
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=address")
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lasan")
|
||||||
|
@ -255,7 +256,8 @@ 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)
|
set(_boost_components "system;filesystem;thread;log;locale;regex")
|
||||||
|
find_package(Boost ${MINIMUM_BOOST_VERSION} REQUIRED COMPONENTS ${_boost_components})
|
||||||
|
|
||||||
add_library(boost_libs INTERFACE)
|
add_library(boost_libs INTERFACE)
|
||||||
add_library(boost_headeronly INTERFACE)
|
add_library(boost_headeronly INTERFACE)
|
||||||
|
@ -269,23 +271,41 @@ if(NOT SLIC3R_STATIC)
|
||||||
target_compile_definitions(boost_headeronly INTERFACE BOOST_LOG_DYN_LINK)
|
target_compile_definitions(boost_headeronly INTERFACE BOOST_LOG_DYN_LINK)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
function(slic3r_remap_configs targets from_Cfg to_Cfg)
|
||||||
|
if(MSVC)
|
||||||
|
string(TOUPPER ${from_Cfg} from_CFG)
|
||||||
|
|
||||||
|
foreach(tgt ${targets})
|
||||||
|
if(TARGET ${tgt})
|
||||||
|
set_target_properties(${tgt} PROPERTIES MAP_IMPORTED_CONFIG_${from_CFG} ${to_Cfg})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
if(TARGET Boost::system)
|
if(TARGET Boost::system)
|
||||||
message(STATUS "Boost::boost exists")
|
message(STATUS "Boost::boost exists")
|
||||||
target_link_libraries(boost_headeronly INTERFACE Boost::boost)
|
target_link_libraries(boost_headeronly INTERFACE Boost::boost)
|
||||||
|
|
||||||
|
# Only from cmake 3.12
|
||||||
|
# list(TRANSFORM _boost_components PREPEND Boost:: OUTPUT_VARIABLE _boost_targets)
|
||||||
|
set(_boost_targets "")
|
||||||
|
foreach(comp ${_boost_components})
|
||||||
|
list(APPEND _boost_targets "Boost::${comp}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
target_link_libraries(boost_libs INTERFACE
|
target_link_libraries(boost_libs INTERFACE
|
||||||
boost_headeronly # includes the custom compile definitions as well
|
boost_headeronly # includes the custom compile definitions as well
|
||||||
Boost::system
|
${_boost_targets}
|
||||||
Boost::filesystem
|
|
||||||
Boost::thread
|
|
||||||
Boost::log
|
|
||||||
Boost::locale
|
|
||||||
Boost::regex
|
|
||||||
)
|
)
|
||||||
|
slic3r_remap_configs("${_boost_targets}" RelWithDebInfo Release)
|
||||||
else()
|
else()
|
||||||
target_include_directories(boost_headeronly INTERFACE ${Boost_INCLUDE_DIRS})
|
target_include_directories(boost_headeronly INTERFACE ${Boost_INCLUDE_DIRS})
|
||||||
target_link_libraries(boost_libs INTERFACE boost_headeronly ${Boost_LIBRARIES})
|
target_link_libraries(boost_libs INTERFACE boost_headeronly ${Boost_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Find and configure intel-tbb
|
# Find and configure intel-tbb
|
||||||
if(SLIC3R_STATIC)
|
if(SLIC3R_STATIC)
|
||||||
set(TBB_STATIC 1)
|
set(TBB_STATIC 1)
|
||||||
|
@ -378,6 +398,14 @@ add_custom_target(pot
|
||||||
|
|
||||||
find_package(NLopt 1.4 REQUIRED)
|
find_package(NLopt 1.4 REQUIRED)
|
||||||
|
|
||||||
|
if(SLIC3R_STATIC)
|
||||||
|
set(OPENVDB_USE_STATIC_LIBS ON)
|
||||||
|
set(USE_BLOSC TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#find_package(OpenVDB 5.0 COMPONENTS openvdb)
|
||||||
|
#slic3r_remap_configs(IlmBase::Half RelWithDebInfo Release)
|
||||||
|
|
||||||
# libslic3r, PrusaSlicer GUI and the PrusaSlicer executable.
|
# libslic3r, PrusaSlicer GUI and the PrusaSlicer executable.
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT PrusaSlicer_app_console)
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT PrusaSlicer_app_console)
|
||||||
|
|
490
cmake/modules/FindOpenVDB.cmake
Normal file
490
cmake/modules/FindOpenVDB.cmake
Normal file
|
@ -0,0 +1,490 @@
|
||||||
|
# Copyright (c) DreamWorks Animation LLC
|
||||||
|
#
|
||||||
|
# All rights reserved. This software is distributed under the
|
||||||
|
# Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
|
||||||
|
#
|
||||||
|
# Redistributions of source code must retain the above copyright
|
||||||
|
# and license notice and the following restrictions and disclaimer.
|
||||||
|
#
|
||||||
|
# * Neither the name of DreamWorks Animation nor the names of
|
||||||
|
# its contributors may be used to endorse or promote products derived
|
||||||
|
# from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
|
||||||
|
# LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
|
||||||
|
#
|
||||||
|
#[=======================================================================[.rst:
|
||||||
|
|
||||||
|
FindOpenVDB
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Find OpenVDB include dirs, libraries and settings
|
||||||
|
|
||||||
|
Use this module by invoking find_package with the form::
|
||||||
|
|
||||||
|
find_package(OpenVDB
|
||||||
|
[version] [EXACT] # Minimum or EXACT version
|
||||||
|
[REQUIRED] # Fail with error if OpenVDB is not found
|
||||||
|
[COMPONENTS <libs>...] # OpenVDB libraries by their canonical name
|
||||||
|
# e.g. "openvdb" for "libopenvdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
IMPORTED Targets
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
``OpenVDB::openvdb``
|
||||||
|
The core openvdb library target.
|
||||||
|
|
||||||
|
Result Variables
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This will define the following variables:
|
||||||
|
|
||||||
|
``OpenVDB_FOUND``
|
||||||
|
True if the system has the OpenVDB library.
|
||||||
|
``OpenVDB_VERSION``
|
||||||
|
The version of the OpenVDB library which was found.
|
||||||
|
``OpenVDB_INCLUDE_DIRS``
|
||||||
|
Include directories needed to use OpenVDB.
|
||||||
|
``OpenVDB_LIBRARIES``
|
||||||
|
Libraries needed to link to OpenVDB.
|
||||||
|
``OpenVDB_LIBRARY_DIRS``
|
||||||
|
OpenVDB library directories.
|
||||||
|
``OpenVDB_DEFINITIONS``
|
||||||
|
Definitions to use when compiling code that uses OpenVDB.
|
||||||
|
``OpenVDB_{COMPONENT}_FOUND``
|
||||||
|
True if the system has the named OpenVDB component.
|
||||||
|
``OpenVDB_USES_BLOSC``
|
||||||
|
True if the OpenVDB Library has been built with blosc support
|
||||||
|
``OpenVDB_USES_LOG4CPLUS``
|
||||||
|
True if the OpenVDB Library has been built with log4cplus support
|
||||||
|
``OpenVDB_USES_EXR``
|
||||||
|
True if the OpenVDB Library has been built with openexr support
|
||||||
|
``OpenVDB_ABI``
|
||||||
|
Set if this module was able to determine the ABI number the located
|
||||||
|
OpenVDB Library was built against. Unset otherwise.
|
||||||
|
|
||||||
|
Cache Variables
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following cache variables may also be set:
|
||||||
|
|
||||||
|
``OpenVDB_INCLUDE_DIR``
|
||||||
|
The directory containing ``openvdb/version.h``.
|
||||||
|
``OpenVDB_{COMPONENT}_LIBRARY``
|
||||||
|
Individual component libraries for OpenVDB
|
||||||
|
|
||||||
|
Hints
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
Instead of explicitly setting the cache variables, the following variables
|
||||||
|
may be provided to tell this module where to look.
|
||||||
|
|
||||||
|
``OPENVDB_ROOT``
|
||||||
|
Preferred installation prefix.
|
||||||
|
``OPENVDB_INCLUDEDIR``
|
||||||
|
Preferred include directory e.g. <prefix>/include
|
||||||
|
``OPENVDB_LIBRARYDIR``
|
||||||
|
Preferred library directory e.g. <prefix>/lib
|
||||||
|
``SYSTEM_LIBRARY_PATHS``
|
||||||
|
Paths appended to all include and lib searches.
|
||||||
|
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.3)
|
||||||
|
# Monitoring <PackageName>_ROOT variables
|
||||||
|
if(POLICY CMP0074)
|
||||||
|
cmake_policy(SET CMP0074 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Include utility functions for version information
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/OpenVDBUtils.cmake)
|
||||||
|
|
||||||
|
mark_as_advanced(
|
||||||
|
OpenVDB_INCLUDE_DIR
|
||||||
|
OpenVDB_LIBRARY
|
||||||
|
)
|
||||||
|
|
||||||
|
set(_OPENVDB_COMPONENT_LIST
|
||||||
|
openvdb
|
||||||
|
)
|
||||||
|
|
||||||
|
if(OpenVDB_FIND_COMPONENTS)
|
||||||
|
set(OPENVDB_COMPONENTS_PROVIDED TRUE)
|
||||||
|
set(_IGNORED_COMPONENTS "")
|
||||||
|
foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS})
|
||||||
|
if(NOT ${COMPONENT} IN_LIST _OPENVDB_COMPONENT_LIST)
|
||||||
|
list(APPEND _IGNORED_COMPONENTS ${COMPONENT})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(_IGNORED_COMPONENTS)
|
||||||
|
message(STATUS "Ignoring unknown components of OpenVDB:")
|
||||||
|
foreach(COMPONENT ${_IGNORED_COMPONENTS})
|
||||||
|
message(STATUS " ${COMPONENT}")
|
||||||
|
endforeach()
|
||||||
|
list(REMOVE_ITEM OpenVDB_FIND_COMPONENTS ${_IGNORED_COMPONENTS})
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(OPENVDB_COMPONENTS_PROVIDED FALSE)
|
||||||
|
set(OpenVDB_FIND_COMPONENTS ${_OPENVDB_COMPONENT_LIST})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Append OPENVDB_ROOT or $ENV{OPENVDB_ROOT} if set (prioritize the direct cmake var)
|
||||||
|
set(_OPENVDB_ROOT_SEARCH_DIR "")
|
||||||
|
|
||||||
|
# Additionally try and use pkconfig to find OpenVDB
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_OpenVDB QUIET OpenVDB)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# Search for OpenVDB include DIR
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(_OPENVDB_INCLUDE_SEARCH_DIRS "")
|
||||||
|
list(APPEND _OPENVDB_INCLUDE_SEARCH_DIRS
|
||||||
|
${OPENVDB_INCLUDEDIR}
|
||||||
|
${_OPENVDB_ROOT_SEARCH_DIR}
|
||||||
|
${PC_OpenVDB_INCLUDE_DIRS}
|
||||||
|
${SYSTEM_LIBRARY_PATHS}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Look for a standard OpenVDB header file.
|
||||||
|
find_path(OpenVDB_INCLUDE_DIR openvdb/version.h
|
||||||
|
PATHS ${_OPENVDB_INCLUDE_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES include
|
||||||
|
)
|
||||||
|
|
||||||
|
OPENVDB_VERSION_FROM_HEADER("${OpenVDB_INCLUDE_DIR}/openvdb/version.h"
|
||||||
|
VERSION OpenVDB_VERSION
|
||||||
|
MAJOR OpenVDB_MAJOR_VERSION
|
||||||
|
MINOR OpenVDB_MINOR_VERSION
|
||||||
|
PATCH OpenVDB_PATCH_VERSION
|
||||||
|
)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# Search for OPENVDB lib DIR
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(_OPENVDB_LIBRARYDIR_SEARCH_DIRS "")
|
||||||
|
|
||||||
|
# Append to _OPENVDB_LIBRARYDIR_SEARCH_DIRS in priority order
|
||||||
|
|
||||||
|
list(APPEND _OPENVDB_LIBRARYDIR_SEARCH_DIRS
|
||||||
|
${OPENVDB_LIBRARYDIR}
|
||||||
|
${_OPENVDB_ROOT_SEARCH_DIR}
|
||||||
|
${PC_OpenVDB_LIBRARY_DIRS}
|
||||||
|
${SYSTEM_LIBRARY_PATHS}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build suffix directories
|
||||||
|
|
||||||
|
set(OPENVDB_PATH_SUFFIXES
|
||||||
|
lib64
|
||||||
|
lib
|
||||||
|
)
|
||||||
|
|
||||||
|
# Static library setup
|
||||||
|
if(UNIX AND OPENVDB_USE_STATIC_LIBS)
|
||||||
|
set(_OPENVDB_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(OpenVDB_LIB_COMPONENTS "")
|
||||||
|
|
||||||
|
foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS})
|
||||||
|
set(LIB_NAME ${COMPONENT})
|
||||||
|
find_library(OpenVDB_${COMPONENT}_LIBRARY ${LIB_NAME} lib${LIB_NAME}
|
||||||
|
PATHS ${_OPENVDB_LIBRARYDIR_SEARCH_DIRS}
|
||||||
|
PATH_SUFFIXES ${OPENVDB_PATH_SUFFIXES}
|
||||||
|
)
|
||||||
|
list(APPEND OpenVDB_LIB_COMPONENTS ${OpenVDB_${COMPONENT}_LIBRARY})
|
||||||
|
|
||||||
|
if(OpenVDB_${COMPONENT}_LIBRARY)
|
||||||
|
set(OpenVDB_${COMPONENT}_FOUND TRUE)
|
||||||
|
else()
|
||||||
|
set(OpenVDB_${COMPONENT}_FOUND FALSE)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(UNIX AND OPENVDB_USE_STATIC_LIBS)
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_OPENVDB_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
|
unset(_OPENVDB_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# Cache and set OPENVDB_FOUND
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(OpenVDB
|
||||||
|
FOUND_VAR OpenVDB_FOUND
|
||||||
|
REQUIRED_VARS
|
||||||
|
OpenVDB_INCLUDE_DIR
|
||||||
|
OpenVDB_LIB_COMPONENTS
|
||||||
|
VERSION_VAR OpenVDB_VERSION
|
||||||
|
HANDLE_COMPONENTS
|
||||||
|
)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# Determine ABI number
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Set the ABI number the library was built against. Uses vdb_print
|
||||||
|
find_program(OPENVDB_PRINT vdb_print PATHS ${OpenVDB_INCLUDE_DIR} )
|
||||||
|
|
||||||
|
OPENVDB_ABI_VERSION_FROM_PRINT(
|
||||||
|
"${OPENVDB_PRINT}"
|
||||||
|
ABI OpenVDB_ABI
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT OpenVDB_FIND_QUIET)
|
||||||
|
if(NOT OpenVDB_ABI)
|
||||||
|
message(WARNING "Unable to determine OpenVDB ABI version from OpenVDB "
|
||||||
|
"installation. The library major version \"${OpenVDB_MAJOR_VERSION}\" "
|
||||||
|
"will be inferred. If this is not correct, use "
|
||||||
|
"add_definitions(-DOPENVDB_ABI_VERSION_NUMBER=N)"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(STATUS "OpenVDB ABI Version: ${OpenVDB_ABI}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# Handle OpenVDB dependencies
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Add standard dependencies
|
||||||
|
|
||||||
|
find_package(IlmBase COMPONENTS Half)
|
||||||
|
if(NOT IlmBase_FOUND)
|
||||||
|
pkg_check_modules(IlmBase QUIET IlmBase)
|
||||||
|
endif()
|
||||||
|
if (IlmBase_FOUND AND NOT TARGET IlmBase::Half)
|
||||||
|
message(STATUS "Falling back to IlmBase found by pkg-config...")
|
||||||
|
|
||||||
|
find_library(IlmHalf_LIBRARY NAMES Half)
|
||||||
|
if(IlmHalf_LIBRARY-NOTFOUND)
|
||||||
|
message(FATAL_ERROR "IlmBase::Half can not be found!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(IlmBase::Half UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(IlmBase::Half PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${IlmHalf_LIBRARY}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${IlmBase_INCLUDE_DIRS})
|
||||||
|
elseif(NOT IlmBase_FOUND)
|
||||||
|
message(FATAL_ERROR "IlmBase::Half can not be found!")
|
||||||
|
endif()
|
||||||
|
find_package(TBB REQUIRED COMPONENTS tbb)
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
find_package(Boost REQUIRED COMPONENTS iostreams system)
|
||||||
|
|
||||||
|
# Use GetPrerequisites to see which libraries this OpenVDB lib has linked to
|
||||||
|
# which we can query for optional deps. This basically runs ldd/otoll/objdump
|
||||||
|
# etc to track deps. We could use a vdb_config binary tools here to improve
|
||||||
|
# this process
|
||||||
|
|
||||||
|
include(GetPrerequisites)
|
||||||
|
|
||||||
|
set(_EXCLUDE_SYSTEM_PREREQUISITES 1)
|
||||||
|
set(_RECURSE_PREREQUISITES 0)
|
||||||
|
set(_OPENVDB_PREREQUISITE_LIST)
|
||||||
|
|
||||||
|
if(NOT OPENVDB_USE_STATIC_LIBS)
|
||||||
|
get_prerequisites(${OpenVDB_openvdb_LIBRARY}
|
||||||
|
_OPENVDB_PREREQUISITE_LIST
|
||||||
|
${_EXCLUDE_SYSTEM_PREREQUISITES}
|
||||||
|
${_RECURSE_PREREQUISITES}
|
||||||
|
""
|
||||||
|
"${SYSTEM_LIBRARY_PATHS}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(_EXCLUDE_SYSTEM_PREREQUISITES)
|
||||||
|
unset(_RECURSE_PREREQUISITES)
|
||||||
|
|
||||||
|
# As the way we resolve optional libraries relies on library file names, use
|
||||||
|
# the configuration options from the main CMakeLists.txt to allow users
|
||||||
|
# to manually identify the requirements of OpenVDB builds if they know them.
|
||||||
|
|
||||||
|
set(OpenVDB_USES_BLOSC ${USE_BLOSC})
|
||||||
|
set(OpenVDB_USES_LOG4CPLUS ${USE_LOG4CPLUS})
|
||||||
|
set(OpenVDB_USES_ILM ${USE_EXR})
|
||||||
|
set(OpenVDB_USES_EXR ${USE_EXR})
|
||||||
|
|
||||||
|
# Search for optional dependencies
|
||||||
|
|
||||||
|
foreach(PREREQUISITE ${_OPENVDB_PREREQUISITE_LIST})
|
||||||
|
set(_HAS_DEP)
|
||||||
|
get_filename_component(PREREQUISITE ${PREREQUISITE} NAME)
|
||||||
|
|
||||||
|
string(FIND ${PREREQUISITE} "blosc" _HAS_DEP)
|
||||||
|
if(NOT ${_HAS_DEP} EQUAL -1)
|
||||||
|
set(OpenVDB_USES_BLOSC ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(FIND ${PREREQUISITE} "log4cplus" _HAS_DEP)
|
||||||
|
if(NOT ${_HAS_DEP} EQUAL -1)
|
||||||
|
set(OpenVDB_USES_LOG4CPLUS ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(FIND ${PREREQUISITE} "IlmImf" _HAS_DEP)
|
||||||
|
if(NOT ${_HAS_DEP} EQUAL -1)
|
||||||
|
set(OpenVDB_USES_ILM ON)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
unset(_OPENVDB_PREREQUISITE_LIST)
|
||||||
|
unset(_HAS_DEP)
|
||||||
|
|
||||||
|
if(OpenVDB_USES_BLOSC)
|
||||||
|
find_package(Blosc )
|
||||||
|
if(NOT Blosc_FOUND OR NOT TARGET Blosc::blosc)
|
||||||
|
message(STATUS "find_package could not find Blosc. Using fallback blosc search...")
|
||||||
|
find_path(Blosc_INCLUDE_DIR blosc.h)
|
||||||
|
find_library(Blosc_LIBRARY NAMES blosc)
|
||||||
|
if (Blosc_INCLUDE_DIR AND Blosc_LIBRARY)
|
||||||
|
set(Blosc_FOUND TRUE)
|
||||||
|
add_library(Blosc::blosc UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(Blosc::blosc PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${Blosc_LIBRARY}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${Blosc_INCLUDE_DIR})
|
||||||
|
elseif()
|
||||||
|
message(FATAL_ERROR "Blosc library can not be found!")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OpenVDB_USES_LOG4CPLUS)
|
||||||
|
find_package(Log4cplus REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OpenVDB_USES_ILM)
|
||||||
|
find_package(IlmBase REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OpenVDB_USES_EXR)
|
||||||
|
find_package(OpenEXR REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Set deps. Note that the order here is important. If we're building against
|
||||||
|
# Houdini 17.5 we must include OpenEXR and IlmBase deps first to ensure the
|
||||||
|
# users chosen namespaced headers are correctly prioritized. Otherwise other
|
||||||
|
# include paths from shared installs (including houdini) may pull in the wrong
|
||||||
|
# headers
|
||||||
|
|
||||||
|
set(_OPENVDB_VISIBLE_DEPENDENCIES
|
||||||
|
Boost::iostreams
|
||||||
|
Boost::system
|
||||||
|
IlmBase::Half
|
||||||
|
)
|
||||||
|
|
||||||
|
set(_OPENVDB_DEFINITIONS)
|
||||||
|
if(OpenVDB_ABI)
|
||||||
|
list(APPEND _OPENVDB_DEFINITIONS "-DOPENVDB_ABI_VERSION_NUMBER=${OpenVDB_ABI}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OpenVDB_USES_EXR)
|
||||||
|
list(APPEND _OPENVDB_VISIBLE_DEPENDENCIES
|
||||||
|
IlmBase::IlmThread
|
||||||
|
IlmBase::Iex
|
||||||
|
IlmBase::Imath
|
||||||
|
OpenEXR::IlmImf
|
||||||
|
)
|
||||||
|
list(APPEND _OPENVDB_DEFINITIONS "-DOPENVDB_TOOLS_RAYTRACER_USE_EXR")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OpenVDB_USES_LOG4CPLUS)
|
||||||
|
list(APPEND _OPENVDB_VISIBLE_DEPENDENCIES Log4cplus::log4cplus)
|
||||||
|
list(APPEND _OPENVDB_DEFINITIONS "-DOPENVDB_USE_LOG4CPLUS")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND _OPENVDB_VISIBLE_DEPENDENCIES
|
||||||
|
TBB::tbb
|
||||||
|
)
|
||||||
|
if(UNIX)
|
||||||
|
list(APPEND _OPENVDB_VISIBLE_DEPENDENCIES
|
||||||
|
Threads::Threads
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_OPENVDB_HIDDEN_DEPENDENCIES)
|
||||||
|
|
||||||
|
if(OpenVDB_USES_BLOSC)
|
||||||
|
if(OPENVDB_USE_STATIC_LIBS)
|
||||||
|
list(APPEND _OPENVDB_VISIBLE_DEPENDENCIES $<LINK_ONLY:Blosc::blosc>)
|
||||||
|
else()
|
||||||
|
list(APPEND _OPENVDB_HIDDEN_DEPENDENCIES Blosc::blosc)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OPENVDB_USE_STATIC_LIBS)
|
||||||
|
list(APPEND _OPENVDB_VISIBLE_DEPENDENCIES $<LINK_ONLY:ZLIB::ZLIB>)
|
||||||
|
else()
|
||||||
|
list(APPEND _OPENVDB_HIDDEN_DEPENDENCIES ZLIB::ZLIB)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# Configure imported target
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(OpenVDB_LIBRARIES
|
||||||
|
${OpenVDB_LIB_COMPONENTS}
|
||||||
|
)
|
||||||
|
set(OpenVDB_INCLUDE_DIRS ${OpenVDB_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(OpenVDB_DEFINITIONS)
|
||||||
|
list(APPEND OpenVDB_DEFINITIONS "${PC_OpenVDB_CFLAGS_OTHER}")
|
||||||
|
list(APPEND OpenVDB_DEFINITIONS "${_OPENVDB_DEFINITIONS}")
|
||||||
|
list(REMOVE_DUPLICATES OpenVDB_DEFINITIONS)
|
||||||
|
|
||||||
|
set(OpenVDB_LIBRARY_DIRS "")
|
||||||
|
foreach(LIB ${OpenVDB_LIB_COMPONENTS})
|
||||||
|
get_filename_component(_OPENVDB_LIBDIR ${LIB} DIRECTORY)
|
||||||
|
list(APPEND OpenVDB_LIBRARY_DIRS ${_OPENVDB_LIBDIR})
|
||||||
|
endforeach()
|
||||||
|
list(REMOVE_DUPLICATES OpenVDB_LIBRARY_DIRS)
|
||||||
|
|
||||||
|
foreach(COMPONENT ${OpenVDB_FIND_COMPONENTS})
|
||||||
|
if(NOT TARGET OpenVDB::${COMPONENT})
|
||||||
|
add_library(OpenVDB::${COMPONENT} UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(OpenVDB::${COMPONENT} PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${OpenVDB_${COMPONENT}_LIBRARY}"
|
||||||
|
INTERFACE_COMPILE_OPTIONS "${OpenVDB_DEFINITIONS}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${OpenVDB_INCLUDE_DIR}"
|
||||||
|
IMPORTED_LINK_DEPENDENT_LIBRARIES "${_OPENVDB_HIDDEN_DEPENDENCIES}" # non visible deps
|
||||||
|
INTERFACE_LINK_LIBRARIES "${_OPENVDB_VISIBLE_DEPENDENCIES}" # visible deps (headers)
|
||||||
|
INTERFACE_COMPILE_FEATURES cxx_std_11
|
||||||
|
)
|
||||||
|
|
||||||
|
if (OPENVDB_USE_STATIC_LIBS)
|
||||||
|
set_target_properties(OpenVDB::${COMPONENT} PROPERTIES
|
||||||
|
INTERFACE_COMPILE_DEFINITIONS "OPENVDB_STATICLIB;OPENVDB_OPENEXR_STATICLIB"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(OpenVDB_FOUND AND NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
|
||||||
|
message(STATUS "OpenVDB libraries: ${OpenVDB_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(_OPENVDB_DEFINITIONS)
|
||||||
|
unset(_OPENVDB_VISIBLE_DEPENDENCIES)
|
||||||
|
unset(_OPENVDB_HIDDEN_DEPENDENCIES)
|
|
@ -93,8 +93,16 @@
|
||||||
# This module will also create the "tbb" target that may be used when building
|
# This module will also create the "tbb" target that may be used when building
|
||||||
# executables and libraries.
|
# executables and libraries.
|
||||||
|
|
||||||
|
unset(TBB_FOUND CACHE)
|
||||||
|
unset(TBB_INCLUDE_DIRS CACHE)
|
||||||
|
unset(TBB_LIBRARIES)
|
||||||
|
unset(TBB_LIBRARIES_DEBUG)
|
||||||
|
unset(TBB_LIBRARIES_RELEASE)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package(Threads QUIET REQUIRED)
|
||||||
|
|
||||||
if(NOT TBB_FOUND)
|
if(NOT TBB_FOUND)
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
@ -215,6 +223,9 @@ if(NOT TBB_FOUND)
|
||||||
foreach(_comp ${TBB_SEARCH_COMPOMPONENTS})
|
foreach(_comp ${TBB_SEARCH_COMPOMPONENTS})
|
||||||
if(";${TBB_FIND_COMPONENTS};tbb;" MATCHES ";${_comp};")
|
if(";${TBB_FIND_COMPONENTS};tbb;" MATCHES ";${_comp};")
|
||||||
|
|
||||||
|
unset(TBB_${_comp}_LIBRARY_DEBUG CACHE)
|
||||||
|
unset(TBB_${_comp}_LIBRARY_RELEASE CACHE)
|
||||||
|
|
||||||
# Search for the libraries
|
# Search for the libraries
|
||||||
find_library(TBB_${_comp}_LIBRARY_RELEASE ${_comp}${TBB_STATIC_SUFFIX}
|
find_library(TBB_${_comp}_LIBRARY_RELEASE ${_comp}${TBB_STATIC_SUFFIX}
|
||||||
HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR}
|
HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR}
|
||||||
|
@ -265,6 +276,7 @@ if(NOT TBB_FOUND)
|
||||||
set(TBB_LIBRARIES ${TBB_LIBRARIES_RELEASE})
|
set(TBB_LIBRARIES ${TBB_LIBRARIES_RELEASE})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(TBB_DEFINITIONS "")
|
||||||
if (MSVC AND TBB_STATIC)
|
if (MSVC AND TBB_STATIC)
|
||||||
set(TBB_DEFINITIONS __TBB_NO_IMPLICIT_LINKAGE)
|
set(TBB_DEFINITIONS __TBB_NO_IMPLICIT_LINKAGE)
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -273,6 +285,7 @@ if(NOT TBB_FOUND)
|
||||||
|
|
||||||
find_package_handle_standard_args(TBB
|
find_package_handle_standard_args(TBB
|
||||||
REQUIRED_VARS TBB_INCLUDE_DIRS TBB_LIBRARIES
|
REQUIRED_VARS TBB_INCLUDE_DIRS TBB_LIBRARIES
|
||||||
|
FAIL_MESSAGE "TBB library cannot be found. Consider set TBBROOT environment variable."
|
||||||
HANDLE_COMPONENTS
|
HANDLE_COMPONENTS
|
||||||
VERSION_VAR TBB_VERSION)
|
VERSION_VAR TBB_VERSION)
|
||||||
|
|
||||||
|
@ -283,6 +296,8 @@ if(NOT TBB_FOUND)
|
||||||
if(NOT CMAKE_VERSION VERSION_LESS 3.0 AND TBB_FOUND)
|
if(NOT CMAKE_VERSION VERSION_LESS 3.0 AND TBB_FOUND)
|
||||||
add_library(TBB::tbb UNKNOWN IMPORTED)
|
add_library(TBB::tbb UNKNOWN IMPORTED)
|
||||||
set_target_properties(TBB::tbb PROPERTIES
|
set_target_properties(TBB::tbb PROPERTIES
|
||||||
|
INTERFACE_COMPILE_DEFINITIONS "${TBB_DEFINITIONS}"
|
||||||
|
INTERFACE_LINK_LIBRARIES "Threads::Threads;${CMAKE_DL_LIBS}"
|
||||||
INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS}
|
INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS}
|
||||||
IMPORTED_LOCATION ${TBB_LIBRARIES})
|
IMPORTED_LOCATION ${TBB_LIBRARIES})
|
||||||
if(TBB_LIBRARIES_RELEASE AND TBB_LIBRARIES_DEBUG)
|
if(TBB_LIBRARIES_RELEASE AND TBB_LIBRARIES_DEBUG)
|
||||||
|
@ -294,11 +309,6 @@ if(NOT TBB_FOUND)
|
||||||
IMPORTED_LOCATION_MINSIZEREL ${TBB_LIBRARIES_RELEASE}
|
IMPORTED_LOCATION_MINSIZEREL ${TBB_LIBRARIES_RELEASE}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
find_package(Threads QUIET REQUIRED)
|
|
||||||
set_target_properties(TBB::tbb PROPERTIES INTERFACE_LINK_LIBRARIES "${CMAKE_DL_LIBS};Threads::Threads")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARIES)
|
mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARIES)
|
||||||
|
|
166
cmake/modules/OpenVDBUtils.cmake
Normal file
166
cmake/modules/OpenVDBUtils.cmake
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
# Copyright (c) DreamWorks Animation LLC
|
||||||
|
#
|
||||||
|
# All rights reserved. This software is distributed under the
|
||||||
|
# Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
|
||||||
|
#
|
||||||
|
# Redistributions of source code must retain the above copyright
|
||||||
|
# and license notice and the following restrictions and disclaimer.
|
||||||
|
#
|
||||||
|
# * Neither the name of DreamWorks Animation nor the names of
|
||||||
|
# its contributors may be used to endorse or promote products derived
|
||||||
|
# from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
|
||||||
|
# LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
|
||||||
|
#
|
||||||
|
#[=======================================================================[.rst:
|
||||||
|
|
||||||
|
OpenVDBUtils.cmake
|
||||||
|
------------------
|
||||||
|
|
||||||
|
A utility CMake file which provides helper functions for configuring an
|
||||||
|
OpenVDB installation.
|
||||||
|
|
||||||
|
Use this module by invoking include with the form::
|
||||||
|
|
||||||
|
include ( OpenVDBUtils )
|
||||||
|
|
||||||
|
|
||||||
|
The following functions are provided:
|
||||||
|
|
||||||
|
``OPENVDB_VERSION_FROM_HEADER``
|
||||||
|
|
||||||
|
OPENVDB_VERSION_FROM_HEADER ( <header_path>
|
||||||
|
VERSION [<version>]
|
||||||
|
MAJOR [<version>]
|
||||||
|
MINOR [<version>]
|
||||||
|
PATCH [<version>] )
|
||||||
|
|
||||||
|
Parse the provided version file to retrieve the current OpenVDB
|
||||||
|
version information. The file is expected to be a version.h file
|
||||||
|
as found in the following path of an OpenVDB repository:
|
||||||
|
openvdb/version.h
|
||||||
|
|
||||||
|
If the file does not exist, variables are unmodified.
|
||||||
|
|
||||||
|
``OPENVDB_ABI_VERSION_FROM_PRINT``
|
||||||
|
|
||||||
|
OPENVDB_ABI_VERSION_FROM_PRINT ( <vdb_print>
|
||||||
|
[QUIET]
|
||||||
|
ABI [<version>] )
|
||||||
|
|
||||||
|
Retrieve the ABI version that an installation of OpenVDB was compiled
|
||||||
|
for using the provided vdb_print binary. Parses the result of:
|
||||||
|
vdb_print --version
|
||||||
|
|
||||||
|
If the binary does not exist or fails to launch, variables are
|
||||||
|
unmodified.
|
||||||
|
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
|
||||||
|
function(OPENVDB_VERSION_FROM_HEADER OPENVDB_VERSION_FILE)
|
||||||
|
cmake_parse_arguments(_VDB "" "VERSION;MAJOR;MINOR;PATCH" "" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT EXISTS ${OPENVDB_VERSION_FILE})
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(STRINGS "${OPENVDB_VERSION_FILE}" openvdb_version_str
|
||||||
|
REGEX "^#define[\t ]+OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER[\t ]+.*"
|
||||||
|
)
|
||||||
|
string(REGEX REPLACE "^.*OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER[\t ]+([0-9]*).*$" "\\1"
|
||||||
|
_OpenVDB_MAJOR_VERSION "${openvdb_version_str}"
|
||||||
|
)
|
||||||
|
|
||||||
|
file(STRINGS "${OPENVDB_VERSION_FILE}" openvdb_version_str
|
||||||
|
REGEX "^#define[\t ]+OPENVDB_LIBRARY_MINOR_VERSION_NUMBER[\t ]+.*"
|
||||||
|
)
|
||||||
|
string(REGEX REPLACE "^.*OPENVDB_LIBRARY_MINOR_VERSION_NUMBER[\t ]+([0-9]*).*$" "\\1"
|
||||||
|
_OpenVDB_MINOR_VERSION "${openvdb_version_str}"
|
||||||
|
)
|
||||||
|
|
||||||
|
file(STRINGS "${OPENVDB_VERSION_FILE}" openvdb_version_str
|
||||||
|
REGEX "^#define[\t ]+OPENVDB_LIBRARY_PATCH_VERSION_NUMBER[\t ]+.*"
|
||||||
|
)
|
||||||
|
string(REGEX REPLACE "^.*OPENVDB_LIBRARY_PATCH_VERSION_NUMBER[\t ]+([0-9]*).*$" "\\1"
|
||||||
|
_OpenVDB_PATCH_VERSION "${openvdb_version_str}"
|
||||||
|
)
|
||||||
|
unset(openvdb_version_str)
|
||||||
|
|
||||||
|
if(_VDB_VERSION)
|
||||||
|
set(${_VDB_VERSION}
|
||||||
|
${_OpenVDB_MAJOR_VERSION}.${_OpenVDB_MINOR_VERSION}.${_OpenVDB_PATCH_VERSION}
|
||||||
|
PARENT_SCOPE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(_VDB_MAJOR)
|
||||||
|
set(${_VDB_MAJOR} ${_OpenVDB_MAJOR_VERSION} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
if(_VDB_MINOR)
|
||||||
|
set(${_VDB_MINOR} ${_OpenVDB_MINOR_VERSION} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
if(_VDB_PATCH)
|
||||||
|
set(${_VDB_PATCH} ${_OpenVDB_PATCH_VERSION} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
|
||||||
|
function(OPENVDB_ABI_VERSION_FROM_PRINT OPENVDB_PRINT)
|
||||||
|
cmake_parse_arguments(_VDB "QUIET" "ABI" "" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT EXISTS ${OPENVDB_PRINT})
|
||||||
|
message(WARNING "vdb_print not found! ${OPENVDB_PRINT}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_VDB_PRINT_VERSION_STRING "")
|
||||||
|
set(_VDB_PRINT_RETURN_STATUS "")
|
||||||
|
|
||||||
|
if(${_VDB_QUIET})
|
||||||
|
execute_process(COMMAND ${OPENVDB_PRINT} "--version"
|
||||||
|
RESULT_VARIABLE _VDB_PRINT_RETURN_STATUS
|
||||||
|
OUTPUT_VARIABLE _VDB_PRINT_VERSION_STRING
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
execute_process(COMMAND ${OPENVDB_PRINT} "--version"
|
||||||
|
RESULT_VARIABLE _VDB_PRINT_RETURN_STATUS
|
||||||
|
OUTPUT_VARIABLE _VDB_PRINT_VERSION_STRING
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${_VDB_PRINT_RETURN_STATUS})
|
||||||
|
message(WARNING "vdb_print returned with status ${_VDB_PRINT_RETURN_STATUS}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_OpenVDB_ABI)
|
||||||
|
string(REGEX REPLACE ".*abi([0-9]*).*" "\\1" _OpenVDB_ABI ${_VDB_PRINT_VERSION_STRING})
|
||||||
|
if(${_OpenVDB_ABI} STREQUAL ${_VDB_PRINT_VERSION_STRING})
|
||||||
|
set(_OpenVDB_ABI "")
|
||||||
|
endif()
|
||||||
|
unset(_VDB_PRINT_RETURN_STATUS)
|
||||||
|
unset(_VDB_PRINT_VERSION_STRING)
|
||||||
|
|
||||||
|
if(_VDB_ABI)
|
||||||
|
set(${_VDB_ABI} ${_OpenVDB_ABI} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
4
deps/CMakeLists.txt
vendored
4
deps/CMakeLists.txt
vendored
|
@ -72,7 +72,7 @@ elseif (APPLE)
|
||||||
message(FATAL_ERROR "Could not determine OS X SDK version. Please use -DCMAKE_OSX_DEPLOYMENT_TARGET=<version>")
|
message(FATAL_ERROR "Could not determine OS X SDK version. Please use -DCMAKE_OSX_DEPLOYMENT_TARGET=<version>")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
message("OS X Deployment Target (inferred from default): ${DEP_OSX_TARGET}")
|
message("OS X Deployment Target (inferred from SDK): ${DEP_OSX_TARGET}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
include("deps-macos.cmake")
|
include("deps-macos.cmake")
|
||||||
|
@ -96,6 +96,7 @@ if (MSVC)
|
||||||
dep_nlopt
|
dep_nlopt
|
||||||
# dep_qhull # Experimental
|
# dep_qhull # Experimental
|
||||||
dep_zlib # on Windows we still need zlib
|
dep_zlib # on Windows we still need zlib
|
||||||
|
dep_openvdb
|
||||||
)
|
)
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
@ -110,6 +111,7 @@ else()
|
||||||
dep_cereal
|
dep_cereal
|
||||||
dep_nlopt
|
dep_nlopt
|
||||||
dep_qhull
|
dep_qhull
|
||||||
|
dep_openvdb
|
||||||
# dep_libigl # Not working, static build has different Eigen
|
# dep_libigl # Not working, static build has different Eigen
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
468
deps/blosc-mods.patch
vendored
Normal file
468
deps/blosc-mods.patch
vendored
Normal file
|
@ -0,0 +1,468 @@
|
||||||
|
From 5669891dfaaa4c814f3ec667ca6bf4e693aea978 Mon Sep 17 00:00:00 2001
|
||||||
|
From: tamasmeszaros <meszaros.q@gmail.com>
|
||||||
|
Date: Wed, 30 Oct 2019 12:54:52 +0100
|
||||||
|
Subject: [PATCH] Blosc 1.17 fixes and cmake config script
|
||||||
|
|
||||||
|
---
|
||||||
|
CMakeLists.txt | 105 +++++++++++++++++-----------------
|
||||||
|
blosc/CMakeLists.txt | 118 +++++++++------------------------------
|
||||||
|
cmake/FindLZ4.cmake | 6 +-
|
||||||
|
cmake/FindSnappy.cmake | 8 ++-
|
||||||
|
cmake/FindZstd.cmake | 8 ++-
|
||||||
|
cmake_config.cmake.in | 24 ++++++++
|
||||||
|
internal-complibs/CMakeLists.txt | 35 ++++++++++++
|
||||||
|
7 files changed, 157 insertions(+), 147 deletions(-)
|
||||||
|
create mode 100644 cmake_config.cmake.in
|
||||||
|
create mode 100644 internal-complibs/CMakeLists.txt
|
||||||
|
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 59d9fab..e9134c2 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -71,7 +71,7 @@
|
||||||
|
# DEV: static includes blosc.a and blosc.h
|
||||||
|
|
||||||
|
|
||||||
|
-cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
+cmake_minimum_required(VERSION 3.1) # Threads::Threads target available from 3.1
|
||||||
|
if (NOT CMAKE_VERSION VERSION_LESS 3.3)
|
||||||
|
cmake_policy(SET CMP0063 NEW)
|
||||||
|
endif()
|
||||||
|
@@ -124,55 +124,30 @@ option(PREFER_EXTERNAL_ZSTD
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
-
|
||||||
|
-if(NOT DEACTIVATE_LZ4)
|
||||||
|
- if(PREFER_EXTERNAL_LZ4)
|
||||||
|
- find_package(LZ4)
|
||||||
|
- else()
|
||||||
|
- message(STATUS "Using LZ4 internal sources.")
|
||||||
|
- endif(PREFER_EXTERNAL_LZ4)
|
||||||
|
- # HAVE_LZ4 will be set to true because even if the library is
|
||||||
|
- # not found, we will use the included sources for it
|
||||||
|
- set(HAVE_LZ4 TRUE)
|
||||||
|
-endif(NOT DEACTIVATE_LZ4)
|
||||||
|
-
|
||||||
|
-if(NOT DEACTIVATE_SNAPPY)
|
||||||
|
- if(PREFER_EXTERNAL_SNAPPY)
|
||||||
|
- find_package(Snappy)
|
||||||
|
- else()
|
||||||
|
- message(STATUS "Using Snappy internal sources.")
|
||||||
|
- endif(PREFER_EXTERNAL_SNAPPY)
|
||||||
|
- # HAVE_SNAPPY will be set to true because even if the library is not found,
|
||||||
|
- # we will use the included sources for it
|
||||||
|
- set(HAVE_SNAPPY TRUE)
|
||||||
|
-endif(NOT DEACTIVATE_SNAPPY)
|
||||||
|
-
|
||||||
|
-if(NOT DEACTIVATE_ZLIB)
|
||||||
|
- # import the ZLIB_ROOT environment variable to help finding the zlib library
|
||||||
|
- if(PREFER_EXTERNAL_ZLIB)
|
||||||
|
- set(ZLIB_ROOT $ENV{ZLIB_ROOT})
|
||||||
|
- find_package(ZLIB)
|
||||||
|
- if (NOT ZLIB_FOUND )
|
||||||
|
- message(STATUS "No zlib found. Using internal sources.")
|
||||||
|
- endif (NOT ZLIB_FOUND )
|
||||||
|
- else()
|
||||||
|
- message(STATUS "Using zlib internal sources.")
|
||||||
|
- endif(PREFER_EXTERNAL_ZLIB)
|
||||||
|
- # HAVE_ZLIB will be set to true because even if the library is not found,
|
||||||
|
- # we will use the included sources for it
|
||||||
|
- set(HAVE_ZLIB TRUE)
|
||||||
|
-endif(NOT DEACTIVATE_ZLIB)
|
||||||
|
-
|
||||||
|
-if (NOT DEACTIVATE_ZSTD)
|
||||||
|
- if (PREFER_EXTERNAL_ZSTD)
|
||||||
|
- find_package(Zstd)
|
||||||
|
- else ()
|
||||||
|
- message(STATUS "Using ZSTD internal sources.")
|
||||||
|
- endif (PREFER_EXTERNAL_ZSTD)
|
||||||
|
- # HAVE_ZSTD will be set to true because even if the library is
|
||||||
|
- # not found, we will use the included sources for it
|
||||||
|
- set(HAVE_ZSTD TRUE)
|
||||||
|
-endif (NOT DEACTIVATE_ZSTD)
|
||||||
|
+set(LIBS "")
|
||||||
|
+macro(use_package _pkg _tgt)
|
||||||
|
+ string(TOUPPER ${_pkg} _PKG)
|
||||||
|
+ if(NOT DEACTIVATE_${_PKG})
|
||||||
|
+ if(PREFER_EXTERNAL_${_PKG})
|
||||||
|
+ find_package(${_pkg})
|
||||||
|
+ if (NOT ${_pkg}_FOUND )
|
||||||
|
+ message(STATUS "No ${_pkg} found. Using internal sources.")
|
||||||
|
+ endif()
|
||||||
|
+ else()
|
||||||
|
+ message(STATUS "Using ${_pkg} internal sources.")
|
||||||
|
+ endif(PREFER_EXTERNAL_${_PKG})
|
||||||
|
+ # HAVE_${_pkg} will be set to true because even if the library is
|
||||||
|
+ # not found, we will use the included sources for it
|
||||||
|
+ set(HAVE_${_PKG} TRUE)
|
||||||
|
+ list(APPEND LIBS ${_pkg}::${_tgt})
|
||||||
|
+ endif(NOT DEACTIVATE_${_PKG})
|
||||||
|
+endmacro()
|
||||||
|
+
|
||||||
|
+set(ZLIB_ROOT $ENV{ZLIB_ROOT})
|
||||||
|
+use_package(ZLIB ZLIB)
|
||||||
|
+use_package(LZ4 LZ4)
|
||||||
|
+use_package(Snappy snappy)
|
||||||
|
+use_package(Zstd Zstd)
|
||||||
|
|
||||||
|
# create the config.h file
|
||||||
|
configure_file ("blosc/config.h.in" "blosc/config.h" )
|
||||||
|
@@ -316,6 +291,7 @@ endif()
|
||||||
|
|
||||||
|
|
||||||
|
# subdirectories
|
||||||
|
+add_subdirectory(internal-complibs)
|
||||||
|
add_subdirectory(blosc)
|
||||||
|
|
||||||
|
if(BUILD_TESTS)
|
||||||
|
@@ -328,7 +304,6 @@ if(BUILD_BENCHMARKS)
|
||||||
|
add_subdirectory(bench)
|
||||||
|
endif(BUILD_BENCHMARKS)
|
||||||
|
|
||||||
|
-
|
||||||
|
# uninstall target
|
||||||
|
if (BLOSC_INSTALL)
|
||||||
|
configure_file(
|
||||||
|
@@ -338,10 +313,38 @@ if (BLOSC_INSTALL)
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/blosc.pc"
|
||||||
|
DESTINATION lib/pkgconfig COMPONENT DEV)
|
||||||
|
|
||||||
|
+ configure_file(
|
||||||
|
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake_config.cmake.in"
|
||||||
|
+ "${CMAKE_CURRENT_BINARY_DIR}/cmakeexports/BloscConfig.cmake"
|
||||||
|
+ @ONLY)
|
||||||
|
+
|
||||||
|
configure_file(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
|
IMMEDIATE @ONLY)
|
||||||
|
+
|
||||||
|
+ include(CMakePackageConfigHelpers)
|
||||||
|
+ write_basic_package_version_file(
|
||||||
|
+ "${CMAKE_CURRENT_BINARY_DIR}/cmakeexports/BloscConfigVersion.cmake"
|
||||||
|
+ VERSION ${BLOSC_VERSION_MAJOR}.${BLOSC_VERSION_MINOR}.${BLOSC_VERSION_PATCH}
|
||||||
|
+ COMPATIBILITY AnyNewerVersion
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ export(EXPORT BloscTargets
|
||||||
|
+ FILE "${CMAKE_CURRENT_BINARY_DIR}/cmakeexports/BloscTargets.cmake"
|
||||||
|
+ NAMESPACE Blosc::)
|
||||||
|
+
|
||||||
|
+ install(EXPORT BloscTargets
|
||||||
|
+ FILE BloscTargets.cmake
|
||||||
|
+ NAMESPACE Blosc::
|
||||||
|
+ DESTINATION lib/cmake/Blosc
|
||||||
|
+ EXPORT_LINK_INTERFACE_LIBRARIES)
|
||||||
|
+
|
||||||
|
+ install(FILES
|
||||||
|
+ "${CMAKE_CURRENT_BINARY_DIR}/cmakeexports/BloscConfig.cmake"
|
||||||
|
+ "${CMAKE_CURRENT_BINARY_DIR}/cmakeexports/BloscConfigVersion.cmake"
|
||||||
|
+ DESTINATION lib/cmake/Blosc COMPONENT DEV)
|
||||||
|
+
|
||||||
|
add_custom_target(uninstall
|
||||||
|
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||||
|
endif()
|
||||||
|
diff --git a/blosc/CMakeLists.txt b/blosc/CMakeLists.txt
|
||||||
|
index 1d1bebe..f554abe 100644
|
||||||
|
--- a/blosc/CMakeLists.txt
|
||||||
|
+++ b/blosc/CMakeLists.txt
|
||||||
|
@@ -1,52 +1,11 @@
|
||||||
|
# a simple way to detect that we are using CMAKE
|
||||||
|
add_definitions(-DUSING_CMAKE)
|
||||||
|
|
||||||
|
-set(INTERNAL_LIBS ${PROJECT_SOURCE_DIR}/internal-complibs)
|
||||||
|
-
|
||||||
|
# Hide symbols by default unless they're specifically exported.
|
||||||
|
# This makes it easier to keep the set of exported symbols the
|
||||||
|
# same across all compilers/platforms.
|
||||||
|
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||||
|
|
||||||
|
-# includes
|
||||||
|
-set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
-if(NOT DEACTIVATE_LZ4)
|
||||||
|
- if (LZ4_FOUND)
|
||||||
|
- set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${LZ4_INCLUDE_DIR})
|
||||||
|
- else(LZ4_FOUND)
|
||||||
|
- set(LZ4_LOCAL_DIR ${INTERNAL_LIBS}/lz4-1.9.1)
|
||||||
|
- set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${LZ4_LOCAL_DIR})
|
||||||
|
- endif(LZ4_FOUND)
|
||||||
|
-endif(NOT DEACTIVATE_LZ4)
|
||||||
|
-
|
||||||
|
-if(NOT DEACTIVATE_SNAPPY)
|
||||||
|
- if (SNAPPY_FOUND)
|
||||||
|
- set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${SNAPPY_INCLUDE_DIR})
|
||||||
|
- else(SNAPPY_FOUND)
|
||||||
|
- set(SNAPPY_LOCAL_DIR ${INTERNAL_LIBS}/snappy-1.1.1)
|
||||||
|
- set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${SNAPPY_LOCAL_DIR})
|
||||||
|
- endif(SNAPPY_FOUND)
|
||||||
|
-endif(NOT DEACTIVATE_SNAPPY)
|
||||||
|
-
|
||||||
|
-if(NOT DEACTIVATE_ZLIB)
|
||||||
|
- if (ZLIB_FOUND)
|
||||||
|
- set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR})
|
||||||
|
- else(ZLIB_FOUND)
|
||||||
|
- set(ZLIB_LOCAL_DIR ${INTERNAL_LIBS}/zlib-1.2.8)
|
||||||
|
- set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${ZLIB_LOCAL_DIR})
|
||||||
|
- endif(ZLIB_FOUND)
|
||||||
|
-endif(NOT DEACTIVATE_ZLIB)
|
||||||
|
-
|
||||||
|
-if (NOT DEACTIVATE_ZSTD)
|
||||||
|
- if (ZSTD_FOUND)
|
||||||
|
- set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${ZSTD_INCLUDE_DIR})
|
||||||
|
- else (ZSTD_FOUND)
|
||||||
|
- set(ZSTD_LOCAL_DIR ${INTERNAL_LIBS}/zstd-1.4.1)
|
||||||
|
- set(BLOSC_INCLUDE_DIRS ${BLOSC_INCLUDE_DIRS} ${ZSTD_LOCAL_DIR} ${ZSTD_LOCAL_DIR}/common)
|
||||||
|
- endif (ZSTD_FOUND)
|
||||||
|
-endif (NOT DEACTIVATE_ZSTD)
|
||||||
|
-
|
||||||
|
-include_directories(${BLOSC_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# library sources
|
||||||
|
set(SOURCES blosc.c blosclz.c fastcopy.c shuffle-generic.c bitshuffle-generic.c
|
||||||
|
@@ -73,53 +32,13 @@ if(WIN32)
|
||||||
|
message(STATUS "using the internal pthread library for win32 systems.")
|
||||||
|
set(SOURCES ${SOURCES} win32/pthread.c)
|
||||||
|
else(NOT Threads_FOUND)
|
||||||
|
- set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
+ list(APPEND LIBS Threads::Threads)
|
||||||
|
endif(NOT Threads_FOUND)
|
||||||
|
else(WIN32)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
- set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
+ list(APPEND LIBS Threads::Threads)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
-if(NOT DEACTIVATE_LZ4)
|
||||||
|
- if(LZ4_FOUND)
|
||||||
|
- set(LIBS ${LIBS} ${LZ4_LIBRARY})
|
||||||
|
- else(LZ4_FOUND)
|
||||||
|
- file(GLOB LZ4_FILES ${LZ4_LOCAL_DIR}/*.c)
|
||||||
|
- set(SOURCES ${SOURCES} ${LZ4_FILES})
|
||||||
|
- endif(LZ4_FOUND)
|
||||||
|
-endif(NOT DEACTIVATE_LZ4)
|
||||||
|
-
|
||||||
|
-if(NOT DEACTIVATE_SNAPPY)
|
||||||
|
- if(SNAPPY_FOUND)
|
||||||
|
- set(LIBS ${LIBS} ${SNAPPY_LIBRARY})
|
||||||
|
- else(SNAPPY_FOUND)
|
||||||
|
- file(GLOB SNAPPY_FILES ${SNAPPY_LOCAL_DIR}/*.cc)
|
||||||
|
- set(SOURCES ${SOURCES} ${SNAPPY_FILES})
|
||||||
|
- endif(SNAPPY_FOUND)
|
||||||
|
-endif(NOT DEACTIVATE_SNAPPY)
|
||||||
|
-
|
||||||
|
-if(NOT DEACTIVATE_ZLIB)
|
||||||
|
- if(ZLIB_FOUND)
|
||||||
|
- set(LIBS ${LIBS} ${ZLIB_LIBRARY})
|
||||||
|
- else(ZLIB_FOUND)
|
||||||
|
- file(GLOB ZLIB_FILES ${ZLIB_LOCAL_DIR}/*.c)
|
||||||
|
- set(SOURCES ${SOURCES} ${ZLIB_FILES})
|
||||||
|
- endif(ZLIB_FOUND)
|
||||||
|
-endif(NOT DEACTIVATE_ZLIB)
|
||||||
|
-
|
||||||
|
-if (NOT DEACTIVATE_ZSTD)
|
||||||
|
- if (ZSTD_FOUND)
|
||||||
|
- set(LIBS ${LIBS} ${ZSTD_LIBRARY})
|
||||||
|
- else (ZSTD_FOUND)
|
||||||
|
- file(GLOB ZSTD_FILES
|
||||||
|
- ${ZSTD_LOCAL_DIR}/common/*.c
|
||||||
|
- ${ZSTD_LOCAL_DIR}/compress/*.c
|
||||||
|
- ${ZSTD_LOCAL_DIR}/decompress/*.c)
|
||||||
|
- set(SOURCES ${SOURCES} ${ZSTD_FILES})
|
||||||
|
- endif (ZSTD_FOUND)
|
||||||
|
-endif (NOT DEACTIVATE_ZSTD)
|
||||||
|
-
|
||||||
|
-
|
||||||
|
# targets
|
||||||
|
if (BUILD_SHARED)
|
||||||
|
add_library(blosc_shared SHARED ${SOURCES})
|
||||||
|
@@ -191,14 +110,17 @@ if (BUILD_TESTS)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
+add_library(blosc INTERFACE)
|
||||||
|
+
|
||||||
|
if (BUILD_SHARED)
|
||||||
|
- target_link_libraries(blosc_shared ${LIBS})
|
||||||
|
- target_include_directories(blosc_shared PUBLIC ${BLOSC_INCLUDE_DIRS})
|
||||||
|
+ target_link_libraries(blosc_shared PRIVATE ${LIBS})
|
||||||
|
+ target_include_directories(blosc_shared PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||||
|
+ target_link_libraries(blosc INTERFACE blosc_shared)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (BUILD_TESTS)
|
||||||
|
- target_link_libraries(blosc_shared_testing ${LIBS})
|
||||||
|
- target_include_directories(blosc_shared_testing PUBLIC ${BLOSC_INCLUDE_DIRS})
|
||||||
|
+ target_link_libraries(blosc_shared_testing PRIVATE ${LIBS})
|
||||||
|
+ target_include_directories(blosc_shared_testing PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_STATIC)
|
||||||
|
@@ -207,17 +129,31 @@ if(BUILD_STATIC)
|
||||||
|
if (MSVC)
|
||||||
|
set_target_properties(blosc_static PROPERTIES PREFIX lib)
|
||||||
|
endif()
|
||||||
|
- target_link_libraries(blosc_static ${LIBS})
|
||||||
|
- target_include_directories(blosc_static PUBLIC ${BLOSC_INCLUDE_DIRS})
|
||||||
|
+ # With the static library, cmake has to deal with transitive dependencies
|
||||||
|
+ target_link_libraries(blosc_static PRIVATE ${LIBS})
|
||||||
|
+ target_include_directories(blosc_static PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||||
|
+ if (NOT BUILD_SHARED)
|
||||||
|
+ target_link_libraries(blosc INTERFACE blosc_static)
|
||||||
|
+ endif()
|
||||||
|
endif(BUILD_STATIC)
|
||||||
|
|
||||||
|
+
|
||||||
|
# install
|
||||||
|
if(BLOSC_INSTALL)
|
||||||
|
install(FILES blosc.h blosc-export.h DESTINATION include COMPONENT DEV)
|
||||||
|
+ set(_inst_libs "blosc")
|
||||||
|
if(BUILD_SHARED)
|
||||||
|
- install(TARGETS blosc_shared DESTINATION ${lib_dir} COMPONENT LIB)
|
||||||
|
+ list(APPEND _inst_libs blosc_shared)
|
||||||
|
endif(BUILD_SHARED)
|
||||||
|
if(BUILD_STATIC)
|
||||||
|
- install(TARGETS blosc_static DESTINATION ${lib_dir} COMPONENT DEV)
|
||||||
|
+ list(APPEND _inst_libs blosc_static)
|
||||||
|
endif(BUILD_STATIC)
|
||||||
|
+
|
||||||
|
+ install(TARGETS ${_inst_libs}
|
||||||
|
+ EXPORT BloscTargets
|
||||||
|
+ LIBRARY DESTINATION ${lib_dir}
|
||||||
|
+ ARCHIVE DESTINATION ${lib_dir}
|
||||||
|
+ RUNTIME DESTINATION bin
|
||||||
|
+ COMPONENT DEV
|
||||||
|
+ INCLUDES DESTINATION include)
|
||||||
|
endif(BLOSC_INSTALL)
|
||||||
|
diff --git a/cmake/FindLZ4.cmake b/cmake/FindLZ4.cmake
|
||||||
|
index e581a80..05de6ef 100644
|
||||||
|
--- a/cmake/FindLZ4.cmake
|
||||||
|
+++ b/cmake/FindLZ4.cmake
|
||||||
|
@@ -5,6 +5,10 @@ find_library(LZ4_LIBRARY NAMES lz4)
|
||||||
|
if (LZ4_INCLUDE_DIR AND LZ4_LIBRARY)
|
||||||
|
set(LZ4_FOUND TRUE)
|
||||||
|
message(STATUS "Found LZ4 library: ${LZ4_LIBRARY}")
|
||||||
|
+ add_library(LZ4::LZ4 UNKNOWN IMPORTED)
|
||||||
|
+ set_target_properties(LZ4::LZ4 PROPERTIES
|
||||||
|
+ IMPORTED_LOCATION ${LZ4_LIBRARY}
|
||||||
|
+ INTERFACE_INCLUDE_DIRECTORIES ${LZ4_INCLUDE_DIR})
|
||||||
|
else ()
|
||||||
|
message(STATUS "No LZ4 library found. Using internal sources.")
|
||||||
|
-endif ()
|
||||||
|
+endif ()
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/cmake/FindSnappy.cmake b/cmake/FindSnappy.cmake
|
||||||
|
index 688d4d5..21dbee1 100644
|
||||||
|
--- a/cmake/FindSnappy.cmake
|
||||||
|
+++ b/cmake/FindSnappy.cmake
|
||||||
|
@@ -3,8 +3,12 @@ find_path(SNAPPY_INCLUDE_DIR snappy-c.h)
|
||||||
|
find_library(SNAPPY_LIBRARY NAMES snappy)
|
||||||
|
|
||||||
|
if (SNAPPY_INCLUDE_DIR AND SNAPPY_LIBRARY)
|
||||||
|
- set(SNAPPY_FOUND TRUE)
|
||||||
|
+ set(Snappy_FOUND TRUE)
|
||||||
|
+ add_library(Snappy::snappy UNKNOWN IMPORTED)
|
||||||
|
+ set_target_properties(Snappy::snappy PROPERTIES
|
||||||
|
+ IMPORTED_LOCATION ${SNAPPY_LIBRARY}
|
||||||
|
+ INTERFACE_INCLUDE_DIRECTORIES ${SNAPPY_INCLUDE_DIR})
|
||||||
|
message(STATUS "Found SNAPPY library: ${SNAPPY_LIBRARY}")
|
||||||
|
else ()
|
||||||
|
message(STATUS "No snappy found. Using internal sources.")
|
||||||
|
-endif ()
|
||||||
|
+endif ()
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/cmake/FindZstd.cmake b/cmake/FindZstd.cmake
|
||||||
|
index 7db4bb9..cabc2f8 100644
|
||||||
|
--- a/cmake/FindZstd.cmake
|
||||||
|
+++ b/cmake/FindZstd.cmake
|
||||||
|
@@ -3,8 +3,12 @@ find_path(ZSTD_INCLUDE_DIR zstd.h)
|
||||||
|
find_library(ZSTD_LIBRARY NAMES zstd)
|
||||||
|
|
||||||
|
if (ZSTD_INCLUDE_DIR AND ZSTD_LIBRARY)
|
||||||
|
- set(ZSTD_FOUND TRUE)
|
||||||
|
+ set(Zstd_FOUND TRUE)
|
||||||
|
+ add_library(Zstd::Zstd UNKNOWN IMPORTED)
|
||||||
|
+ set_target_properties(Zstd::Zstd PROPERTIES
|
||||||
|
+ IMPORTED_LOCATION ${ZSTD_LIBRARY}
|
||||||
|
+ INTERFACE_INCLUDE_DIRECTORIES ${ZSTD_INCLUDE_DIR})
|
||||||
|
message(STATUS "Found Zstd library: ${ZSTD_LIBRARY}")
|
||||||
|
else ()
|
||||||
|
message(STATUS "No Zstd library found. Using internal sources.")
|
||||||
|
-endif ()
|
||||||
|
+endif ()
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/cmake_config.cmake.in b/cmake_config.cmake.in
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0f6af24
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/cmake_config.cmake.in
|
||||||
|
@@ -0,0 +1,24 @@
|
||||||
|
+include(CMakeFindDependencyMacro)
|
||||||
|
+
|
||||||
|
+include("${CMAKE_CURRENT_LIST_DIR}/BloscTargets.cmake")
|
||||||
|
+
|
||||||
|
+function(_blosc_remap_configs from_Cfg to_Cfg)
|
||||||
|
+ string(TOUPPER ${from_Cfg} from_CFG)
|
||||||
|
+ string(TOLOWER ${from_Cfg} from_cfg)
|
||||||
|
+
|
||||||
|
+ if(NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/BloscTargets-${from_cfg}.cmake)
|
||||||
|
+ foreach(tgt IN ITEMS blosc_static blosc_shared blosc)
|
||||||
|
+ if(TARGET Blosc::${tgt})
|
||||||
|
+ set_target_properties(Blosc::${tgt} PROPERTIES
|
||||||
|
+ MAP_IMPORTED_CONFIG_${from_CFG} ${to_Cfg})
|
||||||
|
+ endif()
|
||||||
|
+ endforeach()
|
||||||
|
+ endif()
|
||||||
|
+endfunction()
|
||||||
|
+
|
||||||
|
+# MSVC will try to link RelWithDebInfo or MinSizeRel target with debug config
|
||||||
|
+# if no matching installation is present which would result in link errors.
|
||||||
|
+if(MSVC)
|
||||||
|
+ _blosc_remap_configs(RelWithDebInfo Release)
|
||||||
|
+ _blosc_remap_configs(MinSizeRel Release)
|
||||||
|
+endif()
|
||||||
|
diff --git a/internal-complibs/CMakeLists.txt b/internal-complibs/CMakeLists.txt
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..4586efa
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/internal-complibs/CMakeLists.txt
|
||||||
|
@@ -0,0 +1,35 @@
|
||||||
|
+macro(add_lib_target pkg tgt incdir files)
|
||||||
|
+ string(TOUPPER ${pkg} TGT)
|
||||||
|
+ if(NOT DEACTIVATE_${TGT} AND NOT ${pkg}_FOUND)
|
||||||
|
+ add_library(${tgt}_objs OBJECT ${files})
|
||||||
|
+ add_library(${tgt} INTERFACE)
|
||||||
|
+ target_include_directories(${tgt}_objs PRIVATE $<BUILD_INTERFACE:${incdir}>)
|
||||||
|
+ target_include_directories(${tgt} INTERFACE $<BUILD_INTERFACE:${incdir}>)
|
||||||
|
+ #set_target_properties(${tgt} PROPERTIES INTERFACE_SOURCES "$<TARGET_OBJECTS:${tgt}_objs>")
|
||||||
|
+ set_target_properties(${tgt}_objs PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||||
|
+ target_sources(${tgt} INTERFACE "$<BUILD_INTERFACE:$<TARGET_OBJECTS:${tgt}_objs>>")
|
||||||
|
+ add_library(${pkg}::${tgt} ALIAS ${tgt})
|
||||||
|
+
|
||||||
|
+ # This creates dummy (empty) interface targets in the exported config.
|
||||||
|
+ install(TARGETS ${tgt} EXPORT BloscTargets INCLUDES DESTINATION include)
|
||||||
|
+ endif()
|
||||||
|
+ unset(TGT)
|
||||||
|
+endmacro()
|
||||||
|
+
|
||||||
|
+set(ZLIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib-1.2.8)
|
||||||
|
+file(GLOB ZLIB_FILES ${ZLIB_DIR}/*.c)
|
||||||
|
+add_lib_target(ZLIB ZLIB ${ZLIB_DIR} "${ZLIB_FILES}")
|
||||||
|
+
|
||||||
|
+set(SNAPPY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/snappy-1.1.1)
|
||||||
|
+file(GLOB SNAPPY_FILES ${SNAPPY_DIR}/*.cc)
|
||||||
|
+add_lib_target(Snappy snappy ${SNAPPY_DIR} "${SNAPPY_FILES}")
|
||||||
|
+
|
||||||
|
+set(LZ4_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lz4-1.9.1)
|
||||||
|
+file(GLOB LZ4_FILES ${LZ4_DIR}/*.c)
|
||||||
|
+add_lib_target(LZ4 LZ4 ${LZ4_DIR} "${LZ4_FILES}")
|
||||||
|
+
|
||||||
|
+set(ZSTD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zstd-1.4.1)
|
||||||
|
+file(GLOB ZSTD_FILES ${ZSTD_DIR}/common/*.c ${ZSTD_DIR}/compress/*.c ${ZSTD_DIR}/decompress/*.c)
|
||||||
|
+add_lib_target(Zstd Zstd ${ZSTD_DIR} "${ZSTD_FILES}")
|
||||||
|
+target_include_directories(Zstd INTERFACE $<BUILD_INTERFACE:${ZSTD_DIR}/common>)
|
||||||
|
+target_include_directories(Zstd_objs PRIVATE $<BUILD_INTERFACE:${ZSTD_DIR}/common>)
|
||||||
|
\ No newline at end of file
|
||||||
|
--
|
||||||
|
2.16.2.windows.1
|
||||||
|
|
8
deps/deps-linux.cmake
vendored
8
deps/deps-linux.cmake
vendored
|
@ -5,11 +5,11 @@ include("deps-unix-common.cmake")
|
||||||
|
|
||||||
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.sh
|
CONFIGURE_COMMAND ./bootstrap.sh
|
||||||
--with-libraries=system,filesystem,thread,log,locale,regex
|
--with-libraries=system,iostreams,filesystem,thread,log,locale,regex
|
||||||
"--prefix=${DESTDIR}/usr/local"
|
"--prefix=${DESTDIR}/usr/local"
|
||||||
BUILD_COMMAND ./b2
|
BUILD_COMMAND ./b2
|
||||||
-j ${NPROC}
|
-j ${NPROC}
|
||||||
|
@ -123,3 +123,5 @@ ExternalProject_Add(dep_wxwidgets
|
||||||
BUILD_COMMAND make "-j${NPROC}" && make -C locale allmo
|
BUILD_COMMAND make "-j${NPROC}" && make -C locale allmo
|
||||||
INSTALL_COMMAND make install
|
INSTALL_COMMAND make install
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_dependencies(dep_openvdb dep_boost)
|
23
deps/deps-macos.cmake
vendored
23
deps/deps-macos.cmake
vendored
|
@ -6,7 +6,7 @@ set(DEP_WERRORS_SDK "-Werror=partial-availability -Werror=unguarded-availability
|
||||||
set(DEP_CMAKE_OPTS
|
set(DEP_CMAKE_OPTS
|
||||||
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
|
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
|
||||||
"-DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT}"
|
"-DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT}"
|
||||||
"-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}"
|
"-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEP_OSX_TARGET}"
|
||||||
"-DCMAKE_CXX_FLAGS=${DEP_WERRORS_SDK}"
|
"-DCMAKE_CXX_FLAGS=${DEP_WERRORS_SDK}"
|
||||||
"-DCMAKE_C_FLAGS=${DEP_WERRORS_SDK}"
|
"-DCMAKE_C_FLAGS=${DEP_WERRORS_SDK}"
|
||||||
)
|
)
|
||||||
|
@ -14,28 +14,27 @@ set(DEP_CMAKE_OPTS
|
||||||
include("deps-unix-common.cmake")
|
include("deps-unix-common.cmake")
|
||||||
|
|
||||||
|
|
||||||
set(DEP_BOOST_OSX_TARGET "")
|
|
||||||
if (CMAKE_OSX_DEPLOYMENT_TARGET)
|
|
||||||
set(DEP_BOOST_OSX_TARGET "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
|
|
||||||
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.71.0/source/boost_1_71_0.tar.gz"
|
||||||
URL_HASH SHA256=bd0df411efd9a585e5a2212275f8762079fed8842264954675a4fddc46cfcf60
|
URL_HASH SHA256=96b34f7468f26a141f6020efb813f1a2f3dfb9797ecf76a7d7cbd843cc95f5bd
|
||||||
BUILD_IN_SOURCE 1
|
BUILD_IN_SOURCE 1
|
||||||
CONFIGURE_COMMAND ./bootstrap.sh
|
CONFIGURE_COMMAND ./bootstrap.sh
|
||||||
--with-libraries=system,filesystem,thread,log,locale,regex
|
--with-toolset=clang
|
||||||
|
--with-libraries=system,iostreams,filesystem,thread,log,locale,regex
|
||||||
"--prefix=${DESTDIR}/usr/local"
|
"--prefix=${DESTDIR}/usr/local"
|
||||||
BUILD_COMMAND ./b2
|
BUILD_COMMAND ./b2
|
||||||
-j ${NPROC}
|
-j ${NPROC}
|
||||||
--reconfigure
|
--reconfigure
|
||||||
|
toolset=clang
|
||||||
link=static
|
link=static
|
||||||
variant=release
|
variant=release
|
||||||
threading=multi
|
threading=multi
|
||||||
boost.locale.icu=off
|
boost.locale.icu=off
|
||||||
"cflags=-fPIC ${DEP_BOOST_OSX_TARGET}"
|
"cflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
"cxxflags=-fPIC ${DEP_BOOST_OSX_TARGET}"
|
"cxxflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
|
"mflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
|
"mmflags=-fPIC -mmacosx-version-min=${DEP_OSX_TARGET}"
|
||||||
install
|
install
|
||||||
INSTALL_COMMAND "" # b2 does that already
|
INSTALL_COMMAND "" # b2 does that already
|
||||||
)
|
)
|
||||||
|
@ -114,3 +113,5 @@ ExternalProject_Add(dep_wxwidgets
|
||||||
BUILD_COMMAND make "-j${NPROC}" && PATH=/usr/local/opt/gettext/bin/:$ENV{PATH} 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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_dependencies(dep_openvdb dep_boost)
|
81
deps/deps-unix-common.cmake
vendored
81
deps/deps-unix-common.cmake
vendored
|
@ -7,6 +7,8 @@ else ()
|
||||||
set(TBB_MINGW_WORKAROUND "")
|
set(TBB_MINGW_WORKAROUND "")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
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"
|
||||||
|
@ -53,40 +55,67 @@ find_package(Git REQUIRED)
|
||||||
|
|
||||||
ExternalProject_Add(dep_qhull
|
ExternalProject_Add(dep_qhull
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
URL "https://github.com/qhull/qhull/archive/v7.2.1.tar.gz"
|
URL "https://github.com/qhull/qhull/archive/v7.3.2.tar.gz"
|
||||||
URL_HASH SHA256=6fc251e0b75467e00943bfb7191e986fce0e1f8f6f0251f9c6ce5a843821ea78
|
URL_HASH SHA256=619c8a954880d545194bc03359404ef36a1abd2dde03678089459757fd790cb0
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DBUILD_SHARED_LIBS=OFF
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
${DEP_CMAKE_OPTS}
|
${DEP_CMAKE_OPTS}
|
||||||
PATCH_COMMAND ${GIT_EXECUTABLE} apply --ignore-space-change --ignore-whitespace ${CMAKE_CURRENT_SOURCE_DIR}/qhull-mods.patch
|
UPDATE_COMMAND ""
|
||||||
|
PATCH_COMMAND ${GIT_EXECUTABLE} apply --whitespace=fix ${CMAKE_CURRENT_SOURCE_DIR}/qhull-mods.patch
|
||||||
)
|
)
|
||||||
|
|
||||||
ExternalProject_Add(dep_libigl
|
ExternalProject_Add(dep_blosc
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
URL "https://github.com/libigl/libigl/archive/v2.0.0.tar.gz"
|
GIT_REPOSITORY https://github.com/Blosc/c-blosc.git
|
||||||
URL_HASH SHA256=42518e6b106c7209c73435fd260ed5d34edeb254852495b4c95dce2d95401328
|
GIT_TAG e63775855294b50820ef44d1b157f4de1cc38d3e #v1.17.0
|
||||||
|
DEPENDS
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
-DLIBIGL_BUILD_PYTHON=OFF
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
-DLIBIGL_BUILD_TESTS=OFF
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
-DLIBIGL_BUILD_TUTORIALS=OFF
|
-DCMAKE_DEBUG_POSTFIX=d
|
||||||
-DLIBIGL_USE_STATIC_LIBRARY=OFF #${DEP_BUILD_IGL_STATIC}
|
-DBUILD_SHARED=OFF
|
||||||
-DLIBIGL_WITHOUT_COPYLEFT=OFF
|
-DBUILD_STATIC=ON
|
||||||
-DLIBIGL_WITH_CGAL=OFF
|
-DBUILD_TESTS=OFF
|
||||||
-DLIBIGL_WITH_COMISO=OFF
|
-DBUILD_BENCHMARKS=OFF
|
||||||
-DLIBIGL_WITH_CORK=OFF
|
-DPREFER_EXTERNAL_ZLIB=ON
|
||||||
-DLIBIGL_WITH_EMBREE=OFF
|
UPDATE_COMMAND ""
|
||||||
-DLIBIGL_WITH_MATLAB=OFF
|
PATCH_COMMAND ${GIT_EXECUTABLE} apply --whitespace=fix ${CMAKE_CURRENT_SOURCE_DIR}/blosc-mods.patch
|
||||||
-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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ExternalProject_Add(dep_openexr
|
||||||
|
EXCLUDE_FROM_ALL 1
|
||||||
|
GIT_REPOSITORY https://github.com/openexr/openexr.git
|
||||||
|
GIT_TAG eae0e337c9f5117e78114fd05f7a415819df413a #v2.4.0
|
||||||
|
CMAKE_ARGS
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
|
-DBUILD_TESTING=OFF
|
||||||
|
-DPYILMBASE_ENABLE:BOOL=OFF
|
||||||
|
-DOPENEXR_VIEWERS_ENABLE:BOOL=OFF
|
||||||
|
-DOPENEXR_BUILD_UTILS:BOOL=OFF
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalProject_Add(dep_openvdb
|
||||||
|
EXCLUDE_FROM_ALL 1
|
||||||
|
GIT_REPOSITORY https://github.com/AcademySoftwareFoundation/openvdb.git
|
||||||
|
GIT_TAG aebaf8d95be5e57fd33949281ec357db4a576c2e #v6.2.1
|
||||||
|
DEPENDS dep_blosc dep_openexr dep_tbb
|
||||||
|
CMAKE_ARGS
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
|
-DCMAKE_DEBUG_POSTFIX=d
|
||||||
|
-DCMAKE_PREFIX_PATH=${DESTDIR}/usr/local
|
||||||
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
|
-DOPENVDB_BUILD_PYTHON_MODULE=OFF
|
||||||
|
-DUSE_BLOSC=ON
|
||||||
|
-DOPENVDB_CORE_SHARED=OFF
|
||||||
|
-DOPENVDB_CORE_STATIC=ON
|
||||||
|
-DTBB_STATIC=ON
|
||||||
|
-DOPENVDB_BUILD_VDB_PRINT=ON
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
PATCH_COMMAND ${GIT_EXECUTABLE} apply --whitespace=fix ${CMAKE_CURRENT_SOURCE_DIR}/openvdb-mods.patch
|
||||||
|
)
|
236
deps/deps-windows.cmake
vendored
236
deps/deps-windows.cmake
vendored
|
@ -43,6 +43,18 @@ else ()
|
||||||
set(DEP_BOOST_DEBUG "")
|
set(DEP_BOOST_DEBUG "")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
macro(add_debug_dep _dep)
|
||||||
|
if (${DEP_DEBUG})
|
||||||
|
ExternalProject_Get_Property(${_dep} BINARY_DIR)
|
||||||
|
ExternalProject_Add_Step(${_dep} build_debug
|
||||||
|
DEPENDEES build
|
||||||
|
DEPENDERS install
|
||||||
|
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
|
||||||
|
WORKING_DIRECTORY "${BINARY_DIR}"
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
ExternalProject_Add(dep_boost
|
ExternalProject_Add(dep_boost
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
URL "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz"
|
URL "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz"
|
||||||
|
@ -52,6 +64,7 @@ ExternalProject_Add(dep_boost
|
||||||
BUILD_COMMAND b2.exe
|
BUILD_COMMAND b2.exe
|
||||||
-j "${NPROC}"
|
-j "${NPROC}"
|
||||||
--with-system
|
--with-system
|
||||||
|
--with-iostreams
|
||||||
--with-filesystem
|
--with-filesystem
|
||||||
--with-thread
|
--with-thread
|
||||||
--with-log
|
--with-log
|
||||||
|
@ -68,7 +81,6 @@ ExternalProject_Add(dep_boost
|
||||||
INSTALL_COMMAND "" # b2 does that already
|
INSTALL_COMMAND "" # b2 does that already
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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"
|
||||||
|
@ -83,41 +95,25 @@ ExternalProject_Add(dep_tbb
|
||||||
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
)
|
)
|
||||||
if (${DEP_DEBUG})
|
|
||||||
ExternalProject_Get_Property(dep_tbb BINARY_DIR)
|
|
||||||
ExternalProject_Add_Step(dep_tbb build_debug
|
|
||||||
DEPENDEES build
|
|
||||||
DEPENDERS install
|
|
||||||
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
|
|
||||||
WORKING_DIRECTORY "${BINARY_DIR}"
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
|
add_debug_dep(dep_tbb)
|
||||||
|
|
||||||
ExternalProject_Add(dep_gtest
|
# ExternalProject_Add(dep_gtest
|
||||||
EXCLUDE_FROM_ALL 1
|
# EXCLUDE_FROM_ALL 1
|
||||||
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_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||||
CMAKE_ARGS
|
# CMAKE_ARGS
|
||||||
-DBUILD_GMOCK=OFF
|
# -DBUILD_GMOCK=OFF
|
||||||
-Dgtest_force_shared_crt=ON
|
# -Dgtest_force_shared_crt=ON
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
# -DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
|
# "-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
|
||||||
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
# BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||||
INSTALL_COMMAND ""
|
# INSTALL_COMMAND ""
|
||||||
)
|
# )
|
||||||
if (${DEP_DEBUG})
|
|
||||||
ExternalProject_Get_Property(dep_gtest BINARY_DIR)
|
|
||||||
ExternalProject_Add_Step(dep_gtest build_debug
|
|
||||||
DEPENDEES build
|
|
||||||
DEPENDERS install
|
|
||||||
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
|
|
||||||
WORKING_DIRECTORY "${BINARY_DIR}"
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
|
# add_debug_dep(dep_gtest)
|
||||||
|
|
||||||
ExternalProject_Add(dep_cereal
|
ExternalProject_Add(dep_cereal
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
|
@ -132,7 +128,6 @@ ExternalProject_Add(dep_cereal
|
||||||
INSTALL_COMMAND ""
|
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"
|
||||||
|
@ -151,16 +146,8 @@ ExternalProject_Add(dep_nlopt
|
||||||
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
)
|
)
|
||||||
if (${DEP_DEBUG})
|
|
||||||
ExternalProject_Get_Property(dep_nlopt BINARY_DIR)
|
|
||||||
ExternalProject_Add_Step(dep_nlopt build_debug
|
|
||||||
DEPENDEES build
|
|
||||||
DEPENDERS install
|
|
||||||
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
|
|
||||||
WORKING_DIRECTORY "${BINARY_DIR}"
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
|
add_debug_dep(dep_nlopt)
|
||||||
|
|
||||||
ExternalProject_Add(dep_zlib
|
ExternalProject_Add(dep_zlib
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
|
@ -176,15 +163,9 @@ ExternalProject_Add(dep_zlib
|
||||||
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
)
|
)
|
||||||
if (${DEP_DEBUG})
|
|
||||||
ExternalProject_Get_Property(dep_zlib BINARY_DIR)
|
add_debug_dep(dep_zlib)
|
||||||
ExternalProject_Add_Step(dep_zlib build_debug
|
|
||||||
DEPENDEES build
|
|
||||||
DEPENDERS install
|
|
||||||
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
|
|
||||||
WORKING_DIRECTORY "${BINARY_DIR}"
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
# The following steps are unfortunately needed to remove the _static suffix on libraries
|
# The following steps are unfortunately needed to remove the _static suffix on libraries
|
||||||
ExternalProject_Add_Step(dep_zlib fix_static
|
ExternalProject_Add_Step(dep_zlib fix_static
|
||||||
DEPENDEES install
|
DEPENDEES install
|
||||||
|
@ -199,7 +180,6 @@ if (${DEP_DEBUG})
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
if (${DEPS_BITS} EQUAL 32)
|
if (${DEPS_BITS} EQUAL 32)
|
||||||
set(DEP_LIBCURL_TARGET "x86")
|
set(DEP_LIBCURL_TARGET "x86")
|
||||||
else ()
|
else ()
|
||||||
|
@ -238,29 +218,21 @@ find_package(Git REQUIRED)
|
||||||
|
|
||||||
ExternalProject_Add(dep_qhull
|
ExternalProject_Add(dep_qhull
|
||||||
EXCLUDE_FROM_ALL 1
|
EXCLUDE_FROM_ALL 1
|
||||||
URL "https://github.com/qhull/qhull/archive/v7.2.1.tar.gz"
|
URL "https://github.com/qhull/qhull/archive/v7.3.2.tar.gz"
|
||||||
URL_HASH SHA256=6fc251e0b75467e00943bfb7191e986fce0e1f8f6f0251f9c6ce5a843821ea78
|
URL_HASH SHA256=619c8a954880d545194bc03359404ef36a1abd2dde03678089459757fd790cb0
|
||||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
-DBUILD_SHARED_LIBS=OFF
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
-DCMAKE_DEBUG_POSTFIX=d
|
-DCMAKE_DEBUG_POSTFIX=d
|
||||||
PATCH_COMMAND ${GIT_EXECUTABLE} apply --ignore-space-change --ignore-whitespace ${CMAKE_CURRENT_SOURCE_DIR}/qhull-mods.patch
|
UPDATE_COMMAND ""
|
||||||
|
PATCH_COMMAND ${GIT_EXECUTABLE} apply --whitespace=fix ${CMAKE_CURRENT_SOURCE_DIR}/qhull-mods.patch
|
||||||
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
)
|
)
|
||||||
|
|
||||||
if (${DEP_DEBUG})
|
add_debug_dep(dep_qhull)
|
||||||
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 "")
|
||||||
|
@ -272,49 +244,6 @@ endif ()
|
||||||
|
|
||||||
find_package(Git REQUIRED)
|
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"
|
||||||
|
@ -337,3 +266,92 @@ if (${DEP_DEBUG})
|
||||||
WORKING_DIRECTORY "${SOURCE_DIR}"
|
WORKING_DIRECTORY "${SOURCE_DIR}"
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
ExternalProject_Add(dep_blosc
|
||||||
|
EXCLUDE_FROM_ALL 1
|
||||||
|
#URL https://github.com/Blosc/c-blosc/archive/v1.17.0.zip
|
||||||
|
#URL_HASH SHA256=7463a1df566704f212263312717ab2c36b45d45cba6cd0dccebf91b2cc4b4da9
|
||||||
|
GIT_REPOSITORY https://github.com/Blosc/c-blosc.git
|
||||||
|
GIT_TAG e63775855294b50820ef44d1b157f4de1cc38d3e #v1.17.0
|
||||||
|
DEPENDS dep_zlib
|
||||||
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
|
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||||
|
CMAKE_ARGS
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
|
-DCMAKE_DEBUG_POSTFIX=d
|
||||||
|
-DBUILD_SHARED=OFF
|
||||||
|
-DBUILD_STATIC=ON
|
||||||
|
-DBUILD_TESTS=OFF
|
||||||
|
-DBUILD_BENCHMARKS=OFF
|
||||||
|
-DPREFER_EXTERNAL_ZLIB=ON
|
||||||
|
-DBLOSC_IS_SUBPROJECT:BOOL=ON
|
||||||
|
-DBLOSC_INSTALL:BOOL=ON
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
PATCH_COMMAND ${GIT_EXECUTABLE} apply --whitespace=fix ${CMAKE_CURRENT_SOURCE_DIR}/blosc-mods.patch
|
||||||
|
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
)
|
||||||
|
|
||||||
|
add_debug_dep(dep_blosc)
|
||||||
|
|
||||||
|
ExternalProject_Add(dep_openexr
|
||||||
|
EXCLUDE_FROM_ALL 1
|
||||||
|
GIT_REPOSITORY https://github.com/openexr/openexr.git
|
||||||
|
GIT_TAG eae0e337c9f5117e78114fd05f7a415819df413a #v2.4.0
|
||||||
|
DEPENDS dep_zlib
|
||||||
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
|
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||||
|
CMAKE_ARGS
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
|
-DBUILD_TESTING=OFF
|
||||||
|
-DPYILMBASE_ENABLE:BOOL=OFF
|
||||||
|
-DOPENEXR_VIEWERS_ENABLE:BOOL=OFF
|
||||||
|
-DOPENEXR_BUILD_UTILS:BOOL=OFF
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
)
|
||||||
|
|
||||||
|
add_debug_dep(dep_openexr)
|
||||||
|
|
||||||
|
ExternalProject_Add(dep_openvdb
|
||||||
|
EXCLUDE_FROM_ALL 1
|
||||||
|
#URL https://github.com/AcademySoftwareFoundation/openvdb/archive/v6.2.1.zip
|
||||||
|
#URL_HASH SHA256=dc337399dce8e1c9f21f20e97b1ce7e4933cb0a63bb3b8b734d8fcc464aa0c48
|
||||||
|
GIT_REPOSITORY https://github.com/AcademySoftwareFoundation/openvdb.git
|
||||||
|
GIT_TAG aebaf8d95be5e57fd33949281ec357db4a576c2e #v6.2.1
|
||||||
|
DEPENDS dep_blosc dep_openexr #dep_tbb dep_boost
|
||||||
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
|
CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}"
|
||||||
|
CMAKE_ARGS
|
||||||
|
-DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local
|
||||||
|
-DCMAKE_DEBUG_POSTFIX=d
|
||||||
|
-DCMAKE_PREFIX_PATH=${DESTDIR}/usr/local
|
||||||
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
|
-DOPENVDB_BUILD_PYTHON_MODULE=OFF
|
||||||
|
-DUSE_BLOSC=ON
|
||||||
|
-DOPENVDB_CORE_SHARED=OFF
|
||||||
|
-DOPENVDB_CORE_STATIC=ON
|
||||||
|
-DTBB_STATIC=ON
|
||||||
|
-DOPENVDB_BUILD_VDB_PRINT=ON
|
||||||
|
BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
PATCH_COMMAND ${GIT_EXECUTABLE} apply --whitespace=fix ${CMAKE_CURRENT_SOURCE_DIR}/openvdb-mods.patch
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
)
|
||||||
|
|
||||||
|
if (${DEP_DEBUG})
|
||||||
|
ExternalProject_Get_Property(dep_openvdb BINARY_DIR)
|
||||||
|
ExternalProject_Add_Step(dep_openvdb build_debug
|
||||||
|
DEPENDEES build
|
||||||
|
DEPENDERS install
|
||||||
|
COMMAND ${CMAKE_COMMAND} ../dep_openvdb -DOPENVDB_BUILD_VDB_PRINT=OFF
|
||||||
|
COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj
|
||||||
|
WORKING_DIRECTORY "${BINARY_DIR}"
|
||||||
|
)
|
||||||
|
endif ()
|
128
deps/igl-fixes.patch
vendored
128
deps/igl-fixes.patch
vendored
|
@ -1,128 +0,0 @@
|
||||||
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
|
|
1782
deps/openvdb-mods.patch
vendored
Normal file
1782
deps/openvdb-mods.patch
vendored
Normal file
File diff suppressed because it is too large
Load diff
144
deps/qhull-mods.patch
vendored
144
deps/qhull-mods.patch
vendored
|
@ -1,121 +1,49 @@
|
||||||
From a31ae4781a4afa60e21c70e5b4ae784bcd447c8a Mon Sep 17 00:00:00 2001
|
From 7f55a56b3d112f4dffbf21b1722f400c64bf03b1 Mon Sep 17 00:00:00 2001
|
||||||
From: tamasmeszaros <meszaros.q@gmail.com>
|
From: tamasmeszaros <meszaros.q@gmail.com>
|
||||||
Date: Thu, 6 Jun 2019 15:41:43 +0200
|
Date: Mon, 21 Oct 2019 16:52:04 +0200
|
||||||
Subject: [PATCH] prusa-slicer changes
|
Subject: [PATCH] Fix the build on macOS
|
||||||
|
|
||||||
---
|
---
|
||||||
CMakeLists.txt | 44 +++++++++++++++++++++++++++++++++++---
|
CMakeLists.txt | 10 +++++-----
|
||||||
Config.cmake.in | 2 ++
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||||
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
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
index 59dff41..20c2ec5 100644
|
index 07d3da2..14df8e9 100644
|
||||||
--- a/CMakeLists.txt
|
--- a/CMakeLists.txt
|
||||||
+++ b/CMakeLists.txt
|
+++ b/CMakeLists.txt
|
||||||
@@ -61,7 +61,7 @@
|
@@ -626,18 +626,18 @@ install(TARGETS ${qhull_TARGETS_INSTALL} EXPORT QhullTargets
|
||||||
# $DateTime: 2016/01/18 19:29:17 $$Author: bbarber $
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
project(qhull)
|
write_basic_package_version_file(
|
||||||
-cmake_minimum_required(VERSION 2.6)
|
- "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullConfigVersion.cmake"
|
||||||
+cmake_minimum_required(VERSION 3.0)
|
+ "${CMAKE_CURRENT_BINARY_DIR}/QhullExport/QhullConfigVersion.cmake"
|
||||||
|
VERSION ${qhull_VERSION}
|
||||||
|
COMPATIBILITY AnyNewerVersion
|
||||||
|
)
|
||||||
|
|
||||||
# Define qhull_VERSION in CMakeLists.txt, Makefile, qhull-exports.def, qhull_p-exports.def, qhull_r-exports.def, qhull-warn.pri
|
export(EXPORT QhullTargets
|
||||||
set(qhull_VERSION2 "2015.2 2016/01/18") # not used, See global.c, global_r.c, rbox.c, rbox_r.c
|
- FILE "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullTargets.cmake"
|
||||||
@@ -610,10 +610,48 @@ add_test(NAME user_eg3
|
+ FILE "${CMAKE_CURRENT_BINARY_DIR}/QhullExport/QhullTargets.cmake"
|
||||||
# Define install
|
NAMESPACE Qhull::
|
||||||
# ---------------------------------------
|
)
|
||||||
|
|
||||||
-install(TARGETS ${qhull_TARGETS_INSTALL}
|
configure_file(${PROJECT_SOURCE_DIR}/build/config.cmake.in
|
||||||
+install(TARGETS ${qhull_TARGETS_INSTALL} EXPORT QhullTargets
|
- "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullConfig.cmake"
|
||||||
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
|
+ "${CMAKE_CURRENT_BINARY_DIR}/QhullExport/QhullConfig.cmake"
|
||||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
@ONLY
|
||||||
- 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)
|
@@ -652,8 +652,8 @@ install(EXPORT QhullTargets
|
||||||
install(FILES ${libqhull_DOC} DESTINATION ${INCLUDE_INSTALL_DIR}/libqhull)
|
)
|
||||||
diff --git a/Config.cmake.in b/Config.cmake.in
|
install(
|
||||||
new file mode 100644
|
FILES
|
||||||
index 0000000..bc92bfe
|
- "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullConfig.cmake"
|
||||||
--- /dev/null
|
- "${CMAKE_CURRENT_BINARY_DIR}/Qhull/QhullConfigVersion.cmake"
|
||||||
+++ b/Config.cmake.in
|
+ "${CMAKE_CURRENT_BINARY_DIR}/QhullExport/QhullConfig.cmake"
|
||||||
@@ -0,0 +1,2 @@
|
+ "${CMAKE_CURRENT_BINARY_DIR}/QhullExport/QhullConfigVersion.cmake"
|
||||||
+include("${CMAKE_CURRENT_LIST_DIR}/QhullTargets.cmake")
|
DESTINATION
|
||||||
+
|
${ConfigPackageLocation}
|
||||||
diff --git a/src/libqhull_r/qhull_r-exports.def b/src/libqhull_r/qhull_r-exports.def
|
COMPONENT
|
||||||
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
|
2.17.1
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Dependency report for PrusaSlicer
|
# Dependency report for PrusaSlicer
|
||||||
## Possible dynamic linking on Linux
|
## Possible dynamic linking on Linux
|
||||||
* zlib: This should not be even mentioned in our cmake scripts but due to a bug in the system libraries of gtk it has to be linked to PrusaSlicer.
|
* zlib: Strict dependency required from the system, linked dynamically. Many other libs depend on zlib.
|
||||||
* wxWidgets: searches for wx-3.1 by default, but with cmake option `SLIC3R_WX_STABLE=ON` it will use wx-3.0 bundled with most distros.
|
* wxWidgets: searches for wx-3.1 by default, but with cmake option `SLIC3R_WX_STABLE=ON` it will use wx-3.0 bundled with most distros.
|
||||||
* libcurl
|
* libcurl
|
||||||
* tbb
|
* tbb
|
||||||
|
@ -10,13 +10,13 @@
|
||||||
* expat
|
* expat
|
||||||
* openssl
|
* openssl
|
||||||
* nlopt
|
* nlopt
|
||||||
* gtest
|
* openvdb: This library depends on other libs, namely boost, zlib, openexr, blosc (not strictly), etc...
|
||||||
|
|
||||||
## External libraries in source tree
|
## External libraries in source tree
|
||||||
* ad-mesh: Lots of customization, have to be bundled in the source tree.
|
* ad-mesh: Lots of customization, have to be bundled in the source tree.
|
||||||
* avrdude: Like ad-mesh, many customization, need to be in the source tree.
|
* avrdude: Like ad-mesh, many customization, need to be in the source tree.
|
||||||
* clipper: An important library we have to have full control over it. We also have some slicer specific modifications.
|
* clipper: An important library we have to have full control over it. We also have some slicer specific modifications.
|
||||||
* glu-libtess: This is an extract of the mesa/glu library not oficially available as a package.
|
* glu-libtess: This is an extract of the mesa/glu library not officially available as a package.
|
||||||
* imgui: no packages for debian, author suggests using in the source tree
|
* imgui: no packages for debian, author suggests using in the source tree
|
||||||
* miniz: No packages, author suggests using in the source tree
|
* miniz: No packages, author suggests using in the source tree
|
||||||
* qhull: libqhull-dev does not contain libqhullcpp => link errors. Until it is fixed, we will use the builtin version. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=925540
|
* qhull: libqhull-dev does not contain libqhullcpp => link errors. Until it is fixed, we will use the builtin version. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=925540
|
||||||
|
@ -29,5 +29,6 @@
|
||||||
* igl
|
* igl
|
||||||
* nanosvg
|
* nanosvg
|
||||||
* agg
|
* agg
|
||||||
|
* catch2: Only Arch has packages for catch2, other distros at most catch (v1.x). Being strictly header only, we bundle this in the source tree. Used for the unit-test suites.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Building PrusaSlicer on UNIX/Linux
|
# Building PrusaSlicer on UNIX/Linux
|
||||||
|
|
||||||
PrusaSlicer uses the CMake build system and requires several dependencies.
|
PrusaSlicer uses the CMake build system and requires several dependencies.
|
||||||
The dependencies can be listed in `deps/deps-linux.cmake`, although they don't necessarily need to be as recent
|
The dependencies can be listed in `deps/deps-linux.cmake` and `deps/deps-unix-common.cmake`, although they don't necessarily need to be as recent
|
||||||
as the versions listed - generally versions available on conservative Linux distros such as Debian stable or CentOS should suffice.
|
as the versions listed - generally versions available on conservative Linux distros such as Debian stable or CentOS should suffice.
|
||||||
|
|
||||||
Perl is not required any more.
|
Perl is not required any more.
|
||||||
|
|
|
@ -45,6 +45,7 @@ src/slic3r/GUI/WipeTowerDialog.cpp
|
||||||
src/slic3r/GUI/wxExtensions.cpp
|
src/slic3r/GUI/wxExtensions.cpp
|
||||||
src/slic3r/Utils/Duet.cpp
|
src/slic3r/Utils/Duet.cpp
|
||||||
src/slic3r/Utils/OctoPrint.cpp
|
src/slic3r/Utils/OctoPrint.cpp
|
||||||
|
src/slic3r/Utils/FlashAir.cpp
|
||||||
src/slic3r/Utils/PresetUpdater.cpp
|
src/slic3r/Utils/PresetUpdater.cpp
|
||||||
src/slic3r/Utils/FixModelByWin10.cpp
|
src/slic3r/Utils/FixModelByWin10.cpp
|
||||||
src/libslic3r/Zipper.cpp
|
src/libslic3r/Zipper.cpp
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
add_subdirectory(slabasebed)
|
|
||||||
add_subdirectory(slasupporttree)
|
add_subdirectory(slasupporttree)
|
||||||
|
add_subdirectory(openvdb)
|
||||||
|
|
2
sandboxes/openvdb/CMakeLists.txt
Normal file
2
sandboxes/openvdb/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
add_executable(openvdb_example openvdb_example.cpp)
|
||||||
|
target_link_libraries(openvdb_example libslic3r)
|
37
sandboxes/openvdb/openvdb_example.cpp
Normal file
37
sandboxes/openvdb/openvdb_example.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include <openvdb/openvdb.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Initialize the OpenVDB library. This must be called at least
|
||||||
|
// once per program and may safely be called multiple times.
|
||||||
|
openvdb::initialize();
|
||||||
|
// Create an empty floating-point grid with background value 0.
|
||||||
|
openvdb::FloatGrid::Ptr grid = openvdb::FloatGrid::create();
|
||||||
|
std::cout << "Testing random access:" << std::endl;
|
||||||
|
// Get an accessor for coordinate-based access to voxels.
|
||||||
|
openvdb::FloatGrid::Accessor accessor = grid->getAccessor();
|
||||||
|
// Define a coordinate with large signed indices.
|
||||||
|
openvdb::Coord xyz(1000, -200000000, 30000000);
|
||||||
|
// Set the voxel value at (1000, -200000000, 30000000) to 1.
|
||||||
|
accessor.setValue(xyz, 1.0);
|
||||||
|
// Verify that the voxel value at (1000, -200000000, 30000000) is 1.
|
||||||
|
std::cout << "Grid" << xyz << " = " << accessor.getValue(xyz) << std::endl;
|
||||||
|
// Reset the coordinates to those of a different voxel.
|
||||||
|
xyz.reset(1000, 200000000, -30000000);
|
||||||
|
// Verify that the voxel value at (1000, 200000000, -30000000) is
|
||||||
|
// the background value, 0.
|
||||||
|
std::cout << "Grid" << xyz << " = " << accessor.getValue(xyz) << std::endl;
|
||||||
|
// Set the voxel value at (1000, 200000000, -30000000) to 2.
|
||||||
|
accessor.setValue(xyz, 2.0);
|
||||||
|
// Set the voxels at the two extremes of the available coordinate space.
|
||||||
|
// For 32-bit signed coordinates these are (-2147483648, -2147483648, -2147483648)
|
||||||
|
// and (2147483647, 2147483647, 2147483647).
|
||||||
|
accessor.setValue(openvdb::Coord::min(), 3.0f);
|
||||||
|
accessor.setValue(openvdb::Coord::max(), 4.0f);
|
||||||
|
std::cout << "Testing sequential access:" << std::endl;
|
||||||
|
// Print all active ("on") voxels by means of an iterator.
|
||||||
|
for (openvdb::FloatGrid::ValueOnCIter iter = grid->cbeginValueOn(); iter; ++iter) {
|
||||||
|
std::cout << "Grid" << iter.getCoord() << " = " << *iter << std::endl;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +0,0 @@
|
||||||
add_executable(slabasebed EXCLUDE_FROM_ALL slabasebed.cpp)
|
|
||||||
target_link_libraries(slabasebed libslic3r ${Boost_LIBRARIES} ${TBB_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS})
|
|
|
@ -1,85 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <libslic3r/libslic3r.h>
|
|
||||||
#include <libslic3r/TriangleMesh.hpp>
|
|
||||||
#include <libslic3r/Tesselate.hpp>
|
|
||||||
#include <libslic3r/ClipperUtils.hpp>
|
|
||||||
#include <libslic3r/SLA/SLABasePool.hpp>
|
|
||||||
#include <libslic3r/SLA/SLABoilerPlate.hpp>
|
|
||||||
#include <libnest2d/tools/benchmark.h>
|
|
||||||
|
|
||||||
const std::string USAGE_STR = {
|
|
||||||
"Usage: slabasebed stlfilename.stl"
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace Slic3r { namespace sla {
|
|
||||||
|
|
||||||
Contour3D create_pad(const Polygons &ground_layer,
|
|
||||||
const ExPolygons &holes = {},
|
|
||||||
const PadConfig& cfg = PadConfig());
|
|
||||||
|
|
||||||
Contour3D walls(const Polygon& floor_plate, const Polygon& ceiling,
|
|
||||||
double floor_z_mm, double ceiling_z_mm,
|
|
||||||
double offset_difference_mm, ThrowOnCancel thr);
|
|
||||||
|
|
||||||
void offset(ExPolygon& sh, coord_t distance);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
TriangleMesh model;
|
|
||||||
Benchmark bench;
|
|
||||||
|
|
||||||
model.ReadSTLFile(argv[1]);
|
|
||||||
model.align_to_origin();
|
|
||||||
|
|
||||||
ExPolygons ground_slice;
|
|
||||||
sla::pad_plate(model, ground_slice, 0.1f);
|
|
||||||
if(ground_slice.empty()) return EXIT_FAILURE;
|
|
||||||
|
|
||||||
ground_slice = offset_ex(ground_slice, 0.5);
|
|
||||||
ExPolygon gndfirst; gndfirst = ground_slice.front();
|
|
||||||
sla::breakstick_holes(gndfirst, 0.5, 10, 0.3);
|
|
||||||
|
|
||||||
sla::Contour3D mesh;
|
|
||||||
|
|
||||||
bench.start();
|
|
||||||
|
|
||||||
sla::PadConfig cfg;
|
|
||||||
cfg.min_wall_height_mm = 0;
|
|
||||||
cfg.edge_radius_mm = 0;
|
|
||||||
mesh = sla::create_pad(to_polygons(ground_slice), {}, cfg);
|
|
||||||
|
|
||||||
bench.stop();
|
|
||||||
|
|
||||||
cout << "Base pool creation time: " << std::setprecision(10)
|
|
||||||
<< bench.getElapsedSec() << " seconds." << endl;
|
|
||||||
|
|
||||||
for(auto& trind : mesh.indices) {
|
|
||||||
Vec3d p0 = mesh.points[size_t(trind[0])];
|
|
||||||
Vec3d p1 = mesh.points[size_t(trind[1])];
|
|
||||||
Vec3d p2 = mesh.points[size_t(trind[2])];
|
|
||||||
Vec3d p01 = p1 - p0;
|
|
||||||
Vec3d p02 = p2 - p0;
|
|
||||||
auto a = p01.cross(p02).norm() / 2.0;
|
|
||||||
if(std::abs(a) < 1e-6) std::cout << "degenerate triangle" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// basepool.write_ascii("out.stl");
|
|
||||||
|
|
||||||
std::fstream outstream("out.obj", std::fstream::out);
|
|
||||||
mesh.to_obj(outstream);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
|
@ -167,6 +167,7 @@ int CLI::run(int argc, char **argv)
|
||||||
// sla_print_config.apply(m_print_config, true);
|
// sla_print_config.apply(m_print_config, true);
|
||||||
|
|
||||||
// Loop through transform options.
|
// Loop through transform options.
|
||||||
|
bool user_center_specified = false;
|
||||||
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;
|
||||||
|
@ -209,6 +210,7 @@ int CLI::run(int argc, char **argv)
|
||||||
for (auto &model : m_models)
|
for (auto &model : m_models)
|
||||||
model.duplicate_objects_grid(x, y, (distance > 0) ? distance : 6); // TODO: this is not the right place for setting a default
|
model.duplicate_objects_grid(x, y, (distance > 0) ? distance : 6); // TODO: this is not the right place for setting a default
|
||||||
} else if (opt_key == "center") {
|
} else if (opt_key == "center") {
|
||||||
|
user_center_specified = true;
|
||||||
for (auto &model : m_models) {
|
for (auto &model : m_models) {
|
||||||
model.add_default_instances();
|
model.add_default_instances();
|
||||||
// this affects instances:
|
// this affects instances:
|
||||||
|
@ -403,7 +405,9 @@ 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((! user_center_specified && m_print_config.has("bed_shape")) ?
|
||||||
|
BoundingBoxf(m_print_config.opt<ConfigOptionPoints>("bed_shape")->values).center() :
|
||||||
|
m_config.option<ConfigOptionPoint>("center")->value);
|
||||||
}
|
}
|
||||||
if (printer_technology == ptFFF) {
|
if (printer_technology == ptFFF) {
|
||||||
for (auto* mo : model.objects)
|
for (auto* mo : model.objects)
|
||||||
|
|
|
@ -375,7 +375,7 @@ public:
|
||||||
|
|
||||||
for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
|
for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
|
||||||
Item& itm = fixeditems[idx];
|
Item& itm = fixeditems[idx];
|
||||||
itm.markAsFixedInBin(0);
|
itm.markAsFixedInBin(itm.binId());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pck.configure(m_pconf);
|
m_pck.configure(m_pconf);
|
||||||
|
|
|
@ -22,6 +22,8 @@ add_library(libslic3r STATIC
|
||||||
Config.hpp
|
Config.hpp
|
||||||
EdgeGrid.cpp
|
EdgeGrid.cpp
|
||||||
EdgeGrid.hpp
|
EdgeGrid.hpp
|
||||||
|
ElephantFootCompensation.cpp
|
||||||
|
ElephantFootCompensation.hpp
|
||||||
ExPolygon.cpp
|
ExPolygon.cpp
|
||||||
ExPolygon.hpp
|
ExPolygon.hpp
|
||||||
ExPolygonCollection.cpp
|
ExPolygonCollection.cpp
|
||||||
|
@ -71,6 +73,8 @@ add_library(libslic3r STATIC
|
||||||
Format/STL.hpp
|
Format/STL.hpp
|
||||||
GCode/Analyzer.cpp
|
GCode/Analyzer.cpp
|
||||||
GCode/Analyzer.hpp
|
GCode/Analyzer.hpp
|
||||||
|
GCode/ThumbnailData.cpp
|
||||||
|
GCode/ThumbnailData.hpp
|
||||||
GCode/CoolingBuffer.cpp
|
GCode/CoolingBuffer.cpp
|
||||||
GCode/CoolingBuffer.hpp
|
GCode/CoolingBuffer.hpp
|
||||||
GCode/PostProcessor.cpp
|
GCode/PostProcessor.cpp
|
||||||
|
@ -222,6 +226,7 @@ target_link_libraries(libslic3r
|
||||||
qhull
|
qhull
|
||||||
semver
|
semver
|
||||||
TBB::tbb
|
TBB::tbb
|
||||||
|
# OpenVDB::openvdb
|
||||||
${CMAKE_DL_LIBS}
|
${CMAKE_DL_LIBS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -107,8 +107,7 @@ void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, ExPolygons* ex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons
|
ExPolygons PolyTreeToExPolygons(ClipperLib::PolyTree& polytree)
|
||||||
PolyTreeToExPolygons(ClipperLib::PolyTree& polytree)
|
|
||||||
{
|
{
|
||||||
ExPolygons retval;
|
ExPolygons retval;
|
||||||
for (int i = 0; i < polytree.ChildCount(); ++i)
|
for (int i = 0; i < polytree.ChildCount(); ++i)
|
||||||
|
@ -151,8 +150,7 @@ Slic3r::Polylines ClipperPaths_to_Slic3rPolylines(const ClipperLib::Paths &input
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExPolygons
|
ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input)
|
||||||
ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input)
|
|
||||||
{
|
{
|
||||||
// init Clipper
|
// init Clipper
|
||||||
ClipperLib::Clipper clipper;
|
ClipperLib::Clipper clipper;
|
||||||
|
@ -167,8 +165,7 @@ ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input)
|
||||||
return PolyTreeToExPolygons(polytree);
|
return PolyTreeToExPolygons(polytree);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipperLib::Path
|
ClipperLib::Path Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input)
|
||||||
Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input)
|
|
||||||
{
|
{
|
||||||
ClipperLib::Path retval;
|
ClipperLib::Path retval;
|
||||||
for (Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit)
|
for (Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit)
|
||||||
|
@ -176,8 +173,7 @@ Slic3rMultiPoint_to_ClipperPath(const MultiPoint &input)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipperLib::Path
|
ClipperLib::Path Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input)
|
||||||
Slic3rMultiPoint_to_ClipperPath_reversed(const Slic3r::MultiPoint &input)
|
|
||||||
{
|
{
|
||||||
ClipperLib::Path output;
|
ClipperLib::Path output;
|
||||||
output.reserve(input.points.size());
|
output.reserve(input.points.size());
|
||||||
|
@ -521,7 +517,7 @@ T _clipper_do(const ClipperLib::ClipType clipType,
|
||||||
|
|
||||||
// Fix of #117: A large fractal pyramid takes ages to slice
|
// Fix of #117: A large fractal pyramid takes ages to slice
|
||||||
// The Clipper library has difficulties processing overlapping polygons.
|
// The Clipper library has difficulties processing overlapping polygons.
|
||||||
// Namely, the function Clipper::JoinCommonEdges() has potentially a terrible time complexity if the output
|
// Namely, the function ClipperLib::JoinCommonEdges() has potentially a terrible time complexity if the output
|
||||||
// of the operation is of the PolyTree type.
|
// of the operation is of the PolyTree type.
|
||||||
// This function implmenets a following workaround:
|
// This function implmenets a following workaround:
|
||||||
// 1) Peform the Clipper operation with the output to Paths. This method handles overlaps in a reasonable time.
|
// 1) Peform the Clipper operation with the output to Paths. This method handles overlaps in a reasonable time.
|
||||||
|
@ -918,4 +914,330 @@ Polygons top_level_islands(const Slic3r::Polygons &polygons)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Outer offset shall not split the input contour into multiples. It is expected, that the solution will be non empty and it will contain just a single polygon.
|
||||||
|
ClipperLib::Paths fix_after_outer_offset(const ClipperLib::Path &input, ClipperLib::PolyFillType filltype, bool reverse_result)
|
||||||
|
{
|
||||||
|
ClipperLib::Paths solution;
|
||||||
|
if (! input.empty()) {
|
||||||
|
ClipperLib::Clipper clipper;
|
||||||
|
clipper.AddPath(input, ClipperLib::ptSubject, true);
|
||||||
|
clipper.ReverseSolution(reverse_result);
|
||||||
|
clipper.Execute(ClipperLib::ctUnion, solution, filltype, filltype);
|
||||||
|
}
|
||||||
|
return solution;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner offset may split the source contour into multiple contours, but one shall not be inside the other.
|
||||||
|
ClipperLib::Paths fix_after_inner_offset(const ClipperLib::Path &input, ClipperLib::PolyFillType filltype, bool reverse_result)
|
||||||
|
{
|
||||||
|
ClipperLib::Paths solution;
|
||||||
|
if (! input.empty()) {
|
||||||
|
ClipperLib::Clipper clipper;
|
||||||
|
clipper.AddPath(input, ClipperLib::ptSubject, true);
|
||||||
|
ClipperLib::IntRect r = clipper.GetBounds();
|
||||||
|
r.left -= 10; r.top -= 10; r.right += 10; r.bottom += 10;
|
||||||
|
if (filltype == ClipperLib::pftPositive)
|
||||||
|
clipper.AddPath({ ClipperLib::IntPoint(r.left, r.bottom), ClipperLib::IntPoint(r.left, r.top), ClipperLib::IntPoint(r.right, r.top), ClipperLib::IntPoint(r.right, r.bottom) }, ClipperLib::ptSubject, true);
|
||||||
|
else
|
||||||
|
clipper.AddPath({ ClipperLib::IntPoint(r.left, r.bottom), ClipperLib::IntPoint(r.right, r.bottom), ClipperLib::IntPoint(r.right, r.top), ClipperLib::IntPoint(r.left, r.top) }, ClipperLib::ptSubject, true);
|
||||||
|
clipper.ReverseSolution(reverse_result);
|
||||||
|
clipper.Execute(ClipperLib::ctUnion, solution, filltype, filltype);
|
||||||
|
if (! solution.empty())
|
||||||
|
solution.erase(solution.begin());
|
||||||
|
}
|
||||||
|
return solution;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit)
|
||||||
|
{
|
||||||
|
assert(contour.size() == deltas.size());
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Verify that the deltas are either all positive, or all negative.
|
||||||
|
bool positive = false;
|
||||||
|
bool negative = false;
|
||||||
|
for (float delta : deltas)
|
||||||
|
if (delta < 0.f)
|
||||||
|
negative = true;
|
||||||
|
else if (delta > 0.f)
|
||||||
|
positive = true;
|
||||||
|
assert(! (negative && positive));
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
ClipperLib::Path out;
|
||||||
|
|
||||||
|
if (deltas.size() > 2)
|
||||||
|
{
|
||||||
|
out.reserve(contour.size() * 2);
|
||||||
|
|
||||||
|
// Clamp miter limit to 2.
|
||||||
|
miter_limit = (miter_limit > 2.) ? 2. / (miter_limit * miter_limit) : 0.5;
|
||||||
|
|
||||||
|
// perpenduclar vector
|
||||||
|
auto perp = [](const Vec2d &v) -> Vec2d { return Vec2d(v.y(), - v.x()); };
|
||||||
|
|
||||||
|
// Add a new point to the output, scale by CLIPPER_OFFSET_SCALE and round to ClipperLib::cInt.
|
||||||
|
auto add_offset_point = [&out](Vec2d pt) {
|
||||||
|
pt *= double(CLIPPER_OFFSET_SCALE);
|
||||||
|
pt += Vec2d(0.5 - (pt.x() < 0), 0.5 - (pt.y() < 0));
|
||||||
|
out.emplace_back(ClipperLib::cInt(pt.x()), ClipperLib::cInt(pt.y()));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Minimum edge length, squared.
|
||||||
|
double lmin = *std::max_element(deltas.begin(), deltas.end()) * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR;
|
||||||
|
double l2min = lmin * lmin;
|
||||||
|
// Minimum angle to consider two edges to be parallel.
|
||||||
|
// Vojtech's estimate.
|
||||||
|
// const double sin_min_parallel = EPSILON + 1. / double(CLIPPER_OFFSET_SCALE);
|
||||||
|
// Implementation equal to Clipper.
|
||||||
|
const double sin_min_parallel = 1.;
|
||||||
|
|
||||||
|
// Find the last point further from pt by l2min.
|
||||||
|
Vec2d pt = contour.front().cast<double>();
|
||||||
|
size_t iprev = contour.size() - 1;
|
||||||
|
Vec2d ptprev;
|
||||||
|
for (; iprev > 0; -- iprev) {
|
||||||
|
ptprev = contour[iprev].cast<double>();
|
||||||
|
if ((ptprev - pt).squaredNorm() > l2min)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iprev != 0) {
|
||||||
|
size_t ilast = iprev;
|
||||||
|
// Normal to the (pt - ptprev) segment.
|
||||||
|
Vec2d nprev = perp(pt - ptprev).normalized();
|
||||||
|
for (size_t i = 0; ; ) {
|
||||||
|
// Find the next point further from pt by l2min.
|
||||||
|
size_t j = i + 1;
|
||||||
|
Vec2d ptnext;
|
||||||
|
for (; j <= ilast; ++ j) {
|
||||||
|
ptnext = contour[j].cast<double>();
|
||||||
|
double l2 = (ptnext - pt).squaredNorm();
|
||||||
|
if (l2 > l2min)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j > ilast) {
|
||||||
|
assert(i <= ilast);
|
||||||
|
// If the last edge is too short, merge it with the previous edge.
|
||||||
|
i = ilast;
|
||||||
|
ptnext = contour.front().cast<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal to the (ptnext - pt) segment.
|
||||||
|
Vec2d nnext = perp(ptnext - pt).normalized();
|
||||||
|
|
||||||
|
double delta = deltas[i];
|
||||||
|
double sin_a = clamp(-1., 1., cross2(nprev, nnext));
|
||||||
|
double convex = sin_a * delta;
|
||||||
|
if (convex <= - sin_min_parallel) {
|
||||||
|
// Concave corner.
|
||||||
|
add_offset_point(pt + nprev * delta);
|
||||||
|
add_offset_point(pt);
|
||||||
|
add_offset_point(pt + nnext * delta);
|
||||||
|
} else {
|
||||||
|
double dot = nprev.dot(nnext);
|
||||||
|
if (convex < sin_min_parallel && dot > 0.) {
|
||||||
|
// Nearly parallel.
|
||||||
|
add_offset_point((nprev.dot(nnext) > 0.) ? (pt + nprev * delta) : pt);
|
||||||
|
} else {
|
||||||
|
// Convex corner, possibly extremely sharp if convex < sin_min_parallel.
|
||||||
|
double r = 1. + dot;
|
||||||
|
if (r >= miter_limit)
|
||||||
|
add_offset_point(pt + (nprev + nnext) * (delta / r));
|
||||||
|
else {
|
||||||
|
double dx = std::tan(std::atan2(sin_a, dot) / 4.);
|
||||||
|
Vec2d newpt1 = pt + (nprev - perp(nprev) * dx) * delta;
|
||||||
|
Vec2d newpt2 = pt + (nnext + perp(nnext) * dx) * delta;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
Vec2d vedge = 0.5 * (newpt1 + newpt2) - pt;
|
||||||
|
double dist_norm = vedge.norm();
|
||||||
|
assert(std::abs(dist_norm - std::abs(delta)) < SCALED_EPSILON);
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
add_offset_point(newpt1);
|
||||||
|
add_offset_point(newpt2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ilast)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ptprev = pt;
|
||||||
|
nprev = nnext;
|
||||||
|
pt = ptnext;
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
ClipperLib::Path polytmp(out);
|
||||||
|
unscaleClipperPolygon(polytmp);
|
||||||
|
Slic3r::Polygon offsetted = ClipperPath_to_Slic3rPolygon(polytmp);
|
||||||
|
BoundingBox bbox = get_extents(contour);
|
||||||
|
bbox.merge(get_extents(offsetted));
|
||||||
|
static int iRun = 0;
|
||||||
|
SVG svg(debug_out_path("mittered_offset_path_scaled-%d.svg", iRun ++).c_str(), bbox);
|
||||||
|
svg.draw_outline(Polygon(contour), "blue", scale_(0.01));
|
||||||
|
svg.draw_outline(offsetted, "red", scale_(0.01));
|
||||||
|
svg.draw(contour, "blue", scale_(0.03));
|
||||||
|
svg.draw((Points)offsetted, "blue", scale_(0.03));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Verify that the deltas are all non positive.
|
||||||
|
for (const std::vector<float> &ds : deltas)
|
||||||
|
for (float delta : ds)
|
||||||
|
assert(delta <= 0.);
|
||||||
|
assert(expoly.holes.size() + 1 == deltas.size());
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
// 1) Offset the outer contour.
|
||||||
|
ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, true);
|
||||||
|
|
||||||
|
// 2) Offset the holes one by one, collect the results.
|
||||||
|
ClipperLib::Paths holes;
|
||||||
|
holes.reserve(expoly.holes.size());
|
||||||
|
for (const Polygon& hole : expoly.holes)
|
||||||
|
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, false));
|
||||||
|
|
||||||
|
// 3) Subtract holes from the contours.
|
||||||
|
ClipperLib::Paths output;
|
||||||
|
if (holes.empty())
|
||||||
|
output = std::move(contours);
|
||||||
|
else {
|
||||||
|
ClipperLib::Clipper clipper;
|
||||||
|
clipper.Clear();
|
||||||
|
clipper.AddPaths(contours, ClipperLib::ptSubject, true);
|
||||||
|
clipper.AddPaths(holes, ClipperLib::ptClip, true);
|
||||||
|
clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) Unscale the output.
|
||||||
|
unscaleClipperPolygons(output);
|
||||||
|
return ClipperPaths_to_Slic3rPolygons(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Verify that the deltas are all non positive.
|
||||||
|
for (const std::vector<float>& ds : deltas)
|
||||||
|
for (float delta : ds)
|
||||||
|
assert(delta >= 0.);
|
||||||
|
assert(expoly.holes.size() + 1 == deltas.size());
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
// 1) Offset the outer contour.
|
||||||
|
ClipperLib::Paths contours = fix_after_outer_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftPositive, false);
|
||||||
|
|
||||||
|
// 2) Offset the holes one by one, collect the results.
|
||||||
|
ClipperLib::Paths holes;
|
||||||
|
holes.reserve(expoly.holes.size());
|
||||||
|
for (const Polygon& hole : expoly.holes)
|
||||||
|
append(holes, fix_after_inner_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, true));
|
||||||
|
|
||||||
|
// 3) Subtract holes from the contours.
|
||||||
|
ClipperLib::Paths output;
|
||||||
|
if (holes.empty())
|
||||||
|
output = std::move(contours);
|
||||||
|
else {
|
||||||
|
ClipperLib::Clipper clipper;
|
||||||
|
clipper.Clear();
|
||||||
|
clipper.AddPaths(contours, ClipperLib::ptSubject, true);
|
||||||
|
clipper.AddPaths(holes, ClipperLib::ptClip, true);
|
||||||
|
clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) Unscale the output.
|
||||||
|
unscaleClipperPolygons(output);
|
||||||
|
return ClipperPaths_to_Slic3rPolygons(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExPolygons variable_offset_outer_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Verify that the deltas are all non positive.
|
||||||
|
for (const std::vector<float>& ds : deltas)
|
||||||
|
for (float delta : ds)
|
||||||
|
assert(delta >= 0.);
|
||||||
|
assert(expoly.holes.size() + 1 == deltas.size());
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
// 1) Offset the outer contour.
|
||||||
|
ClipperLib::Paths contours = fix_after_outer_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftPositive, false);
|
||||||
|
|
||||||
|
// 2) Offset the holes one by one, collect the results.
|
||||||
|
ClipperLib::Paths holes;
|
||||||
|
holes.reserve(expoly.holes.size());
|
||||||
|
for (const Polygon& hole : expoly.holes)
|
||||||
|
append(holes, fix_after_inner_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftPositive, true));
|
||||||
|
|
||||||
|
// 3) Subtract holes from the contours.
|
||||||
|
unscaleClipperPolygons(contours);
|
||||||
|
ExPolygons output;
|
||||||
|
if (holes.empty()) {
|
||||||
|
output.reserve(contours.size());
|
||||||
|
for (ClipperLib::Path &path : contours)
|
||||||
|
output.emplace_back(ClipperPath_to_Slic3rPolygon(path));
|
||||||
|
} else {
|
||||||
|
ClipperLib::Clipper clipper;
|
||||||
|
unscaleClipperPolygons(holes);
|
||||||
|
clipper.AddPaths(contours, ClipperLib::ptSubject, true);
|
||||||
|
clipper.AddPaths(holes, ClipperLib::ptClip, true);
|
||||||
|
ClipperLib::PolyTree polytree;
|
||||||
|
clipper.Execute(ClipperLib::ctDifference, polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||||
|
output = PolyTreeToExPolygons(polytree);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Verify that the deltas are all non positive.
|
||||||
|
for (const std::vector<float>& ds : deltas)
|
||||||
|
for (float delta : ds)
|
||||||
|
assert(delta <= 0.);
|
||||||
|
assert(expoly.holes.size() + 1 == deltas.size());
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
// 1) Offset the outer contour.
|
||||||
|
ClipperLib::Paths contours = fix_after_inner_offset(mittered_offset_path_scaled(expoly.contour.points, deltas.front(), miter_limit), ClipperLib::pftNegative, false);
|
||||||
|
|
||||||
|
// 2) Offset the holes one by one, collect the results.
|
||||||
|
ClipperLib::Paths holes;
|
||||||
|
holes.reserve(expoly.holes.size());
|
||||||
|
for (const Polygon& hole : expoly.holes)
|
||||||
|
append(holes, fix_after_outer_offset(mittered_offset_path_scaled(hole, deltas[1 + &hole - expoly.holes.data()], miter_limit), ClipperLib::pftNegative, true));
|
||||||
|
|
||||||
|
// 3) Subtract holes from the contours.
|
||||||
|
unscaleClipperPolygons(contours);
|
||||||
|
ExPolygons output;
|
||||||
|
if (holes.empty()) {
|
||||||
|
output.reserve(contours.size());
|
||||||
|
for (ClipperLib::Path &path : contours)
|
||||||
|
output.emplace_back(ClipperPath_to_Slic3rPolygon(path));
|
||||||
|
} else {
|
||||||
|
ClipperLib::Clipper clipper;
|
||||||
|
unscaleClipperPolygons(holes);
|
||||||
|
clipper.AddPaths(contours, ClipperLib::ptSubject, true);
|
||||||
|
clipper.AddPaths(holes, ClipperLib::ptClip, true);
|
||||||
|
ClipperLib::PolyTree polytree;
|
||||||
|
clipper.Execute(ClipperLib::ctDifference, polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||||
|
output = PolyTreeToExPolygons(polytree);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,11 @@ void safety_offset(ClipperLib::Paths* paths);
|
||||||
|
|
||||||
Polygons top_level_islands(const Slic3r::Polygons &polygons);
|
Polygons top_level_islands(const Slic3r::Polygons &polygons);
|
||||||
|
|
||||||
|
Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
|
||||||
|
Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
|
||||||
|
ExPolygons variable_offset_outer_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
|
||||||
|
ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -113,6 +113,7 @@ void EdgeGrid::Grid::create(const ExPolygonCollection &expolygons, coord_t resol
|
||||||
// m_contours has been initialized. Now fill in the edge grid.
|
// m_contours has been initialized. Now fill in the edge grid.
|
||||||
void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
|
void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
|
||||||
{
|
{
|
||||||
|
assert(resolution > 0);
|
||||||
// 1) Measure the bounding box.
|
// 1) Measure the bounding box.
|
||||||
for (size_t i = 0; i < m_contours.size(); ++ i) {
|
for (size_t i = 0; i < m_contours.size(); ++ i) {
|
||||||
const Slic3r::Points &pts = *m_contours[i];
|
const Slic3r::Points &pts = *m_contours[i];
|
||||||
|
@ -281,7 +282,11 @@ void EdgeGrid::Grid::create_from_m_contours(coord_t resolution)
|
||||||
Visitor(std::vector<std::pair<size_t, size_t>> &cell_data, std::vector<Cell> &cells, size_t cols) :
|
Visitor(std::vector<std::pair<size_t, size_t>> &cell_data, std::vector<Cell> &cells, size_t cols) :
|
||||||
cell_data(cell_data), cells(cells), cols(cols), i(0), j(0) {}
|
cell_data(cell_data), cells(cells), cols(cols), i(0), j(0) {}
|
||||||
|
|
||||||
void operator()(coord_t iy, coord_t ix) { cell_data[cells[iy*cols + ix].end++] = std::pair<size_t, size_t>(i, j); }
|
inline bool operator()(coord_t iy, coord_t ix) {
|
||||||
|
cell_data[cells[iy*cols + ix].end++] = std::pair<size_t, size_t>(i, j);
|
||||||
|
// Continue traversing the grid along the edge.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::pair<size_t, size_t>> &cell_data;
|
std::vector<std::pair<size_t, size_t>> &cell_data;
|
||||||
std::vector<Cell> &cells;
|
std::vector<Cell> &cells;
|
||||||
|
@ -1018,7 +1023,138 @@ float EdgeGrid::Grid::signed_distance_bilinear(const Point &pt) const
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment) const {
|
EdgeGrid::Grid::ClosestPointResult EdgeGrid::Grid::closest_point(const Point &pt, coord_t search_radius) const
|
||||||
|
{
|
||||||
|
BoundingBox bbox;
|
||||||
|
bbox.min = bbox.max = Point(pt(0) - m_bbox.min(0), pt(1) - m_bbox.min(1));
|
||||||
|
bbox.defined = true;
|
||||||
|
// Upper boundary, round to grid and test validity.
|
||||||
|
bbox.max(0) += search_radius;
|
||||||
|
bbox.max(1) += search_radius;
|
||||||
|
ClosestPointResult result;
|
||||||
|
if (bbox.max(0) < 0 || bbox.max(1) < 0)
|
||||||
|
return result;
|
||||||
|
bbox.max(0) /= m_resolution;
|
||||||
|
bbox.max(1) /= m_resolution;
|
||||||
|
if ((size_t)bbox.max(0) >= m_cols)
|
||||||
|
bbox.max(0) = m_cols - 1;
|
||||||
|
if ((size_t)bbox.max(1) >= m_rows)
|
||||||
|
bbox.max(1) = m_rows - 1;
|
||||||
|
// Lower boundary, round to grid and test validity.
|
||||||
|
bbox.min(0) -= search_radius;
|
||||||
|
bbox.min(1) -= search_radius;
|
||||||
|
if (bbox.min(0) < 0)
|
||||||
|
bbox.min(0) = 0;
|
||||||
|
if (bbox.min(1) < 0)
|
||||||
|
bbox.min(1) = 0;
|
||||||
|
bbox.min(0) /= m_resolution;
|
||||||
|
bbox.min(1) /= m_resolution;
|
||||||
|
// Is the interval empty?
|
||||||
|
if (bbox.min(0) > bbox.max(0) ||
|
||||||
|
bbox.min(1) > bbox.max(1))
|
||||||
|
return result;
|
||||||
|
// Traverse all cells in the bounding box.
|
||||||
|
double d_min = double(search_radius);
|
||||||
|
// Signum of the distance field at pt.
|
||||||
|
int sign_min = 0;
|
||||||
|
double l2_seg_min = 1.;
|
||||||
|
for (int r = bbox.min(1); r <= bbox.max(1); ++ r) {
|
||||||
|
for (int c = bbox.min(0); c <= bbox.max(0); ++ c) {
|
||||||
|
const Cell &cell = m_cells[r * m_cols + c];
|
||||||
|
for (size_t i = cell.begin; i < cell.end; ++ i) {
|
||||||
|
const size_t contour_idx = m_cell_data[i].first;
|
||||||
|
const Slic3r::Points &pts = *m_contours[contour_idx];
|
||||||
|
size_t ipt = m_cell_data[i].second;
|
||||||
|
// End points of the line segment.
|
||||||
|
const Slic3r::Point &p1 = pts[ipt];
|
||||||
|
const Slic3r::Point &p2 = pts[(ipt + 1 == pts.size()) ? 0 : ipt + 1];
|
||||||
|
const Slic3r::Point v_seg = p2 - p1;
|
||||||
|
const Slic3r::Point v_pt = pt - p1;
|
||||||
|
// dot(p2-p1, pt-p1)
|
||||||
|
int64_t t_pt = int64_t(v_seg(0)) * int64_t(v_pt(0)) + int64_t(v_seg(1)) * int64_t(v_pt(1));
|
||||||
|
// l2 of seg
|
||||||
|
int64_t l2_seg = int64_t(v_seg(0)) * int64_t(v_seg(0)) + int64_t(v_seg(1)) * int64_t(v_seg(1));
|
||||||
|
if (t_pt < 0) {
|
||||||
|
// Closest to p1.
|
||||||
|
double dabs = sqrt(int64_t(v_pt(0)) * int64_t(v_pt(0)) + int64_t(v_pt(1)) * int64_t(v_pt(1)));
|
||||||
|
if (dabs < d_min) {
|
||||||
|
// Previous point.
|
||||||
|
const Slic3r::Point &p0 = pts[(ipt == 0) ? (pts.size() - 1) : ipt - 1];
|
||||||
|
Slic3r::Point v_seg_prev = p1 - p0;
|
||||||
|
int64_t t2_pt = int64_t(v_seg_prev(0)) * int64_t(v_pt(0)) + int64_t(v_seg_prev(1)) * int64_t(v_pt(1));
|
||||||
|
if (t2_pt > 0) {
|
||||||
|
// Inside the wedge between the previous and the next segment.
|
||||||
|
d_min = dabs;
|
||||||
|
// Set the signum depending on whether the vertex is convex or reflex.
|
||||||
|
int64_t det = int64_t(v_seg_prev(0)) * int64_t(v_seg(1)) - int64_t(v_seg_prev(1)) * int64_t(v_seg(0));
|
||||||
|
assert(det != 0);
|
||||||
|
sign_min = (det > 0) ? 1 : -1;
|
||||||
|
result.contour_idx = contour_idx;
|
||||||
|
result.start_point_idx = ipt;
|
||||||
|
result.t = 0.;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
Vec2d vfoot = (p1 - pt).cast<double>();
|
||||||
|
double dist_foot = vfoot.norm();
|
||||||
|
double dist_foot_err = dist_foot - d_min;
|
||||||
|
assert(std::abs(dist_foot_err) < 1e-7 * d_min);
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (t_pt > l2_seg) {
|
||||||
|
// Closest to p2. Then p2 is the starting point of another segment, which shall be discovered in the same cell.
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Closest to the segment.
|
||||||
|
assert(t_pt >= 0 && t_pt <= l2_seg);
|
||||||
|
int64_t d_seg = int64_t(v_seg(1)) * int64_t(v_pt(0)) - int64_t(v_seg(0)) * int64_t(v_pt(1));
|
||||||
|
double d = double(d_seg) / sqrt(double(l2_seg));
|
||||||
|
double dabs = std::abs(d);
|
||||||
|
if (dabs < d_min) {
|
||||||
|
d_min = dabs;
|
||||||
|
sign_min = (d_seg < 0) ? -1 : ((d_seg == 0) ? 0 : 1);
|
||||||
|
l2_seg_min = l2_seg;
|
||||||
|
result.contour_idx = contour_idx;
|
||||||
|
result.start_point_idx = ipt;
|
||||||
|
result.t = t_pt;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
Vec2d foot = p1.cast<double>() * (1. - result.t / l2_seg_min) + p2.cast<double>() * (result.t / l2_seg_min);
|
||||||
|
Vec2d vfoot = foot - pt.cast<double>();
|
||||||
|
double dist_foot = vfoot.norm();
|
||||||
|
double dist_foot_err = dist_foot - d_min;
|
||||||
|
assert(std::abs(dist_foot_err) < 1e-7 * d_min);
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result.contour_idx != -1 && d_min <= double(search_radius)) {
|
||||||
|
result.distance = d_min * sign_min;
|
||||||
|
result.t /= l2_seg_min;
|
||||||
|
assert(result.t >= 0. && result.t < 1.);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
{
|
||||||
|
const Slic3r::Points &pts = *m_contours[result.contour_idx];
|
||||||
|
const Slic3r::Point &p1 = pts[result.start_point_idx];
|
||||||
|
const Slic3r::Point &p2 = pts[(result.start_point_idx + 1 == pts.size()) ? 0 : result.start_point_idx + 1];
|
||||||
|
Vec2d vfoot;
|
||||||
|
if (result.t == 0)
|
||||||
|
vfoot = p1.cast<double>() - pt.cast<double>();
|
||||||
|
else
|
||||||
|
vfoot = p1.cast<double>() * (1. - result.t) + p2.cast<double>() * result.t - pt.cast<double>();
|
||||||
|
double dist_foot = vfoot.norm();
|
||||||
|
double dist_foot_err = dist_foot - std::abs(result.distance);
|
||||||
|
assert(std::abs(dist_foot_err) < 1e-7 * std::abs(result.distance));
|
||||||
|
}
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
} else
|
||||||
|
result = ClosestPointResult();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment) const
|
||||||
|
{
|
||||||
BoundingBox bbox;
|
BoundingBox bbox;
|
||||||
bbox.min = bbox.max = Point(pt(0) - m_bbox.min(0), pt(1) - m_bbox.min(1));
|
bbox.min = bbox.max = Point(pt(0) - m_bbox.min(0), pt(1) - m_bbox.min(1));
|
||||||
bbox.defined = true;
|
bbox.defined = true;
|
||||||
|
@ -1047,7 +1183,7 @@ bool EdgeGrid::Grid::signed_distance_edges(const Point &pt, coord_t search_radiu
|
||||||
bbox.min(1) > bbox.max(1))
|
bbox.min(1) > bbox.max(1))
|
||||||
return false;
|
return false;
|
||||||
// Traverse all cells in the bounding box.
|
// Traverse all cells in the bounding box.
|
||||||
float d_min = search_radius;
|
double d_min = double(search_radius);
|
||||||
// Signum of the distance field at pt.
|
// Signum of the distance field at pt.
|
||||||
int sign_min = 0;
|
int sign_min = 0;
|
||||||
bool on_segment = false;
|
bool on_segment = false;
|
||||||
|
|
|
@ -25,6 +25,8 @@ public:
|
||||||
void create(const ExPolygons &expolygons, coord_t resolution);
|
void create(const ExPolygons &expolygons, coord_t resolution);
|
||||||
void create(const ExPolygonCollection &expolygons, coord_t resolution);
|
void create(const ExPolygonCollection &expolygons, coord_t resolution);
|
||||||
|
|
||||||
|
const std::vector<const Slic3r::Points*>& contours() const { return m_contours; }
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Test, whether the edges inside the grid intersect with the polygons provided.
|
// Test, whether the edges inside the grid intersect with the polygons provided.
|
||||||
bool intersect(const MultiPoint &polyline, bool closed);
|
bool intersect(const MultiPoint &polyline, bool closed);
|
||||||
|
@ -46,7 +48,19 @@ public:
|
||||||
float signed_distance_bilinear(const Point &pt) const;
|
float signed_distance_bilinear(const Point &pt) const;
|
||||||
|
|
||||||
// Calculate a signed distance to the contours in search_radius from the point.
|
// Calculate a signed distance to the contours in search_radius from the point.
|
||||||
bool signed_distance_edges(const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment = NULL) const;
|
struct ClosestPointResult {
|
||||||
|
size_t contour_idx = size_t(-1);
|
||||||
|
size_t start_point_idx = size_t(-1);
|
||||||
|
// Signed distance to the closest point.
|
||||||
|
double distance = std::numeric_limits<double>::max();
|
||||||
|
// Parameter of the closest point on edge starting with start_point_idx <0, 1)
|
||||||
|
double t = 0.;
|
||||||
|
|
||||||
|
bool valid() const { return contour_idx != size_t(-1); }
|
||||||
|
};
|
||||||
|
ClosestPointResult closest_point(const Point &pt, coord_t search_radius) const;
|
||||||
|
|
||||||
|
bool signed_distance_edges(const Point &pt, coord_t search_radius, coordf_t &result_min_dist, bool *pon_segment = nullptr) const;
|
||||||
|
|
||||||
// Calculate a signed distance to the contours in search_radius from the point. If no edge is found in search_radius,
|
// Calculate a signed distance to the contours in search_radius from the point. If no edge is found in search_radius,
|
||||||
// return an interpolated value from m_signed_distance_field, if it exists.
|
// return an interpolated value from m_signed_distance_field, if it exists.
|
||||||
|
@ -65,7 +79,7 @@ public:
|
||||||
std::vector<std::pair<ContourEdge, ContourEdge>> intersecting_edges() const;
|
std::vector<std::pair<ContourEdge, ContourEdge>> intersecting_edges() const;
|
||||||
bool has_intersecting_edges() const;
|
bool has_intersecting_edges() const;
|
||||||
|
|
||||||
template<typename FUNCTION> void visit_cells_intersecting_line(Slic3r::Point p1, Slic3r::Point p2, FUNCTION func) const
|
template<typename VISITOR> void visit_cells_intersecting_line(Slic3r::Point p1, Slic3r::Point p2, VISITOR &visitor) const
|
||||||
{
|
{
|
||||||
// End points of the line segment.
|
// End points of the line segment.
|
||||||
p1(0) -= m_bbox.min(0);
|
p1(0) -= m_bbox.min(0);
|
||||||
|
@ -82,8 +96,7 @@ public:
|
||||||
assert(ixb >= 0 && size_t(ixb) < m_cols);
|
assert(ixb >= 0 && size_t(ixb) < m_cols);
|
||||||
assert(iyb >= 0 && size_t(iyb) < m_rows);
|
assert(iyb >= 0 && size_t(iyb) < m_rows);
|
||||||
// Account for the end points.
|
// Account for the end points.
|
||||||
func(iy, ix);
|
if (! visitor(iy, ix) || (ix == ixb && iy == iyb))
|
||||||
if (ix == ixb && iy == iyb)
|
|
||||||
// Both ends fall into the same cell.
|
// Both ends fall into the same cell.
|
||||||
return;
|
return;
|
||||||
// Raster the centeral part of the line.
|
// Raster the centeral part of the line.
|
||||||
|
@ -113,7 +126,8 @@ public:
|
||||||
ey = int64_t(dx) * m_resolution;
|
ey = int64_t(dx) * m_resolution;
|
||||||
iy += 1;
|
iy += 1;
|
||||||
}
|
}
|
||||||
func(iy, ix);
|
if (! visitor(iy, ix))
|
||||||
|
return;
|
||||||
} while (ix != ixb || iy != iyb);
|
} while (ix != ixb || iy != iyb);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -131,7 +145,8 @@ public:
|
||||||
ey = int64_t(dx) * m_resolution;
|
ey = int64_t(dx) * m_resolution;
|
||||||
iy -= 1;
|
iy -= 1;
|
||||||
}
|
}
|
||||||
func(iy, ix);
|
if (! visitor(iy, ix))
|
||||||
|
return;
|
||||||
} while (ix != ixb || iy != iyb);
|
} while (ix != ixb || iy != iyb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +168,8 @@ public:
|
||||||
ey = int64_t(dx) * m_resolution;
|
ey = int64_t(dx) * m_resolution;
|
||||||
iy += 1;
|
iy += 1;
|
||||||
}
|
}
|
||||||
func(iy, ix);
|
if (! visitor(iy, ix))
|
||||||
|
return;
|
||||||
} while (ix != ixb || iy != iyb);
|
} while (ix != ixb || iy != iyb);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -185,7 +201,8 @@ public:
|
||||||
ey = int64_t(dx) * m_resolution;
|
ey = int64_t(dx) * m_resolution;
|
||||||
iy -= 1;
|
iy -= 1;
|
||||||
}
|
}
|
||||||
func(iy, ix);
|
if (! visitor(iy, ix))
|
||||||
|
return;
|
||||||
} while (ix != ixb || iy != iyb);
|
} while (ix != ixb || iy != iyb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
416
src/libslic3r/ElephantFootCompensation.cpp
Normal file
416
src/libslic3r/ElephantFootCompensation.cpp
Normal file
|
@ -0,0 +1,416 @@
|
||||||
|
#include "clipper/clipper_z.hpp"
|
||||||
|
|
||||||
|
#include "libslic3r.h"
|
||||||
|
#include "ClipperUtils.hpp"
|
||||||
|
#include "EdgeGrid.hpp"
|
||||||
|
#include "ExPolygon.hpp"
|
||||||
|
#include "ElephantFootCompensation.hpp"
|
||||||
|
#include "Flow.hpp"
|
||||||
|
#include "Geometry.hpp"
|
||||||
|
#include "SVG.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// #define CONTOUR_DISTANCE_DEBUG_SVG
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
struct ResampledPoint {
|
||||||
|
ResampledPoint(size_t idx_src, bool interpolated, double curve_parameter) : idx_src(idx_src), interpolated(interpolated), curve_parameter(curve_parameter) {}
|
||||||
|
|
||||||
|
size_t idx_src;
|
||||||
|
// Is this point interpolated or initial?
|
||||||
|
bool interpolated;
|
||||||
|
// Euclidean distance along the curve from the 0th point.
|
||||||
|
double curve_parameter;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<float> contour_distance(const EdgeGrid::Grid &grid, const size_t idx_contour, const Slic3r::Points &contour, const std::vector<ResampledPoint> &resampled_point_parameters, double search_radius)
|
||||||
|
{
|
||||||
|
assert(! contour.empty());
|
||||||
|
assert(contour.size() >= 2);
|
||||||
|
|
||||||
|
std::vector<float> out;
|
||||||
|
|
||||||
|
if (contour.size() > 2)
|
||||||
|
{
|
||||||
|
#ifdef CONTOUR_DISTANCE_DEBUG_SVG
|
||||||
|
static int iRun = 0;
|
||||||
|
++ iRun;
|
||||||
|
BoundingBox bbox = get_extents(contour);
|
||||||
|
bbox.merge(grid.bbox());
|
||||||
|
ExPolygon expoly_grid;
|
||||||
|
expoly_grid.contour = Polygon(*grid.contours().front());
|
||||||
|
for (size_t i = 1; i < grid.contours().size(); ++ i)
|
||||||
|
expoly_grid.holes.emplace_back(Polygon(*grid.contours()[i]));
|
||||||
|
#endif
|
||||||
|
struct Visitor {
|
||||||
|
Visitor(const EdgeGrid::Grid &grid, const size_t idx_contour, const std::vector<ResampledPoint> &resampled_point_parameters, double dist_same_contour_reject) :
|
||||||
|
grid(grid), idx_contour(idx_contour), resampled_point_parameters(resampled_point_parameters), dist_same_contour_reject(dist_same_contour_reject) {}
|
||||||
|
|
||||||
|
void init(const size_t aidx_point_start, const Point &apt_start, Vec2d dir, const double radius) {
|
||||||
|
this->idx_point_start = aidx_point_start;
|
||||||
|
this->pt = apt_start.cast<double>() + SCALED_EPSILON * dir;
|
||||||
|
dir *= radius;
|
||||||
|
this->pt_start = this->pt.cast<coord_t>();
|
||||||
|
// Trim the vector by the grid's bounding box.
|
||||||
|
const BoundingBox &bbox = this->grid.bbox();
|
||||||
|
double t = 1.;
|
||||||
|
for (size_t axis = 0; axis < 2; ++ axis) {
|
||||||
|
double dx = std::abs(dir(axis));
|
||||||
|
if (dx >= EPSILON) {
|
||||||
|
double tedge = (dir(axis) > 0) ? (double(bbox.max(axis)) - EPSILON - this->pt(axis)) : (this->pt(axis) - double(bbox.min(axis)) - EPSILON);
|
||||||
|
if (tedge < dx)
|
||||||
|
t = tedge / dx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->dir = dir;
|
||||||
|
if (t < 1.)
|
||||||
|
dir *= t;
|
||||||
|
this->pt_end = (this->pt + dir).cast<coord_t>();
|
||||||
|
this->t_min = 1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(coord_t iy, coord_t ix) {
|
||||||
|
// Called with a row and colum of the grid cell, which is intersected by a line.
|
||||||
|
auto cell_data_range = this->grid.cell_data_range(iy, ix);
|
||||||
|
bool valid = true;
|
||||||
|
for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second; ++ it_contour_and_segment) {
|
||||||
|
// End points of the line segment and their vector.
|
||||||
|
auto segment = this->grid.segment(*it_contour_and_segment);
|
||||||
|
if (Geometry::segments_intersect(segment.first, segment.second, this->pt_start, this->pt_end)) {
|
||||||
|
// The two segments intersect. Calculate the intersection.
|
||||||
|
Vec2d pt2 = segment.first.cast<double>();
|
||||||
|
Vec2d dir2 = segment.second.cast<double>() - pt2;
|
||||||
|
Vec2d vptpt2 = pt - pt2;
|
||||||
|
double denom = dir(0) * dir2(1) - dir2(0) * dir(1);
|
||||||
|
|
||||||
|
if (std::abs(denom) >= EPSILON) {
|
||||||
|
double t = cross2(dir2, vptpt2) / denom;
|
||||||
|
assert(t > - EPSILON && t < 1. + EPSILON);
|
||||||
|
bool this_valid = true;
|
||||||
|
if (it_contour_and_segment->first == idx_contour) {
|
||||||
|
// The intersected segment originates from the same contour as the starting point.
|
||||||
|
// Reject the intersection if it is close to the starting point.
|
||||||
|
// Find the start and end points of this segment
|
||||||
|
double param_lo = resampled_point_parameters[idx_point_start].curve_parameter;
|
||||||
|
double param_hi;
|
||||||
|
double param_end = resampled_point_parameters.back().curve_parameter;
|
||||||
|
{
|
||||||
|
const Slic3r::Points &ipts = *grid.contours()[it_contour_and_segment->first];
|
||||||
|
size_t ipt = it_contour_and_segment->second;
|
||||||
|
ResampledPoint key(ipt, false, 0.);
|
||||||
|
auto lower = [](const ResampledPoint& l, const ResampledPoint r) { return l.idx_src < r.idx_src || (l.idx_src == r.idx_src && int(l.interpolated) > int(r.interpolated)); };
|
||||||
|
auto it = std::lower_bound(resampled_point_parameters.begin(), resampled_point_parameters.end(), key, lower);
|
||||||
|
assert(it != resampled_point_parameters.end() && it->idx_src == ipt && ! it->interpolated);
|
||||||
|
double t2 = cross2(dir, vptpt2) / denom;
|
||||||
|
assert(t2 > - EPSILON && t2 < 1. + EPSILON);
|
||||||
|
if (++ ipt == ipts.size())
|
||||||
|
param_hi = t2 * dir2.norm();
|
||||||
|
else
|
||||||
|
param_hi = it->curve_parameter + t2 * dir2.norm();
|
||||||
|
}
|
||||||
|
if (param_lo > param_hi)
|
||||||
|
std::swap(param_lo, param_hi);
|
||||||
|
assert(param_lo >= 0. && param_lo <= param_end);
|
||||||
|
assert(param_hi >= 0. && param_hi <= param_end);
|
||||||
|
this_valid = param_hi > param_lo + dist_same_contour_reject && param_hi - param_end < param_lo - dist_same_contour_reject;
|
||||||
|
}
|
||||||
|
if (t < this->t_min) {
|
||||||
|
this->t_min = t;
|
||||||
|
valid = this_valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! valid)
|
||||||
|
this->t_min = 1.;
|
||||||
|
}
|
||||||
|
// Continue traversing the grid along the edge.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EdgeGrid::Grid &grid;
|
||||||
|
const size_t idx_contour;
|
||||||
|
const std::vector<ResampledPoint> &resampled_point_parameters;
|
||||||
|
const double dist_same_contour_reject;
|
||||||
|
|
||||||
|
size_t idx_point_start;
|
||||||
|
Point pt_start;
|
||||||
|
Point pt_end;
|
||||||
|
Vec2d pt;
|
||||||
|
Vec2d dir;
|
||||||
|
// Minium parameter along the vector (pt_end - pt_start).
|
||||||
|
double t_min;
|
||||||
|
} visitor(grid, idx_contour, resampled_point_parameters, search_radius);
|
||||||
|
|
||||||
|
const Point *pt_this = &contour.back();
|
||||||
|
size_t idx_pt_this = contour.size() - 1;
|
||||||
|
const Point *pt_prev = pt_this - 1;
|
||||||
|
// perpenduclar vector
|
||||||
|
auto perp = [](const Vec2d& v) -> Vec2d { return Vec2d(v.y(), -v.x()); };
|
||||||
|
Vec2d vprev = (*pt_this - *pt_prev).cast<double>().normalized();
|
||||||
|
out.reserve(contour.size() + 1);
|
||||||
|
for (const Point &pt_next : contour) {
|
||||||
|
Vec2d vnext = (pt_next - *pt_this).cast<double>().normalized();
|
||||||
|
Vec2d dir = - (perp(vprev) + perp(vnext)).normalized();
|
||||||
|
Vec2d dir_perp = perp(dir);
|
||||||
|
double cross = cross2(vprev, vnext);
|
||||||
|
double dot = vprev.dot(vnext);
|
||||||
|
double a = (cross < 0 || dot > 0.5) ? (M_PI / 3.) : (0.48 * acos(std::min(1., - dot)));
|
||||||
|
// Throw rays, collect distances.
|
||||||
|
std::vector<double> distances;
|
||||||
|
int num_rays = 15;
|
||||||
|
|
||||||
|
#ifdef CONTOUR_DISTANCE_DEBUG_SVG
|
||||||
|
SVG svg(debug_out_path("contour_distance_raycasted-%d-%d.svg", iRun, &pt_next - contour.data()).c_str(), bbox);
|
||||||
|
svg.draw(expoly_grid);
|
||||||
|
svg.draw_outline(Polygon(contour), "blue", scale_(0.01));
|
||||||
|
svg.draw(*pt_this, "red", scale_(0.1));
|
||||||
|
#endif /* CONTOUR_DISTANCE_DEBUG_SVG */
|
||||||
|
|
||||||
|
for (int i = - num_rays + 1; i < num_rays; ++ i) {
|
||||||
|
double angle = a * i / (int)num_rays;
|
||||||
|
double c = cos(angle);
|
||||||
|
double s = sin(angle);
|
||||||
|
Vec2d v = c * dir + s * dir_perp;
|
||||||
|
visitor.init(idx_pt_this, *pt_this, v, search_radius);
|
||||||
|
grid.visit_cells_intersecting_line(visitor.pt_start, visitor.pt_end, visitor);
|
||||||
|
distances.emplace_back(visitor.t_min);
|
||||||
|
#ifdef CONTOUR_DISTANCE_DEBUG_SVG
|
||||||
|
svg.draw(Line(visitor.pt_start, visitor.pt_end), "yellow", scale_(0.01));
|
||||||
|
if (visitor.t_min < 1.) {
|
||||||
|
Vec2d pt = visitor.pt + visitor.dir * visitor.t_min;
|
||||||
|
svg.draw(Point(pt), "red", scale_(0.1));
|
||||||
|
}
|
||||||
|
#endif /* CONTOUR_DISTANCE_DEBUG_SVG */
|
||||||
|
}
|
||||||
|
#ifdef CONTOUR_DISTANCE_DEBUG_SVG
|
||||||
|
svg.Close();
|
||||||
|
#endif /* CONTOUR_DISTANCE_DEBUG_SVG */
|
||||||
|
std::sort(distances.begin(), distances.end());
|
||||||
|
#if 0
|
||||||
|
double median = distances[distances.size() / 2];
|
||||||
|
double standard_deviation = 0;
|
||||||
|
for (double d : distances)
|
||||||
|
standard_deviation += (d - median) * (d - median);
|
||||||
|
standard_deviation = sqrt(standard_deviation / (distances.size() - 1));
|
||||||
|
double avg = 0;
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (double d : distances)
|
||||||
|
if (d > median - standard_deviation - EPSILON && d < median + standard_deviation + EPSILON) {
|
||||||
|
avg += d;
|
||||||
|
++ cnt;
|
||||||
|
}
|
||||||
|
avg /= double(cnt);
|
||||||
|
out.emplace_back(float(avg * search_radius));
|
||||||
|
#else
|
||||||
|
out.emplace_back(float(distances.front() * search_radius));
|
||||||
|
#endif
|
||||||
|
#ifdef CONTOUR_DISTANCE_DEBUG_SVG
|
||||||
|
printf("contour_distance_raycasted-%d-%d.svg - distance %lf\n", iRun, &pt_next - contour.data(), unscale<double>(out.back()));
|
||||||
|
#endif /* CONTOUR_DISTANCE_DEBUG_SVG */
|
||||||
|
pt_this = &pt_next;
|
||||||
|
idx_pt_this = &pt_next - contour.data();
|
||||||
|
vprev = vnext;
|
||||||
|
}
|
||||||
|
// Rotate the vector by one item.
|
||||||
|
out.emplace_back(out.front());
|
||||||
|
out.erase(out.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
Points resample_polygon(const Points &contour, double dist, std::vector<ResampledPoint> &resampled_point_parameters)
|
||||||
|
{
|
||||||
|
Points out;
|
||||||
|
out.reserve(contour.size());
|
||||||
|
resampled_point_parameters.reserve(contour.size());
|
||||||
|
if (contour.size() > 2) {
|
||||||
|
Vec2d pt_prev = contour.back().cast<double>();
|
||||||
|
for (const Point &pt : contour) {
|
||||||
|
size_t idx_this = &pt - contour.data();
|
||||||
|
const Vec2d pt_this = pt.cast<double>();
|
||||||
|
const Vec2d v = pt_this - pt_prev;
|
||||||
|
const double l = v.norm();
|
||||||
|
const size_t n = size_t(ceil(l / dist));
|
||||||
|
const double l_step = l / n;
|
||||||
|
for (size_t i = 1; i < n; ++ i) {
|
||||||
|
double interpolation_parameter = double(i) / n;
|
||||||
|
Vec2d new_pt = pt_prev + v * interpolation_parameter;
|
||||||
|
out.emplace_back(new_pt.cast<coord_t>());
|
||||||
|
resampled_point_parameters.emplace_back(idx_this, true, l_step);
|
||||||
|
}
|
||||||
|
out.emplace_back(pt);
|
||||||
|
resampled_point_parameters.emplace_back(idx_this, false, l_step);
|
||||||
|
pt_prev = pt_this;
|
||||||
|
}
|
||||||
|
for (size_t i = 1; i < resampled_point_parameters.size(); ++i)
|
||||||
|
resampled_point_parameters[i].curve_parameter += resampled_point_parameters[i - 1].curve_parameter;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void smooth_compensation(std::vector<float> &compensation, float strength, size_t num_iterations)
|
||||||
|
{
|
||||||
|
std::vector<float> out(compensation);
|
||||||
|
for (size_t iter = 0; iter < num_iterations; ++ iter) {
|
||||||
|
for (size_t i = 0; i < compensation.size(); ++ i) {
|
||||||
|
float prev = (i == 0) ? compensation.back() : compensation[i - 1];
|
||||||
|
float next = (i + 1 == compensation.size()) ? compensation.front() : compensation[i + 1];
|
||||||
|
float laplacian = compensation[i] * (1.f - strength) + 0.5f * strength * (prev + next);
|
||||||
|
// Compensations are negative. Only apply the laplacian if it leads to lower compensation.
|
||||||
|
out[i] = std::max(laplacian, compensation[i]);
|
||||||
|
}
|
||||||
|
out.swap(compensation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename INDEX_TYPE, typename CONTAINER>
|
||||||
|
static inline INDEX_TYPE prev_idx_cyclic(INDEX_TYPE idx, const CONTAINER &container)
|
||||||
|
{
|
||||||
|
if (idx == 0)
|
||||||
|
idx = INDEX_TYPE(container.size());
|
||||||
|
return -- idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename INDEX_TYPE, typename CONTAINER>
|
||||||
|
static inline INDEX_TYPE next_idx_cyclic(INDEX_TYPE idx, const CONTAINER &container)
|
||||||
|
{
|
||||||
|
if (++ idx == INDEX_TYPE(container.size()))
|
||||||
|
idx = 0;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U = T>
|
||||||
|
static inline T exchange(T& obj, U&& new_value)
|
||||||
|
{
|
||||||
|
T old_value = std::move(obj);
|
||||||
|
obj = std::forward<U>(new_value);
|
||||||
|
return old_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void smooth_compensation_banded(const Points &contour, float band, std::vector<float> &compensation, float strength, size_t num_iterations)
|
||||||
|
{
|
||||||
|
assert(contour.size() == compensation.size());
|
||||||
|
assert(contour.size() > 2);
|
||||||
|
std::vector<float> out(compensation);
|
||||||
|
float dist_min2 = band * band;
|
||||||
|
static constexpr bool use_min = false;
|
||||||
|
for (size_t iter = 0; iter < num_iterations; ++ iter) {
|
||||||
|
for (int i = 0; i < int(compensation.size()); ++ i) {
|
||||||
|
const Vec2f pthis = contour[i].cast<float>();
|
||||||
|
|
||||||
|
int j = prev_idx_cyclic(i, contour);
|
||||||
|
Vec2f pprev = contour[j].cast<float>();
|
||||||
|
float prev = compensation[j];
|
||||||
|
float l2 = (pthis - pprev).squaredNorm();
|
||||||
|
if (l2 < dist_min2) {
|
||||||
|
float l = sqrt(l2);
|
||||||
|
int jprev = exchange(j, prev_idx_cyclic(j, contour));
|
||||||
|
while (j != i) {
|
||||||
|
const Vec2f pp = contour[j].cast<float>();
|
||||||
|
const float lthis = (pp - pprev).norm();
|
||||||
|
const float lnext = l + lthis;
|
||||||
|
if (lnext > band) {
|
||||||
|
// Interpolate the compensation value.
|
||||||
|
prev = use_min ?
|
||||||
|
std::min(prev, lerp(compensation[jprev], compensation[j], (band - l) / lthis)) :
|
||||||
|
lerp(compensation[jprev], compensation[j], (band - l) / lthis);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev = use_min ? std::min(prev, compensation[j]) : compensation[j];
|
||||||
|
pprev = pp;
|
||||||
|
l = lnext;
|
||||||
|
jprev = exchange(j, prev_idx_cyclic(j, contour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
j = next_idx_cyclic(i, contour);
|
||||||
|
pprev = contour[j].cast<float>();
|
||||||
|
float next = compensation[j];
|
||||||
|
l2 = (pprev - pthis).squaredNorm();
|
||||||
|
if (l2 < dist_min2) {
|
||||||
|
float l = sqrt(l2);
|
||||||
|
int jprev = exchange(j, next_idx_cyclic(j, contour));
|
||||||
|
while (j != i) {
|
||||||
|
const Vec2f pp = contour[j].cast<float>();
|
||||||
|
const float lthis = (pp - pprev).norm();
|
||||||
|
const float lnext = l + lthis;
|
||||||
|
if (lnext > band) {
|
||||||
|
// Interpolate the compensation value.
|
||||||
|
next = use_min ?
|
||||||
|
std::min(next, lerp(compensation[jprev], compensation[j], (band - l) / lthis)) :
|
||||||
|
lerp(compensation[jprev], compensation[j], (band - l) / lthis);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next = use_min ? std::min(next, compensation[j]) : compensation[j];
|
||||||
|
pprev = pp;
|
||||||
|
l = lnext;
|
||||||
|
jprev = exchange(j, next_idx_cyclic(j, contour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float laplacian = compensation[i] * (1.f - strength) + 0.5f * strength * (prev + next);
|
||||||
|
// Compensations are negative. Only apply the laplacian if it leads to lower compensation.
|
||||||
|
out[i] = std::max(laplacian, compensation[i]);
|
||||||
|
}
|
||||||
|
out.swap(compensation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExPolygon elephant_foot_compensation(const ExPolygon &input_expoly, const Flow &external_perimeter_flow, const double compensation)
|
||||||
|
{
|
||||||
|
// The contour shall be wide enough to apply the external perimeter plus compensation on both sides.
|
||||||
|
double min_contour_width = double(external_perimeter_flow.scaled_width() + external_perimeter_flow.scaled_spacing());
|
||||||
|
double scaled_compensation = scale_(compensation);
|
||||||
|
double min_contour_width_compensated = min_contour_width + 2. * scaled_compensation;
|
||||||
|
// Make the search radius a bit larger for the averaging in contour_distance over a fan of rays to work.
|
||||||
|
double search_radius = min_contour_width_compensated + min_contour_width * 0.5;
|
||||||
|
|
||||||
|
EdgeGrid::Grid grid;
|
||||||
|
ExPolygon simplified = input_expoly.simplify(SCALED_EPSILON).front();
|
||||||
|
BoundingBox bbox = get_extents(simplified.contour);
|
||||||
|
bbox.offset(SCALED_EPSILON);
|
||||||
|
grid.set_bbox(bbox);
|
||||||
|
grid.create(simplified, coord_t(0.7 * search_radius));
|
||||||
|
std::vector<std::vector<float>> deltas;
|
||||||
|
deltas.reserve(simplified.holes.size() + 1);
|
||||||
|
ExPolygon resampled(simplified);
|
||||||
|
double resample_interval = scale_(0.5);
|
||||||
|
for (size_t idx_contour = 0; idx_contour <= simplified.holes.size(); ++ idx_contour) {
|
||||||
|
Polygon &poly = (idx_contour == 0) ? resampled.contour : resampled.holes[idx_contour - 1];
|
||||||
|
std::vector<ResampledPoint> resampled_point_parameters;
|
||||||
|
poly.points = resample_polygon(poly.points, resample_interval, resampled_point_parameters);
|
||||||
|
std::vector<float> dists = contour_distance(grid, idx_contour, poly.points, resampled_point_parameters, search_radius);
|
||||||
|
for (float &d : dists) {
|
||||||
|
// printf("Point %d, Distance: %lf\n", int(&d - dists.data()), unscale<double>(d));
|
||||||
|
// Convert contour width to available compensation distance.
|
||||||
|
if (d < min_contour_width)
|
||||||
|
d = 0.f;
|
||||||
|
else if (d > min_contour_width_compensated)
|
||||||
|
d = - float(scaled_compensation);
|
||||||
|
else
|
||||||
|
d = - (d - float(min_contour_width)) / 2.f;
|
||||||
|
assert(d >= - float(scaled_compensation) && d <= 0.f);
|
||||||
|
}
|
||||||
|
// smooth_compensation(dists, 0.4f, 10);
|
||||||
|
smooth_compensation_banded(poly.points, float(0.8 * resample_interval), dists, 0.3f, 3);
|
||||||
|
deltas.emplace_back(dists);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExPolygons out = variable_offset_inner_ex(resampled, deltas, 2.);
|
||||||
|
return out.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &external_perimeter_flow, const double compensation)
|
||||||
|
{
|
||||||
|
ExPolygons out;
|
||||||
|
out.reserve(input.size());
|
||||||
|
for (const ExPolygon &expoly : input)
|
||||||
|
out.emplace_back(elephant_foot_compensation(expoly, external_perimeter_flow, compensation));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
16
src/libslic3r/ElephantFootCompensation.hpp
Normal file
16
src/libslic3r/ElephantFootCompensation.hpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef slic3r_ElephantFootCompensation_hpp_
|
||||||
|
#define slic3r_ElephantFootCompensation_hpp_
|
||||||
|
|
||||||
|
#include "libslic3r.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class Flow;
|
||||||
|
|
||||||
|
ExPolygon elephant_foot_compensation(const ExPolygon &input, const Flow &external_perimeter_flow, const double compensation);
|
||||||
|
ExPolygons elephant_foot_compensation(const ExPolygons &input, const Flow &external_perimeter_flow, const double compensation);
|
||||||
|
|
||||||
|
} // Slic3r
|
||||||
|
|
||||||
|
#endif /* slic3r_ElephantFootCompensation_hpp_ */
|
|
@ -28,6 +28,8 @@ public:
|
||||||
explicit ExPolygon(Polygon &&contour, Polygon &&hole) : contour(std::move(contour)) { holes.emplace_back(std::move(hole)); }
|
explicit ExPolygon(Polygon &&contour, Polygon &&hole) : contour(std::move(contour)) { holes.emplace_back(std::move(hole)); }
|
||||||
explicit ExPolygon(const Points &contour, const Points &hole) : contour(contour) { holes.emplace_back(hole); }
|
explicit ExPolygon(const Points &contour, const Points &hole) : contour(contour) { holes.emplace_back(hole); }
|
||||||
explicit ExPolygon(Points &&contour, Polygon &&hole) : contour(std::move(contour)) { holes.emplace_back(std::move(hole)); }
|
explicit ExPolygon(Points &&contour, Polygon &&hole) : contour(std::move(contour)) { holes.emplace_back(std::move(hole)); }
|
||||||
|
ExPolygon(std::initializer_list<Point> contour) : contour(contour) {}
|
||||||
|
ExPolygon(std::initializer_list<Point> contour, std::initializer_list<Point> hole) : contour(contour), holes({ hole }) {}
|
||||||
|
|
||||||
ExPolygon& operator=(const ExPolygon &other) { contour = other.contour; holes = other.holes; return *this; }
|
ExPolygon& operator=(const ExPolygon &other) { contour = other.contour; holes = other.holes; return *this; }
|
||||||
ExPolygon& operator=(ExPolygon &&other) { contour = std::move(other.contour); holes = std::move(other.holes); return *this; }
|
ExPolygon& operator=(ExPolygon &&other) { contour = std::move(other.contour); holes = std::move(other.holes); return *this; }
|
||||||
|
@ -77,6 +79,9 @@ public:
|
||||||
Lines lines() const;
|
Lines lines() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const ExPolygon &lhs, const ExPolygon &rhs) { return lhs.contour == rhs.contour && lhs.holes == rhs.holes; }
|
||||||
|
inline bool operator!=(const ExPolygon &lhs, const ExPolygon &rhs) { return lhs.contour != rhs.contour || lhs.holes != rhs.holes; }
|
||||||
|
|
||||||
// Count a nuber of polygons stored inside the vector of expolygons.
|
// Count a nuber of polygons stored inside the vector of expolygons.
|
||||||
// Useful for allocating space for polygons when converting expolygons to polygons.
|
// Useful for allocating space for polygons when converting expolygons to polygons.
|
||||||
inline size_t number_polygons(const ExPolygons &expolys)
|
inline size_t number_polygons(const ExPolygons &expolys)
|
||||||
|
@ -301,6 +306,15 @@ inline bool expolygons_contain(ExPolygons &expolys, const Point &pt)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline ExPolygons expolygons_simplify(const ExPolygons &expolys, double tolerance)
|
||||||
|
{
|
||||||
|
ExPolygons out;
|
||||||
|
out.reserve(expolys.size());
|
||||||
|
for (const ExPolygon &exp : expolys)
|
||||||
|
exp.simplify(tolerance, &out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
extern BoundingBox get_extents(const ExPolygon &expolygon);
|
extern BoundingBox get_extents(const ExPolygon &expolygon);
|
||||||
extern BoundingBox get_extents(const ExPolygons &expolygons);
|
extern BoundingBox get_extents(const ExPolygons &expolygons);
|
||||||
extern BoundingBox get_extents_rotated(const ExPolygon &poly, double angle);
|
extern BoundingBox get_extents_rotated(const ExPolygon &poly, double angle);
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
#include "../Utils.hpp"
|
#include "../Utils.hpp"
|
||||||
#include "../GCode.hpp"
|
#include "../GCode.hpp"
|
||||||
#include "../Geometry.hpp"
|
#include "../Geometry.hpp"
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include "../GCode/ThumbnailData.hpp"
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
#include "../I18N.hpp"
|
#include "../I18N.hpp"
|
||||||
|
|
||||||
|
@ -40,6 +43,9 @@ const std::string MODEL_EXTENSION = ".model";
|
||||||
const std::string MODEL_FILE = "3D/3dmodel.model"; // << this is the only format of the string which works with CURA
|
const std::string MODEL_FILE = "3D/3dmodel.model"; // << this is the only format of the string which works with CURA
|
||||||
const std::string CONTENT_TYPES_FILE = "[Content_Types].xml";
|
const std::string CONTENT_TYPES_FILE = "[Content_Types].xml";
|
||||||
const std::string RELATIONSHIPS_FILE = "_rels/.rels";
|
const std::string RELATIONSHIPS_FILE = "_rels/.rels";
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
const std::string THUMBNAIL_FILE = "Metadata/thumbnail.png";
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config";
|
const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config";
|
||||||
const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config";
|
const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config";
|
||||||
const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt";
|
const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt";
|
||||||
|
@ -1806,11 +1812,22 @@ namespace Slic3r {
|
||||||
typedef std::map<int, ObjectData> IdToObjectDataMap;
|
typedef std::map<int, ObjectData> IdToObjectDataMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
bool save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data = nullptr);
|
||||||
|
#else
|
||||||
bool save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config);
|
bool save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
bool _save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data);
|
||||||
|
#else
|
||||||
bool _save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config);
|
bool _save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
|
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
bool _add_relationships_file_to_archive(mz_zip_archive& archive);
|
bool _add_relationships_file_to_archive(mz_zip_archive& archive);
|
||||||
bool _add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data);
|
bool _add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data);
|
||||||
bool _add_object_to_model_stream(std::stringstream& stream, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets);
|
bool _add_object_to_model_stream(std::stringstream& stream, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets);
|
||||||
|
@ -1823,13 +1840,25 @@ namespace Slic3r {
|
||||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data);
|
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data)
|
||||||
|
{
|
||||||
|
clear_errors();
|
||||||
|
return _save_model_to_file(filename, model, config, thumbnail_data);
|
||||||
|
}
|
||||||
|
#else
|
||||||
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config)
|
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config)
|
||||||
{
|
{
|
||||||
clear_errors();
|
clear_errors();
|
||||||
return _save_model_to_file(filename, model, config);
|
return _save_model_to_file(filename, model, config);
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
bool _3MF_Exporter::_save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data)
|
||||||
|
#else
|
||||||
bool _3MF_Exporter::_save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config)
|
bool _3MF_Exporter::_save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config)
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
{
|
{
|
||||||
mz_zip_archive archive;
|
mz_zip_archive archive;
|
||||||
mz_zip_zero_struct(&archive);
|
mz_zip_zero_struct(&archive);
|
||||||
|
@ -1848,6 +1877,19 @@ namespace Slic3r {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
if ((thumbnail_data != nullptr) && thumbnail_data->is_valid())
|
||||||
|
{
|
||||||
|
// Adds the file Metadata/thumbnail.png.
|
||||||
|
if (!_add_thumbnail_file_to_archive(archive, *thumbnail_data))
|
||||||
|
{
|
||||||
|
close_zip_writer(&archive);
|
||||||
|
boost::filesystem::remove(filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// Adds relationships file ("_rels/.rels").
|
// Adds relationships file ("_rels/.rels").
|
||||||
// The content of this file is the same for each PrusaSlicer 3mf.
|
// The content of this file is the same for each PrusaSlicer 3mf.
|
||||||
// The relationshis file contains a reference to the geometry file "3D/3dmodel.model", the name was chosen to be compatible with CURA.
|
// The relationshis file contains a reference to the geometry file "3D/3dmodel.model", the name was chosen to be compatible with CURA.
|
||||||
|
@ -1941,6 +1983,9 @@ namespace Slic3r {
|
||||||
stream << "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n";
|
stream << "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n";
|
||||||
stream << " <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" />\n";
|
stream << " <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" />\n";
|
||||||
stream << " <Default Extension=\"model\" ContentType=\"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\" />\n";
|
stream << " <Default Extension=\"model\" ContentType=\"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\" />\n";
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
stream << " <Default Extension=\"png\" ContentType=\"image/png\" />\n";
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
stream << "</Types>";
|
stream << "</Types>";
|
||||||
|
|
||||||
std::string out = stream.str();
|
std::string out = stream.str();
|
||||||
|
@ -1954,12 +1999,35 @@ namespace Slic3r {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
bool _3MF_Exporter::_add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
|
||||||
|
size_t png_size = 0;
|
||||||
|
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)thumbnail_data.pixels.data(), thumbnail_data.width, thumbnail_data.height, 4, &png_size, MZ_DEFAULT_LEVEL, 1);
|
||||||
|
if (png_data != nullptr)
|
||||||
|
{
|
||||||
|
res = mz_zip_writer_add_mem(&archive, THUMBNAIL_FILE.c_str(), (const void*)png_data, png_size, MZ_DEFAULT_COMPRESSION);
|
||||||
|
mz_free(png_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
add_error("Unable to add thumbnail file to archive");
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
bool _3MF_Exporter::_add_relationships_file_to_archive(mz_zip_archive& archive)
|
bool _3MF_Exporter::_add_relationships_file_to_archive(mz_zip_archive& archive)
|
||||||
{
|
{
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||||
stream << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n";
|
stream << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n";
|
||||||
stream << " <Relationship Target=\"/" << MODEL_FILE << "\" Id=\"rel-1\" Type=\"http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel\" />\n";
|
stream << " <Relationship Target=\"/" << MODEL_FILE << "\" Id=\"rel-1\" Type=\"http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel\" />\n";
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
stream << " <Relationship Target=\"/" << THUMBNAIL_FILE << "\" Id=\"rel-2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail\" />\n";
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
stream << "</Relationships>";
|
stream << "</Relationships>";
|
||||||
|
|
||||||
std::string out = stream.str();
|
std::string out = stream.str();
|
||||||
|
@ -2453,13 +2521,21 @@ namespace Slic3r {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data)
|
||||||
|
#else
|
||||||
bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config)
|
bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config)
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
{
|
{
|
||||||
if ((path == nullptr) || (model == nullptr))
|
if ((path == nullptr) || (model == nullptr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_3MF_Exporter exporter;
|
_3MF_Exporter exporter;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
bool res = exporter.save_model_to_file(path, *model, config, thumbnail_data);
|
||||||
|
#else
|
||||||
bool res = exporter.save_model_to_file(path, *model, config);
|
bool res = exporter.save_model_to_file(path, *model, config);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
exporter.log_errors();
|
exporter.log_errors();
|
||||||
|
|
|
@ -22,13 +22,20 @@ namespace Slic3r {
|
||||||
|
|
||||||
class Model;
|
class Model;
|
||||||
class DynamicPrintConfig;
|
class DynamicPrintConfig;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
struct ThumbnailData;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// Load the content of a 3mf file into the given model and preset bundle.
|
// Load the content of a 3mf file into the given model and preset bundle.
|
||||||
extern bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model, bool check_version);
|
extern bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model, bool check_version);
|
||||||
|
|
||||||
// Save the given model and the config data contained in the given Print into a 3mf file.
|
// Save the given model and the config data contained in the given Print into a 3mf file.
|
||||||
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
|
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
extern bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data = nullptr);
|
||||||
|
#else
|
||||||
extern bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config);
|
extern bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
}; // namespace Slic3r
|
}; // namespace Slic3r
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
#include "GCode/PrintExtents.hpp"
|
#include "GCode/PrintExtents.hpp"
|
||||||
#include "GCode/WipeTower.hpp"
|
#include "GCode/WipeTower.hpp"
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include "GCode/ThumbnailData.hpp"
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
#include "ShortestPath.hpp"
|
#include "ShortestPath.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
|
||||||
|
@ -18,6 +21,9 @@
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include <boost/beast/core/detail/base64.hpp>
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
#include <boost/nowide/iostream.hpp>
|
#include <boost/nowide/iostream.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
|
@ -29,6 +35,10 @@
|
||||||
|
|
||||||
#include <Shiny/Shiny.h>
|
#include <Shiny/Shiny.h>
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE
|
||||||
|
#include "miniz_extension.hpp"
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Enable debugging and asserts, even in the release build.
|
// Enable debugging and asserts, even in the release build.
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
@ -543,7 +553,7 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
|
||||||
//FIXME should we use the printing extruders instead?
|
//FIXME should we use the printing extruders instead?
|
||||||
double gap_over_supports = object.config().support_material_contact_distance;
|
double gap_over_supports = object.config().support_material_contact_distance;
|
||||||
// FIXME should we test object.config().support_material_synchronize_layers ? Currently the support layers are synchronized with object layers iff soluble supports.
|
// FIXME should we test object.config().support_material_synchronize_layers ? Currently the support layers are synchronized with object layers iff soluble supports.
|
||||||
assert(gap_over_supports != 0. || object.config().support_material_synchronize_layers);
|
assert(! object.config().support_material || gap_over_supports != 0. || object.config().support_material_synchronize_layers);
|
||||||
if (gap_over_supports != 0.) {
|
if (gap_over_supports != 0.) {
|
||||||
gap_over_supports = std::max(0., gap_over_supports);
|
gap_over_supports = std::max(0., gap_over_supports);
|
||||||
// Not a soluble support,
|
// Not a soluble support,
|
||||||
|
@ -652,7 +662,11 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
|
||||||
return layers_to_print;
|
return layers_to_print;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, const std::vector<ThumbnailData>* thumbnail_data)
|
||||||
|
#else
|
||||||
void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_data)
|
void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_data)
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
{
|
{
|
||||||
PROFILE_CLEAR();
|
PROFILE_CLEAR();
|
||||||
|
|
||||||
|
@ -678,7 +692,11 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_placeholder_parser_failed_templates.clear();
|
m_placeholder_parser_failed_templates.clear();
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
this->_do_export(*print, file, thumbnail_data);
|
||||||
|
#else
|
||||||
this->_do_export(*print, file);
|
this->_do_export(*print, file);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
fflush(file);
|
fflush(file);
|
||||||
if (ferror(file)) {
|
if (ferror(file)) {
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
@ -742,7 +760,11 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||||
PROFILE_OUTPUT(debug_out_path("gcode-export-profile.txt").c_str());
|
PROFILE_OUTPUT(debug_out_path("gcode-export-profile.txt").c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void GCode::_do_export(Print& print, FILE* file, const std::vector<ThumbnailData>* thumbnail_data)
|
||||||
|
#else
|
||||||
void GCode::_do_export(Print &print, FILE *file)
|
void GCode::_do_export(Print &print, FILE *file)
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
{
|
{
|
||||||
PROFILE_FUNC();
|
PROFILE_FUNC();
|
||||||
|
|
||||||
|
@ -778,22 +800,26 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||||
{
|
{
|
||||||
m_silent_time_estimator.reset();
|
m_silent_time_estimator.reset();
|
||||||
m_silent_time_estimator.set_dialect(print.config().gcode_flavor);
|
m_silent_time_estimator.set_dialect(print.config().gcode_flavor);
|
||||||
m_silent_time_estimator.set_max_acceleration((float)print.config().machine_max_acceleration_extruding.values[1]);
|
/* "Stealth mode" values can be just a copy of "normal mode" values
|
||||||
m_silent_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values[1]);
|
* (when they aren't input for a printer preset).
|
||||||
m_silent_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values[1]);
|
* Thus, use back value from values, instead of second one, which could be absent
|
||||||
m_silent_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values[1]);
|
*/
|
||||||
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values[1]);
|
m_silent_time_estimator.set_max_acceleration((float)print.config().machine_max_acceleration_extruding.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values[1]);
|
m_silent_time_estimator.set_retract_acceleration((float)print.config().machine_max_acceleration_retracting.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values[1]);
|
m_silent_time_estimator.set_minimum_feedrate((float)print.config().machine_min_extruding_rate.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values[1]);
|
m_silent_time_estimator.set_minimum_travel_feedrate((float)print.config().machine_min_travel_rate.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values[1]);
|
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, (float)print.config().machine_max_acceleration_x.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values[1]);
|
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, (float)print.config().machine_max_acceleration_y.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values[1]);
|
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, (float)print.config().machine_max_acceleration_z.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values[1]);
|
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, (float)print.config().machine_max_acceleration_e.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values[1]);
|
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, (float)print.config().machine_max_feedrate_x.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values[1]);
|
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, (float)print.config().machine_max_feedrate_y.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values[1]);
|
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, (float)print.config().machine_max_feedrate_z.values.back());
|
||||||
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values[1]);
|
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, (float)print.config().machine_max_feedrate_e.values.back());
|
||||||
|
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, (float)print.config().machine_max_jerk_x.values.back());
|
||||||
|
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, (float)print.config().machine_max_jerk_y.values.back());
|
||||||
|
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, (float)print.config().machine_max_jerk_z.values.back());
|
||||||
|
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, (float)print.config().machine_max_jerk_e.values.back());
|
||||||
if (print.config().single_extruder_multi_material) {
|
if (print.config().single_extruder_multi_material) {
|
||||||
// As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
|
// As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
|
||||||
// are considered to be active for the single extruder multi-material printers only.
|
// are considered to be active for the single extruder multi-material printers only.
|
||||||
|
@ -930,6 +956,77 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||||
|
|
||||||
// Write information on the generator.
|
// Write information on the generator.
|
||||||
_write_format(file, "; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
_write_format(file, "; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
// Write thumbnails using base64 encoding
|
||||||
|
if (thumbnail_data != nullptr)
|
||||||
|
{
|
||||||
|
const unsigned int max_row_length = 78;
|
||||||
|
|
||||||
|
for (const ThumbnailData& data : *thumbnail_data)
|
||||||
|
{
|
||||||
|
if (data.is_valid())
|
||||||
|
{
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE
|
||||||
|
size_t png_size = 0;
|
||||||
|
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)data.pixels.data(), data.width, data.height, 4, &png_size, MZ_DEFAULT_LEVEL, 1);
|
||||||
|
if (png_data != nullptr)
|
||||||
|
{
|
||||||
|
_write_format(file, "\n;\n; thumbnail begin %dx%d\n", data.width, data.height);
|
||||||
|
|
||||||
|
std::string encoded = boost::beast::detail::base64_encode((const std::uint8_t*)png_data, png_size);
|
||||||
|
|
||||||
|
unsigned int row_count = 0;
|
||||||
|
while (encoded.length() > max_row_length)
|
||||||
|
{
|
||||||
|
_write_format(file, "; %s\n", encoded.substr(0, max_row_length).c_str());
|
||||||
|
encoded = encoded.substr(max_row_length);
|
||||||
|
++row_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoded.length() > 0)
|
||||||
|
_write_format(file, "; %s\n", encoded.c_str());
|
||||||
|
|
||||||
|
_write(file, "; thumbnail end\n;\n");
|
||||||
|
|
||||||
|
mz_free(png_data);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
_write_format(file, "\n;\n; thumbnail begin %dx%d\n", data.width, data.height);
|
||||||
|
|
||||||
|
size_t row_size = 4 * data.width;
|
||||||
|
for (int r = (int)data.height - 1; r >= 0; --r)
|
||||||
|
{
|
||||||
|
std::string encoded = boost::beast::detail::base64_encode((const std::uint8_t*)(data.pixels.data() + r * row_size), row_size);
|
||||||
|
unsigned int row_count = 0;
|
||||||
|
while (encoded.length() > max_row_length)
|
||||||
|
{
|
||||||
|
if (row_count == 0)
|
||||||
|
_write_format(file, "; %s\n", encoded.substr(0, max_row_length).c_str());
|
||||||
|
else
|
||||||
|
_write_format(file, ";>%s\n", encoded.substr(0, max_row_length).c_str());
|
||||||
|
|
||||||
|
encoded = encoded.substr(max_row_length);
|
||||||
|
++row_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoded.length() > 0)
|
||||||
|
{
|
||||||
|
if (row_count == 0)
|
||||||
|
_write_format(file, "; %s\n", encoded.c_str());
|
||||||
|
else
|
||||||
|
_write_format(file, ";>%s\n", encoded.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_write(file, "; thumbnail end\n;\n");
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE
|
||||||
|
}
|
||||||
|
print.throw_if_canceled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// Write notes (content of the Print Settings tab -> Notes)
|
// Write notes (content of the Print Settings tab -> Notes)
|
||||||
{
|
{
|
||||||
std::list<std::string> lines;
|
std::list<std::string> lines;
|
||||||
|
@ -971,6 +1068,9 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||||
_writeln(file, GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag);
|
_writeln(file, GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hold total number of print toolchanges. Check for negative toolchanges (single extruder mode) and set to 0 (no tool change).
|
||||||
|
int total_toolchanges = std::max(0, print.wipe_tower_data().number_of_toolchanges);
|
||||||
|
|
||||||
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
||||||
m_placeholder_parser = print.placeholder_parser();
|
m_placeholder_parser = print.placeholder_parser();
|
||||||
m_placeholder_parser.update_timestamp();
|
m_placeholder_parser.update_timestamp();
|
||||||
|
@ -1033,6 +1133,7 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||||
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
|
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
|
||||||
m_placeholder_parser.set("has_wipe_tower", has_wipe_tower);
|
m_placeholder_parser.set("has_wipe_tower", has_wipe_tower);
|
||||||
m_placeholder_parser.set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming);
|
m_placeholder_parser.set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming);
|
||||||
|
m_placeholder_parser.set("total_toolchanges", total_toolchanges);
|
||||||
std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config().start_gcode.value, initial_extruder_id);
|
std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config().start_gcode.value, initial_extruder_id);
|
||||||
// Set bed temperature if the start G-code does not contain any bed temp control G-codes.
|
// Set bed temperature if the start G-code does not contain any bed temp control G-codes.
|
||||||
this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true);
|
this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true);
|
||||||
|
@ -1283,7 +1384,7 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||||
print.m_print_statistics.estimated_normal_color_print_times = m_normal_time_estimator.get_color_times_dhms(true);
|
print.m_print_statistics.estimated_normal_color_print_times = m_normal_time_estimator.get_color_times_dhms(true);
|
||||||
if (m_silent_time_estimator_enabled)
|
if (m_silent_time_estimator_enabled)
|
||||||
print.m_print_statistics.estimated_silent_color_print_times = m_silent_time_estimator.get_color_times_dhms(true);
|
print.m_print_statistics.estimated_silent_color_print_times = m_silent_time_estimator.get_color_times_dhms(true);
|
||||||
|
print.m_print_statistics.total_toolchanges = total_toolchanges;
|
||||||
std::vector<Extruder> extruders = m_writer.extruders();
|
std::vector<Extruder> extruders = m_writer.extruders();
|
||||||
if (! extruders.empty()) {
|
if (! extruders.empty()) {
|
||||||
std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
|
std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
|
||||||
|
@ -1333,6 +1434,8 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||||
}
|
}
|
||||||
_write_format(file, "; total filament used [g] = %.1lf\n", print.m_print_statistics.total_weight);
|
_write_format(file, "; total filament used [g] = %.1lf\n", print.m_print_statistics.total_weight);
|
||||||
_write_format(file, "; total filament cost = %.1lf\n", print.m_print_statistics.total_cost);
|
_write_format(file, "; total filament cost = %.1lf\n", print.m_print_statistics.total_cost);
|
||||||
|
if (print.m_print_statistics.total_toolchanges > 0)
|
||||||
|
_write_format(file, "; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges);
|
||||||
_write_format(file, "; estimated printing time (normal mode) = %s\n", m_normal_time_estimator.get_time_dhms().c_str());
|
_write_format(file, "; estimated printing time (normal mode) = %s\n", m_normal_time_estimator.get_time_dhms().c_str());
|
||||||
if (m_silent_time_estimator_enabled)
|
if (m_silent_time_estimator_enabled)
|
||||||
_write_format(file, "; estimated printing time (silent mode) = %s\n", m_silent_time_estimator.get_time_dhms().c_str());
|
_write_format(file, "; estimated printing time (silent mode) = %s\n", m_silent_time_estimator.get_time_dhms().c_str());
|
||||||
|
|
|
@ -30,6 +30,9 @@ namespace Slic3r {
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
class GCode;
|
class GCode;
|
||||||
class GCodePreviewData;
|
class GCodePreviewData;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
struct ThumbnailData;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
class AvoidCrossingPerimeters {
|
class AvoidCrossingPerimeters {
|
||||||
public:
|
public:
|
||||||
|
@ -162,7 +165,11 @@ public:
|
||||||
|
|
||||||
// throws std::runtime_exception on error,
|
// throws std::runtime_exception on error,
|
||||||
// throws CanceledException through print->throw_if_canceled().
|
// throws CanceledException through print->throw_if_canceled().
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, const std::vector<ThumbnailData>* thumbnail_data = nullptr);
|
||||||
|
#else
|
||||||
void do_export(Print *print, const char *path, GCodePreviewData *preview_data = nullptr);
|
void do_export(Print *print, const char *path, GCodePreviewData *preview_data = nullptr);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
|
// Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
|
||||||
const Vec2d& origin() const { return m_origin; }
|
const Vec2d& origin() const { return m_origin; }
|
||||||
|
@ -190,7 +197,11 @@ public:
|
||||||
static void append_full_config(const Print& print, std::string& str);
|
static void append_full_config(const Print& print, std::string& str);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void _do_export(Print& print, FILE* file, const std::vector<ThumbnailData>* thumbnail_data);
|
||||||
|
#else
|
||||||
void _do_export(Print &print, FILE *file);
|
void _do_export(Print &print, FILE *file);
|
||||||
|
#endif //ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// Object and support extrusions of the same PrintObject at the same print_z.
|
// Object and support extrusions of the same PrintObject at the same print_z.
|
||||||
struct LayerToPrint
|
struct LayerToPrint
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef slic3r_SpiralVase_hpp_
|
#ifndef slic3r_SpiralVase_hpp_
|
||||||
#define slic3r_SpiralVase_hpp_
|
#define slic3r_SpiralVase_hpp_
|
||||||
|
|
||||||
#include "libslic3r.h"
|
#include "../libslic3r.h"
|
||||||
#include "GCodeReader.hpp"
|
#include "../GCodeReader.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
|
36
src/libslic3r/GCode/ThumbnailData.cpp
Normal file
36
src/libslic3r/GCode/ThumbnailData.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#include "libslic3r/libslic3r.h"
|
||||||
|
#include "ThumbnailData.hpp"
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
void ThumbnailData::set(unsigned int w, unsigned int h)
|
||||||
|
{
|
||||||
|
if ((w == 0) || (h == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((width != w) || (height != h))
|
||||||
|
{
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
// defaults to white texture
|
||||||
|
pixels = std::vector<unsigned char>(width * height * 4, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThumbnailData::reset()
|
||||||
|
{
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
pixels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThumbnailData::is_valid() const
|
||||||
|
{
|
||||||
|
return (width != 0) && (height != 0) && ((unsigned int)pixels.size() == 4 * width * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
27
src/libslic3r/GCode/ThumbnailData.hpp
Normal file
27
src/libslic3r/GCode/ThumbnailData.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef slic3r_ThumbnailData_hpp_
|
||||||
|
#define slic3r_ThumbnailData_hpp_
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
struct ThumbnailData
|
||||||
|
{
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
std::vector<unsigned char> pixels;
|
||||||
|
|
||||||
|
ThumbnailData() { reset(); }
|
||||||
|
void set(unsigned int w, unsigned int h);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
bool is_valid() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
|
#endif // slic3r_ThumbnailData_hpp_
|
|
@ -331,15 +331,18 @@ public:
|
||||||
|
|
||||||
// Let the firmware back up the active speed override value.
|
// Let the firmware back up the active speed override value.
|
||||||
WipeTowerWriter& speed_override_backup()
|
WipeTowerWriter& speed_override_backup()
|
||||||
{
|
{
|
||||||
m_gcode += "M220 B\n";
|
// This is only supported by Prusa at this point (https://github.com/prusa3d/PrusaSlicer/issues/3114)
|
||||||
|
if (m_gcode_flavor == gcfMarlin)
|
||||||
|
m_gcode += "M220 B\n";
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the firmware restore the active speed override value.
|
// Let the firmware restore the active speed override value.
|
||||||
WipeTowerWriter& speed_override_restore()
|
WipeTowerWriter& speed_override_restore()
|
||||||
{
|
{
|
||||||
m_gcode += "M220 R\n";
|
if (m_gcode_flavor == gcfMarlin)
|
||||||
|
m_gcode += "M220 R\n";
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -663,7 +663,6 @@ namespace Voronoi { namespace Internal {
|
||||||
typedef boost::polygon::point_data<coordinate_type> point_type;
|
typedef boost::polygon::point_data<coordinate_type> point_type;
|
||||||
typedef boost::polygon::segment_data<coordinate_type> segment_type;
|
typedef boost::polygon::segment_data<coordinate_type> segment_type;
|
||||||
typedef boost::polygon::rectangle_data<coordinate_type> rect_type;
|
typedef boost::polygon::rectangle_data<coordinate_type> rect_type;
|
||||||
// typedef voronoi_builder<int> VB;
|
|
||||||
typedef boost::polygon::voronoi_diagram<coordinate_type> VD;
|
typedef boost::polygon::voronoi_diagram<coordinate_type> VD;
|
||||||
typedef VD::cell_type cell_type;
|
typedef VD::cell_type cell_type;
|
||||||
typedef VD::cell_type::source_index_type source_index_type;
|
typedef VD::cell_type::source_index_type source_index_type;
|
||||||
|
@ -710,15 +709,15 @@ namespace Voronoi { namespace Internal {
|
||||||
if (cell1.contains_point() && cell2.contains_point()) {
|
if (cell1.contains_point() && cell2.contains_point()) {
|
||||||
point_type p1 = retrieve_point(segments, cell1);
|
point_type p1 = retrieve_point(segments, cell1);
|
||||||
point_type p2 = retrieve_point(segments, cell2);
|
point_type p2 = retrieve_point(segments, cell2);
|
||||||
origin.x((p1(0) + p2(0)) * 0.5);
|
origin.x((p1.x() + p2.x()) * 0.5);
|
||||||
origin.y((p1(1) + p2(1)) * 0.5);
|
origin.y((p1.y() + p2.y()) * 0.5);
|
||||||
direction.x(p1(1) - p2(1));
|
direction.x(p1.y() - p2.y());
|
||||||
direction.y(p2(0) - p1(0));
|
direction.y(p2.x() - p1.x());
|
||||||
} else {
|
} else {
|
||||||
origin = cell1.contains_segment() ? retrieve_point(segments, cell2) : retrieve_point(segments, cell1);
|
origin = cell1.contains_segment() ? retrieve_point(segments, cell2) : retrieve_point(segments, cell1);
|
||||||
segment_type segment = cell1.contains_segment() ? segments[cell1.source_index()] : segments[cell2.source_index()];
|
segment_type segment = cell1.contains_segment() ? segments[cell1.source_index()] : segments[cell2.source_index()];
|
||||||
coordinate_type dx = high(segment)(0) - low(segment)(0);
|
coordinate_type dx = high(segment).x() - low(segment).x();
|
||||||
coordinate_type dy = high(segment)(1) - low(segment)(1);
|
coordinate_type dy = high(segment).y() - low(segment).y();
|
||||||
if ((low(segment) == origin) ^ cell1.contains_point()) {
|
if ((low(segment) == origin) ^ cell1.contains_point()) {
|
||||||
direction.x(dy);
|
direction.x(dy);
|
||||||
direction.y(-dx);
|
direction.y(-dx);
|
||||||
|
@ -727,19 +726,19 @@ namespace Voronoi { namespace Internal {
|
||||||
direction.y(dx);
|
direction.y(dx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
coordinate_type koef = bbox_max_size / (std::max)(fabs(direction(0)), fabs(direction(1)));
|
coordinate_type koef = bbox_max_size / (std::max)(fabs(direction.x()), fabs(direction.y()));
|
||||||
if (edge.vertex0() == NULL) {
|
if (edge.vertex0() == NULL) {
|
||||||
clipped_edge->push_back(point_type(
|
clipped_edge->push_back(point_type(
|
||||||
origin(0) - direction(0) * koef,
|
origin.x() - direction.x() * koef,
|
||||||
origin(1) - direction(1) * koef));
|
origin.y() - direction.y() * koef));
|
||||||
} else {
|
} else {
|
||||||
clipped_edge->push_back(
|
clipped_edge->push_back(
|
||||||
point_type(edge.vertex0()->x(), edge.vertex0()->y()));
|
point_type(edge.vertex0()->x(), edge.vertex0()->y()));
|
||||||
}
|
}
|
||||||
if (edge.vertex1() == NULL) {
|
if (edge.vertex1() == NULL) {
|
||||||
clipped_edge->push_back(point_type(
|
clipped_edge->push_back(point_type(
|
||||||
origin(0) + direction(0) * koef,
|
origin.x() + direction.x() * koef,
|
||||||
origin(1) + direction(1) * koef));
|
origin.y() + direction.y() * koef));
|
||||||
} else {
|
} else {
|
||||||
clipped_edge->push_back(
|
clipped_edge->push_back(
|
||||||
point_type(edge.vertex1()->x(), edge.vertex1()->y()));
|
point_type(edge.vertex1()->x(), edge.vertex1()->y()));
|
||||||
|
@ -759,7 +758,7 @@ namespace Voronoi { namespace Internal {
|
||||||
|
|
||||||
} /* namespace Internal */ } // namespace Voronoi
|
} /* namespace Internal */ } // namespace Voronoi
|
||||||
|
|
||||||
static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_diagram<double> &vd, const ThickPolylines *polylines, const char *path)
|
static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ boost::polygon::voronoi_diagram<double> &vd, const ThickPolylines *polylines, const char *path)
|
||||||
{
|
{
|
||||||
const double scale = 0.2;
|
const double scale = 0.2;
|
||||||
const std::string inputSegmentPointColor = "lightseagreen";
|
const std::string inputSegmentPointColor = "lightseagreen";
|
||||||
|
@ -803,7 +802,7 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d
|
||||||
Voronoi::Internal::point_type(double(it->b(0)), double(it->b(1)))));
|
Voronoi::Internal::point_type(double(it->b(0)), double(it->b(1)))));
|
||||||
|
|
||||||
// Color exterior edges.
|
// Color exterior edges.
|
||||||
for (voronoi_diagram<double>::const_edge_iterator it = vd.edges().begin(); it != vd.edges().end(); ++it)
|
for (boost::polygon::voronoi_diagram<double>::const_edge_iterator it = vd.edges().begin(); it != vd.edges().end(); ++it)
|
||||||
if (!it->is_finite())
|
if (!it->is_finite())
|
||||||
Voronoi::Internal::color_exterior(&(*it));
|
Voronoi::Internal::color_exterior(&(*it));
|
||||||
|
|
||||||
|
@ -818,11 +817,11 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// Draw voronoi vertices.
|
// Draw voronoi vertices.
|
||||||
for (voronoi_diagram<double>::const_vertex_iterator it = vd.vertices().begin(); it != vd.vertices().end(); ++it)
|
for (boost::polygon::voronoi_diagram<double>::const_vertex_iterator it = vd.vertices().begin(); it != vd.vertices().end(); ++it)
|
||||||
if (! internalEdgesOnly || it->color() != Voronoi::Internal::EXTERNAL_COLOR)
|
if (! internalEdgesOnly || it->color() != Voronoi::Internal::EXTERNAL_COLOR)
|
||||||
svg.draw(Point(coord_t((*it)(0)), coord_t((*it)(1))), voronoiPointColor, voronoiPointRadius);
|
svg.draw(Point(coord_t(it->x()), coord_t(it->y())), voronoiPointColor, voronoiPointRadius);
|
||||||
|
|
||||||
for (voronoi_diagram<double>::const_edge_iterator it = vd.edges().begin(); it != vd.edges().end(); ++it) {
|
for (boost::polygon::voronoi_diagram<double>::const_edge_iterator it = vd.edges().begin(); it != vd.edges().end(); ++it) {
|
||||||
if (primaryEdgesOnly && !it->is_primary())
|
if (primaryEdgesOnly && !it->is_primary())
|
||||||
continue;
|
continue;
|
||||||
if (internalEdgesOnly && (it->color() == Voronoi::Internal::EXTERNAL_COLOR))
|
if (internalEdgesOnly && (it->color() == Voronoi::Internal::EXTERNAL_COLOR))
|
||||||
|
@ -845,7 +844,7 @@ static inline void dump_voronoi_to_svg(const Lines &lines, /* const */ voronoi_d
|
||||||
color = voronoiLineColorSecondary;
|
color = voronoiLineColorSecondary;
|
||||||
}
|
}
|
||||||
for (std::size_t i = 0; i + 1 < samples.size(); ++i)
|
for (std::size_t i = 0; i + 1 < samples.size(); ++i)
|
||||||
svg.draw(Line(Point(coord_t(samples[i](0)), coord_t(samples[i](1))), Point(coord_t(samples[i+1](0)), coord_t(samples[i+1](1)))), color, voronoiLineWidth);
|
svg.draw(Line(Point(coord_t(samples[i].x()), coord_t(samples[i].y())), Point(coord_t(samples[i+1].x()), coord_t(samples[i+1].y()))), color, voronoiLineWidth);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
#include <cereal/access.hpp>
|
#include <cereal/access.hpp>
|
||||||
|
|
||||||
#include "boost/polygon/voronoi.hpp"
|
#include "boost/polygon/voronoi.hpp"
|
||||||
using boost::polygon::voronoi_builder;
|
|
||||||
using boost::polygon::voronoi_diagram;
|
|
||||||
|
|
||||||
namespace ClipperLib {
|
namespace ClipperLib {
|
||||||
class PolyNode;
|
class PolyNode;
|
||||||
|
@ -192,7 +190,7 @@ class MedialAxis {
|
||||||
void build(Polylines* polylines);
|
void build(Polylines* polylines);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class VD : public voronoi_diagram<double> {
|
class VD : public boost::polygon::voronoi_diagram<double> {
|
||||||
public:
|
public:
|
||||||
typedef double coord_type;
|
typedef double coord_type;
|
||||||
typedef boost::polygon::point_data<coordinate_type> point_type;
|
typedef boost::polygon::point_data<coordinate_type> point_type;
|
||||||
|
|
|
@ -88,8 +88,12 @@ ExPolygons Layer::merged(float offset_scaled) const
|
||||||
offset_scaled2 = float(- EPSILON);
|
offset_scaled2 = float(- EPSILON);
|
||||||
}
|
}
|
||||||
Polygons polygons;
|
Polygons polygons;
|
||||||
for (LayerRegion *layerm : m_regions)
|
for (LayerRegion *layerm : m_regions) {
|
||||||
append(polygons, offset(to_expolygons(layerm->slices.surfaces), offset_scaled));
|
const PrintRegionConfig &config = layerm->region()->config();
|
||||||
|
// Our users learned to bend Slic3r to produce empty volumes to act as subtracters. Only add the region if it is non-empty.
|
||||||
|
if (config.bottom_solid_layers > 0 || config.top_solid_layers > 0 || config.fill_density > 0. || config.perimeters > 0)
|
||||||
|
append(polygons, offset(to_expolygons(layerm->slices.surfaces), offset_scaled));
|
||||||
|
}
|
||||||
ExPolygons out = union_ex(polygons);
|
ExPolygons out = union_ex(polygons);
|
||||||
if (offset_scaled2 != 0.f)
|
if (offset_scaled2 != 0.f)
|
||||||
out = offset_ex(out, offset_scaled2);
|
out = offset_ex(out, offset_scaled2);
|
||||||
|
|
|
@ -88,7 +88,6 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||||
|
|
||||||
void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered)
|
void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered)
|
||||||
{
|
{
|
||||||
const Surfaces &surfaces = this->fill_surfaces.surfaces;
|
|
||||||
const bool has_infill = this->region()->config().fill_density.value > 0.;
|
const bool has_infill = this->region()->config().fill_density.value > 0.;
|
||||||
const float margin = float(scale_(EXTERNAL_INFILL_MARGIN));
|
const float margin = float(scale_(EXTERNAL_INFILL_MARGIN));
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,11 @@ Point Polygon::point_projection(const Point &point) const
|
||||||
return proj;
|
return proj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox get_extents(const Points &points)
|
||||||
|
{
|
||||||
|
return BoundingBox(points);
|
||||||
|
}
|
||||||
|
|
||||||
BoundingBox get_extents(const Polygon &poly)
|
BoundingBox get_extents(const Polygon &poly)
|
||||||
{
|
{
|
||||||
return poly.bounding_box();
|
return poly.bounding_box();
|
||||||
|
|
|
@ -22,7 +22,8 @@ public:
|
||||||
const Point& operator[](Points::size_type idx) const { return this->points[idx]; }
|
const Point& operator[](Points::size_type idx) const { return this->points[idx]; }
|
||||||
|
|
||||||
Polygon() {}
|
Polygon() {}
|
||||||
explicit Polygon(const Points &points): MultiPoint(points) {}
|
explicit Polygon(const Points &points) : MultiPoint(points) {}
|
||||||
|
Polygon(std::initializer_list<Point> points) : MultiPoint(points) {}
|
||||||
Polygon(const Polygon &other) : MultiPoint(other.points) {}
|
Polygon(const Polygon &other) : MultiPoint(other.points) {}
|
||||||
Polygon(Polygon &&other) : MultiPoint(std::move(other.points)) {}
|
Polygon(Polygon &&other) : MultiPoint(std::move(other.points)) {}
|
||||||
static Polygon new_scale(const std::vector<Vec2d> &points) {
|
static Polygon new_scale(const std::vector<Vec2d> &points) {
|
||||||
|
@ -66,6 +67,10 @@ public:
|
||||||
Point point_projection(const Point &point) const;
|
Point point_projection(const Point &point) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const Polygon &lhs, const Polygon &rhs) { return lhs.points == rhs.points; }
|
||||||
|
inline bool operator!=(const Polygon &lhs, const Polygon &rhs) { return lhs.points != rhs.points; }
|
||||||
|
|
||||||
|
extern BoundingBox get_extents(const Points &points);
|
||||||
extern BoundingBox get_extents(const Polygon &poly);
|
extern BoundingBox get_extents(const Polygon &poly);
|
||||||
extern BoundingBox get_extents(const Polygons &polygons);
|
extern BoundingBox get_extents(const Polygons &polygons);
|
||||||
extern BoundingBox get_extents_rotated(const Polygon &poly, double angle);
|
extern BoundingBox get_extents_rotated(const Polygon &poly, double angle);
|
||||||
|
@ -102,6 +107,15 @@ inline void polygons_append(Polygons &dst, Polygons &&src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Polygons polygons_simplify(const Polygons &polys, double tolerance)
|
||||||
|
{
|
||||||
|
Polygons out;
|
||||||
|
out.reserve(polys.size());
|
||||||
|
for (const Polygon &p : polys)
|
||||||
|
polygons_append(out, p.simplify(tolerance));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
inline void polygons_rotate(Polygons &polys, double angle)
|
inline void polygons_rotate(Polygons &polys, double angle)
|
||||||
{
|
{
|
||||||
const double cos_angle = cos(angle);
|
const double cos_angle = cos(angle);
|
||||||
|
|
|
@ -12,12 +12,11 @@ TrimmedLoop trim_loop(const Polygon &loop, const EdgeGrid::Grid &grid)
|
||||||
TrimmedLoop out;
|
TrimmedLoop out;
|
||||||
|
|
||||||
if (loop.size() >= 2) {
|
if (loop.size() >= 2) {
|
||||||
size_t cnt = loop.points.size();
|
|
||||||
|
|
||||||
struct Visitor {
|
struct Visitor {
|
||||||
Visitor(const EdgeGrid::Grid &grid, const Slic3r::Point *pt_prev, const Slic3r::Point *pt_this) : grid(grid), pt_prev(pt_prev), pt_this(pt_this) {}
|
Visitor(const EdgeGrid::Grid &grid, const Slic3r::Point *pt_prev, const Slic3r::Point *pt_this) : grid(grid), pt_prev(pt_prev), pt_this(pt_this) {}
|
||||||
|
|
||||||
void operator()(coord_t iy, coord_t ix) {
|
bool operator()(coord_t iy, coord_t ix) {
|
||||||
// Called with a row and colum of the grid cell, which is intersected by a line.
|
// Called with a row and colum of the grid cell, which is intersected by a line.
|
||||||
auto cell_data_range = grid.cell_data_range(iy, ix);
|
auto cell_data_range = grid.cell_data_range(iy, ix);
|
||||||
for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second; ++ it_contour_and_segment) {
|
for (auto it_contour_and_segment = cell_data_range.first; it_contour_and_segment != cell_data_range.second; ++ it_contour_and_segment) {
|
||||||
|
@ -27,6 +26,8 @@ TrimmedLoop trim_loop(const Polygon &loop, const EdgeGrid::Grid &grid)
|
||||||
// The two segments intersect. Add them to the output.
|
// The two segments intersect. Add them to the output.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Continue traversing the grid along the edge.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeGrid::Grid &grid;
|
const EdgeGrid::Grid &grid;
|
||||||
|
|
|
@ -1536,7 +1536,11 @@ void Print::process()
|
||||||
// The export_gcode may die for various reasons (fails to process output_filename_format,
|
// The export_gcode may die for various reasons (fails to process output_filename_format,
|
||||||
// write error into the G-code, cannot execute post-processing scripts).
|
// write error into the G-code, cannot execute post-processing scripts).
|
||||||
// It is up to the caller to show an error message.
|
// It is up to the caller to show an error message.
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, const std::vector<ThumbnailData>* thumbnail_data)
|
||||||
|
#else
|
||||||
std::string Print::export_gcode(const std::string &path_template, GCodePreviewData *preview_data)
|
std::string Print::export_gcode(const std::string &path_template, GCodePreviewData *preview_data)
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
{
|
{
|
||||||
// output everything to a G-code file
|
// output everything to a G-code file
|
||||||
// The following call may die if the output_filename_format template substitution fails.
|
// The following call may die if the output_filename_format template substitution fails.
|
||||||
|
@ -1553,7 +1557,11 @@ std::string Print::export_gcode(const std::string &path_template, GCodePreviewDa
|
||||||
|
|
||||||
// The following line may die for multiple reasons.
|
// The following line may die for multiple reasons.
|
||||||
GCode gcode;
|
GCode gcode;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
gcode.do_export(this, path.c_str(), preview_data, thumbnail_data);
|
||||||
|
#else
|
||||||
gcode.do_export(this, path.c_str(), preview_data);
|
gcode.do_export(this, path.c_str(), preview_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
return path.c_str();
|
return path.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2056,6 +2064,7 @@ DynamicConfig PrintStatistics::config() const
|
||||||
config.set_key_value("used_filament", new ConfigOptionFloat (this->total_used_filament / 1000.));
|
config.set_key_value("used_filament", new ConfigOptionFloat (this->total_used_filament / 1000.));
|
||||||
config.set_key_value("extruded_volume", new ConfigOptionFloat (this->total_extruded_volume));
|
config.set_key_value("extruded_volume", new ConfigOptionFloat (this->total_extruded_volume));
|
||||||
config.set_key_value("total_cost", new ConfigOptionFloat (this->total_cost));
|
config.set_key_value("total_cost", new ConfigOptionFloat (this->total_cost));
|
||||||
|
config.set_key_value("total_toolchanges", new ConfigOptionInt(this->total_toolchanges));
|
||||||
config.set_key_value("total_weight", new ConfigOptionFloat (this->total_weight));
|
config.set_key_value("total_weight", new ConfigOptionFloat (this->total_weight));
|
||||||
config.set_key_value("total_wipe_tower_cost", new ConfigOptionFloat (this->total_wipe_tower_cost));
|
config.set_key_value("total_wipe_tower_cost", new ConfigOptionFloat (this->total_wipe_tower_cost));
|
||||||
config.set_key_value("total_wipe_tower_filament", new ConfigOptionFloat (this->total_wipe_tower_filament));
|
config.set_key_value("total_wipe_tower_filament", new ConfigOptionFloat (this->total_wipe_tower_filament));
|
||||||
|
@ -2068,7 +2077,7 @@ DynamicConfig PrintStatistics::placeholders()
|
||||||
for (const std::string &key : {
|
for (const std::string &key : {
|
||||||
"print_time", "normal_print_time", "silent_print_time",
|
"print_time", "normal_print_time", "silent_print_time",
|
||||||
"used_filament", "extruded_volume", "total_cost", "total_weight",
|
"used_filament", "extruded_volume", "total_cost", "total_weight",
|
||||||
"total_wipe_tower_cost", "total_wipe_tower_filament"})
|
"total_toolchanges", "total_wipe_tower_cost", "total_wipe_tower_filament"})
|
||||||
config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}"));
|
config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}"));
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ class PrintObject;
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
class GCode;
|
class GCode;
|
||||||
class GCodePreviewData;
|
class GCodePreviewData;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
struct ThumbnailData;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// Print step IDs for keeping track of the print state.
|
// Print step IDs for keeping track of the print state.
|
||||||
enum PrintStep {
|
enum PrintStep {
|
||||||
|
@ -250,6 +253,7 @@ struct PrintStatistics
|
||||||
double total_used_filament;
|
double total_used_filament;
|
||||||
double total_extruded_volume;
|
double total_extruded_volume;
|
||||||
double total_cost;
|
double total_cost;
|
||||||
|
int total_toolchanges;
|
||||||
double total_weight;
|
double total_weight;
|
||||||
double total_wipe_tower_cost;
|
double total_wipe_tower_cost;
|
||||||
double total_wipe_tower_filament;
|
double total_wipe_tower_filament;
|
||||||
|
@ -270,6 +274,7 @@ struct PrintStatistics
|
||||||
total_used_filament = 0.;
|
total_used_filament = 0.;
|
||||||
total_extruded_volume = 0.;
|
total_extruded_volume = 0.;
|
||||||
total_cost = 0.;
|
total_cost = 0.;
|
||||||
|
total_toolchanges = 0;
|
||||||
total_weight = 0.;
|
total_weight = 0.;
|
||||||
total_wipe_tower_cost = 0.;
|
total_wipe_tower_cost = 0.;
|
||||||
total_wipe_tower_filament = 0.;
|
total_wipe_tower_filament = 0.;
|
||||||
|
@ -305,7 +310,11 @@ public:
|
||||||
void process() override;
|
void process() override;
|
||||||
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
||||||
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
|
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
std::string export_gcode(const std::string& path_template, GCodePreviewData* preview_data, const std::vector<ThumbnailData>* thumbnail_data = nullptr);
|
||||||
|
#else
|
||||||
std::string export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
std::string export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// methods for handling state
|
// methods for handling state
|
||||||
bool is_step_done(PrintStep step) const { return Inherited::is_step_done(step); }
|
bool is_step_done(PrintStep step) const { return Inherited::is_step_done(step); }
|
||||||
|
|
|
@ -1327,8 +1327,10 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->enum_keys_map = &ConfigOptionEnum<PrintHostType>::get_enum_values();
|
def->enum_keys_map = &ConfigOptionEnum<PrintHostType>::get_enum_values();
|
||||||
def->enum_values.push_back("octoprint");
|
def->enum_values.push_back("octoprint");
|
||||||
def->enum_values.push_back("duet");
|
def->enum_values.push_back("duet");
|
||||||
|
def->enum_values.push_back("flashair");
|
||||||
def->enum_labels.push_back("OctoPrint");
|
def->enum_labels.push_back("OctoPrint");
|
||||||
def->enum_labels.push_back("Duet");
|
def->enum_labels.push_back("Duet");
|
||||||
|
def->enum_labels.push_back("FlashAir");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionEnum<PrintHostType>(htOctoPrint));
|
def->set_default_value(new ConfigOptionEnum<PrintHostType>(htOctoPrint));
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ enum GCodeFlavor : unsigned char {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PrintHostType {
|
enum PrintHostType {
|
||||||
htOctoPrint, htDuet
|
htOctoPrint, htDuet, htFlashAir
|
||||||
};
|
};
|
||||||
|
|
||||||
enum InfillPattern {
|
enum InfillPattern {
|
||||||
|
@ -102,6 +102,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<PrintHostType>::g
|
||||||
if (keys_map.empty()) {
|
if (keys_map.empty()) {
|
||||||
keys_map["octoprint"] = htOctoPrint;
|
keys_map["octoprint"] = htOctoPrint;
|
||||||
keys_map["duet"] = htDuet;
|
keys_map["duet"] = htDuet;
|
||||||
|
keys_map["flashair"] = htFlashAir;
|
||||||
}
|
}
|
||||||
return keys_map;
|
return keys_map;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Print.hpp"
|
#include "Print.hpp"
|
||||||
#include "BoundingBox.hpp"
|
#include "BoundingBox.hpp"
|
||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
|
#include "ElephantFootCompensation.hpp"
|
||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "SupportMaterial.hpp"
|
#include "SupportMaterial.hpp"
|
||||||
|
@ -1769,8 +1770,10 @@ end:
|
||||||
Layer *layer = m_layers[layer_id];
|
Layer *layer = m_layers[layer_id];
|
||||||
// Apply size compensation and perform clipping of multi-part objects.
|
// Apply size compensation and perform clipping of multi-part objects.
|
||||||
float delta = float(scale_(m_config.xy_size_compensation.value));
|
float delta = float(scale_(m_config.xy_size_compensation.value));
|
||||||
|
//FIXME only apply the compensation if no raft is enabled.
|
||||||
float elephant_foot_compensation = 0.f;
|
float elephant_foot_compensation = 0.f;
|
||||||
if (layer_id == 0)
|
if (layer_id == 0 && m_config.raft_layers == 0)
|
||||||
|
// Only enable Elephant foot compensation if printing directly on the print bed.
|
||||||
elephant_foot_compensation = float(scale_(m_config.elefant_foot_compensation.value));
|
elephant_foot_compensation = float(scale_(m_config.elefant_foot_compensation.value));
|
||||||
if (layer->m_regions.size() == 1) {
|
if (layer->m_regions.size() == 1) {
|
||||||
// Optimized version for a single region layer.
|
// Optimized version for a single region layer.
|
||||||
|
@ -1789,19 +1792,8 @@ end:
|
||||||
to_expolygons(std::move(layerm->slices.surfaces)) :
|
to_expolygons(std::move(layerm->slices.surfaces)) :
|
||||||
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta);
|
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta);
|
||||||
// Apply the elephant foot compensation.
|
// Apply the elephant foot compensation.
|
||||||
if (elephant_foot_compensation > 0) {
|
if (elephant_foot_compensation > 0)
|
||||||
float elephant_foot_spacing = float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing());
|
expolygons = union_ex(Slic3r::elephant_foot_compensation(expolygons, layerm->flow(frExternalPerimeter), unscale<double>(elephant_foot_compensation)));
|
||||||
float external_perimeter_nozzle = float(scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1)));
|
|
||||||
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
|
||||||
float steps = std::ceil(elephant_foot_compensation / (0.1f * external_perimeter_nozzle));
|
|
||||||
size_t nsteps = size_t(steps);
|
|
||||||
float step = elephant_foot_compensation / steps;
|
|
||||||
for (size_t i = 0; i < nsteps; ++ i) {
|
|
||||||
Polygons tmp = offset(expolygons, - step);
|
|
||||||
append(tmp, diff(to_polygons(expolygons), offset(offset_ex(expolygons, -elephant_foot_spacing - step), elephant_foot_spacing + step)));
|
|
||||||
expolygons = union_ex(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
layerm->slices.set(std::move(expolygons), stInternal);
|
layerm->slices.set(std::move(expolygons), stInternal);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1825,33 +1817,18 @@ end:
|
||||||
layerm->slices.set(std::move(slices), stInternal);
|
layerm->slices.set(std::move(slices), stInternal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (delta < 0.f) {
|
if (delta < 0.f || elephant_foot_compensation > 0.f) {
|
||||||
// Apply the negative XY compensation.
|
// Apply the negative XY compensation.
|
||||||
Polygons trimming = offset(layer->merged(float(EPSILON)), delta - float(EPSILON));
|
Polygons trimming;
|
||||||
|
static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5);
|
||||||
|
if (elephant_foot_compensation > 0.f) {
|
||||||
|
trimming = to_polygons(Slic3r::elephant_foot_compensation(offset_ex(layer->merged(eps), std::min(delta, 0.f) - eps),
|
||||||
|
layer->m_regions.front()->flow(frExternalPerimeter), unscale<double>(elephant_foot_compensation)));
|
||||||
|
} else
|
||||||
|
trimming = offset(layer->merged(float(SCALED_EPSILON)), delta - float(SCALED_EPSILON));
|
||||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
||||||
layer->m_regions[region_id]->trim_surfaces(trimming);
|
layer->m_regions[region_id]->trim_surfaces(trimming);
|
||||||
}
|
}
|
||||||
if (elephant_foot_compensation > 0.f) {
|
|
||||||
// Apply the elephant foot compensation.
|
|
||||||
std::vector<float> elephant_foot_spacing;
|
|
||||||
elephant_foot_spacing.reserve(layer->m_regions.size());
|
|
||||||
float external_perimeter_nozzle = 0.f;
|
|
||||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
|
||||||
LayerRegion *layerm = layer->m_regions[region_id];
|
|
||||||
elephant_foot_spacing.emplace_back(float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing()));
|
|
||||||
external_perimeter_nozzle += float(scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1)));
|
|
||||||
}
|
|
||||||
external_perimeter_nozzle /= (float)layer->m_regions.size();
|
|
||||||
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
|
||||||
float steps = std::ceil(elephant_foot_compensation / (0.1f * external_perimeter_nozzle));
|
|
||||||
size_t nsteps = size_t(steps);
|
|
||||||
float step = elephant_foot_compensation / steps;
|
|
||||||
for (size_t i = 0; i < nsteps; ++ i) {
|
|
||||||
Polygons trimming_polygons = offset(layer->merged(float(EPSILON)), - step - float(EPSILON));
|
|
||||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
|
||||||
layer->m_regions[region_id]->elephant_foot_compensation_step(elephant_foot_spacing[region_id] + step, trimming_polygons);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Merge all regions' slices to get islands, chain them by a shortest path.
|
// Merge all regions' slices to get islands, chain them by a shortest path.
|
||||||
layer->make_slices();
|
layer->make_slices();
|
||||||
|
|
|
@ -32,9 +32,22 @@ void RasterWriter::save(const std::string &fpath, const std::string &prjname)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Zipper zipper(fpath); // zipper with no compression
|
Zipper zipper(fpath); // zipper with no compression
|
||||||
|
save(zipper, prjname);
|
||||||
|
zipper.finalize();
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||||
|
// Rethrow the exception
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string project = prjname.empty()?
|
void RasterWriter::save(Zipper &zipper, const std::string &prjname)
|
||||||
boost::filesystem::path(fpath).stem().string() : prjname;
|
{
|
||||||
|
try {
|
||||||
|
std::string project =
|
||||||
|
prjname.empty() ?
|
||||||
|
boost::filesystem::path(zipper.get_filename()).stem().string() :
|
||||||
|
prjname;
|
||||||
|
|
||||||
zipper.add_entry("config.ini");
|
zipper.add_entry("config.ini");
|
||||||
|
|
||||||
|
@ -53,8 +66,6 @@ void RasterWriter::save(const std::string &fpath, const std::string &prjname)
|
||||||
m_layers_rst[i].rawbytes.size());
|
m_layers_rst[i].rawbytes.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zipper.finalize();
|
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
BOOST_LOG_TRIVIAL(error) << e.what();
|
BOOST_LOG_TRIVIAL(error) << e.what();
|
||||||
// Rethrow the exception
|
// Rethrow the exception
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
|
||||||
#include "SLARaster.hpp"
|
#include "SLARaster.hpp"
|
||||||
|
#include "libslic3r/Zipper.hpp"
|
||||||
|
|
||||||
namespace Slic3r { namespace sla {
|
namespace Slic3r { namespace sla {
|
||||||
|
|
||||||
|
@ -112,6 +113,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void save(const std::string &fpath, const std::string &prjname = "");
|
void save(const std::string &fpath, const std::string &prjname = "");
|
||||||
|
void save(Zipper &zipper, const std::string &prjname = "");
|
||||||
|
|
||||||
void set_statistics(const PrintStatistics &statistics);
|
void set_statistics(const PrintStatistics &statistics);
|
||||||
|
|
||||||
|
|
|
@ -1372,7 +1372,12 @@ void SLAPrint::process()
|
||||||
m_print_statistics.fast_layers_count = fast_layers;
|
m_print_statistics.fast_layers_count = fast_layers;
|
||||||
m_print_statistics.slow_layers_count = slow_layers;
|
m_print_statistics.slow_layers_count = slow_layers;
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
// second argument set to -3 to differentiate it from the same call made into slice_supports()
|
||||||
|
m_report_status(*this, -3, "", SlicingStatus::RELOAD_SLA_PREVIEW);
|
||||||
|
#else
|
||||||
m_report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW);
|
m_report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rasterizing the model objects, and their supports
|
// Rasterizing the model objects, and their supports
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "SLA/SLARasterWriter.hpp"
|
#include "SLA/SLARasterWriter.hpp"
|
||||||
#include "Point.hpp"
|
#include "Point.hpp"
|
||||||
#include "MTUtils.hpp"
|
#include "MTUtils.hpp"
|
||||||
|
#include "Zipper.hpp"
|
||||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -364,6 +365,12 @@ public:
|
||||||
if(m_printer) m_printer->save(fpath, projectname);
|
if(m_printer) m_printer->save(fpath, projectname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void export_raster(Zipper &zipper,
|
||||||
|
const std::string& projectname = "")
|
||||||
|
{
|
||||||
|
if(m_printer) m_printer->save(zipper, projectname);
|
||||||
|
}
|
||||||
|
|
||||||
const PrintObjects& objects() const { return m_objects; }
|
const PrintObjects& objects() const { return m_objects; }
|
||||||
|
|
||||||
const SLAPrintConfig& print_config() const { return m_print_config; }
|
const SLAPrintConfig& print_config() const { return m_print_config; }
|
||||||
|
|
|
@ -368,6 +368,10 @@ void SVG::export_expolygons(const char *path, const std::vector<std::pair<Slic3r
|
||||||
color_holes = color_contour;
|
color_holes = color_contour;
|
||||||
svg.draw_outline(exp_with_attr.first, color_contour, color_holes, exp_with_attr.second.outline_width);
|
svg.draw_outline(exp_with_attr.first, color_contour, color_holes, exp_with_attr.second.outline_width);
|
||||||
}
|
}
|
||||||
|
for (const auto &exp_with_attr : expolygons_with_attributes)
|
||||||
|
if (exp_with_attr.second.radius_points > 0)
|
||||||
|
for (const ExPolygon &expoly : exp_with_attr.first)
|
||||||
|
svg.draw((Points)expoly, exp_with_attr.second.color_points, exp_with_attr.second.radius_points);
|
||||||
svg.Close();
|
svg.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,19 +105,25 @@ public:
|
||||||
const std::string &color_contour,
|
const std::string &color_contour,
|
||||||
const std::string &color_holes,
|
const std::string &color_holes,
|
||||||
const coord_t outline_width = scale_(0.05),
|
const coord_t outline_width = scale_(0.05),
|
||||||
const float fill_opacity = 0.5f) :
|
const float fill_opacity = 0.5f,
|
||||||
|
const std::string &color_points = "black",
|
||||||
|
const coord_t radius_points = 0) :
|
||||||
color_fill (color_fill),
|
color_fill (color_fill),
|
||||||
color_contour (color_contour),
|
color_contour (color_contour),
|
||||||
color_holes (color_holes),
|
color_holes (color_holes),
|
||||||
outline_width (outline_width),
|
outline_width (outline_width),
|
||||||
fill_opacity (fill_opacity)
|
fill_opacity (fill_opacity),
|
||||||
|
color_points (color_points),
|
||||||
|
radius_points (radius_points)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string color_fill;
|
std::string color_fill;
|
||||||
std::string color_contour;
|
std::string color_contour;
|
||||||
std::string color_holes;
|
std::string color_holes;
|
||||||
|
std::string color_points;
|
||||||
coord_t outline_width;
|
coord_t outline_width;
|
||||||
float fill_opacity;
|
float fill_opacity;
|
||||||
|
coord_t radius_points;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void export_expolygons(const char *path, const std::vector<std::pair<Slic3r::ExPolygons, ExPolygonAttributes>> &expolygons_with_attributes);
|
static void export_expolygons(const char *path, const std::vector<std::pair<Slic3r::ExPolygons, ExPolygonAttributes>> &expolygons_with_attributes);
|
||||||
|
|
|
@ -32,4 +32,14 @@
|
||||||
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1)
|
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1)
|
||||||
|
|
||||||
|
|
||||||
|
//====================
|
||||||
|
// 2.2.0.alpha1 techs
|
||||||
|
//====================
|
||||||
|
#define ENABLE_2_2_0_ALPHA1 1
|
||||||
|
|
||||||
|
// Enable thumbnail generator
|
||||||
|
#define ENABLE_THUMBNAIL_GENERATOR (1 && ENABLE_2_2_0_ALPHA1)
|
||||||
|
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG (0 && ENABLE_THUMBNAIL_GENERATOR)
|
||||||
|
#define ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE (1 && ENABLE_THUMBNAIL_GENERATOR)
|
||||||
|
|
||||||
#endif // _technologies_h_
|
#endif // _technologies_h_
|
||||||
|
|
|
@ -217,4 +217,9 @@ void Zipper::finalize()
|
||||||
m_impl->blow_up();
|
m_impl->blow_up();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &Zipper::get_filename() const
|
||||||
|
{
|
||||||
|
return m_impl->m_zipname;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,8 @@ public:
|
||||||
void finish_entry();
|
void finish_entry();
|
||||||
|
|
||||||
void finalize();
|
void finalize();
|
||||||
|
|
||||||
|
const std::string & get_filename() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -424,14 +424,19 @@ int copy_file(const std::string &from, const std::string &to)
|
||||||
static const auto perms = boost::filesystem::owner_read | boost::filesystem::owner_write | boost::filesystem::group_read | boost::filesystem::others_read; // aka 644
|
static const auto perms = boost::filesystem::owner_read | boost::filesystem::owner_write | boost::filesystem::group_read | boost::filesystem::others_read; // aka 644
|
||||||
|
|
||||||
// Make sure the file has correct permission both before and after we copy over it.
|
// Make sure the file has correct permission both before and after we copy over it.
|
||||||
try {
|
// NOTE: error_code variants are used here to supress expception throwing.
|
||||||
if (boost::filesystem::exists(target))
|
// Error code of permission() calls is ignored on purpose - if they fail,
|
||||||
boost::filesystem::permissions(target, perms);
|
// the copy_file() function will fail appropriately and we don't want the permission()
|
||||||
boost::filesystem::copy_file(source, target, boost::filesystem::copy_option::overwrite_if_exists);
|
// calls to cause needless failures on permissionless filesystems (ie. FATs on SD cards etc.)
|
||||||
boost::filesystem::permissions(target, perms);
|
// or when the target file doesn't exist.
|
||||||
} catch (std::exception & /* ex */) {
|
boost::system::error_code ec;
|
||||||
|
boost::filesystem::permissions(target, perms, ec);
|
||||||
|
boost::filesystem::copy_file(source, target, boost::filesystem::copy_option::overwrite_if_exists, ec);
|
||||||
|
if (ec) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
boost::filesystem::permissions(target, perms, ec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,10 @@ if(Qhull_FOUND)
|
||||||
|
|
||||||
message(STATUS "Using qhull from system.")
|
message(STATUS "Using qhull from system.")
|
||||||
if(SLIC3R_STATIC)
|
if(SLIC3R_STATIC)
|
||||||
|
slic3r_remap_configs("Qhull::qhullcpp;Qhull::qhullstatic_r" RelWithDebInfo Release)
|
||||||
target_link_libraries(qhull INTERFACE Qhull::qhullcpp Qhull::qhullstatic_r)
|
target_link_libraries(qhull INTERFACE Qhull::qhullcpp Qhull::qhullstatic_r)
|
||||||
else()
|
else()
|
||||||
|
slic3r_remap_configs("Qhull::qhullcpp;Qhull::qhull_r" RelWithDebInfo Release)
|
||||||
target_link_libraries(qhull INTERFACE Qhull::qhullcpp Qhull::qhull_r)
|
target_link_libraries(qhull INTERFACE Qhull::qhullcpp Qhull::qhull_r)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,8 @@ set(SLIC3R_GUI_SOURCES
|
||||||
Utils/OctoPrint.hpp
|
Utils/OctoPrint.hpp
|
||||||
Utils/Duet.cpp
|
Utils/Duet.cpp
|
||||||
Utils/Duet.hpp
|
Utils/Duet.hpp
|
||||||
|
Utils/FlashAir.cpp
|
||||||
|
Utils/FlashAir.hpp
|
||||||
Utils/PrintHost.cpp
|
Utils/PrintHost.cpp
|
||||||
Utils/PrintHost.hpp
|
Utils/PrintHost.hpp
|
||||||
Utils/Bonjour.cpp
|
Utils/Bonjour.cpp
|
||||||
|
|
|
@ -235,9 +235,9 @@ size_t Index::load(const boost::filesystem::path &path)
|
||||||
value = left_trim(value + 1);
|
value = left_trim(value + 1);
|
||||||
*key_end = 0;
|
*key_end = 0;
|
||||||
boost::optional<Semver> semver;
|
boost::optional<Semver> semver;
|
||||||
if (maybe_semver)
|
if (maybe_semver)
|
||||||
semver = Semver::parse(key);
|
semver = Semver::parse(key);
|
||||||
if (key_value_pair) {
|
if (key_value_pair) {
|
||||||
if (semver)
|
if (semver)
|
||||||
throw file_parser_error("Key cannot be a semantic version", path, idx_line);\
|
throw file_parser_error("Key cannot be a semantic version", path, idx_line);\
|
||||||
// Verify validity of the key / value pair.
|
// Verify validity of the key / value pair.
|
||||||
|
@ -288,7 +288,6 @@ Index::const_iterator Index::find(const Semver &ver) const
|
||||||
|
|
||||||
Index::const_iterator Index::recommended() const
|
Index::const_iterator Index::recommended() const
|
||||||
{
|
{
|
||||||
int idx = -1;
|
|
||||||
const_iterator highest = this->end();
|
const_iterator highest = this->end();
|
||||||
for (const_iterator it = this->begin(); it != this->end(); ++ it)
|
for (const_iterator it = this->begin(); it != this->end(); ++ it)
|
||||||
if (it->is_current_slic3r_supported() &&
|
if (it->is_current_slic3r_supported() &&
|
||||||
|
|
|
@ -10,12 +10,19 @@
|
||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
#include <wx/zipstrm.h>
|
#include <wx/zipstrm.h>
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include <miniz.h>
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx.
|
// Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx.
|
||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
#include "libslic3r/SLAPrint.hpp"
|
#include "libslic3r/SLAPrint.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/GCode/PostProcessor.hpp"
|
#include "libslic3r/GCode/PostProcessor.hpp"
|
||||||
#include "libslic3r/GCode/PreviewData.hpp"
|
#include "libslic3r/GCode/PreviewData.hpp"
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include "libslic3r/GCode/ThumbnailData.hpp"
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -55,6 +62,7 @@ bool BackgroundSlicingProcess::select_technology(PrinterTechnology tech)
|
||||||
switch (tech) {
|
switch (tech) {
|
||||||
case ptFFF: m_print = m_fff_print; break;
|
case ptFFF: m_print = m_fff_print; break;
|
||||||
case ptSLA: m_print = m_sla_print; break;
|
case ptSLA: m_print = m_sla_print; break;
|
||||||
|
default: assert(false); break;
|
||||||
}
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -82,8 +90,12 @@ void BackgroundSlicingProcess::process_fff()
|
||||||
assert(m_print == m_fff_print);
|
assert(m_print == m_fff_print);
|
||||||
m_print->process();
|
m_print->process();
|
||||||
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_slicing_completed_id));
|
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_slicing_completed_id));
|
||||||
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data);
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
if (this->set_step_started(bspsGCodeFinalize)) {
|
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_thumbnail_data);
|
||||||
|
#else
|
||||||
|
m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
if (this->set_step_started(bspsGCodeFinalize)) {
|
||||||
if (! m_export_path.empty()) {
|
if (! m_export_path.empty()) {
|
||||||
//FIXME localize the messages
|
//FIXME localize the messages
|
||||||
// Perform the final post-processing of the export path by applying the print statistics over the file name.
|
// Perform the final post-processing of the export path by applying the print statistics over the file name.
|
||||||
|
@ -99,17 +111,46 @@ void BackgroundSlicingProcess::process_fff()
|
||||||
m_print->set_status(100, _utf8(L("Slicing complete")));
|
m_print->set_status(100, _utf8(L("Slicing complete")));
|
||||||
}
|
}
|
||||||
this->set_step_done(bspsGCodeFinalize);
|
this->set_step_done(bspsGCodeFinalize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
static void write_thumbnail(Zipper& zipper, const ThumbnailData& data)
|
||||||
|
{
|
||||||
|
size_t png_size = 0;
|
||||||
|
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)data.pixels.data(), data.width, data.height, 4, &png_size, MZ_DEFAULT_LEVEL, 1);
|
||||||
|
if (png_data != nullptr)
|
||||||
|
{
|
||||||
|
zipper.add_entry("thumbnail/thumbnail" + std::to_string(data.width) + "x" + std::to_string(data.height) + ".png", (const std::uint8_t*)png_data, png_size);
|
||||||
|
mz_free(png_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
void BackgroundSlicingProcess::process_sla()
|
void BackgroundSlicingProcess::process_sla()
|
||||||
{
|
{
|
||||||
assert(m_print == m_sla_print);
|
assert(m_print == m_sla_print);
|
||||||
m_print->process();
|
m_print->process();
|
||||||
if (this->set_step_started(bspsGCodeFinalize)) {
|
if (this->set_step_started(bspsGCodeFinalize)) {
|
||||||
if (! m_export_path.empty()) {
|
if (! m_export_path.empty()) {
|
||||||
const std::string export_path = m_sla_print->print_statistics().finalize_output_path(m_export_path);
|
const std::string export_path = m_sla_print->print_statistics().finalize_output_path(m_export_path);
|
||||||
m_sla_print->export_raster(export_path);
|
|
||||||
|
Zipper zipper(export_path);
|
||||||
|
m_sla_print->export_raster(zipper);
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
if (m_thumbnail_data != nullptr)
|
||||||
|
{
|
||||||
|
for (const ThumbnailData& data : *m_thumbnail_data)
|
||||||
|
{
|
||||||
|
if (data.is_valid())
|
||||||
|
write_thumbnail(zipper, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
|
zipper.finalize();
|
||||||
|
|
||||||
m_print->set_status(100, (boost::format(_utf8(L("Masked SLA file exported to %1%"))) % export_path).str());
|
m_print->set_status(100, (boost::format(_utf8(L("Masked SLA file exported to %1%"))) % export_path).str());
|
||||||
} else if (! m_upload_job.empty()) {
|
} else if (! m_upload_job.empty()) {
|
||||||
prepare_upload();
|
prepare_upload();
|
||||||
|
@ -417,13 +458,26 @@ void BackgroundSlicingProcess::prepare_upload()
|
||||||
throw std::runtime_error(_utf8(L("Copying of the temporary G-code to the output G-code failed")));
|
throw std::runtime_error(_utf8(L("Copying of the temporary G-code to the output G-code failed")));
|
||||||
}
|
}
|
||||||
run_post_process_scripts(source_path.string(), m_fff_print->config());
|
run_post_process_scripts(source_path.string(), m_fff_print->config());
|
||||||
m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
||||||
} else {
|
} else {
|
||||||
m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
||||||
m_sla_print->export_raster(source_path.string(), m_upload_job.upload_data.upload_path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());
|
Zipper zipper{source_path.string()};
|
||||||
|
m_sla_print->export_raster(zipper, m_upload_job.upload_data.upload_path.string());
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
if (m_thumbnail_data != nullptr)
|
||||||
|
{
|
||||||
|
for (const ThumbnailData& data : *m_thumbnail_data)
|
||||||
|
{
|
||||||
|
if (data.is_valid())
|
||||||
|
write_thumbnail(zipper, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
zipper.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());
|
||||||
|
|
||||||
m_upload_job.upload_data.source_path = std::move(source_path);
|
m_upload_job.upload_data.source_path = std::move(source_path);
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ namespace Slic3r {
|
||||||
|
|
||||||
class DynamicPrintConfig;
|
class DynamicPrintConfig;
|
||||||
class GCodePreviewData;
|
class GCodePreviewData;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
struct ThumbnailData;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
class Model;
|
class Model;
|
||||||
class SLAPrint;
|
class SLAPrint;
|
||||||
|
|
||||||
|
@ -49,6 +52,10 @@ public:
|
||||||
void set_fff_print(Print *print) { m_fff_print = print; }
|
void set_fff_print(Print *print) { m_fff_print = print; }
|
||||||
void set_sla_print(SLAPrint *print) { m_sla_print = print; }
|
void set_sla_print(SLAPrint *print) { m_sla_print = print; }
|
||||||
void set_gcode_preview_data(GCodePreviewData *gpd) { m_gcode_preview_data = gpd; }
|
void set_gcode_preview_data(GCodePreviewData *gpd) { m_gcode_preview_data = gpd; }
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void set_thumbnail_data(const std::vector<ThumbnailData>* data) { m_thumbnail_data = data; }
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// The following wxCommandEvent will be sent to the UI thread / Platter window, when the slicing is finished
|
// The following wxCommandEvent will be sent to the UI thread / Platter window, when the slicing is finished
|
||||||
// and the background processing will transition into G-code export.
|
// and the background processing will transition into G-code export.
|
||||||
// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
|
// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
|
||||||
|
@ -151,6 +158,10 @@ private:
|
||||||
SLAPrint *m_sla_print = nullptr;
|
SLAPrint *m_sla_print = nullptr;
|
||||||
// Data structure, to which the G-code export writes its annotations.
|
// Data structure, to which the G-code export writes its annotations.
|
||||||
GCodePreviewData *m_gcode_preview_data = nullptr;
|
GCodePreviewData *m_gcode_preview_data = nullptr;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
// Data structures, used to write thumbnails into gcode.
|
||||||
|
const std::vector<ThumbnailData>* m_thumbnail_data = nullptr;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
|
// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
|
||||||
std::string m_temp_output_path;
|
std::string m_temp_output_path;
|
||||||
// Output path provided by the user. The output path may be set even if the slicing is running,
|
// Output path provided by the user. The output path may be set even if the slicing is running,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
#include "Camera.hpp"
|
#include "Camera.hpp"
|
||||||
|
#if !ENABLE_THUMBNAIL_GENERATOR
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
|
#endif // !ENABLE_THUMBNAIL_GENERATOR
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "AppConfig.hpp"
|
#include "AppConfig.hpp"
|
||||||
|
|
||||||
|
@ -22,6 +24,10 @@ namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
const double Camera::DefaultDistance = 1000.0;
|
const double Camera::DefaultDistance = 1000.0;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
const double Camera::DefaultZoomToBoxMarginFactor = 1.025;
|
||||||
|
const double Camera::DefaultZoomToVolumesMarginFactor = 1.025;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
double Camera::FrustrumMinZRange = 50.0;
|
double Camera::FrustrumMinZRange = 50.0;
|
||||||
double Camera::FrustrumMinNearZ = 100.0;
|
double Camera::FrustrumMinNearZ = 100.0;
|
||||||
double Camera::FrustrumZMargin = 10.0;
|
double Camera::FrustrumZMargin = 10.0;
|
||||||
|
@ -270,10 +276,18 @@ void Camera::apply_projection(const BoundingBoxf3& box) const
|
||||||
glsafe(::glMatrixMode(GL_MODELVIEW));
|
glsafe(::glMatrixMode(GL_MODELVIEW));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void Camera::zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor)
|
||||||
|
#else
|
||||||
void Camera::zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h)
|
void Camera::zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h)
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
{
|
{
|
||||||
// Calculate the zoom factor needed to adjust the view around the given box.
|
// Calculate the zoom factor needed to adjust the view around the given box.
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
double zoom = calc_zoom_to_bounding_box_factor(box, canvas_w, canvas_h, margin_factor);
|
||||||
|
#else
|
||||||
double zoom = calc_zoom_to_bounding_box_factor(box, canvas_w, canvas_h);
|
double zoom = calc_zoom_to_bounding_box_factor(box, canvas_w, canvas_h);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
if (zoom > 0.0)
|
if (zoom > 0.0)
|
||||||
{
|
{
|
||||||
m_zoom = zoom;
|
m_zoom = zoom;
|
||||||
|
@ -282,6 +296,20 @@ void Camera::zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void Camera::zoom_to_volumes(const GLVolumePtrs& volumes, int canvas_w, int canvas_h, double margin_factor)
|
||||||
|
{
|
||||||
|
Vec3d center;
|
||||||
|
double zoom = calc_zoom_to_volumes_factor(volumes, canvas_w, canvas_h, center, margin_factor);
|
||||||
|
if (zoom > 0.0)
|
||||||
|
{
|
||||||
|
m_zoom = zoom;
|
||||||
|
// center view around the calculated center
|
||||||
|
m_target = center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
#if ENABLE_CAMERA_STATISTICS
|
#if ENABLE_CAMERA_STATISTICS
|
||||||
void Camera::debug_render() const
|
void Camera::debug_render() const
|
||||||
{
|
{
|
||||||
|
@ -376,7 +404,11 @@ std::pair<double, double> Camera::calc_tight_frustrum_zs_around(const BoundingBo
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor) const
|
||||||
|
#else
|
||||||
double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const
|
double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
{
|
{
|
||||||
double max_bb_size = box.max_size();
|
double max_bb_size = box.max_size();
|
||||||
if (max_bb_size == 0.0)
|
if (max_bb_size == 0.0)
|
||||||
|
@ -409,13 +441,15 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
||||||
double max_x = 0.0;
|
double max_x = 0.0;
|
||||||
double max_y = 0.0;
|
double max_y = 0.0;
|
||||||
|
|
||||||
|
#if !ENABLE_THUMBNAIL_GENERATOR
|
||||||
// margin factor to give some empty space around the box
|
// margin factor to give some empty space around the box
|
||||||
double margin_factor = 1.25;
|
double margin_factor = 1.25;
|
||||||
|
#endif // !ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
for (const Vec3d& v : vertices)
|
for (const Vec3d& v : vertices)
|
||||||
{
|
{
|
||||||
// project vertex on the plane perpendicular to camera forward axis
|
// project vertex on the plane perpendicular to camera forward axis
|
||||||
Vec3d pos(v(0) - bb_center(0), v(1) - bb_center(1), v(2) - bb_center(2));
|
Vec3d pos = v - bb_center;
|
||||||
Vec3d proj_on_plane = pos - pos.dot(forward) * forward;
|
Vec3d proj_on_plane = pos - pos.dot(forward) * forward;
|
||||||
|
|
||||||
// calculates vertex coordinate along camera xy axes
|
// calculates vertex coordinate along camera xy axes
|
||||||
|
@ -435,6 +469,72 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
||||||
return std::min((double)canvas_w / (2.0 * max_x), (double)canvas_h / (2.0 * max_y));
|
return std::min((double)canvas_w / (2.0 * max_x), (double)canvas_h / (2.0 * max_y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, int canvas_w, int canvas_h, Vec3d& center, double margin_factor) const
|
||||||
|
{
|
||||||
|
if (volumes.empty())
|
||||||
|
return -1.0;
|
||||||
|
|
||||||
|
// project the volumes vertices on a plane perpendicular to the camera forward axis
|
||||||
|
// then calculates the vertices coordinate on this plane along the camera xy axes
|
||||||
|
|
||||||
|
// ensure that the view matrix is updated
|
||||||
|
apply_view_matrix();
|
||||||
|
|
||||||
|
Vec3d right = get_dir_right();
|
||||||
|
Vec3d up = get_dir_up();
|
||||||
|
Vec3d forward = get_dir_forward();
|
||||||
|
|
||||||
|
BoundingBoxf3 box;
|
||||||
|
for (const GLVolume* volume : volumes)
|
||||||
|
{
|
||||||
|
box.merge(volume->transformed_bounding_box());
|
||||||
|
}
|
||||||
|
center = box.center();
|
||||||
|
|
||||||
|
double min_x = DBL_MAX;
|
||||||
|
double min_y = DBL_MAX;
|
||||||
|
double max_x = -DBL_MAX;
|
||||||
|
double max_y = -DBL_MAX;
|
||||||
|
|
||||||
|
for (const GLVolume* volume : volumes)
|
||||||
|
{
|
||||||
|
const Transform3d& transform = volume->world_matrix();
|
||||||
|
const TriangleMesh* hull = volume->convex_hull();
|
||||||
|
if (hull == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const Vec3f& vertex : hull->its.vertices)
|
||||||
|
{
|
||||||
|
Vec3d v = transform * vertex.cast<double>();
|
||||||
|
|
||||||
|
// project vertex on the plane perpendicular to camera forward axis
|
||||||
|
Vec3d pos = v - center;
|
||||||
|
Vec3d proj_on_plane = pos - pos.dot(forward) * forward;
|
||||||
|
|
||||||
|
// calculates vertex coordinate along camera xy axes
|
||||||
|
double x_on_plane = proj_on_plane.dot(right);
|
||||||
|
double y_on_plane = proj_on_plane.dot(up);
|
||||||
|
|
||||||
|
min_x = std::min(min_x, x_on_plane);
|
||||||
|
min_y = std::min(min_y, y_on_plane);
|
||||||
|
max_x = std::max(max_x, x_on_plane);
|
||||||
|
max_y = std::max(max_y, y_on_plane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
center += 0.5 * (max_x + min_x) * right + 0.5 * (max_y + min_y) * up;
|
||||||
|
|
||||||
|
double dx = margin_factor * (max_x - min_x);
|
||||||
|
double dy = margin_factor * (max_y - min_y);
|
||||||
|
|
||||||
|
if ((dx == 0.0) || (dy == 0.0))
|
||||||
|
return -1.0f;
|
||||||
|
|
||||||
|
return std::min((double)canvas_w / dx, (double)canvas_h / dy);
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
void Camera::set_distance(double distance) const
|
void Camera::set_distance(double distance) const
|
||||||
{
|
{
|
||||||
m_distance = distance;
|
m_distance = distance;
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#define slic3r_Camera_hpp_
|
#define slic3r_Camera_hpp_
|
||||||
|
|
||||||
#include "libslic3r/BoundingBox.hpp"
|
#include "libslic3r/BoundingBox.hpp"
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include "3DScene.hpp"
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -10,6 +13,10 @@ namespace GUI {
|
||||||
struct Camera
|
struct Camera
|
||||||
{
|
{
|
||||||
static const double DefaultDistance;
|
static const double DefaultDistance;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
static const double DefaultZoomToBoxMarginFactor;
|
||||||
|
static const double DefaultZoomToVolumesMarginFactor;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
static double FrustrumMinZRange;
|
static double FrustrumMinZRange;
|
||||||
static double FrustrumMinNearZ;
|
static double FrustrumMinNearZ;
|
||||||
static double FrustrumZMargin;
|
static double FrustrumZMargin;
|
||||||
|
@ -90,7 +97,12 @@ public:
|
||||||
void apply_view_matrix() const;
|
void apply_view_matrix() const;
|
||||||
void apply_projection(const BoundingBoxf3& box) const;
|
void apply_projection(const BoundingBoxf3& box) const;
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor = DefaultZoomToBoxMarginFactor);
|
||||||
|
void zoom_to_volumes(const GLVolumePtrs& volumes, int canvas_w, int canvas_h, double margin_factor = DefaultZoomToVolumesMarginFactor);
|
||||||
|
#else
|
||||||
void zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h);
|
void zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
#if ENABLE_CAMERA_STATISTICS
|
#if ENABLE_CAMERA_STATISTICS
|
||||||
void debug_render() const;
|
void debug_render() const;
|
||||||
|
@ -100,7 +112,12 @@ private:
|
||||||
// returns tight values for nearZ and farZ plane around the given bounding box
|
// returns tight values for nearZ and farZ plane around the given bounding box
|
||||||
// the camera MUST be outside of the bounding box in eye coordinate of the given box
|
// the camera MUST be outside of the bounding box in eye coordinate of the given box
|
||||||
std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const;
|
std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor = DefaultZoomToBoxMarginFactor) const;
|
||||||
|
double calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, int canvas_w, int canvas_h, Vec3d& center, double margin_factor = DefaultZoomToVolumesMarginFactor) const;
|
||||||
|
#else
|
||||||
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
|
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
void set_distance(double distance) const;
|
void set_distance(double distance) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,13 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||||
case coFloat:{
|
case coFloat:{
|
||||||
if (m_opt.type == coPercent && !str.IsEmpty() && str.Last() == '%')
|
if (m_opt.type == coPercent && !str.IsEmpty() && str.Last() == '%')
|
||||||
str.RemoveLast();
|
str.RemoveLast();
|
||||||
else if (check_value && !str.IsEmpty() && str.Last() == '%') {
|
else if (!str.IsEmpty() && str.Last() == '%')
|
||||||
|
{
|
||||||
|
if (!check_value) {
|
||||||
|
m_value.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
wxString label = m_Label->GetLabel();
|
wxString label = m_Label->GetLabel();
|
||||||
if (label.Last() == '\n') label.RemoveLast();
|
if (label.Last() == '\n') label.RemoveLast();
|
||||||
while (label.Last() == ' ') label.RemoveLast();
|
while (label.Last() == ' ') label.RemoveLast();
|
||||||
|
@ -169,13 +175,21 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||||
{
|
{
|
||||||
if (m_opt.nullable && str == na_value())
|
if (m_opt.nullable && str == na_value())
|
||||||
val = ConfigOptionFloatsNullable::nil_value();
|
val = ConfigOptionFloatsNullable::nil_value();
|
||||||
else if (check_value && !str.ToCDouble(&val))
|
else if (!str.ToCDouble(&val))
|
||||||
{
|
{
|
||||||
|
if (!check_value) {
|
||||||
|
m_value.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
show_error(m_parent, _(L("Invalid numeric input.")));
|
show_error(m_parent, _(L("Invalid numeric input.")));
|
||||||
set_value(double_to_string(val), true);
|
set_value(double_to_string(val), true);
|
||||||
}
|
}
|
||||||
if (check_value && (m_opt.min > val || val > m_opt.max))
|
if (m_opt.min > val || val > m_opt.max)
|
||||||
{
|
{
|
||||||
|
if (!check_value) {
|
||||||
|
m_value.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
show_error(m_parent, _(L("Input value is out of range")));
|
show_error(m_parent, _(L("Input value is out of range")));
|
||||||
if (m_opt.min > val) val = m_opt.min;
|
if (m_opt.min > val) val = m_opt.min;
|
||||||
if (val > m_opt.max) val = m_opt.max;
|
if (val > m_opt.max) val = m_opt.max;
|
||||||
|
@ -192,15 +206,24 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
||||||
double val = 0.;
|
double val = 0.;
|
||||||
// Replace the first occurence of comma in decimal number.
|
// Replace the first occurence of comma in decimal number.
|
||||||
str.Replace(",", ".", false);
|
str.Replace(",", ".", false);
|
||||||
if (check_value && !str.ToCDouble(&val))
|
if (!str.ToCDouble(&val))
|
||||||
{
|
{
|
||||||
|
if (!check_value) {
|
||||||
|
m_value.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
show_error(m_parent, _(L("Invalid numeric input.")));
|
show_error(m_parent, _(L("Invalid numeric input.")));
|
||||||
set_value(double_to_string(val), true);
|
set_value(double_to_string(val), true);
|
||||||
}
|
}
|
||||||
else if (check_value && ((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) ||
|
else if (((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) ||
|
||||||
(m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)) &&
|
(m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)) &&
|
||||||
(m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast<std::string>(m_value)))
|
(m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast<std::string>(m_value)))
|
||||||
{
|
{
|
||||||
|
if (!check_value) {
|
||||||
|
m_value.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
|
const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
|
||||||
const wxString stVal = double_to_string(val, 2);
|
const wxString stVal = double_to_string(val, 2);
|
||||||
const wxString msg_text = wxString::Format(_(L("Do you mean %s%% instead of %s %s?\n"
|
const wxString msg_text = wxString::Format(_(L("Do you mean %s%% instead of %s %s?\n"
|
||||||
|
@ -351,6 +374,7 @@ bool TextCtrl::value_was_changed()
|
||||||
boost::any val = m_value;
|
boost::any val = m_value;
|
||||||
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
||||||
// update m_value!
|
// update m_value!
|
||||||
|
// ret_str might be changed inside get_value_by_opt_type
|
||||||
get_value_by_opt_type(ret_str);
|
get_value_by_opt_type(ret_str);
|
||||||
|
|
||||||
switch (m_opt.type) {
|
switch (m_opt.type) {
|
||||||
|
@ -396,8 +420,10 @@ void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/)
|
||||||
|
|
||||||
if (!change_event) {
|
if (!change_event) {
|
||||||
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
||||||
// update m_value to correct work of next value_was_changed(),
|
/* Update m_value to correct work of next value_was_changed().
|
||||||
// but don't check/change inputed value and don't show a warning message
|
* But after checking of entered value, don't fix the "incorrect" value and don't show a warning message,
|
||||||
|
* just clear m_value in this case.
|
||||||
|
*/
|
||||||
get_value_by_opt_type(ret_str, false);
|
get_value_by_opt_type(ret_str, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
#include "libslic3r/ClipperUtils.hpp"
|
#include "libslic3r/ClipperUtils.hpp"
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
#include "libslic3r/GCode/PreviewData.hpp"
|
#include "libslic3r/GCode/PreviewData.hpp"
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include "libslic3r/GCode/ThumbnailData.hpp"
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
#include "libslic3r/Geometry.hpp"
|
#include "libslic3r/Geometry.hpp"
|
||||||
#include "libslic3r/ExtrusionEntity.hpp"
|
#include "libslic3r/ExtrusionEntity.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
|
@ -1117,6 +1120,10 @@ wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar)
|
GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar)
|
||||||
: m_canvas(canvas)
|
: m_canvas(canvas)
|
||||||
, m_context(nullptr)
|
, m_context(nullptr)
|
||||||
|
@ -1647,6 +1654,18 @@ void GLCanvas3D::render()
|
||||||
#endif // ENABLE_RENDER_STATISTICS
|
#endif // ENABLE_RENDER_STATISTICS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
|
{
|
||||||
|
switch (GLCanvas3DManager::get_framebuffers_type())
|
||||||
|
{
|
||||||
|
case GLCanvas3DManager::FB_Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; }
|
||||||
|
case GLCanvas3DManager::FB_Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; }
|
||||||
|
default: { _render_thumbnail_legacy(thumbnail_data, w, h, printable_only, parts_only, transparent_background); break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
void GLCanvas3D::select_all()
|
void GLCanvas3D::select_all()
|
||||||
{
|
{
|
||||||
m_selection.add_all();
|
m_selection.add_all();
|
||||||
|
@ -1930,7 +1949,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
if (it->new_geometry()) {
|
if (it->new_geometry()) {
|
||||||
// New volume.
|
// New volume.
|
||||||
unsigned int old_id = find_old_volume_id(it->composite_id);
|
unsigned int old_id = find_old_volume_id(it->composite_id);
|
||||||
if (old_id != -1)
|
if (old_id != (unsigned int)-1)
|
||||||
map_glvolume_old_to_new[old_id] = m_volumes.volumes.size();
|
map_glvolume_old_to_new[old_id] = m_volumes.volumes.size();
|
||||||
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized);
|
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized);
|
||||||
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
||||||
|
@ -3576,6 +3595,341 @@ void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x)
|
||||||
imgui->end();
|
imgui->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT 0
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
static void debug_output_thumbnail(const ThumbnailData& thumbnail_data)
|
||||||
|
{
|
||||||
|
// debug export of generated image
|
||||||
|
wxImage image(thumbnail_data.width, thumbnail_data.height);
|
||||||
|
image.InitAlpha();
|
||||||
|
|
||||||
|
for (unsigned int r = 0; r < thumbnail_data.height; ++r)
|
||||||
|
{
|
||||||
|
unsigned int rr = (thumbnail_data.height - 1 - r) * thumbnail_data.width;
|
||||||
|
for (unsigned int c = 0; c < thumbnail_data.width; ++c)
|
||||||
|
{
|
||||||
|
unsigned char* px = (unsigned char*)thumbnail_data.pixels.data() + 4 * (rr + c);
|
||||||
|
image.SetRGB((int)c, (int)r, px[0], px[1], px[2]);
|
||||||
|
image.SetAlpha((int)c, (int)r, px[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image.SaveFile("C:/prusa/test/test.png", wxBITMAP_TYPE_PNG);
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
|
||||||
|
|
||||||
|
static void render_volumes_in_thumbnail(Shader& shader, const GLVolumePtrs& volumes, ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
|
{
|
||||||
|
auto is_visible = [](const GLVolume& v) -> bool
|
||||||
|
{
|
||||||
|
bool ret = v.printable;
|
||||||
|
ret &= (!v.shader_outside_printer_detection_enabled || !v.is_outside);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GLfloat orange[] = { 0.923f, 0.504f, 0.264f, 1.0f };
|
||||||
|
static const GLfloat gray[] = { 0.64f, 0.64f, 0.64f, 1.0f };
|
||||||
|
|
||||||
|
GLVolumePtrs visible_volumes;
|
||||||
|
|
||||||
|
for (GLVolume* vol : volumes)
|
||||||
|
{
|
||||||
|
if (!vol->is_modifier && !vol->is_wipe_tower && (!parts_only || (vol->composite_id.volume_id >= 0)))
|
||||||
|
{
|
||||||
|
if (!printable_only || is_visible(*vol))
|
||||||
|
visible_volumes.push_back(vol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visible_volumes.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
BoundingBoxf3 box;
|
||||||
|
for (const GLVolume* vol : visible_volumes)
|
||||||
|
{
|
||||||
|
box.merge(vol->transformed_bounding_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera camera;
|
||||||
|
camera.set_type(Camera::Ortho);
|
||||||
|
camera.zoom_to_volumes(visible_volumes, thumbnail_data.width, thumbnail_data.height);
|
||||||
|
camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
|
||||||
|
camera.apply_view_matrix();
|
||||||
|
camera.apply_projection(box);
|
||||||
|
|
||||||
|
if (transparent_background)
|
||||||
|
glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 0.0f));
|
||||||
|
|
||||||
|
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||||
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
|
shader.start_using();
|
||||||
|
|
||||||
|
GLint shader_id = shader.get_shader_program_id();
|
||||||
|
GLint color_id = ::glGetUniformLocation(shader_id, "uniform_color");
|
||||||
|
GLint print_box_detection_id = ::glGetUniformLocation(shader_id, "print_box.volume_detection");
|
||||||
|
glcheck();
|
||||||
|
|
||||||
|
if (print_box_detection_id != -1)
|
||||||
|
glsafe(::glUniform1i(print_box_detection_id, 0));
|
||||||
|
|
||||||
|
for (const GLVolume* vol : visible_volumes)
|
||||||
|
{
|
||||||
|
if (color_id >= 0)
|
||||||
|
glsafe(::glUniform4fv(color_id, 1, (vol->printable && !vol->is_outside) ? orange : gray));
|
||||||
|
else
|
||||||
|
glsafe(::glColor4fv((vol->printable && !vol->is_outside) ? orange : gray));
|
||||||
|
|
||||||
|
vol->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
shader.stop_using();
|
||||||
|
|
||||||
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
|
if (transparent_background)
|
||||||
|
glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
|
{
|
||||||
|
thumbnail_data.set(w, h);
|
||||||
|
if (!thumbnail_data.is_valid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool multisample = m_multisample_allowed;
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glEnable(GL_MULTISAMPLE));
|
||||||
|
|
||||||
|
GLint max_samples;
|
||||||
|
glsafe(::glGetIntegerv(GL_MAX_SAMPLES, &max_samples));
|
||||||
|
GLsizei num_samples = max_samples / 2;
|
||||||
|
|
||||||
|
GLuint render_fbo;
|
||||||
|
glsafe(::glGenFramebuffers(1, &render_fbo));
|
||||||
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
|
||||||
|
|
||||||
|
GLuint render_tex = 0;
|
||||||
|
GLuint render_tex_buffer = 0;
|
||||||
|
if (multisample)
|
||||||
|
{
|
||||||
|
// use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2
|
||||||
|
glsafe(::glGenRenderbuffers(1, &render_tex_buffer));
|
||||||
|
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_tex_buffer));
|
||||||
|
glsafe(::glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_RGBA8, w, h));
|
||||||
|
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_tex_buffer));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glsafe(::glGenTextures(1, &render_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint render_depth;
|
||||||
|
glsafe(::glGenRenderbuffers(1, &render_depth));
|
||||||
|
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth));
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_DEPTH_COMPONENT24, w, h));
|
||||||
|
else
|
||||||
|
glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h));
|
||||||
|
|
||||||
|
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
|
||||||
|
|
||||||
|
GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
|
||||||
|
glsafe(::glDrawBuffers(1, drawBufs));
|
||||||
|
|
||||||
|
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
|
render_volumes_in_thumbnail(m_shader, m_volumes.volumes, thumbnail_data, printable_only, parts_only, transparent_background);
|
||||||
|
|
||||||
|
if (multisample)
|
||||||
|
{
|
||||||
|
GLuint resolve_fbo;
|
||||||
|
glsafe(::glGenFramebuffers(1, &resolve_fbo));
|
||||||
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo));
|
||||||
|
|
||||||
|
GLuint resolve_tex;
|
||||||
|
glsafe(::glGenTextures(1, &resolve_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, resolve_tex));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolve_tex, 0));
|
||||||
|
|
||||||
|
glsafe(::glDrawBuffers(1, drawBufs));
|
||||||
|
|
||||||
|
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
|
glsafe(::glBindFramebuffer(GL_READ_FRAMEBUFFER, render_fbo));
|
||||||
|
glsafe(::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo));
|
||||||
|
glsafe(::glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR));
|
||||||
|
|
||||||
|
glsafe(::glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo));
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glDeleteTextures(1, &resolve_tex));
|
||||||
|
glsafe(::glDeleteFramebuffers(1, &resolve_fbo));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
debug_output_thumbnail(thumbnail_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||||
|
glsafe(::glDeleteRenderbuffers(1, &render_depth));
|
||||||
|
if (render_tex_buffer != 0)
|
||||||
|
glsafe(::glDeleteRenderbuffers(1, &render_tex_buffer));
|
||||||
|
if (render_tex != 0)
|
||||||
|
glsafe(::glDeleteTextures(1, &render_tex));
|
||||||
|
glsafe(::glDeleteFramebuffers(1, &render_fbo));
|
||||||
|
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glDisable(GL_MULTISAMPLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
|
{
|
||||||
|
thumbnail_data.set(w, h);
|
||||||
|
if (!thumbnail_data.is_valid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool multisample = m_multisample_allowed;
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glEnable(GL_MULTISAMPLE));
|
||||||
|
|
||||||
|
GLint max_samples;
|
||||||
|
glsafe(::glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples));
|
||||||
|
GLsizei num_samples = max_samples / 2;
|
||||||
|
|
||||||
|
GLuint render_fbo;
|
||||||
|
glsafe(::glGenFramebuffersEXT(1, &render_fbo));
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, render_fbo));
|
||||||
|
|
||||||
|
GLuint render_tex = 0;
|
||||||
|
GLuint render_tex_buffer = 0;
|
||||||
|
if (multisample)
|
||||||
|
{
|
||||||
|
// use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2
|
||||||
|
glsafe(::glGenRenderbuffersEXT(1, &render_tex_buffer));
|
||||||
|
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_tex_buffer));
|
||||||
|
glsafe(::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, num_samples, GL_RGBA8, w, h));
|
||||||
|
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, render_tex_buffer));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glsafe(::glGenTextures(1, &render_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, render_tex, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint render_depth;
|
||||||
|
glsafe(::glGenRenderbuffersEXT(1, &render_depth));
|
||||||
|
glsafe(::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_depth));
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, num_samples, GL_DEPTH_COMPONENT24, w, h));
|
||||||
|
else
|
||||||
|
glsafe(::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, w, h));
|
||||||
|
|
||||||
|
glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, render_depth));
|
||||||
|
|
||||||
|
GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
|
||||||
|
glsafe(::glDrawBuffers(1, drawBufs));
|
||||||
|
|
||||||
|
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||||
|
{
|
||||||
|
render_volumes_in_thumbnail(m_shader, m_volumes.volumes, thumbnail_data, printable_only, parts_only, transparent_background);
|
||||||
|
|
||||||
|
if (multisample)
|
||||||
|
{
|
||||||
|
GLuint resolve_fbo;
|
||||||
|
glsafe(::glGenFramebuffersEXT(1, &resolve_fbo));
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, resolve_fbo));
|
||||||
|
|
||||||
|
GLuint resolve_tex;
|
||||||
|
glsafe(::glGenTextures(1, &resolve_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, resolve_tex));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, resolve_tex, 0));
|
||||||
|
|
||||||
|
glsafe(::glDrawBuffers(1, drawBufs));
|
||||||
|
|
||||||
|
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||||
|
{
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, render_fbo));
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, resolve_fbo));
|
||||||
|
glsafe(::glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR));
|
||||||
|
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, resolve_fbo));
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glDeleteTextures(1, &resolve_tex));
|
||||||
|
glsafe(::glDeleteFramebuffersEXT(1, &resolve_fbo));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
debug_output_thumbnail(thumbnail_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
glsafe(::glDeleteRenderbuffersEXT(1, &render_depth));
|
||||||
|
if (render_tex_buffer != 0)
|
||||||
|
glsafe(::glDeleteRenderbuffersEXT(1, &render_tex_buffer));
|
||||||
|
if (render_tex != 0)
|
||||||
|
glsafe(::glDeleteTextures(1, &render_tex));
|
||||||
|
glsafe(::glDeleteFramebuffersEXT(1, &render_fbo));
|
||||||
|
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glDisable(GL_MULTISAMPLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
|
{
|
||||||
|
// check that thumbnail size does not exceed the default framebuffer size
|
||||||
|
const Size& cnv_size = get_canvas_size();
|
||||||
|
unsigned int cnv_w = (unsigned int)cnv_size.get_width();
|
||||||
|
unsigned int cnv_h = (unsigned int)cnv_size.get_height();
|
||||||
|
if ((w > cnv_w) || (h > cnv_h))
|
||||||
|
{
|
||||||
|
float ratio = std::min((float)cnv_w / (float)w, (float)cnv_h / (float)h);
|
||||||
|
w = (unsigned int)(ratio * (float)w);
|
||||||
|
h = (unsigned int)(ratio * (float)h);
|
||||||
|
}
|
||||||
|
|
||||||
|
thumbnail_data.set(w, h);
|
||||||
|
if (!thumbnail_data.is_valid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
render_volumes_in_thumbnail(m_shader, m_volumes.volumes, thumbnail_data, printable_only, parts_only, transparent_background);
|
||||||
|
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
debug_output_thumbnail(thumbnail_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
|
||||||
|
// restore the default framebuffer size to avoid flickering on the 3D scene
|
||||||
|
m_camera.apply_viewport(0, 0, cnv_size.get_width(), cnv_size.get_height());
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
bool GLCanvas3D::_init_toolbars()
|
bool GLCanvas3D::_init_toolbars()
|
||||||
{
|
{
|
||||||
if (!_init_main_toolbar())
|
if (!_init_main_toolbar())
|
||||||
|
@ -3885,12 +4239,21 @@ BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_gizmos, bool include_be
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void GLCanvas3D::_zoom_to_box(const BoundingBoxf3& box, double margin_factor)
|
||||||
|
{
|
||||||
|
const Size& cnv_size = get_canvas_size();
|
||||||
|
m_camera.zoom_to_box(box, cnv_size.get_width(), cnv_size.get_height(), margin_factor);
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
void GLCanvas3D::_zoom_to_box(const BoundingBoxf3& box)
|
void GLCanvas3D::_zoom_to_box(const BoundingBoxf3& box)
|
||||||
{
|
{
|
||||||
const Size& cnv_size = get_canvas_size();
|
const Size& cnv_size = get_canvas_size();
|
||||||
m_camera.zoom_to_box(box, cnv_size.get_width(), cnv_size.get_height());
|
m_camera.zoom_to_box(box, cnv_size.get_width(), cnv_size.get_height());
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
void GLCanvas3D::_update_camera_zoom(double zoom)
|
void GLCanvas3D::_update_camera_zoom(double zoom)
|
||||||
{
|
{
|
||||||
|
@ -4093,7 +4456,9 @@ void GLCanvas3D::_render_objects() const
|
||||||
if (m_volumes.empty())
|
if (m_volumes.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if !ENABLE_THUMBNAIL_GENERATOR
|
||||||
glsafe(::glEnable(GL_LIGHTING));
|
glsafe(::glEnable(GL_LIGHTING));
|
||||||
|
#endif // !ENABLE_THUMBNAIL_GENERATOR
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
m_camera_clipping_plane = m_gizmos.get_sla_clipping_plane();
|
m_camera_clipping_plane = m_gizmos.get_sla_clipping_plane();
|
||||||
|
@ -4137,7 +4502,9 @@ void GLCanvas3D::_render_objects() const
|
||||||
m_shader.stop_using();
|
m_shader.stop_using();
|
||||||
|
|
||||||
m_camera_clipping_plane = ClippingPlane::ClipsNothing();
|
m_camera_clipping_plane = ClippingPlane::ClipsNothing();
|
||||||
|
#if !ENABLE_THUMBNAIL_GENERATOR
|
||||||
glsafe(::glDisable(GL_LIGHTING));
|
glsafe(::glDisable(GL_LIGHTING));
|
||||||
|
#endif // !ENABLE_THUMBNAIL_GENERATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_render_selection() const
|
void GLCanvas3D::_render_selection() const
|
||||||
|
|
|
@ -36,6 +36,9 @@ class GLShader;
|
||||||
class ExPolygon;
|
class ExPolygon;
|
||||||
class BackgroundSlicingProcess;
|
class BackgroundSlicingProcess;
|
||||||
class GCodePreviewData;
|
class GCodePreviewData;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
struct ThumbnailData;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
struct SlicingParameters;
|
struct SlicingParameters;
|
||||||
enum LayerHeightEditActionType : unsigned int;
|
enum LayerHeightEditActionType : unsigned int;
|
||||||
|
|
||||||
|
@ -104,6 +107,10 @@ wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
|
||||||
|
|
||||||
class GLCanvas3D
|
class GLCanvas3D
|
||||||
{
|
{
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
static const double DefaultCameraZoomToBoxMarginFactor;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct GCodePreviewVolumeIndex
|
struct GCodePreviewVolumeIndex
|
||||||
{
|
{
|
||||||
|
@ -520,6 +527,11 @@ public:
|
||||||
bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
|
bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
// printable_only == false -> render also non printable volumes as grayed
|
||||||
|
// parts_only == false -> render also sla support and pad
|
||||||
|
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
void select_all();
|
void select_all();
|
||||||
void deselect_all();
|
void deselect_all();
|
||||||
|
@ -637,7 +649,11 @@ private:
|
||||||
|
|
||||||
BoundingBoxf3 _max_bounding_box(bool include_gizmos, bool include_bed_model) const;
|
BoundingBoxf3 _max_bounding_box(bool include_gizmos, bool include_bed_model) const;
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void _zoom_to_box(const BoundingBoxf3& box, double margin_factor = DefaultCameraZoomToBoxMarginFactor);
|
||||||
|
#else
|
||||||
void _zoom_to_box(const BoundingBoxf3& box);
|
void _zoom_to_box(const BoundingBoxf3& box);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
void _update_camera_zoom(double zoom);
|
void _update_camera_zoom(double zoom);
|
||||||
|
|
||||||
void _refresh_if_shown_on_screen();
|
void _refresh_if_shown_on_screen();
|
||||||
|
@ -666,6 +682,14 @@ private:
|
||||||
void _render_sla_slices() const;
|
void _render_sla_slices() const;
|
||||||
void _render_selection_sidebar_hints() const;
|
void _render_selection_sidebar_hints() const;
|
||||||
void _render_undo_redo_stack(const bool is_undo, float pos_x);
|
void _render_undo_redo_stack(const bool is_undo, float pos_x);
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
// render thumbnail using an off-screen framebuffer
|
||||||
|
void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
||||||
|
// render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported
|
||||||
|
void _render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
||||||
|
// render thumbnail using the default framebuffer
|
||||||
|
void _render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
void _update_volumes_hover_state() const;
|
void _update_volumes_hover_state() const;
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,7 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten
|
||||||
|
|
||||||
GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown;
|
GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown;
|
||||||
bool GLCanvas3DManager::s_compressed_textures_supported = false;
|
bool GLCanvas3DManager::s_compressed_textures_supported = false;
|
||||||
|
GLCanvas3DManager::EFramebufferType GLCanvas3DManager::s_framebuffers_type = GLCanvas3DManager::FB_None;
|
||||||
GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;
|
GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;
|
||||||
|
|
||||||
GLCanvas3DManager::GLCanvas3DManager()
|
GLCanvas3DManager::GLCanvas3DManager()
|
||||||
|
@ -269,6 +270,13 @@ void GLCanvas3DManager::init_gl()
|
||||||
else
|
else
|
||||||
s_compressed_textures_supported = false;
|
s_compressed_textures_supported = false;
|
||||||
|
|
||||||
|
if (GLEW_ARB_framebuffer_object)
|
||||||
|
s_framebuffers_type = FB_Arb;
|
||||||
|
else if (GLEW_EXT_framebuffer_object)
|
||||||
|
s_framebuffers_type = FB_Ext;
|
||||||
|
else
|
||||||
|
s_framebuffers_type = FB_None;
|
||||||
|
|
||||||
if (! s_gl_info.is_version_greater_or_equal_to(2, 0)) {
|
if (! s_gl_info.is_version_greater_or_equal_to(2, 0)) {
|
||||||
// Complain about the OpenGL version.
|
// Complain about the OpenGL version.
|
||||||
wxString message = wxString::Format(
|
wxString message = wxString::Format(
|
||||||
|
|
|
@ -30,6 +30,13 @@ struct Camera;
|
||||||
class GLCanvas3DManager
|
class GLCanvas3DManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum EFramebufferType : unsigned char
|
||||||
|
{
|
||||||
|
FB_None,
|
||||||
|
FB_Arb,
|
||||||
|
FB_Ext
|
||||||
|
};
|
||||||
|
|
||||||
class GLInfo
|
class GLInfo
|
||||||
{
|
{
|
||||||
mutable bool m_detected;
|
mutable bool m_detected;
|
||||||
|
@ -77,6 +84,7 @@ private:
|
||||||
bool m_gl_initialized;
|
bool m_gl_initialized;
|
||||||
static EMultisampleState s_multisample;
|
static EMultisampleState s_multisample;
|
||||||
static bool s_compressed_textures_supported;
|
static bool s_compressed_textures_supported;
|
||||||
|
static EFramebufferType s_framebuffers_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLCanvas3DManager();
|
GLCanvas3DManager();
|
||||||
|
@ -97,6 +105,8 @@ public:
|
||||||
|
|
||||||
static bool can_multisample() { return s_multisample == MS_Enabled; }
|
static bool can_multisample() { return s_multisample == MS_Enabled; }
|
||||||
static bool are_compressed_textures_supported() { return s_compressed_textures_supported; }
|
static bool are_compressed_textures_supported() { return s_compressed_textures_supported; }
|
||||||
|
static bool are_framebuffers_supported() { return (s_framebuffers_type != FB_None); }
|
||||||
|
static EFramebufferType get_framebuffers_type() { return s_framebuffers_type; }
|
||||||
|
|
||||||
static wxGLCanvas* create_wxglcanvas(wxWindow *parent);
|
static wxGLCanvas* create_wxglcanvas(wxWindow *parent);
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,11 @@
|
||||||
#include <Shlobj.h>
|
#include <Shlobj.h>
|
||||||
#endif // __WXMSW__
|
#endif // __WXMSW__
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include <boost/beast/core/detail/base64.hpp>
|
||||||
|
#include <boost/nowide/fstream.hpp>
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
@ -1082,6 +1087,117 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG
|
||||||
|
void GUI_App::gcode_thumbnails_debug()
|
||||||
|
{
|
||||||
|
const std::string BEGIN_MASK = "; thumbnail begin";
|
||||||
|
const std::string END_MASK = "; thumbnail end";
|
||||||
|
std::string gcode_line;
|
||||||
|
bool reading_image = false;
|
||||||
|
unsigned int width = 0;
|
||||||
|
unsigned int height = 0;
|
||||||
|
|
||||||
|
wxFileDialog dialog(GetTopWindow(), _(L("Select a gcode file:")), "", "", "G-code files (*.gcode)|*.gcode;*.GCODE;", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
|
if (dialog.ShowModal() != wxID_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string in_filename = into_u8(dialog.GetPath());
|
||||||
|
std::string out_path = boost::filesystem::path(in_filename).remove_filename().append(L"thumbnail").string();
|
||||||
|
|
||||||
|
boost::nowide::ifstream in_file(in_filename.c_str());
|
||||||
|
std::vector<std::string> rows;
|
||||||
|
std::string row;
|
||||||
|
if (in_file.good())
|
||||||
|
{
|
||||||
|
while (std::getline(in_file, gcode_line))
|
||||||
|
{
|
||||||
|
if (in_file.good())
|
||||||
|
{
|
||||||
|
if (boost::starts_with(gcode_line, BEGIN_MASK))
|
||||||
|
{
|
||||||
|
reading_image = true;
|
||||||
|
gcode_line = gcode_line.substr(BEGIN_MASK.length() + 1);
|
||||||
|
std::string::size_type x_pos = gcode_line.find('x');
|
||||||
|
std::string width_str = gcode_line.substr(0, x_pos);
|
||||||
|
width = (unsigned int)::atoi(width_str.c_str());
|
||||||
|
std::string height_str = gcode_line.substr(x_pos + 1);
|
||||||
|
height = (unsigned int)::atoi(height_str.c_str());
|
||||||
|
row.clear();
|
||||||
|
}
|
||||||
|
else if (reading_image && boost::starts_with(gcode_line, END_MASK))
|
||||||
|
{
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE
|
||||||
|
std::string out_filename = out_path + std::to_string(width) + "x" + std::to_string(height) + ".png";
|
||||||
|
boost::nowide::ofstream out_file(out_filename.c_str(), std::ios::binary);
|
||||||
|
if (out_file.good())
|
||||||
|
{
|
||||||
|
std::string decoded = boost::beast::detail::base64_decode(row);
|
||||||
|
out_file.write(decoded.c_str(), decoded.length());
|
||||||
|
out_file.close();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!row.empty())
|
||||||
|
{
|
||||||
|
rows.push_back(row);
|
||||||
|
row.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((unsigned int)rows.size() == height)
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> thumbnail(4 * width * height, 0);
|
||||||
|
for (unsigned int r = 0; r < (unsigned int)rows.size(); ++r)
|
||||||
|
{
|
||||||
|
std::string decoded_row = boost::beast::detail::base64_decode(rows[r]);
|
||||||
|
if ((unsigned int)decoded_row.length() == width * 4)
|
||||||
|
{
|
||||||
|
void* image_ptr = (void*)(thumbnail.data() + r * width * 4);
|
||||||
|
::memcpy(image_ptr, (const void*)decoded_row.c_str(), width * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxImage image(width, height);
|
||||||
|
image.InitAlpha();
|
||||||
|
|
||||||
|
for (unsigned int r = 0; r < height; ++r)
|
||||||
|
{
|
||||||
|
unsigned int rr = r * width;
|
||||||
|
for (unsigned int c = 0; c < width; ++c)
|
||||||
|
{
|
||||||
|
unsigned char* px = thumbnail.data() + 4 * (rr + c);
|
||||||
|
image.SetRGB((int)c, (int)r, px[0], px[1], px[2]);
|
||||||
|
image.SetAlpha((int)c, (int)r, px[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image.SaveFile(out_path + std::to_string(width) + "x" + std::to_string(height) + ".png", wxBITMAP_TYPE_PNG);
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE
|
||||||
|
|
||||||
|
reading_image = false;
|
||||||
|
width = 0;
|
||||||
|
height = 0;
|
||||||
|
rows.clear();
|
||||||
|
}
|
||||||
|
else if (reading_image)
|
||||||
|
{
|
||||||
|
#if !ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE
|
||||||
|
if (!row.empty() && (gcode_line[1] == ' '))
|
||||||
|
{
|
||||||
|
rows.push_back(row);
|
||||||
|
row.clear();
|
||||||
|
}
|
||||||
|
#endif // !ENABLE_THUMBNAIL_GENERATOR_PNG_TO_GCODE
|
||||||
|
|
||||||
|
row += gcode_line.substr(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in_file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG
|
||||||
|
|
||||||
void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name)
|
void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name)
|
||||||
{
|
{
|
||||||
if (name.empty()) { return; }
|
if (name.empty()) { return; }
|
||||||
|
|
|
@ -87,7 +87,7 @@ class GUI_App : public wxApp
|
||||||
wxFont m_bold_font;
|
wxFont m_bold_font;
|
||||||
wxFont m_normal_font;
|
wxFont m_normal_font;
|
||||||
|
|
||||||
size_t m_em_unit; // width of a "m"-symbol in pixels for current system font
|
int m_em_unit; // width of a "m"-symbol in pixels for current system font
|
||||||
// Note: for 100% Scale m_em_unit = 10 -> it's a good enough coefficient for a size setting of controls
|
// Note: for 100% Scale m_em_unit = 10 -> it's a good enough coefficient for a size setting of controls
|
||||||
|
|
||||||
std::unique_ptr<wxLocale> m_wxLocale;
|
std::unique_ptr<wxLocale> m_wxLocale;
|
||||||
|
@ -105,7 +105,7 @@ public:
|
||||||
bool initialized() const { return m_initialized; }
|
bool initialized() const { return m_initialized; }
|
||||||
|
|
||||||
GUI_App();
|
GUI_App();
|
||||||
~GUI_App();
|
~GUI_App() override;
|
||||||
|
|
||||||
static unsigned get_colour_approx_luma(const wxColour &colour);
|
static unsigned get_colour_approx_luma(const wxColour &colour);
|
||||||
static bool dark_mode();
|
static bool dark_mode();
|
||||||
|
@ -124,8 +124,7 @@ public:
|
||||||
const wxFont& small_font() { return m_small_font; }
|
const wxFont& small_font() { return m_small_font; }
|
||||||
const wxFont& bold_font() { return m_bold_font; }
|
const wxFont& bold_font() { return m_bold_font; }
|
||||||
const wxFont& normal_font() { return m_normal_font; }
|
const wxFont& normal_font() { return m_normal_font; }
|
||||||
size_t em_unit() const { return m_em_unit; }
|
int em_unit() const { return m_em_unit; }
|
||||||
void set_em_unit(const size_t em_unit) { m_em_unit = em_unit; }
|
|
||||||
float toolbar_icon_scale(const bool is_limited = false) const;
|
float toolbar_icon_scale(const bool is_limited = false) const;
|
||||||
|
|
||||||
void recreate_GUI();
|
void recreate_GUI();
|
||||||
|
@ -155,7 +154,7 @@ public:
|
||||||
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
|
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
|
||||||
wxString current_language_code_safe() const;
|
wxString current_language_code_safe() const;
|
||||||
|
|
||||||
virtual bool OnExceptionInMainLoop();
|
virtual bool OnExceptionInMainLoop() override;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// wxWidgets override to get an event on open files.
|
// wxWidgets override to get an event on open files.
|
||||||
|
@ -189,6 +188,11 @@ public:
|
||||||
void open_web_page_localized(const std::string &http_address);
|
void open_web_page_localized(const std::string &http_address);
|
||||||
bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME);
|
bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME);
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
// temporary and debug only -> extract thumbnails from selected gcode and save them as png files
|
||||||
|
void gcode_thumbnails_debug();
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool on_init_inner();
|
bool on_init_inner();
|
||||||
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
|
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
|
||||||
|
|
|
@ -445,7 +445,7 @@ void ObjectList::update_extruder_values_for_items(const size_t max_extruder)
|
||||||
auto object = (*m_objects)[i];
|
auto object = (*m_objects)[i];
|
||||||
wxString extruder;
|
wxString extruder;
|
||||||
if (!object->config.has("extruder") ||
|
if (!object->config.has("extruder") ||
|
||||||
object->config.option<ConfigOptionInt>("extruder")->value > max_extruder)
|
size_t(object->config.option<ConfigOptionInt>("extruder")->value) > max_extruder)
|
||||||
extruder = _(L("default"));
|
extruder = _(L("default"));
|
||||||
else
|
else
|
||||||
extruder = wxString::Format("%d", object->config.option<ConfigOptionInt>("extruder")->value);
|
extruder = wxString::Format("%d", object->config.option<ConfigOptionInt>("extruder")->value);
|
||||||
|
@ -457,7 +457,7 @@ void ObjectList::update_extruder_values_for_items(const size_t max_extruder)
|
||||||
item = m_objects_model->GetItemByVolumeId(i, id);
|
item = m_objects_model->GetItemByVolumeId(i, id);
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
if (!object->volumes[id]->config.has("extruder") ||
|
if (!object->volumes[id]->config.has("extruder") ||
|
||||||
object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value > max_extruder)
|
size_t(object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value) > max_extruder)
|
||||||
extruder = _(L("default"));
|
extruder = _(L("default"));
|
||||||
else
|
else
|
||||||
extruder = wxString::Format("%d", object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value);
|
extruder = wxString::Format("%d", object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value);
|
||||||
|
|
|
@ -632,7 +632,11 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
||||||
show_drop_to_bed = (std::abs(min_z) > EPSILON);
|
show_drop_to_bed = (std::abs(min_z) > EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed]{
|
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed] {
|
||||||
|
// There is a case (under OSX), when this function is called after the Manipulation panel is hidden
|
||||||
|
// So, let check if Manipulation panel is still shown for this moment
|
||||||
|
if (!this->IsShown())
|
||||||
|
return;
|
||||||
m_reset_rotation_button->Show(show_rotation);
|
m_reset_rotation_button->Show(show_rotation);
|
||||||
m_reset_scale_button->Show(show_scale);
|
m_reset_scale_button->Show(show_scale);
|
||||||
m_drop_to_bed_button->Show(show_drop_to_bed);
|
m_drop_to_bed_button->Show(show_drop_to_bed);
|
||||||
|
|
|
@ -375,6 +375,8 @@ void Preview::load_print(bool keep_z_range)
|
||||||
load_print_as_fff(keep_z_range);
|
load_print_as_fff(keep_z_range);
|
||||||
else if (tech == ptSLA)
|
else if (tech == ptSLA)
|
||||||
load_print_as_sla();
|
load_print_as_sla();
|
||||||
|
|
||||||
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preview::reload_print(bool keep_volumes)
|
void Preview::reload_print(bool keep_volumes)
|
||||||
|
|
|
@ -114,8 +114,17 @@ public:
|
||||||
|
|
||||||
m_serializing = true;
|
m_serializing = true;
|
||||||
|
|
||||||
|
// Following is needed to know which to be turn on, but not actually modify
|
||||||
|
// m_current prematurely, so activate_gizmo is not confused.
|
||||||
|
EType old_current = m_current;
|
||||||
ar(m_current);
|
ar(m_current);
|
||||||
|
EType new_current = m_current;
|
||||||
|
m_current = old_current;
|
||||||
|
|
||||||
|
// activate_gizmo call sets m_current and calls set_state for the gizmo
|
||||||
|
// it does nothing in case the gizmo is already activated
|
||||||
|
// it can safely be called for Undefined gizmo
|
||||||
|
activate_gizmo(new_current);
|
||||||
if (m_current != Undefined)
|
if (m_current != Undefined)
|
||||||
m_gizmos[m_current]->load(ar);
|
m_gizmos[m_current]->load(ar);
|
||||||
}
|
}
|
||||||
|
|
|
@ -683,6 +683,11 @@ void MainFrame::init_menubar()
|
||||||
helpMenu->AppendSeparator();
|
helpMenu->AppendSeparator();
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("Keyboard Shortcuts")) + sep + "&?", _(L("Show the list of the keyboard shortcuts")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("Keyboard Shortcuts")) + sep + "&?", _(L("Show the list of the keyboard shortcuts")),
|
||||||
[this](wxCommandEvent&) { wxGetApp().keyboard_shortcuts(); });
|
[this](wxCommandEvent&) { wxGetApp().keyboard_shortcuts(); });
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG
|
||||||
|
helpMenu->AppendSeparator();
|
||||||
|
append_menu_item(helpMenu, wxID_ANY, _(L("DEBUG gcode thumbnails")), _(L("DEBUG ONLY - read the selected gcode file and generates png for the contained thumbnails")),
|
||||||
|
[this](wxCommandEvent&) { wxGetApp().gcode_thumbnails_debug(); });
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
// menubar
|
// menubar
|
||||||
|
|
|
@ -233,7 +233,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n
|
||||||
|
|
||||||
add_undo_buttuns_to_sizer(sizer, field);
|
add_undo_buttuns_to_sizer(sizer, field);
|
||||||
if (is_window_field(field))
|
if (is_window_field(field))
|
||||||
sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, //(option.opt.full_width ? wxEXPAND : 0) |
|
sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, //(option.opt.full_width ? wxEXPAND : 0) |
|
||||||
wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2);
|
wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2);
|
||||||
if (is_sizer_field(field))
|
if (is_sizer_field(field))
|
||||||
sizer->Add(field->getSizer(), 1, /*(*/option.opt.full_width ? wxEXPAND : /*0) |*/ wxALIGN_CENTER_VERTICAL, 0);
|
sizer->Add(field->getSizer(), 1, /*(*/option.opt.full_width ? wxEXPAND : /*0) |*/ wxALIGN_CENTER_VERTICAL, 0);
|
||||||
|
|
|
@ -32,6 +32,9 @@
|
||||||
#include "libslic3r/Format/AMF.hpp"
|
#include "libslic3r/Format/AMF.hpp"
|
||||||
#include "libslic3r/Format/3mf.hpp"
|
#include "libslic3r/Format/3mf.hpp"
|
||||||
#include "libslic3r/GCode/PreviewData.hpp"
|
#include "libslic3r/GCode/PreviewData.hpp"
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#include "libslic3r/GCode/ThumbnailData.hpp"
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/Polygon.hpp"
|
#include "libslic3r/Polygon.hpp"
|
||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
|
@ -83,6 +86,11 @@ using Slic3r::_3DScene;
|
||||||
using Slic3r::Preset;
|
using Slic3r::Preset;
|
||||||
using Slic3r::PrintHostJob;
|
using Slic3r::PrintHostJob;
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
static const std::vector < std::pair<unsigned int, unsigned int>> THUMBNAIL_SIZE_FFF = { { 240, 320 }, { 220, 165 }, { 16, 16 } };
|
||||||
|
static const std::vector<std::pair<unsigned int, unsigned int>> THUMBNAIL_SIZE_SLA = { { 800, 480 } };
|
||||||
|
static const std::pair<unsigned int, unsigned int> THUMBNAIL_SIZE_3MF = { 256, 256 };
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
@ -176,7 +184,7 @@ void ObjectInfo::msw_rescale()
|
||||||
manifold_warning_icon->SetBitmap(create_scaled_bitmap(nullptr, "exclamation"));
|
manifold_warning_icon->SetBitmap(create_scaled_bitmap(nullptr, "exclamation"));
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SlisedInfoIdx
|
enum SlicedInfoIdx
|
||||||
{
|
{
|
||||||
siFilament_m,
|
siFilament_m,
|
||||||
siFilament_mm3,
|
siFilament_mm3,
|
||||||
|
@ -193,7 +201,7 @@ class SlicedInfo : public wxStaticBoxSizer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SlicedInfo(wxWindow *parent);
|
SlicedInfo(wxWindow *parent);
|
||||||
void SetTextAndShow(SlisedInfoIdx idx, const wxString& text, const wxString& new_label="");
|
void SetTextAndShow(SlicedInfoIdx idx, const wxString& text, const wxString& new_label="");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<wxStaticText*, wxStaticText*>> info_vec;
|
std::vector<std::pair<wxStaticText*, wxStaticText*>> info_vec;
|
||||||
|
@ -231,7 +239,7 @@ SlicedInfo::SlicedInfo(wxWindow *parent) :
|
||||||
this->Show(false);
|
this->Show(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlicedInfo::SetTextAndShow(SlisedInfoIdx idx, const wxString& text, const wxString& new_label/*=""*/)
|
void SlicedInfo::SetTextAndShow(SlicedInfoIdx idx, const wxString& text, const wxString& new_label/*=""*/)
|
||||||
{
|
{
|
||||||
const bool show = text != "N/A";
|
const bool show = text != "N/A";
|
||||||
if (show)
|
if (show)
|
||||||
|
@ -1210,7 +1218,7 @@ void Sidebar::show_sliced_info_sizer(const bool show)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there is a wipe tower, insert number of toolchanges info into the array:
|
// if there is a wipe tower, insert number of toolchanges info into the array:
|
||||||
p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, is_wipe_tower ? wxString::Format("%.d", p->plater->fff_print().wipe_tower_data().number_of_toolchanges) : "N/A");
|
p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, is_wipe_tower ? wxString::Format("%.d", ps.total_toolchanges) : "N/A");
|
||||||
|
|
||||||
// Hide non-FFF sliced info parameters
|
// Hide non-FFF sliced info parameters
|
||||||
p->sliced_info->SetTextAndShow(siMateril_unit, "N/A");
|
p->sliced_info->SetTextAndShow(siMateril_unit, "N/A");
|
||||||
|
@ -1363,6 +1371,9 @@ struct Plater::priv
|
||||||
Slic3r::Model model;
|
Slic3r::Model model;
|
||||||
PrinterTechnology printer_technology = ptFFF;
|
PrinterTechnology printer_technology = ptFFF;
|
||||||
Slic3r::GCodePreviewData gcode_preview_data;
|
Slic3r::GCodePreviewData gcode_preview_data;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
std::vector<Slic3r::ThumbnailData> thumbnail_data;
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
// GUI elements
|
// GUI elements
|
||||||
wxSizer* panel_sizer{ nullptr };
|
wxSizer* panel_sizer{ nullptr };
|
||||||
|
@ -1918,6 +1929,10 @@ struct Plater::priv
|
||||||
bool can_mirror() const;
|
bool can_mirror() const;
|
||||||
bool can_reload_from_disk() const;
|
bool can_reload_from_disk() const;
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
void msw_rescale_object_menu();
|
void msw_rescale_object_menu();
|
||||||
|
|
||||||
// returns the path to project file with the given extension (none if extension == wxEmptyString)
|
// returns the path to project file with the given extension (none if extension == wxEmptyString)
|
||||||
|
@ -1985,6 +2000,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||||
background_process.set_fff_print(&fff_print);
|
background_process.set_fff_print(&fff_print);
|
||||||
background_process.set_sla_print(&sla_print);
|
background_process.set_sla_print(&sla_print);
|
||||||
background_process.set_gcode_preview_data(&gcode_preview_data);
|
background_process.set_gcode_preview_data(&gcode_preview_data);
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
background_process.set_thumbnail_data(&thumbnail_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED);
|
background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED);
|
||||||
background_process.set_finished_event(EVT_PROCESS_COMPLETED);
|
background_process.set_finished_event(EVT_PROCESS_COMPLETED);
|
||||||
// Default printer technology for default config.
|
// Default printer technology for default config.
|
||||||
|
@ -3033,6 +3051,34 @@ bool Plater::priv::restart_background_process(unsigned int state)
|
||||||
( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) ||
|
( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) ||
|
||||||
(state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) != 0 ||
|
(state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) != 0 ||
|
||||||
(state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) {
|
(state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) {
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
if (((state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) == 0) &&
|
||||||
|
(this->background_process.state() != BackgroundSlicingProcess::STATE_RUNNING))
|
||||||
|
{
|
||||||
|
// update thumbnail data
|
||||||
|
if (this->printer_technology == ptFFF)
|
||||||
|
{
|
||||||
|
// for ptFFF we need to generate the thumbnails before the export of gcode starts
|
||||||
|
this->thumbnail_data.clear();
|
||||||
|
for (const std::pair<unsigned int, unsigned int>& size : THUMBNAIL_SIZE_FFF)
|
||||||
|
{
|
||||||
|
this->thumbnail_data.push_back(ThumbnailData());
|
||||||
|
generate_thumbnail(this->thumbnail_data.back(), size.first, size.second, true, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->printer_technology == ptSLA)
|
||||||
|
{
|
||||||
|
// for ptSLA generate thumbnails without supports and pad (not yet calculated)
|
||||||
|
// to render also supports and pad see on_slicing_update()
|
||||||
|
this->thumbnail_data.clear();
|
||||||
|
for (const std::pair<unsigned int, unsigned int>& size : THUMBNAIL_SIZE_SLA)
|
||||||
|
{
|
||||||
|
this->thumbnail_data.push_back(ThumbnailData());
|
||||||
|
generate_thumbnail(this->thumbnail_data.back(), size.first, size.second, true, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
// The print is valid and it can be started.
|
// The print is valid and it can be started.
|
||||||
if (this->background_process.start()) {
|
if (this->background_process.start()) {
|
||||||
this->statusbar()->set_cancel_callback([this]() {
|
this->statusbar()->set_cancel_callback([this]() {
|
||||||
|
@ -3372,6 +3418,23 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
||||||
} else if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) {
|
} else if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) {
|
||||||
// Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways.
|
// Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways.
|
||||||
this->preview->reload_print();
|
this->preview->reload_print();
|
||||||
|
|
||||||
|
// uncomment the following lines if you want to render into the thumbnail also supports and pad for SLA printer
|
||||||
|
/*
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
// update thumbnail data
|
||||||
|
// for ptSLA generate the thumbnail after supports and pad have been calculated to have them rendered
|
||||||
|
if ((this->printer_technology == ptSLA) && (evt.status.percent == -3))
|
||||||
|
{
|
||||||
|
this->thumbnail_data.clear();
|
||||||
|
for (const std::pair<unsigned int, unsigned int>& size : THUMBNAIL_SIZE_SLA)
|
||||||
|
{
|
||||||
|
this->thumbnail_data.push_back(ThumbnailData());
|
||||||
|
generate_thumbnail(this->thumbnail_data.back(), size.first, size.second, true, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3597,6 +3660,13 @@ bool Plater::priv::init_object_menu()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool transparent_background)
|
||||||
|
{
|
||||||
|
view3D->get_canvas3d()->render_thumbnail(data, w, h, printable_only, parts_only, transparent_background);
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
|
||||||
void Plater::priv::msw_rescale_object_menu()
|
void Plater::priv::msw_rescale_object_menu()
|
||||||
{
|
{
|
||||||
for (MenuWithSeparators* menu : { &object_menu, &sla_object_menu, &part_menu, &default_menu })
|
for (MenuWithSeparators* menu : { &object_menu, &sla_object_menu, &part_menu, &default_menu })
|
||||||
|
@ -4635,7 +4705,13 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
|
||||||
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure();
|
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure();
|
||||||
const std::string path_u8 = into_u8(path);
|
const std::string path_u8 = into_u8(path);
|
||||||
wxBusyCursor wait;
|
wxBusyCursor wait;
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
ThumbnailData thumbnail_data;
|
||||||
|
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true);
|
||||||
|
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, &thumbnail_data)) {
|
||||||
|
#else
|
||||||
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr)) {
|
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr)) {
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||||
// Success
|
// Success
|
||||||
p->statusbar()->set_status_text(wxString::Format(_(L("3MF file exported to %s")), path));
|
p->statusbar()->set_status_text(wxString::Format(_(L("3MF file exported to %s")), path));
|
||||||
p->set_project_filename(path);
|
p->set_project_filename(path);
|
||||||
|
@ -4799,7 +4875,7 @@ bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** o
|
||||||
const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack().snapshots();
|
const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack().snapshots();
|
||||||
const int idx_in_ss_stack = p->get_active_snapshot_index() + (is_undo ? -(++idx) : idx);
|
const int idx_in_ss_stack = p->get_active_snapshot_index() + (is_undo ? -(++idx) : idx);
|
||||||
|
|
||||||
if (0 < idx_in_ss_stack && idx_in_ss_stack < ss_stack.size() - 1) {
|
if (0 < idx_in_ss_stack && (size_t)idx_in_ss_stack < ss_stack.size() - 1) {
|
||||||
*out_text = ss_stack[idx_in_ss_stack].name.c_str();
|
*out_text = ss_stack[idx_in_ss_stack].name.c_str();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -4812,7 +4888,7 @@ void Plater::undo_redo_topmost_string_getter(const bool is_undo, std::string& ou
|
||||||
const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack().snapshots();
|
const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack().snapshots();
|
||||||
const int idx_in_ss_stack = p->get_active_snapshot_index() + (is_undo ? -1 : 0);
|
const int idx_in_ss_stack = p->get_active_snapshot_index() + (is_undo ? -1 : 0);
|
||||||
|
|
||||||
if (0 < idx_in_ss_stack && idx_in_ss_stack < ss_stack.size() - 1) {
|
if (0 < idx_in_ss_stack && (size_t)idx_in_ss_stack < ss_stack.size() - 1) {
|
||||||
out_text = ss_stack[idx_in_ss_stack].name;
|
out_text = ss_stack[idx_in_ss_stack].name;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1020,7 +1020,7 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
|
||||||
node_parent->GetChildren().Remove(node);
|
node_parent->GetChildren().Remove(node);
|
||||||
|
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
if(id == node_parent->GetChildCount()) id--;
|
if (size_t(id) == node_parent->GetChildCount()) id--;
|
||||||
ret_item = wxDataViewItem(node_parent->GetChildren().Item(id));
|
ret_item = wxDataViewItem(node_parent->GetChildren().Item(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
219
src/slic3r/Utils/FlashAir.cpp
Normal file
219
src/slic3r/Utils/FlashAir.cpp
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
#include "FlashAir.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ctime>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
|
#include <wx/frame.h>
|
||||||
|
#include <wx/event.h>
|
||||||
|
#include <wx/progdlg.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/stattext.h>
|
||||||
|
#include <wx/textctrl.h>
|
||||||
|
#include <wx/checkbox.h>
|
||||||
|
|
||||||
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
|
#include "slic3r/GUI/MsgDialog.hpp"
|
||||||
|
#include "Http.hpp"
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
FlashAir::FlashAir(DynamicPrintConfig *config) :
|
||||||
|
host(config->opt_string("print_host"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
FlashAir::~FlashAir() {}
|
||||||
|
|
||||||
|
const char* FlashAir::get_name() const { return "FlashAir"; }
|
||||||
|
|
||||||
|
bool FlashAir::test(wxString &msg) const
|
||||||
|
{
|
||||||
|
// Since the request is performed synchronously here,
|
||||||
|
// it is ok to refer to `msg` from within the closure
|
||||||
|
|
||||||
|
const char *name = get_name();
|
||||||
|
|
||||||
|
bool res = false;
|
||||||
|
auto url = make_url("command.cgi", "op", "118");
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get upload enabled at: %2%") % name % url;
|
||||||
|
|
||||||
|
auto http = Http::get(std::move(url));
|
||||||
|
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting upload enabled: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||||
|
res = false;
|
||||||
|
msg = format_error(body, error, status);
|
||||||
|
})
|
||||||
|
.on_complete([&, this](std::string body, unsigned) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got upload enabled: %2%") % name % body;
|
||||||
|
|
||||||
|
res = boost::starts_with(body, "1");
|
||||||
|
if (! res) {
|
||||||
|
msg = _(L("Upload not enabled on FlashAir card."));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.perform_sync();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString FlashAir::get_test_ok_msg () const
|
||||||
|
{
|
||||||
|
return _(L("Connection to FlashAir works correctly and upload is enabled."));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString FlashAir::get_test_failed_msg (wxString &msg) const
|
||||||
|
{
|
||||||
|
return wxString::Format("%s: %s", _(L("Could not connect to FlashAir")), msg, _(L("Note: FlashAir with firmware 2.00.02 or newer and activated upload function is required.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlashAir::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const
|
||||||
|
{
|
||||||
|
const char *name = get_name();
|
||||||
|
|
||||||
|
const auto upload_filename = upload_data.upload_path.filename();
|
||||||
|
const auto upload_parent_path = upload_data.upload_path.parent_path();
|
||||||
|
|
||||||
|
wxString test_msg;
|
||||||
|
if (! test(test_msg)) {
|
||||||
|
error_fn(std::move(test_msg));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool res = false;
|
||||||
|
|
||||||
|
auto urlPrepare = make_url("upload.cgi", "WRITEPROTECT=ON&FTIME", timestamp_str());
|
||||||
|
auto urlUpload = make_url("upload.cgi");
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3% / %4%, filename: %5%")
|
||||||
|
% name
|
||||||
|
% upload_data.source_path
|
||||||
|
% urlPrepare
|
||||||
|
% urlUpload
|
||||||
|
% upload_filename.string();
|
||||||
|
|
||||||
|
// set filetime for upload and make card writeprotect to prevent filesystem damage
|
||||||
|
auto httpPrepare = Http::get(std::move(urlPrepare));
|
||||||
|
httpPrepare.on_error([&](std::string body, std::string error, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error prepareing upload: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||||
|
error_fn(format_error(body, error, status));
|
||||||
|
res = false;
|
||||||
|
})
|
||||||
|
.on_complete([&, this](std::string body, unsigned) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got prepare result: %2%") % name % body;
|
||||||
|
res = boost::icontains(body, "SUCCESS");
|
||||||
|
if (! res) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name;
|
||||||
|
error_fn(format_error(body, L("Unknown error occured"), 0));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.perform_sync();
|
||||||
|
|
||||||
|
if(! res ) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start file upload
|
||||||
|
auto http = Http::post(std::move(urlUpload));
|
||||||
|
http.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
||||||
|
.on_complete([&](std::string body, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
||||||
|
res = boost::icontains(body, "SUCCESS");
|
||||||
|
if (! res) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name;
|
||||||
|
error_fn(format_error(body, L("Unknown error occured"), 0));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||||
|
error_fn(format_error(body, error, status));
|
||||||
|
res = false;
|
||||||
|
})
|
||||||
|
.on_progress([&](Http::Progress progress, bool &cancel) {
|
||||||
|
prorgess_fn(std::move(progress), cancel);
|
||||||
|
if (cancel) {
|
||||||
|
// Upload was canceled
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Upload canceled") % name;
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.perform_sync();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlashAir::has_auto_discovery() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlashAir::can_test() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlashAir::can_start_print() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FlashAir::timestamp_str() const
|
||||||
|
{
|
||||||
|
auto t = std::time(nullptr);
|
||||||
|
auto tm = *std::localtime(&t);
|
||||||
|
|
||||||
|
const char *name = get_name();
|
||||||
|
|
||||||
|
unsigned long fattime = ((tm.tm_year - 80) << 25) |
|
||||||
|
((tm.tm_mon + 1) << 21) |
|
||||||
|
(tm.tm_mday << 16) |
|
||||||
|
(tm.tm_hour << 11) |
|
||||||
|
(tm.tm_min << 5) |
|
||||||
|
(tm.tm_sec >> 1);
|
||||||
|
|
||||||
|
return (boost::format("%1$#x") % fattime).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FlashAir::make_url(const std::string &path) const
|
||||||
|
{
|
||||||
|
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||||
|
if (host.back() == '/') {
|
||||||
|
return (boost::format("%1%%2%") % host % path).str();
|
||||||
|
} else {
|
||||||
|
return (boost::format("%1%/%2%") % host % path).str();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (host.back() == '/') {
|
||||||
|
return (boost::format("http://%1%%2%") % host % path).str();
|
||||||
|
} else {
|
||||||
|
return (boost::format("http://%1%/%2%") % host % path).str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FlashAir::make_url(const std::string &path, const std::string &arg, const std::string &val) const
|
||||||
|
{
|
||||||
|
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||||
|
if (host.back() == '/') {
|
||||||
|
return (boost::format("%1%%2%?%3%=%4%") % host % path % arg % val).str();
|
||||||
|
} else {
|
||||||
|
return (boost::format("%1%/%2%?%3%=%4%") % host % path % arg % val).str();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (host.back() == '/') {
|
||||||
|
return (boost::format("http://%1%%2%?%3%=%4%") % host % path % arg % val).str();
|
||||||
|
} else {
|
||||||
|
return (boost::format("http://%1%/%2%?%3%=%4%") % host % path % arg % val).str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
src/slic3r/Utils/FlashAir.hpp
Normal file
44
src/slic3r/Utils/FlashAir.hpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef slic3r_FlashAir_hpp_
|
||||||
|
#define slic3r_FlashAir_hpp_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
#include "PrintHost.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
|
||||||
|
class DynamicPrintConfig;
|
||||||
|
class Http;
|
||||||
|
|
||||||
|
class FlashAir : public PrintHost
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FlashAir(DynamicPrintConfig *config);
|
||||||
|
virtual ~FlashAir();
|
||||||
|
|
||||||
|
virtual const char* get_name() const;
|
||||||
|
|
||||||
|
virtual bool test(wxString &curl_msg) const;
|
||||||
|
virtual wxString get_test_ok_msg () const;
|
||||||
|
virtual wxString get_test_failed_msg (wxString &msg) const;
|
||||||
|
virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const;
|
||||||
|
virtual bool has_auto_discovery() const;
|
||||||
|
virtual bool can_test() const;
|
||||||
|
virtual bool can_start_print() const;
|
||||||
|
virtual std::string get_host() const { return host; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string host;
|
||||||
|
|
||||||
|
std::string timestamp_str() const;
|
||||||
|
std::string make_url(const std::string &path) const;
|
||||||
|
std::string make_url(const std::string &path, const std::string &arg, const std::string &val) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -14,6 +14,7 @@
|
||||||
#include "libslic3r/Channel.hpp"
|
#include "libslic3r/Channel.hpp"
|
||||||
#include "OctoPrint.hpp"
|
#include "OctoPrint.hpp"
|
||||||
#include "Duet.hpp"
|
#include "Duet.hpp"
|
||||||
|
#include "FlashAir.hpp"
|
||||||
#include "../GUI/PrintHostDialogs.hpp"
|
#include "../GUI/PrintHostDialogs.hpp"
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
|
@ -43,6 +44,7 @@ PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config)
|
||||||
switch (host_type) {
|
switch (host_type) {
|
||||||
case htOctoPrint: return new OctoPrint(config);
|
case htOctoPrint: return new OctoPrint(config);
|
||||||
case htDuet: return new Duet(config);
|
case htDuet: return new Duet(config);
|
||||||
|
case htFlashAir: return new FlashAir(config);
|
||||||
default: return nullptr;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
89
t/clipper.t
89
t/clipper.t
|
@ -1,89 +0,0 @@
|
||||||
use Test::More;
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
plan tests => 6;
|
|
||||||
|
|
||||||
BEGIN {
|
|
||||||
use FindBin;
|
|
||||||
use lib "$FindBin::Bin/../lib";
|
|
||||||
use local::lib "$FindBin::Bin/../local-lib";
|
|
||||||
}
|
|
||||||
|
|
||||||
use List::Util qw(sum);
|
|
||||||
use Slic3r;
|
|
||||||
use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex diff_pl);
|
|
||||||
|
|
||||||
{
|
|
||||||
my $square = [ # ccw
|
|
||||||
[10, 10],
|
|
||||||
[20, 10],
|
|
||||||
[20, 20],
|
|
||||||
[10, 20],
|
|
||||||
];
|
|
||||||
my $hole_in_square = [ # cw
|
|
||||||
[14, 14],
|
|
||||||
[14, 16],
|
|
||||||
[16, 16],
|
|
||||||
[16, 14],
|
|
||||||
];
|
|
||||||
my $square2 = [ # ccw
|
|
||||||
[5, 12],
|
|
||||||
[25, 12],
|
|
||||||
[25, 18],
|
|
||||||
[5, 18],
|
|
||||||
];
|
|
||||||
my $intersection = intersection_ex([ $square, $hole_in_square ], [ $square2 ]);
|
|
||||||
|
|
||||||
is sum(map $_->area, @$intersection), Slic3r::ExPolygon->new(
|
|
||||||
[
|
|
||||||
[20, 18],
|
|
||||||
[10, 18],
|
|
||||||
[10, 12],
|
|
||||||
[20, 12],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[14, 16],
|
|
||||||
[16, 16],
|
|
||||||
[16, 14],
|
|
||||||
[14, 14],
|
|
||||||
],
|
|
||||||
)->area, 'hole is preserved after intersection';
|
|
||||||
}
|
|
||||||
|
|
||||||
#==========================================================
|
|
||||||
|
|
||||||
{
|
|
||||||
my $contour1 = [ [0,0], [40,0], [40,40], [0,40] ]; # ccw
|
|
||||||
my $contour2 = [ [10,10], [30,10], [30,30], [10,30] ]; # ccw
|
|
||||||
my $hole = [ [15,15], [15,25], [25,25], [25,15] ]; # cw
|
|
||||||
|
|
||||||
my $union = union_ex([ $contour1, $contour2, $hole ]);
|
|
||||||
|
|
||||||
is_deeply [ map $_->pp, @$union ], [[ [ [40,40], [0,40], [0,0], [40,0] ] ]],
|
|
||||||
'union of two ccw and one cw is a contour with no holes';
|
|
||||||
|
|
||||||
my $diff = diff_ex([ $contour1, $contour2 ], [ $hole ]);
|
|
||||||
is sum(map $_->area, @$diff),
|
|
||||||
Slic3r::ExPolygon->new([ [40,40], [0,40], [0,0], [40,0] ], [ [15,25], [25,25], [25,15], [15,15] ])->area,
|
|
||||||
'difference of a cw from two ccw is a contour with one hole';
|
|
||||||
}
|
|
||||||
|
|
||||||
#==========================================================
|
|
||||||
|
|
||||||
{
|
|
||||||
my $square = Slic3r::Polygon->new_scale( # ccw
|
|
||||||
[10, 10],
|
|
||||||
[20, 10],
|
|
||||||
[20, 20],
|
|
||||||
[10, 20],
|
|
||||||
);
|
|
||||||
my $square_pl = $square->split_at_first_point;
|
|
||||||
|
|
||||||
my $res = diff_pl([$square_pl], []);
|
|
||||||
is scalar(@$res), 1, 'no-op diff_pl returns the right number of polylines';
|
|
||||||
isa_ok $res->[0], 'Slic3r::Polyline', 'no-op diff_pl result';
|
|
||||||
is scalar(@{$res->[0]}), scalar(@$square_pl), 'no-op diff_pl returns the unmodified input polyline';
|
|
||||||
}
|
|
||||||
|
|
||||||
__END__
|
|
|
@ -10,6 +10,8 @@ target_include_directories(Catch2 INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
add_library(Catch2::Catch2 ALIAS Catch2)
|
add_library(Catch2::Catch2 ALIAS Catch2)
|
||||||
include(Catch)
|
include(Catch)
|
||||||
|
|
||||||
|
set(CATCH_EXTRA_ARGS "" CACHE STRING "Extra arguments for catch2 test suites.")
|
||||||
|
|
||||||
add_library(test_common INTERFACE)
|
add_library(test_common INTERFACE)
|
||||||
target_compile_definitions(test_common INTERFACE TEST_DATA_DIR=R"\(${TEST_DATA_DIR}\)" CATCH_CONFIG_FAST_COMPILE)
|
target_compile_definitions(test_common INTERFACE TEST_DATA_DIR=R"\(${TEST_DATA_DIR}\)" CATCH_CONFIG_FAST_COMPILE)
|
||||||
target_link_libraries(test_common INTERFACE Catch2::Catch2)
|
target_link_libraries(test_common INTERFACE Catch2::Catch2)
|
||||||
|
@ -25,3 +27,4 @@ add_subdirectory(libslic3r)
|
||||||
add_subdirectory(timeutils)
|
add_subdirectory(timeutils)
|
||||||
add_subdirectory(fff_print)
|
add_subdirectory(fff_print)
|
||||||
add_subdirectory(sla_print)
|
add_subdirectory(sla_print)
|
||||||
|
# add_subdirectory(example)
|
||||||
|
|
54
tests/catch_main.hpp
Normal file
54
tests/catch_main.hpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef CATCH_MAIN
|
||||||
|
#define CATCH_MAIN
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_EXTERNAL_INTERFACES
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#define CATCH_CONFIG_DEFAULT_REPORTER "verboseconsole"
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
struct VerboseConsoleReporter : public ConsoleReporter {
|
||||||
|
double duration = 0.;
|
||||||
|
using ConsoleReporter::ConsoleReporter;
|
||||||
|
|
||||||
|
void testCaseStarting(TestCaseInfo const& _testInfo) override
|
||||||
|
{
|
||||||
|
Colour::use(Colour::Cyan);
|
||||||
|
stream << "Testing ";
|
||||||
|
Colour::use(Colour::None);
|
||||||
|
stream << _testInfo.name << std::endl;
|
||||||
|
ConsoleReporter::testCaseStarting(_testInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sectionStarting(const SectionInfo &_sectionInfo) override
|
||||||
|
{
|
||||||
|
if (_sectionInfo.name != currentTestCaseInfo->name)
|
||||||
|
stream << _sectionInfo.name << std::endl;
|
||||||
|
|
||||||
|
ConsoleReporter::sectionStarting(_sectionInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sectionEnded(const SectionStats &_sectionStats) override {
|
||||||
|
duration += _sectionStats.durationInSeconds;
|
||||||
|
ConsoleReporter::sectionEnded(_sectionStats);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testCaseEnded(TestCaseStats const& stats) override
|
||||||
|
{
|
||||||
|
if (stats.totals.assertions.allOk()) {
|
||||||
|
Colour::use(Colour::BrightGreen);
|
||||||
|
stream << "Passed";
|
||||||
|
Colour::use(Colour::None);
|
||||||
|
stream << " in " << duration << " [seconds]\n" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
duration = 0.;
|
||||||
|
ConsoleReporter::testCaseEnded(stats);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CATCH_REGISTER_REPORTER( "verboseconsole", VerboseConsoleReporter )
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#endif // CATCH_MAIN
|
|
@ -1,8 +1,6 @@
|
||||||
get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
||||||
add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp)
|
add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp)
|
||||||
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r
|
target_link_libraries(${_TEST_NAME}_tests test_common)
|
||||||
#${Boost_LIBRARIES} ${TBB_LIBRARIES} ${Boost_LIBRARIES}
|
|
||||||
)
|
|
||||||
|
|
||||||
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
||||||
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests "--durations yes")
|
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests ${CATCH_EXTRA_ARGS})
|
|
@ -1,5 +1,5 @@
|
||||||
#define CATCH_CONFIG_MAIN
|
#define CATCH_CONFIG_MAIN
|
||||||
#include <catch2/catch.hpp>
|
#include <catch_main.hpp>
|
||||||
|
|
||||||
TEST_CASE("Is example succesful", "[example]") {
|
TEST_CASE("Is example succesful", "[example]") {
|
||||||
REQUIRE(true);
|
REQUIRE(true);
|
||||||
|
|
|
@ -6,6 +6,7 @@ add_executable(${_TEST_NAME}_tests
|
||||||
test_extrusion_entity.cpp
|
test_extrusion_entity.cpp
|
||||||
test_fill.cpp
|
test_fill.cpp
|
||||||
test_flow.cpp
|
test_flow.cpp
|
||||||
|
test_gcode.cpp
|
||||||
test_gcodewriter.cpp
|
test_gcodewriter.cpp
|
||||||
test_model.cpp
|
test_model.cpp
|
||||||
test_print.cpp
|
test_print.cpp
|
||||||
|
@ -19,4 +20,4 @@ target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
|
||||||
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
||||||
|
|
||||||
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
||||||
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests "--durations yes")
|
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests ${CATCH_EXTRA_ARGS})
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#define CATCH_CONFIG_MAIN
|
#include <catch_main.hpp>
|
||||||
#include <catch2/catch.hpp>
|
|
||||||
|
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
|
@ -138,6 +138,8 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") {
|
||||||
REQUIRE(paths.size() == 1);
|
REQUIRE(paths.size() == 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 // Disabled temporarily due to precission issues on the Mac VM
|
||||||
SECTION("Solid surface fill") {
|
SECTION("Solid surface fill") {
|
||||||
Slic3r::Points points {
|
Slic3r::Points points {
|
||||||
Point::new_scale(6883102, 9598327.01296997),
|
Point::new_scale(6883102, 9598327.01296997),
|
||||||
|
@ -154,6 +156,8 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") {
|
||||||
REQUIRE(test_if_solid_surface_filled(expolygon, 0.55) == true);
|
REQUIRE(test_if_solid_surface_filled(expolygon, 0.55) == true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SECTION("Solid surface fill") {
|
SECTION("Solid surface fill") {
|
||||||
Slic3r::Points points {
|
Slic3r::Points points {
|
||||||
Slic3r::Point(59515297,5422499),Slic3r::Point(59531249,5578697),Slic3r::Point(59695801,6123186),
|
Slic3r::Point(59515297,5422499),Slic3r::Point(59531249,5578697),Slic3r::Point(59695801,6123186),
|
||||||
|
|
|
@ -95,7 +95,6 @@ SCENARIO(" Bridge flow specifics.", "[Flow]") {
|
||||||
SCENARIO("Flow: Flow math for non-bridges", "[Flow]") {
|
SCENARIO("Flow: Flow math for non-bridges", "[Flow]") {
|
||||||
GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") {
|
GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") {
|
||||||
ConfigOptionFloatOrPercent width(1.0, false);
|
ConfigOptionFloatOrPercent width(1.0, false);
|
||||||
float spacing = 0.4f;
|
|
||||||
float nozzle_diameter = 0.4f;
|
float nozzle_diameter = 0.4f;
|
||||||
float bridge_flow = 0.f;
|
float bridge_flow = 0.f;
|
||||||
float layer_height = 0.5f;
|
float layer_height = 0.5f;
|
||||||
|
@ -119,7 +118,6 @@ SCENARIO("Flow: Flow math for non-bridges", "[Flow]") {
|
||||||
}
|
}
|
||||||
/// Check the min/max
|
/// Check the min/max
|
||||||
GIVEN("Nozzle Diameter of 0.25") {
|
GIVEN("Nozzle Diameter of 0.25") {
|
||||||
float spacing = 0.4f;
|
|
||||||
float nozzle_diameter = 0.25f;
|
float nozzle_diameter = 0.25f;
|
||||||
float bridge_flow = 0.f;
|
float bridge_flow = 0.f;
|
||||||
float layer_height = 0.5f;
|
float layer_height = 0.5f;
|
||||||
|
@ -161,7 +159,6 @@ SCENARIO("Flow: Flow math for non-bridges", "[Flow]") {
|
||||||
SCENARIO("Flow: Flow math for bridges", "[Flow]") {
|
SCENARIO("Flow: Flow math for bridges", "[Flow]") {
|
||||||
GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") {
|
GIVEN("Nozzle Diameter of 0.4, a desired width of 1mm and layer height of 0.5") {
|
||||||
auto width = ConfigOptionFloatOrPercent(1.0, false);
|
auto width = ConfigOptionFloatOrPercent(1.0, false);
|
||||||
float spacing = 0.4f;
|
|
||||||
float nozzle_diameter = 0.4f;
|
float nozzle_diameter = 0.4f;
|
||||||
float bridge_flow = 1.0f;
|
float bridge_flow = 1.0f;
|
||||||
float layer_height = 0.5f;
|
float layer_height = 0.5f;
|
||||||
|
|
22
tests/fff_print/test_gcode.cpp
Normal file
22
tests/fff_print/test_gcode.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "libslic3r/GCode.hpp"
|
||||||
|
|
||||||
|
using namespace Slic3r;
|
||||||
|
|
||||||
|
SCENARIO("Origin manipulation", "[GCode]") {
|
||||||
|
Slic3r::GCode gcodegen;
|
||||||
|
WHEN("set_origin to (10,0)") {
|
||||||
|
gcodegen.set_origin(Vec2d(10,0));
|
||||||
|
REQUIRE(gcodegen.origin() == Vec2d(10, 0));
|
||||||
|
}
|
||||||
|
WHEN("set_origin to (10,0) and translate by (5, 5)") {
|
||||||
|
gcodegen.set_origin(Vec2d(10,0));
|
||||||
|
gcodegen.set_origin(gcodegen.origin() + Vec2d(5, 5));
|
||||||
|
THEN("origin returns reference to point") {
|
||||||
|
REQUIRE(gcodegen.origin() == Vec2d(15,5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,8 +14,8 @@ using namespace Slic3r;
|
||||||
/// Helper method to find the tool used for the brim (always the first extrusion)
|
/// Helper method to find the tool used for the brim (always the first extrusion)
|
||||||
static int get_brim_tool(const std::string &gcode)
|
static int get_brim_tool(const std::string &gcode)
|
||||||
{
|
{
|
||||||
int brim_tool = -1;
|
int brim_tool = -1;
|
||||||
int tool = -1;
|
int tool = -1;
|
||||||
GCodeReader parser;
|
GCodeReader parser;
|
||||||
parser.parse_buffer(gcode, [&tool, &brim_tool] (Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line)
|
parser.parse_buffer(gcode, [&tool, &brim_tool] (Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ static int get_brim_tool(const std::string &gcode)
|
||||||
return brim_tool;
|
return brim_tool;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Skirt height is honored") {
|
TEST_CASE("Skirt height is honored", "[Skirt]") {
|
||||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||||
config.set_deserialize({
|
config.set_deserialize({
|
||||||
{ "skirts", 1 },
|
{ "skirts", 1 },
|
||||||
|
@ -60,7 +60,7 @@ TEST_CASE("Skirt height is honored") {
|
||||||
REQUIRE(layers_with_skirt.size() == (size_t)config.opt_int("skirt_height"));
|
REQUIRE(layers_with_skirt.size() == (size_t)config.opt_int("skirt_height"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") {
|
SCENARIO("Original Slic3r Skirt/Brim tests", "[SkirtBrim]") {
|
||||||
GIVEN("A default configuration") {
|
GIVEN("A default configuration") {
|
||||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||||
config.set_num_extruders(4);
|
config.set_num_extruders(4);
|
||||||
|
@ -73,7 +73,8 @@ SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") {
|
||||||
{ "first_layer_speed", "100%" },
|
{ "first_layer_speed", "100%" },
|
||||||
// remove noise from top/solid layers
|
// remove noise from top/solid layers
|
||||||
{ "top_solid_layers", 0 },
|
{ "top_solid_layers", 0 },
|
||||||
{ "bottom_solid_layers", 1 }
|
{ "bottom_solid_layers", 1 },
|
||||||
|
{ "start_gcode", "T[initial_tool]\n" }
|
||||||
});
|
});
|
||||||
|
|
||||||
WHEN("Brim width is set to 5") {
|
WHEN("Brim width is set to 5") {
|
||||||
|
@ -118,31 +119,39 @@ SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// This is a real error! One shall print the brim with the external perimeter extruder!
|
||||||
WHEN("Perimeter extruder = 2 and support extruders = 3") {
|
WHEN("Perimeter extruder = 2 and support extruders = 3") {
|
||||||
THEN("Brim is printed with the extruder used for the perimeters of first object") {
|
THEN("Brim is printed with the extruder used for the perimeters of first object") {
|
||||||
std::string gcode = Slic3r::Test::slice({TestMesh::cube_20x20x20}, {
|
config.set_deserialize({
|
||||||
{ "skirts", 0 },
|
{ "skirts", 0 },
|
||||||
{ "brim_width", 5 },
|
{ "brim_width", 5 },
|
||||||
{ "perimeter_extruder", 2 },
|
{ "perimeter_extruder", 2 },
|
||||||
{ "support_material_extruder", 3 }
|
{ "support_material_extruder", 3 },
|
||||||
});
|
{ "infill_extruder", 4 }
|
||||||
|
});
|
||||||
|
std::string gcode = Slic3r::Test::slice({TestMesh::cube_20x20x20}, config);
|
||||||
int tool = get_brim_tool(gcode);
|
int tool = get_brim_tool(gcode);
|
||||||
REQUIRE(tool == config.opt_int("perimeter_extruder") - 1);
|
REQUIRE(tool == config.opt_int("perimeter_extruder") - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WHEN("Perimeter extruder = 2, support extruders = 3, raft is enabled") {
|
WHEN("Perimeter extruder = 2, support extruders = 3, raft is enabled") {
|
||||||
THEN("brim is printed with same extruder as skirt") {
|
THEN("brim is printed with same extruder as skirt") {
|
||||||
std::string gcode = Slic3r::Test::slice({TestMesh::cube_20x20x20}, {
|
config.set_deserialize({
|
||||||
{ "skirts", 0 },
|
{ "skirts", 0 },
|
||||||
{ "brim_width", 5 },
|
{ "brim_width", 5 },
|
||||||
{ "perimeter_extruder", 2 },
|
{ "perimeter_extruder", 2 },
|
||||||
{ "support_material_extruder", 3 },
|
{ "support_material_extruder", 3 },
|
||||||
{ "raft_layers", 1 }
|
{ "infill_extruder", 4 },
|
||||||
});
|
{ "raft_layers", 1 }
|
||||||
|
});
|
||||||
|
std::string gcode = Slic3r::Test::slice({TestMesh::cube_20x20x20}, config);
|
||||||
int tool = get_brim_tool(gcode);
|
int tool = get_brim_tool(gcode);
|
||||||
REQUIRE(tool == config.opt_int("support_material_extruder") - 1);
|
REQUIRE(tool == config.opt_int("support_material_extruder") - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
WHEN("brim width to 1 with layer_width of 0.5") {
|
WHEN("brim width to 1 with layer_width of 0.5") {
|
||||||
config.set_deserialize({
|
config.set_deserialize({
|
||||||
{ "skirts", 0 },
|
{ "skirts", 0 },
|
||||||
|
@ -200,6 +209,7 @@ SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") {
|
||||||
{ "infill_extruder", 3 }, // ensure that a tool command gets emitted.
|
{ "infill_extruder", 3 }, // ensure that a tool command gets emitted.
|
||||||
{ "cooling", false }, // to prevent speeds to be altered
|
{ "cooling", false }, // to prevent speeds to be altered
|
||||||
{ "first_layer_speed", "100%" }, // to prevent speeds to be altered
|
{ "first_layer_speed", "100%" }, // to prevent speeds to be altered
|
||||||
|
{ "start_gcode", "T[initial_tool]\n" }
|
||||||
});
|
});
|
||||||
|
|
||||||
THEN("overhang generates?") {
|
THEN("overhang generates?") {
|
||||||
|
@ -209,6 +219,8 @@ SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") {
|
||||||
|
|
||||||
// config.set("support_material", true); // to prevent speeds to be altered
|
// config.set("support_material", true); // to prevent speeds to be altered
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// This test is not finished.
|
||||||
THEN("skirt length is large enough to contain object with support") {
|
THEN("skirt length is large enough to contain object with support") {
|
||||||
CHECK(config.opt_bool("support_material")); // test is not valid if support material is off
|
CHECK(config.opt_bool("support_material")); // test is not valid if support material is off
|
||||||
std::string gcode = Slic3r::Test::slice({TestMesh::cube_20x20x20}, config);
|
std::string gcode = Slic3r::Test::slice({TestMesh::cube_20x20x20}, config);
|
||||||
|
@ -242,6 +254,8 @@ SCENARIO("Original Slic3r Skirt/Brim tests", "[!mayfail]") {
|
||||||
double hull_perimeter = unscale<double>(convex_hull.split_at_first_point().length());
|
double hull_perimeter = unscale<double>(convex_hull.split_at_first_point().length());
|
||||||
REQUIRE(skirt_length > hull_perimeter);
|
REQUIRE(skirt_length > hull_perimeter);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
WHEN("Large minimum skirt length is used.") {
|
WHEN("Large minimum skirt length is used.") {
|
||||||
config.set("min_skirt_length", 20);
|
config.set("min_skirt_length", 20);
|
||||||
|
|
|
@ -4,4 +4,4 @@ target_link_libraries(${_TEST_NAME}_tests test_common libnest2d )
|
||||||
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
||||||
|
|
||||||
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
||||||
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests "--durations yes")
|
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests ${CATCH_EXTRA_ARGS})
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#define CATCH_CONFIG_MAIN
|
#include <catch_main.hpp>
|
||||||
#include <catch2/catch.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
|
||||||
#include <libnest2d/libnest2d.hpp>
|
#include <libnest2d/libnest2d.hpp>
|
||||||
#include "printer_parts.hpp"
|
#include "printer_parts.hpp"
|
||||||
//#include <libnest2d/geometry_traits_nfp.hpp>
|
//#include <libnest2d/geometry_traits_nfp.hpp>
|
||||||
|
|
|
@ -2,7 +2,10 @@ get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
||||||
add_executable(${_TEST_NAME}_tests
|
add_executable(${_TEST_NAME}_tests
|
||||||
${_TEST_NAME}_tests.cpp
|
${_TEST_NAME}_tests.cpp
|
||||||
test_3mf.cpp
|
test_3mf.cpp
|
||||||
|
test_clipper_offset.cpp
|
||||||
|
test_clipper_utils.cpp
|
||||||
test_config.cpp
|
test_config.cpp
|
||||||
|
test_elephant_foot_compensation.cpp
|
||||||
test_geometry.cpp
|
test_geometry.cpp
|
||||||
test_polygon.cpp
|
test_polygon.cpp
|
||||||
test_stl.cpp
|
test_stl.cpp
|
||||||
|
@ -11,4 +14,4 @@ target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
|
||||||
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
|
||||||
|
|
||||||
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
# catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ")
|
||||||
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests "--durations yes")
|
add_test(${_TEST_NAME}_tests ${_TEST_NAME}_tests ${CATCH_EXTRA_ARGS})
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue