Closed petrasvestartas closed 2 years ago
Hello!
The visualization and convex hull components are not header-only (and the former will only build if Pangolin is found), so you'd need to build the library first (i.e. as in here). Installing is optional (find_package
should be able to directly discover the library's build folder under the default settings).
After cilantro
has been built (and optionally installed), something like this should work:
cmake_minimum_required(VERSION 3.9)
project(my_project)
find_package(cilantro)
add_executable(my_app my_app.cpp)
target_link_libraries(my_app cilantro)
as a minimal CMake example for a project using the library.
I have no experience using ExternalProject_Add
, but I would be happy to try to help if you run into any issues!
Add_ExternalProject is just a command to clone github repo to current project build/install folder. I do the same for Eigen. Meaning find_package command is not needed.
I do not need Pangolin, but I would like to learn how to compile Cilantro into a library using cmake. Since I am beginner in CMake.
Would it be possible for you to test the example above and adapt it so that it compiles Cilantro as a library?
I'm attaching a minimal CMake project that uses ExternalProject_Add
, based on these:
https://crascit.com/2015/07/25/cmake-gtest/
https://github.com/Crascit/DownloadProject
It downloads/configures external projects at configuration time.
This should work:
mkdir build
cd build
cmake -DGET_LIBS=ON -DBUILD_MY_PROJECTS=ON ..
make -j
I don't know what would be a good way to pass down configuration parameters, as this relies on add_subdirectory
... There may be better ways to do this (I'm not really experienced with CMake either!).
(An alternative would be to build cilantro
externally and use the tiny snippet I shared above :D)
Thank you for reply,
I am wondering if it is possible to simplify the example. Wondering how the library can be directly compiled after repository is downloaded using "add_externalproject" command at build time. Do you have any example for this command too?
I have no prior experience using ExternalProject_Add
, but using it directly seems to be pretty cumbersome! :sweat_smile: This looks like a decent example if you want to go down that route:
https://stackoverflow.com/questions/15175318/cmake-how-to-build-external-projects-and-include-their-targets
Alternatively you could try FetchContent
:
cmake_minimum_required(VERSION 3.19)
project(superbuild LANGUAGES CXX)
cmake_policy(SET CMP0097 NEW)
set(CMAKE_BUILD_TYPE_INIT "Release")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Download deps
include(FetchContent)
FetchContent_Declare(
eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.4.0
)
FetchContent_MakeAvailable(eigen)
FetchContent_Declare(
cilantro
GIT_REPOSITORY https://github.com/kzampog/cilantro.git
GIT_TAG master
)
FetchContent_MakeAvailable(cilantro)
# Build app
add_executable(my_exe main.cpp)
target_link_libraries(my_exe PRIVATE Eigen3::Eigen cilantro)
Thank you for the help. It works for examples that only employs header-only methods like kd-tree.cpp.
But it does not work for other of your examples, like the one below. Do you have any ideas what causes the error?
#include <cilantro/visualization.hpp>
#include <cilantro/spatial/convex_polytope.hpp>
#include <cilantro/utilities/point_cloud.hpp>
void run_demo() {
std::vector<Eigen::Vector3f> points;
points.emplace_back(0,0,0);
points.emplace_back(1,0,0);
points.emplace_back(0,1,0);
points.emplace_back(0,0,1);
points.emplace_back(0,1,1);
points.emplace_back(1,0,1);
points.emplace_back(1,1,0);
points.emplace_back(1,1,1);
points.emplace_back(0.5,0.5,0.5);
cilantro::ConvexHull3f ch(points, true);
std::cout << "Vertices:" << std::endl;
for (size_t i = 0; i < ch.getVertices().cols(); i++) {
std::cout << ch.getVertices().col(i).transpose() << std::endl;
}
std::cout << "Faces:" << std::endl;
for (size_t i = 0; i < ch.getFacetVertexIndices().size(); i++) {
for (size_t j = 0; j < ch.getFacetVertexIndices()[i].size(); j++) {
std::cout << ch.getFacetVertexIndices()[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << "Vertex neighbor faces:" << std::endl;
for (size_t i = 0; i < ch.getVertexNeighborFacets().size(); i++) {
for (size_t j = 0; j < ch.getVertexNeighborFacets()[i].size(); j++) {
std::cout << ch.getVertexNeighborFacets()[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << "Face neighbor faces:" << std::endl;
for (size_t i = 0; i < ch.getFacetNeighborFacets().size(); i++) {
for (size_t j = 0; j < ch.getFacetNeighborFacets()[i].size(); j++) {
std::cout << ch.getFacetNeighborFacets()[i][j] << " ";
}
std::cout << std::endl;
}
}
int main(int argc, char ** argv) {
if (argc < 2) {
std::cout << "No input PLY file path provided, running simple demo." << std::endl;
run_demo();
return 0;
}
/*
cilantro::PointCloud3f cloud(argv[1]);
if (cloud.isEmpty()) {
std::cout << "Input cloud is empty!" << std::endl;
return 0;
}
cilantro::ConvexHull3f ch(cloud.points, true, true);
cilantro::PointCloud3f hull_cloud(cloud, ch.getVertexPointIndices());
cilantro::VectorSet3f vertex_colors(3, ch.getVertices().cols());
std::vector<float> vertex_values(ch.getVertices().cols());
for (size_t i = 0; i < ch.getVertices().cols(); i++) {
if (i%3 == 0) vertex_colors.col(i) = Eigen::Vector3f(1,0,0);
if (i%3 == 1) vertex_colors.col(i) = Eigen::Vector3f(0,1,0);
if (i%3 == 2) vertex_colors.col(i) = Eigen::Vector3f(0,0,1);
vertex_values[i] = ch.getVertices().col(i).norm();
}
cilantro::VectorSet3f face_colors(3, ch.getFacetVertexIndices().size());
std::vector<float> face_values(ch.getFacetVertexIndices().size());
for (size_t i = 0; i < ch.getFacetVertexIndices().size(); i++) {
if (i%3 == 0) face_colors.col(i) = Eigen::Vector3f(1,0,0);
if (i%3 == 1) face_colors.col(i) = Eigen::Vector3f(0,1,0);
if (i%3 == 2) face_colors.col(i) = Eigen::Vector3f(0,0,1);
face_values[i] = (ch.getVertices().col(ch.getFacetVertexIndices()[i][0]) +
ch.getVertices().col(ch.getFacetVertexIndices()[i][1]) +
ch.getVertices().col(ch.getFacetVertexIndices()[i][2])).rowwise().mean().norm();
}
const std::string window_name = "3D convex hull";
pangolin::CreateWindowAndBind(window_name, 640, 480);
cilantro::Visualizer viz(window_name, "disp");
viz.addObject<cilantro::PointCloudRenderable>("cloud", cloud, cilantro::RenderingProperties().setOpacity(1.0));
viz.addObject<cilantro::TriangleMeshRenderable>("mesh", ch.getVertices(), ch.getFacetVertexIndices())
->setVertexNormals(hull_cloud.normals).setVertexColors(vertex_colors).setVertexValues(vertex_values)
.setFaceColors(face_colors).setFaceValues(face_values);
cilantro::RenderingProperties rp = viz.getRenderingProperties("mesh");
rp.setUseFaceNormals(true).setUseFaceColors(false).setOpacity(0.8).setColormapType(cilantro::ColormapType::BLUE2RED);
viz.setRenderingProperties("mesh", rp);
viz.spin();
*/
return 0;
}
I think what you are seeing is because of MSVC only supporting a (very) outdated version of OpenMP (2.0). cilantro
requires a more recent version (>= 4.0 IIRC). If that would be an option, it might be worth trying other compilers on Windows (clang
sounds promising).
FWIW, the above seems to work as expected on recent Ubuntu versions!
BTW, I'd welcome PRs adding OpenMP 2.0 support for building with MSVC :D
Thank you, I will try to use header version which works for now;)
Hi,
I would like to ask if Cilantro is a header-only library?
I clone the repository using ExternalProject via CMake. How you would like to an executable with Cilantro and Eigen? Do I need to compile the cilantro as a library and then link to executable or it is possible to link like header libraries? Example with CMake would be much appreciated.