Game Development Community

Hit Spheres

by Bryan Morgan · in Torque 3D Professional · 09/24/2011 (10:33 am) · 8 replies

I'm currently working on a method for using nodes to do location damage on meshes, but I can't seem to get the world position of the nodes exported to torquescript.

I may be doing this completely wrong, but my function for exporting to torquescript is:
DefineEngineMethod( ShapeBase, getNodePosition, Point3F, ( const char* nodeName ),,
	"@brief Get animated node position of nodeName\n\n"
	
	"@return the position of nodeName\n\n" )
{
   ShapeBase *clientObj = dynamic_cast< ShapeBase* > ( object->getClientObject() );

   S32 nodeIndex;
   if(clientObj)
	   nodeIndex = clientObj->getShape()->findNode(nodeName);
   else
	   Con::errorf("ShapeBase::getNodePosition: Unable to find client Object.");

	MatrixF nodeMat;
	clientObj->getShape()->getNodeWorldTransform(nodeIndex, nodeMat);

	return nodeMat.getPosition();
}

From what I can tell the above code should work and it could be test scripts just lieing to me. In BulletProjectile::onCollision I've simply got this script to spit out node positions of the player mesh I'm shooting at:
if (%col.getType() & ($TypeMasks::PlayerObjectType))
      {
         %pelvis = %col.getNodePosition("Bip01 Pelvis");
         echo("Bip01 Pelvis ", %pelvis);
         
         %spine = %col.getNodePosition("Bip01 Spine");
         echo("Bip01 Spine ", %spine);
         
         %spine1 = %col.getNodePosition("Bip01 Spine1");
         echo("Bip01 Spine1 ", %spine1);
         
         %spine2 = %col.getNodePosition("Bip01 Spine2");
         echo("Bip01 Spine2 ", %spine2);
         
         %neck = %col.getNodePosition("Bip01 Neck");
         echo("Bip01 Neck ", %neck);
         
         %head = %col.getNodePosition("Bip01 Head");
         echo("Bip01 Head ", %head);
      }

The console output always spits out the nodes as being at the origin (all 0). I tried using the server instance of the mesh and it spits out a random infinitesimally small float(something like 5.01231241e-10) but always the same value for all the nodes. Am I doing something incredibly stupid here?

Thanks in advance for any help. If I can get this working I'm going to post a nice big resource that can be used for everything from melee fighting games to vehicle racing crumple zones.

#1
09/24/2011 (12:02 pm)
There's some stuff here that might help you out.
#2
09/24/2011 (12:48 pm)
Thanks for the quick response. That was amazingly helpful. From the looks of it I was really close to figuring it out and it was mostly just a case of over-complicating things.

Now everything can have locational damage or sticky projectiles!
#3
09/27/2011 (10:22 am)
"If I can get this working I'm going to post a nice big resource"

Bryce, this have been a showstopper for me in my project alMadjus. I even have had the issue of hitboxes, melee and bow shooting outsourced, but they failed as well. In case you throw this up as a resource Id be most grateful, and would dive into the thing asap.
#4
09/27/2011 (4:56 pm)
It'll be sometime next week before I get it up because I've only got a couple hours a night to work at it. I was originally going to use hitboxes for my game, but then decided just using nodes is a lot nicer, more reusable system. What I'm currently doing is really simple but very powerful. What you do is you create a node somewhere within the bounds of the mesh you want to do localized hit detection and whenever you get a collision you cast a ray from the point of collision with the bounds in the direction of the impact (really easy with a projectile but needing a little math if it's an impact between two shapebases) and then you do a simple ray-sphere intersection using the node position as your sphere center and whatever radius you want for that node to guarantee accurate representation of the area. If only one node is hit then you just need to apply damage or do whatever you want with that information. If multiple nodes are hit, it's pretty application dependent, but you would probably want to do some sanity checks like ignoring nodes on the opposite side of the mesh from the impact or picking the closest node to the ray if two nodes are hit that overlap. IMO the benefit of using hit nodes over hit boxes is you don't have to align them to the limbs or anything like that, just create a node in your mesh for that limb and if it's hit then you've got a hit to that limb.

