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

📄 ivp_mindist.cxx

📁 hl2 source code. Do not use it illegal.
💻 CXX
📖 第 1 页 / 共 4 页
字号:
	    }
		IVP_ASSERT(new_collisions.n_elems <= new_collisions.memsize);
	    const IVP_Compact_Triangle *tri1 = l1->get_first_triangle();
	    new_mindist->init_mindist(pop0, pop1, tri0->get_first_edge(),tri1->get_first_edge());
		IVP_ASSERT(new_collisions.n_elems <= new_collisions.memsize);
	    new_collisions.add(new_mindist);
		IVP_ASSERT(new_collisions.n_elems <= new_collisions.memsize);
	}
    }
    { // delete unused collisions
	for ( int x = mindists->len()-1; x >= diff_hash.n_found_objects; x--){
	    IVP_Collision *c = mindists->element_at(x);
	    delete c;
	}
    }
    { // add new collisions
	for (int x = new_collisions.len()-1; x>=0; x--){
	    IVP_Collision *c = new_collisions.element_at(x);
	    mindists->add(c);
	}
    }
    
#if 0
    { // check final mindists elements
	for (int x = mindists->len()-1; x>=0; x--){
	    IVP_Collision *c = mindists->element_at(x);
	    const IVP_Compact_Ledge *ledges[2];
	    c->get_ledges(ledges);
	    IVP_ASSERT( ledges0.index_of( ledges[0] ) >= 0 && ledges1.index_of( ledges[1] )  >= 0 );
	}
    }
    { // check all ledge ledge combinations
	for (int i= ledges0.len()-1; i>=0; i--){
	    const IVP_Compact_Ledge *l0 = ledges0.element_at(i);
	    for (int j = ledges1.len()-1;j>=0;j--){
		const IVP_Compact_Ledge *l1 = ledges1.element_at(j);
		int x;
		for (x = mindists->len()-1; x>=0; x--){
		    IVP_Collision *c = mindists->element_at(x);
		    const IVP_Compact_Ledge *ledges[2];
		    c->get_ledges(ledges);
		    if (ledges[0] == l0 && ledges[1] == l1) {
			x = -1;
			break;
		    }
		}
		IVP_ASSERT( x = -1);
	    }
	}
    }
#endif	    

}


void IVP_Mindist_Manager::insert_exact_mindist( IVP_Mindist *new_mindist){
  IVP_ASSERT(new_mindist->mindist_status == IVP_MD_UNINITIALIZED);
  new_mindist->mindist_status = IVP_MD_EXACT;
  
  new_mindist->next = this->exact_mindists;
  new_mindist->prev = NULL;

  if(new_mindist->next){
    new_mindist->next->prev=new_mindist;
  }
  this->exact_mindists = new_mindist;
  
  IVP_Synapse_Real *syn0 = new_mindist->get_synapse(0);
  IVP_Synapse_Real *syn1 = new_mindist->get_synapse(1);

  syn0->insert_exact_synapse_in_object();
  syn1->insert_exact_synapse_in_object();
  
  if ((syn0->get_core()->car_wheel || syn1->get_core()->car_wheel))
  {
	  if ( new_mindist->mindist_function != IVP_MF_PHANTOM )
	  {
		  //ivp_message("exact mindist inserted %x at %f\n", new_mindist, syn0->get_object()->get_environment()->get_current_time().get_seconds());
		  wheel_look_ahead_mindists.add(new_mindist);
	  }
  }
  
}

void IVP_Mindist_Manager::insert_invalid_mindist( IVP_Mindist *new_mindist){
  IVP_ASSERT(new_mindist->mindist_status == IVP_MD_UNINITIALIZED);
  new_mindist->mindist_status = IVP_MD_INVALID;
  
  new_mindist->next = this->invalid_mindists;
  new_mindist->prev = NULL;

  if(new_mindist->next){
    new_mindist->next->prev=new_mindist;
  }
  this->invalid_mindists = new_mindist;
  new_mindist->get_synapse(0)->insert_invalid_synapse_in_object();
  new_mindist->get_synapse(1)->insert_invalid_synapse_in_object();
}

void IVP_Mindist::exact_mindist_went_invalid(IVP_Mindist_Manager *mm){
    mm->remove_exact_mindist(this);
    mm->insert_invalid_mindist(this);
}

// #+# kill this function due data cache problems on PSXII
void IVP_Mindist_Manager::insert_and_recalc_exact_mindist( IVP_Mindist *new_mindist){

    IVP_ASSERT(new_mindist->mindist_status == IVP_MD_UNINITIALIZED);
    IVP_ASSERT(new_mindist->mindist_function != IVP_MF_PHANTOM);
    
    new_mindist->mindist_status = IVP_MD_EXACT;
    
    new_mindist->next = this->exact_mindists;
    new_mindist->prev = NULL;

    if(new_mindist->next){
	new_mindist->next->prev=new_mindist;
    }

    IVP_Synapse_Real *syn0 = new_mindist->get_synapse(0);
    IVP_Synapse_Real *syn1 = new_mindist->get_synapse(1);
    
    syn0->insert_exact_synapse_in_object();
    syn1->insert_exact_synapse_in_object();
    
    //TL : when obj is revived it gets all mindists and builds friction system -> do not move mindist into hull
    
    this->exact_mindists = new_mindist;
    new_mindist->recalc_mindist();

    if ((syn0->get_core()->car_wheel || syn1->get_core()->car_wheel)){
	//ivp_message("exact mindist inserted %x at %f\n", new_mindist, syn0->get_object()->get_environment()->get_current_time().get_seconds());
	wheel_look_ahead_mindists.add(new_mindist);
    }

    
    if (new_mindist->recalc_result == IVP_MDRR_OK){
	IVP_Core *core0=new_mindist->get_synapse(0)->l_obj->physical_core;
	IVP_Core *core1=new_mindist->get_synapse(1)->l_obj->physical_core;
	IVP_Movement_Type allow_hull_bit;
	allow_hull_bit=(IVP_Movement_Type)((core0->movement_state)|(core1->movement_state));
	IVP_BOOL allow_hull_conversion;
	if(allow_hull_bit>=IVP_MT_GET_MINDIST)  {
	    allow_hull_conversion = IVP_FALSE;
	} else {
	    allow_hull_conversion = IVP_TRUE;
	}
	new_mindist->update_exact_mindist_events(allow_hull_conversion,IVP_EH_NOW);
    }else{
	new_mindist->exact_mindist_went_invalid(this);
    }
}

void IVP_Mindist_Manager::insert_and_recalc_phantom_mindist( IVP_Mindist *new_mindist){
    IVP_ASSERT(new_mindist->mindist_status == IVP_MD_UNINITIALIZED);
    IVP_ASSERT(new_mindist->mindist_function == IVP_MF_PHANTOM);
    
    new_mindist->recalc_invalid_mindist();  // be carefull, avoid deep recursions
    
    IVP_FLOAT uncertanty;
    if (new_mindist->recalc_result == IVP_MDRR_OK){
      if (new_mindist->get_length() > 0.0f){
	  if (new_mindist->is_in_phantom_set ){
	      mindist_left_phantom(new_mindist);
	  }
	  insert_exact_mindist(new_mindist);
	  new_mindist->update_exact_mindist_events(IVP_TRUE ,IVP_EH_BIG_DELAY);

	  return;
      }
      uncertanty =   - new_mindist->get_length();
    }else{
      uncertanty =   new_mindist->sum_extra_radius;
    }
    
    if(!new_mindist->is_in_phantom_set )
    {
	mindist_entered_phantom(new_mindist);
    }
    
    {
      IVP_Synapse_Real *syn = new_mindist->get_synapse(0);
      IVP_Real_Object *obj = syn->l_obj;
      IVP_Controller_Phantom *cp = obj->get_controller_phantom();
      if (cp){
	uncertanty += cp->exit_policy_extra_radius;
      }else{
	  IVP_Synapse_Real *syn2 = new_mindist->get_synapse(1);
	  IVP_Real_Object *obj2 = syn2->l_obj;
	  IVP_Controller_Phantom *cp2 = obj2->get_controller_phantom();
	  if (cp2){
	      uncertanty += cp2->exit_policy_extra_radius;
	  }
      }
    }
    insert_lazy_hull_mindist( new_mindist, uncertanty);    
}

class IVP_OO_CMP {
public:
    static inline int calc_hash_index( IVP_Real_Object * o){
	int x = (int)o;
	return x + 1023 * (x>>8);
    }

