blob: ad68a3194840f9e0b43cc495461dddcc3e37468e [file] [log] [blame]
//#####################################################################
// Copyright 2004, Ron Fedkiw, Geoffrey Irving.
// 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
//#####################################################################
#ifndef __DEFORMABLE_OBJECT_COLLISIONS__
#define __DEFORMABLE_OBJECT_COLLISIONS__
#include "../Data_Structures/PAIR.h"
#include "../Particles/SOLIDS_PARTICLE.h"
namespace PhysBAM
{
template<class T, class TV>
class DEFORMABLE_OBJECT_COLLISIONS
{
public:
SOLIDS_PARTICLE<T, TV>* collision_particles;
SOLIDS_PARTICLE<T, TV>* embedded_particles_for_thin_shells;
LIST_ARRAY<PAIR<SOLIDS_PARTICLE<T, TV>*, T> > saved_states;
LIST_ARRAY<SOLIDS_PARTICLE<T, TV>* > saved_embedded_particles_for_thin_shells;
ARRAY<bool> check_collision;
ARRAY<bool> enforce_collision;
bool enforce_tangential_collision_velocity;
ARRAY<TV> total_collision_velocity;
ARRAY<TV> collision_normal;
ARRAY<T> normal_collision_velocity;
T collision_tolerance;
T roughness;
bool perform_self_collision;
ARRAY<TV> X_self_collision_free, V_self_collision_free;
ARRAY<bool> skip_collision_body;
DEFORMABLE_OBJECT_COLLISIONS()
: collision_particles (0), embedded_particles_for_thin_shells (0), enforce_tangential_collision_velocity (false), collision_tolerance ( (T) 1e-6), roughness ( (T) 1e-8)
{
Perform_Self_Collision();
}
virtual ~DEFORMABLE_OBJECT_COLLISIONS()
{
for (int i = 1; i <= saved_states.m; i++) delete saved_states (i).x;
}
void Perform_Self_Collision (const bool perform_self_collision_input = true)
{
perform_self_collision = perform_self_collision_input;
}
void Initialize_Object_Collisions (SOLIDS_PARTICLE<T, TV>& collision_particles_input, const bool enforce_tangential_collision_velocity_input)
{
collision_particles = &collision_particles_input;
enforce_tangential_collision_velocity = enforce_tangential_collision_velocity_input;
Reset_Object_Collisions(); // in case collisions already exist
check_collision.Resize_Array (collision_particles->number, false, false);
ARRAY<bool>::copy (true, check_collision);
enforce_collision.Resize_Array (collision_particles->number);
if (enforce_tangential_collision_velocity) total_collision_velocity.Resize_Array (collision_particles->number);
else
{
collision_normal.Resize_Array (collision_particles->number);
normal_collision_velocity.Resize_Array (collision_particles->number);
}
}
void Set_Embedded_Particles_For_Thin_Shells (SOLIDS_PARTICLE<T, TV>& embedded_particles)
{
embedded_particles_for_thin_shells = &embedded_particles;
}
void Set_Collision_Velocities (ARRAY<TV>& V) // for external forces and velocities
{
if (enforce_tangential_collision_velocity)
{
for (int p = 1; p <= check_collision.m; p++) if (enforce_collision (p)) V (p) = total_collision_velocity (p);
}
else for (int p = 1; p <= check_collision.m; p++) if (enforce_collision (p)) V (p) += (normal_collision_velocity (p) - TV::Dot_Product (V (p), collision_normal (p))) * collision_normal (p);
}
void Zero_Out_Collision_Velocities (ARRAY<TV>& V) // for external forces and velocities
{
if (enforce_tangential_collision_velocity)
{
for (int p = 1; p <= check_collision.m; p++) if (enforce_collision (p)) V (p) = TV();
}
else for (int p = 1; p <= check_collision.m; p++) if (enforce_collision (p)) V (p) -= TV::Dot_Product (V (p), collision_normal (p)) * collision_normal (p);
}
void Reset_Object_Collisions()
{
ARRAY<bool>::copy (false, enforce_collision);
}
virtual void Save_State (PAIR<SOLIDS_PARTICLE<T, TV>*, T>& state, const T time = 0) const
{
state.x->Initialize_Particles (*collision_particles);
state.y = time;
}
virtual void Restore_State (const PAIR<SOLIDS_PARTICLE<T, TV>*, T>& state)
{
collision_particles->Initialize_Particles (*state.x);
}
void Save_State (const int state_index, const T time = 0)
{
if (saved_states.m < state_index) saved_states.Resize_Array (state_index);
delete saved_states (state_index).x;
saved_states (state_index).x = new SOLIDS_PARTICLE<T, TV>;
if (embedded_particles_for_thin_shells)
{
if (saved_embedded_particles_for_thin_shells.m < state_index) saved_embedded_particles_for_thin_shells.Resize_Array (state_index);
delete saved_embedded_particles_for_thin_shells (state_index);
saved_embedded_particles_for_thin_shells (state_index) = new SOLIDS_PARTICLE<T, TV>;
}
Save_State (saved_states (state_index), time);
if (embedded_particles_for_thin_shells) saved_embedded_particles_for_thin_shells (state_index)->Initialize_Particles (*embedded_particles_for_thin_shells);
}
void Restore_State (const int state_index)
{
assert (saved_states (state_index).x);
Restore_State (saved_states (state_index));
if (embedded_particles_for_thin_shells) embedded_particles_for_thin_shells->Initialize_Particles (*saved_embedded_particles_for_thin_shells (state_index));
}
void Delete_State (const int state_index)
{
delete saved_states (state_index).x;
saved_states (state_index).x = 0;
if (embedded_particles_for_thin_shells)
{
delete saved_embedded_particles_for_thin_shells (state_index);
saved_embedded_particles_for_thin_shells (state_index) = 0;
}
}
template <class RW> void Read_State (std::istream& input_stream, const int state_index)
{
if (saved_states.m < state_index) saved_states.Resize_Array (state_index);
delete saved_states (state_index).x;
saved_states (state_index).x = new SOLIDS_PARTICLE<T, TV>;
char version;
bool have_embedded;
Read_Binary<RW> (input_stream, version);
assert (version == 1);
Read_Binary<RW> (input_stream, saved_states (state_index).y, *saved_states (state_index).x, have_embedded);
if (embedded_particles_for_thin_shells)
{
assert (have_embedded);
if (saved_embedded_particles_for_thin_shells.m < state_index) saved_embedded_particles_for_thin_shells.Resize_Array (state_index);
delete saved_embedded_particles_for_thin_shells (state_index);
saved_embedded_particles_for_thin_shells (state_index) = new SOLIDS_PARTICLE<T, TV>;
Read_Binary<RW> (input_stream, *saved_embedded_particles_for_thin_shells (state_index));
}
else
{
assert (!have_embedded);
}
}
template <class RW> void Write_State (std::ostream& output_stream, const int state_index) const
{
assert (saved_states (state_index).x);
char version = 1;
bool have_embedded = embedded_particles_for_thin_shells != 0;
Write_Binary<RW> (output_stream, version, saved_states (state_index).y, *saved_states (state_index).x, have_embedded);
if (embedded_particles_for_thin_shells)
{
assert (saved_embedded_particles_for_thin_shells (state_index));
Write_Binary<RW> (output_stream, *saved_embedded_particles_for_thin_shells (state_index));
}
}
//#####################################################################
};
}
#endif