Game Development Community

1.7.4 : MountForce can't be zeroed

by DragonSix · in Torque Game Builder · 09/07/2008 (9:45 am) · 32 replies

I try to have mounted objects without any mount force, that follow faithfully the moves of the parent with no lag.

Since 1.7.4, it is not possible anymore O_o
%object.setmountforce(0) doesn't set the mount force to 0, ever.

I tested using the exact same code on the 1.5.1 executable, and it does set the mount force correctly.
This is a 1.7 issue.

PS : on 1.7 it seems sometimes it works, sometimes it doesn't, this is very odd...
Page «Previous 1 2
#1
09/07/2008 (9:58 am)
Ok, now this is very odd. I was wrong, it's not every time it doesn't work, but on some instance, it just WONT apply the force I'm asking for.
#2
09/07/2008 (10:11 am)
Here's the code I'm using :
%members = getwordcount(%frame.members);
	for ( %i = 0; %i < %members; %i++ )
	{
		%member = getWord(%frame.members, %i);
		
		%point = %member.mount(%target, %mountlinkpoint, [B]0[/B], 0, 0, 1, 1);
	}
Each member is a static sprite, mounted to a set target, but, for no logical reason, some of these members (which are all identical in all aspect except for the image itself) wont apply the Zero force, and will lag behind the moves of the target.

Then, trying to reset the force on the laggy members wont affect them at all Oo
#3
09/16/2008 (3:03 pm)
We've run into this too, it seemed that between 1.7.2 and 1.7.4 the ability to rigid mount a sprite has disappeared.

To help showcase the problem, here is a project in 1.7.2 and the same project in 1.7.4. It's a way simplified case of one sprite mounted to another, doing crazy moves on a path.

TGB 1.7.2 - mounts are rigid
http://www.skunkstudios.com/bugs/TestMounts_172.zip

TGB 1.7.4 - mounts are um, floppy
http://www.skunkstudios.com/bugs/TestMounts_174.zip

This is kind of a major problem, since the rigid mounting is awesome and we use it all over the place in our games.

Can we get either a fix or just a post on how to fix it? We've compiled all our tune ups into the new engine and really want to move forward on 1.7.4 rather than 1.7.2 due to all the sweet physics and performance improvements.
#4
09/20/2008 (10:19 am)
A little bump to say that I'm not anymore personally bothered by the issue as I could make my own game look good even with it. It doesn't change the fact that it still exist and can bother other people.

@Kalle
Great example, it's exactly what I was talking about.
#5
09/24/2008 (6:08 pm)
There may be a workaround, like aligning everything manually with an onUpdate event, however not having rigid mounts work is a pretty bad bug injection IHMO. I think there was some "removed a redundant second update call" somewhere in the 1.7.3 or 1.7.4 build notes. I have also seen other oddities like the "onTimer" handler fires a lot less often in 1.7.3 causing sprites that used to move smoothly to move much choppier.

I think having a sweet and tuned up physics engine overrides these issues but I am on a mission to get the rigid stuff fixed. Melv May, paging Melv May...
#6
09/24/2008 (6:43 pm)
This bug is related to the process order of mount parents and all of their children. An explanation can be found here:

www.garagegames.com/mg/forums/result.thread.php?qt=51116

The fix in that thread is out of date, though it does work. However, it does not allow for fast mounting/dismounting and can be quite cumbersome on the engine itself. Melv has acknowledged this bug and will endeavour to address it when possible.
#7
09/26/2008 (1:54 am)
Hi everyone,

Just thought I'd jump in and help. I wanted to look at this last night but I got home and was consumed with family stuff until late.

I can't offer up a new release but I can offer-up a fix for anyone with source code.

I'll * definitely* look at this tonight (7pm GMT+0) and post back here with my findings and a fix.

Melv.
#8
09/28/2008 (2:10 am)
Oh dear, so busy.

Finally, I'm downloading the examples from above and looking at this issue now. I won't move until I know what's going on!!!!! :)

Melv.
#9
09/28/2008 (3:58 am)
Here's a has-it-happens update:

Looking at this, it seems that rigid-mounting is not broken at all but what seems to be happening is that the "t2dPath" object is being naughty. The modifications to the mounting/physics are correct but they have exposed a flaw in the way the "t2dPath" object works.

I stepped through the mounting code using the "TestMounts_174" example above and the process works perfectly. What's not obvious when you do this is that the positions its moving to are out of sync with the parent object.

