📄 ivp_impact.cxx
字号:
IVP_DOUBLE push_v0,push_v1;
push_v0=0.0f;
//printf("absolute_velocity %.2f ",relative_world_speed.real_length());
push_v1= - relative_world_speed.dot_product(surf_normal);
IVP_DOUBLE u0,u1; //speed results after push
IVP_DOUBLE div_masses=1.0f/(virt_mass[0]+virt_mass[1]);
//not maximal fast
u0=(2.0f*virt_mass[1]*push_v1+push_v0*(virt_mass[0]-virt_mass[1]));
u1=(2.0f*virt_mass[0]*push_v0+push_v1*(virt_mass[1]-virt_mass[0]));
u0*=div_masses;
u1*=div_masses;
IVP_DOUBLE diff_v0=u0-push_v0;
//IVP_DOUBLE diff_v1=u1-push_v1; //difference of velocity before/after impact
IVP_IF(core[0]->environment->debug_information->debug_impact)
{
printf("start_impulse %.2f\n",diff_v0*virt_mass[0]);
}
return(diff_v0*virt_mass[0]);
}
// #+# simplify this function a lot
void IVP_Impact_Solver_Long_Term::do_impact_of_two_objects(IVP_Mindist *mindist, IVP_Real_Object *obj0, IVP_Real_Object *obj1 )
{
// coll_point in object_coordinates
// surface_normal in world_coords
// environment->debug_information->psi_synchrone=1;
// mindist->synapse[0]->l_obj->to_real()->revive_object_for_simulation();
// mindist->synapse[1]->l_obj->to_real()->revive_object_for_simulation();
IVP_Friction_System* affected_friction_system;
IVP_BOOL having_new_dist;
IVP_Core *core0 = obj0->get_core();
IVP_Core *core1 = obj1->get_core();
IVP_Simulation_Unit *sim_u;
if( obj0->get_movement_state() >= IVP_MT_NOT_SIM ) {
sim_u = core0->sim_unit_of_core;
} else {
sim_u = core1->sim_unit_of_core;
}
IVP_Contact_Point* my_fr_dist = mindist->try_to_generate_managed_friction(&affected_friction_system,&having_new_dist,sim_u,IVP_TRUE); //with recalc_friction_s_vals
IVP_Impact_Solver_Long_Term* imp_solve = my_fr_dist->tmp_contact_info;
IVP_Time now_time, last_time;
IVP_Friction_Core_Pair* pair = affected_friction_system->find_pair_of_cores(core0,core1);
now_time = mindist->get_environment()->get_current_time();
last_time = pair->last_impact_time_pair;
pair->last_impact_time_pair = now_time;
IVP_Environment* env = mindist->get_environment();
// printf("impactt\n");
IVP_Core *impacteers[2];
IVP_FLOAT rescue_val_addon = my_fr_dist->get_rescue_speed_impact(obj0->get_environment());
///////////////////////////////////////////////////////////////////////////
//@@VALVE
///////////////////////////////////////////////////////////////////////////
IVP_Event_Collision event_collision;
event_collision.d_time_since_last_collision = now_time - last_time;
event_collision.environment = env;
event_collision.contact_situation = imp_solve; //is inherited
env->fire_event_pre_collision( &event_collision );
{
if (obj0->flags.collision_listener_exists)
{
IVP_Cluster_Manager *clus_man = env->get_cluster_manager();
clus_man->fire_event_pre_collision(obj0, &event_collision);
}
if (obj1->flags.collision_listener_exists)
{
IVP_Cluster_Manager *clus_man = env->get_cluster_manager();
clus_man->fire_event_pre_collision(obj1, &event_collision);
}
}
imp_solve->do_impact_long_term(impacteers,rescue_val_addon,my_fr_dist);
IVP_U_Float_Point speed_for_callback;
speed_for_callback.set(&imp_solve->speed);
if( core1->physical_unmoveable ) {
speed_for_callback.mult(-1.0f); //IVP_Impact_Solver_Long_Term changes order when core1 is unmovable @@CB fptodp
}
// if((having_new_dist==IVP_FALSE)||1)
{
IVP_Impact_System imp_sys;
imp_sys.init_and_solve_impact_system(mindist, affected_friction_system, pair, my_fr_dist);
}
// copy changed values
event_collision.contact_situation = imp_solve; //is inherited
imp_solve->speed.set(&speed_for_callback);
env->fire_event_post_collision(&event_collision);
{
if (obj0->flags.collision_listener_exists)
{
IVP_Cluster_Manager *clus_man = env->get_cluster_manager();
clus_man->fire_event_post_collision(obj0, &event_collision);
}
if (obj1->flags.collision_listener_exists)
{
IVP_Cluster_Manager *clus_man = env->get_cluster_manager();
clus_man->fire_event_post_collision(obj1, &event_collision);
}
}
}
#if 0
if(0) { //merge example!!
IVP_Core *core_to_merge=mindist->get_synapse(0)->get_object()->physical_core;
IVP_Core *other_core0=mindist->get_synapse(1)->get_object()->physical_core;
if(core_to_merge->physical_unmoveable){
IVP_Core *h = core_to_merge; core_to_merge = other_core0; other_core0 = h;
}
IVP_ASSERT(core_to_merge->physical_unmoveable == IVP_FALSE);
IVP_Core *other_core1;
other_core1=IVP_Impact_Solver_Long_Term::find_second_critical_impact_core(core_to_merge,other_core0);
if(other_core1!=NULL){
IVP_Core *best_other_core = IVP_Impact_Solver_Long_Term::get_best_merge_core(core_to_merge,other_core0,other_core1);
core_to_merge->create_collision_merged_core_with(best_other_core);
}
}
#endif
void IVP_Contact_Point::get_material_info(IVP_Material *mtl[2]) {
int k;
for(k=0;k<2;k++) {
int mat_index = this->get_synapse(k)->get_material_index();
if (mat_index == 0){
mtl[k] = get_synapse(k)->get_object()->l_default_material;
}else{
IVP_Environment *env = get_synapse(0)->get_object()->get_environment();
mtl[k] = env->get_material_manager()->get_material_by_index(0,mat_index); // @@@@@
}
IVP_ASSERT(mtl[k]);
}
}
void IVP_Impact_Solver::get_cos_sin_for_impact(IVP_FLOAT friction_val,IVP_FLOAT percent_energy_conservation,IVP_FLOAT *cos_val,IVP_FLOAT *sin_val) {
IVP_DOUBLE impact_fri_fact=friction_val * (1.0f + IVP_Inline_Math::ivp_sqrtf(percent_energy_conservation));
IVP_DOUBLE fri_angle = IVP_Inline_Math::atand(impact_fri_fact); // #+# bitter, kill,
IVP_DOUBLE c = IVP_Inline_Math::approx5_cos(fri_angle);
*cos_val = c;
*sin_val = c * impact_fri_fact;
}
void IVP_Contact_Point::read_materials_for_contact_situation(IVP_Impact_Solver_Long_Term *info) {
IVP_Real_Object *obj0,*obj1;
obj0 = get_synapse(0)->get_object(); //syn0->get_ivp_polygon();
obj1 = get_synapse(1)->get_object(); //syn1->get_ivp_polygon();
get_material_info(info->materials);
IVP_Environment *env = obj0->get_environment();
//////// IVP_Contact_Situation
info->objects[0] = obj0; // IVP_Contact_Situation
info->objects[1] = obj1;
info->compact_edges[0] = get_synapse(0)->edge;
info->compact_edges[1] = get_synapse(1)->edge;
IVP_ASSERT(obj0 != obj1);
IVP_Material_Manager *mtlm = env->get_material_manager();
info->impact.percent_energy_conservation = mtlm->get_elasticity(info);
this->real_friction_factor = mtlm->get_friction_factor(info);
}
extern IVP_Mindist *g_pCurrentMindist;
extern bool g_fDeferDeleteMindist;
// assert: recalc_mindist called
// assert: mindist of EXACT
// actions perform the impact of two real (!) objects with all !!! side effects
// #+# simplify, move synchronize and revive to do_impact_of_two_objects
void IVP_Mindist::do_impact(){
g_pCurrentMindist = this;
IVP_Environment *env;
env=get_environment();
IVP_ASSERT( mindist_status == IVP_MD_EXACT);
// move variables too impact system
IVP_Real_Object *objects[2];
for (int i = 0;i<2;i++){
IVP_Synapse_Real *syn = this->get_synapse(i);
IVP_Real_Object *obj= syn->l_obj;
objects[i] = obj;
obj->revive_object_for_simulation();
}
g_pCurrentMindist = NULL;
if (g_fDeferDeleteMindist)
{
// BUGBUG: someone changed a collision filter and didn't tell us!
IVP_ASSERT(0);
delete this;
return;
}
//revive_object_core is calling start_memory_transaction and end_memory_transaction, so we cannot start memory transaction earlier
env->sim_unit_mem->start_memory_transaction();
for(int j=0;j<2;j++) {
IVP_Core *core=objects[j]->get_core();
if ( IVP_MTIS_SIMULATED(core->movement_state) && !core->pinned){ //@@CB
core->synchronize_with_rot_z();
}
}
env->mindist_event_timestamp_reference++;
IVP_Impact_Solver_Long_Term::do_impact_of_two_objects(this, objects[0], objects[1] );
env->sim_unit_mem->end_memory_transaction();
}
//find second critical core for core0 that is not core1
IVP_Core *IVP_Impact_Solver_Long_Term::find_second_critical_impact_core(IVP_Core *core0,IVP_Core *core1)
{
for(int c= core0->objects.len()-1;c>=0; c--){
IVP_Real_Object *r_obj=core0->objects.element_at(c);
for(IVP_Synapse_Real *synr=r_obj->get_first_exact_synapse();synr;synr=synr->get_next())
{
IVP_Mindist *mdist=synr->get_mindist();
//if(mdist->coll_watcher.nr_collisions_per_psi>4) {
if(1) { //change that!
for(int i=0;i<2;i++) {
IVP_Synapse_Real *syn;
syn=mdist->get_synapse(i);
IVP_Real_Object *obj=syn->get_object();
if((obj->physical_core!=core0)&&(obj->physical_core!=core1)) {
return obj->physical_core;
}
}
}
}
}
return NULL;
}
//merge (movable) core0 with core1 or core2. return best alternative
IVP_Core *IVP_Impact_Solver_Long_Term::get_best_merge_core(IVP_Core *core0,IVP_Core *core1,IVP_Core *core2)
{
IVP_Friction_Info_For_Core *fr_i=core0->moveable_core_has_friction_info();
if(!fr_i) {
return core1; //friction is disabled
}
IVP_Friction_System *fr_sys=fr_i->l_friction_system;
int anz_1=0;
int anz_2=0;
for (int i = fr_sys->fr_pairs_of_objs.len()-1; i>=0;i--){
IVP_Friction_Core_Pair *my_pair = fr_sys->fr_pairs_of_objs.element_at(i);
int my_1_nr;
if(my_pair->objs[0]==core0){
my_1_nr=1;
} else {
my_1_nr=0;
}
if(my_pair->objs[my_1_nr]==core1){
anz_1=my_pair->number_of_pair_dists();
}
if(my_pair->objs[my_1_nr]==core2) {
anz_2=my_pair->number_of_pair_dists();
}
}
if(anz_2>anz_1) {
return core2;
} else {
return core1;
}
}
void IVP_Impact_Solver_Long_Term::do_impact_long_term(IVP_Core *pushed_cores[2],IVP_FLOAT rescue_speed_val,IVP_Contact_Point *cp)
{
IVP_Impact_Solver imp_solver_stack;
IVP_U_Float_Point surf_normal_stack;
if(!contact_core[1]) {
imp_solver_stack.core[0] = objects[1]->get_core();
imp_solver_stack.core[1] = contact_core[0];
imp_solver_stack.obj_point[0]=&contact_point_cs[1];
imp_solver_stack.obj_point[1]=&contact_point_cs[0];
surf_normal_stack.set_negative(&surf_normal);
imp_solver_stack.surf_normal=&surf_normal_stack;
} else {
imp_solver_stack.core[0]=contact_core[0];
if (!contact_core[0]){
imp_solver_stack.core[0] = objects[0]->get_core();
}
imp_solver_stack.core[1]=contact_core[1];
imp_solver_stack.obj_point[0]=&contact_point_cs[0];
imp_solver_stack.obj_point[1]=&contact_point_cs[1];
imp_solver_stack.surf_normal=&surf_normal;
}
imp_solver_stack.speed=&speed; //return value
imp_solver_stack.percent_energy_conservation = this->impact.percent_energy_conservation;
imp_solver_stack.two_friction_values=IVP_FALSE;
if ( imp_solver_stack.core[0]->car_wheel || imp_solver_stack.core[1]->car_wheel ) {
imp_solver_stack.get_cos_sin_for_impact(0.0f, this->impact.percent_energy_conservation,&imp_solver_stack.cos_friction,&imp_solver_stack.sin_friction);
}else{
imp_solver_stack.get_cos_sin_for_impact(cp->real_friction_factor, this->impact.percent_energy_conservation,&imp_solver_stack.cos_friction,&imp_solver_stack.sin_friction);
if(cp->two_friction_values) {
imp_solver_stack.get_world_direction_second_friction(cp);//imp_solver_stack.two_friction_values=cp->get_world_direction_second_friction(&imp_solver_stack.world_direction_second_friction,&imp_solver_stack.sin_second_friction);
}
}
IVP_IF(1) {
if (contact_core[0]) contact_core[0]->core_plausible_check();
if (contact_core[1]) contact_core[1]->core_plausible_check();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -