📄 ivp_mindist.cxx
字号:
}
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 + -