Game Development Community

Scene Controller "Mounted" to Scene Object?

by Aaron Miller · in Torque 2D Beginner · 03/11/2013 (8:04 pm) · 4 replies

I've been playing around with a way get the PointForceController to track a moving object. As I understand it, save for some camera functionality, mounting is gone. I know you can update the controller's position manually in script, but I was concerned that that might be slow and am wondering if there's a better option.

My C++ is EXTREMELY rusty, but I'm kind of clumsily experimenting based on code I've found in the engine. Basing code off the camera mounting seemed the wrong direction to go. The approach I tried, which works, is to read an object from script and continuously update the controller to its position.

I based the scene object reading code on the GuiSceneObjectCtrl class. The setSceneObject method appears to do what I want (though I'm not sure about the preIntegrate step) so I copied it and it's ConsoleObject method whole.

void GravityController::setTrackObject( const char *name  )
{
   // Reset existing object.
   mSelectedSceneObject = NULL;

   // Get Scene Name.
   mSceneObjectName = StringTable->insert( name ? name : "" );

   // Valid Scene Object Name?
   if ( *mSceneObjectName )
   {
      // Fetch Scene Object.
      SceneObject* pSceneObject = dynamic_cast<SceneObject*>(Sim::findObject( name ));
      // Valid?
      if ( pSceneObject )
      {
        // Yes, so set Scene Object.
        mSelectedSceneObject = pSceneObject;

        // The scene object needs to be integrated otherwise the render OOBB which this GUI control
        // relies upon will be undefined.  This dependency needs resolving but I suspect it never will.
        DebugStats debugStats;
        mSelectedSceneObject->preIntegrate(0.0f, 0.0f, &debugStats );
      }
   }

   else
      mSelectedSceneObject = NULL;

}

I then updated the controller's position at the start of the integrate step:

// Move with a tracked object if present
	if(!mSelectedSceneObject.isNull())
		mPosition = mSelectedSceneObject->getPosition();

It works, but I have a suspicion doing this here is pretty kludgy. Anyone have any advice or an opinion on this? I'm just looking to see if I'm on the right track.

#1
03/11/2013 (8:32 pm)
Aaron, you are correct, mounting as we knew it is gone in T2D MIT but it has been replaced with a much more powerful system - Joints! And it can all be done in script.

You have to change your mindset to work with how box2d handles things but once you do, the world will be your oyster.

Joints are created in your Scene.


myScene.createRevoluteJoint(sceneObjectA, sceneObjectB, [localAnchorA X/Y],[localAnchorB X/Y], [collideConnected]);

sceneObjectA The first scene object to connect to the joint. Use an empty string to indicate the Scene ground body

sceneObjectB The second scene object to connect to the joint. Use an empty string to indicate the Scene ground body.

localAnchorA The local point of the first scene object where the joint connects.

localAnchorB The local point of the second scene object where the joint connects.n

collideConnected Whether the scene objects can collide with each other while connected with this joint.

The function returns The joint Id (-1 if error).

I suggest looking at how it is done in ChainToy for a concrete example.

Note that here are several other types of joints, as described in great detail in our the Box2D manual : http://box2d.org/manual.pdf

And you can always consult our Physics guide for a thorough explanation of how they are integrated in T2D : https://github.com/GarageGames/Torque2D/wiki/Physics-Guide
#2
03/12/2013 (6:00 am)
You might be pleased to know that I added this option to the development branch here this morning.

You can use "setTrackedObject(sceneobject)" and "getTrackedObject()" to set to any scene-object.

Note that the controller will ignore the tracked object itself when applying forces irrelevant of whether it matches the picking rules. Also, when tracking an object, the "position" of the controller is still used but instead of it being a world-space position, it becomes a local-space position of the tracked object. This means that if it is set to (0,0) then the controller tracks the objects position exactly. If you set something else then that is relative to the tracked object and because it's in local-space, it accounts for any angle the object may have.

Hope this helps.
#3
03/12/2013 (4:55 pm)
@Simon: Thanks for feedback, especially the joint example, as I don't have a lot of experience with box2d yet. I thought that both objects would need to be SceneObjects, though. Do SceneControllers count as well? I wasn't seeing the class linkage to the box2d stuff.

@Melv: As usual, awesome! It's great to see how simple what I was trying to do actually was, and the local space aspect is a very nice touch for mounting-like offsets. Thanks!

A quick question about using them with objects: Do you see any problem with having several dozen scene controllers running simultaneously, or are you really meant to only have a few (I'm thinking like the trigger system of old). I see from the Sandbox examples that they can handle a lot of objects, but not sure if the inverse would be wise.
#4
03/13/2013 (2:40 am)
You're most welcome, good feature.

Quote:Do you see any problem with having several dozen scene controllers running simultaneously

I don't see a problem having lots of them but be aware they're active unlike triggers. By this I mean that each tick (approx 1/60th sec) they perform a pick operation on the scene to see what potential objects are there to apply the forces on. This operation however is very fast and it's the exact operation that the Scene itself uses to "pick" which objects are in the area formed by the SceneWindow view for rendering and because you can expect to get potentially thousands of frames per second, you can see it's a fast operation. This means that if nothing is picked then there's little overhead.

The more expensive portion of the PFC is when it does find target objects to apply a force to but here I tried to avoid things like square-roots for the radial-distance calculations etc so it's still pretty quick.

I would recommend however using the "setControlGroups()" and "setControlLayers()" which is past directly to the pick-system to narrow down the potential objects as this will give you the best performance. Also try to filter out using the above calls any static-body objects. These will be ignored by the PFC but it's quicker to not even pick them in the first place by filtering-out via control groups/layers.

So to summarize, you should find that the more objects that are having forces applied the higher the overhead.

Hope this helps.