📄 breakable_constraint.cpp
字号:
#include <hk_physics/physics.h>
#include <hk_physics/constraint/local_constraint_system/local_constraint_system.h>
#include <hk_physics/simunit/psi_info.h>
#include <hk_physics/constraint/breakable_constraint/breakable_constraint_bp.h>
#include <hk_physics/constraint/breakable_constraint/breakable_constraint.h>
#include <hk_physics/core/vm_query_builder/vm_query_builder.h>
#include <hk_math/densematrix_util.h>
#include <hk_math/dense_vector.h>
#if defined (IVP_VERSION_SDK) || defined (IVP_VERSION_EVAL) // IPION
#include <ivp_environment.hxx>
#endif // IPION
hk_Breakable_Constraint::hk_Breakable_Constraint
(
hk_Environment* env,
const hk_Breakable_Constraint_BP* bp
)
: hk_Constraint( env,
bp->m_real_constraint->get_rigid_body(0),
bp->m_real_constraint->get_rigid_body(1),
HK_PRIORITY_LOCAL_CONSTRAINT)
{
init_breakable_constraint(bp);
}
hk_Breakable_Constraint::hk_Breakable_Constraint
(
hk_Local_Constraint_System* constraint_system,
const hk_Breakable_Constraint_BP* bp
)
: hk_Constraint( constraint_system,
bp->m_real_constraint->get_rigid_body(0),
bp->m_real_constraint->get_rigid_body(1),
HK_PRIORITY_LOCAL_CONSTRAINT,
bp->m_real_constraint->get_vmq_storage_size())
{
init_breakable_constraint(bp);
}
hk_Breakable_Constraint::~hk_Breakable_Constraint()
{
// normally constraints are deleted by the constraint solver which owns it.
// however this subconstraint is not really added to the system.
delete m_real_constraint;
}
void hk_Breakable_Constraint::init_constraint(const void* vbp)
{
const hk_Breakable_Constraint_BP* bp = static_cast<const hk_Breakable_Constraint_BP*>(vbp);
init_breakable_constraint(bp);
}
void hk_Breakable_Constraint::init_breakable_constraint(const hk_Breakable_Constraint_BP* bp)
{
m_real_constraint = bp->m_real_constraint;
m_linear_strength = bp->m_linear_strength;
m_angular_strength = bp->m_angular_strength;
m_is_broken = false;
}
void hk_Breakable_Constraint::write_to_blueprint( hk_Breakable_Constraint_BP *pOutBP )
{
pOutBP->m_real_constraint = m_real_constraint;
pOutBP->m_linear_strength = m_linear_strength;
pOutBP->m_angular_strength = m_angular_strength;
}
int hk_Breakable_Constraint::get_vmq_storage_size()
{
// return 0; // HACK: CB
return m_real_constraint->get_vmq_storage_size();
}
struct BreakableConstraintHelper
{
BreakableConstraintHelper( hk_Rigid_Body* b )
: m_core(b->get_rigid_body_core()),
m_old_lin_vel(m_core->_get_linear_velocity()),
m_old_ang_vel(m_core->_get_spin())
{
}
bool breaks( hk_real linear_limit, hk_real angular_limit )
{
// reverse engineer the impulses and check their strength
hk_Vector3 linear = m_core->_get_linear_velocity() - m_old_lin_vel;
if( m_core->get_mass()*linear.length_squared() < linear_limit*linear_limit )
{
hk_Vector3 angular = m_core->_get_spin() - m_old_ang_vel;
hk_Vector3 spin;
spin.set_mul3( m_core->_get_body_inertia(), angular );
if( spin.length_squared() < angular_limit*angular_limit )
{
return false;
}
}
return true;
}
void UnapplyConstraint()
{
// restore old values on break
m_core->_get_linear_velocity() = m_old_lin_vel;
m_core->_get_spin() = m_old_ang_vel;
}
hk_Rigid_Body_Core* m_core;
hk_Vector3 m_old_lin_vel;
hk_Vector3 m_old_ang_vel;
};
void hk_Breakable_Constraint::FireEventIfBroken()
{
if ( m_is_broken && get_constraint_system()->is_active() )
{
IVP_Environment* env = reinterpret_cast<IVP_Environment*>(get_constraint_system()->get_environment());
// The game code will do this if it wants the constraint broken
//get_constraint_system()->deactivate();
if(env)
{
env->fire_event_constraint_broken(this);
}
}
m_is_broken = false;
}
int hk_Breakable_Constraint::setup_and_step_constraint( hk_PSI_Info& pi, void *mem, hk_real tau_factor, hk_real damp_factor )
{
m_is_broken = false;
BreakableConstraintHelper ss0( get_rigid_body(0) );
BreakableConstraintHelper ss1( get_rigid_body(1) );
m_real_constraint->setup_and_step_constraint(pi, mem, tau_factor, damp_factor);
m_is_broken = ss0.breaks(m_linear_strength, m_angular_strength) || ss1.breaks(m_linear_strength, m_angular_strength);
FireEventIfBroken();
// constraint event handler has disabled this constraint due to being broken
// so reset the object's values
if ( !get_constraint_system()->is_active() )
{
ss0.UnapplyConstraint();
ss1.UnapplyConstraint();
}
return m_real_constraint->get_vmq_storage_size();
}
void hk_Breakable_Constraint::step_constraint( hk_PSI_Info& pi, void *mem, hk_real tau_factor, hk_real damp_factor )
{
//if( m_is_broken == false )
{
BreakableConstraintHelper ss0( get_rigid_body(0) );
BreakableConstraintHelper ss1( get_rigid_body(1) );
m_real_constraint->step_constraint(pi,mem,tau_factor,damp_factor);
m_is_broken = ss0.breaks(m_linear_strength, m_angular_strength) || ss1.breaks(m_linear_strength, m_angular_strength);
FireEventIfBroken();
// constraint event handler has disabled this constraint due to being broken
// so reset the object's values
if ( !get_constraint_system()->is_active() )
{
ss0.UnapplyConstraint();
ss1.UnapplyConstraint();
}
}
}
void hk_Breakable_Constraint::apply_effector_PSI( hk_PSI_Info& pi, hk_Array<hk_Entity*>* )
{
HK_ASSERT(0 && "never reached");
}
// HAVOK DO NOT EDIT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -