Code-style consistency improvement:
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files. make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type. This commit contains no other changes aside from adding and applying clang-format-all.sh
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
#include "vec3n.h"
|
||||
//#include "console.h"
|
||||
|
||||
|
||||
extern int numX;
|
||||
|
||||
|
||||
//
|
||||
// Cloth - Backward Integrated Spring Network
|
||||
//
|
||||
@@ -42,157 +40,144 @@ extern int numX;
|
||||
//#include "object.h"
|
||||
//#include "xmlparse.h"
|
||||
|
||||
static const float3x3 I(1, 0, 0, 0, 1, 0, 0, 0, 1);
|
||||
|
||||
|
||||
|
||||
static const float3x3 I(1,0,0,0,1,0,0,0,1);
|
||||
|
||||
inline float3x3 dfdx_spring(const float3 &dir,float length,float rest,float k)
|
||||
inline float3x3 dfdx_spring(const float3 &dir, float length, float rest, float k)
|
||||
{
|
||||
// dir is unit length direction, rest is spring's restlength, k is spring constant.
|
||||
return ( (I-outerprod(dir,dir))*Min(1.0f,rest/length) - I) * -k;
|
||||
// dir is unit length direction, rest is spring's restlength, k is spring constant.
|
||||
return ((I - outerprod(dir, dir)) * Min(1.0f, rest / length) - I) * -k;
|
||||
}
|
||||
inline float3x3 dfdx_damp(const float3 &dir,float length,const float3& vel,float rest,float damping)
|
||||
inline float3x3 dfdx_damp(const float3 &dir, float length, const float3 &vel, float rest, float damping)
|
||||
{
|
||||
// inner spring damping vel is the relative velocity of the endpoints.
|
||||
return (I-outerprod(dir,dir)) * (-damping * -(dot(dir,vel)/Max(length,rest)));
|
||||
// inner spring damping vel is the relative velocity of the endpoints.
|
||||
return (I - outerprod(dir, dir)) * (-damping * -(dot(dir, vel) / Max(length, rest)));
|
||||
}
|
||||
inline float3x3 dfdv_damp(const float3 &dir,float damping)
|
||||
inline float3x3 dfdv_damp(const float3 &dir, float damping)
|
||||
{
|
||||
// derivative of force wrt velocity.
|
||||
return outerprod(dir,dir) * damping;
|
||||
// derivative of force wrt velocity.
|
||||
return outerprod(dir, dir) * damping;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "SpringNetwork.h"
|
||||
|
||||
|
||||
SpringNetwork::SpringNetwork(int _n):X(_n),V(_n),F(_n),dV(_n),A(_n),dFdX(_n),dFdV(_n)
|
||||
SpringNetwork::SpringNetwork(int _n) : X(_n), V(_n), F(_n), dV(_n), A(_n), dFdX(_n), dFdV(_n)
|
||||
{
|
||||
assert(SPRING_STRUCT==0);
|
||||
assert(&spring_shear == &spring_struct +SPRING_SHEAR);
|
||||
assert(&spring_bend == &spring_struct +SPRING_BEND);
|
||||
assert(&spring_struct== &spring_k[SPRING_STRUCT]);
|
||||
assert(&spring_shear == &spring_k[SPRING_SHEAR ]);
|
||||
assert(&spring_bend == &spring_k[SPRING_BEND ]);
|
||||
// spring_struct=1000000.0f;
|
||||
// spring_shear=1000000.0f;
|
||||
|
||||
spring_struct=1000.0f;
|
||||
spring_shear=100.0f;
|
||||
|
||||
spring_bend=25.0f;
|
||||
spring_damp=5.0f;
|
||||
spring_air=1.0f;
|
||||
spring_air=1.0f;
|
||||
cloth_step = 0.25f; // delta time for cloth
|
||||
cloth_gravity=float3(0,-10,0);
|
||||
cloth_sleepthreshold = 0.001f;
|
||||
cloth_sleepcount = 100;
|
||||
awake = cloth_sleepcount;
|
||||
|
||||
//fix/pin two points in worldspace
|
||||
float3Nx3N::Block zero;
|
||||
zero.m = float3x3(0,0,0,0,0,0,0,0,0);
|
||||
zero.c = 0;
|
||||
zero.r = 0;
|
||||
S.blocks.Add(zero);
|
||||
zero.r = numX-1;
|
||||
S.blocks.Add(zero);
|
||||
assert(SPRING_STRUCT == 0);
|
||||
assert(&spring_shear == &spring_struct + SPRING_SHEAR);
|
||||
assert(&spring_bend == &spring_struct + SPRING_BEND);
|
||||
assert(&spring_struct == &spring_k[SPRING_STRUCT]);
|
||||
assert(&spring_shear == &spring_k[SPRING_SHEAR]);
|
||||
assert(&spring_bend == &spring_k[SPRING_BEND]);
|
||||
// spring_struct=1000000.0f;
|
||||
// spring_shear=1000000.0f;
|
||||
|
||||
spring_struct = 1000.0f;
|
||||
spring_shear = 100.0f;
|
||||
|
||||
spring_bend = 25.0f;
|
||||
spring_damp = 5.0f;
|
||||
spring_air = 1.0f;
|
||||
spring_air = 1.0f;
|
||||
cloth_step = 0.25f; // delta time for cloth
|
||||
cloth_gravity = float3(0, -10, 0);
|
||||
cloth_sleepthreshold = 0.001f;
|
||||
cloth_sleepcount = 100;
|
||||
awake = cloth_sleepcount;
|
||||
|
||||
//fix/pin two points in worldspace
|
||||
float3Nx3N::Block zero;
|
||||
zero.m = float3x3(0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
zero.c = 0;
|
||||
zero.r = 0;
|
||||
S.blocks.Add(zero);
|
||||
zero.r = numX - 1;
|
||||
S.blocks.Add(zero);
|
||||
}
|
||||
|
||||
|
||||
SpringNetwork::Spring &SpringNetwork::AddBlocks(Spring &s)
|
||||
{
|
||||
// Called during initial creation of springs in our spring network.
|
||||
// Sets up the sparse matrices corresponding to connections.
|
||||
// Note the indices (s.iab,s.iba) are also stored with spring to avoid looking them up each time a spring is applied
|
||||
// All 3 matrices A,dFdX, and dFdV are contstructed identically so the block array layout will be the same for each.
|
||||
s.iab = A.blocks.count; // added 'ab' blocks will have this index.
|
||||
A.blocks.Add(float3Nx3N::Block(s.a,s.b));
|
||||
dFdX.blocks.Add(float3Nx3N::Block(s.a,s.b));
|
||||
dFdV.blocks.Add(float3Nx3N::Block(s.a,s.b));
|
||||
s.iba = A.blocks.count; // added 'ba' blocks will have this index.
|
||||
A.blocks.Add(float3Nx3N::Block(s.b,s.a));
|
||||
dFdX.blocks.Add(float3Nx3N::Block(s.b,s.a));
|
||||
dFdV.blocks.Add(float3Nx3N::Block(s.b,s.a));
|
||||
return s;
|
||||
// Called during initial creation of springs in our spring network.
|
||||
// Sets up the sparse matrices corresponding to connections.
|
||||
// Note the indices (s.iab,s.iba) are also stored with spring to avoid looking them up each time a spring is applied
|
||||
// All 3 matrices A,dFdX, and dFdV are contstructed identically so the block array layout will be the same for each.
|
||||
s.iab = A.blocks.count; // added 'ab' blocks will have this index.
|
||||
A.blocks.Add(float3Nx3N::Block(s.a, s.b));
|
||||
dFdX.blocks.Add(float3Nx3N::Block(s.a, s.b));
|
||||
dFdV.blocks.Add(float3Nx3N::Block(s.a, s.b));
|
||||
s.iba = A.blocks.count; // added 'ba' blocks will have this index.
|
||||
A.blocks.Add(float3Nx3N::Block(s.b, s.a));
|
||||
dFdX.blocks.Add(float3Nx3N::Block(s.b, s.a));
|
||||
dFdV.blocks.Add(float3Nx3N::Block(s.b, s.a));
|
||||
return s;
|
||||
}
|
||||
|
||||
void SpringNetwork::PreSolveSpring(const SpringNetwork::Spring &s)
|
||||
{
|
||||
// Adds this spring's contribution into force vector F and force derivitves dFdX and dFdV
|
||||
// One optimization would be premultiply dfdx by dt*dt and F and dFdV by dt right here in this function.
|
||||
// However, for educational purposes we wont do that now and intead just follow the paper directly.
|
||||
//assert(dFdX.blocks[s.a].c==s.a); // delete this assert, no bugs here
|
||||
//assert(dFdX.blocks[s.a].r==s.a);
|
||||
float3 extent = X[s.b] - X[s.a];
|
||||
float length = magnitude(extent);
|
||||
float3 dir = (length==0)?float3(0,0,0): extent * 1.0f/length;
|
||||
float3 vel = V[s.b] - V[s.a];
|
||||
float k = spring_k[s.type];
|
||||
float3 f = dir * ((k * (length-s.restlen) ) + spring_damp * dot(vel,dir)); // spring force + damping force
|
||||
F[s.a] += f;
|
||||
F[s.b] -= f;
|
||||
float3x3 dfdx = dfdx_spring(dir,length,s.restlen,k) + dfdx_damp(dir,length,vel,s.restlen,spring_damp);
|
||||
dFdX.blocks[s.a].m -= dfdx; // diagonal chunk dFdX[a,a]
|
||||
dFdX.blocks[s.b].m -= dfdx; // diagonal chunk dFdX[b,b]
|
||||
dFdX.blocks[s.iab].m += dfdx; // off-diag chunk dFdX[a,b]
|
||||
dFdX.blocks[s.iba].m += dfdx; // off-diag chunk dFdX[b,a]
|
||||
float3x3 dfdv = dfdv_damp(dir,spring_damp);
|
||||
dFdV.blocks[s.a].m -= dfdv; // diagonal chunk dFdV[a,a]
|
||||
dFdV.blocks[s.b].m -= dfdv; // diagonal chunk dFdV[b,b]
|
||||
dFdV.blocks[s.iab].m += dfdv; // off-diag chunk dFdV[a,b]
|
||||
dFdV.blocks[s.iba].m += dfdv; // off-diag chunk dFdV[b,a]
|
||||
// Adds this spring's contribution into force vector F and force derivitves dFdX and dFdV
|
||||
// One optimization would be premultiply dfdx by dt*dt and F and dFdV by dt right here in this function.
|
||||
// However, for educational purposes we wont do that now and intead just follow the paper directly.
|
||||
//assert(dFdX.blocks[s.a].c==s.a); // delete this assert, no bugs here
|
||||
//assert(dFdX.blocks[s.a].r==s.a);
|
||||
float3 extent = X[s.b] - X[s.a];
|
||||
float length = magnitude(extent);
|
||||
float3 dir = (length == 0) ? float3(0, 0, 0) : extent * 1.0f / length;
|
||||
float3 vel = V[s.b] - V[s.a];
|
||||
float k = spring_k[s.type];
|
||||
float3 f = dir * ((k * (length - s.restlen)) + spring_damp * dot(vel, dir)); // spring force + damping force
|
||||
F[s.a] += f;
|
||||
F[s.b] -= f;
|
||||
float3x3 dfdx = dfdx_spring(dir, length, s.restlen, k) + dfdx_damp(dir, length, vel, s.restlen, spring_damp);
|
||||
dFdX.blocks[s.a].m -= dfdx; // diagonal chunk dFdX[a,a]
|
||||
dFdX.blocks[s.b].m -= dfdx; // diagonal chunk dFdX[b,b]
|
||||
dFdX.blocks[s.iab].m += dfdx; // off-diag chunk dFdX[a,b]
|
||||
dFdX.blocks[s.iba].m += dfdx; // off-diag chunk dFdX[b,a]
|
||||
float3x3 dfdv = dfdv_damp(dir, spring_damp);
|
||||
dFdV.blocks[s.a].m -= dfdv; // diagonal chunk dFdV[a,a]
|
||||
dFdV.blocks[s.b].m -= dfdv; // diagonal chunk dFdV[b,b]
|
||||
dFdV.blocks[s.iab].m += dfdv; // off-diag chunk dFdV[a,b]
|
||||
dFdV.blocks[s.iba].m += dfdv; // off-diag chunk dFdV[b,a]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SpringNetwork::CalcForces()
|
||||
{
|
||||
// Collect forces and derivatives: F,dFdX,dFdV
|
||||
dFdX.Zero();
|
||||
dFdV.InitDiagonal(-spring_air);
|
||||
F.Init(cloth_gravity);
|
||||
// Collect forces and derivatives: F,dFdX,dFdV
|
||||
dFdX.Zero();
|
||||
dFdV.InitDiagonal(-spring_air);
|
||||
F.Init(cloth_gravity);
|
||||
|
||||
F.element[0]=float3(0,0,0);
|
||||
F.element[numX-1]=float3(0,0,0);
|
||||
|
||||
F -= V * spring_air;
|
||||
for(int i=0;i<springs.count;i++)
|
||||
{
|
||||
PreSolveSpring(springs[i]); // will add to F,dFdX,dFdV
|
||||
}
|
||||
F.element[0] = float3(0, 0, 0);
|
||||
F.element[numX - 1] = float3(0, 0, 0);
|
||||
|
||||
F -= V * spring_air;
|
||||
for (int i = 0; i < springs.count; i++)
|
||||
{
|
||||
PreSolveSpring(springs[i]); // will add to F,dFdX,dFdV
|
||||
}
|
||||
}
|
||||
|
||||
void SpringNetwork::Simulate(float dt)
|
||||
{
|
||||
// Get ready for conjugate gradient iterative solver step.
|
||||
// Initialize operands.
|
||||
if(!awake) return;
|
||||
CalcForces();
|
||||
int n=X.count; // all our big vectors are of this size
|
||||
float3N dFdXmV(n); // temp to store result of matrix multiply
|
||||
float3N B(n);
|
||||
dV.Zero();
|
||||
A.Identity(); // build up the big matrix we feed to solver
|
||||
A -= dFdV * dt + dFdX * (dt*dt) ;
|
||||
|
||||
dFdXmV = dFdX * V;
|
||||
B = F * dt + dFdXmV * (dt*dt);
|
||||
|
||||
ConjGradientFiltered(dV,A,B,S);
|
||||
V = V + dV;
|
||||
// V.element[0] = float3(0,0,0);
|
||||
// V.element[numX-1] = float3(0,0,0);
|
||||
// Get ready for conjugate gradient iterative solver step.
|
||||
// Initialize operands.
|
||||
if (!awake) return;
|
||||
CalcForces();
|
||||
int n = X.count; // all our big vectors are of this size
|
||||
float3N dFdXmV(n); // temp to store result of matrix multiply
|
||||
float3N B(n);
|
||||
dV.Zero();
|
||||
A.Identity(); // build up the big matrix we feed to solver
|
||||
A -= dFdV * dt + dFdX * (dt * dt);
|
||||
|
||||
X = X + V*dt;
|
||||
dFdXmV = dFdX * V;
|
||||
B = F * dt + dFdXmV * (dt * dt);
|
||||
|
||||
UpdateLimits();
|
||||
awake = (dot(V,V)<cloth_sleepthreshold)?awake-1:awake=cloth_sleepcount;
|
||||
ConjGradientFiltered(dV, A, B, S);
|
||||
V = V + dV;
|
||||
// V.element[0] = float3(0,0,0);
|
||||
// V.element[numX-1] = float3(0,0,0);
|
||||
|
||||
X = X + V * dt;
|
||||
|
||||
UpdateLimits();
|
||||
awake = (dot(V, V) < cloth_sleepthreshold) ? awake - 1 : awake = cloth_sleepcount;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user