⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ivp_impact.cxx

📁 hl2 source code. Do not use it illegal.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
// Copyright (C) Ipion Software GmbH 1999-2000. All rights reserved.


#ifndef WIN32
#	pragma implementation "ivp_contact_situation.hxx"
#endif

#include <ivp_physics.hxx>
#include <ivu_memory.hxx>

#include <ivp_compact_ledge.hxx>
#include <ivp_cache_object.hxx>

#include <ivp_physic_private.hxx>
#include <ivp_sim_unit.hxx>
#include <ivp_core_macros.hxx>
#include <ivp_material.hxx>
#include <ivp_impact.hxx> 
#include <ivp_mindist_intern.hxx>
#include <ivp_friction.hxx>
#include <ivp_hull_manager.hxx>
#include "ivp_mindist_macros.hxx"
#include <ivp_listener_collision.hxx>
#include <ivp_calc_next_psi_solver.hxx>
#include <ivp_debug_manager.hxx>
#include <ivp_anomaly_manager.hxx>

#define IVP_SAFETY_FACTOR_FOR_DELAY 1.2f
#define IVP_INV_SAFETY_FACTOR_FOR_DELAY 1.0f/IVP_SAFETY_FACTOR_FOR_DELAY
#define IVP_ROT_MAX_UNCERTAINTY 0.5f // max rot degree speed uncertainty for rescue_speed
#define IVP_COLL_DETECT_MIN_INV_TIME 200.0f // inverse time we have to make sure no collision occurs
#define IVP_COLL_DETECT_MIN_TIME 1.0f/IVP_COLL_DETECT_MIN_INV_TIME
#define IVP_SPEED_ADDON_SYSTEM_IMPACT 0.01f
#define IVP_INV_HALF_CONSERVATION_STEPS 0.5f // elasticity is raised with number of impacts in system, at 1.0f/IVP_INV_HALF_CONSERVATION_STEPS the elasticity is at least 0.5
#define MAXIMUM_SYSTEM_PUSH_NUMBER 5000
#define MINIMAL_IMPACT_VELOCITY_FIXPOINT -11.552f
#define IMPACT_EPS 10E-5f

//#define EASEONIMPACT //doesnt work with balls // #+# kill and remove dependent functions
#define SYSTEM_IMPACT_ENABLED 

// generates friction mindist from mindist when no friction mindist exists and makes sure that friction mindist (generated or not) is up to date
// sim_unit_not_destroy is the one that has to remain after fusion

