Game Development Community

ShapeInstance Data Corruption with high values - LOGGED

by Ivan Mandzhukov · in Torque 3D Professional · 11/10/2010 (7:25 pm) · 5 replies

Hi,
I spent 2-3 days to track e serious bug in a loaded scene.The problem turned out to be a ShapeInstance data curruption.
Some of the transforms as mNodeTransforms usually work well,but suddently on a high load become broken (values are infinit).
Currently I can not locate why this happens,because the bug is hard to be reproduced.

I catch the bug this way:
MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni];
Point3F position.
mountTransform.getColumn( 3, &position );
if( mIsNaN( position ))
	position.set(0,0,0);

This is a stock T3D code.
This bug replicates to Player::calcClassRenderData() and the ray cast there results to a bad bin range.

If I workaround the problem,the crash will not happen, but this corrupts the rendering of the shape instances (missing heads,missing bone data,etc..)

Any ideas will be appreciated.

#1
11/11/2010 (3:28 pm)
Logged as TQA-1198 for the QA team to verify.
#2
11/12/2010 (8:57 am)
thanks ,David.
Currently I found what is causing the issue - when I have two animation threads at the same time on a single player.
This should be not a problem,because T3D is using many threads to control the character's animation.
I will update this forum thread when I find the solution.
#3
11/12/2010 (1:36 pm)
I find some interesting bugs.

In tsTransform.cpp,at the bottom of the file I see this:

void TSTransform::applyScale(const TSScale & scale, MatrixF * mat)
{
   MatrixF mat2;
   TSTransform::setMatrix(scale.mRotate,&mat2);
   MatrixF mat3(mat2);
   mat3.inverse();
   mat2.scale(scale.mScale);
   mat2.mul(mat3);
   mat->mul(mat2);
}

All looks good,but if you pass an identity transform,after inversing I get a non identity transform - ouch!

In mMatrix.h ,locate this:
inline MatrixF& MatrixF::inverse()
{
   m_matF_inverse(m);
   return (*this);
}
and replace with this:
inline MatrixF& MatrixF::inverse()
{
   if(isIdentity()) return (*this);
   m_matF_inverse(m);
   return (*this);
}

Currently this does not solve my problem,but it seems the bug is a combination of several small transformation bugs.
#4
11/13/2010 (5:20 am)
Was there more to your post that's now missing?
#5
11/13/2010 (6:47 am)
@Ken

Using multiple threads with complex animations may crash the time duration (transitiondata.duration),this bug then replicates to the delta.
This is just a workaround,I will provide the full fix but I need some time to track several things.

EDIT:

OK,guys,here is the full fix.When we have a real load (1-2 fps),the transition code sometimes gets confused at this frame,so:

tsThread.cpp
locate TSShapeInstance::updateTransitions()

at the bottom of this method find this:
// reset transition durations to account for new reference transforms
   for (i=0; i<mTransitionThreads.size(); i++)
   {
      TSThread * th = mTransitionThreads[i];
      if (th->transitionData.inTransition)
      {
         th->transitionData.duration *= 1.0f - th->transitionData.pos;
         th->transitionData.pos = 0.0f;
      }

	  if(th->transitionData.duration>1)
	      th->transitionData.pos = 0.0f;
   }

and replace with:

// reset transition durations to account for new reference transforms
   for (i=0; i<mTransitionThreads.size(); i++)
   {
      TSThread * th = mTransitionThreads[i];
      if (th->transitionData.inTransition)
      {
	 if((th->transitionData.duration<0.0001) || (th->transitionData.duration>1))
         th->transitionData.duration = th->getSequence()->duration;

         th->transitionData.duration *= 1.0f - th->transitionData.pos;
         th->transitionData.pos = 0.0f;
      }

	  if(th->transitionData.duration>1)
	      th->transitionData.pos = 0.0f;
   }

Also locate this:

TSThread::TSThread(TSShapeInstance * _shapeInst)
{
   timeScale = 1.0f;
   mShapeInstance = _shapeInst;
   transitionData.inTransition = false;
   blendDisabled = false;
   setSequence(0,0.0f);
}

and replace with this:

TSThread::TSThread(TSShapeInstance * _shapeInst)
{
   timeScale = 1.0f;
   mShapeInstance = _shapeInst;
   transitionData.inTransition = false;
   blendDisabled = false;
   setSequence(0,0.0f);
   transitionData.duration = 0.0f;
}

This is good for animations without transitions to have zero durations instead of random numbers.

Locate advancePos().
At the beginning of this method paste this:
void TSThread::advancePos(F32 delta)
{  if (mFabs(delta)>0.0f && mFabs(delta)<0.00001f) 
      delta = 0.00002f;
   if (mFabs(delta)>1000) 
      delta = 0.0f;
...

Now when delta is ranged, this prevents the shape instance from being animated with wrong values.