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

259 lines
14 KiB
C++
Executable File

// ----------------------------------------------------------------------------
// - Open3D: www.open3d.org -
// ----------------------------------------------------------------------------
// Copyright (c) 2018-2023 www.open3d.org
// SPDX-License-Identifier: MIT
// ----------------------------------------------------------------------------
#pragma once
#include <memory>
#include "open3d/Macro.h"
#include "open3d/core/Tensor.h"
#include "open3d/t/geometry/PointCloud.h"
#include "open3d/t/geometry/TriangleMesh.h"
namespace open3d {
namespace t {
namespace geometry {
/// \class RaycastingScene
/// \brief A scene class with basic ray casting and closest point queries.
///
/// The RaycastingScene allows to compute ray intersections with triangle meshes
/// or compute the closest point on the surface of a mesh with respect to one
/// or more query points.
/// It builds an internal acceleration structure to speed up those queries.
///
/// This class supports only the CPU device.
class RaycastingScene {
public:
/// \brief Default Constructor.
RaycastingScene(int64_t nthreads = 0);
~RaycastingScene();
/// \brief Add a triangle mesh to the scene.
/// \param vertex_positions Vertices as Tensor of dim {N,3} and dtype float.
/// \param triangle_indices Triangles as Tensor of dim {M,3} and dtype
/// uint32_t. \return The geometry ID of the added mesh.
uint32_t AddTriangles(const core::Tensor &vertex_positions,
const core::Tensor &triangle_indices);
/// \brief Add a triangle mesh to the scene.
/// \param mesh A triangle mesh.
/// \return The geometry ID of the added mesh.
uint32_t AddTriangles(const TriangleMesh &mesh);
/// \brief Computes the first intersection of the rays with the scene.
/// \param rays A tensor with >=2 dims, shape {.., 6}, and Dtype Float32
/// describing the rays.
/// {..} can be any number of dimensions, e.g., to organize rays for
/// creating an image the shape can be {height, width, 6}.
/// The last dimension must be 6 and has the format [ox, oy, oz, dx, dy, dz]
/// with [ox,oy,oz] as the origin and [dx,dy,dz] as the direction. It is not
/// necessary to normalize the direction but the returned hit distance uses
/// the length of the direction vector as unit.
/// \param nthreads The number of threads to use. Set to 0 for automatic.
/// \return The returned dictionary contains:
/// - \b t_hit A tensor with the distance to the first hit. The
/// shape is {..}. If there is no intersection the hit distance
/// is \a inf .
/// - \b geometry_ids A tensor with the geometry IDs. The shape is
/// {..}. If there is no intersection the ID is \a INVALID_ID .
/// - \b primitive_ids A tensor with the primitive IDs, which
/// corresponds to the triangle index. The shape is {..}.
/// If there is no intersection the ID is \a INVALID_ID .
/// - \b primitive_uvs A tensor with the barycentric coordinates of
/// the hit points within the hit triangles. The shape is {.., 2}.
/// - \b primitive_normals A tensor with the normals of the hit
/// triangles. The shape is {.., 3}.
std::unordered_map<std::string, core::Tensor> CastRays(
const core::Tensor &rays, const int nthreads = 0);
/// \brief Checks if the rays have any intersection with the scene.
/// \param rays A tensor with >=2 dims, shape {.., 6}, and Dtype Float32
/// describing the rays.
/// {..} can be any number of dimensions, e.g., to organize rays for
/// creating an image the shape can be {height, width, 6}.
/// The last dimension must be 6 and has the format [ox, oy, oz, dx, dy, dz]
/// with [ox,oy,oz] as the origin and [dx,dy,dz] as the direction. It is not
/// necessary to normalize the direction.
/// \param tnear The tnear offset for the rays. The default is 0.
/// \param tfar The tfar value for the ray. The default is infinity.
/// \param nthreads The number of threads to use. Set to 0 for automatic.
/// \return A boolean tensor which indicates if the ray is occluded by the
/// scene (true) or not (false).
core::Tensor TestOcclusions(
const core::Tensor &rays,
const float tnear = 0.f,
const float tfar = std::numeric_limits<float>::infinity(),
const int nthreads = 0);
/// \brief Computes the number of intersection of the rays with the scene.
/// \param rays A tensor with >=2 dims, shape {.., 6}, and Dtype Float32
/// describing the rays.
/// {..} can be any number of dimensions, e.g., to organize rays for
/// creating an image the shape can be {height, width, 6}.
/// The last dimension must be 6 and has the format [ox, oy, oz, dx, dy, dz]
/// with [ox,oy,oz] as the origin and [dx,dy,dz] as the direction. It is not
/// necessary to normalize the direction.
/// \param nthreads The number of threads to use. Set to 0 for automatic.
/// \return A tensor with the number of intersections. The shape is {..}.
core::Tensor CountIntersections(const core::Tensor &rays,
const int nthreads = 0);
/// \brief Lists the intersections of the rays with the scene
/// \param rays A tensor with >=2 dims, shape {.., 6}, and Dtype Float32
/// describing the rays; {..} can be any number of dimensions.
/// The last dimension must be 6 and has the format [ox, oy, oz, dx, dy, dz]
/// with [ox,oy,oz] as the origin and [dx,dy,dz] as the direction. It is not
/// necessary to normalize the direction although it should be normalised if
/// t_hit is to be calculated in coordinate units.
/// \param nthreads The number of threads to use. Set to 0 for automatic.
/// \return The returned dictionary contains: ///
/// - \b ray_splits A tensor with ray intersection splits. Can be
/// used to iterate over all intersections for each ray. The shape
/// is {num_rays + 1}.
/// - \b ray_ids A tensor with ray IDs. The shape is
/// {num_intersections}.
/// - \b t_hit A tensor with the distance to the hit. The shape is
/// {num_intersections}.
/// - \b geometry_ids A tensor with the geometry IDs. The shape is
/// {num_intersections}.
/// - \b primitive_ids A tensor with the primitive IDs, which
/// corresponds to the triangle index. The shape is
/// {num_intersections}.
/// - \b primitive_uvs A tensor with the barycentric coordinates of
/// the intersection points within the triangles. The shape is
/// {num_intersections, 2}.
std::unordered_map<std::string, core::Tensor> ListIntersections(
const core::Tensor &rays, const int nthreads = 0);
/// \brief Computes the closest points on the surfaces of the scene.
/// \param query_points A tensor with >=2 dims, shape {.., 3} and Dtype
/// Float32 describing the query points. {..} can be any number of
/// dimensions, e.g., to organize the query_point to create a 3D grid the
/// shape can be {depth, height, width, 3}. The last dimension must be 3 and
/// has the format [x, y, z].
/// \param nthreads The number of threads to use. Set to 0 for automatic.
/// \return The returned dictionary contains:
/// - \b points A tensor with the closest surface points. The shape
/// is {..}.
/// - \b geometry_ids A tensor with the geometry IDs. The shape is
/// {..}.
/// - \b primitive_ids A tensor with the primitive IDs, which
/// corresponds to the triangle index. The shape is {..}.
/// - \b primitive_uvs A tensor with the barycentric coordinates of
/// the closest points within the triangles. The shape is {.., 2}.
/// - \b primitive_normals A tensor with the normals of the
/// closest triangle . The shape is {.., 3}.
std::unordered_map<std::string, core::Tensor> ComputeClosestPoints(
const core::Tensor &query_points, const int nthreads = 0);
/// \brief Computes the distance to the surface of the scene.
/// \param query_points A tensor with >=2 dims, shape {.., 3} and Dtype
/// Float32 describing the query points. {..} can be any number of
/// dimensions, e.g., to organize the query_point to create a 3D grid the
/// shape can be {depth, height, width, 3}. The last dimension must be 3 and
/// has the format [x, y, z].
/// \param nthreads The number of threads to use. Set to 0 for automatic.
/// \return A tensor with the distances to the
/// surface. The shape is {..}.
core::Tensor ComputeDistance(const core::Tensor &query_points,
const int nthreads = 0);
/// \brief Computes the signed distance to the surface of the scene.
///
/// This function computes the signed distance to the meshes in the scene.
/// The function assumes that all meshes are watertight and that there are
/// no intersections between meshes, i.e., inside and outside must be well
/// defined. The function determines the sign of the distance by counting
/// the intersections of a rays starting at the query points.
///
/// \param query_points A tensor with >=2 dims, shape {.., 3} and Dtype
/// Float32 describing the query points. {..} can be any number of
/// dimensions, e.g., to organize the query_point to create a 3D grid the
/// shape can be {depth, height, width, 3}. The last dimension must be 3 and
/// has the format [x, y, z].
/// \param nthreads The number of threads to use. Set to 0 for automatic.
/// \param nsamples The number of rays used for determining the inside.
/// This must be an odd number. The default is 1. Use a higher value if you
/// notice sign flipping, which can occur when rays hit exactly an edge or
/// vertex in the scene.
///
/// \return A tensor with the signed distances to
/// the surface. The shape is
/// {..}. Negative distances mean a point is inside a closed surface.
core::Tensor ComputeSignedDistance(const core::Tensor &query_points,
const int nthreads = 0,
const int nsamples = 1);
/// \brief Computes the occupancy at the query point positions.
///
/// This function computes whether the query points are inside or outside.
/// The function assumes that all meshes are watertight and that there are
/// no intersections between meshes, i.e., inside and outside must be well
/// defined. The function determines if a point is inside by counting the
/// intersections of a rays starting at the query points.
///
/// \param query_points A tensor with >=2 dims, shape {.., 3} and Dtype
/// Float32 describing the query_points.
/// {..} can be any number of dimensions, e.g., to
/// organize the query_point to create a 3D grid the shape can be
/// {depth, height, width, 3}.
/// The last dimension must be 3 and has the format [x, y, z].
/// \param nthreads The number of threads to use. Set to 0 for automatic.
/// \param nsamples The number of rays used for determining the inside.
/// This must be an odd number. The default is 1. Use a higher value if you
/// notice errors in the occupancy values. Errors can occur when rays hit
/// exactly an edge or vertex in the scene.
///
/// \return A tensor with the occupancy values. The shape is {..}. Values
/// are either 0 or 1. A point is occupied or inside if the value is 1.
core::Tensor ComputeOccupancy(const core::Tensor &query_points,
const int nthreads = 0,
const int nsamples = 1);
/// \brief Creates rays for the given camera parameters.
///
/// \param intrinsic_matrix The upper triangular intrinsic matrix with
/// shape {3,3}.
/// \param extrinsic_matrix The 4x4 world to camera SE(3) transformation
/// matrix. \param width_px The width of the image in pixels. \param
/// height_px The height of the image in pixels. \return A tensor of shape
/// {height_px, width_px, 6} with the rays.
static core::Tensor CreateRaysPinhole(const core::Tensor &intrinsic_matrix,
const core::Tensor &extrinsic_matrix,
int width_px,
int height_px);
/// \brief Creates rays for the given camera parameters.
///
/// \param fov_deg The horizontal field of view in degree.
/// \param center The point the camera is looking at with shape {3}.
/// \param eye The position of the camera with shape {3}.
/// \param up The up-vector with shape {3}.
/// \param width_px The width of the image in pixels.
/// \param height_px The height of the image in pixels.
/// \return A tensor of shape {height_px, width_px, 6} with the rays.
static core::Tensor CreateRaysPinhole(double fov_deg,
const core::Tensor &center,
const core::Tensor &eye,
const core::Tensor &up,
int width_px,
int height_px);
/// \brief The value for invalid IDs.
static uint32_t INVALID_ID();
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace geometry
} // namespace t
} // namespace open3d