image_framework_ymj/include/open3d/geometry/TriangleMesh.h
2024-12-06 16:25:16 +08:00

866 lines
40 KiB
C++
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ----------------------------------------------------------------------------
// - 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