Broad Phase

Broad Phase

class BroadPhase;

Inheritance diagram for ipc::BroadPhase:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "1" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase" fillcolor="#BFBFBF"] "2" [label="ipc::BruteForce" tooltip="ipc::BruteForce"] "3" [label="ipc::HashGrid" tooltip="ipc::HashGrid"] "4" [label="ipc::LBVH" tooltip="ipc::LBVH"] "5" [label="ipc::SpatialHash" tooltip="ipc::SpatialHash"] "6" [label="ipc::SweepAndPrune" tooltip="ipc::SweepAndPrune"] "7" [label="ipc::SweepAndTiniestQueue" tooltip="ipc::SweepAndTiniestQueue"] "8" [label="ipc::cuda::LBVH" tooltip="ipc::cuda::LBVH"] "2" -> "1" [dir=forward tooltip="public-inheritance"] "3" -> "1" [dir=forward tooltip="public-inheritance"] "4" -> "1" [dir=forward tooltip="public-inheritance"] "5" -> "1" [dir=forward tooltip="public-inheritance"] "6" -> "1" [dir=forward tooltip="public-inheritance"] "7" -> "1" [dir=forward tooltip="public-inheritance"] "8" -> "1" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::BroadPhase:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "1" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase" fillcolor="#BFBFBF"] "2" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" -> "2" [dir=forward tooltip="usage"] }

Base class for broad phase collision detection methods.

Subclassed by ipc::BruteForce, ipc::HashGrid, ipc::LBVH, ipc::SpatialHash, ipc::SweepAndPrune, ipc::SweepAndTiniestQueue, ipc::cuda::LBVH

Public Functions

inline virtual ~BroadPhase();
virtual std::string name() const = 0;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void clear();

Clear any built data.

void detect_collision_candidates(Candidates& candidates) const;

Detect all collision candidates needed for a given dimensional simulation.

Parameters:
Candidates &candidates

The detected collision candidates (cleared first).

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const
   
 = 0;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions (cleared first).

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const
   
 = 0;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions (cleared first).

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const
   
 = 0;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions (cleared first).

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const
   
 = 0;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions (cleared first).

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const
   
 = 0;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections (cleared first).

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const
   
 = 0;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions (cleared first).

Public Members

CollisionFilter can_vertices_collide;

Filter for determining if two vertices can collide.

Protected Functions

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

void compute_mesh_aabb(Eigen::Ref<Eigen::Array3d> mesh_min,
    
Eigen::Ref<Eigen::Array3d> mesh_max) const;

Compute the axis-aligned bounding box (AABB) of the mesh.

Parameters:
Eigen::Ref<Eigen::Array3d> mesh_min

[out] Minimum corner of the mesh AABB.

Eigen::Ref<Eigen::Array3d> mesh_max

[out] Maximum corner of the mesh AABB.

virtual bool can_edge_vertex_collide(size_t ei, size_t vi) const;
virtual bool can_edges_collide(size_t eai, size_t ebi) const;
virtual bool can_face_vertex_collide(size_t fi, size_t vi) const;
virtual bool can_edge_face_collide(size_t ei, size_t fi) const;
virtual bool can_faces_collide(size_t fai, size_t fbi) const;

Protected Attributes

AABBs vertex_boxes;

AABBs for the vertices.

AABBs edge_boxes;

AABBs for the edges.

AABBs face_boxes;

AABBs for the faces.

uint8_t dim = 0;

Dimension of the simulation for which the broad phase was built.

Brute Force

class BruteForce : public ipc::BroadPhase;

Inheritance diagram for ipc::BruteForce:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::BruteForce" tooltip="ipc::BruteForce" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::BruteForce:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::BruteForce" tooltip="ipc::BruteForce" fillcolor="#BFBFBF"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Brute force broad phase collision detection.

Public Functions

BruteForce() = default;
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

Private Functions

template <typename Candidate, bool triangular = false>
void detect_candidates(const AABBs& boxes0, const AABBs& boxes1,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates) const;

Detect candidates for collisions between two sets of boxes.

Template Parameters:
typename Candidate

Type of the candidate.

bool triangular = false

Whether to consider (i, j) and (j, i) as the same.

Parameters:
const AABBs &boxes0

[in] First set of boxes.

