blob: 476079631adf7e9eb296b28ada0a2890c9690bf4 [file] [log] [blame]
//#####################################################################
// Copyright 2004, Ron Fedkiw, Geoffrey Irving, Frank Losasso.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class DEFORMABLE_OBJECT_COLLISIONS_3D
//#####################################################################
#ifndef __DEFORMABLE_OBJECT_COLLISIONS_3D__
#define __DEFORMABLE_OBJECT_COLLISIONS_3D__
#include "DEFORMABLE_OBJECT_COLLISIONS.h"
#include "../Geometry/SEGMENTED_CURVE_3D.h"
#include "../Geometry/TRIANGULATED_SURFACE.h"
#include "../Collisions_And_Interactions/COLLISION_BODY_3D.h"
namespace PhysBAM
{
template<class T> class COLLISION_BODY_LIST_3D;
template<class T> class EMBEDDED_TRIANGULATED_SURFACE;
template<class T> class EMBEDDED_TETRAHEDRALIZED_VOLUME;
template<class T> class TRIANGLES_OF_MATERIAL_3D;
template<class T> class EMBEDDED_TETRAHEDRALIZED_VOLUME_BOUNDARY_SURFACE;
template<class T>
class DEFORMABLE_OBJECT_COLLISIONS_3D: public DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >, public COLLISION_BODY_3D<T>
{
public:
using COLLISION_BODY_3D<T>::body_type;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::collision_particles;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::saved_states;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::check_collision;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::enforce_collision;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::enforce_tangential_collision_velocity;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::total_collision_velocity;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::collision_normal;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::normal_collision_velocity;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::collision_tolerance;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::roughness;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::X_self_collision_free;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::V_self_collision_free;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::skip_collision_body;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::Initialize_Object_Collisions;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::embedded_particles_for_thin_shells;
using DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::saved_embedded_particles_for_thin_shells;
SEGMENTED_CURVE_3D<T>* segmented_curve;
TRIANGULATED_SURFACE<T>* triangulated_surface;
COLLISION_BODY_LIST_3D<T>* collision_body_list;
int collision_body_list_id;
static DEFORMABLE_OBJECT_COLLISIONS_3D<T> *m_pointer;
static void Adjust_Nodes_For_Collision_Body_Collisions_Helper_I (long thread_id, void* id);
static T m_dt;
DEFORMABLE_OBJECT_COLLISIONS_3D()
: segmented_curve (0), triangulated_surface (0), collision_body_list (0), collision_body_list_id (0)
{
body_type = COLLISION_BODY_3D<T>::DEFORMABLE_BODY_TYPE;
}
virtual ~DEFORMABLE_OBJECT_COLLISIONS_3D()
{}
void Initialize_Segmented_Curve (SEGMENTED_CURVE_3D<T>& segmented_curve_input)
{
segmented_curve = &segmented_curve_input;
}
void Initialize_Triangulated_Surface (TRIANGULATED_SURFACE<T>& triangulated_surface_input)
{
triangulated_surface = &triangulated_surface_input;
}
void Set_Collision_Body_List (COLLISION_BODY_LIST_3D<T>& collision_body_list_input)
{
collision_body_list = &collision_body_list_input;
skip_collision_body.Resize_Array (collision_body_list->collision_bodies.m);
}
VECTOR_3D<T> Pointwise_Object_Velocity (const int triangle_index, const VECTOR_3D<T>& location) const
{
assert (triangulated_surface && triangulated_surface->particles.store_velocity);
int i, j, k;
triangulated_surface->triangle_mesh.triangles.Get (triangle_index, i, j, k);
VECTOR_3D<T> weights = TRIANGLE_3D<T>::Clamped_Barycentric_Coordinates (location, triangulated_surface->particles.X (i), triangulated_surface->particles.X (j), triangulated_surface->particles.X (k));
return weights.x * triangulated_surface->particles.V (i) + weights.y * triangulated_surface->particles.V (j) + weights.z * triangulated_surface->particles.V (k);
}
VECTOR_3D<T> Pointwise_Object_Pseudo_Velocity (const int triangle_index, const VECTOR_3D<T>& location, const int state1, const int state2) const
{
assert (triangulated_surface && triangulated_surface->particles.store_velocity);
int i, j, k;
triangulated_surface->triangle_mesh.triangles.Get (triangle_index, i, j, k);
VECTOR_3D<T> weights = TRIANGLE_3D<T>::Clamped_Barycentric_Coordinates (location, triangulated_surface->particles.X (i), triangulated_surface->particles.X (j), triangulated_surface->particles.X (k)), dXi, dXj, dXk;
if (embedded_particles_for_thin_shells)
{
dXi = saved_embedded_particles_for_thin_shells (state2)->X (i) - saved_embedded_particles_for_thin_shells (state1)->X (i);
dXj = saved_embedded_particles_for_thin_shells (state2)->X (j) - saved_embedded_particles_for_thin_shells (state1)->X (j);
dXk = saved_embedded_particles_for_thin_shells (state2)->X (k) - saved_embedded_particles_for_thin_shells (state1)->X (k);
}
else
{
dXi = saved_states (state2).x->X (i) - saved_states (state1).x->X (i);
dXj = saved_states (state2).x->X (j) - saved_states (state1).x->X (j);
dXk = saved_states (state2).x->X (k) - saved_states (state1).x->X (k);
}
return (weights.x * dXi + weights.y * dXj + weights.z * dXk) / (saved_states (state2).y - saved_states (state1).y);
}
bool Triangulated_Surface_Intersection (RAY_3D<T>& ray) const
{
assert (triangulated_surface);
return triangulated_surface->Intersection (ray, roughness);
}
bool Triangulated_Surface_Closest_Non_Intersecting_Point (RAY_3D<T>& ray) const
{
assert (triangulated_surface);
return triangulated_surface->Closest_Non_Intersecting_Point (ray, roughness);
}
bool Triangulated_Surface_Inside_Any_Triangle (const VECTOR_3D<T>& location, int& triangle_id) const
{
assert (triangulated_surface);
return triangulated_surface->Inside_Any_Triangle (location, triangle_id, roughness);
}
VECTOR_3D<T> Triangulated_Surface_Surface (const VECTOR_3D<T>& location, const T max_distance, int* triangle_id = 0, T* distance = 0) const
{
assert (triangulated_surface);
return triangulated_surface->Surface (location, max_distance, roughness, triangle_id, distance);
}
VECTOR_3D<T> Triangulated_Surface_World_Space_Point_From_Barycentric_Coordinates (const int triangle_id, const VECTOR_3D<T>& weights) const
{
assert (triangulated_surface);
int i, j, k;
triangulated_surface->triangle_mesh.triangles.Get (triangle_id, i, j, k);
return TRIANGLE_3D<T>::Point_From_Barycentric_Coordinates (weights, triangulated_surface->particles.X (i), triangulated_surface->particles.X (j), triangulated_surface->particles.X (k));
}
TRIANGLE_3D<T> Triangulated_Surface_World_Space_Triangle (const int triangle_id, const bool use_saved_state = false) const
{
if (use_saved_state)
{
assert (saved_states (1).x);
if (embedded_particles_for_thin_shells) return Triangulated_Surface_World_Space_Triangle (triangle_id, *saved_embedded_particles_for_thin_shells (1));
else return Triangulated_Surface_World_Space_Triangle (triangle_id, *saved_states (1).x);
}
else
{
assert (triangulated_surface);
int i, j, k;
triangulated_surface->triangle_mesh.triangles.Get (triangle_id, i, j, k);
return TRIANGLE_3D<T> (triangulated_surface->particles.X (i), triangulated_surface->particles.X (j), triangulated_surface->particles.X (k));
}
}
TRIANGLE_3D<T> Triangulated_Surface_World_Space_Triangle (const int triangle_id, const SOLIDS_PARTICLE<T, VECTOR_3D<T> >& state) const
{
assert (triangulated_surface);
int i, j, k;
triangulated_surface->triangle_mesh.triangles.Get (triangle_id, i, j, k);
return TRIANGLE_3D<T> (state.X (i), state.X (j), state.X (k));
}
void Save_Self_Collision_Free_State() // assumes mass does not change
{
if (segmented_curve)
{
int n = segmented_curve->particles.number;
X_self_collision_free.Resize_Array (n, false, false);
ARRAY<VECTOR_3D<T> >::copy_up_to (segmented_curve->particles.X.array, X_self_collision_free, n);
V_self_collision_free.Resize_Array (n, false, false);
ARRAY<VECTOR_3D<T> >::copy_up_to (segmented_curve->particles.V.array, V_self_collision_free, n);
}
else if (triangulated_surface)
{
int n = triangulated_surface->particles.number;
X_self_collision_free.Resize_Array (n, false, false);
ARRAY<VECTOR_3D<T> >::copy_up_to (triangulated_surface->particles.X.array, X_self_collision_free, n);
V_self_collision_free.Resize_Array (n, false, false);
ARRAY<VECTOR_3D<T> >::copy_up_to (triangulated_surface->particles.V.array, V_self_collision_free, n);
}
}
void Restore_Self_Collision_Free_State()
{
if (segmented_curve)
{
int n = segmented_curve->particles.number;
ARRAY<VECTOR_3D<T> >::copy_up_to (X_self_collision_free, segmented_curve->particles.X.array, n);
ARRAY<VECTOR_3D<T> >::copy_up_to (V_self_collision_free, segmented_curve->particles.V.array, n);
}
else if (triangulated_surface)
{
int n = triangulated_surface->particles.number;
ARRAY<VECTOR_3D<T> >::copy_up_to (X_self_collision_free, triangulated_surface->particles.X.array, n);
ARRAY<VECTOR_3D<T> >::copy_up_to (V_self_collision_free, triangulated_surface->particles.V.array, n);
}
}
void Save_State (const int state_index, const T time = 0)
{
DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::Save_State (state_index, time);
}
void Restore_State (const int state_index)
{
DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::Restore_State (state_index);
}
void Delete_State (const int state_index)
{
DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::Delete_State (state_index);
}
template<class RW> void Read_State (std::istream& input_stream, const int state_index)
{
DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::template Read_State<RW> (input_stream, state_index);
}
template<class RW> void Write_State (std::ostream& output_stream, const int state_index)
{
DEFORMABLE_OBJECT_COLLISIONS<T, VECTOR_3D<T> >::template Write_State<RW> (output_stream, state_index);
}
T Thin_Shell_Density() const
{
return triangulated_surface->density;
}
//#####################################################################
int Adjust_Nodes_For_Collision_Body_Collisions (const T dt);
int Adjust_Nodes_For_Collision_Body_Collisions (EMBEDDED_TRIANGULATED_SURFACE<T>& embedded_triangulated_surface, TRIANGLES_OF_MATERIAL_3D<T>& triangles_of_material, const T dt);
int Adjust_Nodes_For_Collision_Body_Collisions (EMBEDDED_TETRAHEDRALIZED_VOLUME<T>& embedded_tetrahedralized_volume,
EMBEDDED_TETRAHEDRALIZED_VOLUME_BOUNDARY_SURFACE<T>& embedded_tetrahedralized_volume_boundary_surface, const T dt);
int Adjust_Mesh_For_Embedded_Self_Collision (EMBEDDED_TRIANGULATED_SURFACE<T>& embedded_triangulated_surface, TRIANGLES_OF_MATERIAL_3D<T>& triangles_of_material);
int Adjust_Mesh_For_Embedded_Self_Collision (EMBEDDED_TETRAHEDRALIZED_VOLUME<T>& embedded_tetrahedralized_volume,
EMBEDDED_TETRAHEDRALIZED_VOLUME_BOUNDARY_SURFACE<T>& embedded_tetrahedralized_volume_boundary_surface);
bool Earliest_Triangle_Crossover (const VECTOR_3D<T>& start_X, const VECTOR_3D<T>& end_X, const T dt, T& hit_time, VECTOR_3D<T>& normal, VECTOR_3D<T>& weights, int& triangle_id) const;
bool Latest_Triangle_Crossover (const VECTOR_3D<T>& start_X, const VECTOR_3D<T>& end_X, const T dt, T& hit_time, VECTOR_3D<T>& normal, VECTOR_3D<T>& weights, int& triangle_id,
typename TRIANGLE_3D<T>::POINT_TRIANGLE_COLLISION_TYPE& returned_collision_type) const;
bool Any_Triangle_Crossover (const VECTOR_3D<T>& start_X, const VECTOR_3D<T>& end_X, const T dt) const;
void Compute_Occupied_Cells (const GRID_3D<T>& grid, ARRAYS_3D<bool>& occupied, const bool with_body_motion, const T extra_thickness, const T body_thickness_factor,
const bool reset_occupied_to_false = true) const;
void Get_Triangle_Bounding_Boxes (LIST_ARRAY<BOX_3D<T> >& bounding_boxes, const bool with_body_motion, const T extra_thickness, const T body_thickness_factor) const;
void Update_Intersection_Acceleration_Structures (const bool use_swept_triangle_hierarchy, const int state1 = 0, const int state2 = 0);
//#####################################################################
};
}
#endif