Observations and questions about SpatialTransformers

Hello all, here once again with some simple questions:



a) I'm using SimpleGame as a base for my app (don't need anything particularly fancy at this point), and so SpatialTransformers for my animations.  I've noticed that the more objects a ST controls (the higher numObjects is), the faster it runs.  As an example, say this were a part of my code:

SpatialTransformer st1 = new SpatialTransformer(1);
SpatialTransformer st2 = new SpatialTransformer(2);

/*initialize three boxes*/

st1.setObject(box1, 0, -1);
st2.setObject(box2, 0, -1);
st2.setObject(box3, 1, -1);

st1.setPosition(0, 10, new Vector3f(10, 0, 0));
st2.setPosition(0, 10, new Vector3f(10, 0, 0));
st2.setPosition(1, 10, new Vector3f(10, 0, 0));



In the above code, the two boxes controlled by st2 will reach the destination in half the time it takes box1 to reach there.  I've added lines like

st1.setSpeed(1/st1.getNumObjects());

and this seems to fix the problem, but...why does this happen in the first place? 

b) At the moment, I have several SpatialTransformers that each control a type of spatial (the animations for the different types are different, but all STs start, stop, and pause at the same time).  In the interest of optimization (running time and memory usage, not ease of writing), is it better to create one lage ST that oversees everything in the animation, or is it okay to have many smaller STs controlling the parts of the animation?

c) Related to b), how "expensive" is a call to interpolateMissing()?

Sorry to bother y'all with so many questions.  Thank you for reading and have a good day.

-Kal

Hi kalevinrajo;



Answers:



a)  The design of SpatialTransformer, and specifically the way it's update() method is structured, causes each Spatial controlled by the ST to be updated numObjects times.



public class SpatialTransformer extends Controller {

. . .

    public void update(float time) {
        curTime += time * getSpeed();
        setBeginAndEnd();
        Arrays.fill(haveChanged, false);
        delta = endPointTime.time - beginPointTime.time;
        if (delta != 0f) delta = (curTime - beginPointTime.time) / delta;
        for (int i = 0; i < numObjects; i++) {
            updatePivot(i);
            pivots[i].applyToSpatial(toChange[i]);
        }
    }



This is due to the fact that the draw() cycle is based on a traversal of the scenegraph.  For every Spatial / Node in the graph, if a Controller/SpatialTransformer is present, it is executed.  In the case where that ST is controlling more than one Node, each of those get's updated not only for itself, but also for each of the other Spatials controlled by that same ST. 

A couple of ways around this include:
- divide the speed by the number of objects controlled by the ST [as you noted]
- only control one Spatial/Node with each SpatialTransformer.


b)  Given the limitation noted above, I would stick to using one ST per animated Node.  That way, you don't need to use an artificial speed setting to get the correct behavior for animations. 

This should also be more efficient in the draw() cycle because each Node is only updated once, rather than numObjects times.

Unless you have a very large number of moving objects, the memory footprint question should be moot.

c)  I have not profiled the interpolateMissing() method, but you may find that you don't need to call it.

As you can see from this snippet from SpatialTransformer, the keyframed values you provide are getting interpolated for you by default:


public class SpatialTransformer extends Controller {

. . .

    private void updatePivot(int objIndex) {
        if (haveChanged[objIndex])
            return;

        haveChanged[objIndex] = true;
        int parentIndex = parentIndexes[objIndex];
        if (parentIndex != -1) {
            updatePivot(parentIndex);
        }
        pivots[objIndex].interpolateTransforms(beginPointTime.look[objIndex],
                endPointTime.look[objIndex], delta);
        if (parentIndex != -1)
                pivots[objIndex].combineWithParent(pivots[parentIndex]);
    }



I hope this helps.

cheers
-jg-