A brief look at the "t2dPath" object (which I don't know an awful lot about to be honest) indicates that its moving the scene-objects but the problem is that when it takes ownership of the object, it doesn't change its process-order.

I removed the "t2dPath" from the scene, created a world-limit for the parent object which I set to bounce, gave it some linear velocity and the child tracked the parent as you'd expect.

For now at least, the problem seems to be the "t2dPath" object. If anyone is experiencing this problem without using the "t2dPath" object then please let me know ASAP!

If you don't rigid-mount then this problem would still be there but just harder to detect.

I'll see if there's a way to fix this that would allow me to easily post-up some code.

Melv.
#10
09/28/2008 (5:07 am)
Okay, so I've managed to trace this problem down to the root cause. Essentially what's happening is that the "t2dPath" is incorrectly setting the positions of the objects on its path using the native "t2dSceneObject::setPosition()" method and whilst that doesn't seem a problem, it's not good behaviour in the face of tick physics. What you're supposed to do is call "t2dPhysics::setPosition()".

The difference is that when you call the "t2dSceneObject" call you reset the tick physics call for that tick. This makes sense as you do not want the object interpolating from its old position to the new position you just specified, especially if the new position is a large distance from the old position. Instead, you want it to instantly move to the new position. This is why constantly using "setPosition" calls works against tick-physics and so for the rest of the tick interval, no interpolation happens.

Now, when "t2dPath" uses the incorrect "setPosition" call, it causes the object to be stationary for the next tick interval. If this object has children mounted (as is the case in this thread), the children do update during the tick and so there's a disjoint movement between the two objects for that tick interval.

Unfortunately, "t2dPath" constantly uses this call which means that objects on a path don't use tick-physics but just jump from point to point with no interpolation leading to the observation here.

On top of this, there's also an identical problem with the rotation of the object not interpolating and you would experience a similar lag.

So the fix is pretty easy and just requires that the "t2dPath" types call the parent physics methods for "setPosition" and "setRotation".

I'll split this post up and follow with the modified code....
#11
09/28/2008 (5:09 am)
... code fixes ...

//----------------------------------------------------------------------------------------------
// Linear Interpolation.
//----------------------------------------------------------------------------------------------
void t2dPath::linear(PathedObject& object)
{
   // Grab destination, position, and direction.
   t2dVector destination = mNodes[object.mDestinationNode].position;
   t2dVector position = object.mObject->getPosition();
   t2dVector direction = destination - position;
   direction.normalise();

   // Set the velocity.
   object.mObject->setLinearVelocity(direction * object.mSpeed);

   if (object.getOrientToPath())
   {
      t2dVector direction = position - destination;
      F32 rotation = -mAtan(direction.mX, direction.mY);
      object.mObject->getParentPhysics().setRotation(mRadToDeg(rotation) - object.getRotationOffset());
   }
}

//----------------------------------------------------------------------------------------------
// Bezier Interpolation.
//----------------------------------------------------------------------------------------------
void t2dPath::bezier(PathedObject& object, F32 dt)
{
   S32 i = object.mSourceNode;
   S32 j = object.mDestinationNode;
   S32 dir = object.mSourceNode % 2 ? -object.mDirection : object.mDirection;
   t2dVector a = mNodes[i].position;
   F32 rot = mDegToRad(mNodes[i].rotation + (90.0f * dir));
   t2dVector b = a + (t2dVector(mCos(rot), mSin(rot)) * mNodes[i].weight);
   t2dVector d = mNodes[j].position;
   if ((j == 0) && (mNodes.size() % 2)) dir = -dir;
   rot = mDegToRad(mNodes[j].rotation + (90.0f * dir));
   t2dVector c = d + (t2dVector(mCos(rot), mSin(rot)) * mNodes[j].weight);
   
   F32 length = (object.getDirection() == 1) ? getNode(object.getCurrentNode()).bezierLength : getNode(object.getDestinationNode()).bezierLength;
   object.mTime += dt * object.mSpeed;

   F32 t = object.mTime / length;
   if (t > 1.0f) t = 1.0f;
   F32 it = 1.0f - t;
   t2dVector prevPos = object.mObject->getPosition();
   object.mObject->getParentPhysics().setPosition((a*it*it*it) + (3*b*it*it*t) + (3*c*it*t*t) + (d*t*t*t));
   t2dVector currPos = object.mObject->getPosition();

   if (object.getOrientToPath())
   {
      t2dVector direction = currPos - prevPos;
      F32 rotation = -mAtan(direction.mX, direction.mY);
      object.mObject->getParentPhysics().setRotation(mRadToDeg(rotation) + 180.0f - object.getRotationOffset());
   }
}

//----------------------------------------------------------------------------------------------
// Catmull-Rom Interpolation.
//----------------------------------------------------------------------------------------------
void t2dPath::catmull(PathedObject& object, F32 dt)
{
   S32 p0 = object.mSourceNode - object.mDirection;
   S32 p1 = object.mSourceNode;
   S32 p2 = object.mDestinationNode;
   S32 p3 = object.mDestinationNode + object.mDirection;

   F32 length = (object.getDirection() == 1) ? getNode(object.getCurrentNode()).catmullLength : getNode(object.getDestinationNode()).catmullLength;
   object.mTime += dt * object.mSpeed;

   S32 nodeCount = mNodes.size();
   if (p0 < 0) p0 = nodeCount - 1;
   else if (p0 >= nodeCount) p0 = 0;
   if (p3 >= nodeCount) p3 = 0;
   else if (p3 < 0) p3 = nodeCount - 1;

   F32 t = object.mTime / length;
   if (t > 1.0f) t = 1.0f;
   t2dVector pos = 0.5 * ((2 * mNodes[p1].position) + (-mNodes[p0].position + mNodes[p2].position) * t +
      (2 * mNodes[p0].position - 5 * mNodes[p1].position + 4 * mNodes[p2].position - mNodes[p3].position) * t * t +
      (-mNodes[p0].position + 3 * mNodes[p1].position - 3 * mNodes[p2].position + mNodes[p3].position) * t * t * t);

   t2dVector prevPos = object.mObject->getPosition();
   object.mObject->getParentPhysics().setPosition(pos);
   t2dVector currPos = pos;

   if (object.getOrientToPath())
   {
      t2dVector direction = currPos - prevPos;
      F32 rotation = -mAtan(direction.mX, direction.mY);
      object.mObject->getParentPhysics().setRotation(mRadToDeg(rotation) + 180.0f - object.getRotationOffset());
   }
}
#12
09/28/2008 (5:09 am)
Please let me know if this solves your problem.

Melv.
#13
09/28/2008 (5:13 am)
This bug was logged as TGB#136.
#14
09/28/2008 (5:33 am)
Just wanted to add that this fix also has the benefit that objects on the path will move much more smoothly between nodes as they now work with tick-physics.

Melv.
#15
09/29/2008 (1:30 pm)
Melv,

Thanks for the path related fix! We will implement this today. It's also great to hear motion will be smoother; we've seen some hitching with pathing from time to time and we use a lot of paths, so, COOL!

However... you'd asked whether this happens NOT on a path. Yes, it does. Here is a simple example demoing a sprite that moves to the mouse position with mounted kids - crisp in 1.7.2 but lags in 1.7.4. Also, clicking the mouse schedules 3 simple 'setPosition' calls at 1 second intervals, detached from the onUpdate event, and also demonstrates the lag issue.

Crisp in 1.7.2
http://www.skunkstudios.com/bugs/MountNoPath_172.zip

Not crisp in 1.7.4
http://www.skunkstudios.com/bugs/MountNoPath_174.zip

My guess is that the t2dPath fixes wouldn't address this one, but that the issue is similar - eg. perhaps in the t2dStaticSprite or t2dSceneObject classes?

Thanks Melv, really appreciate you looking into this.
#16
09/29/2008 (1:33 pm)
I've also seen the issue happening on staticsprites using setlinearvelocity.
#17
09/29/2008 (2:15 pm)
I'll see if I can find some time on Tuesday to look at those examples. Be aware though that setting the position temporarily stops the objects from interpolating its movement. That can last for up to 1/30th second (using default settings) which is a considerable amount of time. It doesn't matter when you call it either.

Juddering can be caused by using vsync and the rendering and/or other script-callbacks causes you to miss the next logical frame(s). This can cause hitches in the rendering. It's one of the reasons why people using triple-buffering when use vsync in D3D so that the occasional extra time spent doesn't causes a sudden halving of frame-rate.

There are also other reasons why you get hitching, non of which are caused by bugs.

If you can guarantee that your code runs consistently and doesn't suddenly do alot of work in the scripts then there might be something else going on I could trace.

As I say, I'll have a look at your examples above and see if I can isolate the problem.

Cheers,

Melv.
#18
10/14/2008 (11:56 pm)
... oh so very busy all the time. Not looked at this but I can do so shortly.

Sorry!

Melv.
#19
10/28/2008 (9:36 pm)
Melv, in terms of the Sep 29 post, the bug is not related to using vsync or anything odd like that. The demo MountNoPath_174.zip is the simplest case of the bug injected in 1.7.3 that's jacked up the sweet TGB rigid mount system, because all mounted sprites (editor or code) have this sloppy / loose feel as if it was mounted with a non-zero value. In my opinion it's the type of bug that QA missed since it should be widely observed with any rigid mounting tests.

I'm thinking that the solution is just eluding us slightly and thus begging the wisdom of the Melv to get us the elegant one-line fix???
#20
10/29/2008 (1:31 am)
Another failure for my reminder system, sorry!

I've just downloaded those files here and will look at them later this morning (have a reminder on my computer to bug me now). I am not sure if it's related but I have found/fixed a bug related to mounting where when setting the position of an object from script doesn't cause its mounted children to also be move. This results in the tick system interpolating from the old position to the new position.

This could be a slightly related or similar issue.

I'll let you know.

Melv.
Page «Previous 1 2