2
float mydot3(float4 a, float4 b)
4
return a.x*b.x + a.y*b.y + a.z*b.z;
12
} CollisionObjectIndices;
16
float4 shapeTransform[4]; // column major 4x4 matrix
17
float4 linearVelocity;
18
float4 angularVelocity;
20
int softBodyIdentifier;
21
int collisionShapeType;
25
// Compressed from the union
35
} CollisionShapeDescription;
37
// From btBroadphaseProxy.h
38
__constant int CAPSULE_SHAPE_PROXYTYPE = 10;
41
/* Multiply column-major matrix against vector */
42
float4 matrixVectorMul( float4 matrix[4], float4 vector )
45
float4 row0 = (float4)(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x);
46
float4 row1 = (float4)(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y);
47
float4 row2 = (float4)(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z);
48
float4 row3 = (float4)(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w);
49
returnVector.x = dot(row0, vector);
50
returnVector.y = dot(row1, vector);
51
returnVector.z = dot(row2, vector);
52
returnVector.w = dot(row3, vector);
57
SolveCollisionsAndUpdateVelocitiesKernel(
59
const float isolverdt,
60
__global int *g_vertexClothIdentifier,
61
__global float4 *g_vertexPreviousPositions,
62
__global float * g_perClothFriction,
63
__global float * g_clothDampingFactor,
64
__global CollisionObjectIndices * g_perClothCollisionObjectIndices,
65
__global CollisionShapeDescription * g_collisionObjectDetails,
66
__global float4 * g_vertexForces,
67
__global float4 *g_vertexVelocities,
68
__global float4 *g_vertexPositions,
69
__local CollisionShapeDescription *localCollisionShapes)
71
int nodeID = get_global_id(0);
72
float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f);
74
int clothIdentifier = g_vertexClothIdentifier[nodeID];
76
// Abort if this is not a valid cloth
77
if( clothIdentifier < 0 )
81
float4 position = (float4)(g_vertexPositions[nodeID].xyz, 1.f);
82
float4 previousPosition = (float4)(g_vertexPreviousPositions[nodeID].xyz, 1.f);
83
float clothFriction = g_perClothFriction[clothIdentifier];
84
float dampingFactor = g_clothDampingFactor[clothIdentifier];
85
float velocityCoefficient = (1.f - dampingFactor);
88
float4 difference = position - previousPosition;
89
float4 velocity = difference*velocityCoefficient*isolverdt;
90
CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
92
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
95
// We have some possible collisions to deal with
97
// First load all of the collision objects into LDS
98
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
99
if( get_local_id(0) < numObjects )
101
localCollisionShapes[get_local_id(0)] = g_collisionObjectDetails[ collisionObjectIndices.firstObject + get_local_id(0) ];
105
// Safe as the vertices are padded so that not more than one soft body is in a group
106
barrier(CLK_LOCAL_MEM_FENCE);
108
// Annoyingly, even though I know the flow control is not varying, the compiler will not let me skip this
113
// We have some possible collisions to deal with
114
for( int collision = 0; collision < numObjects; ++collision )
116
//CollisionShapeDescription shapeDescription = localCollisionShapes[collision];
117
float colliderFriction = localCollisionShapes[collision].friction;
119
if( localCollisionShapes[collision].collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
121
// Colliding with a capsule
123
float capsuleHalfHeight = localCollisionShapes[collision].halfHeight;
124
float capsuleRadius = localCollisionShapes[collision].radius;
125
float capsuleMargin = localCollisionShapes[collision].margin;
126
int capsuleupAxis = localCollisionShapes[collision].upAxis;
128
float4 worldTransform[4];
129
worldTransform[0] = localCollisionShapes[collision].shapeTransform[0];
130
worldTransform[1] = localCollisionShapes[collision].shapeTransform[1];
131
worldTransform[2] = localCollisionShapes[collision].shapeTransform[2];
132
worldTransform[3] = localCollisionShapes[collision].shapeTransform[3];
134
//float4 c1 = (float4)(0.f, -capsuleHalfHeight, 0.f, 1.f);
135
//float4 c2 = (float4)(0.f, +capsuleHalfHeight, 0.f, 1.f);
136
// Correctly define capsule centerline vector
137
float4 c1 = (float4)(0.f, 0.f, 0.f, 1.f);
138
float4 c2 = (float4)(0.f, 0.f, 0.f, 1.f);
139
c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 );
140
c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 );
141
c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 );
146
float4 worldC1 = matrixVectorMul(worldTransform, c1);
147
float4 worldC2 = matrixVectorMul(worldTransform, c2);
148
float4 segment = (worldC2 - worldC1);
151
// compute distance of tangent to vertex along line segment in capsule
152
float distanceAlongSegment = -( mydot3( (worldC1 - position), segment ) / mydot3(segment, segment) );
154
float4 closestPoint = (worldC1 + (float4)(segment * distanceAlongSegment));
155
float distanceFromLine = length(position - closestPoint);
156
float distanceFromC1 = length(worldC1 - position);
157
float distanceFromC2 = length(worldC2 - position);
159
// Final distance from collision, point to push from, direction to push in
163
if( distanceAlongSegment < 0 )
165
dist = distanceFromC1;
166
normalVector = normalize(position - worldC1);
167
} else if( distanceAlongSegment > 1.f ) {
168
dist = distanceFromC2;
169
normalVector = normalize(position - worldC2);
171
dist = distanceFromLine;
172
normalVector = normalize(position - closestPoint);
175
float4 colliderLinearVelocity = localCollisionShapes[collision].linearVelocity;
176
float4 colliderAngularVelocity = localCollisionShapes[collision].angularVelocity;
177
float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - (float4)(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f));
179
float minDistance = capsuleRadius + capsuleMargin;
181
// In case of no collision, this is the value of velocity
182
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
185
// Check for a collision
186
if( dist < minDistance )
188
// Project back to surface along normal
189
position = position + (float4)((minDistance - dist)*normalVector*0.9f);
190
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
191
float4 relativeVelocity = velocity - velocityOfSurfacePoint;
193
float4 p1 = (float4)(normalize(cross(normalVector, segment)).xyz, 0.f);
194
float4 p2 = (float4)(normalize(cross(p1, normalVector)).xyz, 0.f);
195
// Full friction is sum of velocities in each direction of plane
196
float4 frictionVector = p1*mydot3(relativeVelocity, p1) + p2*mydot3(relativeVelocity, p2);
198
// Real friction is peak friction corrected by friction coefficients
199
frictionVector = frictionVector * (colliderFriction*clothFriction);
201
float approachSpeed = dot(relativeVelocity, normalVector);
203
if( approachSpeed <= 0.0f )
204
forceOnVertex -= frictionVector;
211
g_vertexVelocities[nodeID] = (float4)(velocity.xyz, 0.f);
213
// Update external force
214
g_vertexForces[nodeID] = (float4)(forceOnVertex.xyz, 0.f);
216
g_vertexPositions[nodeID] = (float4)(position.xyz, 0.f);