Game Development Community

WorldEditor object collision while moving

by Dave Young · in Torque Game Engine · 06/25/2008 (11:25 am) · 10 replies

I'm looking for a way to make sure an object will collide with an interior while I'm moving it in the World Editor. This is to ensure that I cannot move it underneath the floor or through a wall. I've tried a few different ways but can't get a selected object to collide with anything while dragging it around, even when I make sure collision is enabled on it. Anyone have any thoughts on a good approach?

#1
06/25/2008 (11:32 am)
This wont be very helpful, but doesn't the world editor modify the transform of the object? If it does, than you could either try to change how it works so that it applies velocity, or maybe check to see if the area where you are trying to move the object to is occupied.

*End of Useless Thought*
#2
06/25/2008 (11:39 am)
It's not *that* useless, I thought of something that might work. Checkdismountpoint does a similar thing by doing a raycast between old and new positions to see if there is something in the way. WorldEditor uses a function to set the transform, so its the perfect place to do a similar check. I'll see how it works out.
#3
06/25/2008 (11:45 am)
Woot!! It worked unbelievably well!! When this modified version of the offset() function is in, I can drag an object around inside an interior and it collides precisely with the walls and floors. It adds the collision check in the middle and exits out. You could get fancy and continue instead of returning, to allow the rest of the objects in the selection a shot at moving.

void WorldEditor::Selection::offset(const Point3F & offset)
{
   for(U32 i = 0; i < mObjectList.size(); i++)
   {
      MatrixF mat = ((SceneObject*)mObjectList[i])->getTransform();
      Point3F wPos;
      Point3F nPos;  //our test point
      mat.getColumn(3, &wPos);
      nPos = wPos;
      nPos += offset;

	  RayInfo info;
	  disableCollision();
          //Check to see if it collides with an interior. If so, dont let it move to the new position
          if(gServerContainer.castRay(wPos, nPos, InteriorObjectType, &info))
	 {
	     enableCollision();
	     return;
          }
 
      // adjust
      wPos += offset;
      mat.setColumn(3, wPos);
      ((SceneObject*)mObjectList[i])->setTransform(mat);
   }

   mCentroidValid = false;
}
#4
06/25/2008 (12:46 pm)
This code could be used to form the basis of a series of "snap to" options in the world editor. There are many times when a designer wants something right on the terrain, or right on the floor of an interior, and they have to do a bunch of work (changing their view etc) to get that object exactly where they want it. With this they could just tick a box saying "snap to ground" then just drag it down "for a mile" and know that the object will stop when it hits the terrain. Good stuff.
#5
06/25/2008 (1:54 pm)
Doesn't TGEA 1.7.x already have a snap-to-ground function in the world editor?
#6
06/25/2008 (2:13 pm)
> There are many times when a designer wants something right on the terrain, or right on the floor of an interior

we're experimenting with a method like this for our in-game furniture positioning in vSide.
eg, cast a ray, and use the collision point and normal to automatically position & orient the object being moved.
#7
06/25/2008 (2:16 pm)
Orion, that's the similar purpose here actually.

There is a drop to ground feature in TGE also, but it doesn't seem to work very well and seems to depend on the collision box or object origin. So far this works well, with an exception of letting the object sink into a wall up to their origin point. That's desirable behavior for my purposes anyway.

I was able to also let the group continue even if one object collided, which lets me drag a group and they all align appropriately against the wall/ground.

I also added a global flag as the collision mask (good idea Mark!) which enables/disables and specifies the objects which will block the movement. Here's an updated version:

void WorldEditor::Selection::offset(const Point3F & offset)
{

   for(U32 i = 0; i < mObjectList.size(); i++)
   {
      MatrixF mat = ((SceneObject*)mObjectList[i])->getTransform();
      Point3F wPos;
	  Point3F nPos;
	  Point3F hitPoint;
          mat.getColumn(3, &wPos);
	  nPos = wPos;
	  nPos += offset;

	  RayInfo info;
	  hitPoint = offset;
	  S32 colMask = Con::getIntVariable("$EditorMovementCollisionMask");
	  if(colMask)
	  {
		  if(gServerContainer.castRay(wPos, nPos, colMask, &info))
		  {
			hitPoint = info.point;
			continue;
		  }
	  }

	  }
      // adjust
      wPos += hitPoint;
      mat.setColumn(3, wPos);
      ((SceneObject*)mObjectList[i])->setTransform(mat);
   }

   mCentroidValid = false;
}

In game.cc's GameInit() I added:

Con::addVariable( "$EditorMovementCollisionMask", TypeS32, &gEditorMovementCollisionMask);

and under the includes:

static S32 gEditorMovementCollisionMask = 0;


Then to toggle it all I use: $EditorMovementCollisionMask = 0; and $EditorMovementCollisionMask = $TypeMasks::InteriorObjectType;
respectively.
#8
06/25/2008 (2:21 pm)
Is there any noticable speed difference while editing?
#10
06/25/2008 (3:51 pm)
Sweet, it's going in right now.