# Problem with low granularity collision detection and response in cloth simulation

This topic is 3818 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

well, I have some spheres that are attached to vertices in a piece of cloth. Sort of a low granularity collision detection and response mechanism. The spheres keep the cloth from penetrating itself. So far I have calculated linear impulse in the collision response not accounting for friction. As a result, after calculating spring forces in the cloth, I calculate collisions between the spheres, which in turn modify the velocity when they collide If I run the simulation with the spheres unattached, the simultion runs fine, I can push spheres against each other, though when I attach them to the cloth, I get an ugly "bouncing effect" when I try to push the spheres together, and it bounces constantly and "explodes" due to having to deal with both linear impulse from collision and the spring damper forces, even though the springs are dampened. Spring forces are calculated first, and then I calculate collision just by using position, velocity, radius and mass, which modifies velocity if there is a collision. So I use the resulting velocity from the spring forces and feed it into the collision detection and response calculation loop, which further modifies it upon collision. Here's a link to the demo: Flag (Remember that the simulation is very delicate and unstable, so if you move the mouse quickly, it will blow up because of the numerical instability, even though the cloth is dampened, so if you move it around gently it will be ok. But that instability is precisely want I want to get rid of) Now, I intend to implement friction in the hopes that it will get rid of the "bounciness" and thus the shaking and the explosions. I need to calculate several things, among them the inertia tensor, but since the colliding objects are perfect spheres, I was thinking if I can substitute the intertia tensor matrix for a scalar. This is the formula I'm thinking of implementing for the linear impulse: J = -vr(e+1)/[1/m1 + 1/m2 + n*[(r1 x n)/I1] x r1 + n*[(r2 x n)/I2] x r2] J = linear impulse vr = relative velocity * = dot product x = cross product I1, I2 = inverse moment of inertia for body1 and body 2 e = Coefficient of resitution n = normal of the impact (unit length) r1, r2 = vector from body's center of gravity to the point of impact Now I would like to make I1 and I2 into a scalar 1.0 if possible to discard them. I have hopes that implementing friction will solve the instability, but if anyone has a quicker suggestion I'd be very thankful. Additionally, here's the important code that does the spring force calculations and the subsequent collision detection and response loop: Remember, this is Actionscript 3.0 and the site can't recognize the syntax, so I'm posting it as C++: And for some reasong the site is getting rid of some addition and subtraction symbols, so don't rely too much on the code below.

/////////// NOT C++ but AS3!!!! ////////////////////////////////

// Apply wind force
for(index = 0; index < TestCollisionSphereVertexList.length; index++)
{

WindX = (randRange(1,2000)-1000.0)/100.0;
WindY = (randRange(1,400)-200.0)/100.0;
WindZ = (randRange(1,400)-200.0)/100.0;

var WindMag:Number = Distance3D(0,0,0,WindX,WindY,WindZ);

WindX/=WindMag;
WindY/=WindMag;
WindZ/=WindMag;

var WindFactor:Number = (randRange(1,100)/100);

WindX*=0.3;
WindY*=0.3;
WindZ*=0.3;

TestCollisionSphereVertexList[index].ForceX+=WindX;
TestCollisionSphereVertexList[index].ForceY+=WindY;
TestCollisionSphereVertexList[index].ForceZ+=WindZ;

}// end for

// Calculate spring forces
for (index = 0; index < TestCollisionSphereSpringList.length; index++)
{

// Calculate difference in position
var PosDiffX:Number = TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].PosX - TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].PosX;
var PosDiffY:Number = TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].PosY - TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].PosY;
var PosDiffZ:Number = TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].PosZ - TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].PosZ;

var SegLength:Number = Distance3D(TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].PosX, TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].PosY, TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].PosZ, TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].PosX, TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].PosY, TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].PosZ);

// Calculate difference in velocity
var VelDiffX:Number = TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].VelX - TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].VelX;
var VelDiffY:Number = TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].VelY - TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].VelY;
var VelDiffZ:Number = TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].VelZ - TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].VelZ;

var RestLength:Number = TestCollisionSphereSpringList[index].RestLength;

var PosVelDot:Number = PosDiffX*VelDiffX + PosDiffY*VelDiffY + PosDiffZ*VelDiffZ;

var Force1X:Number = -((0.8*(SegLength - RestLength)) + 0.04*(PosVelDot/SegLength))*(PosDiffX/SegLength);
var Force1Y:Number = -((0.8*(SegLength - RestLength)) + 0.04*(PosVelDot/SegLength))*(PosDiffY/SegLength);
var Force1Z:Number = -((0.8*(SegLength - RestLength)) + 0.04*(PosVelDot/SegLength))*(PosDiffZ/SegLength);

var ForceMagnitude:Number = Distance3D(0, 0, 0, Force1X, Force1Y, Force1Z);

TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].ForceX += Force1X;
TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].ForceY += Force1Y;
TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point1].ForceZ += Force1Z;

var Force2X:Number = -Force1X;
var Force2Y:Number = -Force1Y;
var Force2Z:Number = -Force1Z;

TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].ForceX += Force2X;
TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].ForceY += Force2Y;
TestCollisionSphereVertexList[TestCollisionSphereSpringList[index].Point2].ForceZ += Force2Z;

}// end for

for(index = 0; index < TestCollisionSphereVertexList.length; index++)
{

// acceleration is determined by force divided by mass
TestCollisionSphereVertexList[index].AccelX = TestCollisionSphereVertexList[index].ForceX/TestCollisionSphereVertexList[index].Mass;
TestCollisionSphereVertexList[index].AccelY = TestCollisionSphereVertexList[index].ForceY/TestCollisionSphereVertexList[index].Mass;
TestCollisionSphereVertexList[index].AccelZ = TestCollisionSphereVertexList[index].ForceZ/TestCollisionSphereVertexList[index].Mass;

// reset forces
TestCollisionSphereVertexList[index].ForceX = 0;
TestCollisionSphereVertexList[index].ForceY = 0;
TestCollisionSphereVertexList[index].ForceZ = 0;

// apply resultant acceleration
TestCollisionSphereVertexList[index].VelX += TestCollisionSphereVertexList[index].AccelX;
TestCollisionSphereVertexList[index].VelY += TestCollisionSphereVertexList[index].AccelY;
TestCollisionSphereVertexList[index].VelZ += TestCollisionSphereVertexList[index].AccelZ;

// apply friction
TestCollisionSphereVertexList[index].VelX /= 1.1;
TestCollisionSphereVertexList[index].VelY /= 1.1;
TestCollisionSphereVertexList[index].VelZ /= 1.1;

// scale back velocity to maintain stability
var FPRes:Number = 0.1;

var VelXInt:int = TestCollisionSphereVertexList[index].VelX/FPRes;
var VelYInt:int = TestCollisionSphereVertexList[index].VelY/FPRes;
var VelZInt:int = TestCollisionSphereVertexList[index].VelZ/FPRes;

TestCollisionSphereVertexList[index].VelX = VelXInt*FPRes;
TestCollisionSphereVertexList[index].VelY = VelYInt*FPRes;
TestCollisionSphereVertexList[index].VelZ = VelZInt*FPRes;

}// end for

var Iteration:int = 0;

for(Iteration = 0; Iteration < 3; Iteration++)
{

var Sphere1:int = 0;
var Sphere2:int = 0;

// Handle TEST Collision spheres
for(Sphere1 = 0; Sphere1 < TestCollisionSphereList.length; Sphere1++)
{

TestCollisionSphereList[Sphere1].Collided = false;

for(Sphere2 = 0; Sphere2 < TestCollisionSphereList.length; Sphere2++)
{

if(Sphere1 != Sphere2)
{

var SphereDistance:Number = Distance3D(TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].PosX+TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelX, TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].PosY+TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelY, TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].PosZ+TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelZ,
TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].PosX+TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelX, TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].PosY+TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelY, TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].PosZ+TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelZ);

{

TestCollisionSphereList[Sphere1].Collided = true;

var AuxVelX:Number = TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelX;
var AuxVelY:Number = TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelY;
var AuxVelZ:Number = TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelZ;

var e:Number = 1.0;

// Apparently lower mass stabilizes the simulation :S
var Mass:Number = 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001;

// Remember that this is all a test and some code looks redundant and ugly
// And notice that I'm not considering friction when calculating the resultant
// velocity

TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelX = ((1.0+e)*Mass*TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelX + AuxVelX*(Mass - e*Mass))/(Mass + Mass);
TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelY = ((1.0+e)*Mass*TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelY + AuxVelY*(Mass - e*Mass))/(Mass + Mass);
TestCollisionSphereVertexList[TestCollisionSphereList[Sphere1].AttachedIndex].VelZ = ((1.0+e)*Mass*TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelZ + AuxVelZ*(Mass - e*Mass))/(Mass + Mass);

TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelX = ((1.0+e)*Mass*AuxVelX - TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelX*(Mass - e*Mass))/(Mass + Mass);
TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelY = ((1.0+e)*Mass*AuxVelY - TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelY*(Mass - e*Mass))/(Mass + Mass);
TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelZ = ((1.0+e)*Mass*AuxVelZ - TestCollisionSphereVertexList[TestCollisionSphereList[Sphere2].AttachedIndex].VelZ*(Mass - e*Mass))/(Mass + Mass);

}// end if

}// end if

}// end for

}// end for

}// end for

for(index = 0; index < TestCollisionSphereVertexList.length; index++)
{

TestCollisionSphereVertexList[index].PosX += TestCollisionSphereVertexList[index].VelX;
TestCollisionSphereVertexList[index].PosY += TestCollisionSphereVertexList[index].VelY;
TestCollisionSphereVertexList[index].PosZ += TestCollisionSphereVertexList[index].VelZ;

}// end for



1. 1
2. 2
3. 3
Rutin
15
4. 4
5. 5

• 10
• 9
• 9
• 11
• 11
• ### Forum Statistics

• Total Topics
633684
• Total Posts
3013316
×