MiniCLTaskWrap.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2007 Erwin Coumans  http://bulletphysics.com
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #include <MiniCL/cl_MiniCL_Defs.h>
00017 
00018 #define MSTRINGIFY(A) A
00019 #include "../OpenCLC10/ApplyForces.cl"
00020 #include "../OpenCLC10/Integrate.cl"
00021 #include "../OpenCLC10/PrepareLinks.cl"
00022 #include "../OpenCLC10/SolvePositions.cl"
00023 #include "../OpenCLC10/UpdateNodes.cl"
00024 #include "../OpenCLC10/UpdateNormals.cl"
00025 #include "../OpenCLC10/UpdatePositions.cl"
00026 #include "../OpenCLC10/UpdatePositionsFromVelocities.cl"
00027 #include "../OpenCLC10/VSolveLinks.cl"
00028 #include "../OpenCLC10/UpdateFixedVertexPositions.cl"
00029 //#include "../OpenCLC10/SolveCollisionsAndUpdateVelocities.cl"
00030 
00031 
00032 MINICL_REGISTER(PrepareLinksKernel)
00033 MINICL_REGISTER(VSolveLinksKernel)
00034 MINICL_REGISTER(UpdatePositionsFromVelocitiesKernel)
00035 MINICL_REGISTER(SolvePositionsFromLinksKernel)
00036 MINICL_REGISTER(updateVelocitiesFromPositionsWithVelocitiesKernel)
00037 MINICL_REGISTER(updateVelocitiesFromPositionsWithoutVelocitiesKernel)
00038 MINICL_REGISTER(IntegrateKernel)
00039 MINICL_REGISTER(ApplyForcesKernel)
00040 MINICL_REGISTER(ResetNormalsAndAreasKernel)
00041 MINICL_REGISTER(NormalizeNormalsAndAreasKernel)
00042 MINICL_REGISTER(UpdateSoftBodiesKernel)
00043 MINICL_REGISTER(UpdateFixedVertexPositions)
00044 
00045 float mydot3a(float4 a, float4 b)
00046 {
00047    return a.x*b.x + a.y*b.y + a.z*b.z;
00048 }
00049 
00050 
00051 typedef struct 
00052 {
00053         int firstObject;
00054         int endObject;
00055 } CollisionObjectIndices;
00056 
00057 typedef struct 
00058 {
00059         float4 shapeTransform[4]; // column major 4x4 matrix
00060         float4 linearVelocity;
00061         float4 angularVelocity;
00062 
00063         int softBodyIdentifier;
00064         int collisionShapeType;
00065         
00066 
00067         // Shape information
00068         // Compressed from the union
00069         float radius;
00070         float halfHeight;
00071         int upAxis;
00072                 
00073         float margin;
00074         float friction;
00075 
00076         int padding0;
00077         
00078 } CollisionShapeDescription;
00079 
00080 // From btBroadphaseProxy.h
00081 __constant int CAPSULE_SHAPE_PROXYTYPE = 10;
00082 
00083 // Multiply column-major matrix against vector
00084 float4 matrixVectorMul( float4 matrix[4], float4 vector )
00085 {
00086         float4 returnVector;
00087         float4 row0 = float4(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x);
00088         float4 row1 = float4(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y);
00089         float4 row2 = float4(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z);
00090         float4 row3 = float4(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w);
00091         returnVector.x = dot(row0, vector);
00092         returnVector.y = dot(row1, vector);
00093         returnVector.z = dot(row2, vector);
00094         returnVector.w = dot(row3, vector);
00095         return returnVector;
00096 }
00097 
00098 __kernel void 
00099 SolveCollisionsAndUpdateVelocitiesKernel( 
00100         const int numNodes,
00101         const float isolverdt,
00102         __global int *g_vertexClothIdentifier,
00103         __global float4 *g_vertexPreviousPositions,
00104         __global float * g_perClothFriction,
00105         __global float * g_clothDampingFactor,
00106         __global CollisionObjectIndices * g_perClothCollisionObjectIndices,
00107         __global CollisionShapeDescription * g_collisionObjectDetails,
00108         __global float4 * g_vertexForces,
00109         __global float4 *g_vertexVelocities,
00110         __global float4 *g_vertexPositions GUID_ARG)
00111 {
00112         int nodeID = get_global_id(0);
00113         float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f);
00114         
00115         if( get_global_id(0) < numNodes )
00116         {       
00117                 int clothIdentifier = g_vertexClothIdentifier[nodeID];
00118                 
00119                 // Abort if this is not a valid cloth
00120                 if( clothIdentifier < 0 )
00121                         return;
00122 
00123 
00124                 float4 position (g_vertexPositions[nodeID].xyz, 1.f);
00125                 float4 previousPosition (g_vertexPreviousPositions[nodeID].xyz, 1.f);
00126                         
00127                 float clothFriction = g_perClothFriction[clothIdentifier];
00128                 float dampingFactor = g_clothDampingFactor[clothIdentifier];
00129                 float velocityCoefficient = (1.f - dampingFactor);              
00130                 float4 difference = position - previousPosition;
00131                 float4 velocity = difference*velocityCoefficient*isolverdt;
00132                 
00133                 CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
00134         
00135                 int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
00136                 
00137                 if( numObjects > 0 )
00138                 {
00139                         // We have some possible collisions to deal with
00140                         for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision )
00141                         {
00142                                 CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision];
00143                                 float colliderFriction = shapeDescription.friction;
00144 
00145                                 if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
00146                                 {
00147                                         // Colliding with a capsule
00148 
00149                                         float capsuleHalfHeight = shapeDescription.halfHeight;
00150                                         float capsuleRadius = shapeDescription.radius;
00151                                         float capsuleMargin = shapeDescription.margin;
00152                                         int capsuleupAxis = shapeDescription.upAxis;
00153 
00154                                         // Four columns of worldTransform matrix
00155                                         float4 worldTransform[4];
00156                                         worldTransform[0] = shapeDescription.shapeTransform[0];
00157                                         worldTransform[1] = shapeDescription.shapeTransform[1];
00158                                         worldTransform[2] = shapeDescription.shapeTransform[2];
00159                                         worldTransform[3] = shapeDescription.shapeTransform[3];
00160 
00161                                         // Correctly define capsule centerline vector 
00162                                         float4 c1 (0.f, 0.f, 0.f, 1.f); 
00163                                         float4 c2 (0.f, 0.f, 0.f, 1.f);
00164                                         c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 );
00165                                         c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 );
00166                                         c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 );
00167                                         c2.x = -c1.x;
00168                                         c2.y = -c1.y;
00169                                         c2.z = -c1.z;
00170 
00171 
00172                                         float4 worldC1 = matrixVectorMul(worldTransform, c1);
00173                                         float4 worldC2 = matrixVectorMul(worldTransform, c2);
00174                                         float4 segment = (worldC2 - worldC1);
00175 
00176                                         // compute distance of tangent to vertex along line segment in capsule
00177                                         float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) );
00178 
00179                                         float4 closestPoint = (worldC1 + (segment * distanceAlongSegment));
00180                                         float distanceFromLine = length(position - closestPoint);
00181                                         float distanceFromC1 = length(worldC1 - position);
00182                                         float distanceFromC2 = length(worldC2 - position);
00183                                         
00184                                         // Final distance from collision, point to push from, direction to push in
00185                                         // for impulse force
00186                                         float dist;
00187                                         float4 normalVector;
00188                                         if( distanceAlongSegment < 0 )
00189                                         {
00190                                                 dist = distanceFromC1;
00191                                                 normalVector = float4(normalize(position - worldC1).xyz, 0.f);
00192                                         } else if( distanceAlongSegment > 1.f ) {
00193                                                 dist = distanceFromC2;
00194                                                 normalVector = float4(normalize(position - worldC2).xyz, 0.f);  
00195                                         } else {
00196                                                 dist = distanceFromLine;
00197                                                 normalVector = float4(normalize(position - closestPoint).xyz, 0.f);
00198                                         }
00199                                                 
00200                                         float4 colliderLinearVelocity = shapeDescription.linearVelocity;
00201                                         float4 colliderAngularVelocity = shapeDescription.angularVelocity;
00202                                         float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - float4(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f));
00203 
00204                                         float minDistance = capsuleRadius + capsuleMargin;
00205                                         
00206                                         // In case of no collision, this is the value of velocity
00207                                         velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
00208                                         
00209                                         
00210                                         // Check for a collision
00211                                         if( dist < minDistance )
00212                                         {
00213                                                 // Project back to surface along normal
00214                                                 position = position + float4(normalVector*(minDistance - dist)*0.9f);
00215                                                 velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
00216                                                 float4 relativeVelocity = velocity - velocityOfSurfacePoint;
00217 
00218                                                 float4 p1 = normalize(cross(normalVector, segment));
00219                                                 float4 p2 = normalize(cross(p1, normalVector));
00220                                                 // Full friction is sum of velocities in each direction of plane
00221                                                 float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2);
00222 
00223                                                 // Real friction is peak friction corrected by friction coefficients
00224                                                 frictionVector = frictionVector * (colliderFriction*clothFriction);
00225 
00226                                                 float approachSpeed = dot(relativeVelocity, normalVector);
00227 
00228                                                 if( approachSpeed <= 0.0f )
00229                                                         forceOnVertex -= frictionVector;
00230                                         }
00231                                 }
00232                         }
00233                 }
00234 
00235                 g_vertexVelocities[nodeID] = float4(velocity.xyz, 0.f); 
00236 
00237                 // Update external force
00238                 g_vertexForces[nodeID] = float4(forceOnVertex.xyz, 0.f);
00239 
00240                 g_vertexPositions[nodeID] = float4(position.xyz, 0.f);
00241         }
00242 }
00243 
00244 
00245 MINICL_REGISTER(SolveCollisionsAndUpdateVelocitiesKernel);
00246 
00247 
00248 
00249