Cloth Physics

Started by
14 comments, last by BloodLust666 (dupe) 16 years, 5 months ago
I've been working on cloth physics for some time now and I can't seem to get it to look right. I'm using the spring-ball approach where I'm loading a mesh, creating a ball at everything vertice and putting a spring through all edges and one past it (as long as the dot product of those vectors are close to 1). I'm also calculating using Hooke's look and a spring constant, but I can't seem to find the right values to make it look right, the cloth seems to stretch too much and look very rubbery. I want to be able to set a maximum (and maybe minimum) percent each spring can stretch and have the cloth stay intact. Here's an image of what i'm seeing:
Eddie RiveronSoftware EngineerCreator of 3D Wrath EngineWebsite soon!
Advertisement
Can you post the code you use?
I remember that there's a very good article linked from here about cloth sim, I use it sometimes ago.
The real problem with cloth sim is that it's hatd to make it "rigid". Springs/mass are great for very soft cloth, but you can't really make a "rigid" cloth without a very good integration scheme, or small time step etc. (which mean more computation time).
Increase the spring constant to get something harder, but maybe you will have to fight against oscillations, which can be decrease with damping...

I think another way to create cloth is to use the fast LSM (which was posted here 1 or 2 month ago), which could lead, I think, to very hard and stable cloth.
		void cWCloth::_Update(WcrFLOAT dt)		{			float springLen;			float extension;			sWVector3D force, acc, vel;			sWVector3D tension;			for (WuLONG i=0 ; i<m_Springs.GetNetItems() ; ++i)			{				springLen = ((*m_pCurrent)[m_Springs->m_BallIndex[0]]->m_Position -							(*m_pCurrent)[m_Springs->m_BallIndex[1]]->m_Position).Length();				extension = springLen - m_Springs->m_fNaturalLength;				m_Springs->m_fExtension = springLen / m_Springs->m_fNaturalLength;				m_Springs->m_fTension = m_fSpringConstant * extension / m_Springs->m_fNaturalLength;			}			for (WuLONG i=0 ; i<m_Balls[0].GetNetItems() ; ++i)			{				force = m_v3Gravity + m_v3ExternalForce;				vel = sWVector3D();				for (WuLONG j=0 ; j<m_Springs.GetNetItems() ; ++j)				{                    // if the the current ball is the first ball of the spring					if (m_Springs[j]->m_BallIndex[0] == i)					{						tension = (*m_pCurrent)[m_Springs[j]->m_BallIndex[1]]->m_Position -									(*m_pCurrent)->m_Position;						tension.Normalize();						force += tension * m_Springs[j]->m_fTension;						/*if (m_Springs[j]->m_fExtension > m_fMaxExtension)						{							vel += (tension * 								((m_Springs[j]->m_fExtension - m_fMaxExtension) 								* (m_Springs[j]->m_fNaturalLength)));						} else						if (m_Springs[j]->m_fExtension < m_fMinExtension)						{							vel += (tension * 								((m_Springs[j]->m_fExtension - m_fMinExtension) 								* (m_Springs[j]->m_fNaturalLength)));						}*/					}					else                    // if the current ball is the second ball of the spring					if (m_Springs[j]->m_BallIndex[1] == i)					{						tension = (*m_pCurrent)[m_Springs[j]->m_BallIndex[0]]->m_Position -									(*m_pCurrent)->m_Position;						tension.Normalize();						force += tension * m_Springs[j]->m_fTension;					}				}								// Calculate where the ball is going to be				acc = force / m_fBallMass;				(*m_pNext)->m_Velocity = (*m_pCurrent)->m_Velocity + (acc * dt) + vel;				(*m_pNext)->m_Velocity *= 0.75f;				if (i != 0 && i != 110)				(*m_pNext)->m_Position = (*m_pCurrent)->m_Position + 					((*m_pCurrent)->m_Velocity + (*m_pNext)->m_Velocity) * dt/2.0f;				// Position the vertice at the next ball				if (i != 0 && i != 110)				m_pModel->Objects[0]->Verts->Vertex = (*m_pNext)->m_Position;			}			// Swap the lists			tWVectorList<sWBall> * temp = m_pCurrent;			m_pCurrent = m_pNext;			m_pNext = temp;		}


inside that comment, i tried to add implementation for what i was saying; having a maximum percent of extension and minimum extension. it worked a little bit, but not completely...
Eddie RiveronSoftware EngineerCreator of 3D Wrath EngineWebsite soon!
If I understand correctly you apply a 0.75 damping on velocituy, this can be a too much (I think value between 0.99 and 0.95 are better, lower the system will loose to much energy).

Also I'm surprised about
m_Springs-&gt;m_fExtension = springLen / m_Springs-&gt;m_fNaturalLength;m_Springs-&gt;m_fTension = m_fSpringConstant * extension / m_Springs-&gt;m_fNaturalLength

(maybe I just don't understand the code), but the force to apply to the particle are lineary dependant to the extension (in meter). For example if the spring has a rest length of L, and the distance between the 2 particles are X, then the force is X * constant.
The higher the constant value is, the harder the cloth will be.
You can also apply other forces, look at this article (this is the one I was talking in my previous post) :
http://www.intel.com/cd/ids/developer/asmo-na/eng/20413.htm
Natural length is the length of the edge when i first loaded the mesh and created the balls.

The extension is the percentage from the current length divided by the natural length.

I remember now why i changed the damp from .95 to .75, because this happened

Eddie RiveronSoftware EngineerCreator of 3D Wrath EngineWebsite soon!
That article is good and all; the code works and it looks like really good cloth, but the code is a bit big to try to break apart and figure out my specific problem... Is there maybe some tutorial or any other smaller projects that show how to do cloth physics?
Eddie RiveronSoftware EngineerCreator of 3D Wrath EngineWebsite soon!
I would use infinitely stiff springs. Look at the Thomas Jakobsen character physics article. I think I have some code somewhere, but I achieved a very basic cloth animation demo like that very easily. Not sure about springs, especially when you need very stiff springs and you are performing a basic euler integration.

Everything is better with Metal.

I can second the Jakobsen recommendation, it is quite easy to come up with a stable implementation using this approach. You may also want to check out how Ageia did their cloth, it's described here (PDF). This has a nice approach for implementing bending constraints amongst other things.
I agree with above that the method described by Jakobsen is pretty easy to implement nice looking springs.

However, I have some source codes of different springs implementation; the problem is I can't remember where I found it:) If you find out who is author, let me know.
http://data.hardwire.cz/nic/springs.zip
Ok, I have new implementation and it works A LOT better. The cloth is now intact but it waves WAY too much... it seems that the forces are too great for it.

void cWCloth::_Update(WcrFLOAT dt)		{			float springLen;			float extension;			//sWVector3D force, acc, vel;			//sWVector3D tension;			sWVector3D Force, relative, relVel;			float springForce, damp, force;			for (WuLONG i=0 ; i<m_Balls[0].GetNetItems() ; ++i)			{				if (i != 0 && i != 110)				{					m_Balls[0]->m_Velocity += (m_v3Gravity + m_v3ExternalForce) * dt;					m_Balls[0]->m_Position += m_Balls[0]->m_Velocity * dt;					m_pModel->Objects[0]->Verts->Vertex = m_Balls[0]->m_Position;				} else				{					m_Balls[0]->m_Velocity = sWVector3D();				}			}			for (WuLONG i=0 ; i<m_Springs.GetNetItems() ; ++i)			{				Force = m_Balls[0][m_Springs->m_BallIndex[1]]->m_Position - m_Balls[0][m_Springs->m_BallIndex[0]]->m_Position;				Force.Normalize();				relative = m_Balls[0][m_Springs->m_BallIndex[0]]->m_Position - m_Balls[0][m_Springs->m_BallIndex[1]]->m_Position;				relVel = m_Balls[0][m_Springs->m_BallIndex[0]]->m_Velocity - m_Balls[0][m_Springs->m_BallIndex[1]]->m_Velocity;				springForce = m_fSpringConstant * (relative.Length() - m_Springs->m_fNaturalLength);				damp = (m_fDamping * (relative * relVel)) / m_Springs->m_fNaturalLength;				force = (springForce + damp) / 2.0f;				Force *= force;				m_Balls[0][m_Springs->m_BallIndex[0]]->m_Velocity += Force * dt;				m_Balls[0][m_Springs->m_BallIndex[1]]->m_Velocity -= Force * dt;			}


The only way it looks decent is when:
m_fDamping = 1.4f
m_fSpringContant = 2000.0f
m_v3Gravity = vector(0, -100, 0)

Eddie RiveronSoftware EngineerCreator of 3D Wrath EngineWebsite soon!

This topic is closed to new replies.

Advertisement