Box2D Forums

It is currently Sat May 25, 2013 7:59 am

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Wed Nov 24, 2010 9:27 pm 
Offline

Joined: Thu Nov 04, 2010 9:22 am
Posts: 13
What is the expected behavior for a collision, after failing the contact filter's ShouldCollide()? Examining the source, it looks like the collision would be retested every step. However, in practice:

* 2 simple rectangles are overlapping - 1 dynamic & 1 static. There is no contact created because ShouldCollide() is false. Neither has vertexes within the other - picture a cross.
* I then change some internal rules so that ShouldCollide() will return a collision between them. However, it seems ShouldCollide() is not getting called again for the 2 fixtures, even when the dynamic object is moving. (There are no joints involved) It only seems to reported again if a vertex of 1 object crosses in/out of the other object.

Is this expected? If so, how can I force a reexamination of existing collisions for a fixture?

Thanks!


Top
 Profile  
 
PostPosted: Thu Nov 25, 2010 8:05 am 
Offline

Joined: Thu Nov 04, 2010 9:22 am
Posts: 13
OK it doesn't seem to be related to vertexes - it seems to be pretty random actually, sometimes it reprocesses the collision and sometimes not.


Top
 Profile  
 
PostPosted: Thu Nov 25, 2010 11:23 am 
Offline
Site Admin

Joined: Thu Sep 06, 2007 12:34 am
Posts: 2931
The broad-phase uses enlarged AABBs to reduce the number of updates. Once you filter out a collision, you can't get the collision to be solid again until the objects move substantially. However, you can call b2Fixture::SetFilterData to trigger re-filtering.

From the manual:
Quote:
Sometimes you might need to change collision filtering after a fixture has already been created. You can get and set the b2Filter structure on an existing fixture using b2Fixture::GetFilterData and b2Fixture::SetFilterData. Note that changing the filter data will not add or remove contacts until the next time step (see the World class).


Top
 Profile  
 
PostPosted: Thu Nov 25, 2010 1:46 pm 
Offline

Joined: Thu Nov 04, 2010 9:22 am
Posts: 13
Erin Catto wrote:
The broad-phase uses enlarged AABBs to reduce the number of updates. Once you filter out a collision, you can't get the collision to be solid again until the objects move substantially. However, you can call b2Fixture::SetFilterData to trigger re-filtering.

From the manual:
Quote:
Sometimes you might need to change collision filtering after a fixture has already been created. You can get and set the b2Filter structure on an existing fixture using b2Fixture::GetFilterData and b2Fixture::SetFilterData. Note that changing the filter data will not add or remove contacts until the next time step (see the World class).


Yes SetFilterData calls contact->FlagForFiltering on all contacts - but there is no contact for this collision so nothing to re-filter. Would I have to move the object off-screen then back the next step, to override this? Or can I remove it from the broad-phase list somehow? I'm not averse to changing the code I'm just not sure where to look.

Also, I notice you removed fixture.Refilter() - but there is another reason to refilter contacts other than changing filter data: custom code in the contact filter. In this case I have a one-way platform, and solidity is based on a combination of position and player input.


Top
 Profile  
 
PostPosted: Thu Nov 25, 2010 7:42 pm 
Offline

Joined: Thu Nov 04, 2010 9:22 am
Posts: 13
I've gotten this working correctly, by setting the position to -999, -999, then immediately setting it back to the correct value. However, it's not exactly elegant and I'd prefer not to lose existing contacts as there could be side effects from that. If there's a better solution, please let me know!

Thanks


Top
 Profile  
 
PostPosted: Fri Nov 26, 2010 12:16 am 
Offline
Site Admin

Joined: Thu Sep 06, 2007 12:34 am
Posts: 2931
Right. You want to force the broad-phase proxy to be added to the move buffer. There is not an API for this because no one has ever requested it before.


Top
 Profile  
 
PostPosted: Fri Nov 26, 2010 10:17 am 
Offline

Joined: Thu Nov 04, 2010 9:22 am
Posts: 13
Thanks, ok here's my quick and dirty solution if anyone else needs it, it seems to work well. (Although, it seems the setpos(-999, -999) then setpos back worked just as well, and did not trigger any extra contact events as I feared.)

Code:
void b2Fixture::RecheckCollisions(b2BroadPhase* broadPhase)
{
   if (m_proxyCount == 0)
   {
      return;
   }

   for (int32 i = 0; i < m_proxyCount; ++i)
   {
      b2FixtureProxy* proxy = m_proxies + i;
      broadPhase->BufferMove(proxy->proxyId);
   }
}


Top
 Profile  
 
PostPosted: Wed Jan 05, 2011 2:37 am 
Offline

Joined: Sat Aug 21, 2010 1:37 am
Posts: 36
May have this quick solution implemented.

Still get errors on:
Code:
      b2FixtureProxy* proxy = m_proxies + i;
      broadPhase->BufferMove(proxy->proxyId);


Errors:

'b2FixtureProxy' was not declared in this scope

'proxy' was not declared in this scope

'm_proxies' was not declared in this scope

I'm for the first time trying to change the source code and learn so any help as to where/how these would be declared would be much appreciated.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group