IVP_Contact_Point *IVP_Mindist::try_to_generate_managed_friction(IVP_Friction_System **associated_fs,IVP_BOOL *having_new,IVP_Simulation_Unit *sim_unit_not_destroy,IVP_BOOL call_recalc_svals){
    
    IVP_Mindist *my_dist = this;
    IVP_Real_Object *obj0 = get_sorted_synapse(0)->l_obj;
    IVP_Real_Object *obj1 = get_sorted_synapse(1)->l_obj;


    IVP_IF(obj0->get_environment()->debug_information->debug_friction){
	printf("new_fri_mindist\n");
    }

    IVP_Friction_System *fr_sys0,*fr_sys1;
    IVP_Friction_Info_For_Core *fr_info0,*fr_info1;

    IVP_Core *core0 = obj0->friction_core;
    IVP_Core *core1 = obj1->friction_core;
    
    if(core0->physical_unmoveable){
	IVP_Core *temp_core;
	temp_core=core0;
	core0=core1;
	core1=temp_core;
    }
    
    //core0 is now movable
    
    fr_info0=core0->moveable_core_has_friction_info();
    
    IVP_Environment *my_env = core0->environment;
    IVP_Contact_Point *friction_dist;
    IVP_BOOL gen_success;
    
    friction_dist = IVP_Friction_Manager::generate_contact_point(my_dist,&gen_success);
    {
	if(gen_success!=IVP_TRUE) {
	    *associated_fs=fr_info0->l_friction_system;
	    *having_new=IVP_FALSE;
	    if(call_recalc_svals) {
		friction_dist->recalc_friction_s_vals();
		friction_dist->read_materials_for_contact_situation(friction_dist->tmp_contact_info);		
	    }
	    return friction_dist;
	}
    }
    if(call_recalc_svals) {
	friction_dist->recalc_friction_s_vals(); // this is overhead, because nearly the same function was called for the associated mindist
	friction_dist->read_materials_for_contact_situation(friction_dist->tmp_contact_info);
    }

    {
	IVP_Event_Friction event_friction;
	IVP_Environment *env = obj0->get_environment();
	event_friction.environment = env;
	event_friction.contact_situation= friction_dist->tmp_contact_info; //is inherited
	event_friction.friction_handle = friction_dist;
	env->fire_event_friction_created(&event_friction);
	{
	    if (obj0->flags.collision_listener_exists){
		IVP_Cluster_Manager *clus_man = env->get_cluster_manager();
		clus_man->fire_event_friction_created(obj0, &event_friction);
	    }
	    if (obj1->flags.collision_listener_exists){
		IVP_Cluster_Manager *clus_man = env->get_cluster_manager();
		clus_man->fire_event_friction_created(obj1, &event_friction);
	    }
	}
    }
    
    // IVP_ASSERT(my_env->get_mindist_manager()->debug_test_having_fr_mindist(friction_dist)==IVP_TRUE);
    
    *having_new=IVP_TRUE;
    
    IVP_Friction_System *affected_fs;
    
    if(fr_info0)
	{
	    fr_sys0=fr_info0->l_friction_system;
	    fr_info1=core1->get_friction_info(fr_sys0);
	    if(fr_info1)
		{
		    //both objects have same friction_system
		    fr_sys0->add_dist_to_system(friction_dist);
		    fr_sys0->dist_added_update_pair_info(friction_dist);
		    //fr_sys0->fr_solver.calc_calc_solver(fr_sys0);
		    affected_fs=fr_sys0;
		} else {
		    if(core1->physical_unmoveable)
			{
				// obj1 may have other friction systems. Doesnt matter systems act independently.
			    goto add_second_to_first;
			} else {
			    fr_info1=core1->moveable_core_has_friction_info(); //obj1 is movable and so has only one fr_sys
			    if(fr_info1)
				{
				    //movable object has already a different system, fusion systems
				    //core0->environment->get_friction_manager()->fusion_friction_systems(fr_sys0,fr_info1->l_friction_system);
				    fr_sys0->fusion_friction_systems(fr_info1->l_friction_system);
				    goto add_second_to_first_dist_only;
				} else {
				add_second_to_first:		    
				    // add second core to system of first core
				    fr_info1=new IVP_Friction_Info_For_Core();
				    fr_info1->l_friction_system=fr_sys0;
				    core1->add_friction_info(fr_info1);
				    fr_sys0->add_core_to_system(core1);
		    
				add_second_to_first_dist_only:		    
				    fr_sys0->add_dist_to_system(friction_dist);
				    fr_sys0->dist_added_update_pair_info(friction_dist);
				    //fr_sys0->fr_solver.calc_calc_solver(fr_sys0);
				    affected_fs=fr_sys0;
				}
			}
		}
	} else {
	    //first obj has no friction system, first make info-block
	    fr_info0=new IVP_Friction_Info_For_Core();
	    //core0->add_friction_info(fr_info0);		    

	    if(core1->physical_unmoveable)
		{
		    // obj may have other systems that act independently. Make new system
		    goto new_system_for_both_objects;
		} else {
		    fr_info1=core1->moveable_core_has_friction_info();
		    if(fr_info1)
			{
				// add obj0 to system of obj1
			    fr_sys1=fr_info1->l_friction_system;
			    fr_info0->l_friction_system=fr_sys1;
			    core0->add_friction_info(fr_info0);
			    fr_sys1->add_core_to_system(core0);
			    fr_sys1->add_dist_to_system(friction_dist);
			    fr_sys1->dist_added_update_pair_info(friction_dist);
				//fr_sys1->fr_solver.calc_calc_solver(fr_sys1);
			    affected_fs=fr_sys1;
		
			} else {
				// make a new system for both objects
			new_system_for_both_objects:
			    IVP_Friction_System *new_system;
			    new_system=new IVP_Friction_System(my_env);
			    fr_info1=new IVP_Friction_Info_For_Core();
			    fr_info0->l_friction_system=new_system;
			    fr_info1->l_friction_system=new_system;
			    core1->add_friction_info(fr_info1);		    
			    core0->add_friction_info(fr_info0);		    
		
				//my_env->get_friction_manager()->add_friction_system(new_system);
			    new_system->add_dist_to_system(friction_dist);
			    new_system->dist_added_update_pair_info(friction_dist);
				//new_system->fr_solver.calc_calc_solver(new_system);		
			    new_system->add_core_to_system(core0);
			    new_system->add_core_to_system(core1);
			    affected_fs=new_system;
			}
		}
	}
    
    //allow to go from object to its distances
    fr_info0->friction_info_insert_friction_dist(friction_dist);
    fr_info1->friction_info_insert_friction_dist(friction_dist);
#ifdef EASEONIMPACT
    fr_info0->set_all_dists_of_obj_neutral();
    fr_info1->set_all_dists_of_obj_neutral();
#endif    

    //printf("add_fri_dist %lx to sys %lx\n",(long)friction_dist,(long)affected_fs); UFTEST

    *associated_fs=affected_fs;
    //friction_dist->l_friction_system=affected_fs;
#ifdef DEBUG
    IVP_IF(0) {
	IVP_Friction_System *fs0,*fs1;
	fs0=NULL;
	fs1=NULL;
	if(!core0->physical_unmoveable) {
	    IVP_Friction_Info_For_Core *info_friction=core0->moveable_core_has_friction_info();
	    if(info_friction) {
		fs0=info_friction->l_friction_system;
	    }
	}
	if(!core1->physical_unmoveable) {
	    IVP_Friction_Info_For_Core *info_for_core=core1->moveable_core_has_friction_info();
	    if(info_for_core) {
		fs1=info_for_core->l_friction_system;
	    }
	}
	printf("\nmaking_new_frdist for cores %lx %d  %lx %d  fss %lx %lx  with sim_units: %lx %lx\n",
	       (long)core0,core0->physical_unmoveable,
	       (long)core1,core1->physical_unmoveable,
	       (long)fs0,(long)fs1,(long)core0->sim_unit_of_core,(long)core1->sim_unit_of_core);
	core0->sim_unit_of_core->sim_unit_debug_out();
	core1->sim_unit_of_core->sim_unit_debug_out();
    }
#endif        
    friction_dist->calc_virtual_mass_of_mindist();
    
    IVP_IF(obj0->get_environment()->get_debug_manager()->check_fs) {
	affected_fs->test_hole_fr_system_data();
    }
    
    IVP_Simulation_Unit *sim0,*sim1;
    sim0=core0->sim_unit_of_core;
    sim1=core1->sim_unit_of_core;

    if( !(core1->physical_unmoveable | core0->physical_unmoveable) ) {
	if(sim0!=sim1) {
	    if(sim1==sim_unit_not_destroy) {
		sim1->fusion_simulation_unities(sim0);
		P_DELETE(sim0);
	    } else {
		sim0->fusion_simulation_unities(sim1);
		P_DELETE(sim1);
	    }
	}
    }
#ifdef DEBUG    
    IVP_IF(1) {
	if(!core0->physical_unmoveable) {
	    core0->sim_unit_of_core->sim_unit_debug_consistency();
	}
	if(!core1->physical_unmoveable) {
	    core1->sim_unit_of_core->sim_unit_debug_consistency();
	}
    }
#endif    
    return friction_dist;
}

