Jerky movement

cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Jerky movement

Post by cobolt_dink »

I think this has always been a problem but with the fixed timestep I think i've noticed it a bit more. Objects that have a linear velocity on them don't move very smoothly all the time. Sometimes they are fine and then they will have a slight stutter to them. I always use btDefaultMotionState() when I create a rigid body and I always get the world transform from it when I render it. Is there something else I'm supposed to be doing? The physics are locked at 60 FPS but the renderer is uncapped and actually at lower rendering speeds (debug mode, even then ~200 FPS) the jerkyness seems to be even worse.
pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Re: Jerky movement

Post by pico »

Do your objects 'fly' or do they move over other bodies? If they move over a subdivided triangle mesh and stutter then this is currently a work in progress issue.
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: Jerky movement

Post by cobolt_dink »

I guess 'fly' would be more it. The linear velocity is set every frame so that it always has constant speed. The mesh they move over is just two triangles that make up a quad for the floor. There would still be a problem with this?
pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Re: Jerky movement

Post by pico »

If your body touches the triangle mesh on the ground then you can experience an edge collision.
When you use CCD then this problem will occur more often.

You can read more about that problem here:
http://code.google.com/p/bullet/issues/detail?id=27#c10
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: Jerky movement

Post by cobolt_dink »

I read through your link and that actually doesn't seem to be the problem I'm having (I think). My problem occurs everywhere and not just over a triangle edge. I moved the body up off the floor and the problem is still there. The effect is probably more like 'ghosting'. The ball is in one place and in the next frame it has jumped to another. To me it seems like the rigid body isn't getting interpolated. Even if that was the case having the physics locked at 60 and the renderer running at ~200 I would think the physics would be called enough for the movement to look smooth.
User avatar
sinoth
Posts: 13
Joined: Tue Apr 07, 2009 8:27 pm
Location: USA

Re: Jerky movement

Post by sinoth »

Do you mind sharing your code that deals with the physics step, grabbing the world transform, and rendering? Maybe we can find something odd there.
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: Jerky movement

Post by cobolt_dink »

Timestep:

Code: Select all

#define PHYSICS_TIMESTEP 1.0f/60.0f

void DoPhysics(float delta)
{
	m_accumulator += delta;

	while (m_accumulator >= PHYSICS_TIMESTEP)
	{
		m_dynamicsWorld->stepSimulation(PHYSICS_TIMESTEP);

		m_accumulator -= PHYSICS_TIMESTEP;
	}
}
Getting world matrix:

Code: Select all

D3DXMATRIX GetWorldMatrix()
{
	D3DXMATRIX mat; 

	if (GetBody() != NULL)
	{
		btTransform trans;
		GetBody()->getMotionState()->getWorldTransform(trans);
		mat = ConvertBulletTransform(&trans);

		return mat;
	}

void PrepareMatrixFromRULP(D3DXMATRIX &matOutput, D3DXVECTOR3 *R, D3DXVECTOR3 *U, 
									 D3DXVECTOR3 *L, D3DXVECTOR3 *P)
{
	matOutput._11 = R->x; matOutput._12 = R->y; matOutput._13 = R->z; matOutput._14 = 0.f;
    matOutput._21 = U->x; matOutput._22 = U->y; matOutput._23 = U->z; matOutput._24 = 0.f;
    matOutput._31 = L->x; matOutput._32 = L->y; matOutput._33 = L->z; matOutput._34 = 0.f;
    matOutput._41 = P->x; matOutput._42 = P->y; matOutput._43 = P->z; matOutput._44 = 1.f;
}

D3DXMATRIX ConvertBulletTransform(btTransform *bulletTransformMatrix)
{
   D3DXMATRIX world;
   btVector3 R = bulletTransformMatrix->getBasis().getColumn(0);
   btVector3 U = bulletTransformMatrix->getBasis().getColumn(1);
   btVector3 L = bulletTransformMatrix->getBasis().getColumn(2);
   btVector3 P = bulletTransformMatrix->getOrigin();

   D3DXVECTOR3 vR, vU, vL, vP;
   vR.x = R.x(); vR.y = R.y(); vR.z = R.z();
   vU.x = U.x(); vU.y = U.y(); vU.z = U.z();
   vL.x = L.x(); vL.y = L.y(); vL.z = L.z();
   vP.x = P.x(); vP.y = P.y(); vP.z = P.z();

   PrepareMatrixFromRULP(world, &vR, &vU, &vL, &vP);

   return world;
}
Rendering:

Code: Select all

for (size_t i=0; i<m_renderList.size(); ++i)
	{
		m_d3ddev->GetDevice()->SetMaterial(&m_renderList[i].GetMaterial().GetMaterial());
		m_d3ddev->GetDevice()->SetTexture(0, m_renderList[i].GetMaterial().GetTexture());
	
		for (int j=0; j<m_renderList[i].GetSize(); ++j)
		{
			m_d3ddev->GetDevice()->SetRenderState(D3DRS_TEXTUREFACTOR, 
				                                  D3DCOLOR_COLORVALUE(1, 1, 1, m_renderList[i].GetEntity(j)->GetAlpha()));
			m_d3ddev->GetDevice()->SetTransform(D3DTS_WORLD, &m_renderList[i].GetEntity(j)->GetWorldMatrix());
			m_renderList[i].GetEntity(j)->Render();
		}
	}
I have non physics based entities that move and they all seem to have smooth movement no matter the framerate. So I would assume I'm not doing something right with Bullet.
Jacky_J
Posts: 16
Joined: Fri May 11, 2007 7:06 am

Re: Jerky movement

Post by Jacky_J »

You're suffering from a problem called temporal aliasing. Even though you're using getWorldTransform, which supports interpolation, you're passing in a fixed time step so bullet doesn't interpolate (because it doesn't need to). If you pass in FrameTime to stepSimulation, the problem will go away. Of course this defeats the purpose of using a fixed timestep. I'm actually trying to figure out manually interpolate in bullet myself.
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: Jerky movement

Post by cobolt_dink »

The problem with the variable timestep is when I remove an rigid body the bodies on top of it don't always get activated and just hang in midair. Though even with the fixed timesetep I have to give a good 'up' impulse before removing the body to get the stacked bodies to active. Seems like a lose-lose all the way around.

I guess fixing my renderer to be locked at 60FPS would probably solve the problem too?
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: Jerky movement

Post by cobolt_dink »

This works but seems very hackish:

Code: Select all

             m_accumulator += delta;

	m_dynamicsWorld->stepSimulation(delta, 3);
	
	while (m_accumulator >= PHYSICS_TIMESTEP)
	{
		m_accumulator = -= PHYSICS_TIMESTEP;

		if (m_removeList.size() > 0)
		{
			for (std::list<btRigidBody *>::iterator it=m_removeList.begin(); it!=m_removeList.end(); ++it)
				RemoveRigidBody((*it));

			m_removeList.clear();
		}
	}
The main problem seems to be that the removed body doesn't stick around long enough for it to activate the bodies its in contact with before actually getting removed itself. Removing it after a full physics step has been completed seems to do the trick. But that seems really ugly.
Jacky_J
Posts: 16
Joined: Fri May 11, 2007 7:06 am

Re: Jerky movement

Post by Jacky_J »

Okay, so the problem is no longer with the accumulator, but with waking objects up. You shouldn't need to wrap your accumulator around your remove code. You may have to do something where you activate all your objects if you remove an object. Do you have your own list of objects?

pseudocode:

Code: Select all

void RemoveObject(Object *o) {
  addToDeleteList(o)

  for every other object {
    object.activate()
  }
}

cobolt_dink wrote:This works but seems very hackish:

Code: Select all

             m_accumulator += delta;

	m_dynamicsWorld->stepSimulation(delta, 3);
	
	while (m_accumulator >= PHYSICS_TIMESTEP)
	{
		m_accumulator = -= PHYSICS_TIMESTEP;

		if (m_removeList.size() > 0)
		{
			for (std::list<btRigidBody *>::iterator it=m_removeList.begin(); it!=m_removeList.end(); ++it)
				RemoveRigidBody((*it));

			m_removeList.clear();
		}
	}
The main problem seems to be that the removed body doesn't stick around long enough for it to activate the bodies its in contact with before actually getting removed itself. Removing it after a full physics step has been completed seems to do the trick. But that seems really ugly.
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: Jerky movement

Post by cobolt_dink »

I originally had lists of objects that started out together so that if one got removed only the items in the list would get activated. If you had several hundred objects on screen it seems like it would be quite a CPU drain to activate all of them when 99% of them would only go back to sleep. I wanted to get rid of the lists so I switched to this idea and to only activate the blocks that needed to be activated. But it seems like a full physics step needs to be taken so the activation will go through.
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: Jerky movement

Post by cobolt_dink »

Thought I had this problem fixed but it has come back using stacks of cylinders. And actually testing something else it happened to a stack of blocks that got hit in a short time frame. Anybody have any ideas other then activating all the bodies when I remove one? I know I can't be the first person to use Bullet that had stacks of objects and removed the bottom one to see what happened.