00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
00018 #include "vectormath/vmInclude.h"
00019 #include <stdio.h>
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
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
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
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
00264 btAlignedObjectArray< int > batchValues;
00265 batchValues.resize( numLinks, 0 );
00266
00267
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
00281
00282
00283 btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists;
00284 vertexConnectedColourLists.resize(numVertices);
00285
00286
00287
00288
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
00297 btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] );
00298 btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] );
00299
00300
00301 int colour = 0;
00302 while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() )
00303 ++colour;
00304
00305
00306
00307
00308 colourListVertex0.push_back(colour);
00309 colourListVertex1.push_back(colour);
00310 batchValues[linkIndex] = colour;
00311 }
00312
00313
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
00341
00342
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
00357 for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
00358 {
00359
00360
00361
00362
00363 int linkLocation = m_linkAddresses[linkIndex];
00364
00365
00366
00367
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
00382 m_linkAddresses[linkIndex] = newLocation;
00383 }
00384
00385
00386 }
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
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
00468 btAlignedObjectArray< int > batchValues;
00469 batchValues.resize( numTriangles );
00470
00471
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
00489
00490
00491 btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists;
00492 vertexConnectedColourLists.resize(numVertices);
00493
00494
00495
00496
00497
00498
00499 for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
00500 {
00501
00502
00503
00504
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
00512 btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] );
00513 btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] );
00514 btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] );
00515
00516
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
00526
00527
00528 colourListVertex0.push_back(colour);
00529 colourListVertex1.push_back(colour);
00530 colourListVertex2.push_back(colour);
00531
00532 batchValues[triangleIndex] = colour;
00533 }
00534
00535
00536
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
00562
00563
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
00573 for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
00574 {
00575
00576
00577
00578
00579 int triangleLocation = m_triangleAddresses[triangleIndex];
00580
00581
00582
00583
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
00593 m_triangleAddresses[triangleIndex] = newLocation;
00594 }
00595 }
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
00628
00629
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
00682 m_vertexData.moveFromAccelerator(!bMove);
00683
00684
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
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 }
00710
00711 void btOpenCLSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate )
00712 {
00713 if( forceUpdate || m_softBodySet.size() != softBodies.size() )
00714 {
00715
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
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
00742 m_perClothFriction.push_back(softBody->m_cfg.kDF);
00743 m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) );
00744
00745
00746
00747 int firstVertex = getVertexData().getNumVertices();
00748 int numVertices = softBody->m_nodes.size();
00749 int maxVertices = numVertices;
00750
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
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
00765
00766
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
00777
00778 for( int triangle = 0; triangle < numTriangles; ++triangle )
00779 {
00780
00781
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
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
00797
00798
00799 getLinkData().createLinks( numLinks );
00800
00801
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
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
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
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
00876 setNumberOfPositionIterations(maxPiterations);
00877 setNumberOfVelocityIterations(maxViterations);
00878
00879
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
00890 m_linkData.generateBatches();
00891 m_triangleData.generateBatches();
00892
00893
00894 buildShaders();
00895 }
00896 }
00897
00898
00899 btSoftBodyLinkData &btOpenCLSoftBodySolver::getLinkData()
00900 {
00901
00902 return m_linkData;
00903 }
00904
00905 btSoftBodyVertexData &btOpenCLSoftBodySolver::getVertexData()
00906 {
00907
00908 return m_vertexData;
00909 }
00910
00911 btSoftBodyTriangleData &btOpenCLSoftBodySolver::getTriangleData()
00912 {
00913
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);
00921 ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 1, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexNormal.m_buffer);
00922 ciErrNum = clSetKernelArg(m_resetNormalsAndAreasKernel, 2, sizeof(cl_mem), (void*)&m_vertexData.m_clVertexArea.m_buffer);
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
00985
00986
00987 m_vertexData.moveToAccelerator();
00988 m_triangleData.moveToAccelerator();
00989
00990 resetNormalsAndAreas( numVertices );
00991
00992
00993
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 }
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
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
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
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 }
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
01154
01155
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
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
01204
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
01218
01219 m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
01220 m_perClothCollisionObjects[currentCloth].endObject = collisionObject;
01221 currentCloth = nextCloth;
01222 startIndex = collisionObject;
01223 }
01224 }
01225
01226
01227 m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
01228 m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size();
01229
01230 }
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
01243
01244
01245
01246 float kst = 1.f;
01247 float ti = 0.f;
01248
01249
01250 m_clPerClothDampingFactor.moveToGPU();
01251 m_clPerClothVelocityCorrectionCoefficient.moveToGPU();
01252
01253
01254
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
01277
01278
01279 if( m_numberOfVelocityIterations > 0 )
01280 {
01281 updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt );
01282 } else {
01283 updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt );
01284 }
01285
01286
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 }
01298
01299
01300
01301 solveCollisionsAndUpdateVelocities( 1.f/solverdt );
01302
01303 }
01304
01305
01307
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 }
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 }
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 }
01436
01437
01438
01439 void btOpenCLSoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt )
01440 {
01441
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 }
01473
01474
01475
01476
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 }
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
01547
01548
01549
01550
01551 #ifdef MAC
01552 char* flags = "-cl-mad-enable -DMAC -DGUID_ARG";
01553 #else
01554
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
01576
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
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
01641
01642 m_clCollisionObjectDetails.changedOnCPU();
01643 m_clPerClothCollisionObjects.changedOnCPU();
01644 m_collisionObjectDetails.clear();
01645
01646 if ( m_bUpdateAnchoredNodePos )
01647 {
01648
01649
01650
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
01670 applyForces( timeStep * getTimeScale() );
01671 }
01672
01673 {
01674 BT_PROFILE("integrate");
01675
01676 integrate( timeStep * getTimeScale() );
01677 }
01678
01679 {
01680 BT_PROFILE("updateBounds");
01681 updateBounds();
01682 }
01683
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 }
01703
01704 void btOpenCLSoftBodySolver::processCollision( btSoftBody*, btSoftBody* )
01705 {
01706
01707 }
01708
01709
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
01722 CollisionShapeDescription newCollisionShapeDescription;
01723 newCollisionShapeDescription.softBodyIdentifier = softBodyIndex;
01724 newCollisionShapeDescription.collisionShapeType = shapeType;
01725
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
01744 }
01745 } else {
01746 btAssert(0 && "Unknown soft body");
01747 }
01748 }
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
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
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