IVP_DOUBLE IVP_Impact_Solver::get_total_energy(){
    // energy of both objects doing impact
    IVP_DOUBLE ener;
    ener =  core[0]->get_energy_on_test(&trans_speed[0],&rot_speed[0])
	+   core[1]->get_energy_on_test(&trans_speed[1],&rot_speed[1]);
    IVP_IF(core[0]->environment->debug_information->debug_impact)	{
	    IVP_DOUBLE trans_e=trans_speed[1].quad_length() * core[1]->get_mass();
	    IVP_U_Float_Point hp;
	    hp.set_pairwise_mult( &rot_speed[1], &rot_speed[1]);
	    IVP_DOUBLE rot_e = hp.dot_product(core[1]->get_rot_inertia());
	
	    printf("total_energies trans %.3f rot %.3f sum %.3f\n",0.5f*trans_e,0.5f*rot_e,ener);
	}
    return ener;
}

//get relative world speed seen from obj 0
void IVP_Impact_Solver::get_relative_speed_vector()
{
    IVP_U_Float_Point world_speed0,world_speed1;
    core[0]->get_surface_speed_on_test(obj_point[0],&trans_speed[0],&rot_speed[0],&world_speed0);
    core[1]->get_surface_speed_on_test(obj_point[1],&trans_speed[1],&rot_speed[1],&world_speed1);
    relative_world_speed.subtract(&world_speed1,&world_speed0);
    //relative_world_speed is now relative speed seen from now still object 0
}

// calculates push direction vector. length of vector is 1.0
// if vector isnt steep enough for friction, vector is adjusted (made steepeer).
// function is used by 'do_push' and before 'estimate_push_impulse'
void IVP_Impact_Solver::get_world_push_direction()
{
    //given : relative_world_speed;
    //wanted : vector world_push_direction giving direction of push (normized)
    //world_push_direction differs from relative_world_speed if allowed friction is exceeded. then length is also smaller than 1.0f 

    IVP_U_Float_Point part_in_direction_surf; //decomposition of velo vec in direction normal and rest (this is the rest)

    world_push_direction.set(&relative_world_speed);
    world_push_direction.fast_normize();

    IVP_DOUBLE angle=world_push_direction.dot_product(surf_normal); // is negativ. the greater (absolut) the steeper is angle
    //angle is cos alpha . alpha seen from surface normal

    IVP_IF(core[0]->environment->debug_information->debug_impact)
    {
      printf("wpd %.2f %.2f %.2f  ",world_push_direction.k[0],world_push_direction.k[1],world_push_direction.k[2]);
    }
    if((angle>0.0f))
    {
	//turnaround_next_time: objects may still be closing, but is only rest speed that can be neglected, as lowest energy point of impact was already traversed
	IVP_IF(core[0]->environment->debug_information->debug_impact)
	{
	    printf(" impact_speed_now_reversed ");
	}
	//world_push_direction.set(surf_normal);
	//world_push_direction.mult(-1.0f);
	world_push_direction.set(&integral_pushes_world);
	world_push_direction.fast_normize();
	//angle=-angle;
	//world_push_direction.subtract(surf_normal); // impact direction is mirrored relative to surface
	return;
    } else {
      IVP_IF(core[0]->environment->debug_information->debug_impact){
	  printf(" not_reversed ");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -