Weird radius damage on Physics Shape (T3D 1.2) Possible bug?
by Robert Pinter · in Torque 3D Professional · 10/21/2013 (3:50 am) · 11 replies
Hi All,
I have an issue with the radius damage behavior when I use destructible physic shapes.
The problem in shell nuts is, I have some destructible shapes which are working well, when I use any of the normal pistol or gun in the Full PhysX demo. So when they are damaged the shapes are changed to damaged and debris and the physic simulation is working fine, I can shot the debris and they are moving by physics as expected.
But when I use a grenade launcher or proxy mine, actually radius damage, something is weird, because the shape damaged and switched to the damaged state and debris, but no any physics impulse applied on the damaged or on debris shapes, e.g. they stay at the same position (of course the physics is working and gravity is applied) and no any force or impulsed applied on them what normally can be expect when a grenade explode.
So what I would expect is.
1. When the Grenade explode the shape destroyed and changed to broken and debris, IT IS OK.
2. The damaged shape and debris should continue the moving on that velocity which is coming from the radius damage force/impulse, but they are not.
3. On further detonation the debris should affected by the detonation, but they are not.
When I set the unbroken shape to invulnerable then the shape affected by the detonation all the time and physic impulse applied, but soon they switched to broken shape/debris they are not affected anymore, just working with normal bullet hit.
So actually I have checked the Pacific Demo and the behavior the same of the explode in that demo.
Do somebody explain where is the problem? I guess something is missing in the scripting
Also my second question is, I can see the physics shapes have an effect on each other when they collide e.g. they are able to break each other, but how can I ensure if the physics shape fall down, it damage itself and destroy it, like when the glass bottle fall down and broke to apart.
Thanks
Here is the radius damage code.
and here is the project titles code.
I have an issue with the radius damage behavior when I use destructible physic shapes.
The problem in shell nuts is, I have some destructible shapes which are working well, when I use any of the normal pistol or gun in the Full PhysX demo. So when they are damaged the shapes are changed to damaged and debris and the physic simulation is working fine, I can shot the debris and they are moving by physics as expected.
But when I use a grenade launcher or proxy mine, actually radius damage, something is weird, because the shape damaged and switched to the damaged state and debris, but no any physics impulse applied on the damaged or on debris shapes, e.g. they stay at the same position (of course the physics is working and gravity is applied) and no any force or impulsed applied on them what normally can be expect when a grenade explode.
So what I would expect is.
1. When the Grenade explode the shape destroyed and changed to broken and debris, IT IS OK.
2. The damaged shape and debris should continue the moving on that velocity which is coming from the radius damage force/impulse, but they are not.
3. On further detonation the debris should affected by the detonation, but they are not.
When I set the unbroken shape to invulnerable then the shape affected by the detonation all the time and physic impulse applied, but soon they switched to broken shape/debris they are not affected anymore, just working with normal bullet hit.
So actually I have checked the Pacific Demo and the behavior the same of the explode in that demo.
Do somebody explain where is the problem? I guess something is missing in the scripting
Also my second question is, I can see the physics shapes have an effect on each other when they collide e.g. they are able to break each other, but how can I ensure if the physics shape fall down, it damage itself and destroy it, like when the glass bottle fall down and broke to apart.
Thanks
Here is the radius damage code.
//-----------------------------------------------------------------------------
// Torque
// Copyright GarageGames, LLC 2011
//-----------------------------------------------------------------------------
// Support function which applies damage to objects within the radius of
// some effect, usually an explosion. This function will also optionally
// apply an impulse to each object.
function radiusDamage(%sourceObject, %position, %radius, %damage, %damageType, %impulse)
{
// Use the container system to iterate through all the objects
// within our explosion radius. We'll apply damage to all ShapeBase
// objects.
//InitContainerRadiusSearch(%position, %radius, $TypeMasks::ShapeBaseObjectType);
InitContainerRadiusSearch(%position, %radius, $TypeMasks::GameBaseObjectType|$TypeMasks::DynamicShapeObjectType);
%halfRadius = %radius / 2;
while ((%targetObject = containerSearchNext()) != 0)
{
echo(%sourceObject.getId());
// Don't damage the source object... can cause infinite recursion.
if ( %targetObject == %sourceObject )
continue;
// Calculate how much exposure the current object has to
// the explosive force. The object types listed are objects
// that will block an explosion. If the object is totally blocked,
// then no damage is applied.
//%coverage = 1;
//$TypeMasks::InteriorObjectType
%coverage = calcExplosionCoverage(%position, %targetObject,
$TypeMasks::InteriorObjectType|
$TypeMasks::TerrainObjectType |
$TypeMasks::ForceFieldObjectType |
$TypeMasks::StaticShapeObjectType |
$TypeMasks::VehicleObjectType|
$TypeMasks::DebrisObjectType);
echo(%coverage);
if (%coverage == 0)
continue;
// Radius distance subtracts out the length of smallest bounding
// box axis to return an appriximate distance to the edge of the
// object's bounds, as opposed to the distance to it's center.
%dist = containerSearchCurrRadiusDist();
// Calculate a distance scale for the damage and the impulse.
// Full damage is applied to anything less than half the radius away,
// linear scale from there.
%distScale = (%dist < %halfRadius)? 1.0 : 1.0 - ((%dist - %halfRadius) / %halfRadius);
if ( %targetObject.isMethod( "damage" ) )
{
// Apply the damage
%targetObject.damage(%sourceObject, %position, %damage * %coverage * %distScale, %damageType);
}
// Apply the impulse
if (%impulse)
{
%impulseVec = VectorSub(%targetObject.getWorldBoxCenter(), %position);
%impulseVec = VectorNormalize(%impulseVec);
%impulseVec = VectorScale(%impulseVec, %impulse * %distScale);
%targetObject.applyImpulse(%position, %impulseVec);
//%targetObject.applyRadialImpulse(%position, %radius, %impulse);
// RadialImpulseEvent::send( %position, %radius, %impulse );
}
}
}and here is the project titles code.
//-----------------------------------------------------------------------------
// Torque
// Copyright GarageGames, LLC 2011
//-----------------------------------------------------------------------------
// "Universal" script methods for projectile damage handling. You can easily
// override these support functions with an equivalent namespace method if your
// weapon needs a unique solution for applying damage.
function ProjectileData::onCollision(%data, %proj, %col, %fade, %pos, %normal)
{
//echo("ProjectileData::onCollision("@%data.getName()@", "@%proj@", "@%col.getClassName()@", "@%fade@", "@%pos@", "@%normal@")");
// Apply damage to the object all shape base objects
if (%data.directDamage > 0)
{
if (%col.getType() & ($TypeMasks::GameBaseObjectType))
%col.damage(%proj, %pos, %data.directDamage, %data.damageType);
}
}
function ProjectileData::onExplode(%data, %proj, %position, %mod)
{
//echo("ProjectileData::onExplode("@%data.getName()@", "@%proj@", "@%position@", "@%mod@")");
// Damage objects within the projectiles damage radius
if (%data.damageRadius > 0)
{
if ( %data.radiusDamage > 0 )
{
radiusDamage(%proj, %position, %data.damageRadius, %data.radiusDamage, %data.damageType, %data.areaImpulse);
}
//if ( %data.areaImpulse > 0 )
//{
// Apply a physical impulse from the explosion to objects in the radius.
//
// Note that this event is performed immediately on the server-side and
// then transmitted to all clients via a NetEvent and performed there as well.
//
// RadialImpulseEvent::send( %pos, %data.damageRadius, %data.areaImpulse );
//}
}
}About the author
Some of my old programming stuff. [URL] http://www.youtube.com/user/satanka102/videos [/URL]
#2
10/21/2013 (2:03 pm)
Quote:PhysX shapes are GameBase Objects and not ShapeBase Objects.What witchcraft is this?
Quote:if the physics shape fall down, it damage itself and destroy itUsually you'd use an onCollision callback, or onImpact (I forget which is used in what situation). Not sure if PhysX shapes fire those callbacks but it's worth a try!
#3
It seems to me when I use
RadialImpulseEvent::send( %pos, %data.damageRadius, %data.areaImpulse );
it seems to work for a while, because it add impulse on server and client side too, so I guess the problem is the applyimpulse not take any effect on the debris on client side, but maybe I am totally wrong.
@Daniel, accodring the docs I didn't fine those callbacks for Physics shapes, but maybe it can be use via gamebase object, I will try it.
Thanks
10/21/2013 (3:40 pm)
Thanks @Ron, well yes you are right the physics objects are gamebase objects, but if you look at my code in radiusdamage.cs you can see the "InitContainerRadiusSearch" already has the "$TypeMasks::GameBaseObjectType" and the problem is the same.It seems to me when I use
RadialImpulseEvent::send( %pos, %data.damageRadius, %data.areaImpulse );
it seems to work for a while, because it add impulse on server and client side too, so I guess the problem is the applyimpulse not take any effect on the debris on client side, but maybe I am totally wrong.
@Daniel, accodring the docs I didn't fine those callbacks for Physics shapes, but maybe it can be use via gamebase object, I will try it.
Thanks
#4
@Daniel.... simplified the response to explain how the PhysX stuff is addressed. It's not witchcraft, just simplification :-).
Ron
10/21/2013 (3:56 pm)
Ok, well I will be honest, I did not read all the code. If you have that then the problem is likely that the debris does not have a proper collision shape. If I recall, the impulse works in conjunction with the collision mesh for the detection. I could be wrong on this and it has been a bit of time since I messed around with destructible meshes. Did you add collision to the debris?@Daniel.... simplified the response to explain how the PhysX stuff is addressed. It's not witchcraft, just simplification :-).
Ron
#5
The collisions are ok on debris, let me illustrate the problem on video.
EDIT
Here is the behavior of the boxes when they are not breakable.
Here is the issue with breakable boxes.
Rob
10/21/2013 (4:45 pm)
Hi Ron,The collisions are ok on debris, let me illustrate the problem on video.
EDIT
Here is the behavior of the boxes when they are not breakable.
Here is the issue with breakable boxes.
Rob
#6
Robert: actually I'm not sure where/how those callbacks would be documented. Have a look at the Player class scripts for an example. You'll need to write a datablock function with the appropriate name and arguments.
10/21/2013 (4:51 pm)
I was just surprised that PhysicsShape is not a ShapeBase.Robert: actually I'm not sure where/how those callbacks would be documented. Have a look at the Player class scripts for an example. You'll need to write a datablock function with the appropriate name and arguments.
#7
I will have a look the script and figure out something, but at first case the no impulse on debris are very annoying to me. :)
Rob
10/21/2013 (5:01 pm)
Thanks Daniel,I will have a look the script and figure out something, but at first case the no impulse on debris are very annoying to me. :)
Rob
#8
I have traced back the projectile and physicshape and physicsdebris sourcecode and I found some interesting thing. When you set the physicshape to udestroyable then impulse is applied and the "IsSimulationEnabled" or "mEnabled" and the physicsshape is recognized as physic actor. Immediately when the Physicsshape set to destroyable and debris is created the "mEnabled" is set to False and not set as Physic Actor and impulse is ignored on the debris. Also the bullet decal hole is not applied on the debris or the position and normal is wrong.
Do you know if these are fixed in the T3D 3.0?
11/02/2013 (3:58 am)
Guys,I have traced back the projectile and physicshape and physicsdebris sourcecode and I found some interesting thing. When you set the physicshape to udestroyable then impulse is applied and the "IsSimulationEnabled" or "mEnabled" and the physicsshape is recognized as physic actor. Immediately when the Physicsshape set to destroyable and debris is created the "mEnabled" is set to False and not set as Physic Actor and impulse is ignored on the debris. Also the bullet decal hole is not applied on the debris or the position and normal is wrong.
Do you know if these are fixed in the T3D 3.0?
#9
InitContainerRadiusSearch(%position, %radius, $TypeMasks::GameBaseObjectType|$TypeMasks::DynamicShapeObjectType);
I'm not sure though, will take another peek.
11/02/2013 (3:44 pm)
I think the problem lies in here:InitContainerRadiusSearch(%position, %radius, $TypeMasks::GameBaseObjectType|$TypeMasks::DynamicShapeObjectType);
I'm not sure though, will take another peek.
#10
Yes I tried that, but the debris has marked as not dynamic because of some reason. When I trace the radius damage it says the isDynamic variable is false of all debris, however when you shot it they move.
I think at debris creation time this parameter is not set.
11/02/2013 (10:29 pm)
Thanks BillyBob,Yes I tried that, but the debris has marked as not dynamic because of some reason. When I trace the radius damage it says the isDynamic variable is false of all debris, however when you shot it they move.
I think at debris creation time this parameter is not set.
#11
It seems the code below solved my radius impulse problem.
"game/scripts/server/projectile.cs"
"game/scripts/server/radiusdamage.cs"
The evidence
I just only have to find out the self damage on fall and the bullet hole problem. :)
11/05/2013 (4:58 pm)
Hey,It seems the code below solved my radius impulse problem.
"game/scripts/server/projectile.cs"
function ProjectileData::onCollision( %data, %proj, %col, %fade, %pos, %normal )
{
//echo("ProjectileData::onCollision("@%data.getName()@", "@%proj@", "@%col.getClassName()@", "@%fade@", "@%pos@", "@%normal@")");
// Apply damage from the direct hit to GameBase objects.
if ( %data.directDamage > 0 )
{
if ( %col.getType() & ( $TypeMasks::ShapeBaseObjectType ) )
%col.damage( %proj.sourceObject, %pos, %data.directDamage, %data.damageType );
}
// Note that we are not applying an impulse to for being directly hit
// because Projectile has already handled that in code.
}
function ProjectileData::onExplode( %data, %proj, %pos, %mod )
{
//echo("ProjectileData::onExplode("@%data.getName()@", "@%proj@", "@%position@", "@%mod@")");
if ( %data.damageRadius > 0 )
{
if ( %data.radiusDamage > 0 )
{
// Apply damage from the explosion to objects within the radius of the blast.
radiusDamage( %obj, %pos, %data.damageRadius, %data.radiusDamage, %data.damageType );
}
if ( %data.areaImpulse > 0 )
{
// Apply a physical impulse from the explosion to objects in the radius.
//
// Note that this event is performed immediately on the server-side and
// then transmitted to all clients via a NetEvent and performed there as well.
//
RadialImpulseEvent::send( %pos, %data.damageRadius, %data.areaImpulse );
}
}
}"game/scripts/server/radiusdamage.cs"
function radiusDamage(%sourceObject, %position, %radius, %damage, %damageType)
{
InitContainerRadiusSearch(%position, %radius, $TypeMasks::GameBaseObjectType);
%halfRadius = %radius / 2;
while ( ( %targetObject = containerSearchNext() ) != 0 )
{
// Don't damage the source object... can cause infinite recursion.
if ( %targetObject == %sourceObject )
continue;
%coverage = 1;
//%coverage = calcExplosionCoverage(%position, %targetObject,
// $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType |
// $TypeMasks::ForceFieldObjectType | $TypeMasks::VehicleObjectType);
if ( %coverage == 0 )
continue;
%dist = containerSearchCurrRadiusDist();
%distScale = (%dist < %halfRadius)? 1.0 : 1.0 - ((%dist - %halfRadius) / %halfRadius);
// Apply the damage
if ( %targetObject.isMethod( "damage" ) )
{
%targetObject.damage( %sourceObject,
%position,
%damage * %coverage * %distScale,
%damageType) ;
}
}
}The evidence
I just only have to find out the self damage on fall and the bullet hole problem. :)
Associate Ron Kapaun
3tdstudios.com
InitContainerRadiusSearch(%position, %radius, $TypeMasks::ShapeBaseObjectType);
Should read like this:
InitContainerRadiusSearch(%position, %radius, $TypeMasks::GameBaseObjectType);
That should fix your genade impulse issues. Since PhysX shapes are GameBase Objects and not ShapeBase Objects.
Ron