    // calc hash index of c, con is a reference
    static inline int calc_hash_index( IVP_Collision *c, IVP_Real_Object * con){
	IVP_Real_Object *objects[2];
	c->get_objects(objects);
	int x = int(objects[0]) ^ int(objects[1]) ^ int(con);  // take other object (trick to avoid if)
	IVP_ASSERT( objects[0] == con || objects[1] == con );
	return x + 1023 * (x>>8);
    }

    static inline IVP_BOOL are_equal( IVP_Collision *c, IVP_Real_Object *search ){
	IVP_Real_Object *objects[2];
	c->get_objects(objects);
	if (objects[0] == search) return IVP_TRUE;
	if (objects[1] == search) return IVP_TRUE;
	return IVP_FALSE;
    }
};

class IVP_Vector_of_OV_Elements_128 : public IVP_U_Vector<class IVP_OV_Element> {
    void *elem_buffer[128];
public:
    IVP_Vector_of_OV_Elements_128(): IVP_U_Vector<class IVP_OV_Element>(&elem_buffer[0],128){;};
};

//vector of cores with 2 default elements already alloced
class IVP_Vector_of_Objects_128: public IVP_U_Vector<class IVP_Real_Object> {
    IVP_Real_Object *elem_buffer[128];
public:
    IVP_Vector_of_Objects_128(): IVP_U_Vector<IVP_Real_Object>( (void **)&elem_buffer[0],128 ){;};
};

void IVP_Mindist_Manager::recheck_ov_element(IVP_Real_Object *object){

    IVP_Vector_of_OV_Elements_128 colliding_elements; // for recheck_ov_element

    IVP_OV_Element *elem = object->get_ov_element();

    if(!elem) 
		return; // not collision enabled 

    // check surrounding

    // check, whether old elem is still useable
    IVP_Core *core = object->get_core();
    const IVP_U_Point *object_position = core->get_position_PSI();
    
#if 0
    const IVP_DOUBLE use_old_hull_factor = 0.5f;
    IVP_U_Point sphere_position; sphere_position.set(elem->center);

    IVP_DOUBLE moved_distance = sphere_position.quad_distance_to(object_position);
    IVP_DOUBLE old_hull_time = elem->radius - core->upper_limit_radius;
    if (moved_distance < use_old_hull_factor * old_hull_time){
	return;
    }
#endif
    environment->ov_tree_manager->remove_ov_element( elem);

    environment->get_statistic_manager()->range_world_exceeded++;

    elem->center.set(object_position);

    IVP_DOUBLE radius;

    IVP_Hull_Manager *hm = object->get_hull_manager();

    if (!scanning_universe)	{	// check for new objects in the universe manager
	IVP_DOUBLE hull_time = environment->range_manager->get_coll_range_in_world(object);	// distance to check
	IVP_DOUBLE real_check_sphere = hull_time + core->upper_limit_radius;

	IVP_Universe_Manager *um = environment->get_universe_manager();
	if (um){
	    // only ask for new objects if object can collide 
	    IVP_Movement_Type mt = object->get_movement_state();
	    if ( IVP_MTIS_CAN_COLLIDE(mt)){
		scanning_universe = IVP_TRUE;   // needed to avoid recursion
		um->ensure_objects_in_environment( object, &elem->center, real_check_sphere);
		scanning_universe = IVP_FALSE;  // finished
	    }
	}
	radius = environment->ov_tree_manager->insert_ov_element( elem, real_check_sphere, real_check_sphere, &colliding_elements);
	
	IVP_DOUBLE real_hull_time =   radius - core->upper_limit_radius;
	elem->add_to_hull_manager( hm, real_hull_time );	    // insert into event queue
	
    } else {	// recursive call by IVP_Universe_Manager, use minimal radius
	IVP_DOUBLE real_check_sphere = core->upper_limit_radius;
	radius = environment->ov_tree_manager->insert_ov_element( elem, real_check_sphere, real_check_sphere, NULL);
	IVP_DOUBLE real_hull_time =   P_DOUBLE_EPS;	// recheck as soon as possible because it's not checked now
	elem->add_to_hull_manager( hm, real_hull_time );	    // insert into event queue
	return;			// thats it, IVP_Universe_Manager can only add objects which do not have collision candidates except object
    }

    IVP_Collision_Filter *coll_filter = environment->get_collision_filter();

    short a_buffer[1024];
    int buffer_size = 1024;
    { // optimize buffersize in order to reduce memory fills at diffhash
	int ref_size = elem->collision_fvector.len() + colliding_elements.len() + 1;
	ref_size <<= 2;
	while ( buffer_size > ref_size) buffer_size >>= 1;
    }
    // convert old list into hash
    IVP_Diff_Hash<IVP_OO_CMP, IVP_U_FVector<IVP_Collision>,IVP_Collision, IVP_Real_Object> diff_hash( &elem->collision_fvector, a_buffer, buffer_size, object );

    // compare new and old list and create/delete elements accordingly
    // old elements will be sorted to the start of the vector
    // unused to the end
    // new objects into a new vector
    IVP_Vector_of_Objects_128 new_objects;
    
    { // compare new list with old list
      for (int i= colliding_elements.len()-1;i>=0;i--){
	IVP_OV_Element *el = colliding_elements.element_at(i); 

	// now build a new one
	IVP_Real_Object *obj0=object;
	IVP_Real_Object *obj1=el->real_object;
	if( !IVP_MTIS_CAN_COLLIDE(obj0->get_movement_state()) && !IVP_MTIS_CAN_COLLIDE( obj1->get_movement_state())){
	  continue; 
	}
	if(obj0->friction_core == obj1->friction_core) 
	    continue;

	if((obj0->get_core()->pinned && obj1->get_core()->pinned) ||
		(obj0->get_core()->pinned && obj1->get_core()->physical_unmoveable) ||
		(obj0->get_core()->physical_unmoveable && obj1->get_core()->pinned))
	    continue;
	
	if (coll_filter->check_objects_for_collision_detection(obj0,obj1) == IVP_FALSE) continue;
	// search for existing
	if ( diff_hash.check_element( obj1, obj0 )){
	    continue;
	}
	new_objects.add(obj1);
      }
    }
    { // delete unused collisions
	for ( int x = elem->collision_fvector.len()-1; x >= diff_hash.n_found_objects; x--){
	    IVP_Collision *c = elem->collision_fvector.element_at(x);
		//
		// HACKHACK: E3 2003, get around delete of collision object that is calling us up the stack
		//
		if ( c != g_pCurrentMindist )
		{
		    P_DELETE(c);
		}
		else
		{
			g_fDeferDeleteMindist = true;
		}
	}
    }
    { // create new ones
	for ( int x = new_objects.len()-1; x>=0; x -- ) {
	    IVP_Real_Object *obj1 = new_objects.element_at(x);
	    for (int k = environment->collision_delegator_roots.len()-1; k>=0; k--){
		IVP_Collision_Delegator_Root *cdr = environment->collision_delegator_roots.element_at(k);
		IVP_Collision *coll = cdr->delegate_collisions_for_object(object, obj1);
		if (coll) break;
	    }
	}
    }
}

 
void IVP_Mindist_Manager::enable_collision_detection_for_object(IVP_Real_Object *object){
    P_DELETE(object->ov_element);
    object->ov_element = new IVP_OV_Element(object);
    recheck_ov_element(object);
}


