calibration_tools_v1.0/lidar_driver/include/open3d/geometry/TriangleMesh.h

866 lines
40 KiB
C
Raw Permalink Normal View History

2025-02-20 10:45:17 +08:00
// ----------------------------------------------------------------------------
// - Open3D: www.open3d.org -
// ----------------------------------------------------------------------------
// Copyright (c) 2018-2023 www.open3d.org
// SPDX-License-Identifier: MIT
// ----------------------------------------------------------------------------
#pragma once
#include <Eigen/Core>
#include <memory>
#include <numeric>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "open3d/geometry/Image.h"
#include "open3d/geometry/MeshBase.h"
#include "open3d/utility/Helper.h"
namespace open3d {
namespace geometry {
class PointCloud;
class TetraMesh;
/// \class TriangleMesh
///
/// \brief Triangle mesh contains vertices and triangles represented by the
/// indices to the vertices.
///
/// Optionally, the mesh may also contain triangle normals, vertex normals and
/// vertex colors.
class TriangleMesh : public MeshBase {
public:
/// \brief Default Constructor.
TriangleMesh() : MeshBase(Geometry::GeometryType::TriangleMesh) {}
/// \brief Parameterized Constructor.
///
/// \param vertices list of vertices.
/// \param triangles list of triangles.
TriangleMesh(const std::vector<Eigen::Vector3d> &vertices,
const std::vector<Eigen::Vector3i> &triangles)
: MeshBase(Geometry::GeometryType::TriangleMesh, vertices),
triangles_(triangles) {}
~TriangleMesh() override {}
public:
virtual TriangleMesh &Clear() override;
virtual TriangleMesh &Transform(
const Eigen::Matrix4d &transformation) override;
virtual TriangleMesh &Rotate(const Eigen::Matrix3d &R,
const Eigen::Vector3d &center) override;
public:
TriangleMesh &operator+=(const TriangleMesh &mesh);
TriangleMesh operator+(const TriangleMesh &mesh) const;
/// Returns `true` if the mesh contains triangles.
bool HasTriangles() const {
return vertices_.size() > 0 && triangles_.size() > 0;
}
/// Returns `true` if the mesh contains triangle normals.
bool HasTriangleNormals() const {
return HasTriangles() && triangles_.size() == triangle_normals_.size();
}
/// Returns `true` if the mesh contains adjacency normals.
bool HasAdjacencyList() const {
return vertices_.size() > 0 &&
adjacency_list_.size() == vertices_.size();
}
bool HasTriangleUvs() const {
return HasTriangles() && triangle_uvs_.size() == 3 * triangles_.size();
}
/// Returns `true` if the mesh has texture.
bool HasTextures() const {
bool is_all_texture_valid = std::accumulate(
textures_.begin(), textures_.end(), true,
[](bool a, const Image &b) { return a && !b.IsEmpty(); });
return !textures_.empty() && is_all_texture_valid;
}
bool HasMaterials() const { return !materials_.empty(); }
bool HasTriangleMaterialIds() const {
return HasTriangles() &&
triangle_material_ids_.size() == triangles_.size();
}
/// Normalize both triangle normals and vertex normals to length 1.
TriangleMesh &NormalizeNormals() {
MeshBase::NormalizeNormals();
for (size_t i = 0; i < triangle_normals_.size(); i++) {
triangle_normals_[i].normalize();
if (std::isnan(triangle_normals_[i](0))) {
triangle_normals_[i] = Eigen::Vector3d(0.0, 0.0, 1.0);
}
}
return *this;
}
/// \brief Function to compute triangle normals, usually called before
/// rendering.
TriangleMesh &ComputeTriangleNormals(bool normalized = true);
/// \brief Function to compute vertex normals, usually called before
/// rendering.
TriangleMesh &ComputeVertexNormals(bool normalized = true);
/// \brief Function to compute adjacency list, call before adjacency list is
/// needed.
TriangleMesh &ComputeAdjacencyList();
/// \brief Function that removes duplicated verties, i.e., vertices that
/// have identical coordinates.
TriangleMesh &RemoveDuplicatedVertices();
/// \brief Function that removes duplicated triangles, i.e., removes
/// triangles that reference the same three vertices and have the same
/// orientation.
TriangleMesh &RemoveDuplicatedTriangles();
/// \brief This function removes vertices from the triangle mesh that are
/// not referenced in any triangle of the mesh.
TriangleMesh &RemoveUnreferencedVertices();
/// \brief Function that removes degenerate triangles, i.e., triangles that
/// reference a single vertex multiple times in a single triangle.
///
/// They are usually the product of removing duplicated vertices.
TriangleMesh &RemoveDegenerateTriangles();
/// \brief Function that removes all non-manifold edges, by successively
/// deleting triangles with the smallest surface area adjacent to the
/// non-manifold edge until the number of adjacent triangles to the edge is
/// `<= 2`.
TriangleMesh &RemoveNonManifoldEdges();
/// \brief Function that will merge close by vertices to a single one.
/// The vertex position, normal and color will be the average of the
/// vertices.
///
/// \param eps defines the maximum distance of close by vertices.
/// This function might help to close triangle soups.
TriangleMesh &MergeCloseVertices(double eps);
/// \brief Function to sharpen triangle mesh.
///
/// The output value (\f$v_o\f$) is the input value (\f$v_i\f$) plus
/// strength times the input value minus the sum of he adjacent values.
/// \f$v_o = v_i + strength (v_i * |N| - \sum_{n \in N} v_n)\f$.
///
/// \param number_of_iterations defines the number of repetitions
/// of this operation.
/// \param strength - The strength of the filter.
std::shared_ptr<TriangleMesh> FilterSharpen(
int number_of_iterations,
double strength,
FilterScope scope = FilterScope::All) const;
/// \brief Function to smooth triangle mesh with simple neighbour average.
///
/// \f$v_o = \frac{v_i + \sum_{n \in N} v_n)}{|N| + 1}\f$, with \f$v_i\f$
/// being the input value, \f$v_o\f$ the output value, and \f$N\f$ is the
/// set of adjacent neighbours.
///
/// \param number_of_iterations defines the number of repetitions
/// of this operation.
std::shared_ptr<TriangleMesh> FilterSmoothSimple(
int number_of_iterations,
FilterScope scope = FilterScope::All) const;
/// \brief Function to smooth triangle mesh using Laplacian.
///
/// \f$v_o = v_i \cdot \lambda (\sum_{n \in N} w_n v_n - v_i)\f$,
/// with \f$v_i\f$ being the input value, \f$v_o\f$ the output value,
/// \f$N\f$ is the set of adjacent neighbours, \f$w_n\f$ is the weighting of
/// the neighbour based on the inverse distance (closer neighbours have
/// higher weight),
///
/// \param number_of_iterations defines the number of repetitions
/// of this operation.
/// \param lambda_filter is the smoothing parameter.
std::shared_ptr<TriangleMesh> FilterSmoothLaplacian(
int number_of_iterations,
double lambda_filter,
FilterScope scope = FilterScope::All) const;
/// \brief Function to smooth triangle mesh using method of Taubin,
/// "Curve and Surface Smoothing Without Shrinkage", 1995.
/// Applies in each iteration two times FilterSmoothLaplacian, first
/// with lambda_filter and second with mu as smoothing parameter.
/// This method avoids shrinkage of the triangle mesh.
///
/// \param number_of_iterations defines the number of repetitions
/// of this operation.
/// \param lambda_filter is the filter parameter
/// \param mu is the filter parameter
std::shared_ptr<TriangleMesh> FilterSmoothTaubin(
int number_of_iterations,
double lambda_filter = 0.5,
double mu = -0.53,
FilterScope scope = FilterScope::All) const;
/// Function that computes the Euler-Poincaré characteristic, i.e.,
/// V + F - E, where V is the number of vertices, F is the number
/// of triangles, and E is the number of edges.
int EulerPoincareCharacteristic() const;
/// Function that returns the non-manifold edges of the triangle mesh.
/// If \param allow_boundary_edges is set to false, then also boundary
/// edges are returned.
std::vector<Eigen::Vector2i> GetNonManifoldEdges(
bool allow_boundary_edges = true) const;
/// Function that checks if the given triangle mesh is edge-manifold.
/// A mesh is edge­-manifold if each edge is bounding either one or two
/// triangles. If allow_boundary_edges is set to false, then this function
/// returns false if there exists boundary edges.
bool IsEdgeManifold(bool allow_boundary_edges = true) const;
/// Function that returns a list of non-manifold vertex indices.
/// A vertex is manifold if its star is edgemanifold and edgeconnected.
/// (Two or more faces connected only by a vertex and not by an edge.)
std::vector<int> GetNonManifoldVertices() const;
/// Function that checks if all vertices in the triangle mesh are manifold.
/// A vertex is manifold if its star is edgemanifold and edgeconnected.
/// (Two or more faces connected only by a vertex and not by an edge.)
bool IsVertexManifold() const;
/// Function that returns a list of triangles that are intersecting the
/// mesh.
std::vector<Eigen::Vector2i> GetSelfIntersectingTriangles() const;
/// Function that tests if the triangle mesh is self-intersecting.
/// Tests each triangle pair for intersection.
bool IsSelfIntersecting() const;
/// Function that tests if the bounding boxes of the triangle meshes are
/// intersecting.
bool IsBoundingBoxIntersecting(const TriangleMesh &other) const;
/// Function that tests if the triangle mesh intersects another triangle
/// mesh. Tests each triangle against each other triangle.
bool IsIntersecting(const TriangleMesh &other) const;
/// Function that tests if the given triangle mesh is orientable, i.e.
/// the triangles can be oriented in such a way that all normals point
/// towards the outside.
bool IsOrientable() const;
/// Function that tests if the given triangle mesh is watertight by
/// checking if it is vertex manifold and edge-manifold with no boundary
/// edges, but not self-intersecting.
bool IsWatertight() const;
/// If the mesh is orientable then this function rearranges the
/// triangles such that all normals point towards the
/// outside/inside.
bool OrientTriangles();
/// Function that returns a map from edges (vertex0, vertex1) to the
/// triangle indices the given edge belongs to.
std::unordered_map<Eigen::Vector2i,
std::vector<int>,
utility::hash_eigen<Eigen::Vector2i>>
GetEdgeToTrianglesMap() const;
/// Function that returns a map from edges (vertex0, vertex1) to the
/// vertex (vertex2) indices the given edge belongs to.
std::unordered_map<Eigen::Vector2i,
std::vector<int>,
utility::hash_eigen<Eigen::Vector2i>>
GetEdgeToVerticesMap() const;
/// Function that computes the area of a mesh triangle
static double ComputeTriangleArea(const Eigen::Vector3d &p0,
const Eigen::Vector3d &p1,
const Eigen::Vector3d &p2);
/// Function that computes the area of a mesh triangle identified by the
/// triangle index
double GetTriangleArea(size_t triangle_idx) const;
static inline Eigen::Vector3i GetOrderedTriangle(int vidx0,
int vidx1,
int vidx2) {
if (vidx0 > vidx2) {
std::swap(vidx0, vidx2);
}
if (vidx0 > vidx1) {
std::swap(vidx0, vidx1);
}
if (vidx1 > vidx2) {
std::swap(vidx1, vidx2);
}
return Eigen::Vector3i(vidx0, vidx1, vidx2);
}
/// Function that computes the surface area of the mesh, i.e. the sum of
/// the individual triangle surfaces.
double GetSurfaceArea() const;
/// Function that computes the surface area of the mesh, i.e. the sum of
/// the individual triangle surfaces.
double GetSurfaceArea(std::vector<double> &triangle_areas) const;
/// Function that computes the volume of the mesh, under the condition that
/// it is watertight and orientable.
/// See Zhang and Chen, "Efficient feature extraction for 2D/3D objects in
/// mesh representation", 2001.
double GetVolume() const;
/// Function that computes the plane equation from the three points.
/// If the three points are co-linear, then this function returns the
/// invalid plane (0, 0, 0, 0).
static Eigen::Vector4d ComputeTrianglePlane(const Eigen::Vector3d &p0,
const Eigen::Vector3d &p1,
const Eigen::Vector3d &p2);
/// Function that computes the plane equation of a mesh triangle identified
/// by the triangle index.
Eigen::Vector4d GetTrianglePlane(size_t triangle_idx) const;
/// Helper function to get an edge with ordered vertex indices.
static inline Eigen::Vector2i GetOrderedEdge(int vidx0, int vidx1) {
return Eigen::Vector2i(std::min(vidx0, vidx1), std::max(vidx0, vidx1));
}
/// Function to sample \param number_of_points points uniformly from the
/// mesh.
std::shared_ptr<PointCloud> SamplePointsUniformlyImpl(
size_t number_of_points,
std::vector<double> &triangle_areas,
double surface_area,
bool use_triangle_normal);
/// Function to sample points uniformly from the mesh.
///
/// \param number_of_points points uniformly from the mesh.
/// \param use_triangle_normal Set to true to assign the triangle normals to
/// the returned points instead of the interpolated vertex normals. The
/// triangle normals will be computed and added to the mesh if necessary.
std::shared_ptr<PointCloud> SamplePointsUniformly(
size_t number_of_points, bool use_triangle_normal = false);
/// Function to sample points from the mesh with Possion disk, based on the
/// method presented in Yuksel, "Sample Elimination for Generating Poisson
/// Disk Sample Sets", EUROGRAPHICS.
///
/// \param number_of_points Number of points that should be sampled.
/// \param init_factor Factor for the initial uniformly sampled PointCloud.
/// This init PointCloud is used for sample elimination.
/// \param pcl_init Initial PointCloud that is used for sample elimination.
/// If this parameter is provided the init_factor is ignored.
/// \param use_triangle_normal If True assigns the triangle normals instead
/// of the interpolated vertex normals to the returned points. The triangle
/// normals will be computed and added to the mesh if necessary.
std::shared_ptr<PointCloud> SamplePointsPoissonDisk(
size_t number_of_points,
double init_factor = 5,
const std::shared_ptr<PointCloud> pcl_init = nullptr,
bool use_triangle_normal = false);
/// Function to subdivide triangle mesh using the simple midpoint algorithm.
/// Each triangle is subdivided into four triangles per iteration and the
/// new vertices lie on the midpoint of the triangle edges.
/// \param number_of_iterations defines a single iteration splits each
/// triangle into four triangles that cover the same surface.
std::shared_ptr<TriangleMesh> SubdivideMidpoint(
int number_of_iterations) const;
/// Function to subdivide triangle mesh using Loop's scheme.
/// Cf. Charles T. Loop, "Smooth subdivision surfaces based on triangles",
/// 1987. Each triangle is subdivided into four triangles per iteration.
/// \param number_of_iterations defines a single iteration splits each
/// triangle into four triangles that cover the same surface.
std::shared_ptr<TriangleMesh> SubdivideLoop(int number_of_iterations) const;
/// Function to simplify mesh using Vertex Clustering.
/// The result can be a non-manifold mesh.
/// \param voxel_size - The size of the voxel within vertices are pooled.
/// \param contraction - Method to aggregate vertex information. Average
/// computes a simple average, Quadric minimizes the distance to the
/// adjacent planes.
std::shared_ptr<TriangleMesh> SimplifyVertexClustering(
double voxel_size,
SimplificationContraction contraction =
SimplificationContraction::Average) const;
/// Function to simplify mesh using Quadric Error Metric Decimation by
/// Garland and Heckbert.
/// \param target_number_of_triangles defines the number of triangles that
/// the simplified mesh should have. It is not guaranteed that this number
/// will be reached.
/// \param maximum_error defines the maximum error where a vertex is allowed
/// to be merged
/// \param boundary_weight a weight applied to edge vertices used to
/// preserve boundaries
std::shared_ptr<TriangleMesh> SimplifyQuadricDecimation(
int target_number_of_triangles,
double maximum_error,
double boundary_weight) const;
/// Function to select points from \p input TriangleMesh into
/// output TriangleMesh
/// Vertices with indices in \p indices are selected.
/// \param indices defines Indices of vertices to be selected.
/// \param cleanup If true it automatically calls
/// TriangleMesh::RemoveDuplicatedVertices,
/// TriangleMesh::RemoveDuplicatedTriangles,
/// TriangleMesh::RemoveUnreferencedVertices, and
/// TriangleMesh::RemoveDegenerateTriangles
std::shared_ptr<TriangleMesh> SelectByIndex(
const std::vector<size_t> &indices, bool cleanup = true) const;
/// Function to crop pointcloud into output pointcloud
/// All points with coordinates outside the bounding box \p bbox are
/// clipped.
/// \param bbox defines the input Axis Aligned Bounding Box.
std::shared_ptr<TriangleMesh> Crop(
const AxisAlignedBoundingBox &bbox) const;
/// Function to crop pointcloud into output pointcloud
/// All points with coordinates outside the bounding box \p bbox are
/// clipped.
/// \param bbox defines the input Oriented Bounding Box.
std::shared_ptr<TriangleMesh> Crop(const OrientedBoundingBox &bbox) const;
/// \brief Function that clusters connected triangles, i.e., triangles that
/// are connected via edges are assigned the same cluster index.
///
/// \return A vector that contains the cluster index per
/// triangle, a second vector contains the number of triangles per
/// cluster, and a third vector contains the surface area per cluster.
std::tuple<std::vector<int>, std::vector<size_t>, std::vector<double>>
ClusterConnectedTriangles() const;
/// \brief This function removes the triangles with index in
/// \p triangle_indices. Call \ref RemoveUnreferencedVertices to clean up
/// vertices afterwards.
///
/// \param triangle_indices Indices of the triangles that should be
/// removed.
void RemoveTrianglesByIndex(const std::vector<size_t> &triangle_indices);
/// \brief This function removes the triangles that are masked in
/// \p triangle_mask. Call \ref RemoveUnreferencedVertices to clean up
/// vertices afterwards.
///
/// \param triangle_mask Mask of triangles that should be removed.
/// Should have same size as \ref triangles_.
void RemoveTrianglesByMask(const std::vector<bool> &triangle_mask);
/// \brief This function removes the vertices with index in
/// \p vertex_indices. Note that also all triangles associated with the
/// vertices are removeds.
///
/// \param vertex_indices Indices of the vertices that should be
/// removed.
void RemoveVerticesByIndex(const std::vector<size_t> &vertex_indices);
/// \brief This function removes the vertices that are masked in
/// \p vertex_mask. Note that also all triangles associated with the
/// vertices are removed.
///
/// \param vertex_mask Mask of vertices that should be removed.
/// Should have same size as \ref vertices_.
void RemoveVerticesByMask(const std::vector<bool> &vertex_mask);
/// \brief This function deforms the mesh using the method by
/// Sorkine and Alexa, "As-Rigid-As-Possible Surface Modeling", 2007.
///
/// \param constraint_vertex_indices Indices of the triangle vertices that
/// should be constrained by the vertex positions in
/// constraint_vertex_positions.
/// \param constraint_vertex_positions Vertex positions used for the
/// constraints.
/// \param max_iter maximum number of iterations to minimize energy
/// functional.
/// \param energy energy model that should be optimized
/// \param smoothed_alpha alpha parameter of the smoothed ARAP model
/// \return The deformed TriangleMesh
std::shared_ptr<TriangleMesh> DeformAsRigidAsPossible(
const std::vector<int> &constraint_vertex_indices,
const std::vector<Eigen::Vector3d> &constraint_vertex_positions,
size_t max_iter,
DeformAsRigidAsPossibleEnergy energy =
DeformAsRigidAsPossibleEnergy::Spokes,
double smoothed_alpha = 0.01) const;
/// \brief Alpha shapes are a generalization of the convex hull. With
/// decreasing alpha value the shape schrinks and creates cavities.
/// See Edelsbrunner and Muecke, "Three-Dimensional Alpha Shapes", 1994.
/// \param pcd PointCloud for what the alpha shape should be computed.
/// \param alpha parameter to control the shape. A very big value will
/// give a shape close to the convex hull.
/// \param tetra_mesh If not a nullptr, then uses this to construct the
/// alpha shape. Otherwise, ComputeDelaunayTetrahedralization is called.
/// \param pt_map Optional map from tetra_mesh vertex indices to pcd
/// points.
/// \return TriangleMesh of the alpha shape.
static std::shared_ptr<TriangleMesh> CreateFromPointCloudAlphaShape(
const PointCloud &pcd,
double alpha,
std::shared_ptr<TetraMesh> tetra_mesh = nullptr,
std::vector<size_t> *pt_map = nullptr);
/// Function that computes a triangle mesh from an oriented PointCloud \p
/// pcd. This implements the Ball Pivoting algorithm proposed in F.
/// Bernardini et al., "The ball-pivoting algorithm for surface
/// reconstruction", 1999. The implementation is also based on the
/// algorithms outlined in Digne, "An Analysis and Implementation of a
/// Parallel Ball Pivoting Algorithm", 2014. The surface reconstruction is
/// done by rolling a ball with a given radius (cf. \p radii) over the
/// point cloud, whenever the ball touches three points a triangle is
/// created.
/// \param pcd defines the PointCloud from which the TriangleMesh surface is
/// reconstructed. Has to contain normals.
/// \param radii defines the radii of
/// the ball that are used for the surface reconstruction.
static std::shared_ptr<TriangleMesh> CreateFromPointCloudBallPivoting(
const PointCloud &pcd, const std::vector<double> &radii);
/// \brief Function that computes a triangle mesh from an oriented
/// PointCloud pcd. This implements the Screened Poisson Reconstruction
/// proposed in Kazhdan and Hoppe, "Screened Poisson Surface
/// Reconstruction", 2013. This function uses the original implementation by
/// Kazhdan. See https://github.com/mkazhdan/PoissonRecon
///
/// \param pcd PointCloud with normals and optionally colors.
/// \param depth Maximum depth of the tree that will be used for surface
/// reconstruction. Running at depth d corresponds to solving on a grid
/// whose resolution is no larger than 2^d x 2^d x 2^d. Note that since the
/// reconstructor adapts the octree to the sampling density, the specified
/// reconstruction depth is only an upper bound.
/// \param width Specifies the target width of the finest level octree
/// cells. This parameter is ignored if depth is specified.
/// \param scale Specifies the ratio between the diameter of the cube used
/// for reconstruction and the diameter of the samples' bounding cube.
/// \param linear_fit If true, the reconstructor use linear interpolation to
/// estimate the positions of iso-vertices.
/// \param n_threads Number of threads used for reconstruction. Set to -1 to
/// automatically determine it.
/// \return The estimated TriangleMesh, and per vertex density values that
/// can be used to to trim the mesh.
static std::tuple<std::shared_ptr<TriangleMesh>, std::vector<double>>
CreateFromPointCloudPoisson(const PointCloud &pcd,
size_t depth = 8,
float width = 0.0f,
float scale = 1.1f,
bool linear_fit = false,
int n_threads = -1);
/// Factory function to create a tetrahedron mesh (trianglemeshfactory.cpp).
/// the mesh centroid will be at (0,0,0) and \p radius defines the
/// distance from the center to the mesh vertices.
/// \param radius defines the distance from centroid to mesh vetices.
/// \param create_uv_map add default UV map to the mesh.
static std::shared_ptr<TriangleMesh> CreateTetrahedron(
double radius = 1.0, bool create_uv_map = false);
/// Factory function to create an octahedron mesh (trianglemeshfactory.cpp).
/// the mesh centroid will be at (0,0,0) and \p radius defines the
/// distance from the center to the mesh vertices.
/// \param radius defines the distance from centroid to mesh vetices.
/// \param create_uv_map add default UV map to the mesh.
static std::shared_ptr<TriangleMesh> CreateOctahedron(
double radius = 1.0, bool create_uv_map = false);
/// Factory function to create an icosahedron mesh
/// (trianglemeshfactory.cpp). The mesh centroid will be at (0,0,0) and
/// \param radius defines the distance from the center to the mesh vertices.
/// \param create_uv_map add default UV map to the mesh.
static std::shared_ptr<TriangleMesh> CreateIcosahedron(
double radius = 1.0, bool create_uv_map = false);
/// Factory function to create solid mesh from an OrientedBoundingBox.
/// \param obox OrientedBoundingBox object to create a mesh of
/// \param scale scale factor along each direction of OrientedBoundingBox
/// \param create_uv_map add default UV map to the mesh.
static std::shared_ptr<TriangleMesh> CreateFromOrientedBoundingBox(
const OrientedBoundingBox &obox,
const Eigen::Vector3d &scale = Eigen::Vector3d::Ones(),
bool create_uv_map = false);
/// Factory function to create a box mesh (TriangleMeshFactory.cpp)
/// The left bottom corner on the front will be placed at (0, 0, 0).
/// \param width is x-directional length.
/// \param height is y-directional length.
/// \param depth is z-directional length.
/// \param create_uv_map add default UV map to the shape.
/// \param map_texture_to_each_face if true, maps the entire texture image
/// to each face. If false, sets the default uv map to the mesh.
static std::shared_ptr<TriangleMesh> CreateBox(
double width = 1.0,
double height = 1.0,
double depth = 1.0,
bool create_uv_map = false,
bool map_texture_to_each_face = false);
/// Factory function to create a sphere mesh (TriangleMeshFactory.cpp)
/// The sphere with radius will be centered at (0, 0, 0).
/// Its axis is aligned with z-axis.
/// \param radius defines radius of the sphere.
/// \param resolution defines the resolution of the sphere. The longitudes
/// will be split into resolution segments (i.e. there are resolution + 1
/// latitude lines including the north and south pole). The latitudes will
/// be split into `2 * resolution segments (i.e. there are 2 * resolution
/// longitude lines.)
/// \param create_uv_map add default UV map to the mesh.
static std::shared_ptr<TriangleMesh> CreateSphere(
double radius = 1.0,
int resolution = 20,
bool create_uv_map = false);
/// Factory function to create a cylinder mesh (TriangleMeshFactory.cpp)
/// The axis of the cylinder will be from (0, 0, -height/2) to (0, 0,
/// height/2). The circle with radius will be split into
/// resolution segments. The height will be split into split
/// segments.
/// \param radius defines the radius of the cylinder.
/// \param height defines the height of the cylinder.
/// \param resolution defines that the circle will be split into resolution
/// segments.
/// \param split defines that the height will be split into split segments.
/// \param create_uv_map add default UV map to the mesh.
static std::shared_ptr<TriangleMesh> CreateCylinder(
double radius = 1.0,
double height = 2.0,
int resolution = 20,
int split = 4,
bool create_uv_map = false);
/// Factory function to create a cone mesh (TriangleMeshFactory.cpp)
/// The axis of the cone will be from (0, 0, 0) to (0, 0, height).
/// The circle with radius will be split into resolution
/// segments. The height will be split into split segments.
/// \param radius defines the radius of the cone.
/// \param height defines the height of the cone.
/// \param resolution defines that the circle will be split into resolution
/// segments.
/// \param split defines that the height will be split into split segments.
/// \param create_uv_map add default UV map to the mesh.
static std::shared_ptr<TriangleMesh> CreateCone(double radius = 1.0,
double height = 2.0,
int resolution = 20,
int split = 1,
bool create_uv_map = false);
/// Factory function to create a torus mesh (TriangleMeshFactory.cpp)
/// The torus will be centered at (0, 0, 0) and a radius of
/// torus_radius. The tube of the torus will have a radius of
/// tube_radius. The number of segments in radial and tubular direction are
/// radial_resolution and tubular_resolution respectively.
///
/// \param torus_radius defines the radius from the center of the torus to
/// the center of the tube.
/// \param tube_radius defines the radius of the torus tube.
/// \param radial_resolution defines the he number of segments along the
/// radial direction.
/// \param tubular_resolution defines the number of segments along the
/// tubular direction.
static std::shared_ptr<TriangleMesh> CreateTorus(
double torus_radius = 1.0,
double tube_radius = 0.5,
int radial_resolution = 30,
int tubular_resolution = 20);
/// Factory function to create an arrow mesh (TriangleMeshFactory.cpp)
/// The axis of the cone with cone_radius will be along the z-axis.
/// The cylinder with cylinder_radius is from
/// (0, 0, 0) to (0, 0, cylinder_height), and
/// the cone is from (0, 0, cylinder_height)
/// to (0, 0, cylinder_height + cone_height).
/// The cone will be split into resolution segments.
/// The cylinder_height will be split into cylinder_split
/// segments. The cone_height will be split into cone_split
/// segments.
//
/// \param cylinder_radius defines the radius of the cylinder.
/// \param cone_radius defines the radius of the cone.
/// \param cylinder_height defines the height of the cylinder. The cylinder
/// is from (0, 0, 0) to (0, 0, cylinder_height)
/// \param cone_height defines the height of the cone. The axis of the cone
/// will be from (0, 0, cylinder_height) to (0, 0, cylinder_height +
/// cone_height).
/// \param resolution defines the cone will be split into resolution
/// segments.
/// \param cylinder_split defines the cylinder_height will be split into
/// cylinder_split segments.
/// \param cone_split defines the cone_height will be split into cone_split
/// segments.
static std::shared_ptr<TriangleMesh> CreateArrow(
double cylinder_radius = 1.0,
double cone_radius = 1.5,
double cylinder_height = 5.0,
double cone_height = 4.0,
int resolution = 20,
int cylinder_split = 4,
int cone_split = 1);
/// Factory function to create a coordinate frame mesh
/// (TriangleMeshFactory.cpp).
/// arrows respectively. \p size is the length of the axes.
/// \param size defines the size of the coordinate frame.
/// \param origin defines the origin of the coordinate frame.
static std::shared_ptr<TriangleMesh> CreateCoordinateFrame(
double size = 1.0,
const Eigen::Vector3d &origin = Eigen::Vector3d(0.0, 0.0, 0.0));
/// Factory function to create a Mobius strip.
/// \param length_split defines the number of segments along the Mobius
/// strip.
/// \param width_split defines the number of segments along the width
/// of the Mobius strip.\param twists defines the number of twists of the
/// strip.
/// \param radius defines the radius of the Mobius strip.
/// \param flatness controls the height of the strip.
/// \param width controls the width of the Mobius strip.
/// \param scale is used to scale the entire Mobius strip.
static std::shared_ptr<TriangleMesh> CreateMobius(int length_split = 70,
int width_split = 15,
int twists = 1,
double radius = 1,
double flatness = 1,
double width = 1,
double scale = 1);
protected:
// Forward child class type to avoid indirect nonvirtual base
TriangleMesh(Geometry::GeometryType type) : MeshBase(type) {}
void FilterSmoothLaplacianHelper(
std::shared_ptr<TriangleMesh> &mesh,
const std::vector<Eigen::Vector3d> &prev_vertices,
const std::vector<Eigen::Vector3d> &prev_vertex_normals,
const std::vector<Eigen::Vector3d> &prev_vertex_colors,
const std::vector<std::unordered_set<int>> &adjacency_list,
double lambda_filter,
bool filter_vertex,
bool filter_normal,
bool filter_color) const;
/// \brief Function that computes for each edge in the triangle mesh and
/// passed as parameter edges_to_vertices the cot weight.
///
/// \param edges_to_vertices map from edge to vector of neighbouring
/// vertices.
/// \param min_weight minimum weight returned. Weights smaller than this
/// get clamped.
/// \return cot weight per edge.
std::unordered_map<Eigen::Vector2i,
double,
utility::hash_eigen<Eigen::Vector2i>>
ComputeEdgeWeightsCot(
const std::unordered_map<Eigen::Vector2i,
std::vector<int>,
utility::hash_eigen<Eigen::Vector2i>>
&edges_to_vertices,
double min_weight = std::numeric_limits<double>::lowest()) const;
public:
/// List of triangles denoted by the index of points forming the triangle.
std::vector<Eigen::Vector3i> triangles_;
/// Triangle normals.
std::vector<Eigen::Vector3d> triangle_normals_;
/// The set adjacency_list[i] contains the indices of adjacent vertices of
/// vertex i.
std::vector<std::unordered_set<int>> adjacency_list_;
/// List of uv coordinates per triangle.
std::vector<Eigen::Vector2d> triangle_uvs_;
struct Material {
struct MaterialParameter {
float f4[4] = {0};
MaterialParameter() {
f4[0] = 0;
f4[1] = 0;
f4[2] = 0;
f4[3] = 0;
}
MaterialParameter(const float v1,
const float v2,
const float v3,
const float v4) {
f4[0] = v1;
f4[1] = v2;
f4[2] = v3;
f4[3] = v4;
}
MaterialParameter(const float v1, const float v2, const float v3) {
f4[0] = v1;
f4[1] = v2;
f4[2] = v3;
f4[3] = 1;
}
MaterialParameter(const float v1, const float v2) {
f4[0] = v1;
f4[1] = v2;
f4[2] = 0;
f4[3] = 0;
}
explicit MaterialParameter(const float v1) {
f4[0] = v1;
f4[1] = 0;
f4[2] = 0;
f4[3] = 0;
}
static MaterialParameter CreateRGB(const float r,
const float g,
const float b) {
return {r, g, b, 1.f};
}
float r() const { return f4[0]; }
float g() const { return f4[1]; }
float b() const { return f4[2]; }
float a() const { return f4[3]; }
};
MaterialParameter baseColor;
float baseMetallic = 0.f;
float baseRoughness = 1.f;
float baseReflectance = 0.5f;
float baseClearCoat = 0.f;
float baseClearCoatRoughness = 0.f;
float baseAnisotropy = 0.f;
std::shared_ptr<Image> albedo;
std::shared_ptr<Image> normalMap;
std::shared_ptr<Image> ambientOcclusion;
std::shared_ptr<Image> metallic;
std::shared_ptr<Image> roughness;
std::shared_ptr<Image> reflectance;
std::shared_ptr<Image> clearCoat;
std::shared_ptr<Image> clearCoatRoughness;
std::shared_ptr<Image> anisotropy;
std::unordered_map<std::string, MaterialParameter> floatParameters;
std::unordered_map<std::string, Image> additionalMaps;
};
std::vector<std::pair<std::string, Material>> materials_;
/// List of material ids.
std::vector<int> triangle_material_ids_;
/// Textures of the image.
std::vector<Image> textures_;
};
} // namespace geometry
} // namespace open3d