1. Overview
This tutorial provides the basic usage of using AMCAXMeshing for triangle mesh algorithm.
1.1 Trianlge Soup
AMCAXMeshing uses triangle soup to store mesh data. Triangle soup mainly contains the coordinates of mesh points and the index information of faces, and is a template parameter that mesh algorithms rely on.
class TriSoupTraits_Coord
{
public:
using PointT = VecProxy<3, double>;
using VecT = VecProxy<3, double>;
using NormalT = VecProxy<3, double>;
using Tex3D = VecProxy<3, double>;
using Color = VecProxy<3, float>;
using Triangle = VecProxy<3, int>;
using Points = std::vector<PointT>;
using Normals = std::vector<NormalT>;
using Tex3Ds = std::vector<Tex3D>;
using Colors = std::vector<Color>;
using Triangles = std::vector<Triangle>;
};
1.2 Using namespace
For clarity in the example code, using namespace
Namespace of all interface in the AMCAX Meshing module.
Definition misc.docu:35
Namespace of all interface in the AMCAX kernel.
Definition misc.docu:8
1.3 Mesh IO
AMCAXMeshing currently provides reading and writing of commonly used mesh file formats such as obj and stl.
mesh IO header file
2. Algorithm Examples
2.1 Mesh Simplify
#include <cfloat>
#include <thread>
using namespace AMCAX::Meshing::Mesh;
using namespace AMCAX::Meshing::Remeshing;
void Remeshing_FastQEM()
{
int overall_percent{};
[&overall_percent](int _overall_percent,
AMCAXMeshing_UNUSED bool& cancel) -> void
{
overall_percent = _overall_percent;
std::cout << "[Progress] Overall progress: " << overall_percent << "%"
<< std::endl;
if (overall_percent == 100)
std::cout << std::endl;
};
obj_reader.
read(
"./data/32770_sf.obj", io_options);
for (double ratio : {0.01, 0.1, 0.3, 0.6})
{
std::thread simplify_thread(
[&]()
{
fast_qem.simplify(
size_t(obj_reader.
m_triangles.size() * ratio), 0.1f, 20, pro_fn);
});
simplify_thread.join();
Logger::info(
"FastQEM: ratio " + std::to_string(ratio) +
"; time " + std::to_string(elapsed.count()) +
" s");
obj_writer.
m_points = std::move(fast_qem.m_points);
obj_writer.
m_triangles = std::move(fast_qem.m_triangles);
std::string out_filename = "FastQEM_" + std::to_string(ratio) + ".obj";
obj_writer.
write(out_filename, io_options, 10);
}
}
int main()
{
Remeshing_FastQEM();
}
std::function< void(int overall_percent, bool &cancel)> CbFunc
Progress callback with stage index and dual-level percentage.
Definition CallbackFunction.hpp:22
Fast QEM simplification algorithm.
static AMCAXMeshing_API void info(const std::string &msg)
log info level message
static AMCAXMeshing_API void elapse_reset()
reset elapsed time.
AMCAXMeshing_NODISCARD static AMCAXMeshing_API std::chrono::duration< double > elapsed()
return the elapsed time since the last reset.
Options about pre-described properties in mesh IO.
Definition IOOptions.hpp:19
bool vertex_has_point
Whether vertex contains point.
Definition IOOptions.hpp:21
Read triangle soup from an OBJ file.
Definition OBJReader.hpp:38
Points m_points
point position
Definition OBJReader.hpp:139
Triangles m_triangles
triangle faces
Definition OBJReader.hpp:144
AMCAXMeshing_API bool read(const std::string &filename, IOOptions &opt)
Read triangle soup from the file. results will be stored in member variables of reader,...
Write triangle soup to an OBJ file.
Definition OBJWriter.hpp:38
AMCAXMeshing_API void clear()
Clear data stored in writer.
Triangles m_triangles
triangle faces
Definition OBJWriter.hpp:146
AMCAXMeshing_API bool write(const std::string &filename, IOOptions &opt, std::streamsize precision)
Write triangle soup to file with given options and precison.
Points m_points
point position
Definition OBJWriter.hpp:141
Implement a fast QEM simplification algorithm based on triangle soup.
Definition TriSoup_FastQEM.hpp:35
Click here example1 to get the complete source code for the above example, which you can download according to your learning needs.
2.2 Mesh Boolean
using EIAC = AMCAX::Meshing::Geometry::EIAC;
void read_mesh(
const std::string& filename, Points& points, Triangles& triangles,
IOOptions& io_options
)
{
{
reader.
read(filename, io_options);
}
{
reader.
read(filename, io_options);
}
}
void write_mesh(
const std::string& filename,
const Points& points,
const Triangles& triangles,
IOOptions& io_options)
{
writer.
write(filename, io_options, 10);
};
void MeshBoolean_MeshBoolean()
{
Points points1, points2, result_points;
Triangles triangles1, triangles2, result_triangles;
read_mesh("./data/bunny25k.obj", points1, triangles1, io_options);
read_mesh("./data/cow.obj", points2, triangles2, io_options);
MeshBoolean boolean(true);
boolean.addTriMeshAsInput(points1, triangles1);
boolean.addTriMeshAsInput(points2, triangles2);
std::vector<std::pair<MeshBoolean::iPoints, MeshBoolean::iTriangles>> result_meshes;
result_meshes.emplace_back(result_points, result_triangles);
boolean.setTriMeshAsOutput(result_meshes);
boolean.computeLabels();
{
boolean.Union();
std::cout << "Union results: " << result_meshes.size() << " meshes" << std::endl;
for (size_t i = 0; i < result_meshes.size(); ++i) {
std::string filename = "AMCAXMeshing_Union_" + std::to_string(i) + ".obj";
write_mesh(filename.c_str(), result_meshes[i].first, result_meshes[i].second, io_options);
}
}
{
boolean.Intersection();
std::cout << "Intersection results: " << result_meshes.size() << " meshes" << std::endl;
for (size_t i = 0; i < result_meshes.size(); ++i) {
std::string filename = "AMCAXMeshing_Intersection_" + std::to_string(i) + ".obj";
write_mesh(filename.c_str(), result_meshes[i].first, result_meshes[i].second, io_options);
}
}
{
boolean.Xor();
std::cout << "Xor results: " << result_meshes.size() << " meshes" << std::endl;
for (size_t i = 0; i < result_meshes.size(); ++i) {
std::string filename = "AMCAXMeshing_Xor" + std::to_string(i) + ".obj";
write_mesh(filename.c_str(), result_meshes[i].first, result_meshes[i].second, io_options);
}
}
{
boolean.Subtraction();
std::cout << "Subtraction results: " << result_meshes.size() << " meshes" << std::endl;
for (size_t i = 0; i < result_meshes.size(); ++i) {
std::string filename = "AMCAXMeshing_Subtraction_" + std::to_string(i) + ".obj";
write_mesh(filename.c_str(), result_meshes[i].first, result_meshes[i].second, io_options);
}
}
}
int main() {
MeshBoolean_MeshBoolean();
}
reader triangle soup from STL file.
This file implement writer for STL file.
Repair triangle mesh to clean mesh.
Class for mesh boolean operations.
Definition MeshBoolean.hpp:55
Read triangle soup from an STL file.
Definition STLReader.hpp:33
AMCAXMeshing_API bool read(const std::string &filename, IOOptions &opt)
Read triangle soup from the file.
Points m_points
vertex position
Definition STLReader.hpp:67
Triangles m_triangles
triangles
Definition STLReader.hpp:68
Write mesh to an STL file.
Definition STLWriter.hpp:33
CommonTraits-based triangle mesh traits class, Uses VecProxy types as basic geometry types.
Definition TriSoup.hpp:87
StandardTraits-based triangle mesh traits class, Uses base Geometry types as basic geometry types.
Definition TriSoup.hpp:41
std::vector< Triangle > Triangles
An array that stores indices of three vertices for all faces.
Definition TriSoup.hpp:57
std::vector< PointT > Points
An array that stores points for vertices.
Definition TriSoup.hpp:51
AMCAXMeshing_API bool ends_with(const std::string &big_str, const std::string &small_str)
Checks if string ends with substring.
Click here example2 to get the complete source code for the above example, which you can download according to your learning needs.
2.3 Mesh Repair
using namespace AMCAX::Meshing::Mesh;
using namespace AMCAX::Meshing::MeshTools;
void MeshRepair_MeshRepair()
{
int overall_percent{};
[&overall_percent](int _overall_percent,
AMCAXMeshing_UNUSED bool& cancel) -> void
{
overall_percent = _overall_percent;
std::cout << "[Progress] Overall progress: " << overall_percent << "%"
<< std::endl;
if (overall_percent == 100)
std::cout << std::endl;
};
stl_reader.
read(
"./data/CamelBox.stl", io_options);
repair.repair();
io_options.stl_binary = true;
stl_writer.
write(
"repaired.stl", io_options, 10);
obj_writer.
write(
"repaired.obj", io_options, 10);
}
int main()
{
MeshRepair_MeshRepair();
}
Interfaces of mesh arrangements.
bool face_has_normal
Whether face contains normal.
Definition IOOptions.hpp:27
Triangles m_triangles
triangles
Definition STLWriter.hpp:92
AMCAXMeshing_API bool write(const std::string &filename, IOOptions &opt, std::streamsize precision=6)
Write mesh to file with given options and precison.
Points m_points
vertex position
Definition STLWriter.hpp:91
std::vector< Triangle > Triangles
An array that stores indices of three vertices for all faces.
Definition TriSoup.hpp:103
std::vector< PointT > Points
An array that stores points for vertices.
Definition TriSoup.hpp:97
Click here example3 to get the complete source code for the above example, which you can download according to your learning needs.
2.4 Mesh Subdivision
2.4.1 ButterFly Subdivision
using namespace AMCAX::Meshing::Mesh;
using namespace AMCAX::Meshing::Subdivision;
using namespace AMCAX::Meshing::Remeshing;
void Subdivision_TriSoup_ButterFly()
{
obj_reader.
read(
"./data/kelan.obj", io_options);
for (double ratio : {2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.})
{
size_t sub_times = size_t(std::ceil(ratio / 4.0) + 0.1);
for (size_t i = 0; i < sub_times; i++)
subdivider.subdivide();
if (
size_t(obj_reader.
m_triangles.size() * ratio + fast_qem.m_triangles.size() * 0.01) < fast_qem.m_triangles.size())
fast_qem.simplify(
size_t(obj_reader.
m_triangles.size() * ratio), FLT_MAX, 20);
Logger::info(
"ButterFly: ratio " + std::to_string(ratio) +
"; time " + std::to_string(elapsed.count()) +
" s");
obj_writer.
m_points = std::move(fast_qem.m_points);
obj_writer.
m_triangles = std::move(fast_qem.m_triangles);
std::string out_filename = "TriSoupModifiedButterFly_" + std::to_string(ratio) + ".obj";
obj_writer.
write(out_filename, io_options, 10);
}
}
int main()
{
Subdivision_TriSoup_ButterFly();
}
Implement ButterFly subdivision algorithm.
Modified butterfly subdivision for triangle mesh.
Definition TriSoup_ButterFlySubdivision.hpp:33
Click here example4 to get the complete source code for the above example, which you can download according to your learning needs.
2.4.2 Loop Subdivision
using namespace AMCAX::Meshing::Mesh;
using namespace AMCAX::Meshing::Remeshing;
using namespace AMCAX::Meshing::Subdivision;
void Subdivision_TriSoup_LoopSubdivision()
{
obj_reader.
read(
"./data/kelan.obj", io_options);
for (double ratio : {2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.})
{
size_t sub_times = size_t(std::ceil(ratio / 4.0) + 0.1);
for (size_t i = 0; i < sub_times; i++)
subdivider.subdivide();
if (
size_t(obj_reader.
m_triangles.size() * ratio + fast_qem.m_triangles.size() * 0.01) < fast_qem.m_triangles.size())
fast_qem.simplify(
size_t(obj_reader.
m_triangles.size() * ratio), FLT_MAX, 12);
Logger::info(
"Loop: ratio " + std::to_string(ratio) +
"; time " + std::to_string(elapsed.count()) +
" s");
obj_writer.
m_points = std::move(fast_qem.m_points);
obj_writer.
m_triangles = std::move(fast_qem.m_triangles);
std::string out_filename = "TriSoupLoopSub_" + std::to_string(ratio) + ".obj";
obj_writer.
write(out_filename, io_options, 10);
}
}
int main()
{
Subdivision_TriSoup_LoopSubdivision();
}
Implement loop subdivision algorithm.
Loop subdivision for triangle mesh.
Definition TriSoup_LoopSubdivision.hpp:80
Click here example5 to get the complete source code for the above example, which you can download according to your learning needs.
2.5 Remeshing
2.5.1 Incremental Remeshing
using namespace AMCAX::Meshing::Mesh;
using namespace AMCAX::Meshing::Remeshing;
void incremental_remesh_test()
{
std::string inputfilename = "./data/filename_1.obj";
reader.
read(inputfilename, io_options);
input_points = std::move(reader.
m_points);
output_points = input_points;
output_triangles = input_triangles;
params.featurePreserved = true;
params.isAdaptive = true;
params.iterNum = 10;
params.Max_error = 0.0005;
params.targetEdgeLength = 0.1;
std::string outputfilename = std::to_string(params.iterNum) + ".obj";
writer.
m_points = std::move(output_points);
writer.
write(outputfilename, io_options, 15);
}
int main()
{
incremental_remesh_test();
}
Commonly used mathematical constants.
Interfaces of triMesh incremental remeshing.
Class for incremental mesh remeshing.
Definition TriMesh_IncrementalRemeshing.hpp:27
AMCAXMeshing_API void setReferenceMesh(const iPoints &points, const iTriangles &triangles)
add a triangle mesh (triangle soup) as one input.
AMCAXMeshing_API void setVariableMesh(iPoints &points, iTriangles &triangles)
Set the triangle mesh (triangle soup) as output destination.
AMCAXMeshing_API void remesh(Params params)
Adaptive/Isotropic remeshing controlled by the control parameters.
constexpr double pi
Mathematical constant Pi, ratio of a circle's circumference to its diameter.
Definition Constants.hpp:42
the parameters that control the remeshing
Definition TriMesh_IncrementalRemeshing.hpp:43
Click here example6 to get the complete source code for the above example, which you can download according to your learning needs.
2.6 Mesh parameterisation algorithm
using namespace AMCAX::Meshing::Mesh;
using namespace AMCAX::Meshing::Parameterization;
void Parameterization_Bijective()
{
obj_reader.
read(
"./data/cow.obj", io_options);
para.parameterization();
std::string out_filename = "res_parameterization.obj";
obj_writer.
write(out_filename, io_options, 10);
}
int main()
{
Parameterization_Bijective();
}
Bijective parameterization algorithm.
Class for bijective mesh parametrization.
Definition MeshParameterization.hpp:29
Click here example7 to get the complete source code for the above example, which you can download according to your learning needs.
2.7 Mesh Cutting Algorithm
using namespace AMCAX::Meshing::Mesh;
using namespace AMCAX::Meshing::Parameterization;
void Parameterization_With_MeshCut()
{
std::string in_filename = "./data/bunny25k.obj";
std::string out_cut_filename = "bunny_cut.obj";
std::string out_para_filename ="bunny_parameterization.obj";
obj_reader.
read(in_filename, io_options);
Points i_points = std::move(obj_reader.
m_points);
Triangles i_triangles = std::move(obj_reader.
m_triangles);
Points cut_points;
Triangles cut_triangles;
mesh_cut.cut(cut_points, cut_triangles);
obj_writer.
write(out_cut_filename, io_options, 10);
Points para_points;
para.parameterization();
obj_writer.
m_points = std::move(para_points);
obj_writer.
write(out_para_filename, io_options, 10);
}
int main()
{
Parameterization_With_MeshCut();
}
Greedy cut algorithm for triangle mesh.
Class for cutting a mesh into an open mesh using a greedy algorithm.
Definition TriMeshCut.hpp:31
Click here example8 to get the complete source code for the above example, which you can download according to your learning needs.