const AABBs &boxes1

[in] Second set of boxes.

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two primitives can collide given their ids.

std::vector<Candidate> &candidates

[out] The candidate collisions.

Hash Grid

class HashGrid : public ipc::BroadPhase;

Inheritance diagram for ipc::HashGrid:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::HashGrid" tooltip="ipc::HashGrid" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::HashGrid:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::HashGrid" tooltip="ipc::HashGrid" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Hash grid broad phase collision detection.

Public Functions

HashGrid() = default;
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

inline virtual void clear() override;

Clear the hash grid.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

inline double cell_size() const;
inline const Eigen::Array3i& grid_size() const;
inline const Eigen::Array3d& domain_min() const;
inline const Eigen::Array3d& domain_max() const;
virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Protected Functions

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces) override;

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

void resize(Eigen::ConstRef<Eigen::Array3d> domain_min,
    
Eigen::ConstRef<Eigen::Array3d> domain_max, double cell_size);
void insert_boxes();
void insert_boxes(
    
const AABBs& boxes, std::vector<HashItem>& items) const;
void insert_box(const AABB& aabb, const long id,
    
std::vector<HashItem>& items) const;

Add an AABB of the extents to the hash grid.

inline long hash(int x, int y, int z) const;

Create the hash of a cell location.

Protected Attributes

double m_cell_size = -1;
Eigen::Array3i m_grid_size;
Eigen::Array3d m_domain_min;
Eigen::Array3d m_domain_max;
std::vector<HashItem> vertex_items;
std::vector<HashItem> edge_items;
std::vector<HashItem> face_items;

Private Functions

template <typename Candidate>
void detect_candidates(const std::vector<HashItem>& items0,
    
const std::vector<HashItem>& items1, const AABBs& boxes0,
    
const AABBs& boxes1,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates) const;

Find the candidate collisions between two sets of items.

Template Parameters:
typename Candidate

The type of collision candidate.

Parameters:
const std::vector<HashItem> &items0

[in] First set of items.

const std::vector<HashItem> &items1

[in] Second set of items.

const AABBs &boxes0

[in] First set’s boxes.

const AABBs &boxes1

[in] Second set’s boxes.

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two items can collide.

std::vector<Candidate> &candidates

[out] The candidate collisions.

template <typename Candidate>
void detect_candidates(const std::vector<HashItem>& items,
    
const AABBs& boxes,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates) const;

Find the candidate collisions among a set of items.

Template Parameters:
typename Candidate

The type of collision candidate.

Parameters:
const std::vector<HashItem> &items

[in] The set of items.

const AABBs &boxes

[in] The items’ boxes.

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two items can collide.

std::vector<Candidate> &candidates

[out] The candidate collisions.

Spatial Hash

class SpatialHash : public ipc::BroadPhase;

Inheritance diagram for ipc::SpatialHash:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::SpatialHash" tooltip="ipc::SpatialHash" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::SpatialHash:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::SpatialHash" tooltip="ipc::SpatialHash" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Spatial hash broad phase collision detection.

Public Functions

SpatialHash();
~SpatialHash();
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

inline virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0) override;

Build the spatial hash for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

inline virtual void build(
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0) override;

Build the spatial hash for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

inline virtual void build(const AABBs& _vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const uint8_t _dim) override;

Build the spatial hash from vertex boxes.

Parameters:
const AABBs &_vertex_boxes

AABB boxes for each vertex.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t _dim

Dimension of the simulation (2D or 3D)

void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, double inflation_radius,
    
double voxel_size);

Build the spatial hash for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius

Radius of inflation around all elements.

double voxel_size

Size of the voxels used in the spatial hash.

void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, double inflation_radius,
    
double voxel_size);

Build the spatial hash for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius

Radius of inflation around all elements.

double voxel_size

Size of the voxels used in the spatial hash.

void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim,
    
double voxel_size);

Build the spatial hash from vertex boxes.

Parameters:
const AABBs &vertex_boxes

AABB boxes for each vertex.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

double voxel_size

Size of the voxels used in the spatial hash.

virtual void clear() override;

Clear any built data.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Private Functions

