From 2fdded0835cb86f4b77f69eae020215cc5068740 Mon Sep 17 00:00:00 2001 From: Anthony Lombardi Date: Thu, 1 Jun 2023 12:25:00 -0400 Subject: [PATCH] ENH: Add Support for loading mesh files * Adds VTK as an optional depenency, if VTK_DIR is defined then Autoscoper will be compiled with mesh support --- CMakeLists.txt | 19 +++++++++++++ SuperBuild.cmake | 1 + libautoscoper/CMakeLists.txt | 29 +++++++++++++++++++ libautoscoper/src/Mesh.cpp | 27 ++++++++++++++++++ libautoscoper/src/Mesh.hpp | 17 ++++++++++++ libautoscoper/src/Trial.cpp | 54 ++++++++++++++++++++++++++++++++---- libautoscoper/src/Trial.hpp | 14 ++++++++-- 7 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 libautoscoper/src/Mesh.cpp create mode 100644 libautoscoper/src/Mesh.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f9ae70d9..9ec8aac9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,18 @@ if(NOT DEFINED Autoscoper_EXECUTABLE_LINK_FLAGS) endif() mark_as_superbuild(Autoscoper_EXECUTABLE_LINK_FLAGS:STRING) +#----------------------------------------------------------------------------- +# Collision Detection +#----------------------------------------------------------------------------- +if(DEFINED VTK_DIR AND EXISTS ${VTK_DIR}) + message(STATUS "Configuring with collision detection") + set(Autoscoper_COLLISION_DETECTION 1) +else() + message(STATUS "Configuring without collision detection. If you want to enable collision detection, please set VTK_DIR.") + set(Autoscoper_COLLISION_DETECTION 0) +endif() +mark_as_superbuild(Autoscoper_COLLISION_DETECTION) + #----------------------------------------------------------------------------- # Dependencies #----------------------------------------------------------------------------- @@ -252,6 +264,9 @@ if(Autoscoper_CONFIGURE_LAUCHER_SCRIPT) endif() endif() endforeach() + if(Autoscoper_COLLISION_DETECTION AND NOT VTK IN_LIST Autoscoper_DEPENDENCIES) # If collision is enabled but VTK was not built as part of the superbuild + list(APPEND _library_paths "${VTK_DIR}/bin/$/") + endif() string(REPLACE ";" "${_pathsep}" PATHS_CONFIG "${_library_paths}") @@ -283,8 +298,12 @@ if(Autoscoper_INSTALL_DEPENDENCIES) foreach(dependency IN LISTS Autoscoper_DEPENDENCIES) install(SCRIPT "${Autoscoper_SUPERBUILD_DIR}/${dependency}-build/cmake_install.cmake") endforeach() + if(Autoscoper_COLLISION_DETECTION) + install(SCRIPT "${VTK_DIR}/cmake_install.cmake") + endif() endif() + #----------------------------------------------------------------------------- # Sample Data #----------------------------------------------------------------------------- diff --git a/SuperBuild.cmake b/SuperBuild.cmake index 7c66bf49..ab75ebbc 100644 --- a/SuperBuild.cmake +++ b/SuperBuild.cmake @@ -34,6 +34,7 @@ ExternalProject_Add(${proj} -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED:BOOL=${CMAKE_CXX_STANDARD_REQUIRED} -DQt5_DIR:PATH=${Qt5_DIR} + -DVTK_DIR:PATH=${VTK_DIR} # Options -DAutoscoper_SUPERBUILD:BOOL=OFF -DAutoscoper_SUPERBUILD_DIR:PATH=${CMAKE_BINARY_DIR} diff --git a/libautoscoper/CMakeLists.txt b/libautoscoper/CMakeLists.txt index 17646061..00e6e26e 100644 --- a/libautoscoper/CMakeLists.txt +++ b/libautoscoper/CMakeLists.txt @@ -60,6 +60,15 @@ list(APPEND libautoscoper_SOURCES src/filesystem_compat.cpp ) +if(Autoscoper_COLLISION_DETECTION) # Add collision detection sources + list(APPEND libautoscoper_SOURCES + src/Mesh.cpp + ) + list(APPEND libautoscoper_HEADERS + src/Mesh.hpp + ) +endif() + if(Autoscoper_RENDERING_BACKEND STREQUAL "CUDA") # CUDA 10.2 supports C++ up to version 14 # See https://docs.nvidia.com/cuda/archive/10.2/cuda-c-programming-guide/index.html#c-cplusplus-language-support @@ -125,6 +134,26 @@ target_compile_definitions(libautoscoper PUBLIC Autoscoper_RENDERING_USE_${Autoscoper_RENDERING_BACKEND}_BACKEND ) +if (Autoscoper_COLLISION_DETECTION) # Add definitions for collision detection + target_compile_definitions(libautoscoper PUBLIC + Autoscoper_COLLISION_DETECTION + ) + find_package(VTK COMPONENTS + CommonCore + CommonSystem + FiltersSources + IOGeometry + ) + if(NOT VTK_FOUND) + message(FATAL_ERROR "VTK was not found") + endif() + target_link_libraries(libautoscoper PUBLIC ${VTK_LIBRARIES}) + vtk_module_autoinit( + TARGETS libautoscoper + MODULES ${VTK_LIBRARIES} + ) +endif() + set_target_properties(libautoscoper PROPERTIES RUNTIME_OUTPUT_NAME "libautoscoper${Autoscoper_ARTIFACT_SUFFIX}" LIBRARY_OUTPUT_NAME "libautoscoper${Autoscoper_ARTIFACT_SUFFIX}" diff --git a/libautoscoper/src/Mesh.cpp b/libautoscoper/src/Mesh.cpp new file mode 100644 index 00000000..f8a42760 --- /dev/null +++ b/libautoscoper/src/Mesh.cpp @@ -0,0 +1,27 @@ +#include "Mesh.hpp" +#include +#include + +Mesh::Mesh(const std::string& filename) +{ + vtkSTLReader* reader = vtkSTLReader::New(); + reader->SetFileName(filename.c_str()); + reader->Update(); + this->polyData = reader->GetOutput(); + reader->Delete(); +} + +Mesh::Mesh(const Mesh& other) +{ + this->polyData = vtkPolyData::New(); + this->polyData->DeepCopy(other.polyData); +} + +void Mesh::Write(const std::string& filename) const +{ + vtkSTLWriter* writer = vtkSTLWriter::New(); + writer->SetFileName(filename.c_str()); + writer->SetInputData(this->polyData); + writer->Write(); + writer->Delete(); +} diff --git a/libautoscoper/src/Mesh.hpp b/libautoscoper/src/Mesh.hpp new file mode 100644 index 00000000..5d066feb --- /dev/null +++ b/libautoscoper/src/Mesh.hpp @@ -0,0 +1,17 @@ +#pragma once +#include +#include + +class Mesh +{ +public: + Mesh(const std::string& filename); + Mesh(const Mesh&); + + vtkPolyData* GetPolyData() const { return this->polyData; } + + void Write(const std::string& filename) const; + +private: + vtkPolyData* polyData; +}; \ No newline at end of file diff --git a/libautoscoper/src/Trial.cpp b/libautoscoper/src/Trial.cpp index 8990a88c..e22ebbbf 100644 --- a/libautoscoper/src/Trial.cpp +++ b/libautoscoper/src/Trial.cpp @@ -98,9 +98,18 @@ Trial::Trial(const std::string& filename) std::vector volumeFlips; std::vector renderResolution; std::vector optimizationOffsets; - - parse( - file, version, mayaCams, camRootDirs, volumeFiles, voxelSizes, volumeFlips, renderResolution, optimizationOffsets); + std::vector meshFiles; + + parse(file, + version, + mayaCams, + camRootDirs, + volumeFiles, + voxelSizes, + volumeFlips, + renderResolution, + optimizationOffsets, + meshFiles); file.close(); @@ -122,7 +131,7 @@ Trial::Trial(const std::string& filename) convertToAbsolutePaths(volumeFiles, configLocation); } - validate(mayaCams, camRootDirs, volumeFiles, voxelSizes, filename); + validate(mayaCams, camRootDirs, volumeFiles, voxelSizes, meshFiles, filename); loadCameras(mayaCams); @@ -133,6 +142,8 @@ Trial::Trial(const std::string& filename) loadOffsets(optimizationOffsets); loadRenderResolution(renderResolution); + + loadMeshes(meshFiles); } void Trial::convertToUnixSlashes(std::string& path) @@ -193,7 +204,8 @@ void Trial::parse(std::ifstream& file, std::vector& voxelSizes, std::vector& volumeFlips, std::vector& renderResolution, - std::vector& optimizationOffsets) + std::vector& optimizationOffsets, + std::vector& meshFiles) { std::string line, key, value; @@ -230,6 +242,9 @@ void Trial::parse(std::ifstream& file, } else if (key.compare("OptimizationOffsets") == 0) { asys::SystemTools::GetLineFromStream(lineStream, value); optimizationOffsets.push_back(value); + } else if (key.compare("MeshFile") == 0) { + asys::SystemTools::GetLineFromStream(lineStream, value); + meshFiles.push_back(value); } else if (key.compare("Version") == 0) { asys::SystemTools::GetLineFromStream(lineStream, value); parseVersion(value, version); @@ -252,6 +267,7 @@ void Trial::validate(const std::vector& mayaCams, const std::vector& camRootDirs, const std::vector& volumeFiles, const std::vector& voxelSizes, + const std::vector& meshFiles, const std::string& filename) { @@ -279,6 +295,14 @@ void Trial::validate(const std::vector& mayaCams, "and " + std::to_string(voxelSizes.size()) + " voxel sizes.")); } + + if (meshFiles.size() != 0 && volumeFiles.size() != meshFiles.size()) { + throw std::runtime_error(filename, std::string("You must specify a mesh file for each volume or none at all.\n") + "Found" + + std::to_string(volumeFiles.size()) + + " volumes " + "and " + + std::to_string(meshFiles.size()) + " mesh files.")); + } } void Trial::loadCameras(std::vector& mayaCams) @@ -367,6 +391,26 @@ void Trial::loadRenderResolution(std::vector& renderResolution) } } +void Trial::loadMeshes(std::vector& meshFiles) +{ + if (meshFiles.size() > 0) { +#ifdef Autoscoper_COLLISION_DETECTION + meshes.clear(); + for (unsigned int i = 0; i < meshFiles.size(); ++i) { + try { + Mesh mesh(meshFiles[i]); + meshes.push_back(mesh); + } catch (std::exception& e) { + std::cerr << e.what() << std::endl; + } + } +#else + std::cerr << "WARNING: Autoscoper was not compiled with collision detection support. No mesh files" + << " will be loaded." << std::endl; +#endif // Autoscoper_COLLISION_DETECTION + } +} + void Trial::save(const std::string& filename) { std::vector mayaCamsFiles; diff --git a/libautoscoper/src/Trial.hpp b/libautoscoper/src/Trial.hpp index f5f9e599..93988fa3 100644 --- a/libautoscoper/src/Trial.hpp +++ b/libautoscoper/src/Trial.hpp @@ -52,8 +52,11 @@ #include "Volume.hpp" #include "VolumeTransform.hpp" -namespace xromm { +#ifdef Autoscoper_COLLISION_DETECTION +# include "Mesh.hpp" +#endif // Autoscoper_COLLISION_DETECTION +namespace xromm { // The trial class contains all of the state information for an autoscoper run. // It should eventually become an in-memory representation of the xromm // autoscoper file format. Currently that file format does not however hold the @@ -72,6 +75,9 @@ class Trial std::vector