btSoftBodySolver_DX11.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 #include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
00017 #include "vectormath/vmInclude.h"
00018 
00019 #include "btSoftBodySolver_DX11.h"
00020 #include "btSoftBodySolverVertexBuffer_DX11.h"
00021 #include "BulletSoftBody/btSoftBody.h"
00022 #include "BulletCollision/CollisionShapes/btCapsuleShape.h"
00023 #include <stdio.h> //printf
00024 #define MSTRINGIFY(A) #A
00025 static char* PrepareLinksHLSLString = 
00026 #include "HLSL/PrepareLinks.hlsl"
00027 static char* UpdatePositionsFromVelocitiesHLSLString = 
00028 #include "HLSL/UpdatePositionsFromVelocities.hlsl"
00029 static char* SolvePositionsHLSLString = 
00030 #include "HLSL/SolvePositions.hlsl"
00031 static char* UpdateNodesHLSLString = 
00032 #include "HLSL/UpdateNodes.hlsl"
00033 static char* UpdatePositionsHLSLString = 
00034 #include "HLSL/UpdatePositions.hlsl"
00035 static char* UpdateConstantsHLSLString = 
00036 #include "HLSL/UpdateConstants.hlsl"
00037 static char* IntegrateHLSLString = 
00038 #include "HLSL/Integrate.hlsl"
00039 static char* ApplyForcesHLSLString = 
00040 #include "HLSL/ApplyForces.hlsl"
00041 static char* UpdateNormalsHLSLString = 
00042 #include "HLSL/UpdateNormals.hlsl"
00043 static char* OutputToVertexArrayHLSLString = 
00044 #include "HLSL/OutputToVertexArray.hlsl"
00045 static char* VSolveLinksHLSLString = 
00046 #include "HLSL/VSolveLinks.hlsl"
00047 static char* ComputeBoundsHLSLString = 
00048 #include "HLSL/ComputeBounds.hlsl"
00049 static char* SolveCollisionsAndUpdateVelocitiesHLSLString =
00050 #include "HLSL/SolveCollisionsAndUpdateVelocities.hlsl"
00051 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
00052 
00053 btSoftBodyLinkDataDX11::btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : 
00054                 m_dx11Links( d3dDevice, d3dDeviceContext, &m_links, false ),
00055                 m_dx11LinkStrength( d3dDevice, d3dDeviceContext, &m_linkStrength, false ),
00056                 m_dx11LinksMassLSC( d3dDevice, d3dDeviceContext, &m_linksMassLSC, false ),
00057                 m_dx11LinksRestLengthSquared( d3dDevice, d3dDeviceContext, &m_linksRestLengthSquared, false ),
00058                 m_dx11LinksCLength( d3dDevice, d3dDeviceContext, &m_linksCLength, false ),
00059                 m_dx11LinksLengthRatio( d3dDevice, d3dDeviceContext, &m_linksLengthRatio, false ),
00060                 m_dx11LinksRestLength( d3dDevice, d3dDeviceContext, &m_linksRestLength, false ),
00061                 m_dx11LinksMaterialLinearStiffnessCoefficient( d3dDevice, d3dDeviceContext, &m_linksMaterialLinearStiffnessCoefficient, false )
00062 {
00063         m_d3dDevice = d3dDevice;
00064         m_d3dDeviceContext = d3dDeviceContext;
00065 }
00066 
00067 btSoftBodyLinkDataDX11::~btSoftBodyLinkDataDX11()
00068 {
00069 }
00070 
00071 static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec )
00072 {
00073         Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() );
00074         return outVec;
00075 }
00076 
00077 void btSoftBodyLinkDataDX11::createLinks( int numLinks )
00078 {
00079         int previousSize = m_links.size();
00080         int newSize = previousSize + numLinks;
00081 
00082         btSoftBodyLinkData::createLinks( numLinks );
00083 
00084         // Resize the link addresses array as well
00085         m_linkAddresses.resize( newSize );
00086 }
00087 
00088 void btSoftBodyLinkDataDX11::setLinkAt( const btSoftBodyLinkData::LinkDescription &link, int linkIndex )
00089 {
00090         btSoftBodyLinkData::setLinkAt( link, linkIndex );
00091 
00092         // Set the link index correctly for initialisation
00093         m_linkAddresses[linkIndex] = linkIndex;
00094 }
00095 
00096 bool btSoftBodyLinkDataDX11::onAccelerator()
00097 {
00098         return m_onGPU;
00099 }
00100 
00101 bool btSoftBodyLinkDataDX11::moveToAccelerator()
00102 {
00103         bool success = true;
00104         success = success && m_dx11Links.moveToGPU();
00105         success = success && m_dx11LinkStrength.moveToGPU();
00106         success = success && m_dx11LinksMassLSC.moveToGPU();
00107         success = success && m_dx11LinksRestLengthSquared.moveToGPU();
00108         success = success && m_dx11LinksCLength.moveToGPU();
00109         success = success && m_dx11LinksLengthRatio.moveToGPU();
00110         success = success && m_dx11LinksRestLength.moveToGPU();
00111         success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveToGPU();
00112 
00113         if( success )
00114                 m_onGPU = true;
00115 
00116         return success;
00117 }
00118 
00119 bool btSoftBodyLinkDataDX11::moveFromAccelerator()
00120 {
00121         bool success = true;
00122         success = success && m_dx11Links.moveFromGPU();
00123         success = success && m_dx11LinkStrength.moveFromGPU();
00124         success = success && m_dx11LinksMassLSC.moveFromGPU();
00125         success = success && m_dx11LinksRestLengthSquared.moveFromGPU();
00126         success = success && m_dx11LinksCLength.moveFromGPU();
00127         success = success && m_dx11LinksLengthRatio.moveFromGPU();
00128         success = success && m_dx11LinksRestLength.moveFromGPU();
00129         success = success && m_dx11LinksMaterialLinearStiffnessCoefficient.moveFromGPU();
00130 
00131         if( success )
00132                 m_onGPU = false;
00133 
00134         return success;
00135 }
00136 
00137 void btSoftBodyLinkDataDX11::generateBatches()
00138 {
00139         int numLinks = getNumLinks();
00140 
00141         // Do the graph colouring here temporarily
00142         btAlignedObjectArray< int > batchValues;
00143         batchValues.resize( numLinks, 0 );
00144 
00145         // Find the maximum vertex value internally for now
00146         int maxVertex = 0;
00147         for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
00148         {
00149                 int vertex0 = getVertexPair(linkIndex).vertex0;
00150                 int vertex1 = getVertexPair(linkIndex).vertex1;
00151                 if( vertex0 > maxVertex )
00152                         maxVertex = vertex0;
00153                 if( vertex1 > maxVertex )
00154                         maxVertex = vertex1;
00155         }
00156         int numVertices = maxVertex + 1;
00157 
00158         // Set of lists, one for each node, specifying which colours are connected
00159         // to that node.
00160         // No two edges into a node can share a colour.
00161         btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists;
00162         vertexConnectedColourLists.resize(numVertices);
00163 
00164 
00165 
00166         // Simple algorithm that chooses the lowest batch number
00167         // that none of the links attached to either of the connected 
00168         // nodes is in
00169         for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
00170         {                               
00171                 int linkLocation = m_linkAddresses[linkIndex];
00172 
00173                 int vertex0 = getVertexPair(linkLocation).vertex0;
00174                 int vertex1 = getVertexPair(linkLocation).vertex1;
00175 
00176                 // Get the two node colour lists
00177                 btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] );
00178                 btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] );
00179 
00180                 // Choose the minimum colour that is in neither list
00181                 int colour = 0;
00182                 while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size()  )
00183                         ++colour;
00184                 // i should now be the minimum colour in neither list
00185                 // Add to the two lists so that future edges don't share
00186                 // And store the colour against this edge
00187 
00188                 colourListVertex0.push_back(colour);
00189                 colourListVertex1.push_back(colour);
00190                 batchValues[linkIndex] = colour;
00191         }
00192 
00193         // Check the colour counts
00194         btAlignedObjectArray< int > batchCounts;
00195         for( int i = 0; i < numLinks; ++i )
00196         {
00197                 int batch = batchValues[i];
00198                 if( batch >= batchCounts.size() )
00199                         batchCounts.push_back(1);
00200                 else
00201                         ++(batchCounts[batch]);
00202         }
00203 
00204         m_batchStartLengths.resize(batchCounts.size());
00205         if( m_batchStartLengths.size() > 0 )
00206         {
00207                 m_batchStartLengths[0] = BatchPair( 0, 0 );
00208 
00209                 int sum = 0;
00210                 for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex )
00211                 {
00212                         m_batchStartLengths[batchIndex].start = sum;
00213                         m_batchStartLengths[batchIndex].length = batchCounts[batchIndex];
00214                         sum += batchCounts[batchIndex];
00215                 }
00216         }
00217 
00219         // Sort data based on batches
00220 
00221         // Create source arrays by copying originals
00222         btAlignedObjectArray<btSoftBodyLinkData::LinkNodePair>                          m_links_Backup(m_links);
00223         btAlignedObjectArray<float>                                                                                     m_linkStrength_Backup(m_linkStrength);
00224         btAlignedObjectArray<float>                                                                                     m_linksMassLSC_Backup(m_linksMassLSC);
00225         btAlignedObjectArray<float>                                                                                     m_linksRestLengthSquared_Backup(m_linksRestLengthSquared);
00226         btAlignedObjectArray<Vectormath::Aos::Vector3>                                          m_linksCLength_Backup(m_linksCLength);
00227         btAlignedObjectArray<float>                                                                                     m_linksLengthRatio_Backup(m_linksLengthRatio);
00228         btAlignedObjectArray<float>                                                                                     m_linksRestLength_Backup(m_linksRestLength);
00229         btAlignedObjectArray<float>                                                                                     m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient);
00230 
00231 
00232         for( int batch = 0; batch < batchCounts.size(); ++batch )
00233                 batchCounts[batch] = 0;
00234 
00235         // Do sort as single pass into destination arrays       
00236         for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
00237         {
00238                 // To maintain locations run off the original link locations rather than the current position.
00239                 // It's not cache efficient, but as we run this rarely that should not matter.
00240                 // It's faster than searching the link location array for the current location and then updating it.
00241                 // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
00242                 int linkLocation = m_linkAddresses[linkIndex];
00243 
00244                 // Obtain batch and calculate target location for the
00245                 // next element in that batch, incrementing the batch counter
00246                 // afterwards
00247                 int batch = batchValues[linkIndex];
00248                 int newLocation = m_batchStartLengths[batch].start + batchCounts[batch];
00249 
00250                 batchCounts[batch] = batchCounts[batch] + 1;
00251                 m_links[newLocation] = m_links_Backup[linkLocation];
00252 #if 1
00253                 m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation];
00254                 m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation];
00255                 m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation];
00256                 m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation];
00257                 m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation];
00258                 m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation];
00259 #endif
00260                 // Update the locations array to account for the moved entry
00261                 m_linkAddresses[linkIndex] = newLocation;
00262         }
00263 } // void btSoftBodyLinkDataDX11::generateBatches()
00264 
00265 
00266 
00267 btSoftBodyVertexDataDX11::btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : 
00268         m_dx11ClothIdentifier( d3dDevice, d3dDeviceContext, &m_clothIdentifier, false ),
00269         m_dx11VertexPosition( d3dDevice, d3dDeviceContext, &m_vertexPosition, false ),
00270         m_dx11VertexPreviousPosition( d3dDevice, d3dDeviceContext, &m_vertexPreviousPosition, false ),
00271         m_dx11VertexVelocity( d3dDevice, d3dDeviceContext, &m_vertexVelocity, false ),
00272         m_dx11VertexForceAccumulator( d3dDevice, d3dDeviceContext, &m_vertexForceAccumulator, false ),
00273         m_dx11VertexNormal( d3dDevice, d3dDeviceContext, &m_vertexNormal, false ),
00274         m_dx11VertexInverseMass( d3dDevice, d3dDeviceContext, &m_vertexInverseMass, false ),
00275         m_dx11VertexArea( d3dDevice, d3dDeviceContext, &m_vertexArea, false ),
00276         m_dx11VertexTriangleCount( d3dDevice, d3dDeviceContext, &m_vertexTriangleCount, false )
00277 {
00278         m_d3dDevice = d3dDevice;
00279         m_d3dDeviceContext = d3dDeviceContext;
00280 }
00281 
00282 btSoftBodyVertexDataDX11::~btSoftBodyVertexDataDX11()
00283 {
00284 
00285 }
00286 
00287 bool btSoftBodyVertexDataDX11::onAccelerator()
00288 {
00289         return m_onGPU;
00290 }
00291 
00292 bool btSoftBodyVertexDataDX11::moveToAccelerator()
00293 {
00294         bool success = true;
00295         success = success && m_dx11ClothIdentifier.moveToGPU();
00296         success = success && m_dx11VertexPosition.moveToGPU();
00297         success = success && m_dx11VertexPreviousPosition.moveToGPU();
00298         success = success && m_dx11VertexVelocity.moveToGPU();
00299         success = success && m_dx11VertexForceAccumulator.moveToGPU();
00300         success = success && m_dx11VertexNormal.moveToGPU();
00301         success = success && m_dx11VertexInverseMass.moveToGPU();
00302         success = success && m_dx11VertexArea.moveToGPU();
00303         success = success && m_dx11VertexTriangleCount.moveToGPU();
00304 
00305         if( success )
00306                 m_onGPU = true;
00307 
00308         return success;
00309 }
00310 
00311 bool btSoftBodyVertexDataDX11::moveFromAccelerator(bool bCopy, bool bCopyMinimum)
00312 {
00313         bool success = true;
00314 
00315         if (!bCopy)
00316         {
00317                 success = success && m_dx11ClothIdentifier.moveFromGPU();
00318                 success = success && m_dx11VertexPosition.moveFromGPU();
00319                 success = success && m_dx11VertexPreviousPosition.moveFromGPU();
00320                 success = success && m_dx11VertexVelocity.moveFromGPU();
00321                 success = success && m_dx11VertexForceAccumulator.moveFromGPU();
00322                 success = success && m_dx11VertexNormal.moveFromGPU();
00323                 success = success && m_dx11VertexInverseMass.moveFromGPU();
00324                 success = success && m_dx11VertexArea.moveFromGPU();
00325                 success = success && m_dx11VertexTriangleCount.moveFromGPU();
00326         }
00327         else
00328         {
00329                 if (bCopyMinimum)
00330                 {
00331                         success = success && m_dx11VertexPosition.copyFromGPU();
00332                         success = success && m_dx11VertexNormal.copyFromGPU();
00333                 }
00334                 else
00335                 {
00336                         success = success && m_dx11ClothIdentifier.copyFromGPU();
00337                         success = success && m_dx11VertexPosition.copyFromGPU();
00338                         success = success && m_dx11VertexPreviousPosition.copyFromGPU();
00339                         success = success && m_dx11VertexVelocity.copyFromGPU();
00340                         success = success && m_dx11VertexForceAccumulator.copyFromGPU();
00341                         success = success && m_dx11VertexNormal.copyFromGPU();
00342                         success = success && m_dx11VertexInverseMass.copyFromGPU();
00343                         success = success && m_dx11VertexArea.copyFromGPU();
00344                         success = success && m_dx11VertexTriangleCount.copyFromGPU();
00345                 }
00346         }
00347 
00348         if( success )
00349                 m_onGPU = true;
00350 
00351         return success;
00352 }
00353 
00354 
00355 btSoftBodyTriangleDataDX11::btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) : 
00356         m_dx11VertexIndices( d3dDevice, d3dDeviceContext, &m_vertexIndices, false ),
00357         m_dx11Area( d3dDevice, d3dDeviceContext, &m_area, false ),
00358         m_dx11Normal( d3dDevice, d3dDeviceContext, &m_normal, false )
00359 {
00360         m_d3dDevice = d3dDevice;
00361         m_d3dDeviceContext = d3dDeviceContext;
00362 }
00363 
00364 btSoftBodyTriangleDataDX11::~btSoftBodyTriangleDataDX11()
00365 {
00366 
00367 }
00368 
00369 
00371 void btSoftBodyTriangleDataDX11::createTriangles( int numTriangles )
00372 {
00373         int previousSize = getNumTriangles();
00374         int newSize = previousSize + numTriangles;
00375 
00376         btSoftBodyTriangleData::createTriangles( numTriangles );
00377 
00378         // Resize the link addresses array as well
00379         m_triangleAddresses.resize( newSize );
00380 }
00381 
00383 void btSoftBodyTriangleDataDX11::setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex )
00384 {
00385         btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex );
00386 
00387         m_triangleAddresses[triangleIndex] = triangleIndex;
00388 }
00389 
00390 bool btSoftBodyTriangleDataDX11::onAccelerator()
00391 {
00392         return m_onGPU;
00393 }
00394 
00395 bool btSoftBodyTriangleDataDX11::moveToAccelerator()
00396 {
00397         bool success = true;
00398         success = success && m_dx11VertexIndices.moveToGPU();
00399         success = success && m_dx11Area.moveToGPU();
00400         success = success && m_dx11Normal.moveToGPU();
00401 
00402         if( success )
00403                 m_onGPU = true;
00404 
00405         return success;
00406 }
00407 
00408 bool btSoftBodyTriangleDataDX11::moveFromAccelerator()
00409 {
00410         bool success = true;
00411         success = success && m_dx11VertexIndices.moveFromGPU();
00412         success = success && m_dx11Area.moveFromGPU();
00413         success = success && m_dx11Normal.moveFromGPU();
00414 
00415         if( success )
00416                 m_onGPU = true;
00417 
00418         return success;
00419 }
00420 
00427 void btSoftBodyTriangleDataDX11::generateBatches()
00428 {
00429         int numTriangles = getNumTriangles();
00430         if( numTriangles == 0 )
00431                 return;
00432 
00433         // Do the graph colouring here temporarily
00434         btAlignedObjectArray< int > batchValues;
00435         batchValues.resize( numTriangles );
00436 
00437         // Find the maximum vertex value internally for now
00438         int maxVertex = 0;
00439         for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
00440         {
00441                 int vertex0 = getVertexSet(triangleIndex).vertex0;
00442                 int vertex1 = getVertexSet(triangleIndex).vertex1;
00443                 int vertex2 = getVertexSet(triangleIndex).vertex2;
00444                 
00445                 if( vertex0 > maxVertex )
00446                         maxVertex = vertex0;
00447                 if( vertex1 > maxVertex )
00448                         maxVertex = vertex1;
00449                 if( vertex2 > maxVertex )
00450                         maxVertex = vertex2;
00451         }
00452         int numVertices = maxVertex + 1;
00453 
00454         // Set of lists, one for each node, specifying which colours are connected
00455         // to that node.
00456         // No two edges into a node can share a colour.
00457         btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists;
00458         vertexConnectedColourLists.resize(numVertices);
00459 
00460 
00461         //std::cout << "\n";
00462         // Simple algorithm that chooses the lowest batch number
00463         // that none of the faces attached to either of the connected 
00464         // nodes is in
00465         for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
00466         {
00467                 // To maintain locations run off the original link locations rather than the current position.
00468                 // It's not cache efficient, but as we run this rarely that should not matter.
00469                 // It's faster than searching the link location array for the current location and then updating it.
00470                 // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
00471                 int triangleLocation = m_triangleAddresses[triangleIndex];
00472 
00473                 int vertex0 = getVertexSet(triangleLocation).vertex0;
00474                 int vertex1 = getVertexSet(triangleLocation).vertex1;
00475                 int vertex2 = getVertexSet(triangleLocation).vertex2;
00476 
00477                 // Get the three node colour lists
00478                 btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] );
00479                 btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] );
00480                 btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] );
00481 
00482                 // Choose the minimum colour that is in none of the lists
00483                 int colour = 0;
00484                 while( 
00485                         colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || 
00486                         colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ||
00487                         colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() )
00488                 {
00489                         ++colour;
00490                 }
00491                 // i should now be the minimum colour in neither list
00492                 // Add to the three lists so that future edges don't share
00493                 // And store the colour against this face
00494                 colourListVertex0.push_back(colour);
00495                 colourListVertex1.push_back(colour);
00496                 colourListVertex2.push_back(colour);
00497 
00498                 batchValues[triangleIndex] = colour;
00499         }
00500 
00501 
00502         // Check the colour counts
00503         btAlignedObjectArray< int > batchCounts;
00504         for( int i = 0; i < numTriangles; ++i )
00505         {
00506                 int batch = batchValues[i];
00507                 if( batch >= batchCounts.size() )
00508                         batchCounts.push_back(1);
00509                 else
00510                         ++(batchCounts[batch]);
00511         }
00512 
00513 
00514         m_batchStartLengths.resize(batchCounts.size());
00515         m_batchStartLengths[0] = BatchPair( 0, 0 );
00516 
00517 
00518         int sum = 0;
00519         for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex )
00520         {
00521                 m_batchStartLengths[batchIndex].start = sum;
00522                 m_batchStartLengths[batchIndex].length = batchCounts[batchIndex];
00523                 sum += batchCounts[batchIndex];
00524         }
00525         
00527         // Sort data based on batches
00528         
00529         // Create source arrays by copying originals
00530         btAlignedObjectArray<btSoftBodyTriangleData::TriangleNodeSet>                                                   m_vertexIndices_Backup(m_vertexIndices);
00531         btAlignedObjectArray<float>                                                                             m_area_Backup(m_area);
00532         btAlignedObjectArray<Vectormath::Aos::Vector3>                                  m_normal_Backup(m_normal);
00533 
00534 
00535         for( int batch = 0; batch < batchCounts.size(); ++batch )
00536                 batchCounts[batch] = 0;
00537 
00538         // Do sort as single pass into destination arrays       
00539         for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
00540         {
00541                 // To maintain locations run off the original link locations rather than the current position.
00542                 // It's not cache efficient, but as we run this rarely that should not matter.
00543                 // It's faster than searching the link location array for the current location and then updating it.
00544                 // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
00545                 int triangleLocation = m_triangleAddresses[triangleIndex];
00546 
00547                 // Obtain batch and calculate target location for the
00548                 // next element in that batch, incrementing the batch counter
00549                 // afterwards
00550                 int batch = batchValues[triangleIndex];
00551                 int newLocation = m_batchStartLengths[batch].start + batchCounts[batch];
00552 
00553                 batchCounts[batch] = batchCounts[batch] + 1;
00554                 m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation];
00555                 m_area[newLocation] = m_area_Backup[triangleLocation];
00556                 m_normal[newLocation] = m_normal_Backup[triangleLocation];
00557 
00558                 // Update the locations array to account for the moved entry
00559                 m_triangleAddresses[triangleIndex] = newLocation;
00560         }
00561 } // btSoftBodyTriangleDataDX11::generateBatches
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 btDX11SoftBodySolver::btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory) :
00575         m_dx11Device( dx11Device ),
00576         m_dx11Context( dx11Context ),
00577         dxFunctions( m_dx11Device, m_dx11Context, dx11CompileFromMemory ),
00578         m_linkData(m_dx11Device, m_dx11Context),
00579         m_vertexData(m_dx11Device, m_dx11Context),
00580         m_triangleData(m_dx11Device, m_dx11Context),
00581         m_dx11PerClothAcceleration( m_dx11Device, m_dx11Context, &m_perClothAcceleration, true ),
00582         m_dx11PerClothWindVelocity( m_dx11Device, m_dx11Context, &m_perClothWindVelocity, true ),
00583         m_dx11PerClothDampingFactor( m_dx11Device, m_dx11Context, &m_perClothDampingFactor, true ),
00584         m_dx11PerClothVelocityCorrectionCoefficient( m_dx11Device, m_dx11Context, &m_perClothVelocityCorrectionCoefficient, true ),
00585         m_dx11PerClothLiftFactor( m_dx11Device, m_dx11Context, &m_perClothLiftFactor, true ),
00586         m_dx11PerClothDragFactor( m_dx11Device, m_dx11Context, &m_perClothDragFactor, true ),
00587         m_dx11PerClothMediumDensity( m_dx11Device, m_dx11Context, &m_perClothMediumDensity, true ),
00588         m_dx11PerClothCollisionObjects( m_dx11Device, m_dx11Context, &m_perClothCollisionObjects, true ),
00589         m_dx11CollisionObjectDetails( m_dx11Device, m_dx11Context, &m_collisionObjectDetails, true ),
00590         m_dx11PerClothMinBounds( m_dx11Device, m_dx11Context, &m_perClothMinBounds, false ),
00591         m_dx11PerClothMaxBounds( m_dx11Device, m_dx11Context, &m_perClothMaxBounds, false ),
00592         m_dx11PerClothFriction( m_dx11Device, m_dx11Context, &m_perClothFriction, false ),
00593         m_enableUpdateBounds(false)
00594 {
00595         // Initial we will clearly need to update solver constants
00596         // For now this is global for the cloths linked with this solver - we should probably make this body specific 
00597         // for performance in future once we understand more clearly when constants need to be updated
00598         m_updateSolverConstants = true;
00599 
00600         m_shadersInitialized = false;
00601 }
00602 
00603 btDX11SoftBodySolver::~btDX11SoftBodySolver()
00604 {       
00605         releaseKernels();
00606 }
00607 
00608 void btDX11SoftBodySolver::releaseKernels()
00609 {
00610         
00611         SAFE_RELEASE( prepareLinksKernel.kernel );
00612         SAFE_RELEASE( prepareLinksKernel.constBuffer );
00613         SAFE_RELEASE( integrateKernel.kernel );
00614         SAFE_RELEASE( integrateKernel.constBuffer );
00615         SAFE_RELEASE( integrateKernel.kernel );
00616         SAFE_RELEASE( solvePositionsFromLinksKernel.constBuffer );
00617         SAFE_RELEASE( solvePositionsFromLinksKernel.kernel );
00618         SAFE_RELEASE( updatePositionsFromVelocitiesKernel.constBuffer );
00619         SAFE_RELEASE( updatePositionsFromVelocitiesKernel.kernel );
00620         SAFE_RELEASE( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer );
00621         SAFE_RELEASE( updateVelocitiesFromPositionsWithoutVelocitiesKernel.kernel );
00622         SAFE_RELEASE( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer );
00623         SAFE_RELEASE( updateVelocitiesFromPositionsWithVelocitiesKernel.kernel );
00624         SAFE_RELEASE( resetNormalsAndAreasKernel.constBuffer );
00625         SAFE_RELEASE( resetNormalsAndAreasKernel.kernel );
00626         SAFE_RELEASE( normalizeNormalsAndAreasKernel.constBuffer );
00627         SAFE_RELEASE( normalizeNormalsAndAreasKernel.kernel );
00628         SAFE_RELEASE( updateSoftBodiesKernel.constBuffer );
00629         SAFE_RELEASE( updateSoftBodiesKernel.kernel );
00630         SAFE_RELEASE( solveCollisionsAndUpdateVelocitiesKernel.kernel );
00631         SAFE_RELEASE( solveCollisionsAndUpdateVelocitiesKernel.constBuffer );
00632         SAFE_RELEASE( computeBoundsKernel.kernel );
00633         SAFE_RELEASE( computeBoundsKernel.constBuffer );
00634         SAFE_RELEASE( vSolveLinksKernel.kernel );
00635         SAFE_RELEASE( vSolveLinksKernel.constBuffer );
00636 
00637         SAFE_RELEASE( addVelocityKernel.constBuffer );
00638         SAFE_RELEASE( addVelocityKernel.kernel );
00639         SAFE_RELEASE( applyForcesKernel.constBuffer );
00640         SAFE_RELEASE( applyForcesKernel.kernel );
00641 
00642         m_shadersInitialized = false;
00643 }
00644 
00645 
00646 void btDX11SoftBodySolver::copyBackToSoftBodies(bool bMove)
00647 {
00648         // Move the vertex data back to the host first
00649         m_vertexData.moveFromAccelerator(!bMove);
00650 
00651         // Loop over soft bodies, copying all the vertex positions back for each body in turn
00652         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
00653         {
00654                 btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ];
00655                 btSoftBody *softBody = softBodyInterface->getSoftBody();
00656 
00657                 int firstVertex = softBodyInterface->getFirstVertex();
00658                 int numVertices = softBodyInterface->getNumVertices();
00659 
00660                 // Copy vertices from solver back into the softbody
00661                 for( int vertex = 0; vertex < numVertices; ++vertex )
00662                 {
00663                         using Vectormath::Aos::Point3;
00664                         Point3 vertexPosition( getVertexData().getVertexPositions()[firstVertex + vertex] );
00665 
00666                         softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() );
00667                         softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() );
00668                         softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() );
00669 
00670                         softBody->m_nodes[vertex].m_n.setX( vertexPosition.getX() );
00671                         softBody->m_nodes[vertex].m_n.setY( vertexPosition.getY() );
00672                         softBody->m_nodes[vertex].m_n.setZ( vertexPosition.getZ() );
00673                 }
00674         }
00675 } // btDX11SoftBodySolver::copyBackToSoftBodies
00676 
00677 
00678 void btDX11SoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate )
00679 {
00680         if( forceUpdate || m_softBodySet.size() != softBodies.size() )
00681         {
00682                 // Have a change in the soft body set so update, reloading all the data
00683                 getVertexData().clear();
00684                 getTriangleData().clear();
00685                 getLinkData().clear();
00686                 m_softBodySet.resize(0);
00687 
00688 
00689                 for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex )
00690                 {
00691                         btSoftBody *softBody = softBodies[ softBodyIndex ];
00692                         using Vectormath::Aos::Matrix3;
00693                         using Vectormath::Aos::Point3;
00694 
00695                         // Create SoftBody that will store the information within the solver
00696                         btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody );
00697                         m_softBodySet.push_back( newSoftBody );
00698 
00699                         m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) );
00700                         m_perClothDampingFactor.push_back(softBody->m_cfg.kDP);
00701                         m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF );
00702                         m_perClothLiftFactor.push_back( softBody->m_cfg.kLF );
00703                         m_perClothDragFactor.push_back( softBody->m_cfg.kDG );
00704                         m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density);
00705                         // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time
00706                         m_perClothMinBounds.push_back( UIntVector3( 0, 0, 0 ) );
00707                         m_perClothMaxBounds.push_back( UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ) );
00708                         m_perClothFriction.push_back( softBody->getFriction() );
00709                         m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) );
00710 
00711                         // Add space for new vertices and triangles in the default solver for now
00712                         // TODO: Include space here for tearing too later
00713                         int firstVertex = getVertexData().getNumVertices();
00714                         int numVertices = softBody->m_nodes.size();
00715                         int maxVertices = numVertices;
00716                         // Allocate space for new vertices in all the vertex arrays
00717                         getVertexData().createVertices( maxVertices, softBodyIndex );
00718 
00719                         int firstTriangle = getTriangleData().getNumTriangles();
00720                         int numTriangles = softBody->m_faces.size();
00721                         int maxTriangles = numTriangles;
00722                         getTriangleData().createTriangles( maxTriangles );
00723 
00724                         // Copy vertices from softbody into the solver
00725                         for( int vertex = 0; vertex < numVertices; ++vertex )
00726                         {
00727                                 Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ());
00728                                 btSoftBodyVertexData::VertexDescription desc;
00729 
00730                                 // TODO: Position in the softbody might be pre-transformed
00731                                 // or we may need to adapt for the pose.
00732                                 //desc.setPosition( cloth.getMeshTransform()*multPoint );
00733                                 desc.setPosition( multPoint );
00734 
00735                                 float vertexInverseMass = softBody->m_nodes[vertex].m_im;
00736                                 desc.setInverseMass(vertexInverseMass);
00737                                 getVertexData().setVertexAt( desc, firstVertex + vertex );
00738                         }
00739 
00740                         // Copy triangles similarly
00741                         // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene
00742                         for( int triangle = 0; triangle < numTriangles; ++triangle )
00743                         {
00744                                 // Note that large array storage is relative to the array not to the cloth
00745                                 // So we need to add firstVertex to each value
00746                                 int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0]));
00747                                 int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0]));
00748                                 int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0]));
00749                                 btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex);
00750                                 getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle );
00751                                 
00752                                 // Increase vertex triangle counts for this triangle            
00753                                 getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++;
00754                                 getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++;
00755                                 getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++;
00756                         }
00757 
00758                         int firstLink = getLinkData().getNumLinks();
00759                         int numLinks = softBody->m_links.size();
00760                         int maxLinks = numLinks;
00761                         
00762                         // Allocate space for the links
00763                         getLinkData().createLinks( numLinks );
00764 
00765                         // Add the links
00766                         for( int link = 0; link < numLinks; ++link )
00767                         {
00768                                 int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]);
00769                                 int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]);
00770 
00771                                 btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST);
00772                                 newLink.setLinkStrength(1.f);
00773                                 getLinkData().setLinkAt(newLink, firstLink + link);
00774                         }
00775                         
00776                         newSoftBody->setFirstVertex( firstVertex );
00777                         newSoftBody->setFirstTriangle( firstTriangle );
00778                         newSoftBody->setNumVertices( numVertices );
00779                         newSoftBody->setMaxVertices( maxVertices );
00780                         newSoftBody->setNumTriangles( numTriangles );
00781                         newSoftBody->setMaxTriangles( maxTriangles );
00782                         newSoftBody->setFirstLink( firstLink );
00783                         newSoftBody->setNumLinks( numLinks );
00784                 }
00785 
00786 
00787 
00788                 updateConstants(0.f);
00789 
00790 
00791                 m_linkData.generateBatches();           
00792                 m_triangleData.generateBatches();
00793         }
00794 }
00795 
00796 
00797 btSoftBodyLinkData &btDX11SoftBodySolver::getLinkData()
00798 {
00799         // TODO: Consider setting link data to "changed" here
00800         return m_linkData;
00801 }
00802 
00803 btSoftBodyVertexData &btDX11SoftBodySolver::getVertexData()
00804 {
00805         // TODO: Consider setting vertex data to "changed" here
00806         return m_vertexData;
00807 }
00808 
00809 btSoftBodyTriangleData &btDX11SoftBodySolver::getTriangleData()
00810 {
00811         // TODO: Consider setting triangle data to "changed" here
00812         return m_triangleData;
00813 }
00814 
00815 bool btDX11SoftBodySolver::checkInitialized()
00816 {
00817         if( !m_shadersInitialized )
00818                 if( buildShaders() )
00819                         m_shadersInitialized = true;
00820 
00821         return m_shadersInitialized;
00822 }
00823 
00824 void btDX11SoftBodySolver::resetNormalsAndAreas( int numVertices )
00825 {
00826         // No need to batch link solver, it is entirely parallel
00827         // Copy kernel parameters to GPU
00828         UpdateSoftBodiesCB constBuffer;
00829         
00830         constBuffer.numNodes = numVertices;
00831         constBuffer.epsilon = FLT_EPSILON;
00832         
00833         // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
00834         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
00835         m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
00836         memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) );       
00837         m_dx11Context->Unmap( integrateKernel.constBuffer, 0 );
00838         m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer );
00839 
00840         // Set resources and dispatch
00841         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL );
00842         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL );
00843 
00844         // Execute the kernel
00845         m_dx11Context->CSSetShader( resetNormalsAndAreasKernel.kernel, NULL, 0 );
00846 
00847         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
00848         m_dx11Context->Dispatch(numBlocks, 1, 1 );
00849 
00850         {
00851                 // Tidy up 
00852                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
00853                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
00854                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
00855 
00856                 ID3D11Buffer *pBufferNull = NULL;
00857                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
00858         }       
00859 } // btDX11SoftBodySolver::resetNormalsAndAreas
00860 
00861 void btDX11SoftBodySolver::normalizeNormalsAndAreas( int numVertices )
00862 {
00863         // No need to batch link solver, it is entirely parallel
00864         // Copy kernel parameters to GPU
00865         UpdateSoftBodiesCB constBuffer;
00866         
00867         constBuffer.numNodes = numVertices;
00868         constBuffer.epsilon = FLT_EPSILON;
00869         
00870         // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
00871         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
00872         m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
00873         memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) );       
00874         m_dx11Context->Unmap( integrateKernel.constBuffer, 0 );
00875         m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer );
00876 
00877         // Set resources and dispatch   
00878         m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexTriangleCount.getSRV()) );
00879 
00880         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL );
00881         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL );
00882 
00883         // Execute the kernel
00884         m_dx11Context->CSSetShader( normalizeNormalsAndAreasKernel.kernel, NULL, 0 );
00885 
00886         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
00887         m_dx11Context->Dispatch(numBlocks, 1, 1 );
00888 
00889         {
00890                 // Tidy up 
00891                 ID3D11ShaderResourceView* pViewNULL = NULL;
00892                 m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
00893 
00894                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
00895                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
00896                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
00897 
00898                 ID3D11Buffer *pBufferNull = NULL;
00899                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
00900         }       
00901 } // btDX11SoftBodySolver::normalizeNormalsAndAreas
00902 
00903 void btDX11SoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles )
00904 {
00905         // No need to batch link solver, it is entirely parallel
00906         // Copy kernel parameters to GPU
00907         UpdateSoftBodiesCB constBuffer;
00908         
00909         constBuffer.startFace = firstTriangle;
00910         constBuffer.numFaces = numTriangles;
00911         
00912         // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
00913         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
00914         m_dx11Context->Map( updateSoftBodiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
00915         memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) );       
00916         m_dx11Context->Unmap( updateSoftBodiesKernel.constBuffer, 0 );
00917         m_dx11Context->CSSetConstantBuffers( 0, 1, &updateSoftBodiesKernel.constBuffer );
00918 
00919         // Set resources and dispatch   
00920         m_dx11Context->CSSetShaderResources( 0, 1, &(m_triangleData.m_dx11VertexIndices.getSRV()) );
00921         m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) );
00922 
00923         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL );
00924         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL );
00925         m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_triangleData.m_dx11Normal.getUAV()), NULL );
00926         m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_triangleData.m_dx11Area.getUAV()), NULL );
00927 
00928         // Execute the kernel
00929         m_dx11Context->CSSetShader( updateSoftBodiesKernel.kernel, NULL, 0 );
00930 
00931         int     numBlocks = (numTriangles + (128-1)) / 128;
00932         m_dx11Context->Dispatch(numBlocks, 1, 1 );
00933 
00934         {
00935                 // Tidy up 
00936                 ID3D11ShaderResourceView* pViewNULL = NULL;
00937                 m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL );
00938 
00939                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
00940                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
00941                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
00942 
00943                 ID3D11Buffer *pBufferNull = NULL;
00944                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
00945         }       
00946 } // btDX11SoftBodySolver::executeUpdateSoftBodies
00947 
00948 void btDX11SoftBodySolver::updateSoftBodies()
00949 {
00950         using namespace Vectormath::Aos;
00951 
00952 
00953         int numVertices = m_vertexData.getNumVertices();
00954         int numTriangles = m_triangleData.getNumTriangles();
00955 
00956         // Ensure data is on accelerator
00957         m_vertexData.moveToAccelerator();
00958         m_triangleData.moveToAccelerator();
00959 
00960         resetNormalsAndAreas( numVertices );
00961 
00962 
00963         // Go through triangle batches so updates occur correctly
00964         for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex )
00965         {
00966 
00967                 int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].start;
00968                 int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].length;
00969 
00970                 executeUpdateSoftBodies( startTriangle, numTriangles );
00971         }
00972 
00973 
00974         normalizeNormalsAndAreas( numVertices );
00975         
00976 
00977 } // btDX11SoftBodySolver::updateSoftBodies
00978 
00979 
00980 Vectormath::Aos::Vector3 btDX11SoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a )
00981 {
00982         return a*Vectormath::Aos::dot(v, a);
00983 }
00984 
00985 void btDX11SoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce )
00986 {
00987         float dtInverseMass = solverdt*inverseMass;
00988         if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) )
00989         {
00990                 vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass;
00991         } else {
00992                 vertexForce += force;
00993         }
00994 }
00995 
00996 void btDX11SoftBodySolver::applyForces( float solverdt )
00997 {               
00998         using namespace Vectormath::Aos;
00999 
01000 
01001         // Ensure data is on accelerator
01002         m_vertexData.moveToAccelerator();
01003         m_dx11PerClothAcceleration.moveToGPU();
01004         m_dx11PerClothLiftFactor.moveToGPU();
01005         m_dx11PerClothDragFactor.moveToGPU();
01006         m_dx11PerClothMediumDensity.moveToGPU();
01007         m_dx11PerClothWindVelocity.moveToGPU();
01008 
01009         // No need to batch link solver, it is entirely parallel
01010         // Copy kernel parameters to GPU
01011         ApplyForcesCB constBuffer;
01012         
01013         constBuffer.numNodes = m_vertexData.getNumVertices();
01014         constBuffer.solverdt = solverdt;
01015         constBuffer.epsilon = FLT_EPSILON;
01016         
01017         // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
01018         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01019         m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01020         memcpy( MappedResource.pData, &constBuffer, sizeof(ApplyForcesCB) );    
01021         m_dx11Context->Unmap( integrateKernel.constBuffer, 0 );
01022         m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer );
01023 
01024         // Set resources and dispatch   
01025         m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
01026         m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexNormal.getSRV()) );
01027         m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexArea.getSRV()) );
01028         m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) );
01029         m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothLiftFactor.getSRV()) );
01030         m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11PerClothDragFactor.getSRV()) );
01031         m_dx11Context->CSSetShaderResources( 6, 1, &(m_dx11PerClothWindVelocity.getSRV()) );
01032         m_dx11Context->CSSetShaderResources( 7, 1, &(m_dx11PerClothAcceleration.getSRV()) );
01033         m_dx11Context->CSSetShaderResources( 8, 1, &(m_dx11PerClothMediumDensity.getSRV()) );
01034 
01035         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
01036         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
01037 
01038         // Execute the kernel
01039         m_dx11Context->CSSetShader( applyForcesKernel.kernel, NULL, 0 );
01040 
01041         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
01042         m_dx11Context->Dispatch(numBlocks, 1, 1 );
01043 
01044         {
01045                 // Tidy up 
01046                 ID3D11ShaderResourceView* pViewNULL = NULL;
01047                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01048                 m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01049                 m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
01050                 m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
01051                 m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL );
01052                 m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL );
01053                 m_dx11Context->CSSetShaderResources( 6, 1, &pViewNULL );
01054                 m_dx11Context->CSSetShaderResources( 7, 1, &pViewNULL );
01055                 m_dx11Context->CSSetShaderResources( 8, 1, &pViewNULL );
01056 
01057                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01058                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01059                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
01060 
01061                 ID3D11Buffer *pBufferNull = NULL;
01062                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01063         }       
01064 } // btDX11SoftBodySolver::applyForces
01065 
01069 void btDX11SoftBodySolver::integrate( float solverdt )
01070 {
01071         // TEMPORARY COPIES
01072         m_vertexData.moveToAccelerator();
01073 
01074         // No need to batch link solver, it is entirely parallel
01075         // Copy kernel parameters to GPU
01076         IntegrateCB constBuffer;
01077         
01078         constBuffer.numNodes = m_vertexData.getNumVertices();
01079         constBuffer.solverdt = solverdt;
01080         
01081         // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
01082         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01083         m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01084         memcpy( MappedResource.pData, &constBuffer, sizeof(IntegrateCB) );      
01085         m_dx11Context->Unmap( integrateKernel.constBuffer, 0 );
01086         m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer );
01087 
01088         // Set resources and dispatch
01089         m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) );
01090 
01091         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL );
01092         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
01093         m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL );
01094         m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
01095 
01096         // Execute the kernel
01097         m_dx11Context->CSSetShader( integrateKernel.kernel, NULL, 0 );
01098 
01099         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
01100         m_dx11Context->Dispatch(numBlocks, 1, 1 );
01101 
01102         {
01103                 // Tidy up 
01104                 ID3D11ShaderResourceView* pViewNULL = NULL;
01105                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01106 
01107                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01108                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01109                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
01110                 m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL );
01111                 m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &pUAViewNULL, NULL );
01112 
01113                 ID3D11Buffer *pBufferNull = NULL;
01114                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01115         }       
01116 } // btDX11SoftBodySolver::integrate
01117 
01118 float btDX11SoftBodySolver::computeTriangleArea( 
01119         const Vectormath::Aos::Point3 &vertex0,
01120         const Vectormath::Aos::Point3 &vertex1,
01121         const Vectormath::Aos::Point3 &vertex2 )
01122 {
01123         Vectormath::Aos::Vector3 a = vertex1 - vertex0;
01124         Vectormath::Aos::Vector3 b = vertex2 - vertex0;
01125         Vectormath::Aos::Vector3 crossProduct = cross(a, b);
01126         float area = length( crossProduct );
01127         return area;
01128 } // btDX11SoftBodySolver::computeTriangleArea
01129 
01130 
01131 void btDX11SoftBodySolver::updateBounds()
01132 {       
01133         using Vectormath::Aos::Point3;
01134         // Interpretation structure for float and int
01135         
01136         struct FPRep {
01137                 unsigned int mantissa  : 23;
01138                 unsigned int exponent : 8;
01139                 unsigned int sign    : 1;
01140         };
01141         union FloatAsInt
01142         {
01143                 float floatValue;
01144                 int intValue;
01145                 unsigned int uintValue;
01146                 FPRep fpRep;
01147         };
01148 
01149         
01150         // Update bounds array to min and max int values to allow easy atomics
01151         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
01152         {
01153                 m_perClothMinBounds[softBodyIndex] = UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX );
01154                 m_perClothMaxBounds[softBodyIndex] = UIntVector3( 0, 0, 0 );
01155         }
01156         
01157         m_dx11PerClothMinBounds.moveToGPU();
01158         m_dx11PerClothMaxBounds.moveToGPU();
01159 
01160 
01161         computeBounds( );
01162 
01163 
01164         m_dx11PerClothMinBounds.moveFromGPU();
01165         m_dx11PerClothMaxBounds.moveFromGPU();
01166 
01167 
01168         
01169         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
01170         {
01171                 UIntVector3 minBoundUInt = m_perClothMinBounds[softBodyIndex];
01172                 UIntVector3 maxBoundUInt = m_perClothMaxBounds[softBodyIndex];
01173                                 
01174                 // Convert back to float
01175                 FloatAsInt fai;
01176 
01177                 btVector3 minBound;
01178                 fai.uintValue = minBoundUInt.x;
01179             fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
01180                 minBound.setX( fai.floatValue );
01181                 fai.uintValue = minBoundUInt.y;
01182                 fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
01183                 minBound.setY( fai.floatValue );
01184                 fai.uintValue = minBoundUInt.z;
01185                 fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
01186                 minBound.setZ( fai.floatValue );
01187 
01188                 btVector3 maxBound;
01189                 fai.uintValue = maxBoundUInt.x;
01190                 fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
01191                 maxBound.setX( fai.floatValue );
01192                 fai.uintValue = maxBoundUInt.y;
01193                 fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
01194                 maxBound.setY( fai.floatValue );
01195                 fai.uintValue = maxBoundUInt.z;
01196                 fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
01197                 maxBound.setZ( fai.floatValue );
01198                 
01199                 // And finally assign to the soft body
01200                 m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound );
01201         }
01202 }
01203 
01204 void btDX11SoftBodySolver::updateConstants( float timeStep )
01205 {
01206         using namespace Vectormath::Aos;
01207 
01208         if( m_updateSolverConstants )
01209         {
01210                 m_updateSolverConstants = false;
01211 
01212                 // Will have to redo this if we change the structure (tear, maybe) or various other possible changes
01213 
01214                 // Initialise link constants
01215                 const int numLinks = m_linkData.getNumLinks();
01216                 for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
01217                 {
01218                         btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) );
01219                         m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 )));
01220                         float invMass0 = m_vertexData.getInverseMass(vertices.vertex0);
01221                         float invMass1 = m_vertexData.getInverseMass(vertices.vertex1);
01222                         float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex);
01223                         float massLSC = (invMass0 + invMass1)/linearStiffness;
01224                         m_linkData.getMassLSC(linkIndex) = massLSC;
01225                         float restLength = m_linkData.getRestLength(linkIndex);
01226                         float restLengthSquared = restLength*restLength;
01227                         m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared;
01228                 }
01229         }
01230 } // btDX11SoftBodySolver::updateConstants
01231 
01235 void btDX11SoftBodySolver::prepareCollisionConstraints()
01236 {
01237         // First do a simple sort on the collision objects
01238         btAlignedObjectArray<int> numObjectsPerClothPrefixSum;
01239         btAlignedObjectArray<int> numObjectsPerCloth;
01240         numObjectsPerCloth.resize( m_softBodySet.size(), 0 );
01241         numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 );
01242 
01243 
01244         class QuickSortCompare
01245         {
01246                 public:
01247 
01248                 bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const
01249                 {
01250                         return ( a.softBodyIdentifier < b.softBodyIdentifier );
01251                 }
01252         };
01253 
01254         QuickSortCompare comparator;
01255         m_collisionObjectDetails.quickSort( comparator );
01256 
01257         // Generating indexing for perClothCollisionObjects
01258         // First clear the previous values with the "no collision object for cloth" constant
01259         for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex )
01260         {
01261                 m_perClothCollisionObjects[clothIndex].firstObject = -1;
01262                 m_perClothCollisionObjects[clothIndex].endObject = -1;
01263         }
01264         int currentCloth = 0;
01265         int startIndex = 0;
01266         for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject )
01267         {
01268                 int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier;
01269                 if( nextCloth != currentCloth )
01270                 {       
01271                         // Changed cloth in the array
01272                         // Set the end index and the range is what we need for currentCloth
01273                         m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
01274                         m_perClothCollisionObjects[currentCloth].endObject = collisionObject;
01275                         currentCloth = nextCloth;
01276                         startIndex = collisionObject;
01277                 }
01278         }
01279 
01280         // And update last cloth        
01281         m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
01282         m_perClothCollisionObjects[currentCloth].endObject =  m_collisionObjectDetails.size();
01283         
01284 } // btDX11SoftBodySolver::prepareCollisionConstraints
01285 
01286 
01287 void btDX11SoftBodySolver::solveConstraints( float solverdt )
01288 {
01289 
01290         //std::cerr << "'GPU' solve constraints\n";
01291         using Vectormath::Aos::Vector3;
01292         using Vectormath::Aos::Point3;
01293         using Vectormath::Aos::lengthSqr;
01294         using Vectormath::Aos::dot;
01295 
01296         // Prepare links
01297         int numLinks = m_linkData.getNumLinks();
01298         int numVertices = m_vertexData.getNumVertices();
01299 
01300         float kst = 1.f;
01301         float ti = 0.f;
01302 
01303 
01304         m_dx11PerClothDampingFactor.moveToGPU();
01305         m_dx11PerClothVelocityCorrectionCoefficient.moveToGPU();
01306 
01307 
01308         // Ensure data is on accelerator
01309         m_linkData.moveToAccelerator();
01310         m_vertexData.moveToAccelerator();
01311 
01312 
01313         prepareLinks(); 
01314 
01315         for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration )
01316         {
01317                 for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i )
01318                 {
01319                         int startLink = m_linkData.m_batchStartLengths[i].start;
01320                         int numLinks = m_linkData.m_batchStartLengths[i].length;
01321 
01322                         solveLinksForVelocity( startLink, numLinks, kst );
01323                 }
01324         }
01325 
01326         
01327         prepareCollisionConstraints();
01328 
01329         // Compute new positions from velocity
01330         // Also update the previous position so that our position computation is now based on the new position from the velocity solution
01331         // rather than based directly on the original positions
01332         if( m_numberOfVelocityIterations > 0 )
01333         {
01334                 updateVelocitiesFromPositionsWithVelocities( 1.f/solverdt );
01335         } else {
01336                 updateVelocitiesFromPositionsWithoutVelocities( 1.f/solverdt );
01337         }
01338 
01339 
01340         // Solve drift
01341         for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration )
01342         {
01343                 for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i )
01344                 {
01345                         int startLink = m_linkData.m_batchStartLengths[i].start;
01346                         int numLinks = m_linkData.m_batchStartLengths[i].length;
01347 
01348                         solveLinksForPosition( startLink, numLinks, kst, ti );
01349                 }
01350                 
01351         } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration )
01352 
01353         // At this point assume that the force array is blank - we will overwrite it
01354         solveCollisionsAndUpdateVelocities( 1.f/solverdt );
01355 } // btDX11SoftBodySolver::solveConstraints
01356 
01357 
01358 
01359 
01361 // Kernel dispatches
01362 void btDX11SoftBodySolver::prepareLinks()
01363 {
01364         // No need to batch link solver, it is entirely parallel
01365         // Copy kernel parameters to GPU
01366         PrepareLinksCB constBuffer;
01367         
01368         constBuffer.numLinks = m_linkData.getNumLinks();
01369         
01370         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01371         m_dx11Context->Map( prepareLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01372         memcpy( MappedResource.pData, &constBuffer, sizeof(PrepareLinksCB) );   
01373         m_dx11Context->Unmap( prepareLinksKernel.constBuffer, 0 );
01374         m_dx11Context->CSSetConstantBuffers( 0, 1, &prepareLinksKernel.constBuffer );
01375 
01376         // Set resources and dispatch
01377         m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) );
01378         m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) );
01379         m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) );
01380 
01381         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_linkData.m_dx11LinksLengthRatio.getUAV()), NULL );
01382         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_linkData.m_dx11LinksCLength.getUAV()), NULL );
01383 
01384         // Execute the kernel
01385         m_dx11Context->CSSetShader( prepareLinksKernel.kernel, NULL, 0 );
01386 
01387         int     numBlocks = (constBuffer.numLinks + (128-1)) / 128;
01388         m_dx11Context->Dispatch(numBlocks , 1, 1 );
01389 
01390         {
01391                 // Tidy up 
01392                 ID3D11ShaderResourceView* pViewNULL = NULL;
01393                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01394                 m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01395                 m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
01396 
01397                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01398                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01399                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
01400                 
01401                 ID3D11Buffer *pBufferNull = NULL;
01402                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01403         }
01404 } // btDX11SoftBodySolver::prepareLinks
01405 
01406 
01407 void btDX11SoftBodySolver::updatePositionsFromVelocities( float solverdt )
01408 {
01409         // No need to batch link solver, it is entirely parallel
01410         // Copy kernel parameters to GPU
01411         UpdatePositionsFromVelocitiesCB constBuffer;
01412         
01413         constBuffer.numNodes = m_vertexData.getNumVertices();
01414         constBuffer.solverSDT = solverdt;
01415         
01416         // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
01417         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01418         m_dx11Context->Map( updatePositionsFromVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01419         memcpy( MappedResource.pData, &constBuffer, sizeof(UpdatePositionsFromVelocitiesCB) );  
01420         m_dx11Context->Unmap( updatePositionsFromVelocitiesKernel.constBuffer, 0 );
01421         m_dx11Context->CSSetConstantBuffers( 0, 1, &updatePositionsFromVelocitiesKernel.constBuffer );
01422 
01423         // Set resources and dispatch                   
01424         m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getSRV()) );
01425 
01426         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL );
01427         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL );
01428 
01429         // Execute the kernel
01430         m_dx11Context->CSSetShader( updatePositionsFromVelocitiesKernel.kernel, NULL, 0 );
01431 
01432         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
01433         m_dx11Context->Dispatch(numBlocks, 1, 1 );
01434 
01435         {
01436                 // Tidy up 
01437                 ID3D11ShaderResourceView* pViewNULL = NULL;
01438                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01439 
01440                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01441                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01442                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
01443 
01444                 ID3D11Buffer *pBufferNull = NULL;
01445                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01446         }       
01447 } // btDX11SoftBodySolver::updatePositionsFromVelocities
01448 
01449 void btDX11SoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti )
01450 {
01451         // Copy kernel parameters to GPU
01452         SolvePositionsFromLinksKernelCB constBuffer;
01453 
01454         // Set the first link of the batch
01455         // and the batch size
01456         constBuffer.startLink = startLink;
01457         constBuffer.numLinks = numLinks;
01458 
01459         constBuffer.kst = kst;
01460         constBuffer.ti = ti;
01461         
01462         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01463         m_dx11Context->Map( solvePositionsFromLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01464         memcpy( MappedResource.pData, &constBuffer, sizeof(SolvePositionsFromLinksKernelCB) );  
01465         m_dx11Context->Unmap( solvePositionsFromLinksKernel.constBuffer, 0 );
01466         m_dx11Context->CSSetConstantBuffers( 0, 1, &solvePositionsFromLinksKernel.constBuffer );
01467 
01468         // Set resources and dispatch
01469         m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) );
01470         m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) );
01471         m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksRestLengthSquared.getSRV()) );
01472         m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) );
01473 
01474         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL );
01475 
01476         // Execute the kernel
01477         m_dx11Context->CSSetShader( solvePositionsFromLinksKernel.kernel, NULL, 0 );
01478 
01479         int     numBlocks = (constBuffer.numLinks + (128-1)) / 128;
01480         m_dx11Context->Dispatch(numBlocks , 1, 1 );
01481 
01482         {
01483                 // Tidy up 
01484                 ID3D11ShaderResourceView* pViewNULL = NULL;
01485                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01486                 m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01487                 m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
01488                 m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
01489 
01490                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01491                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01492 
01493                 ID3D11Buffer *pBufferNull = NULL;
01494                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01495         }       
01496         
01497 } // btDX11SoftBodySolver::solveLinksForPosition
01498 
01499 void btDX11SoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst )
01500 {
01501         // Copy kernel parameters to GPU
01502         VSolveLinksCB constBuffer;
01503 
01504         // Set the first link of the batch
01505         // and the batch size
01506 
01507         constBuffer.startLink = startLink;
01508         constBuffer.numLinks = numLinks;
01509         constBuffer.kst = kst;
01510         
01511         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01512         m_dx11Context->Map( vSolveLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01513         memcpy( MappedResource.pData, &constBuffer, sizeof(VSolveLinksCB) );    
01514         m_dx11Context->Unmap( vSolveLinksKernel.constBuffer, 0 );
01515         m_dx11Context->CSSetConstantBuffers( 0, 1, &vSolveLinksKernel.constBuffer );
01516 
01517         // Set resources and dispatch
01518         m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) );
01519         m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksLengthRatio.getSRV()) );
01520         m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksCLength.getSRV()) );
01521         m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) );
01522 
01523         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
01524 
01525         // Execute the kernel
01526         m_dx11Context->CSSetShader( vSolveLinksKernel.kernel, NULL, 0 );
01527 
01528         int     numBlocks = (constBuffer.numLinks + (128-1)) / 128;
01529         m_dx11Context->Dispatch(numBlocks , 1, 1 );
01530 
01531         {
01532                 // Tidy up 
01533                 ID3D11ShaderResourceView* pViewNULL = NULL;
01534                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01535                 m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01536                 m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
01537                 m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
01538 
01539                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01540                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01541 
01542                 ID3D11Buffer *pBufferNull = NULL;
01543                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01544         }       
01545 } // btDX11SoftBodySolver::solveLinksForVelocity
01546 
01547 
01548 void btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities( float isolverdt )
01549 {
01550         // Copy kernel parameters to GPU
01551         UpdateVelocitiesFromPositionsWithVelocitiesCB constBuffer;
01552 
01553         // Set the first link of the batch
01554         // and the batch size
01555         constBuffer.numNodes = m_vertexData.getNumVertices();
01556         constBuffer.isolverdt = isolverdt;
01557 
01558         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01559         m_dx11Context->Map( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01560         memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) );    
01561         m_dx11Context->Unmap( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0 );
01562         m_dx11Context->CSSetConstantBuffers( 0, 1, &updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer );
01563 
01564         // Set resources and dispatch
01565         m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) );
01566         m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) );
01567         m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
01568         m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothVelocityCorrectionCoefficient.getSRV()) );
01569         m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothDampingFactor.getSRV()) );
01570 
01571         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
01572         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
01573 
01574 
01575         // Execute the kernel
01576         m_dx11Context->CSSetShader( updateVelocitiesFromPositionsWithVelocitiesKernel.kernel, NULL, 0 );
01577 
01578         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
01579         m_dx11Context->Dispatch(numBlocks , 1, 1 );
01580 
01581         {
01582                 // Tidy up 
01583                 ID3D11ShaderResourceView* pViewNULL = NULL;
01584                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01585                 m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01586                 m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
01587                 m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
01588                 m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL );
01589 
01590                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01591                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01592                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
01593 
01594                 ID3D11Buffer *pBufferNull = NULL;
01595                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01596         }       
01597 
01598 } // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities
01599 
01600 void btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities( float isolverdt )
01601 {
01602         // Copy kernel parameters to GPU
01603         UpdateVelocitiesFromPositionsWithoutVelocitiesCB constBuffer;
01604 
01605         // Set the first link of the batch
01606         // and the batch size
01607         constBuffer.numNodes = m_vertexData.getNumVertices();
01608         constBuffer.isolverdt = isolverdt;
01609 
01610         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01611         m_dx11Context->Map( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01612         memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) ); 
01613         m_dx11Context->Unmap( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0 );
01614         m_dx11Context->CSSetConstantBuffers( 0, 1, &updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer );
01615 
01616         // Set resources and dispatch
01617         m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) );
01618         m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) );
01619         m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
01620         m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) );
01621 
01622         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
01623         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
01624 
01625 
01626         // Execute the kernel
01627         m_dx11Context->CSSetShader( updateVelocitiesFromPositionsWithoutVelocitiesKernel.kernel, NULL, 0 );
01628 
01629         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
01630         m_dx11Context->Dispatch(numBlocks , 1, 1 );
01631 
01632         {
01633                 // Tidy up 
01634                 ID3D11ShaderResourceView* pViewNULL = NULL;
01635                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01636                 m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01637                 m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
01638                 m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
01639 
01640                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01641                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01642                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
01643 
01644                 ID3D11Buffer *pBufferNull = NULL;
01645                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01646         }       
01647 
01648 } // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities
01649 
01650 
01651 void btDX11SoftBodySolver::computeBounds( )
01652 {
01653         ComputeBoundsCB constBuffer;
01654         m_vertexData.moveToAccelerator();
01655 
01656         // Set the first link of the batch
01657         // and the batch size
01658         constBuffer.numNodes = m_vertexData.getNumVertices();
01659         constBuffer.numSoftBodies = m_softBodySet.size();
01660 
01661         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01662         m_dx11Context->Map( computeBoundsKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01663         memcpy( MappedResource.pData, &constBuffer, sizeof(ComputeBoundsCB) );  
01664         m_dx11Context->Unmap( computeBoundsKernel.constBuffer, 0 );
01665         m_dx11Context->CSSetConstantBuffers( 0, 1, &computeBoundsKernel.constBuffer );
01666 
01667         // Set resources and dispatch
01668         m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
01669         m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) );
01670 
01671         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_dx11PerClothMinBounds.getUAV()), NULL );
01672         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_dx11PerClothMaxBounds.getUAV()), NULL );
01673         
01674         // Execute the kernel
01675         m_dx11Context->CSSetShader( computeBoundsKernel.kernel, NULL, 0 );
01676 
01677         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
01678         m_dx11Context->Dispatch(numBlocks , 1, 1 );
01679 
01680         {
01681                 // Tidy up 
01682                 ID3D11ShaderResourceView* pViewNULL = NULL;
01683                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01684                 m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01685 
01686                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01687                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01688                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
01689 
01690                 ID3D11Buffer *pBufferNull = NULL;
01691                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01692         }       
01693 }
01694 
01695 void btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities( float isolverdt )
01696 {
01697 
01698         // Copy kernel parameters to GPU
01699         m_vertexData.moveToAccelerator();
01700         m_dx11PerClothFriction.moveToGPU();
01701         m_dx11PerClothDampingFactor.moveToGPU();
01702         m_dx11PerClothCollisionObjects.moveToGPU();
01703         m_dx11CollisionObjectDetails.moveToGPU();
01704 
01705         SolveCollisionsAndUpdateVelocitiesCB constBuffer;
01706 
01707         // Set the first link of the batch
01708         // and the batch size
01709         constBuffer.numNodes = m_vertexData.getNumVertices();
01710         constBuffer.isolverdt = isolverdt;
01711 
01712 
01713         D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01714         m_dx11Context->Map( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01715         memcpy( MappedResource.pData, &constBuffer, sizeof(SolveCollisionsAndUpdateVelocitiesCB) );     
01716         m_dx11Context->Unmap( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0 );
01717         m_dx11Context->CSSetConstantBuffers( 0, 1, &solveCollisionsAndUpdateVelocitiesKernel.constBuffer );
01718 
01719         // Set resources and dispatch
01720         m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );    
01721         m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) );
01722         m_dx11Context->CSSetShaderResources( 2, 1, &(m_dx11PerClothFriction.getSRV()) );
01723         m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) );
01724         m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothCollisionObjects.getSRV()) );
01725         m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11CollisionObjectDetails.getSRV()) );
01726 
01727         m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
01728         m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
01729         m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL );
01730         
01731         // Execute the kernel
01732         m_dx11Context->CSSetShader( solveCollisionsAndUpdateVelocitiesKernel.kernel, NULL, 0 );
01733 
01734         int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
01735         m_dx11Context->Dispatch(numBlocks , 1, 1 );
01736 
01737         {
01738                 // Tidy up 
01739                 ID3D11ShaderResourceView* pViewNULL = NULL;
01740                 m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01741                 m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01742                 m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
01743                 m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
01744                 m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL );
01745                 m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL );
01746 
01747                 ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01748                 m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01749                 m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
01750                 m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL );
01751 
01752                 ID3D11Buffer *pBufferNull = NULL;
01753                 m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01754         }       
01755 
01756 } // btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities
01757 
01758 // End kernel dispatches
01760 
01761 
01762 
01763 
01764 
01765 
01766 
01767 
01768 
01769 
01770 
01771 
01772 
01773 
01774 btDX11SoftBodySolver::btAcceleratedSoftBodyInterface *btDX11SoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody )
01775 {
01776         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
01777         {
01778                 btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
01779                 if( softBodyInterface->getSoftBody() == softBody )
01780                         return softBodyInterface;
01781         }
01782         return 0;
01783 }
01784 
01785 const btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * const btDX11SoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) const
01786 {
01787         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
01788         {
01789                 btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
01790                 if( softBodyInterface->getSoftBody() == softBody )
01791                         return softBodyInterface;
01792         }
01793         return 0;
01794 }
01795 
01796 int btDX11SoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody )
01797 {
01798         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
01799         {
01800                 btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
01801                 if( softBodyInterface->getSoftBody() == softBody )
01802                         return softBodyIndex;
01803         }
01804         return 1;
01805 }
01806 
01807 
01808 void btSoftBodySolverOutputDXtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer )
01809 {
01810         
01811 
01812         btSoftBodySolver *solver = softBody->getSoftBodySolver();
01813         btAssert( solver->getSolverType() == btSoftBodySolver::DX_SOLVER || solver->getSolverType() == btSoftBodySolver::DX_SIMD_SOLVER );
01814         btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver );
01815 
01816         btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody );
01817         btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData );
01818         
01819 
01820         const int firstVertex = currentCloth->getFirstVertex();
01821         const int lastVertex = firstVertex + currentCloth->getNumVertices();
01822 
01823         if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
01824         {               
01825                 // If we're doing a CPU-buffer copy must copy the data back to the host first
01826                 vertexData.m_dx11VertexPosition.copyFromGPU();
01827                 vertexData.m_dx11VertexNormal.copyFromGPU();
01828 
01829                 const int firstVertex = currentCloth->getFirstVertex();
01830                 const int lastVertex = firstVertex + currentCloth->getNumVertices();
01831                 const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer);                                         
01832                 float *basePointer = cpuVertexBuffer->getBasePointer();                                         
01833 
01834                 if( vertexBuffer->hasVertexPositions() )
01835                 {
01836                         const int vertexOffset = cpuVertexBuffer->getVertexOffset();
01837                         const int vertexStride = cpuVertexBuffer->getVertexStride();
01838                         float *vertexPointer = basePointer + vertexOffset;
01839 
01840                         for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
01841                         {
01842                                 Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex);
01843                                 *(vertexPointer + 0) = position.getX();
01844                                 *(vertexPointer + 1) = position.getY();
01845                                 *(vertexPointer + 2) = position.getZ();
01846                                 vertexPointer += vertexStride;
01847                         }
01848                 }
01849                 if( vertexBuffer->hasNormals() )
01850                 {
01851                         const int normalOffset = cpuVertexBuffer->getNormalOffset();
01852                         const int normalStride = cpuVertexBuffer->getNormalStride();
01853                         float *normalPointer = basePointer + normalOffset;
01854 
01855                         for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
01856                         {
01857                                 Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex);
01858                                 *(normalPointer + 0) = normal.getX();
01859                                 *(normalPointer + 1) = normal.getY();
01860                                 *(normalPointer + 2) = normal.getZ();
01861                                 normalPointer += normalStride;
01862                         }
01863                 }
01864         } 
01865 } // btDX11SoftBodySolver::outputToVertexBuffers
01866 
01867 
01868 
01869 bool btSoftBodySolverOutputDXtoDX::checkInitialized()
01870 {
01871         if( !m_shadersInitialized )
01872                 if( buildShaders() )
01873                         m_shadersInitialized = true;
01874 
01875         return m_shadersInitialized;
01876 }
01877 
01878 void btSoftBodySolverOutputDXtoDX::releaseKernels()
01879 {
01880         SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.constBuffer );
01881         SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.kernel );
01882         SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.constBuffer );
01883         SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.kernel );
01884 
01885         m_shadersInitialized = false;
01886 }
01887 
01888 
01889 bool btSoftBodySolverOutputDXtoDX::buildShaders()
01890 {
01891         // Ensure current kernels are released first
01892         releaseKernels();
01893 
01894         bool returnVal = true;
01895 
01896         if( m_shadersInitialized )
01897                 return true;
01898         
01899 
01900         outputToVertexArrayWithNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithNormalsKernel", sizeof(OutputToVertexArrayCB) );
01901         if( !outputToVertexArrayWithNormalsKernel.constBuffer)
01902                 returnVal = false;
01903         outputToVertexArrayWithoutNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithoutNormalsKernel", sizeof(OutputToVertexArrayCB) );
01904         if( !outputToVertexArrayWithoutNormalsKernel.constBuffer )
01905                 returnVal = false;
01906 
01907 
01908         if( returnVal )
01909                 m_shadersInitialized = true;
01910 
01911         return returnVal;
01912 }
01913 
01914 
01915 void btSoftBodySolverOutputDXtoDX::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer )
01916 {
01917         
01918 
01919         btSoftBodySolver *solver = softBody->getSoftBodySolver();
01920         btAssert( solver->getSolverType() == btSoftBodySolver::DX_SOLVER || solver->getSolverType() == btSoftBodySolver::DX_SIMD_SOLVER );
01921         btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver );
01922         checkInitialized();
01923         btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody );
01924         btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData );
01925 
01926 
01927         const int firstVertex = currentCloth->getFirstVertex();
01928         const int lastVertex = firstVertex + currentCloth->getNumVertices();
01929 
01930         if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
01931         {               
01932                 btSoftBodySolverOutputDXtoDX::copySoftBodyToVertexBuffer( softBody, vertexBuffer );
01933         } else  if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::DX11_BUFFER )
01934         {
01935                 // Do a DX11 copy shader DX to DX copy
01936 
01937                 const btDX11VertexBufferDescriptor *dx11VertexBuffer = static_cast< btDX11VertexBufferDescriptor* >(vertexBuffer);      
01938 
01939                 // No need to batch link solver, it is entirely parallel
01940                 // Copy kernel parameters to GPU
01941                 OutputToVertexArrayCB constBuffer;
01942                 ID3D11ComputeShader* outputToVertexArrayShader = outputToVertexArrayWithoutNormalsKernel.kernel;
01943                 ID3D11Buffer* outputToVertexArrayConstBuffer = outputToVertexArrayWithoutNormalsKernel.constBuffer;
01944                 
01945                 constBuffer.startNode = firstVertex;
01946                 constBuffer.numNodes = currentCloth->getNumVertices();
01947                 constBuffer.positionOffset = vertexBuffer->getVertexOffset();
01948                 constBuffer.positionStride = vertexBuffer->getVertexStride();
01949                 if( vertexBuffer->hasNormals() )
01950                 {
01951                         constBuffer.normalOffset = vertexBuffer->getNormalOffset();
01952                         constBuffer.normalStride = vertexBuffer->getNormalStride();
01953                         outputToVertexArrayShader = outputToVertexArrayWithNormalsKernel.kernel;
01954                         outputToVertexArrayConstBuffer = outputToVertexArrayWithNormalsKernel.constBuffer;
01955                 }       
01956                 
01957                 // TODO: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
01958                 D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
01959                 dxFunctions.m_dx11Context->Map( outputToVertexArrayConstBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
01960                 memcpy( MappedResource.pData, &constBuffer, sizeof(OutputToVertexArrayCB) );    
01961                 dxFunctions.m_dx11Context->Unmap( outputToVertexArrayConstBuffer, 0 );
01962                 dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &outputToVertexArrayConstBuffer );
01963 
01964                 // Set resources and dispatch
01965                 dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &(vertexData.m_dx11VertexPosition.getSRV()) );
01966                 dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &(vertexData.m_dx11VertexNormal.getSRV()) );
01967 
01968                 ID3D11UnorderedAccessView* dx11UAV = dx11VertexBuffer->getDX11UAV();
01969                 dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(dx11UAV), NULL );
01970 
01971                 // Execute the kernel
01972                 dxFunctions.m_dx11Context->CSSetShader( outputToVertexArrayShader, NULL, 0 );
01973 
01974                 int     numBlocks = (constBuffer.numNodes + (128-1)) / 128;
01975                 dxFunctions.m_dx11Context->Dispatch(numBlocks, 1, 1 );
01976 
01977                 {
01978                         // Tidy up 
01979                         ID3D11ShaderResourceView* pViewNULL = NULL;
01980                         dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
01981                         dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
01982 
01983                         ID3D11UnorderedAccessView* pUAViewNULL = NULL;
01984                         dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
01985 
01986                         ID3D11Buffer *pBufferNull = NULL;
01987                         dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
01988                 }       
01989         }
01990 } // btDX11SoftBodySolver::outputToVertexBuffers
01991 
01992 
01993 
01994 
01995 DXFunctions::KernelDesc DXFunctions::compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros )
01996 {
01997         const char *cs5String = "cs_5_0";
01998 
01999         HRESULT hr = S_OK;
02000         ID3DBlob* pErrorBlob = NULL;
02001         ID3DBlob* pBlob = NULL;
02002         ID3D11ComputeShader*            kernelPointer = 0;
02003 
02004         hr = m_dx11CompileFromMemory( 
02005                 shaderString,
02006                 strlen(shaderString),
02007                 shaderName,
02008                 compileMacros,
02009                 NULL,
02010                 shaderName,
02011                 cs5String,
02012                 D3D10_SHADER_ENABLE_STRICTNESS,
02013                 NULL,
02014                 NULL,
02015                 &pBlob,
02016                 &pErrorBlob,
02017                 NULL
02018                 );
02019 
02020         if( FAILED(hr) )
02021         {
02022                 if( pErrorBlob ) {
02023                         btAssert( "Compilation of compute shader failed\n" );
02024                         char *debugString = (char*)pErrorBlob->GetBufferPointer();
02025                         OutputDebugStringA( debugString );
02026                 }
02027         
02028                 SAFE_RELEASE( pErrorBlob );
02029                 SAFE_RELEASE( pBlob );    
02030 
02031                 DXFunctions::KernelDesc descriptor;
02032                 descriptor.kernel = 0;
02033                 descriptor.constBuffer = 0;
02034                 return descriptor;
02035         }    
02036 
02037         // Create the Compute Shader
02038         hr = m_dx11Device->CreateComputeShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &kernelPointer );
02039         if( FAILED( hr ) )
02040         {
02041                 DXFunctions::KernelDesc descriptor;
02042                 descriptor.kernel = 0;
02043                 descriptor.constBuffer = 0;
02044                 return descriptor;
02045         }
02046 
02047         ID3D11Buffer* constBuffer = 0;
02048         if( constBufferSize > 0 )
02049         {
02050                 // Create the constant buffer
02051                 D3D11_BUFFER_DESC constant_buffer_desc;
02052                 ZeroMemory(&constant_buffer_desc, sizeof(constant_buffer_desc));
02053                 constant_buffer_desc.ByteWidth = constBufferSize;
02054                 constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
02055                 constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
02056                 constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
02057                 m_dx11Device->CreateBuffer(&constant_buffer_desc, NULL, &constBuffer);
02058                 if( FAILED( hr ) )
02059                 {
02060                         KernelDesc descriptor;
02061                         descriptor.kernel = 0;
02062                         descriptor.constBuffer = 0;
02063                         return descriptor;
02064                 }
02065         }
02066 
02067         SAFE_RELEASE( pErrorBlob );
02068         SAFE_RELEASE( pBlob );
02069 
02070         DXFunctions::KernelDesc descriptor;
02071         descriptor.kernel = kernelPointer;
02072         descriptor.constBuffer = constBuffer;
02073         return descriptor;
02074 } // compileComputeShader
02075 
02076 
02077 
02078 bool btDX11SoftBodySolver::buildShaders()
02079 {
02080         // Ensure current kernels are released first
02081         releaseKernels();
02082 
02083         bool returnVal = true;
02084 
02085         if( m_shadersInitialized )
02086                 return true;
02087 
02088         prepareLinksKernel = dxFunctions.compileComputeShaderFromString( PrepareLinksHLSLString, "PrepareLinksKernel", sizeof(PrepareLinksCB) );
02089         if( !prepareLinksKernel.constBuffer )
02090                 returnVal = false;
02091         updatePositionsFromVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsFromVelocitiesHLSLString, "UpdatePositionsFromVelocitiesKernel", sizeof(UpdatePositionsFromVelocitiesCB) );
02092         if( !updatePositionsFromVelocitiesKernel.constBuffer )
02093                 returnVal = false;
02094         solvePositionsFromLinksKernel = dxFunctions.compileComputeShaderFromString( SolvePositionsHLSLString, "SolvePositionsFromLinksKernel", sizeof(SolvePositionsFromLinksKernelCB) );
02095         if( !updatePositionsFromVelocitiesKernel.constBuffer )
02096                 returnVal = false;
02097         vSolveLinksKernel = dxFunctions.compileComputeShaderFromString( VSolveLinksHLSLString, "VSolveLinksKernel", sizeof(VSolveLinksCB) );
02098         if( !vSolveLinksKernel.constBuffer )
02099                 returnVal = false;
02100         updateVelocitiesFromPositionsWithVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNodesHLSLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) );
02101         if( !updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer )
02102                 returnVal = false;
02103         updateVelocitiesFromPositionsWithoutVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsHLSLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) );
02104         if( !updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer )
02105                 returnVal = false;
02106         integrateKernel = dxFunctions.compileComputeShaderFromString( IntegrateHLSLString, "IntegrateKernel", sizeof(IntegrateCB) );
02107         if( !integrateKernel.constBuffer )
02108                 returnVal = false;
02109         applyForcesKernel = dxFunctions.compileComputeShaderFromString( ApplyForcesHLSLString, "ApplyForcesKernel", sizeof(ApplyForcesCB) );
02110         if( !applyForcesKernel.constBuffer )
02111                 returnVal = false;
02112         solveCollisionsAndUpdateVelocitiesKernel = dxFunctions.compileComputeShaderFromString( SolveCollisionsAndUpdateVelocitiesHLSLString, "SolveCollisionsAndUpdateVelocitiesKernel", sizeof(SolveCollisionsAndUpdateVelocitiesCB) );
02113         if( !solveCollisionsAndUpdateVelocitiesKernel.constBuffer )
02114                 returnVal = false;
02115 
02116         // TODO: Rename to UpdateSoftBodies
02117         resetNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "ResetNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) );
02118         if( !resetNormalsAndAreasKernel.constBuffer )
02119                 returnVal = false;
02120         normalizeNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "NormalizeNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) );
02121         if( !normalizeNormalsAndAreasKernel.constBuffer )
02122                 returnVal = false;
02123         updateSoftBodiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "UpdateSoftBodiesKernel", sizeof(UpdateSoftBodiesCB) );
02124         if( !updateSoftBodiesKernel.constBuffer )
02125                 returnVal = false;
02126 
02127         computeBoundsKernel = dxFunctions.compileComputeShaderFromString( ComputeBoundsHLSLString, "ComputeBoundsKernel", sizeof(ComputeBoundsCB) );
02128         if( !computeBoundsKernel.constBuffer )
02129                 returnVal = false;
02130 
02131 
02132 
02133         if( returnVal )
02134                 m_shadersInitialized = true;
02135 
02136         return returnVal;
02137 }
02138 
02139 
02140 static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform )
02141 {
02142         Vectormath::Aos::Transform3 outTransform;
02143         outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0)));
02144         outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1)));
02145         outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2)));
02146         outTransform.setCol(3, toVector3(transform.getOrigin()));
02147         return outTransform;    
02148 }
02149 
02150 
02151 void btDX11SoftBodySolver::btAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound )
02152 {
02153         float scalarMargin = this->getSoftBody()->getCollisionShape()->getMargin();
02154         btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin );
02155         m_softBody->m_bounds[0] = lowerBound - vectorMargin;
02156         m_softBody->m_bounds[1] = upperBound + vectorMargin;
02157 }
02158 
02159 void btDX11SoftBodySolver::processCollision( btSoftBody*, btSoftBody* )
02160 {
02161 
02162 }
02163 
02164 // Add the collision object to the set to deal with for a particular soft body
02165 void btDX11SoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObject )
02166 {
02167         int softBodyIndex = findSoftBodyIndex( softBody );
02168 
02169         if( softBodyIndex >= 0 )
02170         {
02171                 const btCollisionShape *collisionShape = collisionObject->getCollisionShape();
02172                 float friction = collisionObject->getCollisionObject()->getFriction();
02173                 int shapeType = collisionShape->getShapeType();
02174                 if( shapeType == CAPSULE_SHAPE_PROXYTYPE )
02175                 {
02176                         // Add to the list of expected collision objects
02177                         CollisionShapeDescription newCollisionShapeDescription;
02178                         newCollisionShapeDescription.softBodyIdentifier = softBodyIndex;
02179                         newCollisionShapeDescription.collisionShapeType = shapeType;
02180                         // TODO: May need to transpose this matrix either here or in HLSL
02181                         newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform());
02182                         const btCapsuleShape *capsule = static_cast<const btCapsuleShape*>( collisionShape );
02183                         newCollisionShapeDescription.radius = capsule->getRadius();
02184                         newCollisionShapeDescription.halfHeight = capsule->getHalfHeight();
02185                         newCollisionShapeDescription.margin = capsule->getMargin();
02186                         newCollisionShapeDescription.friction = friction;
02187                         const btRigidBody* body = static_cast< const btRigidBody* >( collisionObject->getCollisionObject() );
02188                         newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity());
02189                         newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity());
02190                         m_collisionObjectDetails.push_back( newCollisionShapeDescription );
02191 
02192                 } else {
02193 #ifdef _DEBUG
02194                         printf("Unsupported collision shape type\n");
02195 #endif
02196                 }
02197         } else {
02198                 btAssert("Unknown soft body");
02199         }
02200 } // btDX11SoftBodySolver::processCollision
02201 
02202 
02203 
02204 void btDX11SoftBodySolver::predictMotion( float timeStep )
02205 {
02206         // Clear the collision shape array for the next frame
02207         // Ensure that the DX11 ones are moved off the device so they will be updated correctly
02208         m_dx11CollisionObjectDetails.changedOnCPU();
02209         m_dx11PerClothCollisionObjects.changedOnCPU();
02210         m_collisionObjectDetails.clear();
02211 
02212         // Fill the force arrays with current acceleration data etc
02213         m_perClothWindVelocity.resize( m_softBodySet.size() );
02214         for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
02215         {
02216                 btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody();
02217                 
02218                 m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity());
02219         }
02220         m_dx11PerClothWindVelocity.changedOnCPU();
02221 
02222         // Apply forces that we know about to the cloths
02223         applyForces(  timeStep * getTimeScale() );
02224 
02225         // Itegrate motion for all soft bodies dealt with by the solver
02226         integrate( timeStep * getTimeScale() );
02227 
02228         // Update bounds
02229         // Will update the bounds for all softBodies being dealt with by the solver and 
02230         // set the values in the btSoftBody object
02231         if (m_enableUpdateBounds)
02232                 updateBounds();
02233 
02234         // End prediction work for solvers
02235 }
02236