One-Way Collisions (walking through objects)
by James Ford · in Torque Game Builder · 08/20/2007 (4:41 pm) · 6 replies
This topic came up in the adventure kit forum but I believe is a general collision bug. I have included a project all setup for you. It is using the "shootercontrols" behavior so you can move around with the arrow keys (but this is not required to see the bug, you can edit your velocity manually and then click run). Just run it an press the up arrow, you should "pop" through the tree when you collide with it and appear at its top left corner.
This problem seems to manifest itself only with polygon collision detection with relatively small collision polygons/images, which happen to be necessary with the semi-isometric view in the adventure kit.
I "think" the problem is in the calculation of the collision normal. In resolveClampCollision the collision normal.Y value is always negative. The collision normal.X changes from positive to negative when you test a collision going from left to right to going right to left, but the collision normal.Y is always negative.
Screenshot1, before collision:

Screenshot2, after collision:

Project:
www.box.net/shared/static/noeo3ubkrk.rar
Thread in the Adventure Kit Forum about this topic:
Several collision issues and where can I find the player?
Heres the entire mission file, if you wanted to add it to your own project or whatever, it is using the starter art so you might want to add that too:
%levelContent = new t2dSceneGraph() {
canSaveDynamicFields = "1";
UseLayerSorting = "1";
layerSortMode0 = "Normal";
layerSortMode1 = "Normal";
layerSortMode2 = "Normal";
layerSortMode3 = "Normal";
layerSortMode4 = "Normal";
layerSortMode5 = "Normal";
layerSortMode6 = "Normal";
layerSortMode7 = "Normal";
layerSortMode8 = "Normal";
layerSortMode9 = "Normal";
layerSortMode10 = "Y Axis";
layerSortMode11 = "Normal";
layerSortMode12 = "Normal";
layerSortMode13 = "Normal";
layerSortMode14 = "Normal";
layerSortMode15 = "Normal";
layerSortMode16 = "Normal";
layerSortMode17 = "Normal";
layerSortMode18 = "Normal";
layerSortMode19 = "Normal";
layerSortMode20 = "Normal";
layerSortMode21 = "Normal";
layerSortMode22 = "Normal";
layerSortMode23 = "Normal";
layerSortMode24 = "Normal";
layerSortMode25 = "Normal";
layerSortMode26 = "Normal";
layerSortMode27 = "Normal";
layerSortMode28 = "Normal";
layerSortMode29 = "Normal";
layerSortMode30 = "Normal";
layerSortMode31 = "Normal";
cameraPosition = "0 0";
cameraSize = "100 75";
new t2dStaticSprite(tree) {
imageMap = "treesImageMap";
frame = "0";
canSaveDynamicFields = "1";
Position = "-0.889 -0.219";
size = "28.223 34.570";
SortPoint = "0.020 -0.213";
Layer = "10";
CollisionActiveReceive = "1";
CollisionPhysicsSend = "0";
CollisionPhysicsReceive = "0";
CollisionPolyList = "-0.717 -0.308 0.822 -0.301 0.895 -0.212 -0.784 -0.207";
mountID = "2";
};
new t2dStaticSprite(player) {
imageMap = "space_crateImageMap";
frame = "0";
canSaveDynamicFields = "1";
Position = "1.726 23.373";
size = "6.548 8.000";
CollisionActiveSend = "1";
CollisionPhysicsReceive = "0";
CollisionPolyList = "-0.414 0.385 0.033 0.072 0.420 0.367 0.006 0.778";
LinkPoints = "-0.334 0.311";
mountID = "3";
_behavior0 = "ShooterControlsBehavior";
};
};
This problem seems to manifest itself only with polygon collision detection with relatively small collision polygons/images, which happen to be necessary with the semi-isometric view in the adventure kit.
I "think" the problem is in the calculation of the collision normal. In resolveClampCollision the collision normal.Y value is always negative. The collision normal.X changes from positive to negative when you test a collision going from left to right to going right to left, but the collision normal.Y is always negative.
Screenshot1, before collision:

Screenshot2, after collision:

Project:
www.box.net/shared/static/noeo3ubkrk.rar
Thread in the Adventure Kit Forum about this topic:
Several collision issues and where can I find the player?
Heres the entire mission file, if you wanted to add it to your own project or whatever, it is using the starter art so you might want to add that too:
%levelContent = new t2dSceneGraph() {
canSaveDynamicFields = "1";
UseLayerSorting = "1";
layerSortMode0 = "Normal";
layerSortMode1 = "Normal";
layerSortMode2 = "Normal";
layerSortMode3 = "Normal";
layerSortMode4 = "Normal";
layerSortMode5 = "Normal";
layerSortMode6 = "Normal";
layerSortMode7 = "Normal";
layerSortMode8 = "Normal";
layerSortMode9 = "Normal";
layerSortMode10 = "Y Axis";
layerSortMode11 = "Normal";
layerSortMode12 = "Normal";
layerSortMode13 = "Normal";
layerSortMode14 = "Normal";
layerSortMode15 = "Normal";
layerSortMode16 = "Normal";
layerSortMode17 = "Normal";
layerSortMode18 = "Normal";
layerSortMode19 = "Normal";
layerSortMode20 = "Normal";
layerSortMode21 = "Normal";
layerSortMode22 = "Normal";
layerSortMode23 = "Normal";
layerSortMode24 = "Normal";
layerSortMode25 = "Normal";
layerSortMode26 = "Normal";
layerSortMode27 = "Normal";
layerSortMode28 = "Normal";
layerSortMode29 = "Normal";
layerSortMode30 = "Normal";
layerSortMode31 = "Normal";
cameraPosition = "0 0";
cameraSize = "100 75";
new t2dStaticSprite(tree) {
imageMap = "treesImageMap";
frame = "0";
canSaveDynamicFields = "1";
Position = "-0.889 -0.219";
size = "28.223 34.570";
SortPoint = "0.020 -0.213";
Layer = "10";
CollisionActiveReceive = "1";
CollisionPhysicsSend = "0";
CollisionPhysicsReceive = "0";
CollisionPolyList = "-0.717 -0.308 0.822 -0.301 0.895 -0.212 -0.784 -0.207";
mountID = "2";
};
new t2dStaticSprite(player) {
imageMap = "space_crateImageMap";
frame = "0";
canSaveDynamicFields = "1";
Position = "1.726 23.373";
size = "6.548 8.000";
CollisionActiveSend = "1";
CollisionPhysicsReceive = "0";
CollisionPolyList = "-0.414 0.385 0.033 0.072 0.420 0.367 0.006 0.778";
LinkPoints = "-0.334 0.311";
mountID = "3";
_behavior0 = "ShooterControlsBehavior";
};
};
About the author
http://jamesdev.info
#2
The reason we haven't fixed it ourselves yet, like we usually do, is because we have no clue what the code in question is supposed to be doing and not the time to become T2D collision experts. I'm sure Melv could understand the issue in minutes while it will take me days to start to understand how it all works.
08/21/2007 (8:34 am)
Quote:Bit of a hack, but may be a workaround for you until the issue is resolved.Might be a good solution for someone wanting to ship a game, but in our case we just want to see the bug fixed.
The reason we haven't fixed it ourselves yet, like we usually do, is because we have no clue what the code in question is supposed to be doing and not the time to become T2D collision experts. I'm sure Melv could understand the issue in minutes while it will take me days to start to understand how it all works.
#3
Here is the unmodified code in function:
bool t2dPhysics::sweptPolyToPolyCollision( F32 elapsedTime, cCollisionStatus* pCollisionStatus )
Near the bottom, around line 1812
Here is the same section with the new fix:
Note that we moved the "Respace Normal" code block above the "overlap case" code block.
08/31/2007 (1:25 pm)
We got a fix for this bug by making slight changes to t2dPhysics.cc. The issue is, the collision normal is calculated based on the objects centerpoint not the collision image centerpoint. So, if your collision image does not contain the object centerpoint your collision normal can be wrong. This fix is lifted from the TorqueX collision code, where the GarageGames guys already addressed this issue.Here is the unmodified code in function:
bool t2dPhysics::sweptPolyToPolyCollision( F32 elapsedTime, cCollisionStatus* pCollisionStatus )
Near the bottom, around line 1812
// Set Overlapped Status.
pCollisionStatus->mOverlapped = mLessThanZero(pCollisionStatus->mCollisionTimeReal);
// Make sure the collision polygons are pushed away.
// NOTE:- This is the overlap case.
if ( (pCollisionStatus->mCollisionNormal * refLocalOffset) < 0.0f )
pCollisionStatus->mCollisionNormal = -pCollisionStatus->mCollisionNormal;
// Respace Normal.
pCollisionStatus->mCollisionNormal *= dstRotation;
// T2D Debug Profiling.
#ifdef TORQUE_ENABLE_PROFILER
PROFILE_START(T2D_t2dPhysics_findContactPoints);Here is the same section with the new fix:
// Set Overlapped Status.
pCollisionStatus->mOverlapped = mLessThanZero(pCollisionStatus->mCollisionTimeReal);
// Respace Normal.
pCollisionStatus->mCollisionNormal *= dstRotation;
// We cannot assume that the collision polys contain
// the 0,0 origin point. So compute offset between the
// actual poly centers for testing the normal direction.
t2dVector polyCenter( 0, 0 );
for ( S32 i=0; i < srcPolyCount; i++ )
polyCenter += srcPoly[i];
polyCenter *= 1.0f / (F32)srcPolyCount;
t2dVector polyOffset = srcPosition + ( polyCenter ^ srcRotation );
polyCenter.set( 0,0 );
for ( S32 i=0; i < dstPolyCount; i++ )
polyCenter += dstPoly[i];
polyCenter *= 1.0f / (F32)dstPolyCount;
polyOffset -= dstPosition + ( polyCenter ^ dstRotation );
// Make sure the collision polygons are pushed away.
// NOTE:- This is the overlap case.
if ( (pCollisionStatus->mCollisionNormal * polyOffset) < 0.0f )
pCollisionStatus->mCollisionNormal = -pCollisionStatus->mCollisionNormal;
// T2D Debug Profiling.
#ifdef TORQUE_ENABLE_PROFILER
PROFILE_START(T2D_t2dPhysics_findContactPoints);Note that we moved the "Respace Normal" code block above the "overlap case" code block.
#4
08/31/2007 (1:47 pm)
How does one go about requesting this get added to the code base?
#5
08/31/2007 (1:55 pm)
@BillyJack - We're taking care of it... we have been in contact with GG about the issue and they suggested the fix was probably in TorqueX.
#6
Thanks!
--clint
09/10/2007 (2:44 pm)
Really glad to see that this is getting addressed. If you want another sample project for this bug, I created one and reported this issue last December.Thanks!
--clint
Torque Owner Gary Preston
Although from what I recall, it isn't due to the size of the collision polygon. It's when you have a collision bound that takes up only a fraction of the overall sprite bounds. E.G very small collision bounds will work correctly (at least when I tried it on an earlier TGB version) so long as the sprite is also small, allowing the collision poly to fill most of the sprites space.
In your example both sprites have collision bounds that take up a small percentage of the overall sprites bounds.
I worked around the issue by mounting the sprite image to a dummy scene object. The scene object was used for movement and collisions, whist the mounted sprite was used for the visual side of things. Bit of a hack, but may be a workaround for you until the issue is resolved.