Hopefully my explanation was somewhat useful. I'll be uploading a resource anyways to show it in use for localized damage to both a player mesh and a vehicle, but it really is very simple to implement as long as your not going for anything unnecessarily complicated.
#5
09/27/2011 (7:09 pm)
Okay, once again I need help getting the scripts or something to do what I expect of them. I've written a test onCollision function:

function BulletProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
   // Apply impact force from the projectile.
   
   if (%col.getType() & $TypeMasks::ShapeBaseObjectType){
      echo("Calculating...");
      %nodePos = %col.getNodePosition("Bip01 Pelvis");   //Get position of node we want to look for
      %radius = 100;   //arbitrary radius for now. Should definitely hit at this size.
      %rayVec = -%normal; //Direction of projectile before impact should be inverse of normal?
      
      // d . d t^2 + 2d . (p0 - pc)t + (p0 - pc) . (p0 - pc) - r2 = 0
      %a = VectorDot(%rayVec, %rayVec); // d . d
      %b1 = 2 * %rayVec;                // 2d
      %b2 = VectorSub(%pos, %nodePos);  // p0 - pC
      %b = VectorDot(%b1, %b2);         // 2d . (p0 - pC)
      %c1 = VectorDot(%b2, %b2);        // (p0 - pC) . (p0 - pC)
      %c2 = %radius * %radius;          // r^2
      %c = %c1 - %c2;                   // (p0 - pC) . (p0 - pC) - r^2
      
      // b^2 - 4 a c
      %result1 = VectorCross(%b,%b);            // b is a vector so b^2 is cross product
      %result2 = 4 * VectorCross(%a, %c);       // a and c also vectors; 4 a c
      %result = VectorSub(%result1, %result2);  // b^2 - 4 a c
      
      // To actually find points of intersection
      // t = (-b +/- sqrt(b^2 - 4 a c)) / (2 a)
      // But shouldn't be necessary for most cases
      
      if(%result < 0)   //No hit
      echo("NO HIT!");
         //return;
         
      if(%result == 0)  //Glancing blow
         //return;
      echo("NEAR HIT!");
         
      if(%result > 0) //Hit
         //return;
      echo("HIT!");
   }
   
   // Apply damage to the object all shape base objects
   if ( %col.getType() & $TypeMasks::GameBaseObjectType )
      %col.damage(%obj,%pos,%this.directDamage,"BulletProjectile");
}
But for some reason I can't get it to actually enter the if block. I tried with a ship mesh that I had created but since it was having weird problems with the camera position when riding it I figured it was something wrong with the mesh. I dragged the soldier mesh onto the map and even though I could shoot it and the emitter was coming from the mesh, it wasn't entering my if block. Shouldn't the ShapeBaseObjectType TypeMask work for any mesh?
#6
09/28/2011 (12:36 am)
The mesh that you placed for testing, did you place it as a TSStatic? They're not derived from ShapeBase, so don't have ShapeBaseObjectType set.
#7
09/28/2011 (1:36 am)
Nice explanation, I did have a somewhat different approach though.

I tried to make a system where the model had hidden meshes, which could be swapped in and out to emulate damage. All collision with these was done with hitboxes covering all bones.
The plan was to automatically parse the player object (and AI's) to generate the code for the array of hitboxes. So that one never again would have to meddle with setting up hit-code for a odd looking player/AI object (different race/monster) but I drowned in it as it went above my head.

Will be really interesting to see your approach and soluting when it hits us :P
#8
09/28/2011 (4:11 pm)
@Guy: The player mesh was a TSStatic when I was testing. I wasn't aware that TSStatic wasn't derived from ShapeBase.

@Christian: Think I'll be just as interested to see it done as anyone. It's been several years since I did any vector maths in college and my old notes where a bit rough to read through. There are certainly some pitfalls I need to work on to make the code easy to use but hopefully I'll have it done while on leave the next two weeks.