Skip to content

Commit

Permalink
Added an OpenMesh interface
Browse files Browse the repository at this point in the history
Added an interface to parameterize OpenMesh triangle meshes.
  • Loading branch information
aschier committed May 5, 2020
1 parent 747f40f commit 2ccdfcf
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 2 deletions.
30 changes: 28 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ project(bff)

option(BUILD_CLI "Build BFF command line" ON)
option(BUILD_GUI "Build BFF GUI" ON)
option(WITH_OPENMESH_INTERFACE "Build with OpenMesh interface" OFF)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand Down Expand Up @@ -36,9 +37,33 @@ file(GLOB BFF_SOURCES
"mesh/src/*.cpp" "mesh/include/*.h"
"project/src/*.cpp" "project/include/*.h")

if(${WITH_OPENMESH_INTERFACE})
find_package(OpenMesh REQUIRED)
add_library(bff-openmesh-interface INTERFACE)
target_link_libraries(bff-openmesh-interface INTERFACE
bff
${OPENMESH_LIBRARIES}
)
target_include_directories(bff-openmesh-interface INTERFACE
${OPENMESH_INCLUDE_DIR}
)
endif()

# create bff static library
add_library(bff ${BFF_SOURCES})
target_link_libraries(bff ${SuiteSparse_LIBRARIES})
if(${WITH_OPENMESH_INTERFACE})
target_link_libraries(bff
PUBLIC
${OPENMESH_LIBRARIES}
openmesh_structures
)
target_include_directories(bff
PUBLIC
${OPENMESH_INCLUDE_DIR}
)
endif()

