📄 ivp_impact.cxx
字号:
}
imp_solver_stack.do_impact(pushed_cores,IVP_TRUE,impacts_while_system,rescue_speed_val);
IVP_IF(1) {
if (contact_core[0]) contact_core[0]->core_plausible_check();
if (contact_core[1]) contact_core[1]->core_plausible_check();
}
}
//call recalc_friction_s_vals for all fr_dists except the initial one
//is nearly same as check_all_fr_mindists_to_be_valid
//->make redesign !!!!!
void IVP_Impact_System::impact_system_check_start_pair(IVP_Friction_Core_Pair *start_pair,IVP_Contact_Point *mdfr) {
for (int i = start_pair->fr_dists.len()-1; i>=0;i--){
IVP_Contact_Point *my_dist = start_pair->fr_dists.element_at(i);
if( mdfr != my_dist ) { // warning old version checked mdfr != next_dist
my_dist->recalc_friction_s_vals();
IVP_Impact_Solver_Long_Term *info=my_dist->tmp_contact_info;
my_dist->read_materials_for_contact_situation(info);
//printf("impact_sys_update_contact_vals %lx\n",(long)my_dist);
if(info->friction_is_broken==IVP_TRUE) {
associated_fs_system->delete_friction_distance(my_dist);
}
}
}
}
// optimize: first (initial) friction mindist is checked although it is known that it is valid
// Impact System:
// An Impact System is oriented to the Friction System. Friction Mindists are checked if
// they are still valid and then if they may collide in the near future. If they do, the
// impact is done instantly for speedup.
//
// There are three lists. One list with interesting Mindists. One list with Cores that are
// known (means they are synchronized for that point in time) and one list with Cores that
// have already impacted (they are synchronized and their speed has changed, meaning their
// Exact_Mindists and their Next_PSI_Matrix have to be updated. More speedup is gained with
// delaying technique. A core that is pushed only very weak doesnt change its speed. The
// speed is added in next PSI. Delayed cores need no update in Exact_Mindists and
// Next_PSI_Matrix. But the synchronize has to be undone. Delayed cores are found in list
// with known cores, but not necessarily in list with pushed cores. When a push is done in
// Impact System, the pushed cores (not a delayed one) are taken and their Mindists are
// rechecked (calc_coll_distance). A Core that was pushed is put into pushed list. A delayed
// push means that Mindists dont need call to calc_coll_distance. When everything is over,
// the cores beeing in known list and NOT beeing in pushed list are unsynchronized. All
// Cores in pushed list are updated in Exact_Mindists and Next_PSI_Matrix.
// #+# these things with start_pair and except_pair are weird and not necessary any longer:
// remove
void IVP_Impact_System::init_and_solve_impact_system(IVP_Mindist *mindist, IVP_Friction_System *fs_system,IVP_Friction_Core_Pair *start_pair,IVP_Contact_Point *start_fr_dist)
{
IVP_Core *start_core0=start_fr_dist->get_synapse(0)->get_object()->get_core();
IVP_Core *start_core1=start_fr_dist->get_synapse(1)->get_object()->get_core();
sum_of_pushes=0;
associated_fs_system=fs_system;
l_environment=start_pair->objs[0]->environment;
IVP_Core *core0,*core1;
if(start_core0 && !start_core0->physical_unmoveable && !start_core0->pinned) { //@@CBPIN
add_pushed_core_with_pairs_except(start_core0,start_pair);
//invalidate_impact_mindists(start_core0);
}
core0 = start_pair->objs[0];//start_mindist->synapse[0]->get_core();
if(!core0->physical_unmoveable && !core0->pinned) { //@@CBPIN
add_known_core_to_impact_system(core0);
}
if(start_core1 && !start_core1->physical_unmoveable && !start_core1->pinned) { //@@CBPIN
add_pushed_core_with_pairs_except(start_core1,start_pair);
//invalidate_impact_mindists(start_core1);
}
core1 = start_pair->objs[1];//start_mindist->synapse[1]->get_core();
if(!core1->physical_unmoveable && !core1->pinned) { //@@CBPIN
add_known_core_to_impact_system(core1);
}
add_pair_to_impact_system(start_pair);
impact_system_check_start_pair(start_pair,start_fr_dist);
IVP_IF(1) {
l_environment->get_debug_manager()->debug_imp_sys=IVP_FALSE;
}
IVP_IF(l_environment->get_debug_manager()->file_out_impacts) {
if(l_environment->get_current_time().get_time() > 10000.86f) {
printf("critical_imp_sys\n");
l_environment->get_debug_manager()->debug_imp_sys=IVP_TRUE;
}
fprintf(l_environment->get_debug_manager()->out_deb_file,"starting_impact_system at time %f\n",l_environment->get_current_time().get_time());
}
int impact_sys_counter = 0;
while(test_loop_all_pairs()==IVP_TRUE) {
impact_sys_counter ++;
sum_of_pushes++;
if(sum_of_pushes > MAXIMUM_SYSTEM_PUSH_NUMBER) {
IVP_IF(1) {
printf("system_push_number exceeded\n");
}
P_DELETE(mindist);
break;
// put some mindists into hull!
}
}
l_environment->get_statistic_manager()->impact_sum_sys+= impact_sys_counter+1;
IVP_IF(sum_of_pushes>1) {
//printf("did_impact_sys %d pushes at %f\n",sum_of_pushes,l_environment->get_current_time());
#if 0
for(IVP_Friction_Core_Pair *my_pair=get_first_impact_pair();my_pair;my_pair=get_next_impact_pair())
{
printf(" paair %lx ",(long)my_pair&0x0000ffff);
for(IVP_Contact_Point *my_fr=my_pair->get_first_fr_dist_obj_pairs();my_fr;my_fr=my_pair->get_next_fr_dist_obj_pairs())
{
printf("md %lx ",(long)my_fr&0x0000ffff);
}
}
printf("\n");
#endif
}
IVP_IF(1) {
debug_check_all_dists_at_end();
}
recalc_all_affected_cores();
IVP_IF(1) {
associated_fs_system->debug_clean_tmp_info();
}
IVP_IF(l_environment->get_debug_manager()->file_out_impacts) {
l_environment->get_debug_manager()->debug_imp_sys=IVP_FALSE;
fprintf(l_environment->get_debug_manager()->out_deb_file,"\n");
}
}
void IVP_Impact_System::add_pair_to_impact_system(IVP_Friction_Core_Pair *new_pair)
{
i_s_pairs.add(new_pair);
#if 0 /* this is done now at recalc_friction_s_vals */
for (int i = new_pair->fr_dists.len()-1; i>=0; i--){
IVP_Contact_Point *my_dist = new_pair->fr_dists.element_at(i);
my_dist->tmp_contact_info->rescue_factor=1.0f;
my_dist->tmp_contact_info->impacts_while_system=0;
my_dist->tmp_contact_info->coll_time_is_valid=IVP_FALSE;
}
#endif
}
void IVP_Impact_System::synchronize_core_for_impact_system(IVP_Core *new_core) {
if (IVP_MTIS_SIMULATED( new_core->movement_state )){
new_core->synchronize_with_rot_z();
}
}
void IVP_Impact_System::add_pushed_core_with_pairs_except(IVP_Core *new_core,IVP_Friction_Core_Pair *start_pair)
{
add_pushed_core_to_impact_system(new_core);
// connection of core to all its pairs is missing -> loop is quite big, but add_core is not too often done
for ( int i = associated_fs_system->fr_pairs_of_objs.len()-1; i>=0; i--){
IVP_Friction_Core_Pair *fr_pair = associated_fs_system->fr_pairs_of_objs.element_at(i);
if((fr_pair->objs[0] == new_core) || (fr_pair->objs[1] == new_core)) {
if(fr_pair!=start_pair) {
if(pair_is_already_in_system(fr_pair)==IVP_FALSE) {
if(fr_pair->check_all_fr_mindists_to_be_valid(this->associated_fs_system) > 0) {
//warning: at this point fr_pair could be deleted
add_pair_to_impact_system(fr_pair);
}
}
}
}
}
}
// speedup: put flag in pairs
IVP_BOOL IVP_Impact_System::pair_is_already_in_system(IVP_Friction_Core_Pair *test_pair) {
for (int i = i_s_pairs.len()-1; i>=0; i--){
IVP_Friction_Core_Pair *my_pair = i_s_pairs.element_at(i);
if(my_pair==test_pair) {
return IVP_TRUE;
}
}
return IVP_FALSE;
}
void IVP_Friction_System::debug_clean_tmp_info() {
IVP_Contact_Point *my_dist;
for(my_dist=this->get_first_friction_dist();my_dist;my_dist=this->get_next_friction_dist(my_dist)) {
my_dist->tmp_contact_info=NULL;
}
}
void IVP_Impact_System::debug_check_all_dists_at_end() {
IVP_Contact_Point *my_dist;
for(my_dist=associated_fs_system->get_first_friction_dist();my_dist;my_dist=associated_fs_system->get_next_friction_dist(my_dist)) {
my_dist->recalc_friction_s_vals();
my_dist->calc_coll_distance();
my_dist->tmp_contact_info->coll_time_is_valid=IVP_FALSE;
if(my_dist->tmp_contact_info->impact.distance_reached_in_time < ivp_mindist_settings.minimum_friction_dist) {
IVP_Core *core0,*core1;
core0=my_dist->get_synapse(0)->get_object()->physical_core;
core1=my_dist->get_synapse(1)->get_object()->physical_core;
int unmov0,unmov1;
unmov0=(int)core0->physical_unmoveable | (int)core0->temporarily_unmovable;
unmov1=(int)core1->physical_unmoveable | (int)core1->temporarily_unmovable;
if(unmov0&unmov1) {
continue;
}
if(core_is_already_known_to_system(core0) && core_is_already_known_to_system(core1)) {
printf("error_in_impact_system_missed_impact\n");
}
}
}
}
IVP_BOOL IVP_Impact_System::test_loop_all_pairs()
{
#ifndef SYSTEM_IMPACT_ENABLED
return IVP_FALSE;
#endif
IVP_Contact_Point *worst_impact_dist=NULL;
IVP_Friction_Core_Pair *associated_pair = NULL;
IVP_DOUBLE smallest_distance = ivp_mindist_settings.minimum_friction_dist;
IVP_DOUBLE rescue_speed_addon=0.0f;
IVP_IF(l_environment->get_debug_manager()->file_out_impacts) {
fprintf(l_environment->get_debug_manager()->out_deb_file,"calc_new_coll_distances\n");
}
for (int i = i_s_pairs.len()-1; i >= 0 ; i--){
IVP_Friction_Core_Pair *my_pair = i_s_pairs.element_at(i);
int unmov0,unmov1;
unmov0=(int)my_pair->objs[0]->physical_unmoveable | (int)my_pair->objs[0]->temporarily_unmovable; //@@CBPIN
unmov1=(int)my_pair->objs[1]->physical_unmoveable | (int)my_pair->objs[1]->temporarily_unmovable; //@@CBPIN
if(unmov0 & unmov1) {
continue;
}
for (int k = my_pair->fr_dists.len()-1; k>=0; k--){
IVP_Contact_Point *my_fr = my_pair->fr_dists.element_at(k);
if(my_fr->tmp_contact_info->coll_time_is_valid==IVP_TRUE) {
IVP_IF(l_environment->get_debug_manager()->debug_imp_sys) {
printf("did_not_test %lx\n",0x0000ffff&(long)my_fr);
}
} else {
l_environment->get_statistic_manager()->impact_coll_checks++;
my_fr->calc_coll_distance();
}
if(my_fr->tmp_contact_info->impact.distance_reached_in_time< smallest_distance ) {
rescue_speed_addon=my_fr->tmp_contact_info->impact.rescue_speed_addon;
smallest_distance=my_fr->tmp_contact_info->impact.distance_reached_in_time;
worst_impact_dist=my_fr;
associated_pair=my_pair;
}
}
}
IVP_IF(l_environment->get_debug_manager()->file_out_impacts) {
fprintf(l_environment->get_debug_manager()->out_deb_file,"\n");
}
if(worst_impact_dist){
IVP_ASSERT(worst_impact_dist->tmp_contact_info->impact.distance_reached_in_time < ivp_mindist_settings.minimum_friction_dist);
IVP_Core *core;
for(int i=1;i>=0;i--) {
core=worst_impact_dist->tmp_contact_info->contact_core[i];
if(core) {
if(core_is_already_known_to_system(core)==IVP_FALSE) {
// Mac port was: if (i_s_known_cores.index_of(core) == -1) {
add_known_core_to_impact_system(core);
synchronize_core_for_impact_system(core);
}
}
}
IVP_Core *impacting_cores[2];
worst_impact_dist->tmp_contact_info->impacts_while_system++;
worst_impact_dist->tmp_contact_info->do_impact_long_term(impacting_cores,worst_impact_dist->tmp_contact_info->impact.rescue_speed_addon,worst_impact_dist);
//printf("did_sys_imp %lx\n",(long)(&worst_impact_dist->long_term_impact_info)&0x0000ffff);
{
for(int i=1;i>=0;i--) {
core = impacting_cores[i];
if(core && !core->physical_unmoveable && !core->pinned) { //@@CBPIN
if(core_was_already_pushed_in_system(core)==IVP_FALSE) {
add_pushed_core_with_pairs_except(core,associated_pair);
} else {
invalidate_impact_mindists(core);
}
}
}
}
return IVP_TRUE;
} else {
return IVP_FALSE;
}
}
void IVP_Impact_System::invalidate_impact_mindists(IVP_Core *my_core)
{ //there is a cheaper way: via synapses
IVP_Friction_Info_For_Core *my_info = my_core->get_friction_info(associated_fs_system);
for (int i = my_info->friction_springs.len()-1; i>=0; i--){
IVP_Contact_Point *my_dist = my_info->friction_springs.element_at(i);
my_dist->tmp_contact_info->coll_time_is_valid=IVP_FALSE;
}
}
//direction of second friction lies orthogonal to surf_normal
//returns TRUE when second friction value is used
// &imp_solver_stack.world_direction_second_friction,&imp_solver_stack.sin_second_friction
void IVP_Impact_Solver::get_world_direction_second_friction(IVP_Contact_Point *cp) { //IVP_U_Float_Point *ret_second_friction_vec,IVP_FLOAT *sin_second_friction) {
IVP_Material *mtl[2];
cp->get_material_info(mtl);
IVP_U_Float_Point *ret_second_friction_vec=&world_direction_second_friction;
IVP_BOOL use_second_friction=IVP_FALSE;
int i;
for(i=0;i<2;i++) {
if(mtl[i]->second_friction_x_enabled) {
#if 1
//following is copy-paste from function 'two_values_friction'
//-> maybe make common structure and fill it
IVP_U_Float_Point x_direction;
IVP_Core *i_core=cp->get_synapse(i)->l_obj->friction_core;
IVP_U_Matrix *mat=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -