7
} CollisionObjectIndices;
11
float4 shapeTransform[4]; // column major 4x4 matrix
12
float4 linearVelocity;
13
float4 angularVelocity;
15
int softBodyIdentifier;
16
int collisionShapeType;
20
// Compressed from the union
30
} CollisionShapeDescription;
32
/* From btBroadphaseProxy.h */
33
__constant int CAPSULE_SHAPE_PROXYTYPE = 10;
35
/* Multiply column-major matrix against vector */
36
float4 matrixVectorMul( float4 matrix[4], float4 vector )
39
float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x);
40
float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y);
41
float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z);
42
float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w);
43
returnVector.x = dot(row0, vector);
44
returnVector.y = dot(row1, vector);
45
returnVector.z = dot(row2, vector);
46
returnVector.w = dot(row3, vector);
51
SolveCollisionsAndUpdateVelocitiesKernel(
53
const float isolverdt,
54
__global int *g_vertexClothIdentifier,
55
__global float4 *g_vertexPreviousPositions,
56
__global float * g_perClothFriction,
57
__global float * g_clothDampingFactor,
58
__global CollisionObjectIndices * g_perClothCollisionObjectIndices,
59
__global CollisionShapeDescription * g_collisionObjectDetails,
60
__global float4 * g_vertexForces,
61
__global float4 *g_vertexVelocities,
62
__global float4 *g_vertexPositions)
64
int nodeID = get_global_id(0);
65
float3 forceOnVertex = (float3)(0.f, 0.f, 0.f);
66
if( get_global_id(0) < numNodes )
68
int clothIdentifier = g_vertexClothIdentifier[nodeID];
70
// Abort if this is not a valid cloth
71
if( clothIdentifier < 0 )
74
float4 position = (float4)(g_vertexPositions[nodeID].xyz, 1.f);
75
float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 1.f);
77
float clothFriction = g_perClothFriction[clothIdentifier];
78
float dampingFactor = g_clothDampingFactor[clothIdentifier];
79
float velocityCoefficient = (1.f - dampingFactor);
80
CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
82
if( collisionObjectIndices.firstObject != collisionObjectIndices.endObject )
84
velocity = (float3)(15, 0, 0);
86
/* We have some possible collisions to deal with */
87
for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision )
89
CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision];
90
float colliderFriction = shapeDescription.friction;
92
if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
94
/* Colliding with a capsule */
96
float capsuleHalfHeight = shapeDescription.halfHeight;
97
float capsuleRadius = shapeDescription.radius;
98
float capsuleMargin = shapeDescription.margin;
99
int capsuleupAxis = shapeDescription.upAxis;
101
/* Four columns of worldTransform matrix */
102
float4 worldTransform[4];
103
worldTransform[0] = shapeDescription.shapeTransform[0];
104
worldTransform[1] = shapeDescription.shapeTransform[1];
105
worldTransform[2] = shapeDescription.shapeTransform[2];
106
worldTransform[3] = shapeDescription.shapeTransform[3];
108
// Correctly define capsule centerline vector
109
float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f);
110
float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f);
111
c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 );
112
c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 );
113
c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 );
118
float4 worldC1 = matrixVectorMul(worldTransform, c1);
119
float4 worldC2 = matrixVectorMul(worldTransform, c2);
120
float3 segment = (worldC2 - worldC1).xyz;
122
/* compute distance of tangent to vertex along line segment in capsule */
123
float distanceAlongSegment = -( dot( (worldC1 - position).xyz, segment ) / dot(segment, segment) );
125
float4 closestPoint = (worldC1 + (float4)(segment * distanceAlongSegment, 0.f));
126
float distanceFromLine = length(position - closestPoint);
127
float distanceFromC1 = length(worldC1 - position);
128
float distanceFromC2 = length(worldC2 - position);
130
/* Final distance from collision, point to push from, direction to push in
134
if( distanceAlongSegment < 0 )
136
dist = distanceFromC1;
137
normalVector = normalize(position - worldC1).xyz;
138
} else if( distanceAlongSegment > 1.f ) {
139
dist = distanceFromC2;
140
normalVector = normalize(position - worldC2).xyz;
142
dist = distanceFromLine;
143
normalVector = normalize(position - closestPoint).xyz;
146
float3 colliderLinearVelocity = shapeDescription.linearVelocity.xyz;
147
float3 colliderAngularVelocity = shapeDescription.angularVelocity.xyz;
148
float3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position.xyz - (float3)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w));
150
float minDistance = capsuleRadius + capsuleMargin;
152
/* In case of no collision, this is the value of velocity */
153
velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt;
156
// Check for a collision
157
if( dist < minDistance )
159
/* Project back to surface along normal */
160
position = position + (float4)((minDistance - dist)*normalVector*0.9f, 0.f);
161
velocity = (position - previousPosition).xyz * velocityCoefficient * isolverdt;
162
float3 relativeVelocity = velocity - velocityOfSurfacePoint;
164
float3 p1 = normalize(cross(normalVector, segment));
165
float3 p2 = normalize(cross(p1, normalVector));
166
/* Full friction is sum of velocities in each direction of plane */
167
float3 frictionVector = p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2);
169
/* Real friction is peak friction corrected by friction coefficients */
170
frictionVector = frictionVector * (colliderFriction*clothFriction);
172
float approachSpeed = dot(relativeVelocity, normalVector);
174
if( approachSpeed <= 0.0f )
175
forceOnVertex -= frictionVector;
181
/* Update velocity */
182
float3 difference = position.xyz - previousPosition.xyz;
183
velocity = difference*velocityCoefficient*isolverdt;
186
g_vertexVelocities[nodeID] = (float4)(velocity, 0.f);
188
/* Update external force */
189
g_vertexForces[nodeID] = (float4)(forceOnVertex, 0.f);
191
g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f);