btSoftBodySolver_OpenCL.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
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 
00017 #include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
00018 #include "vectormath/vmInclude.h"
00019 #include <stdio.h> //@todo: remove the debugging printf at some stage
00020 #include "btSoftBodySolver_OpenCL.h"
00021 #include "BulletSoftBody/btSoftBodySolverVertexBuffer.h"
00022 #include "BulletSoftBody/btSoftBody.h"
00023 #include "BulletSoftBody/btSoftBodyInternals.h"
00024 #include "BulletCollision/CollisionShapes/btCapsuleShape.h"
00025 #include "BulletCollision/CollisionShapes/btSphereShape.h"
00026 #include "LinearMath/btQuickprof.h"
00027 #include <limits.h>
00028 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
00029 
00030 #define BT_SUPPRESS_OPENCL_ASSERTS
00031 
00032 #ifdef USE_MINICL
00033         #include "MiniCL/cl.h"
00034 #else //USE_MINICL
00035         #ifdef __APPLE__
00036                 #include <OpenCL/OpenCL.h>
00037         #else
00038                 #include <CL/cl.h>
00039         #endif //__APPLE__
00040 #endif//USE_MINICL
00041 
00042 #define BT_DEFAULT_WORKGROUPSIZE 64
00043 
00044 
00045 #define RELEASE_CL_KERNEL(kernelName) {if( kernelName ){ clReleaseKernel( kernelName ); kernelName = 0; }}
00046 
00047 
00048 //CL_VERSION_1_1 seems broken on NVidia SDK so just disable it
00049 
00051 #define MSTRINGIFY(A) #A
00052 static const char* PrepareLinksCLString = 
00053 #include "OpenCLC10/PrepareLinks.cl"
00054 static const char* UpdatePositionsFromVelocitiesCLString = 
00055 #include "OpenCLC10/UpdatePositionsFromVelocities.cl"
00056 static const char* SolvePositionsCLString = 
00057 #include "OpenCLC10/SolvePositions.cl"
00058 static const char* UpdateNodesCLString = 
00059 #include "OpenCLC10/UpdateNodes.cl"
00060 static const char* UpdatePositionsCLString = 
00061 #include "OpenCLC10/UpdatePositions.cl"
00062 static const char* UpdateConstantsCLString = 
00063 #include "OpenCLC10/UpdateConstants.cl"
00064 static const char* IntegrateCLString = 
00065 #include "OpenCLC10/Integrate.cl"
00066 static const char* ApplyForcesCLString = 
00067 #include "OpenCLC10/ApplyForces.cl"
00068 static const char* UpdateFixedVertexPositionsCLString = 
00069 #include "OpenCLC10/UpdateFixedVertexPositions.cl"
00070 static const char* UpdateNormalsCLString = 
00071 #include "OpenCLC10/UpdateNormals.cl"
00072 static const char* VSolveLinksCLString = 
00073 #include "OpenCLC10/VSolveLinks.cl"
00074 static const char* SolveCollisionsAndUpdateVelocitiesCLString =
00075 #include "OpenCLC10/SolveCollisionsAndUpdateVelocities.cl"
00076 
00077 
00078 btSoftBodyVertexDataOpenCL::btSoftBodyVertexDataOpenCL( cl_command_queue queue, cl_context ctx) :
00079     m_queue(queue),
00080         m_clClothIdentifier( queue, ctx, &m_clothIdentifier, false ),
00081         m_clVertexPosition( queue, ctx, &m_vertexPosition, false ),
00082         m_clVertexPreviousPosition( queue, ctx, &m_vertexPreviousPosition, false ),
00083         m_clVertexVelocity( queue, ctx, &m_vertexVelocity, false ),
00084         m_clVertexForceAccumulator( queue, ctx, &m_vertexForceAccumulator, false ),
00085         m_clVertexNormal( queue, ctx, &m_vertexNormal, false ),
00086         m_clVertexInverseMass( queue, ctx, &m_vertexInverseMass, false ),
00087         m_clVertexArea( queue, ctx, &m_vertexArea, false ),
00088         m_clVertexTriangleCount( queue, ctx, &m_vertexTriangleCount, false )
00089 {
00090 }
00091 
00092 btSoftBodyVertexDataOpenCL::~btSoftBodyVertexDataOpenCL()
00093 {
00094 
00095 }
00096 
00097 bool btSoftBodyVertexDataOpenCL::onAccelerator()
00098 {
00099         return m_onGPU;
00100 }
00101 
00102 bool btSoftBodyVertexDataOpenCL::moveToAccelerator()
00103 {
00104         bool success = true;
00105         success = success && m_clClothIdentifier.moveToGPU();
00106         success = success && m_clVertexPosition.moveToGPU();
00107         success = success && m_clVertexPreviousPosition.moveToGPU();
00108         success = success && m_clVertexVelocity.moveToGPU();
00109         success = success && m_clVertexForceAccumulator.moveToGPU();
00110         success = success && m_clVertexNormal.moveToGPU();
00111         success = success && m_clVertexInverseMass.moveToGPU();
00112         success = success && m_clVertexArea.moveToGPU();
00113         success = success && m_clVertexTriangleCount.moveToGPU();
00114 
00115         if( success )
00116                 m_onGPU = true;
00117 
00118         return success;
00119 }
00120 
00121 bool btSoftBodyVertexDataOpenCL::moveFromAccelerator(bool bCopy, bool bCopyMinimum)
00122 {
00123         bool success = true;
00124 
00125         if (!bCopy)
00126         {
00127                 success = success && m_clClothIdentifier.moveFromGPU();
00128                 success = success && m_clVertexPosition.moveFromGPU();
00129                 success = success && m_clVertexPreviousPosition.moveFromGPU();
00130                 success = success && m_clVertexVelocity.moveFromGPU();
00131                 success = success && m_clVertexForceAccumulator.moveFromGPU();
00132                 success = success && m_clVertexNormal.moveFromGPU();
00133                 success = success && m_clVertexInverseMass.moveFromGPU();
00134                 success = success && m_clVertexArea.moveFromGPU();
00135                 success = success && m_clVertexTriangleCount.moveFromGPU();
00136         }
00137         else
00138         {
00139                 if (bCopyMinimum)
00140                 {
00141                         success = success && m_clVertexPosition.copyFromGPU();
00142                         success = success && m_clVertexNormal.copyFromGPU();
00143                 }
00144                 else
00145                 {
00146                         success = success && m_clClothIdentifier.copyFromGPU();
00147                         success = success && m_clVertexPosition.copyFromGPU();
00148                         success = success && m_clVertexPreviousPosition.copyFromGPU();
00149                         success = success && m_clVertexVelocity.copyFromGPU();
00150                         success = success && m_clVertexForceAccumulator.copyFromGPU();
00151                         success = success && m_clVertexNormal.copyFromGPU();
00152                         success = success && m_clVertexInverseMass.copyFromGPU();
00153                         success = success && m_clVertexArea.copyFromGPU();
00154                         success = success && m_clVertexTriangleCount.copyFromGPU();
00155                 }
00156         }
00157 
00158         if( success )
00159                 m_onGPU = true;
00160 
00161         return success;
00162 }
00163 
00164 btSoftBodyLinkDataOpenCL::btSoftBodyLinkDataOpenCL(cl_command_queue queue,  cl_context ctx) 
00165 :m_cqCommandQue(queue),
00166         m_clLinks( queue, ctx, &m_links, false ),
00167         m_clLinkStrength( queue, ctx, &m_linkStrength, false ),
00168         m_clLinksMassLSC( queue, ctx, &m_linksMassLSC, false ),
00169         m_clLinksRestLengthSquared( queue, ctx, &m_linksRestLengthSquared, false ),
00170         m_clLinksCLength( queue, ctx, &m_linksCLength, false ),
00171         m_clLinksLengthRatio( queue, ctx, &m_linksLengthRatio, false ),
00172         m_clLinksRestLength( queue, ctx, &m_linksRestLength, false ),
00173         m_clLinksMaterialLinearStiffnessCoefficient( queue, ctx, &m_linksMaterialLinearStiffnessCoefficient, false )
00174 {
00175 }
00176 
00177 btSoftBodyLinkDataOpenCL::~btSoftBodyLinkDataOpenCL()
00178 {
00179 }
00180 
00181 static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec )
00182 {
00183         Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() );
00184         return outVec;
00185 }
00186 
00188 void btSoftBodyLinkDataOpenCL::createLinks( int numLinks )
00189 {
00190         int previousSize = m_links.size();
00191         int newSize = previousSize + numLinks;
00192 
00193         btSoftBodyLinkData::createLinks( numLinks );
00194 
00195         // Resize the link addresses array as well
00196         m_linkAddresses.resize( newSize );
00197 }
00198 
00200 void btSoftBodyLinkDataOpenCL::setLinkAt( 
00201         const LinkDescription &link, 
00202         int linkIndex )
00203 {
00204         btSoftBodyLinkData::setLinkAt( link, linkIndex );
00205 
00206         // Set the link index correctly for initialisation
00207         m_linkAddresses[linkIndex] = linkIndex;
00208 }
00209 
00210 bool btSoftBodyLinkDataOpenCL::onAccelerator()
00211 {
00212         return m_onGPU;
00213 }
00214 
00215 bool btSoftBodyLinkDataOpenCL::moveToAccelerator()
00216 {
00217         bool success = true;
00218         success = success && m_clLinks.moveToGPU();
00219         success = success && m_clLinkStrength.moveToGPU();
00220         success = success && m_clLinksMassLSC.moveToGPU();
00221         success = success && m_clLinksRestLengthSquared.moveToGPU();
00222         success = success && m_clLinksCLength.moveToGPU();
00223         success = success && m_clLinksLengthRatio.moveToGPU();
00224         success = success && m_clLinksRestLength.moveToGPU();
00225         success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveToGPU();
00226 
00227         if( success ) {
00228                 m_onGPU = true;
00229         }
00230 
00231         return success;
00232 }
00233 
00234 bool btSoftBodyLinkDataOpenCL::moveFromAccelerator()
00235 {
00236         bool success = true;
00237         success = success && m_clLinks.moveFromGPU();
00238         success = success && m_clLinkStrength.moveFromGPU();
00239         success = success && m_clLinksMassLSC.moveFromGPU();
00240         success = success && m_clLinksRestLengthSquared.moveFromGPU();
00241         success = success && m_clLinksCLength.moveFromGPU();
00242         success = success && m_clLinksLengthRatio.moveFromGPU();
00243         success = success && m_clLinksRestLength.moveFromGPU();
00244         success = success && m_clLinksMaterialLinearStiffnessCoefficient.moveFromGPU();
00245 
00246         if( success ) {
00247                 m_onGPU = false;
00248         }
00249 
00250         return success;
00251 }
00252 
00259 void btSoftBodyLinkDataOpenCL::generateBatches()
00260 {
00261         int numLinks = getNumLinks();
00262 
00263         // Do the graph colouring here temporarily
00264         btAlignedObjectArray< int > batchValues;
00265         batchValues.resize( numLinks, 0 );
00266 
00267         // Find the maximum vertex value internally for now
00268         int maxVertex = 0;
00269         for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
00270         {
00271                 int vertex0 = getVertexPair(linkIndex).vertex0;
00272                 int vertex1 = getVertexPair(linkIndex).vertex1;
00273                 if( vertex0 > maxVertex )
00274                         maxVertex = vertex0;
00275                 if( vertex1 > maxVertex )
00276                         maxVertex = vertex1;
00277         }
00278         int numVertices = maxVertex + 1;
00279 
00280         // Set of lists, one for each node, specifying which colours are connected
00281         // to that node.
00282         // No two edges into a node can share a colour.
00283         btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists;
00284         vertexConnectedColourLists.resize(numVertices);
00285 
00286         // Simple algorithm that chooses the lowest batch number
00287         // that none of the links attached to either of the connected 
00288         // nodes is in
00289         for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
00290         {                               
00291                 int linkLocation = m_linkAddresses[linkIndex];
00292 
00293                 int vertex0 = getVertexPair(linkLocation).vertex0;
00294                 int vertex1 = getVertexPair(linkLocation).vertex1;
00295 
00296                 // Get the two node colour lists
00297                 btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] );
00298                 btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] );
00299 
00300                 // Choose the minimum colour that is in neither list
00301                 int colour = 0;
00302                 while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size()  )
00303                         ++colour;
00304                 // i should now be the minimum colour in neither list
00305                 // Add to the two lists so that future edges don't share
00306                 // And store the colour against this edge
00307 
00308                 colourListVertex0.push_back(colour);
00309                 colourListVertex1.push_back(colour);
00310                 batchValues[linkIndex] = colour;
00311         }
00312 
00313         // Check the colour counts
00314         btAlignedObjectArray< int > batchCounts;
00315         for( int i = 0; i < numLinks; ++i )
00316         {
00317                 int batch = batchValues[i];
00318                 if( batch >= batchCounts.size() )
00319                         batchCounts.push_back(1);
00320                 else
00321                         ++(batchCounts[batch]);
00322         }
00323 
00324         m_batchStartLengths.resize(batchCounts.size());
00325         if( m_batchStartLengths.size() > 0 )
00326         {
00327                 m_batchStartLengths.resize(batchCounts.size());
00328                 m_batchStartLengths[0] = BatchPair(0, 0);
00329 
00330                 int sum = 0;
00331                 for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex )
00332                 {
00333                         m_batchStartLengths[batchIndex].start = sum;
00334                         m_batchStartLengths[batchIndex].length = batchCounts[batchIndex];
00335                         sum += batchCounts[batchIndex];
00336                 }
00337         }
00338 
00340         // Sort data based on batches
00341 
00342         // Create source arrays by copying originals
00343         btAlignedObjectArray<LinkNodePair>                                                                      m_links_Backup(m_links);
00344         btAlignedObjectArray<float>                                                                                     m_linkStrength_Backup(m_linkStrength);
00345         btAlignedObjectArray<float>                                                                                     m_linksMassLSC_Backup(m_linksMassLSC);
00346         btAlignedObjectArray<float>                                                                                     m_linksRestLengthSquared_Backup(m_linksRestLengthSquared);
00347         btAlignedObjectArray<Vectormath::Aos::Vector3>                                          m_linksCLength_Backup(m_linksCLength);
00348         btAlignedObjectArray<float>                                                                                     m_linksLengthRatio_Backup(m_linksLengthRatio);
00349         btAlignedObjectArray<float>                                                                                     m_linksRestLength_Backup(m_linksRestLength);
00350         btAlignedObjectArray<float>                                                                                     m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient);
00351 
00352 
00353         for( int batch = 0; batch < batchCounts.size(); ++batch )
00354                 batchCounts[batch] = 0;
00355 
00356         // Do sort as single pass into destination arrays       
00357         for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
00358         {
00359                 // To maintain locations run off the original link locations rather than the current position.
00360                 // It's not cache efficient, but as we run this rarely that should not matter.
00361                 // It's faster than searching the link location array for the current location and then updating it.
00362                 // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
00363                 int linkLocation = m_linkAddresses[linkIndex];
00364 
00365                 // Obtain batch and calculate target location for the
00366                 // next element in that batch, incrementing the batch counter
00367                 // afterwards
00368                 int batch = batchValues[linkIndex];
00369                 int newLocation = m_batchStartLengths[batch].start + batchCounts[batch];
00370 
00371                 batchCounts[batch] = batchCounts[batch] + 1;
00372                 m_links[newLocation] = m_links_Backup[linkLocation];
00373 #if 1
00374                 m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation];
00375                 m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation];
00376                 m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation];
00377                 m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation];
00378                 m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation];
00379                 m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation];
00380 #endif
00381                 // Update the locations array to account for the moved entry
00382                 m_linkAddresses[linkIndex] = newLocation;
00383         }
00384 
00385 
00386 } // void generateBatches()
00387 
00388 
00389 
00390 
00391 
00392 btSoftBodyTriangleDataOpenCL::btSoftBodyTriangleDataOpenCL( cl_command_queue queue , cl_context ctx) : 
00393     m_queue( queue ),
00394         m_clVertexIndices( queue, ctx, &m_vertexIndices, false ),
00395         m_clArea( queue, ctx, &m_area, false ),
00396         m_clNormal( queue, ctx, &m_normal, false )
00397 {
00398 }
00399 
00400 btSoftBodyTriangleDataOpenCL::~btSoftBodyTriangleDataOpenCL()
00401 {
00402 }
00403 
00405 void btSoftBodyTriangleDataOpenCL::createTriangles( int numTriangles )
00406 {
00407         int previousSize = getNumTriangles();
00408         int newSize = previousSize + numTriangles;
00409 
00410         btSoftBodyTriangleData::createTriangles( numTriangles );
00411 
00412         // Resize the link addresses array as well
00413         m_triangleAddresses.resize( newSize );
00414 }
00415 
00417 void btSoftBodyTriangleDataOpenCL::setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex )
00418 {
00419         btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex );
00420 
00421         m_triangleAddresses[triangleIndex] = triangleIndex;
00422 }
00423 
00424 bool btSoftBodyTriangleDataOpenCL::onAccelerator()
00425 {
00426         return m_onGPU;
00427 }
00428 
00429 bool btSoftBodyTriangleDataOpenCL::moveToAccelerator()
00430 {
00431         bool success = true;
00432         success = success && m_clVertexIndices.moveToGPU();
00433         success = success && m_clArea.moveToGPU();
00434         success = success && m_clNormal.moveToGPU();
00435 
00436         if( success )
00437                 m_onGPU = true;
00438 
00439         return success;
00440 }
00441 
00442 bool btSoftBodyTriangleDataOpenCL::moveFromAccelerator()
00443 {
00444         bool success = true;
00445         success = success && m_clVertexIndices.moveFromGPU();
00446         success = success && m_clArea.moveFromGPU();
00447         success = success && m_clNormal.moveFromGPU();
00448 
00449         if( success )
00450                 m_onGPU = true;
00451 
00452         return success;
00453 }
00454 
00461 void btSoftBodyTriangleDataOpenCL::generateBatches()
00462 {
00463         int numTriangles = getNumTriangles();
00464         if( numTriangles == 0 )
00465                 return;
00466 
00467         // Do the graph colouring here temporarily
00468         btAlignedObjectArray< int > batchValues;
00469         batchValues.resize( numTriangles );
00470 
00471         // Find the maximum vertex value internally for now
00472         int maxVertex = 0;
00473         for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
00474         {
00475                 int vertex0 = getVertexSet(triangleIndex).vertex0;
00476                 int vertex1 = getVertexSet(triangleIndex).vertex1;
00477                 int vertex2 = getVertexSet(triangleIndex).vertex2;
00478                 
00479                 if( vertex0 > maxVertex )
00480                         maxVertex = vertex0;
00481                 if( vertex1 > maxVertex )
00482                         maxVertex = vertex1;
00483                 if( vertex2 > maxVertex )
00484                         maxVertex = vertex2;
00485         }
00486         int numVertices = maxVertex + 1;
00487 
00488         // Set of lists, one for each node, specifying which colours are connected
00489         // to that node.
00490         // No two edges into a node can share a colour.
00491         btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists;
00492         vertexConnectedColourLists.resize(numVertices);
00493 
00494 
00495         //std::cout << "\n";
00496         // Simple algorithm that chooses the lowest batch number
00497         // that none of the faces attached to either of the connected 
00498         // nodes is in
00499         for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
00500         {
00501                 // To maintain locations run off the original link locations rather than the current position.
00502                 // It's not cache efficient, but as we run this rarely that should not matter.
00503                 // It's faster than searching the link location array for the current location and then updating it.
00504                 // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
00505                 int triangleLocation = m_triangleAddresses[triangleIndex];
00506 
00507                 int vertex0 = getVertexSet(triangleLocation).vertex0;
00508                 int vertex1 = getVertexSet(triangleLocation).vertex1;
00509                 int vertex2 = getVertexSet(triangleLocation).vertex2;
00510 
00511                 // Get the three node colour lists
00512                 btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] );
00513                 btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] );
00514                 btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] );
00515 
00516                 // Choose the minimum colour that is in none of the lists
00517                 int colour = 0;
00518                 while( 
00519                         colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || 
00520                         colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ||
00521                         colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() )
00522                 {
00523                         ++colour;
00524                 }
00525                 // i should now be the minimum colour in neither list
00526                 // Add to the three lists so that future edges don't share
00527                 // And store the colour against this face
00528                 colourListVertex0.push_back(colour);
00529                 colourListVertex1.push_back(colour);
00530                 colourListVertex2.push_back(colour);
00531 
00532                 batchValues[triangleIndex] = colour;
00533         }
00534 
00535 
00536         // Check the colour counts
00537         btAlignedObjectArray< int > batchCounts;
00538         for( int i = 0; i < numTriangles; ++i )
00539         {
00540                 int batch = batchValues[i];
00541                 if( batch >= batchCounts.size() )
00542                         batchCounts.push_back(1);
00543                 else
00544                         ++(batchCounts[batch]);
00545         }
00546 
00547 
00548         m_batchStartLengths.resize(batchCounts.size());
00549         m_batchStartLengths[0] = btSomePair(0,0);
00550 
00551 
00552         int sum = 0;
00553         for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex )
00554         {
00555                 m_batchStartLengths[batchIndex].first = sum;
00556                 m_batchStartLengths[batchIndex].second = batchCounts[batchIndex];
00557                 sum += batchCounts[batchIndex];
00558         }
00559         
00561         // Sort data based on batches
00562         
00563         // Create source arrays by copying originals
00564         btAlignedObjectArray<btSoftBodyTriangleData::TriangleNodeSet>                                                   m_vertexIndices_Backup(m_vertexIndices);
00565         btAlignedObjectArray<float>                                                                             m_area_Backup(m_area);
00566         btAlignedObjectArray<Vectormath::Aos::Vector3>                                  m_normal_Backup(m_normal);
00567 
00568 
00569         for( int batch = 0; batch < batchCounts.size(); ++batch )
00570                 batchCounts[batch] = 0;
00571 
00572         // Do sort as single pass into destination arrays       
00573         for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
00574         {
00575                 // To maintain locations run off the original link locations rather than the current position.
00576                 // It's not cache efficient, but as we run this rarely that should not matter.
00577                 // It's faster than searching the link location array for the current location and then updating it.
00578                 // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
00579                 int triangleLocation = m_triangleAddresses[triangleIndex];
00580 
00581                 // Obtain batch and calculate target location for the
00582                 // next element in that batch, incrementing the batch counter
00583                 // afterwards
00584                 int batch = batchValues[triangleIndex];
00585                 int newLocation = m_batchStartLengths[batch].first + batchCounts[batch];
00586 
00587                 batchCounts[batch] = batchCounts[batch] + 1;
00588                 m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation];
00589                 m_area[newLocation] = m_area_Backup[triangleLocation];
00590                 m_normal[newLocation] = m_normal_Backup[triangleLocation];
00591 
00592                 // Update the locations array to account for the moved entry
00593                 m_triangleAddresses[triangleIndex] = newLocation;
00594         }
00595 } // btSoftBodyTriangleDataOpenCL::generateBatches
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 btOpenCLSoftBodySolver::btOpenCLSoftBodySolver(cl_command_queue queue, cl_context ctx, bool bUpdateAchchoredNodePos) :
00604         m_linkData(queue, ctx),
00605         m_vertexData(queue, ctx),
00606         m_triangleData(queue, ctx),
00607         m_defaultCLFunctions(queue, ctx),
00608         m_currentCLFunctions(&m_defaultCLFunctions),
00609         m_clPerClothAcceleration(queue, ctx, &m_perClothAcceleration, true ),
00610         m_clPerClothWindVelocity(queue, ctx, &m_perClothWindVelocity, true ),
00611         m_clPerClothDampingFactor(queue,ctx, &m_perClothDampingFactor, true ),
00612         m_clPerClothVelocityCorrectionCoefficient(queue, ctx,&m_perClothVelocityCorrectionCoefficient, true ),
00613         m_clPerClothLiftFactor(queue, ctx,&m_perClothLiftFactor, true ),
00614         m_clPerClothDragFactor(queue, ctx,&m_perClothDragFactor, true ),
00615         m_clPerClothMediumDensity(queue, ctx,&m_perClothMediumDensity, true ),
00616         m_clPerClothCollisionObjects( queue, ctx, &m_perClothCollisionObjects, true ),
00617         m_clCollisionObjectDetails( queue, ctx, &m_collisionObjectDetails, true ),
00618         m_clPerClothFriction( queue, ctx, &m_perClothFriction, false ),
00619         m_clAnchorPosition( queue, ctx, &m_anchorPosition, true ),
00620         m_clAnchorIndex( queue, ctx, &m_anchorIndex, true),
00621         m_cqCommandQue( queue ),
00622         m_cxMainContext(ctx),
00623         m_defaultWorkGroupSize(BT_DEFAULT_WORKGROUPSIZE),
00624         m_bUpdateAnchoredNodePos(bUpdateAchchoredNodePos)
00625 {
00626 
00627         // Initial we will clearly need to update solver constants
00628         // For now this is global for the cloths linked with this solver - we should probably make this body specific 
00629         // for performance in future once we understand more clearly when constants need to be updated
00630         m_updateSolverConstants = true;
00631 
00632         m_shadersInitialized = false;
00633 
00634         m_prepareLinksKernel = 0;
00635         m_solvePositionsFromLinksKernel = 0;
00636         m_updateConstantsKernel = 0;
00637         m_integrateKernel = 0;
00638         m_addVelocityKernel = 0;
00639         m_updatePositionsFromVelocitiesKernel = 0;
00640         m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = 0;
00641         m_updateVelocitiesFromPositionsWithVelocitiesKernel = 0;
00642         m_vSolveLinksKernel = 0;
00643         m_solveCollisionsAndUpdateVelocitiesKernel = 0;
00644         m_resetNormalsAndAreasKernel = 0;
00645         m_updateSoftBodiesKernel = 0;
00646         m_normalizeNormalsAndAreasKernel = 0;
00647         m_outputToVertexArrayKernel = 0;
00648         m_applyForcesKernel = 0;
00649         m_updateFixedVertexPositionsKernel = 0;
00650 }
00651 
00652 btOpenCLSoftBodySolver::~btOpenCLSoftBodySolver()
00653 {
00654         releaseKernels();
00655 }
00656 
00657 void btOpenCLSoftBodySolver::releaseKernels()
00658 {
00659         RELEASE_CL_KERNEL( m_prepareLinksKernel );
00660         RELEASE_CL_KERNEL( m_solvePositionsFromLinksKernel );
00661         RELEASE_CL_KERNEL( m_updateConstantsKernel );
00662         RELEASE_CL_KERNEL( m_integrateKernel );
00663         RELEASE_CL_KERNEL( m_addVelocityKernel );
00664         RELEASE_CL_KERNEL( m_updatePositionsFromVelocitiesKernel );
00665         RELEASE_CL_KERNEL( m_updateVelocitiesFromPositionsWithoutVelocitiesKernel );
00666         RELEASE_CL_KERNEL( m_updateVelocitiesFromPositionsWithVelocitiesKernel );
00667         RELEASE_CL_KERNEL( m_vSolveLinksKernel );
00668         RELEASE_CL_KERNEL( m_solveCollisionsAndUpdateVelocitiesKernel );
00669         RELEASE_CL_KERNEL( m_resetNormalsAndAreasKernel );
00670         RELEASE_CL_KERNEL( m_normalizeNormalsAndAreasKernel );
00671         RELEASE_CL_KERNEL( m_outputToVertexArrayKernel );
00672         RELEASE_CL_KERNEL( m_applyForcesKernel );
00673         RELEASE_CL_KERNEL( m_updateFixedVertexPositionsKernel );
00674 
00675         m_shadersInitialized = false;
00676 }
00677 
00678 void btOpenCLSoftBodySolver::copyBackToSoftBodies(bool bMove)
00679 {
00680 
00681         // Move the vertex data back to the host first
00682         m_vertexData.moveFromAccelerator(!bMove);
00683 
00684         // Loop over soft bodies, copying all the vertex positions back for each body in turn
00685         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
00686         {
00687                 btOpenCLAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ];
00688                 btSoftBody *softBody = softBodyInterface->getSoftBody();
00689 
00690                 int firstVertex = softBodyInterface->getFirstVertex();
00691                 int numVertices = softBodyInterface->getNumVertices();
00692 
00693                 // Copy vertices from solver back into the softbody
00694                 for( int vertex = 0; vertex < numVertices; ++vertex )
00695                 {
00696                         using Vectormath::Aos::Point3;
00697                         Point3 vertexPosition( m_vertexData.getVertexPositions()[firstVertex + vertex] );
00698                         Point3 normal(m_vertexData.getNormal(firstVertex + vertex));
00699 
00700                         softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() );
00701                         softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() );
00702                         softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() );
00703 
00704                         softBody->m_nodes[vertex].m_n.setX( normal.getX() );
00705                         softBody->m_nodes[vertex].m_n.setY( normal.getY() );
00706                         softBody->m_nodes[vertex].m_n.setZ( normal.getZ() );
00707                 }
00708         }       
00709 } // btOpenCLSoftBodySolver::copyBackToSoftBodies
00710 
00711 void btOpenCLSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate )
00712 {
00713         if( forceUpdate || m_softBodySet.size() != softBodies.size() )
00714         {
00715                 // Have a change in the soft body set so update, reloading all the data
00716                 getVertexData().clear();
00717                 getTriangleData().clear();
00718                 getLinkData().clear();
00719                 m_softBodySet.resize(0);
00720                 m_anchorIndex.clear();
00721 
00722                 int maxPiterations = 0;
00723                 int maxViterations = 0;
00724 
00725                 for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex )
00726                 {
00727                         btSoftBody *softBody = softBodies[ softBodyIndex ];
00728                         using Vectormath::Aos::Matrix3;
00729                         using Vectormath::Aos::Point3;
00730 
00731                         // Create SoftBody that will store the information within the solver
00732                         btOpenCLAcceleratedSoftBodyInterface *newSoftBody = new btOpenCLAcceleratedSoftBodyInterface( softBody );
00733                         m_softBodySet.push_back( newSoftBody );
00734 
00735                         m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) );
00736                         m_perClothDampingFactor.push_back(softBody->m_cfg.kDP);
00737                         m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF );
00738                         m_perClothLiftFactor.push_back( softBody->m_cfg.kLF );
00739                         m_perClothDragFactor.push_back( softBody->m_cfg.kDG );
00740                         m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density);
00741                         // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time
00742                         m_perClothFriction.push_back(softBody->m_cfg.kDF);
00743                         m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) );
00744 
00745                         // Add space for new vertices and triangles in the default solver for now
00746                         // TODO: Include space here for tearing too later
00747                         int firstVertex = getVertexData().getNumVertices();
00748                         int numVertices = softBody->m_nodes.size();
00749                         int maxVertices = numVertices;
00750                         // Allocate space for new vertices in all the vertex arrays
00751                         getVertexData().createVertices( maxVertices, softBodyIndex );
00752 
00753                         int firstTriangle = getTriangleData().getNumTriangles();
00754                         int numTriangles = softBody->m_faces.size();
00755                         int maxTriangles = numTriangles;
00756                         getTriangleData().createTriangles( maxTriangles );
00757 
00758                         // Copy vertices from softbody into the solver
00759                         for( int vertex = 0; vertex < numVertices; ++vertex )
00760                         {
00761                                 Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ());
00762                                 btSoftBodyVertexData::VertexDescription desc;
00763 
00764                                 // TODO: Position in the softbody might be pre-transformed
00765                                 // or we may need to adapt for the pose.
00766                                 //desc.setPosition( cloth.getMeshTransform()*multPoint );
00767                                 desc.setPosition( multPoint );
00768 
00769                                 float vertexInverseMass = softBody->m_nodes[vertex].m_im;
00770                                 desc.setInverseMass(vertexInverseMass);
00771                                 getVertexData().setVertexAt( desc, firstVertex + vertex );
00772 
00773                                 m_anchorIndex.push_back(-1);
00774                         }
00775 
00776                         // Copy triangles similarly
00777                         // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene
00778                         for( int triangle = 0; triangle < numTriangles; ++triangle )
00779                         {
00780                                 // Note that large array storage is relative to the array not to the cloth
00781                                 // So we need to add firstVertex to each value
00782                                 int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0]));
00783                                 int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0]));
00784                                 int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0]));
00785                                 btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex);
00786                                 getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle );
00787                                 
00788                                 // Increase vertex triangle counts for this triangle            
00789                                 getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++;
00790                                 getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++;
00791                                 getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++;
00792                         }
00793 
00794                         int firstLink = getLinkData().getNumLinks();
00795                         int numLinks = softBody->m_links.size();
00796 //                      int maxLinks = numLinks;
00797                         
00798                         // Allocate space for the links
00799                         getLinkData().createLinks( numLinks );
00800 
00801                         // Add the links
00802                         for( int link = 0; link < numLinks; ++link )
00803                         {
00804                                 int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]);
00805                                 int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]);
00806 
00807                                 btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST);
00808                                 newLink.setLinkStrength(1.f);
00809                                 getLinkData().setLinkAt(newLink, firstLink + link);
00810                         }
00811                         
00812                         newSoftBody->setFirstVertex( firstVertex );
00813                         newSoftBody->setFirstTriangle( firstTriangle );
00814                         newSoftBody->setNumVertices( numVertices );
00815                         newSoftBody->setMaxVertices( maxVertices );
00816                         newSoftBody->setNumTriangles( numTriangles );
00817                         newSoftBody->setMaxTriangles( maxTriangles );
00818                         newSoftBody->setFirstLink( firstLink );
00819                         newSoftBody->setNumLinks( numLinks );
00820 
00821                         // Find maximum piterations and viterations
00822                         int piterations = softBody->m_cfg.piterations;
00823 
00824             if ( piterations > maxPiterations )
00825                   maxPiterations = piterations;
00826 
00827             int viterations = softBody->m_cfg.viterations;
00828 
00829                         if ( viterations > maxViterations )
00830                   maxViterations = viterations;
00831 
00832                         // zero mass
00833                         for( int vertex = 0; vertex < numVertices; ++vertex )
00834                         {
00835                                 if ( softBody->m_nodes[vertex].m_im == 0 )
00836                                 {
00837                                         AnchorNodeInfoCL nodeInfo;
00838                                         nodeInfo.clVertexIndex = firstVertex + vertex;
00839                                         nodeInfo.pNode = &softBody->m_nodes[vertex];
00840 
00841                                         m_anchorNodeInfoArray.push_back(nodeInfo);
00842                                 }
00843                         }                       
00844 
00845                         // anchor position
00846                         if ( numVertices > 0 )
00847                         {
00848                                 for ( int anchorIndex = 0; anchorIndex < softBody->m_anchors.size(); anchorIndex++ )
00849                                 {
00850                                         btSoftBody::Node* anchorNode = softBody->m_anchors[anchorIndex].m_node;
00851                                         btSoftBody::Node* firstNode = &softBody->m_nodes[0];
00852 
00853                                         AnchorNodeInfoCL nodeInfo;
00854                                         nodeInfo.clVertexIndex = firstVertex + (int)(anchorNode - firstNode);
00855                                         nodeInfo.pNode = anchorNode;
00856 
00857                                         m_anchorNodeInfoArray.push_back(nodeInfo);
00858                                 }
00859                         }                       
00860                 }
00861 
00862                 
00863                 m_anchorPosition.clear();               
00864                 m_anchorPosition.resize(m_anchorNodeInfoArray.size());
00865 
00866                 for ( int anchorNode = 0; anchorNode < m_anchorNodeInfoArray.size(); anchorNode++ )
00867                 {
00868                         const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[anchorNode];
00869                         m_anchorIndex[anchorNodeInfo.clVertexIndex] = anchorNode;
00870                         getVertexData().getInverseMass(anchorNodeInfo.clVertexIndex) = 0.0f;
00871                 }
00872                 
00873                 updateConstants(0.f);
00874 
00875                 // set position and velocity iterations
00876                 setNumberOfPositionIterations(maxPiterations);
00877                 setNumberOfVelocityIterations(maxViterations);
00878 
00879                 // set wind velocity
00880                 m_perClothWindVelocity.resize( m_softBodySet.size() );
00881                 for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
00882                 {
00883                         btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody();                     
00884                         m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity());
00885                 }
00886 
00887                 m_clPerClothWindVelocity.changedOnCPU();
00888 
00889                 // generate batches
00890                 m_linkData.generateBatches();           
00891                 m_triangleData.generateBatches();
00892 
00893                 // Build the shaders to match the batching parameters
00894                 buildShaders();
00895         }
00896 }
00897 
00898 
00899 btSoftBodyLinkData &btOpenCLSoftBodySolver::getLinkData()
00900 {
00901         // TODO: Consider setting link data to "changed" here
00902         return m_linkData;
00903 }
00904 
00905 btSoftBodyVertexData &btOpenCLSoftBodySolver::getVertexData()
00906 {
00907         // TODO: Consider setting vertex data to "changed" here
00908         return m_vertexData;
00909 }
00910 
00911 btSoftBodyTriangleData &btOpenCLSoftBodySolver::getTriangleData()
00912 {
00913         // TODO: Consider setting triangle data to "changed" here
00914         return m_triangleData;
00915 }
00916 
00917 void btOpenCLSoftBodySolver::resetNormalsAndAreas( int numVertices )
00918 {
00919         cl_int ciErrNum;
00920         ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 0, sizeof(numVertices), (void*)&numVertices); //oclCHECKERROR(ciErrNum, CL_SUCCESS);
00921         ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 1, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexNormal.m_buffer);//oclCHECKERROR(ciErrNum, CL_SUCCESS);
00922         ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel,  2, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexArea.m_buffer); //oclCHECKERROR(ciErrNum, CL_SUCCESS);
00923         size_t numWorkItems = m_defaultWorkGroupSize*((numVertices + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
00924 
00925         if (numWorkItems)
00926         {
00927                 ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_resetNormalsAndAreasKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0 );
00928 
00929                 if( ciErrNum != CL_SUCCESS )
00930                 {
00931                         btAssert( 0 && "enqueueNDRangeKernel(m_resetNormalsAndAreasKernel)" );
00932                 }
00933         }
00934 
00935 }
00936 
00937 void btOpenCLSoftBodySolver::normalizeNormalsAndAreas( int numVertices )
00938 {
00939         cl_int ciErrNum;
00940 
00941         ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 0, sizeof(int),(void*) &numVertices);
00942         ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 1, sizeof(cl_mem), &m_vertexData.m_clVertexTriangleCount.m_buffer);
00943         ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer);
00944         ciErrNum = clSetKernelArg(m_normalizeNormalsAndAreasKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer);
00945         size_t  numWorkItems = m_defaultWorkGroupSize*((numVertices + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
00946         if (numWorkItems)
00947         {
00948                 ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_normalizeNormalsAndAreasKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0);
00949                 if( ciErrNum != CL_SUCCESS ) 
00950                 {
00951                         btAssert( 0 && "enqueueNDRangeKernel(m_normalizeNormalsAndAreasKernel)");
00952                 }
00953         }
00954 
00955 }
00956 
00957 void btOpenCLSoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles )
00958 {
00959         cl_int ciErrNum;
00960         ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 0, sizeof(int), (void*) &firstTriangle);
00961         ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 1, sizeof(int), &numTriangles);
00962         ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 2, sizeof(cl_mem), &m_triangleData.m_clVertexIndices.m_buffer);
00963         ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer);
00964         ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer);
00965         ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer);
00966         ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 6, sizeof(cl_mem), &m_triangleData.m_clNormal.m_buffer);
00967         ciErrNum = clSetKernelArg(m_updateSoftBodiesKernel, 7, sizeof(cl_mem), &m_triangleData.m_clArea.m_buffer);
00968 
00969         size_t numWorkItems = m_defaultWorkGroupSize*((numTriangles + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
00970         ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue, m_updateSoftBodiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0);
00971         if( ciErrNum != CL_SUCCESS ) 
00972         {
00973                 btAssert( 0 &&  "enqueueNDRangeKernel(m_normalizeNormalsAndAreasKernel)");
00974         }
00975 
00976 }
00977 
00978 void btOpenCLSoftBodySolver::updateSoftBodies()
00979 {
00980         using namespace Vectormath::Aos;
00981 
00982 
00983         int numVertices = m_vertexData.getNumVertices();
00984 //      int numTriangles = m_triangleData.getNumTriangles();
00985 
00986         // Ensure data is on accelerator
00987         m_vertexData.moveToAccelerator();
00988         m_triangleData.moveToAccelerator();
00989 
00990         resetNormalsAndAreas( numVertices );
00991 
00992 
00993         // Go through triangle batches so updates occur correctly
00994         for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex )
00995         {
00996 
00997                 int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].first;
00998                 int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].second;
00999 
01000                 executeUpdateSoftBodies( startTriangle, numTriangles );
01001         }
01002 
01003 
01004         normalizeNormalsAndAreas( numVertices );
01005 } // updateSoftBodies
01006 
01007 
01008 Vectormath::Aos::Vector3 btOpenCLSoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a )
01009 {
01010         return a*Vectormath::Aos::dot(v, a);
01011 }
01012 
01013 void btOpenCLSoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce )
01014 {
01015         float dtInverseMass = solverdt*inverseMass;
01016         if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) )
01017         {
01018                 vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass;
01019         } else {
01020                 vertexForce += force;
01021         }
01022 }
01023 
01024 void btOpenCLSoftBodySolver::updateFixedVertexPositions()
01025 {       
01026         // Ensure data is on accelerator
01027         m_vertexData.moveToAccelerator();
01028         m_clAnchorPosition.moveToGPU();
01029         m_clAnchorIndex.moveToGPU();
01030 
01031         cl_int ciErrNum ;
01032         int numVerts = m_vertexData.getNumVertices();
01033         ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel, 0, sizeof(int), &numVerts);
01034         ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,1, sizeof(cl_mem), &m_clAnchorIndex.m_buffer);
01035         ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,2, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer);
01036         ciErrNum = clSetKernelArg(m_updateFixedVertexPositionsKernel,3, sizeof(cl_mem), &m_clAnchorPosition.m_buffer);
01037 
01038         size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01039         if (numWorkItems)
01040         {
01041                 ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateFixedVertexPositionsKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0);
01042                 if( ciErrNum != CL_SUCCESS ) 
01043                 {
01044                         btAssert( 0 &&  "enqueueNDRangeKernel(m_updateFixedVertexPositionsKernel)");
01045                 }
01046         }
01047 
01048 }
01049 
01050 void btOpenCLSoftBodySolver::applyForces( float solverdt )
01051 {       
01052         // Ensure data is on accelerator
01053         m_vertexData.moveToAccelerator();
01054         m_clPerClothAcceleration.moveToGPU();
01055         m_clPerClothLiftFactor.moveToGPU();
01056         m_clPerClothDragFactor.moveToGPU();
01057         m_clPerClothMediumDensity.moveToGPU();
01058         m_clPerClothWindVelocity.moveToGPU();   
01059 
01060         cl_int ciErrNum ;
01061         int numVerts = m_vertexData.getNumVertices();
01062         ciErrNum = clSetKernelArg(m_applyForcesKernel, 0, sizeof(int), &numVerts);
01063         ciErrNum = clSetKernelArg(m_applyForcesKernel, 1, sizeof(float), &solverdt);
01064         float fl = FLT_EPSILON;
01065         ciErrNum = clSetKernelArg(m_applyForcesKernel, 2, sizeof(float), &fl);
01066         ciErrNum = clSetKernelArg(m_applyForcesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clClothIdentifier.m_buffer);
01067         ciErrNum = clSetKernelArg(m_applyForcesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexNormal.m_buffer);
01068         ciErrNum = clSetKernelArg(m_applyForcesKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexArea.m_buffer);
01069         ciErrNum = clSetKernelArg(m_applyForcesKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer);
01070         ciErrNum = clSetKernelArg(m_applyForcesKernel, 7, sizeof(cl_mem), &m_clPerClothLiftFactor.m_buffer);
01071         ciErrNum = clSetKernelArg(m_applyForcesKernel, 8 ,sizeof(cl_mem), &m_clPerClothDragFactor.m_buffer);
01072         ciErrNum = clSetKernelArg(m_applyForcesKernel, 9, sizeof(cl_mem), &m_clPerClothWindVelocity.m_buffer);
01073         ciErrNum = clSetKernelArg(m_applyForcesKernel,10, sizeof(cl_mem), &m_clPerClothAcceleration.m_buffer);
01074         ciErrNum = clSetKernelArg(m_applyForcesKernel,11, sizeof(cl_mem), &m_clPerClothMediumDensity.m_buffer);
01075         ciErrNum = clSetKernelArg(m_applyForcesKernel,12, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer);
01076         ciErrNum = clSetKernelArg(m_applyForcesKernel,13, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer);
01077 
01078         size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01079         if (numWorkItems)
01080         {
01081                 ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_applyForcesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize, 0,0,0);
01082                 if( ciErrNum != CL_SUCCESS ) 
01083                 {
01084                         btAssert( 0 &&  "enqueueNDRangeKernel(m_applyForcesKernel)");
01085                 }
01086         }
01087 
01088 }
01089 
01093 void btOpenCLSoftBodySolver::integrate( float solverdt )
01094 {
01095         // Ensure data is on accelerator
01096         m_vertexData.moveToAccelerator();
01097 
01098         cl_int ciErrNum;
01099         int numVerts = m_vertexData.getNumVertices();
01100         ciErrNum = clSetKernelArg(m_integrateKernel, 0, sizeof(int), &numVerts);
01101         ciErrNum = clSetKernelArg(m_integrateKernel, 1, sizeof(float), &solverdt);
01102         ciErrNum = clSetKernelArg(m_integrateKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer);
01103         ciErrNum = clSetKernelArg(m_integrateKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer);
01104         ciErrNum = clSetKernelArg(m_integrateKernel, 4, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer);
01105         ciErrNum = clSetKernelArg(m_integrateKernel, 5, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer);
01106         ciErrNum = clSetKernelArg(m_integrateKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer);
01107 
01108         size_t numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01109         if (numWorkItems)
01110         {
01111                 ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_integrateKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0);
01112                 if( ciErrNum != CL_SUCCESS )
01113                 {
01114                         btAssert( 0 &&  "enqueueNDRangeKernel(m_integrateKernel)");
01115                 }
01116         }
01117 
01118 }
01119 
01120 float btOpenCLSoftBodySolver::computeTriangleArea( 
01121         const Vectormath::Aos::Point3 &vertex0,
01122         const Vectormath::Aos::Point3 &vertex1,
01123         const Vectormath::Aos::Point3 &vertex2 )
01124 {
01125         Vectormath::Aos::Vector3 a = vertex1 - vertex0;
01126         Vectormath::Aos::Vector3 b = vertex2 - vertex0;
01127         Vectormath::Aos::Vector3 crossProduct = cross(a, b);
01128         float area = length( crossProduct );
01129         return area;
01130 }
01131 
01132 
01133 void btOpenCLSoftBodySolver::updateBounds()
01134 {       
01135         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
01136         {
01137                 btVector3 minBound(-1e30,-1e30,-1e30), maxBound(1e30,1e30,1e30);
01138                 m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound );
01139         }
01140 
01141 } // btOpenCLSoftBodySolver::updateBounds
01142 
01143 
01144 void btOpenCLSoftBodySolver::updateConstants( float timeStep )
01145 {                       
01146 
01147         using namespace Vectormath::Aos;
01148 
01149         if( m_updateSolverConstants )
01150         {
01151                 m_updateSolverConstants = false;
01152 
01153                 // Will have to redo this if we change the structure (tear, maybe) or various other possible changes
01154 
01155                 // Initialise link constants
01156                 const int numLinks = m_linkData.getNumLinks();
01157                 for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
01158                 {
01159                         btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) );
01160                         m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 )));
01161                         float invMass0 = m_vertexData.getInverseMass(vertices.vertex0);
01162                         float invMass1 = m_vertexData.getInverseMass(vertices.vertex1);
01163                         float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex);
01164                         float massLSC = (invMass0 + invMass1)/linearStiffness;
01165                         m_linkData.getMassLSC(linkIndex) = massLSC;
01166                         float restLength = m_linkData.getRestLength(linkIndex);
01167                         float restLengthSquared = restLength*restLength;
01168                         m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared;
01169                 }
01170         }
01171 
01172 }
01173 
01174 class QuickSortCompare
01175 {
01176         public:
01177 
01178         bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const
01179         {
01180                 return ( a.softBodyIdentifier < b.softBodyIdentifier );
01181         }
01182 };
01183 
01184 
01188 void btOpenCLSoftBodySolver::prepareCollisionConstraints()
01189 {
01190         // First do a simple sort on the collision objects
01191         btAlignedObjectArray<int> numObjectsPerClothPrefixSum;
01192         btAlignedObjectArray<int> numObjectsPerCloth;
01193         numObjectsPerCloth.resize( m_softBodySet.size(), 0 );
01194         numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 );
01195 
01196 
01197         
01198         m_collisionObjectDetails.quickSort( QuickSortCompare() );
01199 
01200         if (!m_perClothCollisionObjects.size())
01201                 return;
01202 
01203         // Generating indexing for perClothCollisionObjects
01204         // First clear the previous values with the "no collision object for cloth" constant
01205         for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex )
01206         {
01207                 m_perClothCollisionObjects[clothIndex].firstObject = -1;
01208                 m_perClothCollisionObjects[clothIndex].endObject = -1;
01209         }
01210         int currentCloth = 0;
01211         int startIndex = 0;
01212         for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject )
01213         {
01214                 int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier;
01215                 if( nextCloth != currentCloth )
01216                 {       
01217                         // Changed cloth in the array
01218                         // Set the end index and the range is what we need for currentCloth
01219                         m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
01220                         m_perClothCollisionObjects[currentCloth].endObject = collisionObject;
01221                         currentCloth = nextCloth;
01222                         startIndex = collisionObject;
01223                 }
01224         }
01225 
01226         // And update last cloth        
01227         m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
01228         m_perClothCollisionObjects[currentCloth].endObject =  m_collisionObjectDetails.size();
01229         
01230 } // btOpenCLSoftBodySolver::prepareCollisionConstraints
01231 
01232 
01233 
01234 void btOpenCLSoftBodySolver::solveConstraints( float solverdt )
01235 {
01236 
01237         using Vectormath::Aos::Vector3;
01238         using Vectormath::Aos::Point3;
01239         using Vectormath::Aos::lengthSqr;
01240         using Vectormath::Aos::dot;
01241 
01242         // Prepare links
01243 //      int numLinks = m_linkData.getNumLinks();
01244 //      int numVertices = m_vertexData.getNumVertices();
01245 
01246         float kst = 1.f;
01247         float ti = 0.f;
01248 
01249 
01250         m_clPerClothDampingFactor.moveToGPU();
01251         m_clPerClothVelocityCorrectionCoefficient.moveToGPU();
01252 
01253 
01254         // Ensure data is on accelerator
01255         m_linkData.moveToAccelerator();
01256         m_vertexData.moveToAccelerator();
01257 
01258         prepareLinks(); 
01259 
01260 
01261 
01262         for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration )
01263         {
01264                 for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i )
01265                 {
01266                         int startLink = m_linkData.m_batchStartLengths[i].start;
01267                         int numLinks = m_linkData.m_batchStartLengths[i].length;
01268 
01269                         solveLinksForVelocity( startLink, numLinks, kst );
01270                 }
01271         }
01272 
01273         
01274         prepareCollisionConstraints();
01275 
01276         // Compute new positions from velocity
01277         // Also update the previous position so that our position computation is now based on the new position from the velocity solution
01278         // rather than based directly on the original positions
01279         if( m_numberOfVelocityIterations > 0 )
01280         {
01281                 updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt );
01282         } else {
01283                 updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt );
01284         }
01285 
01286         // Solve position
01287         for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration )
01288         {
01289                 for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i )
01290                 {
01291                         int startLink = m_linkData.m_batchStartLengths[i].start;
01292                         int numLinks = m_linkData.m_batchStartLengths[i].length;
01293 
01294                         solveLinksForPosition( startLink, numLinks, kst, ti );
01295                 }
01296                 
01297         } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration )
01298 
01299         
01300         // At this point assume that the force array is blank - we will overwrite it
01301         solveCollisionsAndUpdateVelocities( 1.f/solverdt );
01302 
01303 }
01304 
01305 
01307 // Kernel dispatches
01308 void btOpenCLSoftBodySolver::prepareLinks()
01309 {
01310         cl_int ciErrNum;
01311         int numLinks = m_linkData.getNumLinks();
01312         ciErrNum = clSetKernelArg(m_prepareLinksKernel,0, sizeof(int), &numLinks);
01313         ciErrNum = clSetKernelArg(m_prepareLinksKernel,1, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer);
01314         ciErrNum = clSetKernelArg(m_prepareLinksKernel,2, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer);
01315         ciErrNum = clSetKernelArg(m_prepareLinksKernel,3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer);
01316         ciErrNum = clSetKernelArg(m_prepareLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clLinksLengthRatio.m_buffer);
01317         ciErrNum = clSetKernelArg(m_prepareLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clLinksCLength.m_buffer);
01318 
01319         size_t  numWorkItems = m_defaultWorkGroupSize*((m_linkData.getNumLinks() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01320         ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_prepareLinksKernel, 1 , NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0);
01321         if( ciErrNum != CL_SUCCESS ) 
01322         {
01323                 btAssert( 0 &&  "enqueueNDRangeKernel(m_prepareLinksKernel)");
01324         }
01325 
01326 }
01327 
01328 void btOpenCLSoftBodySolver::updatePositionsFromVelocities( float solverdt )
01329 {
01330         cl_int ciErrNum;
01331         int numVerts = m_vertexData.getNumVertices();
01332         ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,0, sizeof(int), &numVerts);
01333         ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,1, sizeof(float), &solverdt);
01334         ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,2, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer);
01335         ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer);
01336         ciErrNum = clSetKernelArg(m_updatePositionsFromVelocitiesKernel,4, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer);
01337 
01338         size_t  numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01339         ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updatePositionsFromVelocitiesKernel, 1, NULL, &numWorkItems,&m_defaultWorkGroupSize,0,0,0);
01340         if( ciErrNum != CL_SUCCESS ) 
01341         {
01342                 btAssert( 0 &&  "enqueueNDRangeKernel(m_updatePositionsFromVelocitiesKernel)");
01343         }
01344 
01345 }
01346 
01347 void btOpenCLSoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti )
01348 {
01349         cl_int ciErrNum;
01350         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,0, sizeof(int), &startLink);
01351         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,1, sizeof(int), &numLinks);
01352         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,2, sizeof(float), &kst);
01353         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,3, sizeof(float), &ti);
01354         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,4, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer);
01355         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,5, sizeof(cl_mem), &m_linkData.m_clLinksMassLSC.m_buffer);
01356         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,6, sizeof(cl_mem), &m_linkData.m_clLinksRestLengthSquared.m_buffer);
01357         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,7, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer);
01358         ciErrNum = clSetKernelArg(m_solvePositionsFromLinksKernel,8, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer);
01359 
01360         size_t  numWorkItems = m_defaultWorkGroupSize*((numLinks + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01361         ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solvePositionsFromLinksKernel,1,NULL,&numWorkItems,&m_defaultWorkGroupSize,0,0,0);
01362         if( ciErrNum!= CL_SUCCESS ) 
01363         {
01364                 btAssert( 0 &&  "enqueueNDRangeKernel(m_solvePositionsFromLinksKernel)");
01365         }
01366 
01367 } // solveLinksForPosition
01368 
01369 
01370 void btOpenCLSoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst )
01371 {
01372         cl_int ciErrNum;
01373         ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 0, sizeof(int), &startLink);
01374         ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 1, sizeof(int), &numLinks);
01375         ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 2, sizeof(float), &kst);
01376         ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 3, sizeof(cl_mem), &m_linkData.m_clLinks.m_buffer);
01377         ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 4, sizeof(cl_mem), &m_linkData.m_clLinksLengthRatio.m_buffer);
01378         ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 5, sizeof(cl_mem), &m_linkData.m_clLinksCLength.m_buffer);
01379         ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 6, sizeof(cl_mem), &m_vertexData.m_clVertexInverseMass.m_buffer);
01380         ciErrNum = clSetKernelArg(m_vSolveLinksKernel, 7, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer);
01381 
01382         size_t  numWorkItems = m_defaultWorkGroupSize*((numLinks + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01383         ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_vSolveLinksKernel,1,NULL,&numWorkItems, &m_defaultWorkGroupSize,0,0,0);
01384         if( ciErrNum != CL_SUCCESS ) 
01385         {
01386                 btAssert( 0 &&  "enqueueNDRangeKernel(m_vSolveLinksKernel)");
01387         }
01388 
01389 }
01390 
01391 void btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithVelocities( float isolverdt )
01392 {
01393         cl_int ciErrNum;
01394         int numVerts = m_vertexData.getNumVertices();
01395         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel,0, sizeof(int), &numVerts);
01396         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 1, sizeof(float), &isolverdt);
01397         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 2, sizeof(cl_mem), &m_vertexData.m_clVertexPosition.m_buffer);
01398         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 3, sizeof(cl_mem), &m_vertexData.m_clVertexPreviousPosition.m_buffer);
01399         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 4, sizeof(cl_mem), &m_vertexData.m_clClothIdentifier.m_buffer);
01400         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 5, sizeof(cl_mem), &m_clPerClothVelocityCorrectionCoefficient.m_buffer);
01401         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 6, sizeof(cl_mem), &m_clPerClothDampingFactor.m_buffer);
01402         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 7, sizeof(cl_mem), &m_vertexData.m_clVertexVelocity.m_buffer);
01403         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithVelocitiesKernel, 8, sizeof(cl_mem), &m_vertexData.m_clVertexForceAccumulator.m_buffer);
01404 
01405         size_t  numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01406         ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateVelocitiesFromPositionsWithVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0);
01407         if( ciErrNum != CL_SUCCESS ) 
01408         {
01409                 btAssert( 0 &&  "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithVelocitiesKernel)");
01410         }
01411 
01412 
01413 } // updateVelocitiesFromPositionsWithVelocities
01414 
01415 void btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities( float isolverdt )
01416 {
01417         cl_int ciErrNum;
01418         int numVerts = m_vertexData.getNumVertices();
01419         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 0, sizeof(int), &numVerts);
01420         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 1, sizeof(float), &isolverdt);
01421         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer);
01422         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer);
01423         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 4, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer);
01424         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer);
01425         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 6, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer);
01426         ciErrNum = clSetKernelArg(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 7, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer);
01427 
01428         size_t  numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01429         ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_updateVelocitiesFromPositionsWithoutVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0);
01430         if( ciErrNum != CL_SUCCESS ) 
01431         {
01432                 btAssert( 0 &&  "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel)");
01433         }
01434 
01435 } // updateVelocitiesFromPositionsWithoutVelocities
01436 
01437 
01438 
01439 void btOpenCLSoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt )
01440 {
01441         // Copy kernel parameters to GPU
01442         m_vertexData.moveToAccelerator();
01443         m_clPerClothFriction.moveToGPU();
01444         m_clPerClothDampingFactor.moveToGPU();
01445         m_clPerClothCollisionObjects.moveToGPU();
01446         m_clCollisionObjectDetails.moveToGPU();
01447 
01448         cl_int ciErrNum;
01449         int numVerts = m_vertexData.getNumVertices();
01450         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 0, sizeof(int), &numVerts);
01451         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 1, sizeof(int), &isolverdt);
01452         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 2, sizeof(cl_mem),&m_vertexData.m_clClothIdentifier.m_buffer);
01453         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 3, sizeof(cl_mem),&m_vertexData.m_clVertexPreviousPosition.m_buffer);
01454         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 4, sizeof(cl_mem),&m_clPerClothFriction.m_buffer);
01455         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 5, sizeof(cl_mem),&m_clPerClothDampingFactor.m_buffer);
01456         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 6, sizeof(cl_mem),&m_clPerClothCollisionObjects.m_buffer);
01457         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 7, sizeof(cl_mem),&m_clCollisionObjectDetails.m_buffer);
01458         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 8, sizeof(cl_mem),&m_vertexData.m_clVertexForceAccumulator.m_buffer);
01459         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 9, sizeof(cl_mem),&m_vertexData.m_clVertexVelocity.m_buffer);
01460         ciErrNum = clSetKernelArg(m_solveCollisionsAndUpdateVelocitiesKernel, 10, sizeof(cl_mem),&m_vertexData.m_clVertexPosition.m_buffer);
01461 
01462         size_t  numWorkItems = m_defaultWorkGroupSize*((m_vertexData.getNumVertices() + (m_defaultWorkGroupSize-1)) / m_defaultWorkGroupSize);
01463         if (numWorkItems)
01464         {
01465                 ciErrNum = clEnqueueNDRangeKernel(m_cqCommandQue,m_solveCollisionsAndUpdateVelocitiesKernel, 1, NULL, &numWorkItems, &m_defaultWorkGroupSize,0,0,0);
01466                 if( ciErrNum != CL_SUCCESS ) 
01467                 {
01468                         btAssert( 0 &&  "enqueueNDRangeKernel(m_updateVelocitiesFromPositionsWithoutVelocitiesKernel)");
01469                 }
01470         }
01471 
01472 } // btOpenCLSoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities
01473 
01474 
01475 
01476 // End kernel dispatches
01478 
01479 
01480 void btSoftBodySolverOutputCLtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer )
01481 {
01482 
01483         btSoftBodySolver *solver = softBody->getSoftBodySolver();
01484         btAssert( solver->getSolverType() == btSoftBodySolver::CL_SOLVER || solver->getSolverType() == btSoftBodySolver::CL_SIMD_SOLVER );
01485         btOpenCLSoftBodySolver *dxSolver = static_cast< btOpenCLSoftBodySolver * >( solver );
01486 
01487         btOpenCLAcceleratedSoftBodyInterface* currentCloth = dxSolver->findSoftBodyInterface( softBody );
01488         btSoftBodyVertexDataOpenCL &vertexData( dxSolver->m_vertexData );
01489         
01490 
01491         const int firstVertex = currentCloth->getFirstVertex();
01492         const int lastVertex = firstVertex + currentCloth->getNumVertices();
01493 
01494         if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
01495         {               
01496                 const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer);                                         
01497                 float *basePointer = cpuVertexBuffer->getBasePointer();                                         
01498 
01499                 vertexData.m_clVertexPosition.copyFromGPU();
01500                 vertexData.m_clVertexNormal.copyFromGPU();
01501 
01502                 if( vertexBuffer->hasVertexPositions() )
01503                 {
01504                         const int vertexOffset = cpuVertexBuffer->getVertexOffset();
01505                         const int vertexStride = cpuVertexBuffer->getVertexStride();
01506                         float *vertexPointer = basePointer + vertexOffset;
01507 
01508                         for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
01509                         {
01510                                 Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex);
01511                                 *(vertexPointer + 0) = position.getX();
01512                                 *(vertexPointer + 1) = position.getY();
01513                                 *(vertexPointer + 2) = position.getZ();
01514                                 vertexPointer += vertexStride;
01515                         }
01516                 }
01517                 if( vertexBuffer->hasNormals() )
01518                 {
01519                         const int normalOffset = cpuVertexBuffer->getNormalOffset();
01520                         const int normalStride = cpuVertexBuffer->getNormalStride();
01521                         float *normalPointer = basePointer + normalOffset;
01522 
01523                         for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
01524                         {
01525                                 Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex);
01526                                 *(normalPointer + 0) = normal.getX();
01527                                 *(normalPointer + 1) = normal.getY();
01528                                 *(normalPointer + 2) = normal.getZ();
01529                                 normalPointer += normalStride;
01530                         }
01531                 }
01532         }
01533 
01534 } // btSoftBodySolverOutputCLtoCPU::outputToVertexBuffers
01535 
01536 
01537 
01538 cl_kernel CLFunctions::compileCLKernelFromString( const char* kernelSource, const char* kernelName, const char* additionalMacros ,const char* orgSrcFileNameForCaching)
01539 {
01540         printf("compiling kernelName: %s ",kernelName);
01541         cl_kernel kernel=0;
01542         cl_int ciErrNum;
01543         size_t program_length = strlen(kernelSource);
01544 
01545         cl_program m_cpProgram = clCreateProgramWithSource(m_cxMainContext, 1, (const char**)&kernelSource, &program_length, &ciErrNum);
01546 //      oclCHECKERROR(ciErrNum, CL_SUCCESS);
01547                 
01548     // Build the program with 'mad' Optimization option
01549 
01550         
01551 #ifdef MAC
01552         char* flags = "-cl-mad-enable -DMAC -DGUID_ARG";
01553 #else
01554         //const char* flags = "-DGUID_ARG= -fno-alias";
01555         const char* flags = "-DGUID_ARG= ";
01556 #endif
01557 
01558         char* compileFlags = new char[strlen(additionalMacros) + strlen(flags) + 5];
01559         sprintf(compileFlags, "%s %s", flags, additionalMacros);
01560     ciErrNum = clBuildProgram(m_cpProgram, 0, NULL, compileFlags, NULL, NULL);
01561     if (ciErrNum != CL_SUCCESS)
01562     {
01563                 size_t numDevices;
01564                 clGetProgramInfo( m_cpProgram, CL_PROGRAM_DEVICES, 0, 0, &numDevices );
01565                 cl_device_id *devices = new cl_device_id[numDevices];
01566                 clGetProgramInfo( m_cpProgram, CL_PROGRAM_DEVICES, numDevices, devices, &numDevices );
01567         for( int i = 0; i < 2; ++i )
01568                 {
01569                         char *build_log;
01570                         size_t ret_val_size;
01571                         clGetProgramBuildInfo(m_cpProgram, devices[i], CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
01572                         build_log = new char[ret_val_size+1];
01573                         clGetProgramBuildInfo(m_cpProgram, devices[i], CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
01574     
01575                         // to be carefully, terminate with \0
01576                         // there's no information in the reference whether the string is 0 terminated or not
01577                         build_log[ret_val_size] = '\0';
01578         
01579 
01580                         printf("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log);
01581                         delete[] build_log;
01582                 }
01583 #ifndef BT_SUPPRESS_OPENCL_ASSERTS
01584                 btAssert(0);
01585 #endif //BT_SUPPRESS_OPENCL_ASSERTS
01586                 m_kernelCompilationFailures++;
01587                 return 0;
01588     }
01589         
01590         
01591     // Create the kernel
01592     kernel = clCreateKernel(m_cpProgram, kernelName, &ciErrNum);
01593     if (ciErrNum != CL_SUCCESS)
01594     {
01595                 const char* msg = "";
01596         switch(ciErrNum)
01597         {
01598         case CL_INVALID_PROGRAM:
01599             msg = "Program is not a valid program object.";
01600             break;
01601         case CL_INVALID_PROGRAM_EXECUTABLE:
01602             msg = "There is no successfully built executable for program.";
01603             break;
01604         case CL_INVALID_KERNEL_NAME:
01605             msg = "kernel_name is not found in program.";
01606             break;
01607         case CL_INVALID_KERNEL_DEFINITION:
01608             msg = "the function definition for __kernel function given by kernel_name such as the number of arguments, the argument types are not the same for all devices for which the program executable has been built.";
01609             break;
01610         case CL_INVALID_VALUE:
01611             msg = "kernel_name is NULL.";
01612             break;
01613         case CL_OUT_OF_HOST_MEMORY:
01614             msg = "Failure to allocate resources required by the OpenCL implementation on the host.";
01615             break;
01616                 default:
01617                         {
01618                         }
01619         }
01620 
01621         printf("Error in clCreateKernel for kernel '%s', error is \"%s\", Line %u in file %s !!!\n\n", kernelName, msg, __LINE__, __FILE__);
01622 
01623 #ifndef BT_SUPPRESS_OPENCL_ASSERTS
01624                 btAssert(0);
01625 #endif //BT_SUPPRESS_OPENCL_ASSERTS
01626                 m_kernelCompilationFailures++;
01627                 return 0;
01628     }
01629 
01630         printf("ready. \n");
01631         delete [] compileFlags;
01632         if (!kernel)
01633                 m_kernelCompilationFailures++;
01634         return kernel;
01635 
01636 }
01637 
01638 void btOpenCLSoftBodySolver::predictMotion( float timeStep )
01639 {
01640         // Clear the collision shape array for the next frame
01641         // Ensure that the DX11 ones are moved off the device so they will be updated correctly
01642         m_clCollisionObjectDetails.changedOnCPU();
01643         m_clPerClothCollisionObjects.changedOnCPU();
01644         m_collisionObjectDetails.clear();       
01645 
01646         if ( m_bUpdateAnchoredNodePos )
01647         {
01648                 // In OpenCL cloth solver, if softbody node has zero inverse mass(infinite mass) or anchor attached, 
01649                 // we need to update the node position in case the node or anchor is animated externally.
01650                 // If there is no such node, we can eliminate the unnecessary CPU-to-GPU data trasferring. 
01651                 for ( int i = 0; i < m_anchorNodeInfoArray.size(); i++ )
01652                 {
01653                         const AnchorNodeInfoCL& anchorNodeInfo = m_anchorNodeInfoArray[i];
01654                         btSoftBody::Node* node = anchorNodeInfo.pNode;
01655 
01656                         using Vectormath::Aos::Point3;
01657                         Point3 pos((float)node->m_x.getX(), (float)node->m_x.getY(), (float)node->m_x.getZ());                          
01658                         m_anchorPosition[i] = pos;
01659                 }
01660 
01661                 if ( m_anchorNodeInfoArray.size() > 0 )
01662                         m_clAnchorPosition.changedOnCPU();
01663 
01664                 updateFixedVertexPositions();
01665         }
01666                 
01667         {
01668                 BT_PROFILE("applyForces");
01669                 // Apply forces that we know about to the cloths
01670                 applyForces(  timeStep * getTimeScale() );
01671         }
01672 
01673         {
01674                 BT_PROFILE("integrate");
01675                 // Itegrate motion for all soft bodies dealt with by the solver
01676                 integrate( timeStep * getTimeScale() );
01677         }
01678 
01679         {
01680                 BT_PROFILE("updateBounds");
01681                 updateBounds();
01682         }
01683         // End prediction work for solvers
01684 }
01685 
01686 static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform )
01687 {
01688         Vectormath::Aos::Transform3 outTransform;
01689         outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0)));
01690         outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1)));
01691         outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2)));
01692         outTransform.setCol(3, toVector3(transform.getOrigin()));
01693         return outTransform;    
01694 }
01695 
01696 void btOpenCLAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound )
01697 {
01698         float scalarMargin = (float)getSoftBody()->getCollisionShape()->getMargin();
01699         btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin );
01700         m_softBody->m_bounds[0] = lowerBound - vectorMargin;
01701         m_softBody->m_bounds[1] = upperBound + vectorMargin;
01702 }  // btOpenCLSoftBodySolver::btDX11AcceleratedSoftBodyInterface::updateBounds
01703 
01704 void btOpenCLSoftBodySolver::processCollision( btSoftBody*, btSoftBody* )
01705 {
01706 
01707 }
01708 
01709 // Add the collision object to the set to deal with for a particular soft body
01710 void btOpenCLSoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObject )
01711 {
01712         int softBodyIndex = findSoftBodyIndex( softBody );
01713 
01714         if( softBodyIndex >= 0 )
01715         {
01716                 const btCollisionShape *collisionShape = collisionObject->getCollisionShape();
01717                 float friction = collisionObject->getCollisionObject()->getFriction();
01718                 int shapeType = collisionShape->getShapeType();
01719                 if( shapeType == CAPSULE_SHAPE_PROXYTYPE )
01720                 {
01721                         // Add to the list of expected collision objects
01722                         CollisionShapeDescription newCollisionShapeDescription;
01723                         newCollisionShapeDescription.softBodyIdentifier = softBodyIndex;
01724                         newCollisionShapeDescription.collisionShapeType = shapeType;
01725                         // TODO: May need to transpose this matrix either here or in HLSL
01726                         newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform());
01727                         const btCapsuleShape *capsule = static_cast<const btCapsuleShape*>( collisionShape );
01728                         newCollisionShapeDescription.radius = capsule->getRadius();
01729                         newCollisionShapeDescription.halfHeight = capsule->getHalfHeight();
01730                         newCollisionShapeDescription.margin = capsule->getMargin();
01731                         newCollisionShapeDescription.upAxis = capsule->getUpAxis();
01732                         newCollisionShapeDescription.friction = friction;
01733                         const btRigidBody* body = static_cast< const btRigidBody* >( collisionObject->getCollisionObject() );
01734                         newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity());
01735                         newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity());
01736                         m_collisionObjectDetails.push_back( newCollisionShapeDescription );
01737 
01738                 }               
01739                 else {
01740 #ifdef _DEBUG
01741                         printf("Unsupported collision shape type\n");
01742 #endif
01743                         //btAssert(0 && "Unsupported collision shape type\n");
01744                 }
01745         } else {
01746                 btAssert(0 && "Unknown soft body");
01747         }
01748 } // btOpenCLSoftBodySolver::processCollision
01749 
01750 
01751 
01752 
01753 
01754 btOpenCLAcceleratedSoftBodyInterface* btOpenCLSoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody )
01755 {
01756         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
01757         {
01758                 btOpenCLAcceleratedSoftBodyInterface* softBodyInterface = m_softBodySet[softBodyIndex];
01759                 if( softBodyInterface->getSoftBody() == softBody )
01760                         return softBodyInterface;
01761         }
01762         return 0;
01763 }
01764 
01765 
01766 int btOpenCLSoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody )
01767 {
01768         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
01769         {
01770                 btOpenCLAcceleratedSoftBodyInterface* softBodyInterface = m_softBodySet[softBodyIndex];
01771                 if( softBodyInterface->getSoftBody() == softBody )
01772                         return softBodyIndex;
01773         }
01774         return 1;
01775 }
01776 
01777 bool btOpenCLSoftBodySolver::checkInitialized()
01778 {
01779         if( !m_shadersInitialized )
01780                 if( buildShaders() )
01781                         m_shadersInitialized = true;
01782 
01783         return m_shadersInitialized;
01784 }
01785 
01786 bool btOpenCLSoftBodySolver::buildShaders()
01787 {
01788         if( m_shadersInitialized )
01789                 return true;
01790 
01791         const char* additionalMacros="";
01792 
01793         // Ensure current kernels are released first
01794         releaseKernels();
01795         
01796         m_currentCLFunctions->clearKernelCompilationFailures();
01797 
01798         m_prepareLinksKernel = m_currentCLFunctions->compileCLKernelFromString( PrepareLinksCLString, "PrepareLinksKernel",additionalMacros,"OpenCLC10/PrepareLinks.cl" );
01799         m_updatePositionsFromVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsFromVelocitiesCLString, "UpdatePositionsFromVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdatePositionsFromVelocities.cl");
01800         m_solvePositionsFromLinksKernel = m_currentCLFunctions->compileCLKernelFromString( SolvePositionsCLString, "SolvePositionsFromLinksKernel",additionalMacros,"OpenCLC10/SolvePositions.cl" );
01801         m_vSolveLinksKernel = m_currentCLFunctions->compileCLKernelFromString( VSolveLinksCLString, "VSolveLinksKernel" ,additionalMacros,"OpenCLC10/VSolveLinks.cl");
01802         m_updateVelocitiesFromPositionsWithVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNodesCLString, "updateVelocitiesFromPositionsWithVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdateNodes.cl");
01803         m_updateVelocitiesFromPositionsWithoutVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdatePositionsCLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel" ,additionalMacros,"OpenCLC10/UpdatePositions.cl");
01804         m_solveCollisionsAndUpdateVelocitiesKernel = m_currentCLFunctions->compileCLKernelFromString( SolveCollisionsAndUpdateVelocitiesCLString, "SolveCollisionsAndUpdateVelocitiesKernel" ,additionalMacros,"OpenCLC10/SolveCollisionsAndUpdateVelocities.cl");
01805         m_integrateKernel = m_currentCLFunctions->compileCLKernelFromString( IntegrateCLString, "IntegrateKernel" ,additionalMacros,"OpenCLC10/Integrate.cl");
01806         m_applyForcesKernel = m_currentCLFunctions->compileCLKernelFromString( ApplyForcesCLString, "ApplyForcesKernel" ,additionalMacros,"OpenCLC10/ApplyForces.cl");
01807         m_updateFixedVertexPositionsKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateFixedVertexPositionsCLString, "UpdateFixedVertexPositions" , additionalMacros, "OpenCLC10/UpdateFixedVertexPositions.cl");
01808 
01809         // TODO: Rename to UpdateSoftBodies
01810         m_resetNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "ResetNormalsAndAreasKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl");
01811         m_normalizeNormalsAndAreasKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "NormalizeNormalsAndAreasKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl");
01812         m_updateSoftBodiesKernel = m_currentCLFunctions->compileCLKernelFromString( UpdateNormalsCLString, "UpdateSoftBodiesKernel" ,additionalMacros,"OpenCLC10/UpdateNormals.cl");
01813 
01814 
01815         if( m_currentCLFunctions->getKernelCompilationFailures()==0 )
01816                 m_shadersInitialized = true;
01817 
01818         return m_shadersInitialized;
01819 }
01820