Game Development Community

ContainerRayCast - Exempt From Collision

by Scott Doerrfeld · in Torque Game Engine · 03/10/2006 (1:10 pm) · 2 replies

I have a 4-door car and I want the player to be able to walk up to any one of the car doors and open it individually. So far I have tried to achieve this by making each door a separate DTS object. I am using ContainerRayCast to cast a ray from the player's eye. The idea is if the player is facing a door and clicks the mouse, that door will open. The problem I have run into is that the first object returned from the RayCast is the car.

Ideally, I could have the car object be exempt from the RayCast. I know this can be done by passing the car object as the fourth parameter when I call ContainerRayCast, but then the RayCast will return the player object. Is there a way to have both the player AND the car object be exempt from the RayCast?

#1
03/10/2006 (1:28 pm)
I have done this by adding an extra 'exempt' object to ContainerRayCast. The first exempt object is always the player object, and I made an extra exempt object optional.

Here is the change I made to sceneObject.cc (changes highlighted in bold):

[b]// MAR: The define below was changed from 5 arguments to 6 to allow an extra exempt object.[/b]
ConsoleFunction( containerRayCast, const char*, 4, [b]6[/b], "( Point3F start, Point3F end, bitset mask, SceneObject exempt1=NULL [b]SceneObject exempt2=NULL[/b])"
      "Cast a ray from start to end, checking for collision against items matching mask.\n\n"
      "If exempt is specified, then it is temporarily excluded from collision checks (For "
      "instance, you might want to exclude the player if said player was firing a weapon.)\n"
      "@returns A string containing either null, if nothing was struck, or these fields:\n"
      "            - The ID of the object that was struck.\n"
      "            - The x, y, z position that it was struck.\n"
      "            - The x, y, z of the normal of the face that was struck.")
{
   char *returnBuffer = Con::getReturnBuffer(256);
   Point3F start, end;
   dSscanf(argv[1], "%g %g %g", &start.x, &start.y, &start.z);
   dSscanf(argv[2], "%g %g %g", &end.x,   &end.y,   &end.z);
   U32 mask = dAtoi(argv[3]);

   SceneObject* pExempt = NULL;
[b]   SceneObject* pExempt2 = NULL;   // MAR: added statement for second exempt object[/b]

   if (argc > 4) {
      U32 exemptId = dAtoi(argv[4]);
      Sim::findObject(exemptId, pExempt);
   }
   if (pExempt)
      pExempt->disableCollision();

[b]   // MAR: [begin] This was added to allow for a second exempted object
   if (argc > 5) {
	   U32 exemptId = dAtoi(argv[5]);
	   Sim::findObject(exemptId, pExempt2);
   }
   if (pExempt2)
	   pExempt2->disableCollision();
   // MAR: [end]
[/b]
   
   RayInfo rinfo;
   S32 ret = 0;
   if (gServerContainer.castRay(start, end, mask, &rinfo) == true)
      ret = rinfo.object->getId();

   if (pExempt)
      pExempt->enableCollision();
[b]   // MAR: added statement for second exempt object
   if (pExempt2)
	   pExempt2->enableCollision();[/b]

   // add the hit position and normal?
   if(ret)
   {
      dSprintf(returnBuffer, 256, "%d %g %g %g %g %g %g",
               ret, rinfo.point.x, rinfo.point.y, rinfo.point.z,
               rinfo.normal.x, rinfo.normal.y, rinfo.normal.z);
   }
   else
   {
      returnBuffer[0] = '0';
      returnBuffer[1] = '[[60c224ae17cbc]]';
   }

   return(returnBuffer);
}

Hope that helps. I'll probably add this as a resource when I get the chance.
#2
03/10/2006 (3:17 pm)
Thank you, Rubes. This definitely works exactly as intended! Another method I am looking at is to setup a new ObjectType for "clickable" objects that can be used for the search mask. This is described here, though this method is a bit more complex. It would be great if new object types could be created more easily!