/** recalculation of all exact mindist at the end of PSI */
void IVP_Mindist_Manager::recalc_all_exact_mindists_events()
{
	IVP_Mindist *mdist, *mdist_next;
	
	for( mdist=this->exact_mindists; mdist; mdist=mdist_next )
	{
		mdist_next = mdist->next;
		IVP_ASSERT(mdist->mindist_status == IVP_MD_EXACT);
		IVP_IF_PREFETCH_ENABLED(mdist_next)
		{
			IVP_PREFETCH_BLOCK(mdist_next,sizeof(*mdist_next));
		}
		mdist->update_exact_mindist_events(IVP_TRUE, IVP_EH_SMALL_DELAY);
	}
}

/** recalculation of all exact mindist at the end of PSI */
void IVP_Mindist_Manager::recalc_all_exact_wheel_mindist()
{
	for ( int i = wheel_look_ahead_mindists.len()-1; i>=0; i--)
	{
		IVP_Mindist *mdist = wheel_look_ahead_mindists.element_at(i);
		
		IVP_ASSERT( mdist->mindist_function != IVP_MF_PHANTOM );
		this->recalc_exact_mindist(mdist);
		
		IVP_Synapse_Real *syn0 = mdist->get_sorted_synapse(0);
		IVP_Synapse_Real *syn1 = mdist->get_sorted_synapse(1);
		
		if (syn0->get_status()!=IVP_ST_BALL) 
		{
			IVP_Synapse_Real *temp=syn0;    
			syn0=syn1;    
			syn1=temp;
		}

⌨️ 快捷键说明

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