void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, double voxel_size);
int locate_voxel_index(Eigen::ConstRef<Eigen::Array3d> p) const;
Eigen::Array3i locate_voxel_axis_index(
    
Eigen::ConstRef<Eigen::Array3d> p) const;
void locate_box_voxel_axis_index(Eigen::Array3d min_corner,
    
Eigen::Array3d max_corner, Eigen::Ref<Eigen::Array3i> min_index,
    
Eigen::Ref<Eigen::Array3i> max_index,
    
const double inflation_radius = 0) const;
int voxel_axis_index_to_voxel_index(
    
Eigen::ConstRef<Eigen::Array3i> voxel_axis_index) const;
int voxel_axis_index_to_voxel_index(int ix, int iy, int iz) const;

Private Members

Eigen::Array3d left_bottom_corner;

The left bottom corner of the world bounding box.

Eigen::Array3d right_top_corner;

The right top corner of the world bounding box.

Eigen::Array3i voxel_count;

The number of voxels in each dimension.

std::unique_ptr<Impl> impl;

Pointer to the implementation details.

double one_div_voxel_size = -1;

1.0 / voxel_size

int voxel_count_0x1 = -1;

The number of voxels in the first two dimensions.

struct Impl;

Public Functions

inline void fill_voxel_to_primitives();
inline void clear();
inline bool is_vertex_index(int idx) const;

Check if primitive index refers to a vertex.

inline bool is_edge_index(int idx) const;

Check if primitive index refers to an edge.

inline bool is_triangle_index(int idx) const;

Check if primitive index refers to a triangle.

inline int to_edge_index(int idx) const;

Convert a primitive index to an edge index.

inline int to_triangle_index(int idx) const;

Convert a primitive index to a triangle index.

inline void query_point_for_points(
    
int vi, unordered_set<int>& vert_ids) const;
inline void query_point_for_edges(
    
int vi, unordered_set<int>& edge_ids) const;
inline void query_point_for_triangles(
    
int vi, unordered_set<int>& tri_ids) const;
inline void query_edge_for_edges(
    
int eai, unordered_set<int>& edge_ids) const;
inline void query_edge_for_triangles(
    
int ei, unordered_set<int>& tri_ids) const;
inline void query_triangle_for_triangles(
    
int ti, unordered_set<int>& tri_ids) const;

Public Members

unordered_map<int, std::vector<int>> voxel_to_primitives;

Map from voxel index to the primitive indices it contains.

std::vector<std::vector<int>> point_to_voxels;

Map from point index to the voxel indices it occupies.

std::vector<std::vector<int>> edge_to_voxels;

Map from edge index to the voxel indices it occupies.

std::vector<std::vector<int>> face_to_voxels;

Map from face index to the voxel indices it occupies.

int edge_start_ind = -1;

The index of the first edge in voxel_occupancies.

int tri_start_ind = -1;

The index of the first triangle in voxel_occupancies.

LBVH —

class LBVH : public ipc::BroadPhase;

Inheritance diagram for ipc::LBVH:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::LBVH" tooltip="ipc::LBVH" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::LBVH:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::LBVH" tooltip="ipc::LBVH" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Linear Bounding Volume Hierarchy (LBVH) broad phase collision detection.

Public Types

using Nodes = std::vector<Node, DefaultInitAllocator<Node>>;
using MortonCodeElements = std::vector<MortonCodeElement,
    DefaultInitAllocator<MortonCodeElement>>;
using RightmostLeaves
   
 = std::vector<int32_t, DefaultInitAllocator<int32_t>>;

For each node, the index of the rightmost leaf reachable from it.

Used to skip subtrees during triangular (self-collision) traversal.

Public Functions

LBVH();
~LBVH();
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void clear() override;

Clear any built data.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

inline const Nodes& vertex_nodes() const;
inline const Nodes& edge_nodes() const;
inline const Nodes& face_nodes() const;
virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Public Members

Eigen::Array3d min;
Eigen::Array3d max;

Public Static Attributes

static constexpr index_t INVALID_ID = 0xFFFFFFFF;

Protected Functions

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces) override;

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

void init_bvh(const AABBs& boxes, Nodes& lbvh,
    
RightmostLeaves& rightmost_leaves) const;

Initialize a LBVH from a set of boxes.

Parameters:
const AABBs &boxes

[in] Set of boxes to initialize the LBVH with.

Nodes &lbvh

[out] The LBVH to initialize.

RightmostLeaves &rightmost_leaves

[out] For each node, the rightmost leaf index reachable. Values are the leaf’s position in the Morton-sorted leaf array from [0, n) where n is the number of primitives.

inline bool has_vertices() const;
inline bool has_edges() const;
inline bool has_faces() const;
virtual bool can_edge_vertex_collide(
    
size_t ei, size_t vi) const override;
virtual bool can_edges_collide(
    
size_t eai, size_t ebi) const override;
virtual bool can_face_vertex_collide(
    
size_t fi, size_t vi) const override;
virtual bool can_edge_face_collide(
    
size_t ei, size_t fi) const override;
virtual bool can_faces_collide(
    
size_t fai, size_t fbi) const override;

Protected Attributes

Nodes vertex_bvh;

BVH containing the vertices.

RightmostLeaves vertex_rightmost_leaves;

Rightmost leaf indices for vertex BVH (used for self-collision skip).

Values are from [0, n) where n is the number of primitives. Values are the leaf’s position in the Morton-sorted leaf array.

Nodes edge_bvh;

BVH containing the edges.

RightmostLeaves edge_rightmost_leaves;

Rightmost leaf indices for edge BVH (used for self-collision skip).

Values are from [0, n) where n is the number of primitives. Values are the leaf’s position in the Morton-sorted leaf array.

Nodes face_bvh;

BVH containing the faces.

RightmostLeaves face_rightmost_leaves;

Rightmost leaf indices for face BVH (used for self-collision skip).

Values are from [0, n) where n is the number of primitives. Values are the leaf’s position in the Morton-sorted leaf array.

Protected Static Functions

template <typename Candidate, bool swap_order = false,
    bool triangular = false>
static void detect_candidates(const Nodes& source,
    
const Nodes& target, const RightmostLeaves& rightmost_leaves,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates);

Detect candidate collisions between a LBVH and a sets of boxes.

Template Parameters:
typename Candidate

Type of candidate collision.

bool swap_order = false

Whether to swap the order of box id with the LBVH id when adding to the candidates.

bool triangular = false

Whether to consider (i, j) and (j, i) as the same.

Parameters:
const Nodes &source

[in] The LBVH to traverse.

const Nodes &target

[in] The LBVH to traverse.

const RightmostLeaves &rightmost_leaves

[in] The rightmost leaf indices for the target LBVH (used for self-collision skip).

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two primitives can collide given their ids.

std::vector<Candidate> &candidates

[out] The candidate collisions.

template <typename Candidate>
static inline void detect_candidates(const Nodes& source_and_target,
    
const RightmostLeaves& rightmost_leaves,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates);

Detect candidate collisions between a single LBVH and itself.

Template Parameters:
typename Candidate

Type of candidate collision.

Parameters:
const Nodes &source_and_target

[in] The LBVH to traverse.

const RightmostLeaves &rightmost_leaves

[in] The rightmost leaf indices for the LBVH (used for self-collision skip).

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two primitives can collide given their ids.

std::vector<Candidate> &candidates

[out] The candidate collisions.

Private Types

using HostConstructionInfo = ConstructionInfo<std::atomic<int>>;
using ConstructionInfos = std::vector<HostConstructionInfo,
    DefaultInitAllocator<HostConstructionInfo>>;
using EdgeIndices = std::vector<std::array<index_t, 2>,
    DefaultInitAllocator<std::array<index_t, 2>>>;
using FaceIndices = std::vector<std::array<index_t, 3>,
    DefaultInitAllocator<std::array<index_t, 3>>>;

Private Members

EdgeIndices edge_vertex_ids;

Edge vertices in the original mesh order.

FaceIndices face_vertex_ids;

Face vertices in the original mesh order.

struct ipc::LBVH mesh_aabb;

The axis-aligned bounding box of the entire mesh.

template <typename Counter> struct ConstructionInfo;

Per-internal-node scratch for the bottom-up build.

See also

ipc::details::build_hierarchy_from_leaf

Template Parameters:
typename Counter

The visitation counter’s type: std::atomic<int> here, and a plain int for the device build in ipc::cuda::LBVH, where atomicAdd() supplies the atomicity.

Public Members

int left_range;

Left range endpoint passed up by the left child.

int right_range;

Right range endpoint passed up by the right child.

Counter visitation_count;

Number of threads that arrived at this node.

struct MortonCodeElement;

Public Members

uint64_t morton_code;

Key for sorting.

size_t box_id;

Pointer into boxes buffer.

struct Node;

Public Functions

inline bool is_inner() const;

Check if this node is an inner node.

inline bool is_leaf() const;

Check if this node is a leaf node.

inline bool is_valid() const;

Check if this node is valid.

inline bool intersects(const Node& other) const;

Check if this node’s AABB intersects with another node’s AABB.

Public Members

Eigen::Array3f aabb_min;

The min corner of the AABB.

Eigen::Array3f aabb_max;

The max corner of the AABB.

Public Static Attributes

static constexpr int32_t INVALID_POINTER = 0x0;

Sweep and Prune

class SweepAndPrune : public ipc::BroadPhase;

Inheritance diagram for ipc::SweepAndPrune:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::SweepAndPrune" tooltip="ipc::SweepAndPrune" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::SweepAndPrune:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::SweepAndPrune" tooltip="ipc::SweepAndPrune" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Sweep and Prune broad phase collision detection.

Public Functions

SweepAndPrune();
~SweepAndPrune();
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
double inflation_radius = 0) override;

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
double inflation_radius = 0) override;

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertex positions

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const uint8_t dim) override;

Build the broad phase from precomputed AABBs.

Parameters:
const AABBs &vertex_boxes

Precomputed vertex AABBs

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void clear() override;

Clear any built data.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Protected Functions

virtual bool can_edge_vertex_collide(
    
size_t ei, size_t vi) const override;
virtual bool can_edges_collide(
    
size_t eai, size_t ebi) const override;
virtual bool can_face_vertex_collide(
    
size_t fi, size_t vi) const override;
virtual bool can_edge_face_collide(
    
size_t ei, size_t fi) const override;
virtual bool can_faces_collide(
    
size_t fai, size_t fbi) const override;

Protected Attributes

std::unique_ptr<Boxes> boxes;
mutable int vv_sort_axis = 0;
mutable int ev_sort_axis = 0;
mutable int ee_sort_axis = 0;
mutable int fv_sort_axis = 0;
mutable int ef_sort_axis = 0;
mutable int ff_sort_axis = 0;
struct Boxes;

Public Functions

~Boxes() = default;

Public Members

std::vector<scalable_ccd::AABB> vertices;
std::vector<scalable_ccd::AABB> edges;
std::vector<scalable_ccd::AABB> faces;

Sweep and Tiniest Queue

Requires CUDA (IPC_TOOLKIT_WITH_CUDA).

class SweepAndTiniestQueue : public ipc::BroadPhase;

Inheritance diagram for ipc::SweepAndTiniestQueue:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::SweepAndTiniestQueue" tooltip="ipc::SweepAndTiniestQueue" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::SweepAndTiniestQueue:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::SweepAndTiniestQueue" tooltip="ipc::SweepAndTiniestQueue" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Sweep and Tiniest Queue broad phase collision detection.

Public Functions

SweepAndTiniestQueue();
~SweepAndTiniestQueue();
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
double inflation_radius = 0) override;

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
double inflation_radius = 0) override;

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertex positions

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const uint8_t dim) override;

Build the broad phase from precomputed AABBs.

Parameters:
const AABBs &vertex_boxes

Precomputed vertex AABBs

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void clear() override;

Clear any built data.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Private Functions

virtual bool can_edge_vertex_collide(
    
size_t ei, size_t vi) const override;
virtual bool can_edges_collide(
    
size_t eai, size_t ebi) const override;
virtual bool can_face_vertex_collide(
    
size_t fi, size_t vi) const override;
virtual bool can_edge_face_collide(
    
size_t ei, size_t fi) const override;
virtual bool can_faces_collide(
    
size_t fai, size_t fbi) const override;

Private Members

std::unique_ptr<Boxes> boxes;

LBVH (CUDA)

Requires CUDA (IPC_TOOLKIT_WITH_CUDA).

class LBVH : public ipc::BroadPhase;

Inheritance diagram for ipc::cuda::LBVH:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::cuda::LBVH" tooltip="ipc::cuda::LBVH" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::cuda::LBVH:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::cuda::LBVH" tooltip="ipc::cuda::LBVH" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

GPU Linear Bounding Volume Hierarchy (LBVH) broad phase.

A first-class GPU counterpart to ipc::LBVH: it builds the vertex/edge/face AABBs and their BVHs, and runs the traversal and mesh-connectivity filtering, entirely on the device. Construction uses Morton codes + the Apetrei [2014] single-pass bottom-up build and reuses the 32-byte ipc::LBVH::Node layout, so the device tree can be copied back to the host and validated against &#8212; or traversed by &#8212; the CPU code. The build, the scalar descent, and the shared-vertex exclusion are the same ipc::details functions ipc::LBVH runs; only the parallel launches, the sort, and the atomics are CUDA’s.

Detection runs the BVH descent (AABB overlap + triangular dedup) and the connectivity (shared-vertex) exclusion on the device. The user vertex filter (can_vertices_collide) is honored on the device only when it is the default accept-all filter; a non-trivial filter is applied on the host while materializing the device-emitted (connectivity-filtered) candidates. Either way the output matches the CPU ipc::LBVH exactly for any filter.

All device-side primitive and vertex ids are 32-bit, independent of ipc::index_t: ipc::LBVH::Node stores its primitive id as an int32_t, which already caps every LBVH at 2^31 - 1 primitives, and the connectivity and candidate buffers use the same width so a downstream kernel reads one consistent id type (see DeviceCandidateView).

The detect_*() methods are const, as the BroadPhase interface requires, but share device buffers; concurrent calls on one object are serialized by an internal mutex. Device memory is retained across clear() and build() (the candidate buffers keep their high-water-mark capacity so a per-frame call allocates nothing) and released by the destructor.

Public Functions

LBVH();
~LBVH();
LBVH(LBVH&& other) noexcept;

Move; the moved-from object is left cleared and usable.

LBVH& operator=(LBVH&& other) noexcept;

Move-assign; the moved-from object is left cleared and usable.

LBVH(const LBVH&) = delete;
LBVH& operator=(const LBVH&) = delete;
inline virtual std::string name() const override;

Get the name of the broad phase method.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0) override;

Build the broad phase for static collision detection.

The vertex boxes and everything after them are built on the device.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions (rowwise, |V| × 2 or |V| × 3).

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges.

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces.

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0) override;

Build the broad phase for continuous collision detection.

The vertex boxes and everything after them are built on the device.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertex positions (rowwise).

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertex positions (rowwise).

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges.

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces.

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void clear() override;

Clear any built data. Device memory is retained for reuse.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions (cleared first).

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions (cleared first).

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions (cleared first).

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions (cleared first).

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections (cleared first).

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions (cleared first).

DeviceCandidateView detect_vertex_vertex_candidates_device() const;
DeviceCandidateView detect_edge_vertex_candidates_device() const;
DeviceCandidateView detect_edge_edge_candidates_device() const;
DeviceCandidateView detect_face_vertex_candidates_device() const;
DeviceCandidateView detect_edge_face_candidates_device() const;
DeviceCandidateView detect_face_face_candidates_device() const;
size_t num_vertex_nodes() const;

Number of nodes in the vertex BVH (2 * n_leaves - 1, or 0).

size_t num_edge_nodes() const;

Number of nodes in the edge BVH (2 * n_leaves - 1, or 0).

size_t num_face_nodes() const;

Number of nodes in the face BVH (2 * n_leaves - 1, or 0).

void vertex_nodes_to_host(ipc::LBVH::Nodes& nodes,
    
ipc::LBVH::RightmostLeaves& rightmost_leaves) const;

Copy the vertex BVH back to the host.

void edge_nodes_to_host(ipc::LBVH::Nodes& nodes,
    
ipc::LBVH::RightmostLeaves& rightmost_leaves) const;

Copy the edge BVH back to the host.

void face_nodes_to_host(ipc::LBVH::Nodes& nodes,
    
ipc::LBVH::RightmostLeaves& rightmost_leaves) const;

Copy the face BVH back to the host.

Protected Functions

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces) override;

Build the device trees from BroadPhase::vertex_boxes.

Reached through the inherited BroadPhase::build(const AABBs&, edges,

faces, dim), which has copied the caller’s boxes into vertex_boxes. The boxes are uploaded and then, as in

ipc::LBVH, cleared from the host: the device trees make them redundant.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges.

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces.

virtual bool can_edge_vertex_collide(
    
size_t ei, size_t vi) const override;
virtual bool can_edges_collide(
    
size_t eai, size_t ebi) const override;
virtual bool can_face_vertex_collide(
    
size_t fi, size_t vi) const override;
virtual bool can_edge_face_collide(
    
size_t ei, size_t fi) const override;
virtual bool can_faces_collide(
    
size_t fai, size_t fbi) const override;

Private Functions

Impl& impl() const;

The implementation, created on first use.

A moved-from object hands its Impl over and is left with none; rather than guard every method against that, this re-seeds it on demand, so a moved-from object behaves exactly like a cleared one. Allocating here instead of in the move is what lets the move be noexcept. Mutable because the const detect_*() methods, which the BroadPhase interface requires, do use (and mutate) the device buffers; see the class comment.

Private Members

mutable std::unique_ptr<Impl> m_impl;

See impl().

struct DeviceCandidateView;

Non-owning view of device-resident candidate pairs (SoA).

The pointers address device memory owned by this LBVH and stay valid until the next detect_*() or detect_*_device() call of the SAME candidate type (both variants share one buffer per type), or until clear(), build(), or destruction. The ids are int32_t, not index_t: see the class comment.

Public Members

const int32_t* a = nullptr;

Device pointer to the first ids.

const int32_t* b = nullptr;

Device pointer to the second ids.

size_t size = 0;

Number of candidate pairs.

AABB

class AABB;

Axis aligned bounding-box of some type.

Public Functions

AABB() = default;
AABB(Eigen::ConstRef<ArrayMax3d> min,
    
Eigen::ConstRef<ArrayMax3d> max);
inline AABB(const AABB& aabb1, const AABB& aabb2);
inline AABB(
    
const AABB& aabb1, const AABB& aabb2, const AABB& aabb3);
bool intersects(const AABB& other) const;

Check if another AABB intersects with this one.

Parameters:
const AABB &other

The other AABB.

Returns:

If the two AABBs intersect.

Public Members

Eigen::Array3d min;

Minimum corner of the AABB.

Eigen::Array3d max;

Maximum corner of the AABB.

std::array<index_t, 3> vertex_ids;

Vertex IDs attached to the AABB.

Public Static Functions

static AABB from_point(Eigen::ConstRef<VectorMax3d> p,
    
const double inflation_radius = 0);

Construct an AABB for a static point.

Parameters:
Eigen::ConstRef<VectorMax3d> p

The point’s position.

const double inflation_radius = 0

Radius of a sphere around the point which the AABB encloses.

Returns:

The constructed AABB.

static inline AABB from_point(Eigen::ConstRef<VectorMax3d> p_t0,
    
Eigen::ConstRef<VectorMax3d> p_t1,
    
const double inflation_radius = 0);

Construct an AABB for a moving point (i.e.

temporal edge).

Parameters:
Eigen::ConstRef<VectorMax3d> p_t0

The point’s position at time t=0.

Eigen::ConstRef<VectorMax3d> p_t1

The point’s position at time t=1.

const double inflation_radius = 0

Radius of a capsule around the temporal edge which the AABB encloses.

Returns:

The constructed AABB.

static void conservative_inflation(Eigen::Ref<ArrayMax3d> min,
    
Eigen::Ref<ArrayMax3d> max, const double inflation_radius);

Compute a conservative inflation of the AABB.

static inline double conservative_lower_bound(
    
const double v, const double inflation_radius);

Conservatively inflate one lower bound.

The single-coordinate policy behind conservative_inflation(): the bound is moved out by the radius, then nudged to the next representable double away from the box so rounding can never shrink it. Host/device so the GPU broad phases build bit-identical boxes.

Parameters:
const double v

The coordinate to bound from below.

const double inflation_radius

The radius to inflate by.

Returns:

The conservative lower bound.

static inline double conservative_upper_bound(
    
const double v, const double inflation_radius);

Conservatively inflate one upper bound.

Parameters:
const double v

The coordinate to bound from above.

const double inflation_radius

The radius to inflate by.

Returns:

The conservative upper bound.