📄 ivp_core.cxx
字号:
this->movement_state=IVP_MT_NOT_SIM;
this->speed.set_to_zero();
this->rot_speed.set_to_zero();
this->speed_change.set_to_zero();
this->rot_speed_change.set_to_zero();
this->delta_world_f_core_psis.set_to_zero();
IVP_Event_Sim es(environment);
calc_next_PSI_matrix_zero_speed(&es);
}
// because of not wanted interpolations on calm objects
void IVP_Core::stop_physical_movement()
{
stop_movement_without_collision_recheck();
IVP_Time time = environment->get_current_time();
for(int c = objects.len()-1;c>=0;c--){
IVP_Real_Object *r_obj=this->objects.element_at(c);
IVP_ASSERT(r_obj->get_movement_state()!=IVP_MT_STATIC);
r_obj->set_movement_state(IVP_MT_NOT_SIM);
environment->get_mindist_manager()->recheck_ov_element(r_obj);
IVP_Hull_Manager *h_manager = r_obj->get_hull_manager();
h_manager->exit_hull_for_simulation(time);
if (r_obj->cache_object){
environment->get_cache_object_manager()->invalid_cache_object(r_obj);
}
}
}
void IVP_Core::reset_freeze_check_values() {
IVP_Time time = environment->get_current_time();
this->time_of_calm_reference[0] = time.get_time();
this->time_of_calm_reference[1] = time.get_time();
}
// init core for calc_next_PSI_matrix
void IVP_Core::init_core_for_simulation(){
IVP_ASSERT(movement_state == IVP_MT_NOT_SIM);
movement_state = IVP_MT_MOVING;
//speed_change.set_to_zero();
//rot_speed_change.set_to_zero();
IVP_Time time = environment->get_current_time();
IVP_Time last_time = time - environment->get_delta_PSI_time();
this->time_of_last_psi = last_time;
reset_freeze_check_values();
this->time_of_last_psi = time;
for(int c = objects.len()-1;c>=0;c--){
IVP_Real_Object *r_obj=this->objects.element_at(c);
IVP_ASSERT(r_obj->get_movement_state()!=IVP_MT_STATIC);
r_obj->set_movement_state(IVP_MT_MOVING);
IVP_Hull_Manager *h_manager = r_obj->get_hull_manager();
h_manager->init_hull_for_simulation();
r_obj->get_all_near_mindists();
}
}
/** sets rot_speed so that it is synchronized with interpolation
* ensure that calc_next_PSI_matrix is called prior to this method
* does not call calc_next_PSI_matrix */
void IVP_Core::synchronize_with_rot_z(){
IVP_ASSERT(tmp_null.old_sync_info == NULL);
IVP_U_Memory *mem=environment->sim_unit_mem;
void *p=mem->get_mem_transaction(sizeof(IVP_Old_Sync_Rot_Z));
tmp_null.old_sync_info=(IVP_Old_Sync_Rot_Z*)p;
tmp_null.old_sync_info->was_pushed_during_i_s=IVP_FALSE;
IVP_Time current_time = environment->get_current_time();
IVP_IF(1) {
IVP_Debug_Manager *dm=environment->get_debug_manager();
if(dm->file_out_impacts) {
fprintf(dm->out_deb_file,"doing_synchronize %lx at %f\n",0x0000ffff&(long)this,current_time.get_time());
}
}
tmp_null.old_sync_info->old_sync_rot_speed. set(&rot_speed);
tmp_null.old_sync_info->old_sync_q_world_f_core_next_psi = q_world_f_core_next_psi;
IVP_U_Quat q_core_f_core; q_core_f_core.set_invert_mult( &q_world_f_core_last_psi, &q_world_f_core_next_psi);
inline_calc_at_quaternion( current_time, & q_world_f_core_next_psi );
q_world_f_core_next_psi.set_matrix( &m_world_f_core_last_psi );
inline_calc_at_position( current_time, & m_world_f_core_last_psi.vv );
#ifdef IVP_FAST_WHEELS_ENABLED
if (!this->rot_inertias_are_equal)
#endif
{
// new quaternion based solution to calculate the rotation speed:
IVP_DOUBLE f = 2.0f * i_delta_time;
rot_speed.set( f * IVP_Inline_Math::asind( q_core_f_core.x),
f * IVP_Inline_Math::asind( q_core_f_core.y),
f * IVP_Inline_Math::asind( q_core_f_core.z) );
}
}
/****************************************
* undos synchronize_with_rot_z (only if not calc_next_PSI_matrix is not called
**************************/
void IVP_Core::undo_synchronize_rot_z() {
IVP_IF(1) {
IVP_Debug_Manager *dm=environment->get_debug_manager();
if(dm->file_out_impacts) {
fprintf(dm->out_deb_file,"undoing_synchro %x at %f\n",0x0000ffff&(IVP_INT32)this,environment->get_current_time().get_time());
}
}
rot_speed. set(&tmp_null.old_sync_info->old_sync_rot_speed);
q_world_f_core_next_psi = tmp_null.old_sync_info->old_sync_q_world_f_core_next_psi;
tmp_null.old_sync_info=NULL;
//q_world_f_core_last_psi .set_matrix(&m_world_f_core_last_psi);
}
IVP_Vec_PCore::IVP_Vec_PCore(const IVP_Core *pc,const IVP_U_Float_Point *p){
pc->m_world_f_core_last_psi.vimult3(p,this);
}
void IVP_Core::calc_calc(){
IVP_ASSERT(get_rot_inertia()->real_length() > P_DOUBLE_EPS);
IVP_U_Float_Hesse *iri = (IVP_U_Float_Hesse *)get_inv_rot_inertia();
const IVP_U_Float_Point *ri = get_rot_inertia();
iri->set( 1.0f/ri->k[0],1.0f/ri->k[1], 1.0f/ri->k[2]);
iri->hesse_val = 1.0f/get_mass();
IVP_U_Float_Point diff_vec( iri->k[1] - iri->k[2],
iri->k[2] - iri->k[0],
iri->k[0] - iri->k[1]);
IVP_DOUBLE qdiff = diff_vec.quad_length();
IVP_DOUBLE qrlen = iri->quad_length();
const IVP_DOUBLE eps = 0.1f;
if ( qdiff < qrlen * (eps * eps) ){
rot_inertias_are_equal = IVP_TRUE;
}else{
rot_inertias_are_equal = IVP_FALSE;
}
inv_object_diameter = 0.5f / upper_limit_radius;
}
void IVP_Core::transform_PSI_matrizes_core(const IVP_U_Matrix *m_core_f_core){
m_world_f_core_last_psi.mmult4(m_core_f_core, &m_world_f_core_last_psi);
pos_world_f_core_last_psi.set ( m_world_f_core_last_psi.get_position());
q_world_f_core_last_psi.set_quaternion( &m_world_f_core_last_psi);
q_world_f_core_next_psi = q_world_f_core_last_psi;
}
void IVP_Core::init(IVP_Real_Object *io){
P_MEM_CLEAR(this);
objects.reset();
objects.add(io);
environment = io->get_environment();
//please change: unmoveable and not sim objs get no simulation unit -> no sim unit per default
sim_unit_of_core = new IVP_Simulation_Unit();
sim_unit_of_core->add_sim_unit_core( this );
sim_unit_of_core->set_unit_movement_type(IVP_MT_NOT_SIM);
this->add_core_controller(environment->standard_gravity_controller);
//current_sim_man_slot = -1; //not simulated
movement_state=IVP_MT_NOT_SIM;
}
IVP_Core::IVP_Core(IVP_Real_Object *io){
init(io);
environment->get_sim_units_manager()->add_sim_unit_to_manager(sim_unit_of_core);
}
IVP_Core::IVP_Core(IVP_Real_Object *io, const IVP_U_Quat *q_world_f_object_init, const IVP_U_Point *position, IVP_BOOL physical_unmoveable_, IVP_BOOL enable_piling_optimization)
{
init(io);
physical_unmoveable = physical_unmoveable_;
// init_core_for_simulation();
environment->get_sim_units_manager()->add_sim_unit_to_manager(sim_unit_of_core);
q_world_f_core_last_psi = *q_world_f_object_init;
q_world_f_core_last_psi.normize_quat();
q_world_f_core_next_psi = q_world_f_core_last_psi;
pos_world_f_core_last_psi.set(position);
delta_world_f_core_psis.set_to_zero();
// set redundant matrix
q_world_f_core_last_psi.set_matrix(&m_world_f_core_last_psi);
m_world_f_core_last_psi.vv.set(position);
set_radius( 1000.0f,1000.0f);
this->set_fast_piling_allowed( enable_piling_optimization );
}
IVP_Core::~IVP_Core()
{
this->environment->remove_revive_core(this);
if(this->physical_unmoveable == IVP_TRUE) {
if(this->core_friction_info.for_unmoveables.l_friction_info_hash != NULL) {
P_DELETE( this->core_friction_info.for_unmoveables.l_friction_info_hash );
}
} else {
int i;
IVP_Controller *my_controller;
for(i=controllers_of_core.len()-1;i>=0;i--) {
my_controller=controllers_of_core.element_at(i);
my_controller->core_is_going_to_be_deleted_event(this);
}
}
if(this->sim_unit_of_core) {
this->sim_unit_of_core->sim_unit_remove_core(this);
}
P_DELETE(spin_clipping);
}
IVP_Core_Merged::IVP_Core_Merged(IVP_Real_Object *real_obj): IVP_Core( real_obj ){
this->objects.remove(real_obj);
}
IVP_Core_Merged::IVP_Core_Merged(IVP_Core *core0, IVP_Core *core1):
IVP_Core(core0->objects.element_at(0))
{
// Core Merge Constructor
P_MEM_CLEAR(this); //warning: this is not so good (old values are destroyed, e.g. a vector object in IVP_Core)
physical_unmoveable = (IVP_BOOL)(core0->physical_unmoveable | core1->physical_unmoveable);
environment = core0->environment;
movement_state=IVP_MT_MOVING;
set_by_merge(core0, core1);
IVP_Event_Sim es(environment);
IVP_Calc_Next_PSI_Solver nps(this);
nps.calc_next_PSI_matrix( &es, NULL );
}
// @@@ maybe not necessary each PSI !!!!
IVP_Movement_Type IVP_Core::calc_movement_state(IVP_Time psi_time) {
// check short time movements
while(1){ // break if object has moved
IVP_DOUBLE qdist = pos_world_f_core_last_psi.quad_distance_to(&position_world_f_core_calm_reference[0]);
if(qdist > IVP_MINIMAL_TRANS_SPEED_PER_PSI_SHORT * IVP_MINIMAL_TRANS_SPEED_PER_PSI_SHORT) break;
IVP_DOUBLE qrot_sum = q_world_f_core_next_psi.inline_estimate_q_diff_to( &q_world_f_core_calm_reference[0] );
if (qrot_sum * upper_limit_radius * upper_limit_radius > IVP_MINIMAL_ROT_SPEED_PER_PSI_SHORT * IVP_MINIMAL_ROT_SPEED_PER_PSI_SHORT) break;
// don't check long term for slow objects
if (psi_time - time_of_calm_reference[0] > environment->get_freeze_manager()->freeze_check_dtime){
return IVP_MT_CALM;
}
return IVP_MT_SLOW;
}
q_world_f_core_calm_reference[0].set(&q_world_f_core_next_psi);
position_world_f_core_calm_reference[0].set( & pos_world_f_core_last_psi );
this->time_of_calm_reference[0] = psi_time.get_time();
while(1){ // break if object has moved
IVP_DOUBLE q_dist = pos_world_f_core_last_psi.quad_distance_to(&position_world_f_core_calm_reference[1]);
if(q_dist > IVP_MINIMAL_TRANS_SPEED_PER_PSI_LONG*IVP_MINIMAL_TRANS_SPEED_PER_PSI_LONG) break;
IVP_DOUBLE qrot_sum = q_world_f_core_last_psi.inline_estimate_q_diff_to( &q_world_f_core_calm_reference[1] );
if (qrot_sum * upper_limit_radius * upper_limit_radius > IVP_MINIMAL_ROT_SPEED_PER_PSI_LONG*IVP_MINIMAL_ROT_SPEED_PER_PSI_LONG) break;
if (psi_time - time_of_calm_reference[1] > IVP_HAS_MOVED_LONG_TIME){
return IVP_MT_CALM; // enforce calm down after some seconds
}
return IVP_MT_MOVING;
}
q_world_f_core_calm_reference[1].set(&q_world_f_core_last_psi);
position_world_f_core_calm_reference[1].set( & pos_world_f_core_last_psi );
this->time_of_calm_reference[1]= psi_time.get_time();
return IVP_MT_MOVING;
}
// create a new collision core
void IVP_Core::create_collision_merged_core_with(IVP_Core *other_core){
IVP_ASSERT( other_core != this);
return;
IVP_Core_Collision *ccore = new IVP_Core_Collision(this,other_core);
// update coordinates of all real objects
{
IVP_U_Matrix *m_world_f_core_merged = &ccore->m_world_f_core_last_psi;
if ( this->m_world_f_core_last_psi.quad_distance_to(m_world_f_core_merged) > P_DOUBLE_EPS){
IVP_Core *core = this;
IVP_U_Matrix new_m_core_f_core;
m_world_f_core_merged->mimult4(&core->m_world_f_core_last_psi, & new_m_core_f_core);
for(int c = objects.len()-1;c>=0;c--){
IVP_Real_Object *obj=this->objects.element_at(c);
// 1. step, calc new_m_core_f_core
IVP_U_Matrix new_m_object_f_core;
IVP_U_Matrix old_m_core_f_object;
obj->calc_m_core_f_object(&old_m_core_f_object);
old_m_core_f_object.mimult4( &new_m_core_f_core, &new_m_object_f_core);
new_m_object_f_core.orthonormize();
obj->set_new_m_object_f_core(&new_m_object_f_core);
ccore->objects.add(obj);
obj->physical_core = ccore;
}
}
if ( other_core->m_world_f_core_last_psi.quad_distance_to(m_world_f_core_merged) > P_DOUBLE_EPS){
IVP_Core *core = other_core;
IVP_U_Matrix new_m_core_f_core;
m_world_f_core_merged->mimult4(&core->m_world_f_core_last_psi, & new_m_core_f_core);
for(int c2 = other_core->objects.len()-1;c2>=0;c2--){
IVP_Real_Object *obj=other_core->objects.element_at(c2);
// 1. step, calc new_m_core_f_core
IVP_U_Matrix new_m_object_f_core;
IVP_U_Matrix old_m_core_f_object;
obj->calc_m_core_f_object(&old_m_core_f_object);
old_m_core_f_object.mimult4( &new_m_core_f_core, &new_m_object_f_core);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -