Chain physics

Started by
3 comments, last by helix 21 years, 6 months ago
I am trying to model a chain hanging from a movable object and would like to get some realistic motion. I found something online that had somewhat of a description but when I tried what they said to do, my chain is not visible (presumably because my calculations moved it offscreen somewhere...). How does my code look? The URL in my comments is where I found the description.
  
// Chain physics

	//	http://www.lns.cornell.edu/spr/2001-06/msg0033480.html

	//	Neighboring masses connected by a spring of natural length 1 and spring constant k


	D3DXVECTOR3 vForceParent = D3DXVECTOR3(0.0f,0.0f,0.0f);
	D3DXVECTOR3 vForceChild = D3DXVECTOR3(0.0f,0.0f,0.0f);
	D3DXVECTOR3 vForce = D3DXVECTOR3(0.0f,0.0f,0.0f);
	D3DXVECTOR3 vPos;
	float r, f;

	// Find the force on the mass due to parent (if not top level link)

	if( m_pParent && m_nLink > 1 )
	{
		vPos = m_pParent->GetPos();
		vForceParent.x = vPos.x - m_vPos.x;
		vForceParent.y = vPos.y - m_vPos.y;
		vForceParent.z = vPos.z - m_vPos.z;

		r = (float)sqrt( (vForceParent.x * vForceParent.x) + (vForceParent.y * vForceParent.y) + (vForceParent.z * vForceParent.z) );
		f = r - 1.0f;

		vForceParent.x = f * vForceParent.x / r;
		vForceParent.y = f * vForceParent.y / r;
		vForceParent.z = f * vForceParent.z / r;
	}

	// Find the force on the mass due to child (if not bottom level link with nothing attached)

	//TODO: Only handle one child currently

	if( m_pChildren.GetSize() > 0 && (m_nLink < s_nNumLinks || m_bPayload) )
	{
		vPos = m_pChildren[0]->GetPos();
		vForceChild.x = vPos.x - m_vPos.x;
		vForceChild.y = vPos.y - m_vPos.y;
		vForceChild.z = vPos.z - m_vPos.z;

		r = (float)sqrt( (vForceChild.x * vForceChild.x) + (vForceChild.y * vForceChild.y) + (vForceChild.z * vForceChild.z) );
		f = r - 1.0f;

		vForceChild.x = f * vForceChild.x / r;
		vForceChild.y = f * vForceChild.y / r;
		vForceChild.z = f * vForceChild.z / r;
	}

	// Find resultant force on the mass

	vForce = vForceParent + vForceChild;
	vForce.y += GRAVITY;				// Gravity

	vForce *= 0.5f * FRAMERATE_S;

	// Update the position of the link

	m_vPos += vForce;
  
If this is a bad way of doing it, does anyone have a suggestion for a better method?
Advertisement
Well, I found a better method in the book "Physics for Game Developers." My chain still doesn''t function correctly though. The only link visible is the "locked" one (doesn''t recieve any forces on it). So something is screwy.


  //// ChainPhysics()//	Runs the chain physics//void CraneChain::ChainPhysics( void ){	D3DXVECTOR3 dragVector;	D3DXVECTOR3 f1,f2,d,v;	float L;	// Process gravity and drag forces if not top level link	if( m_nLink > 1 )	{		// Gravity		m_vForces += GRAVITY_VEC * LINK_MASS;		// Viscous drag		dragVector = -m_vVel;		D3DXVec3Normalize( &dragVector, &dragVector );		m_vForces += dragVector * Util::VecLen2( &m_vVel ) * DRAG_COEFFICIENT;		// Wind		D3DXVECTOR3 windVec;		windVec.x = RandomFloat(0.0f,10.0f);		windVec.y = 0.0f;		windVec.z = RandomFloat(0.0f,1.0f);		Util::Normalize( &windVec, &windVec );		m_vForces += windVec * WIND_FORCE_FACTOR;		// Process spring forces		if( m_pChildren.GetSize() > 0 )		{			d = m_vPos - m_pChildren[0]->GetPos();			v = m_vVel - m_pChildren[0]->GetVel();			L = (CHAIN_OUTER_RADIUS + CHAIN_INNER_RADIUS) * 2.0f;	// Length of spring at rest			const float len = Util::VecLen( &d );			const float dot = Util::DotProd( &v, &d );			f1 = -(SPRING_TENSION * (len - L) + SPRING_DAMPENING * dot / len) * (d / len);			f2 = -f1;			m_vForces += f1;			m_pChildren[0]->SetForces( &f2 );		}	}	m_vAccel = m_vForces / LINK_MASS;	m_vVel += m_vAccel * FRAMERATE_S;	m_vPos += m_vVel * FRAMERATE_S;	//TODO: Collision detection and response}  
Ok, I forgot to transform the child's position into the correct object space.

D3DXVec3TransformCoord( &d, &(m_pChildren[0]->GetPos()), &m_mAnimPoint );
d = m_vPos - d;

Still doesn't work correctly, but now I have something to work with (my links are visible). The problem is that the links aren't bound together like you would expect. What I mean is the chain keeps expanding forever, there aren't any constraints to keep it together. Where could I add this constraint?

[edited by - beoch on October 7, 2002 8:16:03 PM]
I tried to do something like that once, and your code seems very similar to mine(which I no longer have). I can''t see why your chain would expand. The lines
f1 = -(SPRING_TENSION * (len - L) + SPRING_DAMPENING * dot / len) * (d / len);
f2 = -f1;
m_vForces += f1;
m_pChildren[0]->SetForces( &f2 );
should pull the links together.
What do you have SPRING_TENSION, SPRING_DAMPENING, and L defined as?

  const float SPRING_TENSION	= 500.0f;const float SPRING_SHEAR	= 300.0f;const float SPRING_DAMPENING    = 2.0f;const float CHAIN_OUTER_RADIUS	= 2.0f;const float CHAIN_INNER_RADIUS	= 1.0f;......L = (CHAIN_OUTER_RADIUS + CHAIN_INNER_RADIUS) * 2.0f;	// Length of spring at rest  


I never thought of tweaking those values. I was modifying some code for a flag sample that used springs so they might be off for what I was trying to do...

This topic is closed to new replies.

Advertisement