target_include_directories(bff
PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/deps/rectangle-bin-pack/include>
Expand Down Expand Up @@ -101,5 +126,6 @@ install(DIRECTORY project/include/ DESTINATION include FILES_MATCHING PATTERN "*
install(DIRECTORY mesh/include/ DESTINATION include FILES_MATCHING PATTERN "*.inl")
install(DIRECTORY linear-algebra/include/ DESTINATION include FILES_MATCHING PATTERN "*.inl")
install(DIRECTORY project/include/ DESTINATION include FILES_MATCHING PATTERN "*.inl")
install(EXPORT bff-targets FILE bffTargets.cmake DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/boundary-first-flattening/cmake)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bffConfig.cmake DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/boundary-first-flattening/cmake)
if(${WITH_OPENMESH_INTERFACE})
install(DIRECTORY openmesh-interface/include/ DESTINATION include FILES_MATCHING PATTERN "*.hpp")
endif()
59 changes: 59 additions & 0 deletions cmake/FindOpenMesh.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# - Try to find OPENMESH
# Once done this will define
#
# OPENMESH_FOUND - system has OPENMESH
# OPENMESH_INCLUDE_DIR - the OPENMESH include directory
# OPENMESH_LIBRARIES - the OPENMESH libraries
# OPENMESH_LIBRARY_DIR - the OPENMESH libraries directory
#

IF (OPENMESH_INCLUDE_DIR)
# Already in cache, be silent
SET(OPENMESH_FIND_QUIETLY TRUE)
ENDIF (OPENMESH_INCLUDE_DIR)

FIND_PATH(OPENMESH_INCLUDE_DIR OpenMesh/Core/Mesh/PolyMeshT.hh
PATHS /usr/local/include
/usr/include
/opt/local/include
/opt/include
${OPENMESH_DIR}/src
${OPENMESH_DIR}/include
$ENV{OPENMESH_DIR}/src
$ENV{OPENMESH_DIR}/include
)

IF (OPENMESH_INCLUDE_DIR)
IF (WIN32)
SET(OPENMESH_LIBRARY_DIR "${OPENMESH_INCLUDE_DIR}/../lib")
ELSE (WIN32)
SET(OPENMESH_LIBRARY_DIR "${OPENMESH_INCLUDE_DIR}/../lib/OpenMesh")
ENDIF (WIN32)

FIND_LIBRARY(OPENMESH_CORE_LIBRARY_RELEASE NAMES OpenMeshCore libOpenMeshCore PATHS ${OPENMESH_LIBRARY_DIR})
FIND_LIBRARY(OPENMESH_TOOLS_LIBRARY_RELEASE NAMES OpenMeshTools libOpenMeshTools PATHS ${OPENMESH_LIBRARY_DIR})
SET(OPENMESH_LIBRARY_RELEASE
${OPENMESH_CORE_LIBRARY_RELEASE}
${OPENMESH_TOOLS_LIBRARY_RELEASE})

FIND_LIBRARY(OPENMESH_CORE_LIBRARY_DEBUG NAMES OpenMeshCored libOpenMeshCored PATHS ${OPENMESH_LIBRARY_DIR})
FIND_LIBRARY(OPENMESH_TOOLS_LIBRARY_DEBUG NAMES OpenMeshToolsd libOpenMeshToolsd PATHS ${OPENMESH_LIBRARY_DIR})
SET(OPENMESH_LIBRARY_DEBUG
${OPENMESH_CORE_LIBRARY_DEBUG}
${OPENMESH_TOOLS_LIBRARY_DEBUG})
ENDIF (OPENMESH_INCLUDE_DIR)

if(OPENMESH_LIBRARY_RELEASE)
if(OPENMESH_LIBRARY_DEBUG)
set(OPENMESH_LIBRARIES_ optimized ${OPENMESH_CORE_LIBRARY_RELEASE} optimized ${OPENMESH_TOOLS_LIBRARY_RELEASE} debug ${OPENMESH_CORE_LIBRARY_DEBUG} debug ${OPENMESH_TOOLS_LIBRARY_DEBUG})
else()
set(OPENMESH_LIBRARIES_ ${OPENMESH_LIBRARY_RELEASE})
endif()

set(OPENMESH_LIBRARIES ${OPENMESH_LIBRARIES_} CACHE FILEPATH "The OpenMesh library")
endif()

IF(OPENMESH_INCLUDE_DIR AND OPENMESH_LIBRARIES)
SET(OPENMESH_FOUND TRUE)
MESSAGE(STATUS "Found OpenMesh: ${OPENMESH_LIBRARIES}")
ENDIF(OPENMESH_INCLUDE_DIR AND OPENMESH_LIBRARIES)
122 changes: 122 additions & 0 deletions openmesh-interface/include/bffOpenMesh.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#pragma once

#include <array>
#include <unordered_map>

#include <Vector.h>
#include <MeshIO.h>
#include <BFFMesh.h>

#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>

namespace bff {
template<typename Traits>
bff::Mesh openmesh_to_bff_mesh(const OpenMesh::TriMesh_ArrayKernelT<Traits> &mesh) {
PolygonSoup soup;
bff::Mesh result;

for(auto const vh : mesh.vertices()) {
auto p = mesh.point(vh);
soup.positions.push_back(bff::Vector(p[0], p[1], p[2]));
}

for(auto const fh : mesh.faces()) {
// We do not handle uncuttable edges, as our mesh definition is for triangles only
for(auto v_it = mesh.cfv_ccwbegin(fh); v_it != mesh.cfv_ccwend(fh); v_it++) {
soup.indices.push_back(v_it->idx());
}
}

soup.table.construct(soup.positions.size(), soup.indices);
std::vector<int> isCuttableEdge(soup.table.getSize(), 1);

std::string error;
bff::MeshIO::buildMesh(soup, isCuttableEdge, result, error);
if(error.size() > 0) {
std::cerr << "Error converting OpenMesh to BFF-Mesh: " << error << std::endl;
}

return result;
}
template<typename Traits>
OpenMesh::TriMesh_ArrayKernelT<Traits> bff_mesh_to_openmesh(bff::Mesh &mesh) {
typedef OpenMesh::TriMesh_ArrayKernelT<Traits> TriMesh;
TriMesh result;
result.request_halfedge_texcoords2D();

// TODO: assign vertex UVs for inner vertices and halfedge UVs for cuts,
// so UV shells can be reconstructed.
// When the cut vertices have face-vertex UVs, the edges from a
// chart boundary vertex to the inside of the chart will be cut
// (have different UV vertices) as well.
// This probably cannot be solved by assigning UVs to vertices and (half)edges
// but needs a separate UV list. Possibly we should use two functions, one returning
// the halfedge-UV mesh and one returning a mesh, a UV list and
// a list of face_vertex->UV_index assignments.

vector<TriMesh::VertexHandle> vertexHandles;
map<pair<int, int>, bff::Vector> facevertex_uvs;

// Create vertices
for(const auto v: mesh.vertices) {
// Add all vertices, which are no duplicates
if(v.referenceIndex == -1) {
auto p = v.position * (mesh.radius != 0? mesh.radius: 1.0);
auto vh = result.add_vertex({p[0], p[1], p[2]});
vertexHandles.push_back(vh);
}
}

// Create UVs
for(auto w: mesh.wedges()) {
auto v = w.vertex();
int vertexIndex = v->referenceIndex == -1 ? v->index : v->referenceIndex;
int faceIndex = w.face()->index;
facevertex_uvs[make_pair(faceIndex, vertexIndex)] = w.uv;
}

// Create faces
int uncuttableEdges = 0;
for(auto f: mesh.faces) {
if(f.fillsHole) { continue; }
if(uncuttableEdges > 0) {
uncuttableEdges--;
continue;
}

HalfEdgeCIter he = f.he;
while(!he->edge->isCuttable) he = he->next;
HalfEdgeCIter fhe = he;
std::unordered_map<int, bool> seenUncuttableEdges;

std::array<TriMesh::VertexHandle, 3> vhs;
short j = 0;
do {
assert(j < 3);
VertexCIter v = he->vertex;
int vIndex = v->referenceIndex == -1 ? v->index : v->referenceIndex;
vhs[j] = vertexHandles[vIndex];

he = he->next;
while(!he->edge->isCuttable) {
seenUncuttableEdges[he->edge->index] = true;
he = he->flip->next;
}
j++;
} while(he != fhe);
uncuttableEdges = (int)seenUncuttableEdges.size();

result.add_face(vhs.data(), 3);
}

// assign UVs
for(auto heh: result.halfedges()) {
int f_idx = result.face_handle(heh).idx();
int v_idx = result.to_vertex_handle(heh).idx();
bff::Vector uv = facevertex_uvs[make_pair(f_idx, v_idx)];
result.set_texcoord2D(heh, OpenMesh::Vec2d(uv[0], uv[1]));
}

return result;
}
}

0 comments on commit 2ccdfcf

Please sign in to comment.