Bullet Collision Detection & Physics Library
btSoftBodySolver_DX11.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
17 #include "vectormath/vmInclude.h"
18 
19 #include "btSoftBodySolver_DX11.h"
23 #include <stdio.h> //printf
24 #define MSTRINGIFY(A) #A
25 static char* PrepareLinksHLSLString =
26 #include "HLSL/PrepareLinks.hlsl"
28 #include "HLSL/UpdatePositionsFromVelocities.hlsl"
29 static char* SolvePositionsHLSLString =
30 #include "HLSL/SolvePositions.hlsl"
31 static char* UpdateNodesHLSLString =
32 #include "HLSL/UpdateNodes.hlsl"
33 static char* UpdatePositionsHLSLString =
34 #include "HLSL/UpdatePositions.hlsl"
35 static char* UpdateConstantsHLSLString =
36 #include "HLSL/UpdateConstants.hlsl"
37 static char* IntegrateHLSLString =
38 #include "HLSL/Integrate.hlsl"
39 static char* ApplyForcesHLSLString =
40 #include "HLSL/ApplyForces.hlsl"
41 static char* UpdateNormalsHLSLString =
42 #include "HLSL/UpdateNormals.hlsl"
43 static char* OutputToVertexArrayHLSLString =
44 #include "HLSL/OutputToVertexArray.hlsl"
45 static char* VSolveLinksHLSLString =
46 #include "HLSL/VSolveLinks.hlsl"
47 static char* ComputeBoundsHLSLString =
48 #include "HLSL/ComputeBounds.hlsl"
49 static char* SolveCollisionsAndUpdateVelocitiesHLSLString =
50 #include "HLSL/SolveCollisionsAndUpdateVelocities.hlsl"
52 
53 btSoftBodyLinkDataDX11::btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) :
54  m_dx11Links( d3dDevice, d3dDeviceContext, &m_links, false ),
55  m_dx11LinkStrength( d3dDevice, d3dDeviceContext, &m_linkStrength, false ),
56  m_dx11LinksMassLSC( d3dDevice, d3dDeviceContext, &m_linksMassLSC, false ),
57  m_dx11LinksRestLengthSquared( d3dDevice, d3dDeviceContext, &m_linksRestLengthSquared, false ),
58  m_dx11LinksCLength( d3dDevice, d3dDeviceContext, &m_linksCLength, false ),
59  m_dx11LinksLengthRatio( d3dDevice, d3dDeviceContext, &m_linksLengthRatio, false ),
60  m_dx11LinksRestLength( d3dDevice, d3dDeviceContext, &m_linksRestLength, false ),
61  m_dx11LinksMaterialLinearStiffnessCoefficient( d3dDevice, d3dDeviceContext, &m_linksMaterialLinearStiffnessCoefficient, false )
62 {
63  m_d3dDevice = d3dDevice;
64  m_d3dDeviceContext = d3dDeviceContext;
65 }
66 
68 {
69 }
70 
72 {
73  Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() );
74  return outVec;
75 }
76 
78 {
79  int previousSize = m_links.size();
80  int newSize = previousSize + numLinks;
81 
83 
84  // Resize the link addresses array as well
85  m_linkAddresses.resize( newSize );
86 }
87 
89 {
90  btSoftBodyLinkData::setLinkAt( link, linkIndex );
91 
92  // Set the link index correctly for initialisation
93  m_linkAddresses[linkIndex] = linkIndex;
94 }
95 
97 {
98  return m_onGPU;
99 }
100 
102 {
103  bool success = true;
104  success = success && m_dx11Links.moveToGPU();
105  success = success && m_dx11LinkStrength.moveToGPU();
106  success = success && m_dx11LinksMassLSC.moveToGPU();
107  success = success && m_dx11LinksRestLengthSquared.moveToGPU();
108  success = success && m_dx11LinksCLength.moveToGPU();
109  success = success && m_dx11LinksLengthRatio.moveToGPU();
110  success = success && m_dx11LinksRestLength.moveToGPU();
112 
113  if( success )
114  m_onGPU = true;
115 
116  return success;
117 }
118 
120 {
121  bool success = true;
122  success = success && m_dx11Links.moveFromGPU();
123  success = success && m_dx11LinkStrength.moveFromGPU();
124  success = success && m_dx11LinksMassLSC.moveFromGPU();
125  success = success && m_dx11LinksRestLengthSquared.moveFromGPU();
126  success = success && m_dx11LinksCLength.moveFromGPU();
127  success = success && m_dx11LinksLengthRatio.moveFromGPU();
128  success = success && m_dx11LinksRestLength.moveFromGPU();
130 
131  if( success )
132  m_onGPU = false;
133 
134  return success;
135 }
136 
138 {
139  int numLinks = getNumLinks();
140 
141  // Do the graph colouring here temporarily
142  btAlignedObjectArray< int > batchValues;
143  batchValues.resize( numLinks, 0 );
144 
145  // Find the maximum vertex value internally for now
146  int maxVertex = 0;
147  for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
148  {
149  int vertex0 = getVertexPair(linkIndex).vertex0;
150  int vertex1 = getVertexPair(linkIndex).vertex1;
151  if( vertex0 > maxVertex )
152  maxVertex = vertex0;
153  if( vertex1 > maxVertex )
154  maxVertex = vertex1;
155  }
156  int numVertices = maxVertex + 1;
157 
158  // Set of lists, one for each node, specifying which colours are connected
159  // to that node.
160  // No two edges into a node can share a colour.
161  btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists;
162  vertexConnectedColourLists.resize(numVertices);
163 
164 
165 
166  // Simple algorithm that chooses the lowest batch number
167  // that none of the links attached to either of the connected
168  // nodes is in
169  for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
170  {
171  int linkLocation = m_linkAddresses[linkIndex];
172 
173  int vertex0 = getVertexPair(linkLocation).vertex0;
174  int vertex1 = getVertexPair(linkLocation).vertex1;
175 
176  // Get the two node colour lists
177  btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] );
178  btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] );
179 
180  // Choose the minimum colour that is in neither list
181  int colour = 0;
182  while( colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() || colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() )
183  ++colour;
184  // i should now be the minimum colour in neither list
185  // Add to the two lists so that future edges don't share
186  // And store the colour against this edge
187 
188  colourListVertex0.push_back(colour);
189  colourListVertex1.push_back(colour);
190  batchValues[linkIndex] = colour;
191  }
192 
193  // Check the colour counts
194  btAlignedObjectArray< int > batchCounts;
195  for( int i = 0; i < numLinks; ++i )
196  {
197  int batch = batchValues[i];
198  if( batch >= batchCounts.size() )
199  batchCounts.push_back(1);
200  else
201  ++(batchCounts[batch]);
202  }
203 
204  m_batchStartLengths.resize(batchCounts.size());
205  if( m_batchStartLengths.size() > 0 )
206  {
207  m_batchStartLengths[0] = BatchPair( 0, 0 );
208 
209  int sum = 0;
210  for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex )
211  {
212  m_batchStartLengths[batchIndex].start = sum;
213  m_batchStartLengths[batchIndex].length = batchCounts[batchIndex];
214  sum += batchCounts[batchIndex];
215  }
216  }
217 
219  // Sort data based on batches
220 
221  // Create source arrays by copying originals
223  btAlignedObjectArray<float> m_linkStrength_Backup(m_linkStrength);
224  btAlignedObjectArray<float> m_linksMassLSC_Backup(m_linksMassLSC);
225  btAlignedObjectArray<float> m_linksRestLengthSquared_Backup(m_linksRestLengthSquared);
227  btAlignedObjectArray<float> m_linksLengthRatio_Backup(m_linksLengthRatio);
228  btAlignedObjectArray<float> m_linksRestLength_Backup(m_linksRestLength);
229  btAlignedObjectArray<float> m_linksMaterialLinearStiffnessCoefficient_Backup(m_linksMaterialLinearStiffnessCoefficient);
230 
231 
232  for( int batch = 0; batch < batchCounts.size(); ++batch )
233  batchCounts[batch] = 0;
234 
235  // Do sort as single pass into destination arrays
236  for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
237  {
238  // To maintain locations run off the original link locations rather than the current position.
239  // It's not cache efficient, but as we run this rarely that should not matter.
240  // It's faster than searching the link location array for the current location and then updating it.
241  // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
242  int linkLocation = m_linkAddresses[linkIndex];
243 
244  // Obtain batch and calculate target location for the
245  // next element in that batch, incrementing the batch counter
246  // afterwards
247  int batch = batchValues[linkIndex];
248  int newLocation = m_batchStartLengths[batch].start + batchCounts[batch];
249 
250  batchCounts[batch] = batchCounts[batch] + 1;
251  m_links[newLocation] = m_links_Backup[linkLocation];
252 #if 1
253  m_linkStrength[newLocation] = m_linkStrength_Backup[linkLocation];
254  m_linksMassLSC[newLocation] = m_linksMassLSC_Backup[linkLocation];
255  m_linksRestLengthSquared[newLocation] = m_linksRestLengthSquared_Backup[linkLocation];
256  m_linksLengthRatio[newLocation] = m_linksLengthRatio_Backup[linkLocation];
257  m_linksRestLength[newLocation] = m_linksRestLength_Backup[linkLocation];
258  m_linksMaterialLinearStiffnessCoefficient[newLocation] = m_linksMaterialLinearStiffnessCoefficient_Backup[linkLocation];
259 #endif
260  // Update the locations array to account for the moved entry
261  m_linkAddresses[linkIndex] = newLocation;
262  }
263 } // void btSoftBodyLinkDataDX11::generateBatches()
264 
265 
266 
267 btSoftBodyVertexDataDX11::btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) :
268  m_dx11ClothIdentifier( d3dDevice, d3dDeviceContext, &m_clothIdentifier, false ),
269  m_dx11VertexPosition( d3dDevice, d3dDeviceContext, &m_vertexPosition, false ),
270  m_dx11VertexPreviousPosition( d3dDevice, d3dDeviceContext, &m_vertexPreviousPosition, false ),
271  m_dx11VertexVelocity( d3dDevice, d3dDeviceContext, &m_vertexVelocity, false ),
272  m_dx11VertexForceAccumulator( d3dDevice, d3dDeviceContext, &m_vertexForceAccumulator, false ),
273  m_dx11VertexNormal( d3dDevice, d3dDeviceContext, &m_vertexNormal, false ),
274  m_dx11VertexInverseMass( d3dDevice, d3dDeviceContext, &m_vertexInverseMass, false ),
275  m_dx11VertexArea( d3dDevice, d3dDeviceContext, &m_vertexArea, false ),
276  m_dx11VertexTriangleCount( d3dDevice, d3dDeviceContext, &m_vertexTriangleCount, false )
277 {
278  m_d3dDevice = d3dDevice;
279  m_d3dDeviceContext = d3dDeviceContext;
280 }
281 
283 {
284 
285 }
286 
288 {
289  return m_onGPU;
290 }
291 
293 {
294  bool success = true;
295  success = success && m_dx11ClothIdentifier.moveToGPU();
296  success = success && m_dx11VertexPosition.moveToGPU();
297  success = success && m_dx11VertexPreviousPosition.moveToGPU();
298  success = success && m_dx11VertexVelocity.moveToGPU();
299  success = success && m_dx11VertexForceAccumulator.moveToGPU();
300  success = success && m_dx11VertexNormal.moveToGPU();
301  success = success && m_dx11VertexInverseMass.moveToGPU();
302  success = success && m_dx11VertexArea.moveToGPU();
303  success = success && m_dx11VertexTriangleCount.moveToGPU();
304 
305  if( success )
306  m_onGPU = true;
307 
308  return success;
309 }
310 
311 bool btSoftBodyVertexDataDX11::moveFromAccelerator(bool bCopy, bool bCopyMinimum)
312 {
313  bool success = true;
314 
315  if (!bCopy)
316  {
317  success = success && m_dx11ClothIdentifier.moveFromGPU();
318  success = success && m_dx11VertexPosition.moveFromGPU();
319  success = success && m_dx11VertexPreviousPosition.moveFromGPU();
320  success = success && m_dx11VertexVelocity.moveFromGPU();
321  success = success && m_dx11VertexForceAccumulator.moveFromGPU();
322  success = success && m_dx11VertexNormal.moveFromGPU();
323  success = success && m_dx11VertexInverseMass.moveFromGPU();
324  success = success && m_dx11VertexArea.moveFromGPU();
325  success = success && m_dx11VertexTriangleCount.moveFromGPU();
326  }
327  else
328  {
329  if (bCopyMinimum)
330  {
331  success = success && m_dx11VertexPosition.copyFromGPU();
332  success = success && m_dx11VertexNormal.copyFromGPU();
333  }
334  else
335  {
336  success = success && m_dx11ClothIdentifier.copyFromGPU();
337  success = success && m_dx11VertexPosition.copyFromGPU();
338  success = success && m_dx11VertexPreviousPosition.copyFromGPU();
339  success = success && m_dx11VertexVelocity.copyFromGPU();
340  success = success && m_dx11VertexForceAccumulator.copyFromGPU();
341  success = success && m_dx11VertexNormal.copyFromGPU();
342  success = success && m_dx11VertexInverseMass.copyFromGPU();
343  success = success && m_dx11VertexArea.copyFromGPU();
344  success = success && m_dx11VertexTriangleCount.copyFromGPU();
345  }
346  }
347 
348  if( success )
349  m_onGPU = true;
350 
351  return success;
352 }
353 
354 
355 btSoftBodyTriangleDataDX11::btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext ) :
356  m_dx11VertexIndices( d3dDevice, d3dDeviceContext, &m_vertexIndices, false ),
357  m_dx11Area( d3dDevice, d3dDeviceContext, &m_area, false ),
358  m_dx11Normal( d3dDevice, d3dDeviceContext, &m_normal, false )
359 {
360  m_d3dDevice = d3dDevice;
361  m_d3dDeviceContext = d3dDeviceContext;
362 }
363 
365 {
366 
367 }
368 
369 
372 {
373  int previousSize = getNumTriangles();
374  int newSize = previousSize + numTriangles;
375 
377 
378  // Resize the link addresses array as well
379  m_triangleAddresses.resize( newSize );
380 }
381 
384 {
385  btSoftBodyTriangleData::setTriangleAt( triangle, triangleIndex );
386 
387  m_triangleAddresses[triangleIndex] = triangleIndex;
388 }
389 
391 {
392  return m_onGPU;
393 }
394 
396 {
397  bool success = true;
398  success = success && m_dx11VertexIndices.moveToGPU();
399  success = success && m_dx11Area.moveToGPU();
400  success = success && m_dx11Normal.moveToGPU();
401 
402  if( success )
403  m_onGPU = true;
404 
405  return success;
406 }
407 
409 {
410  bool success = true;
411  success = success && m_dx11VertexIndices.moveFromGPU();
412  success = success && m_dx11Area.moveFromGPU();
413  success = success && m_dx11Normal.moveFromGPU();
414 
415  if( success )
416  m_onGPU = true;
417 
418  return success;
419 }
420 
428 {
429  int numTriangles = getNumTriangles();
430  if( numTriangles == 0 )
431  return;
432 
433  // Do the graph colouring here temporarily
434  btAlignedObjectArray< int > batchValues;
435  batchValues.resize( numTriangles );
436 
437  // Find the maximum vertex value internally for now
438  int maxVertex = 0;
439  for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
440  {
441  int vertex0 = getVertexSet(triangleIndex).vertex0;
442  int vertex1 = getVertexSet(triangleIndex).vertex1;
443  int vertex2 = getVertexSet(triangleIndex).vertex2;
444 
445  if( vertex0 > maxVertex )
446  maxVertex = vertex0;
447  if( vertex1 > maxVertex )
448  maxVertex = vertex1;
449  if( vertex2 > maxVertex )
450  maxVertex = vertex2;
451  }
452  int numVertices = maxVertex + 1;
453 
454  // Set of lists, one for each node, specifying which colours are connected
455  // to that node.
456  // No two edges into a node can share a colour.
457  btAlignedObjectArray< btAlignedObjectArray< int > > vertexConnectedColourLists;
458  vertexConnectedColourLists.resize(numVertices);
459 
460 
461  //std::cout << "\n";
462  // Simple algorithm that chooses the lowest batch number
463  // that none of the faces attached to either of the connected
464  // nodes is in
465  for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
466  {
467  // To maintain locations run off the original link locations rather than the current position.
468  // It's not cache efficient, but as we run this rarely that should not matter.
469  // It's faster than searching the link location array for the current location and then updating it.
470  // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
471  int triangleLocation = m_triangleAddresses[triangleIndex];
472 
473  int vertex0 = getVertexSet(triangleLocation).vertex0;
474  int vertex1 = getVertexSet(triangleLocation).vertex1;
475  int vertex2 = getVertexSet(triangleLocation).vertex2;
476 
477  // Get the three node colour lists
478  btAlignedObjectArray< int > &colourListVertex0( vertexConnectedColourLists[vertex0] );
479  btAlignedObjectArray< int > &colourListVertex1( vertexConnectedColourLists[vertex1] );
480  btAlignedObjectArray< int > &colourListVertex2( vertexConnectedColourLists[vertex2] );
481 
482  // Choose the minimum colour that is in none of the lists
483  int colour = 0;
484  while(
485  colourListVertex0.findLinearSearch(colour) != colourListVertex0.size() ||
486  colourListVertex1.findLinearSearch(colour) != colourListVertex1.size() ||
487  colourListVertex2.findLinearSearch(colour) != colourListVertex2.size() )
488  {
489  ++colour;
490  }
491  // i should now be the minimum colour in neither list
492  // Add to the three lists so that future edges don't share
493  // And store the colour against this face
494  colourListVertex0.push_back(colour);
495  colourListVertex1.push_back(colour);
496  colourListVertex2.push_back(colour);
497 
498  batchValues[triangleIndex] = colour;
499  }
500 
501 
502  // Check the colour counts
503  btAlignedObjectArray< int > batchCounts;
504  for( int i = 0; i < numTriangles; ++i )
505  {
506  int batch = batchValues[i];
507  if( batch >= batchCounts.size() )
508  batchCounts.push_back(1);
509  else
510  ++(batchCounts[batch]);
511  }
512 
513 
514  m_batchStartLengths.resize(batchCounts.size());
515  m_batchStartLengths[0] = BatchPair( 0, 0 );
516 
517 
518  int sum = 0;
519  for( int batchIndex = 0; batchIndex < batchCounts.size(); ++batchIndex )
520  {
521  m_batchStartLengths[batchIndex].start = sum;
522  m_batchStartLengths[batchIndex].length = batchCounts[batchIndex];
523  sum += batchCounts[batchIndex];
524  }
525 
527  // Sort data based on batches
528 
529  // Create source arrays by copying originals
531  btAlignedObjectArray<float> m_area_Backup(m_area);
533 
534 
535  for( int batch = 0; batch < batchCounts.size(); ++batch )
536  batchCounts[batch] = 0;
537 
538  // Do sort as single pass into destination arrays
539  for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
540  {
541  // To maintain locations run off the original link locations rather than the current position.
542  // It's not cache efficient, but as we run this rarely that should not matter.
543  // It's faster than searching the link location array for the current location and then updating it.
544  // The other alternative would be to unsort before resorting, but this is equivalent to doing that.
545  int triangleLocation = m_triangleAddresses[triangleIndex];
546 
547  // Obtain batch and calculate target location for the
548  // next element in that batch, incrementing the batch counter
549  // afterwards
550  int batch = batchValues[triangleIndex];
551  int newLocation = m_batchStartLengths[batch].start + batchCounts[batch];
552 
553  batchCounts[batch] = batchCounts[batch] + 1;
554  m_vertexIndices[newLocation] = m_vertexIndices_Backup[triangleLocation];
555  m_area[newLocation] = m_area_Backup[triangleLocation];
556  m_normal[newLocation] = m_normal_Backup[triangleLocation];
557 
558  // Update the locations array to account for the moved entry
559  m_triangleAddresses[triangleIndex] = newLocation;
560  }
561 } // btSoftBodyTriangleDataDX11::generateBatches
562 
563 
564 
565 
566 
567 
568 
569 
570 
571 
572 
573 
574 btDX11SoftBodySolver::btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory) :
575  m_dx11Device( dx11Device ),
576  m_dx11Context( dx11Context ),
577  dxFunctions( m_dx11Device, m_dx11Context, dx11CompileFromMemory ),
578  m_linkData(m_dx11Device, m_dx11Context),
579  m_vertexData(m_dx11Device, m_dx11Context),
580  m_triangleData(m_dx11Device, m_dx11Context),
581  m_dx11PerClothAcceleration( m_dx11Device, m_dx11Context, &m_perClothAcceleration, true ),
582  m_dx11PerClothWindVelocity( m_dx11Device, m_dx11Context, &m_perClothWindVelocity, true ),
583  m_dx11PerClothDampingFactor( m_dx11Device, m_dx11Context, &m_perClothDampingFactor, true ),
584  m_dx11PerClothVelocityCorrectionCoefficient( m_dx11Device, m_dx11Context, &m_perClothVelocityCorrectionCoefficient, true ),
585  m_dx11PerClothLiftFactor( m_dx11Device, m_dx11Context, &m_perClothLiftFactor, true ),
586  m_dx11PerClothDragFactor( m_dx11Device, m_dx11Context, &m_perClothDragFactor, true ),
587  m_dx11PerClothMediumDensity( m_dx11Device, m_dx11Context, &m_perClothMediumDensity, true ),
588  m_dx11PerClothCollisionObjects( m_dx11Device, m_dx11Context, &m_perClothCollisionObjects, true ),
589  m_dx11CollisionObjectDetails( m_dx11Device, m_dx11Context, &m_collisionObjectDetails, true ),
590  m_dx11PerClothMinBounds( m_dx11Device, m_dx11Context, &m_perClothMinBounds, false ),
591  m_dx11PerClothMaxBounds( m_dx11Device, m_dx11Context, &m_perClothMaxBounds, false ),
592  m_dx11PerClothFriction( m_dx11Device, m_dx11Context, &m_perClothFriction, false ),
593  m_enableUpdateBounds(false)
594 {
595  // Initial we will clearly need to update solver constants
596  // For now this is global for the cloths linked with this solver - we should probably make this body specific
597  // for performance in future once we understand more clearly when constants need to be updated
599 
600  m_shadersInitialized = false;
601 }
602 
604 {
605  releaseKernels();
606 }
607 
609 {
610 
636 
641 
642  m_shadersInitialized = false;
643 }
644 
645 
647 {
648  // Move the vertex data back to the host first
650 
651  // Loop over soft bodies, copying all the vertex positions back for each body in turn
652  for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
653  {
654  btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ];
655  btSoftBody *softBody = softBodyInterface->getSoftBody();
656 
657  int firstVertex = softBodyInterface->getFirstVertex();
658  int numVertices = softBodyInterface->getNumVertices();
659 
660  // Copy vertices from solver back into the softbody
661  for( int vertex = 0; vertex < numVertices; ++vertex )
662  {
664  Point3 vertexPosition( getVertexData().getVertexPositions()[firstVertex + vertex] );
665 
666  softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() );
667  softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() );
668  softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() );
669 
670  softBody->m_nodes[vertex].m_n.setX( vertexPosition.getX() );
671  softBody->m_nodes[vertex].m_n.setY( vertexPosition.getY() );
672  softBody->m_nodes[vertex].m_n.setZ( vertexPosition.getZ() );
673  }
674  }
675 } // btDX11SoftBodySolver::copyBackToSoftBodies
676 
677 
679 {
680  if( forceUpdate || m_softBodySet.size() != softBodies.size() )
681  {
682  // Have a change in the soft body set so update, reloading all the data
683  getVertexData().clear();
685  getLinkData().clear();
686  m_softBodySet.resize(0);
687 
688 
689  for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex )
690  {
691  btSoftBody *softBody = softBodies[ softBodyIndex ];
694 
695  // Create SoftBody that will store the information within the solver
696  btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody );
697  m_softBodySet.push_back( newSoftBody );
698 
705  // Simple init values. Actually we'll put 0 and -1 into them at the appropriate time
706  m_perClothMinBounds.push_back( UIntVector3( 0, 0, 0 ) );
707  m_perClothMaxBounds.push_back( UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX ) );
710 
711  // Add space for new vertices and triangles in the default solver for now
712  // TODO: Include space here for tearing too later
713  int firstVertex = getVertexData().getNumVertices();
714  int numVertices = softBody->m_nodes.size();
715  int maxVertices = numVertices;
716  // Allocate space for new vertices in all the vertex arrays
717  getVertexData().createVertices( maxVertices, softBodyIndex );
718 
719  int firstTriangle = getTriangleData().getNumTriangles();
720  int numTriangles = softBody->m_faces.size();
721  int maxTriangles = numTriangles;
722  getTriangleData().createTriangles( maxTriangles );
723 
724  // Copy vertices from softbody into the solver
725  for( int vertex = 0; vertex < numVertices; ++vertex )
726  {
727  Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ());
729 
730  // TODO: Position in the softbody might be pre-transformed
731  // or we may need to adapt for the pose.
732  //desc.setPosition( cloth.getMeshTransform()*multPoint );
733  desc.setPosition( multPoint );
734 
735  float vertexInverseMass = softBody->m_nodes[vertex].m_im;
736  desc.setInverseMass(vertexInverseMass);
737  getVertexData().setVertexAt( desc, firstVertex + vertex );
738  }
739 
740  // Copy triangles similarly
741  // We're assuming here that vertex indices are based on the firstVertex rather than the entire scene
742  for( int triangle = 0; triangle < numTriangles; ++triangle )
743  {
744  // Note that large array storage is relative to the array not to the cloth
745  // So we need to add firstVertex to each value
746  int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0]));
747  int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0]));
748  int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0]));
749  btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex);
750  getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle );
751 
752  // Increase vertex triangle counts for this triangle
756  }
757 
758  int firstLink = getLinkData().getNumLinks();
759  int numLinks = softBody->m_links.size();
760  int maxLinks = numLinks;
761 
762  // Allocate space for the links
763  getLinkData().createLinks( numLinks );
764 
765  // Add the links
766  for( int link = 0; link < numLinks; ++link )
767  {
768  int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]);
769  int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]);
770 
771  btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST);
772  newLink.setLinkStrength(1.f);
773  getLinkData().setLinkAt(newLink, firstLink + link);
774  }
775 
776  newSoftBody->setFirstVertex( firstVertex );
777  newSoftBody->setFirstTriangle( firstTriangle );
778  newSoftBody->setNumVertices( numVertices );
779  newSoftBody->setMaxVertices( maxVertices );
780  newSoftBody->setNumTriangles( numTriangles );
781  newSoftBody->setMaxTriangles( maxTriangles );
782  newSoftBody->setFirstLink( firstLink );
783  newSoftBody->setNumLinks( numLinks );
784  }
785 
786 
787 
788  updateConstants(0.f);
789 
790 
793  }
794 }
795 
796 
798 {
799  // TODO: Consider setting link data to "changed" here
800  return m_linkData;
801 }
802 
804 {
805  // TODO: Consider setting vertex data to "changed" here
806  return m_vertexData;
807 }
808 
810 {
811  // TODO: Consider setting triangle data to "changed" here
812  return m_triangleData;
813 }
814 
816 {
817  if( !m_shadersInitialized )
818  if( buildShaders() )
819  m_shadersInitialized = true;
820 
821  return m_shadersInitialized;
822 }
823 
825 {
826  // No need to batch link solver, it is entirely parallel
827  // Copy kernel parameters to GPU
828  UpdateSoftBodiesCB constBuffer;
829 
830  constBuffer.numNodes = numVertices;
831  constBuffer.epsilon = FLT_EPSILON;
832 
833  // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
834  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
835  m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
836  memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) );
838  m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer );
839 
840  // Set resources and dispatch
841  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL );
842  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL );
843 
844  // Execute the kernel
845  m_dx11Context->CSSetShader( resetNormalsAndAreasKernel.kernel, NULL, 0 );
846 
847  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
848  m_dx11Context->Dispatch(numBlocks, 1, 1 );
849 
850  {
851  // Tidy up
852  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
853  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
854  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
855 
856  ID3D11Buffer *pBufferNull = NULL;
857  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
858  }
859 } // btDX11SoftBodySolver::resetNormalsAndAreas
860 
862 {
863  // No need to batch link solver, it is entirely parallel
864  // Copy kernel parameters to GPU
865  UpdateSoftBodiesCB constBuffer;
866 
867  constBuffer.numNodes = numVertices;
868  constBuffer.epsilon = FLT_EPSILON;
869 
870  // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
871  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
872  m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
873  memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) );
875  m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer );
876 
877  // Set resources and dispatch
878  m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexTriangleCount.getSRV()) );
879 
880  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL );
881  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL );
882 
883  // Execute the kernel
884  m_dx11Context->CSSetShader( normalizeNormalsAndAreasKernel.kernel, NULL, 0 );
885 
886  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
887  m_dx11Context->Dispatch(numBlocks, 1, 1 );
888 
889  {
890  // Tidy up
891  ID3D11ShaderResourceView* pViewNULL = NULL;
892  m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
893 
894  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
895  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
896  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
897 
898  ID3D11Buffer *pBufferNull = NULL;
899  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
900  }
901 } // btDX11SoftBodySolver::normalizeNormalsAndAreas
902 
903 void btDX11SoftBodySolver::executeUpdateSoftBodies( int firstTriangle, int numTriangles )
904 {
905  // No need to batch link solver, it is entirely parallel
906  // Copy kernel parameters to GPU
907  UpdateSoftBodiesCB constBuffer;
908 
909  constBuffer.startFace = firstTriangle;
910  constBuffer.numFaces = numTriangles;
911 
912  // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
913  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
914  m_dx11Context->Map( updateSoftBodiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
915  memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateSoftBodiesCB) );
917  m_dx11Context->CSSetConstantBuffers( 0, 1, &updateSoftBodiesKernel.constBuffer );
918 
919  // Set resources and dispatch
920  m_dx11Context->CSSetShaderResources( 0, 1, &(m_triangleData.m_dx11VertexIndices.getSRV()) );
921  m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) );
922 
923  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexNormal.getUAV()), NULL );
924  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexArea.getUAV()), NULL );
925  m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_triangleData.m_dx11Normal.getUAV()), NULL );
926  m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_triangleData.m_dx11Area.getUAV()), NULL );
927 
928  // Execute the kernel
929  m_dx11Context->CSSetShader( updateSoftBodiesKernel.kernel, NULL, 0 );
930 
931  int numBlocks = (numTriangles + (128-1)) / 128;
932  m_dx11Context->Dispatch(numBlocks, 1, 1 );
933 
934  {
935  // Tidy up
936  ID3D11ShaderResourceView* pViewNULL = NULL;
937  m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL );
938 
939  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
940  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
941  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
942 
943  ID3D11Buffer *pBufferNull = NULL;
944  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
945  }
946 } // btDX11SoftBodySolver::executeUpdateSoftBodies
947 
949 {
950  using namespace Vectormath::Aos;
951 
952 
953  int numVertices = m_vertexData.getNumVertices();
954  int numTriangles = m_triangleData.getNumTriangles();
955 
956  // Ensure data is on accelerator
959 
960  resetNormalsAndAreas( numVertices );
961 
962 
963  // Go through triangle batches so updates occur correctly
964  for( int batchIndex = 0; batchIndex < m_triangleData.m_batchStartLengths.size(); ++batchIndex )
965  {
966 
967  int startTriangle = m_triangleData.m_batchStartLengths[batchIndex].start;
968  int numTriangles = m_triangleData.m_batchStartLengths[batchIndex].length;
969 
970  executeUpdateSoftBodies( startTriangle, numTriangles );
971  }
972 
973 
974  normalizeNormalsAndAreas( numVertices );
975 
976 
977 } // btDX11SoftBodySolver::updateSoftBodies
978 
979 
981 {
982  return a*Vectormath::Aos::dot(v, a);
983 }
984 
985 void btDX11SoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce )
986 {
987  float dtInverseMass = solverdt*inverseMass;
988  if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) )
989  {
990  vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass;
991  } else {
992  vertexForce += force;
993  }
994 }
995 
996 void btDX11SoftBodySolver::applyForces( float solverdt )
997 {
998  using namespace Vectormath::Aos;
999 
1000 
1001  // Ensure data is on accelerator
1008 
1009  // No need to batch link solver, it is entirely parallel
1010  // Copy kernel parameters to GPU
1011  ApplyForcesCB constBuffer;
1012 
1013  constBuffer.numNodes = m_vertexData.getNumVertices();
1014  constBuffer.solverdt = solverdt;
1015  constBuffer.epsilon = FLT_EPSILON;
1016 
1017  // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
1018  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1019  m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1020  memcpy( MappedResource.pData, &constBuffer, sizeof(ApplyForcesCB) );
1022  m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer );
1023 
1024  // Set resources and dispatch
1025  m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
1026  m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexNormal.getSRV()) );
1027  m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexArea.getSRV()) );
1028  m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) );
1029  m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothLiftFactor.getSRV()) );
1030  m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11PerClothDragFactor.getSRV()) );
1031  m_dx11Context->CSSetShaderResources( 6, 1, &(m_dx11PerClothWindVelocity.getSRV()) );
1032  m_dx11Context->CSSetShaderResources( 7, 1, &(m_dx11PerClothAcceleration.getSRV()) );
1033  m_dx11Context->CSSetShaderResources( 8, 1, &(m_dx11PerClothMediumDensity.getSRV()) );
1034 
1035  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
1036  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
1037 
1038  // Execute the kernel
1039  m_dx11Context->CSSetShader( applyForcesKernel.kernel, NULL, 0 );
1040 
1041  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
1042  m_dx11Context->Dispatch(numBlocks, 1, 1 );
1043 
1044  {
1045  // Tidy up
1046  ID3D11ShaderResourceView* pViewNULL = NULL;
1047  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1048  m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1049  m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
1050  m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
1051  m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL );
1052  m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL );
1053  m_dx11Context->CSSetShaderResources( 6, 1, &pViewNULL );
1054  m_dx11Context->CSSetShaderResources( 7, 1, &pViewNULL );
1055  m_dx11Context->CSSetShaderResources( 8, 1, &pViewNULL );
1056 
1057  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1058  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1059  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
1060 
1061  ID3D11Buffer *pBufferNull = NULL;
1062  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1063  }
1064 } // btDX11SoftBodySolver::applyForces
1065 
1069 void btDX11SoftBodySolver::integrate( float solverdt )
1070 {
1071  // TEMPORARY COPIES
1073 
1074  // No need to batch link solver, it is entirely parallel
1075  // Copy kernel parameters to GPU
1076  IntegrateCB constBuffer;
1077 
1078  constBuffer.numNodes = m_vertexData.getNumVertices();
1079  constBuffer.solverdt = solverdt;
1080 
1081  // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
1082  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1083  m_dx11Context->Map( integrateKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1084  memcpy( MappedResource.pData, &constBuffer, sizeof(IntegrateCB) );
1086  m_dx11Context->CSSetConstantBuffers( 0, 1, &integrateKernel.constBuffer );
1087 
1088  // Set resources and dispatch
1089  m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) );
1090 
1091  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL );
1092  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
1093  m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL );
1094  m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
1095 
1096  // Execute the kernel
1097  m_dx11Context->CSSetShader( integrateKernel.kernel, NULL, 0 );
1098 
1099  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
1100  m_dx11Context->Dispatch(numBlocks, 1, 1 );
1101 
1102  {
1103  // Tidy up
1104  ID3D11ShaderResourceView* pViewNULL = NULL;
1105  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1106 
1107  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1108  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1109  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
1110  m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL );
1111  m_dx11Context->CSSetUnorderedAccessViews( 3, 1, &pUAViewNULL, NULL );
1112 
1113  ID3D11Buffer *pBufferNull = NULL;
1114  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1115  }
1116 } // btDX11SoftBodySolver::integrate
1117 
1119  const Vectormath::Aos::Point3 &vertex0,
1120  const Vectormath::Aos::Point3 &vertex1,
1121  const Vectormath::Aos::Point3 &vertex2 )
1122 {
1123  Vectormath::Aos::Vector3 a = vertex1 - vertex0;
1124  Vectormath::Aos::Vector3 b = vertex2 - vertex0;
1125  Vectormath::Aos::Vector3 crossProduct = cross(a, b);
1126  float area = length( crossProduct );
1127  return area;
1128 } // btDX11SoftBodySolver::computeTriangleArea
1129 
1130 
1132 {
1134  // Interpretation structure for float and int
1135 
1136  struct FPRep {
1137  unsigned int mantissa : 23;
1138  unsigned int exponent : 8;
1139  unsigned int sign : 1;
1140  };
1141  union FloatAsInt
1142  {
1143  float floatValue;
1144  int intValue;
1145  unsigned int uintValue;
1146  FPRep fpRep;
1147  };
1148 
1149 
1150  // Update bounds array to min and max int values to allow easy atomics
1151  for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
1152  {
1153  m_perClothMinBounds[softBodyIndex] = UIntVector3( UINT_MAX, UINT_MAX, UINT_MAX );
1154  m_perClothMaxBounds[softBodyIndex] = UIntVector3( 0, 0, 0 );
1155  }
1156 
1157  m_dx11PerClothMinBounds.moveToGPU();
1158  m_dx11PerClothMaxBounds.moveToGPU();
1159 
1160 
1161  computeBounds( );
1162 
1163 
1164  m_dx11PerClothMinBounds.moveFromGPU();
1165  m_dx11PerClothMaxBounds.moveFromGPU();
1166 
1167 
1168 
1169  for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
1170  {
1171  UIntVector3 minBoundUInt = m_perClothMinBounds[softBodyIndex];
1172  UIntVector3 maxBoundUInt = m_perClothMaxBounds[softBodyIndex];
1173 
1174  // Convert back to float
1175  FloatAsInt fai;
1176 
1177  btVector3 minBound;
1178  fai.uintValue = minBoundUInt.x;
1179  fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
1180  minBound.setX( fai.floatValue );
1181  fai.uintValue = minBoundUInt.y;
1182  fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
1183  minBound.setY( fai.floatValue );
1184  fai.uintValue = minBoundUInt.z;
1185  fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
1186  minBound.setZ( fai.floatValue );
1187 
1188  btVector3 maxBound;
1189  fai.uintValue = maxBoundUInt.x;
1190  fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
1191  maxBound.setX( fai.floatValue );
1192  fai.uintValue = maxBoundUInt.y;
1193  fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
1194  maxBound.setY( fai.floatValue );
1195  fai.uintValue = maxBoundUInt.z;
1196  fai.uintValue ^= (((fai.uintValue >> 31) - 1) | 0x80000000);
1197  maxBound.setZ( fai.floatValue );
1198 
1199  // And finally assign to the soft body
1200  m_softBodySet[softBodyIndex]->updateBounds( minBound, maxBound );
1201  }
1202 }
1203 
1205 {
1206  using namespace Vectormath::Aos;
1207 
1209  {
1210  m_updateSolverConstants = false;
1211 
1212  // Will have to redo this if we change the structure (tear, maybe) or various other possible changes
1213 
1214  // Initialise link constants
1215  const int numLinks = m_linkData.getNumLinks();
1216  for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
1217  {
1219  m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 )));
1220  float invMass0 = m_vertexData.getInverseMass(vertices.vertex0);
1221  float invMass1 = m_vertexData.getInverseMass(vertices.vertex1);
1222  float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex);
1223  float massLSC = (invMass0 + invMass1)/linearStiffness;
1224  m_linkData.getMassLSC(linkIndex) = massLSC;
1225  float restLength = m_linkData.getRestLength(linkIndex);
1226  float restLengthSquared = restLength*restLength;
1227  m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared;
1228  }
1229  }
1230 } // btDX11SoftBodySolver::updateConstants
1231 
1236 {
1237  // First do a simple sort on the collision objects
1238  btAlignedObjectArray<int> numObjectsPerClothPrefixSum;
1239  btAlignedObjectArray<int> numObjectsPerCloth;
1240  numObjectsPerCloth.resize( m_softBodySet.size(), 0 );
1241  numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 );
1242 
1243 
1244  class QuickSortCompare
1245  {
1246  public:
1247 
1248  bool operator() ( const CollisionShapeDescription& a, const CollisionShapeDescription& b ) const
1249  {
1250  return ( a.softBodyIdentifier < b.softBodyIdentifier );
1251  }
1252  };
1253 
1254  QuickSortCompare comparator;
1255  m_collisionObjectDetails.quickSort( comparator );
1256 
1257  // Generating indexing for perClothCollisionObjects
1258  // First clear the previous values with the "no collision object for cloth" constant
1259  for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex )
1260  {
1261  m_perClothCollisionObjects[clothIndex].firstObject = -1;
1262  m_perClothCollisionObjects[clothIndex].endObject = -1;
1263  }
1264  int currentCloth = 0;
1265  int startIndex = 0;
1266  for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject )
1267  {
1268  int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier;
1269  if( nextCloth != currentCloth )
1270  {
1271  // Changed cloth in the array
1272  // Set the end index and the range is what we need for currentCloth
1273  m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
1274  m_perClothCollisionObjects[currentCloth].endObject = collisionObject;
1275  currentCloth = nextCloth;
1276  startIndex = collisionObject;
1277  }
1278  }
1279 
1280  // And update last cloth
1281  m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
1282  m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size();
1283 
1284 } // btDX11SoftBodySolver::prepareCollisionConstraints
1285 
1286 
1288 {
1289 
1290  //std::cerr << "'GPU' solve constraints\n";
1294  using Vectormath::Aos::dot;
1295 
1296  // Prepare links
1297  int numLinks = m_linkData.getNumLinks();
1298  int numVertices = m_vertexData.getNumVertices();
1299 
1300  float kst = 1.f;
1301  float ti = 0.f;
1302 
1303 
1306 
1307 
1308  // Ensure data is on accelerator
1311 
1312 
1313  prepareLinks();
1314 
1315  for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration )
1316  {
1317  for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i )
1318  {
1319  int startLink = m_linkData.m_batchStartLengths[i].start;
1320  int numLinks = m_linkData.m_batchStartLengths[i].length;
1321 
1322  solveLinksForVelocity( startLink, numLinks, kst );
1323  }
1324  }
1325 
1326 
1328 
1329  // Compute new positions from velocity
1330  // Also update the previous position so that our position computation is now based on the new position from the velocity solution
1331  // rather than based directly on the original positions
1332  if( m_numberOfVelocityIterations > 0 )
1333  {
1335  } else {
1337  }
1338 
1339 
1340  // Solve drift
1341  for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration )
1342  {
1343  for( int i = 0; i < m_linkData.m_batchStartLengths.size(); ++i )
1344  {
1345  int startLink = m_linkData.m_batchStartLengths[i].start;
1346  int numLinks = m_linkData.m_batchStartLengths[i].length;
1347 
1348  solveLinksForPosition( startLink, numLinks, kst, ti );
1349  }
1350 
1351  } // for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration )
1352 
1353  // At this point assume that the force array is blank - we will overwrite it
1354  solveCollisionsAndUpdateVelocities( 1.f/solverdt );
1355 } // btDX11SoftBodySolver::solveConstraints
1356 
1357 
1358 
1359 
1361 // Kernel dispatches
1363 {
1364  // No need to batch link solver, it is entirely parallel
1365  // Copy kernel parameters to GPU
1366  PrepareLinksCB constBuffer;
1367 
1368  constBuffer.numLinks = m_linkData.getNumLinks();
1369 
1370  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1371  m_dx11Context->Map( prepareLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1372  memcpy( MappedResource.pData, &constBuffer, sizeof(PrepareLinksCB) );
1374  m_dx11Context->CSSetConstantBuffers( 0, 1, &prepareLinksKernel.constBuffer );
1375 
1376  // Set resources and dispatch
1377  m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) );
1378  m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) );
1379  m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) );
1380 
1381  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_linkData.m_dx11LinksLengthRatio.getUAV()), NULL );
1382  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_linkData.m_dx11LinksCLength.getUAV()), NULL );
1383 
1384  // Execute the kernel
1385  m_dx11Context->CSSetShader( prepareLinksKernel.kernel, NULL, 0 );
1386 
1387  int numBlocks = (constBuffer.numLinks + (128-1)) / 128;
1388  m_dx11Context->Dispatch(numBlocks , 1, 1 );
1389 
1390  {
1391  // Tidy up
1392  ID3D11ShaderResourceView* pViewNULL = NULL;
1393  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1394  m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1395  m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
1396 
1397  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1398  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1399  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
1400 
1401  ID3D11Buffer *pBufferNull = NULL;
1402  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1403  }
1404 } // btDX11SoftBodySolver::prepareLinks
1405 
1406 
1408 {
1409  // No need to batch link solver, it is entirely parallel
1410  // Copy kernel parameters to GPU
1411  UpdatePositionsFromVelocitiesCB constBuffer;
1412 
1413  constBuffer.numNodes = m_vertexData.getNumVertices();
1414  constBuffer.solverSDT = solverdt;
1415 
1416  // Todo: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
1417  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1418  m_dx11Context->Map( updatePositionsFromVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1419  memcpy( MappedResource.pData, &constBuffer, sizeof(UpdatePositionsFromVelocitiesCB) );
1421  m_dx11Context->CSSetConstantBuffers( 0, 1, &updatePositionsFromVelocitiesKernel.constBuffer );
1422 
1423  // Set resources and dispatch
1424  m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getSRV()) );
1425 
1426  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getUAV()), NULL );
1427  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL );
1428 
1429  // Execute the kernel
1430  m_dx11Context->CSSetShader( updatePositionsFromVelocitiesKernel.kernel, NULL, 0 );
1431 
1432  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
1433  m_dx11Context->Dispatch(numBlocks, 1, 1 );
1434 
1435  {
1436  // Tidy up
1437  ID3D11ShaderResourceView* pViewNULL = NULL;
1438  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1439 
1440  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1441  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1442  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
1443 
1444  ID3D11Buffer *pBufferNull = NULL;
1445  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1446  }
1447 } // btDX11SoftBodySolver::updatePositionsFromVelocities
1448 
1449 void btDX11SoftBodySolver::solveLinksForPosition( int startLink, int numLinks, float kst, float ti )
1450 {
1451  // Copy kernel parameters to GPU
1452  SolvePositionsFromLinksKernelCB constBuffer;
1453 
1454  // Set the first link of the batch
1455  // and the batch size
1456  constBuffer.startLink = startLink;
1457  constBuffer.numLinks = numLinks;
1458 
1459  constBuffer.kst = kst;
1460  constBuffer.ti = ti;
1461 
1462  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1463  m_dx11Context->Map( solvePositionsFromLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1464  memcpy( MappedResource.pData, &constBuffer, sizeof(SolvePositionsFromLinksKernelCB) );
1466  m_dx11Context->CSSetConstantBuffers( 0, 1, &solvePositionsFromLinksKernel.constBuffer );
1467 
1468  // Set resources and dispatch
1469  m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) );
1470  m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksMassLSC.getSRV()) );
1471  m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksRestLengthSquared.getSRV()) );
1472  m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) );
1473 
1474  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL );
1475 
1476  // Execute the kernel
1477  m_dx11Context->CSSetShader( solvePositionsFromLinksKernel.kernel, NULL, 0 );
1478 
1479  int numBlocks = (constBuffer.numLinks + (128-1)) / 128;
1480  m_dx11Context->Dispatch(numBlocks , 1, 1 );
1481 
1482  {
1483  // Tidy up
1484  ID3D11ShaderResourceView* pViewNULL = NULL;
1485  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1486  m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1487  m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
1488  m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
1489 
1490  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1491  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1492 
1493  ID3D11Buffer *pBufferNull = NULL;
1494  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1495  }
1496 
1497 } // btDX11SoftBodySolver::solveLinksForPosition
1498 
1499 void btDX11SoftBodySolver::solveLinksForVelocity( int startLink, int numLinks, float kst )
1500 {
1501  // Copy kernel parameters to GPU
1502  VSolveLinksCB constBuffer;
1503 
1504  // Set the first link of the batch
1505  // and the batch size
1506 
1507  constBuffer.startLink = startLink;
1508  constBuffer.numLinks = numLinks;
1509  constBuffer.kst = kst;
1510 
1511  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1512  m_dx11Context->Map( vSolveLinksKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1513  memcpy( MappedResource.pData, &constBuffer, sizeof(VSolveLinksCB) );
1515  m_dx11Context->CSSetConstantBuffers( 0, 1, &vSolveLinksKernel.constBuffer );
1516 
1517  // Set resources and dispatch
1518  m_dx11Context->CSSetShaderResources( 0, 1, &(m_linkData.m_dx11Links.getSRV()) );
1519  m_dx11Context->CSSetShaderResources( 1, 1, &(m_linkData.m_dx11LinksLengthRatio.getSRV()) );
1520  m_dx11Context->CSSetShaderResources( 2, 1, &(m_linkData.m_dx11LinksCLength.getSRV()) );
1521  m_dx11Context->CSSetShaderResources( 3, 1, &(m_vertexData.m_dx11VertexInverseMass.getSRV()) );
1522 
1523  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
1524 
1525  // Execute the kernel
1526  m_dx11Context->CSSetShader( vSolveLinksKernel.kernel, NULL, 0 );
1527 
1528  int numBlocks = (constBuffer.numLinks + (128-1)) / 128;
1529  m_dx11Context->Dispatch(numBlocks , 1, 1 );
1530 
1531  {
1532  // Tidy up
1533  ID3D11ShaderResourceView* pViewNULL = NULL;
1534  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1535  m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1536  m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
1537  m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
1538 
1539  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1540  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1541 
1542  ID3D11Buffer *pBufferNull = NULL;
1543  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1544  }
1545 } // btDX11SoftBodySolver::solveLinksForVelocity
1546 
1547 
1549 {
1550  // Copy kernel parameters to GPU
1552 
1553  // Set the first link of the batch
1554  // and the batch size
1555  constBuffer.numNodes = m_vertexData.getNumVertices();
1556  constBuffer.isolverdt = isolverdt;
1557 
1558  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1559  m_dx11Context->Map( updateVelocitiesFromPositionsWithVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1560  memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) );
1563 
1564  // Set resources and dispatch
1565  m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) );
1566  m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) );
1567  m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
1568  m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothVelocityCorrectionCoefficient.getSRV()) );
1569  m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothDampingFactor.getSRV()) );
1570 
1571  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
1572  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
1573 
1574 
1575  // Execute the kernel
1577 
1578  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
1579  m_dx11Context->Dispatch(numBlocks , 1, 1 );
1580 
1581  {
1582  // Tidy up
1583  ID3D11ShaderResourceView* pViewNULL = NULL;
1584  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1585  m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1586  m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
1587  m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
1588  m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL );
1589 
1590  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1591  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1592  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
1593 
1594  ID3D11Buffer *pBufferNull = NULL;
1595  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1596  }
1597 
1598 } // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithVelocities
1599 
1601 {
1602  // Copy kernel parameters to GPU
1604 
1605  // Set the first link of the batch
1606  // and the batch size
1607  constBuffer.numNodes = m_vertexData.getNumVertices();
1608  constBuffer.isolverdt = isolverdt;
1609 
1610  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1611  m_dx11Context->Map( updateVelocitiesFromPositionsWithoutVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1612  memcpy( MappedResource.pData, &constBuffer, sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) );
1615 
1616  // Set resources and dispatch
1617  m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) );
1618  m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) );
1619  m_dx11Context->CSSetShaderResources( 2, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
1620  m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) );
1621 
1622  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
1623  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
1624 
1625 
1626  // Execute the kernel
1628 
1629  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
1630  m_dx11Context->Dispatch(numBlocks , 1, 1 );
1631 
1632  {
1633  // Tidy up
1634  ID3D11ShaderResourceView* pViewNULL = NULL;
1635  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1636  m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1637  m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
1638  m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
1639 
1640  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1641  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1642  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
1643 
1644  ID3D11Buffer *pBufferNull = NULL;
1645  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1646  }
1647 
1648 } // btDX11SoftBodySolver::updateVelocitiesFromPositionsWithoutVelocities
1649 
1650 
1652 {
1653  ComputeBoundsCB constBuffer;
1655 
1656  // Set the first link of the batch
1657  // and the batch size
1658  constBuffer.numNodes = m_vertexData.getNumVertices();
1659  constBuffer.numSoftBodies = m_softBodySet.size();
1660 
1661  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1662  m_dx11Context->Map( computeBoundsKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1663  memcpy( MappedResource.pData, &constBuffer, sizeof(ComputeBoundsCB) );
1665  m_dx11Context->CSSetConstantBuffers( 0, 1, &computeBoundsKernel.constBuffer );
1666 
1667  // Set resources and dispatch
1668  m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
1669  m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPosition.getSRV()) );
1670 
1671  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_dx11PerClothMinBounds.getUAV()), NULL );
1672  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_dx11PerClothMaxBounds.getUAV()), NULL );
1673 
1674  // Execute the kernel
1675  m_dx11Context->CSSetShader( computeBoundsKernel.kernel, NULL, 0 );
1676 
1677  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
1678  m_dx11Context->Dispatch(numBlocks , 1, 1 );
1679 
1680  {
1681  // Tidy up
1682  ID3D11ShaderResourceView* pViewNULL = NULL;
1683  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1684  m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1685 
1686  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1687  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1688  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
1689 
1690  ID3D11Buffer *pBufferNull = NULL;
1691  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1692  }
1693 }
1694 
1696 {
1697 
1698  // Copy kernel parameters to GPU
1702  m_dx11PerClothCollisionObjects.moveToGPU();
1703  m_dx11CollisionObjectDetails.moveToGPU();
1704 
1706 
1707  // Set the first link of the batch
1708  // and the batch size
1709  constBuffer.numNodes = m_vertexData.getNumVertices();
1710  constBuffer.isolverdt = isolverdt;
1711 
1712 
1713  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1714  m_dx11Context->Map( solveCollisionsAndUpdateVelocitiesKernel.constBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1715  memcpy( MappedResource.pData, &constBuffer, sizeof(SolveCollisionsAndUpdateVelocitiesCB) );
1717  m_dx11Context->CSSetConstantBuffers( 0, 1, &solveCollisionsAndUpdateVelocitiesKernel.constBuffer );
1718 
1719  // Set resources and dispatch
1720  m_dx11Context->CSSetShaderResources( 0, 1, &(m_vertexData.m_dx11ClothIdentifier.getSRV()) );
1721  m_dx11Context->CSSetShaderResources( 1, 1, &(m_vertexData.m_dx11VertexPreviousPosition.getSRV()) );
1722  m_dx11Context->CSSetShaderResources( 2, 1, &(m_dx11PerClothFriction.getSRV()) );
1723  m_dx11Context->CSSetShaderResources( 3, 1, &(m_dx11PerClothDampingFactor.getSRV()) );
1724  m_dx11Context->CSSetShaderResources( 4, 1, &(m_dx11PerClothCollisionObjects.getSRV()) );
1725  m_dx11Context->CSSetShaderResources( 5, 1, &(m_dx11CollisionObjectDetails.getSRV()) );
1726 
1727  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(m_vertexData.m_dx11VertexForceAccumulator.getUAV()), NULL );
1728  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &(m_vertexData.m_dx11VertexVelocity.getUAV()), NULL );
1729  m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &(m_vertexData.m_dx11VertexPosition.getUAV()), NULL );
1730 
1731  // Execute the kernel
1733 
1734  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
1735  m_dx11Context->Dispatch(numBlocks , 1, 1 );
1736 
1737  {
1738  // Tidy up
1739  ID3D11ShaderResourceView* pViewNULL = NULL;
1740  m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1741  m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1742  m_dx11Context->CSSetShaderResources( 2, 1, &pViewNULL );
1743  m_dx11Context->CSSetShaderResources( 3, 1, &pViewNULL );
1744  m_dx11Context->CSSetShaderResources( 4, 1, &pViewNULL );
1745  m_dx11Context->CSSetShaderResources( 5, 1, &pViewNULL );
1746 
1747  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1748  m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1749  m_dx11Context->CSSetUnorderedAccessViews( 1, 1, &pUAViewNULL, NULL );
1750  m_dx11Context->CSSetUnorderedAccessViews( 2, 1, &pUAViewNULL, NULL );
1751 
1752  ID3D11Buffer *pBufferNull = NULL;
1753  m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1754  }
1755 
1756 } // btDX11SoftBodySolver::solveCollisionsAndUpdateVelocities
1757 
1758 // End kernel dispatches
1760 
1761 
1762 
1763 
1764 
1765 
1766 
1767 
1768 
1769 
1770 
1771 
1772 
1773 
1775 {
1776  for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
1777  {
1778  btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
1779  if( softBodyInterface->getSoftBody() == softBody )
1780  return softBodyInterface;
1781  }
1782  return 0;
1783 }
1784 
1786 {
1787  for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
1788  {
1789  btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
1790  if( softBodyInterface->getSoftBody() == softBody )
1791  return softBodyInterface;
1792  }
1793  return 0;
1794 }
1795 
1797 {
1798  for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
1799  {
1800  btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
1801  if( softBodyInterface->getSoftBody() == softBody )
1802  return softBodyIndex;
1803  }
1804  return 1;
1805 }
1806 
1807 
1809 {
1810 
1811 
1812  btSoftBodySolver *solver = softBody->getSoftBodySolver();
1814  btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver );
1815 
1816  btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody );
1817  btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData );
1818 
1819 
1820  const int firstVertex = currentCloth->getFirstVertex();
1821  const int lastVertex = firstVertex + currentCloth->getNumVertices();
1822 
1823  if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
1824  {
1825  // If we're doing a CPU-buffer copy must copy the data back to the host first
1826  vertexData.m_dx11VertexPosition.copyFromGPU();
1827  vertexData.m_dx11VertexNormal.copyFromGPU();
1828 
1829  const int firstVertex = currentCloth->getFirstVertex();
1830  const int lastVertex = firstVertex + currentCloth->getNumVertices();
1831  const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer);
1832  float *basePointer = cpuVertexBuffer->getBasePointer();
1833 
1834  if( vertexBuffer->hasVertexPositions() )
1835  {
1836  const int vertexOffset = cpuVertexBuffer->getVertexOffset();
1837  const int vertexStride = cpuVertexBuffer->getVertexStride();
1838  float *vertexPointer = basePointer + vertexOffset;
1839 
1840  for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
1841  {
1842  Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex);
1843  *(vertexPointer + 0) = position.getX();
1844  *(vertexPointer + 1) = position.getY();
1845  *(vertexPointer + 2) = position.getZ();
1846  vertexPointer += vertexStride;
1847  }
1848  }
1849  if( vertexBuffer->hasNormals() )
1850  {
1851  const int normalOffset = cpuVertexBuffer->getNormalOffset();
1852  const int normalStride = cpuVertexBuffer->getNormalStride();
1853  float *normalPointer = basePointer + normalOffset;
1854 
1855  for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
1856  {
1857  Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex);
1858  *(normalPointer + 0) = normal.getX();
1859  *(normalPointer + 1) = normal.getY();
1860  *(normalPointer + 2) = normal.getZ();
1861  normalPointer += normalStride;
1862  }
1863  }
1864  }
1865 } // btDX11SoftBodySolver::outputToVertexBuffers
1866 
1867 
1868 
1870 {
1871  if( !m_shadersInitialized )
1872  if( buildShaders() )
1873  m_shadersInitialized = true;
1874 
1875  return m_shadersInitialized;
1876 }
1877 
1879 {
1880  SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.constBuffer );
1881  SAFE_RELEASE( outputToVertexArrayWithNormalsKernel.kernel );
1882  SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.constBuffer );
1883  SAFE_RELEASE( outputToVertexArrayWithoutNormalsKernel.kernel );
1884 
1885  m_shadersInitialized = false;
1886 }
1887 
1888 
1890 {
1891  // Ensure current kernels are released first
1892  releaseKernels();
1893 
1894  bool returnVal = true;
1895 
1896  if( m_shadersInitialized )
1897  return true;
1898 
1899 
1900  outputToVertexArrayWithNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithNormalsKernel", sizeof(OutputToVertexArrayCB) );
1901  if( !outputToVertexArrayWithNormalsKernel.constBuffer)
1902  returnVal = false;
1903  outputToVertexArrayWithoutNormalsKernel = dxFunctions.compileComputeShaderFromString( OutputToVertexArrayHLSLString, "OutputToVertexArrayWithoutNormalsKernel", sizeof(OutputToVertexArrayCB) );
1904  if( !outputToVertexArrayWithoutNormalsKernel.constBuffer )
1905  returnVal = false;
1906 
1907 
1908  if( returnVal )
1909  m_shadersInitialized = true;
1910 
1911  return returnVal;
1912 }
1913 
1914 
1916 {
1917 
1918 
1919  btSoftBodySolver *solver = softBody->getSoftBodySolver();
1921  btDX11SoftBodySolver *dxSolver = static_cast< btDX11SoftBodySolver * >( solver );
1922  checkInitialized();
1923  btDX11SoftBodySolver::btAcceleratedSoftBodyInterface * currentCloth = dxSolver->findSoftBodyInterface( softBody );
1924  btSoftBodyVertexDataDX11 &vertexData( dxSolver->m_vertexData );
1925 
1926 
1927  const int firstVertex = currentCloth->getFirstVertex();
1928  const int lastVertex = firstVertex + currentCloth->getNumVertices();
1929 
1930  if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
1931  {
1933  } else if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::DX11_BUFFER )
1934  {
1935  // Do a DX11 copy shader DX to DX copy
1936 
1937  const btDX11VertexBufferDescriptor *dx11VertexBuffer = static_cast< btDX11VertexBufferDescriptor* >(vertexBuffer);
1938 
1939  // No need to batch link solver, it is entirely parallel
1940  // Copy kernel parameters to GPU
1941  OutputToVertexArrayCB constBuffer;
1942  ID3D11ComputeShader* outputToVertexArrayShader = outputToVertexArrayWithoutNormalsKernel.kernel;
1943  ID3D11Buffer* outputToVertexArrayConstBuffer = outputToVertexArrayWithoutNormalsKernel.constBuffer;
1944 
1945  constBuffer.startNode = firstVertex;
1946  constBuffer.numNodes = currentCloth->getNumVertices();
1947  constBuffer.positionOffset = vertexBuffer->getVertexOffset();
1948  constBuffer.positionStride = vertexBuffer->getVertexStride();
1949  if( vertexBuffer->hasNormals() )
1950  {
1951  constBuffer.normalOffset = vertexBuffer->getNormalOffset();
1952  constBuffer.normalStride = vertexBuffer->getNormalStride();
1953  outputToVertexArrayShader = outputToVertexArrayWithNormalsKernel.kernel;
1954  outputToVertexArrayConstBuffer = outputToVertexArrayWithNormalsKernel.constBuffer;
1955  }
1956 
1957  // TODO: factor this out. Number of nodes is static and sdt might be, too, we can update this just once on setup
1958  D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
1959  dxFunctions.m_dx11Context->Map( outputToVertexArrayConstBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );
1960  memcpy( MappedResource.pData, &constBuffer, sizeof(OutputToVertexArrayCB) );
1961  dxFunctions.m_dx11Context->Unmap( outputToVertexArrayConstBuffer, 0 );
1962  dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &outputToVertexArrayConstBuffer );
1963 
1964  // Set resources and dispatch
1965  dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &(vertexData.m_dx11VertexPosition.getSRV()) );
1966  dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &(vertexData.m_dx11VertexNormal.getSRV()) );
1967 
1968  ID3D11UnorderedAccessView* dx11UAV = dx11VertexBuffer->getDX11UAV();
1969  dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &(dx11UAV), NULL );
1970 
1971  // Execute the kernel
1972  dxFunctions.m_dx11Context->CSSetShader( outputToVertexArrayShader, NULL, 0 );
1973 
1974  int numBlocks = (constBuffer.numNodes + (128-1)) / 128;
1975  dxFunctions.m_dx11Context->Dispatch(numBlocks, 1, 1 );
1976 
1977  {
1978  // Tidy up
1979  ID3D11ShaderResourceView* pViewNULL = NULL;
1980  dxFunctions.m_dx11Context->CSSetShaderResources( 0, 1, &pViewNULL );
1981  dxFunctions.m_dx11Context->CSSetShaderResources( 1, 1, &pViewNULL );
1982 
1983  ID3D11UnorderedAccessView* pUAViewNULL = NULL;
1984  dxFunctions.m_dx11Context->CSSetUnorderedAccessViews( 0, 1, &pUAViewNULL, NULL );
1985 
1986  ID3D11Buffer *pBufferNull = NULL;
1987  dxFunctions.m_dx11Context->CSSetConstantBuffers( 0, 1, &pBufferNull );
1988  }
1989  }
1990 } // btDX11SoftBodySolver::outputToVertexBuffers
1991 
1992 
1993 
1994 
1995 DXFunctions::KernelDesc DXFunctions::compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros )
1996 {
1997  const char *cs5String = "cs_5_0";
1998 
1999  HRESULT hr = S_OK;
2000  ID3DBlob* pErrorBlob = NULL;
2001  ID3DBlob* pBlob = NULL;
2002  ID3D11ComputeShader* kernelPointer = 0;
2003 
2004  hr = m_dx11CompileFromMemory(
2005  shaderString,
2006  strlen(shaderString),
2007  shaderName,
2008  compileMacros,
2009  NULL,
2010  shaderName,
2011  cs5String,
2012  D3D10_SHADER_ENABLE_STRICTNESS,
2013  NULL,
2014  NULL,
2015  &pBlob,
2016  &pErrorBlob,
2017  NULL
2018  );
2019 
2020  if( FAILED(hr) )
2021  {
2022  if( pErrorBlob ) {
2023  btAssert( "Compilation of compute shader failed\n" );
2024  char *debugString = (char*)pErrorBlob->GetBufferPointer();
2025  OutputDebugStringA( debugString );
2026  }
2027 
2028  SAFE_RELEASE( pErrorBlob );
2029  SAFE_RELEASE( pBlob );
2030 
2031  DXFunctions::KernelDesc descriptor;
2032  descriptor.kernel = 0;
2033  descriptor.constBuffer = 0;
2034  return descriptor;
2035  }
2036 
2037  // Create the Compute Shader
2038  hr = m_dx11Device->CreateComputeShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &kernelPointer );
2039  if( FAILED( hr ) )
2040  {
2041  DXFunctions::KernelDesc descriptor;
2042  descriptor.kernel = 0;
2043  descriptor.constBuffer = 0;
2044  return descriptor;
2045  }
2046 
2047  ID3D11Buffer* constBuffer = 0;
2048  if( constBufferSize > 0 )
2049  {
2050  // Create the constant buffer
2051  D3D11_BUFFER_DESC constant_buffer_desc;
2052  ZeroMemory(&constant_buffer_desc, sizeof(constant_buffer_desc));
2053  constant_buffer_desc.ByteWidth = constBufferSize;
2054  constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
2055  constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
2056  constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
2057  m_dx11Device->CreateBuffer(&constant_buffer_desc, NULL, &constBuffer);
2058  if( FAILED( hr ) )
2059  {
2060  KernelDesc descriptor;
2061  descriptor.kernel = 0;
2062  descriptor.constBuffer = 0;
2063  return descriptor;
2064  }
2065  }
2066 
2067  SAFE_RELEASE( pErrorBlob );
2068  SAFE_RELEASE( pBlob );
2069 
2070  DXFunctions::KernelDesc descriptor;
2071  descriptor.kernel = kernelPointer;
2072  descriptor.constBuffer = constBuffer;
2073  return descriptor;
2074 } // compileComputeShader
2075 
2076 
2077 
2079 {
2080  // Ensure current kernels are released first
2081  releaseKernels();
2082 
2083  bool returnVal = true;
2084 
2085  if( m_shadersInitialized )
2086  return true;
2087 
2090  returnVal = false;
2093  returnVal = false;
2094  solvePositionsFromLinksKernel = dxFunctions.compileComputeShaderFromString( SolvePositionsHLSLString, "SolvePositionsFromLinksKernel", sizeof(SolvePositionsFromLinksKernelCB) );
2096  returnVal = false;
2097  vSolveLinksKernel = dxFunctions.compileComputeShaderFromString( VSolveLinksHLSLString, "VSolveLinksKernel", sizeof(VSolveLinksCB) );
2099  returnVal = false;
2100  updateVelocitiesFromPositionsWithVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNodesHLSLString, "updateVelocitiesFromPositionsWithVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithVelocitiesCB) );
2102  returnVal = false;
2103  updateVelocitiesFromPositionsWithoutVelocitiesKernel = dxFunctions.compileComputeShaderFromString( UpdatePositionsHLSLString, "updateVelocitiesFromPositionsWithoutVelocitiesKernel", sizeof(UpdateVelocitiesFromPositionsWithoutVelocitiesCB) );
2105  returnVal = false;
2106  integrateKernel = dxFunctions.compileComputeShaderFromString( IntegrateHLSLString, "IntegrateKernel", sizeof(IntegrateCB) );
2108  returnVal = false;
2109  applyForcesKernel = dxFunctions.compileComputeShaderFromString( ApplyForcesHLSLString, "ApplyForcesKernel", sizeof(ApplyForcesCB) );
2111  returnVal = false;
2112  solveCollisionsAndUpdateVelocitiesKernel = dxFunctions.compileComputeShaderFromString( SolveCollisionsAndUpdateVelocitiesHLSLString, "SolveCollisionsAndUpdateVelocitiesKernel", sizeof(SolveCollisionsAndUpdateVelocitiesCB) );
2114  returnVal = false;
2115 
2116  // TODO: Rename to UpdateSoftBodies
2117  resetNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "ResetNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) );
2119  returnVal = false;
2120  normalizeNormalsAndAreasKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "NormalizeNormalsAndAreasKernel", sizeof(UpdateSoftBodiesCB) );
2122  returnVal = false;
2123  updateSoftBodiesKernel = dxFunctions.compileComputeShaderFromString( UpdateNormalsHLSLString, "UpdateSoftBodiesKernel", sizeof(UpdateSoftBodiesCB) );
2125  returnVal = false;
2126 
2127  computeBoundsKernel = dxFunctions.compileComputeShaderFromString( ComputeBoundsHLSLString, "ComputeBoundsKernel", sizeof(ComputeBoundsCB) );
2129  returnVal = false;
2130 
2131 
2132 
2133  if( returnVal )
2134  m_shadersInitialized = true;
2135 
2136  return returnVal;
2137 }
2138 
2139 
2141 {
2142  Vectormath::Aos::Transform3 outTransform;
2143  outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0)));
2144  outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1)));
2145  outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2)));
2146  outTransform.setCol(3, toVector3(transform.getOrigin()));
2147  return outTransform;
2148 }
2149 
2150 
2152 {
2153  float scalarMargin = this->getSoftBody()->getCollisionShape()->getMargin();
2154  btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin );
2155  m_softBody->m_bounds[0] = lowerBound - vectorMargin;
2156  m_softBody->m_bounds[1] = upperBound + vectorMargin;
2157 }
2158 
2160 {
2161 
2162 }
2163 
2164 // Add the collision object to the set to deal with for a particular soft body
2166 {
2167  int softBodyIndex = findSoftBodyIndex( softBody );
2168 
2169  if( softBodyIndex >= 0 )
2170  {
2171  const btCollisionShape *collisionShape = collisionObject->getCollisionShape();
2172  float friction = collisionObject->getCollisionObject()->getFriction();
2173  int shapeType = collisionShape->getShapeType();
2174  if( shapeType == CAPSULE_SHAPE_PROXYTYPE )
2175  {
2176  // Add to the list of expected collision objects
2177  CollisionShapeDescription newCollisionShapeDescription;
2178  newCollisionShapeDescription.softBodyIdentifier = softBodyIndex;
2179  newCollisionShapeDescription.collisionShapeType = shapeType;
2180  // TODO: May need to transpose this matrix either here or in HLSL
2181  newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform());
2182  const btCapsuleShape *capsule = static_cast<const btCapsuleShape*>( collisionShape );
2183  newCollisionShapeDescription.radius = capsule->getRadius();
2184  newCollisionShapeDescription.halfHeight = capsule->getHalfHeight();
2185  newCollisionShapeDescription.margin = capsule->getMargin();
2186  newCollisionShapeDescription.friction = friction;
2187  const btRigidBody* body = static_cast< const btRigidBody* >( collisionObject->getCollisionObject() );
2188  newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity());
2189  newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity());
2190  m_collisionObjectDetails.push_back( newCollisionShapeDescription );
2191 
2192  } else {
2193 #ifdef _DEBUG
2194  printf("Unsupported collision shape type\n");
2195 #endif
2196  }
2197  } else {
2198  btAssert("Unknown soft body");
2199  }
2200 } // btDX11SoftBodySolver::processCollision
2201 
2202 
2203 
2205 {
2206  // Clear the collision shape array for the next frame
2207  // Ensure that the DX11 ones are moved off the device so they will be updated correctly
2208  m_dx11CollisionObjectDetails.changedOnCPU();
2209  m_dx11PerClothCollisionObjects.changedOnCPU();
2211 
2212  // Fill the force arrays with current acceleration data etc
2214  for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
2215  {
2216  btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody();
2217 
2218  m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity());
2219  }
2221 
2222  // Apply forces that we know about to the cloths
2223  applyForces( timeStep * getTimeScale() );
2224 
2225  // Itegrate motion for all soft bodies dealt with by the solver
2226  integrate( timeStep * getTimeScale() );
2227 
2228  // Update bounds
2229  // Will update the bounds for all softBodies being dealt with by the solver and
2230  // set the values in the btSoftBody object
2232  updateBounds();
2233 
2234  // End prediction work for solvers
2235 }
2236 
static T sum(const btAlignedObjectArray< T > &items)
virtual void setTriangleAt(const TriangleDescription &triangle, int triangleIndex)
static char m_dx11LinksLengthRatio(d3dDevice, d3dDeviceContext,&m_linksLengthRatio, false)
btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:835
btDX11Buffer< CollisionObjectIndices > m_dx11PerClothCollisionObjects
void createVertices(int numVertices, int clothIdentifier, int maxVertices=0)
Create numVertices new vertices for cloth clothIdentifier maxVertices allows a buffer zone of extra v...
btDX11Buffer< Vectormath::Aos::Point3 > m_dx11VertexPreviousPosition
virtual void setLinkAt(const LinkDescription &link, int linkIndex)
Insert the link described into the correct data structures assuming space has already been allocated ...
void push_back(const T &_Val)
void generateBatches()
Generate (and later update) the batching for the entire triangle set.
int getShapeType() const
virtual void integrate(float solverdt)
Integrate motion on the solver.
static char m_dx11LinksMassLSC(d3dDevice, d3dDeviceContext,&m_linksMassLSC, false)
Config m_cfg
Definition: btSoftBody.h:648
virtual void createTriangles(int numTriangles)
Allocate enough space in all link-related arrays to fit numLinks links.
ID3D11DeviceContext * m_dx11Context
virtual void createTriangles(int numTriangles)
Vectormath::Aos::Vector3 ProjectOnAxis(const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a)
void setPosition(const Vectormath::Aos::Point3 &position)
bool moveToGPU()
Move the data to the GPU if it is not there already.
btDX11Buffer< float > m_dx11PerClothDampingFactor
virtual bool hasVertexPositions() const
virtual void setLinkAt(const LinkDescription &link, int linkIndex)
Insert the link described into the correct data structures assuming space has already been allocated ...
btDX11Buffer< Vectormath::Aos::Vector3 > m_dx11VertexVelocity
DXFunctions::KernelDesc computeBoundsKernel
ID3D11ComputeShader * kernel
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_normal
DXFunctions::KernelDesc updatePositionsFromVelocitiesKernel
btAlignedObjectArray< TriangleNodeSet > m_vertexIndices
btDX11Buffer< float > m_dx11LinksMaterialLinearStiffnessCoefficient
virtual btSoftBodyTriangleData & getTriangleData()
void generateBatches()
Generate (and later update) the batching for the entire link set.
float computeTriangleArea(const Vectormath::Aos::Point3 &vertex0, const Vectormath::Aos::Point3 &vertex1, const Vectormath::Aos::Point3 &vertex2)
void setZ(btScalar _z)
Set the z value.
Definition: btVector3.h:571
virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer)
Output current computed vertex data to the vertex buffers for all cloths in the solver.
virtual BufferTypes getBufferType() const =0
Return the type of the vertex buffer descriptor.
virtual bool onAccelerator()
Return true if data is on the accelerator.
static char m_dx11LinksRestLength(d3dDevice, d3dDeviceContext,&m_linksRestLength, false)
float & getRestLengthSquared(int linkIndex)
Return reference to rest length squared for link linkIndex as stored on the host. ...
void normalizeNormalsAndAreas(int numVertices)
btAlignedObjectArray< int > m_triangleAddresses
Link addressing information for each cloth.
The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned ...
int & getTriangleCount(int vertexIndex)
Get access to the array of how many triangles touch each vertex.
#define btAssert(x)
Definition: btScalar.h:101
virtual void processCollision(btSoftBody *, const btCollisionObjectWrapper *)
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
btDX11Buffer< float > m_dx11PerClothDragFactor
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient
Velocity correction coefficient.
static char m_dx11LinksMaterialLinearStiffnessCoefficient(d3dDevice, d3dDeviceContext,&m_linksMaterialLinearStiffnessCoefficient, false)
float & getLinearStiffnessCoefficient(int linkIndex)
Return reference to linear stiffness coefficient for link linkIndex as stored on the host...
LinkNodePair & getVertexPair(int linkIndex)
Return reference to the vertex index pair for link linkIndex as stored on the host.
virtual void updateSoftBodies()
Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes...
Class describing a vertex for input into the system.
btVector3 getColumn(int i) const
Get a column of the matrix as a vector.
Definition: btMatrix3x3.h:134
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_linksCLength
btSoftBodyVertexDataDX11(ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext)
btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects
Collision shape details: pair of index of first collision shape for the cloth and number of collision...
virtual bool moveFromAccelerator(bool bCopy=false, bool bCopyMinimum=true)
Move data to host memory from the accelerator if bCopy is false.
void updateVelocitiesFromPositionsWithVelocities(float isolverdt)
DXFunctions::KernelDesc applyForcesKernel
void updateVelocitiesFromPositionsWithoutVelocities(float isolverdt)
void resetNormalsAndAreas(int numVertices)
btDX11Buffer< Vectormath::Aos::Vector3 > m_dx11VertexForceAccumulator
tNodeArray m_nodes
Definition: btSoftBody.h:654
tLinkArray m_links
Definition: btSoftBody.h:655
void updateBounds(const btVector3 &lowerBound, const btVector3 &upperBound)
Update the bounds in the btSoftBody object.
DXFunctions::KernelDesc addVelocityKernel
btDX11Buffer< float > m_dx11LinksLengthRatio
virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer)
Output current computed vertex data to the vertex buffers for all cloths in the solver.
static float4 normalize(const float4 &a)
bool copyFromGPU()
Copy the data back from the GPU without changing its state to be CPU-side.
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
btAlignedObjectArray< UIntVector3 > m_perClothMinBounds
Minimum bounds for each cloth.
btAlignedObjectArray< float > m_linkStrength
btDX11Buffer< float > m_dx11VertexInverseMass
Transform3 & setCol(int col, const Vector3 &vec)
float & getMassLSC(int linkIndex)
Return reference to the MassLSC value for link linkIndex as stored on the host.
static Vectormath::Aos::Vector3 toVector3(const btVector3 &vec)
virtual void createLinks(int numLinks)
Allocate enough space in all link-related arrays to fit numLinks links.
btAcceleratedSoftBodyInterface * findSoftBodyInterface(const btSoftBody *const softBody)
void setX(btScalar _x)
Set the x value.
Definition: btVector3.h:567
DXFunctions::KernelDesc solvePositionsFromLinksKernel
btDX11Buffer< float > m_dx11LinkStrength
btDX11Buffer< float > m_dx11PerClothVelocityCorrectionCoefficient
float lengthSqr(const Vector3 &vec)
Definition: neon/vec_aos.h:447
btSoftBodyWorldInfo * getWorldInfo()
Definition: btSoftBody.h:697
void solveLinksForPosition(int startLink, int numLinks, float kst, float ti)
btAlignedObjectArray< float > m_perClothMediumDensity
Density of the medium in which each cloth sits.
btDX11Buffer< Vectormath::Aos::Vector3 > m_dx11VertexNormal
int size() const
return the number of elements in the array
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
virtual ID3D11UnorderedAccessView * getDX11UAV() const
btDX11Buffer< float > m_dx11LinksRestLength
const btVector3 & getWindVelocity()
Return the wind velocity for interaction with the air.
virtual SolverTypes getSolverType() const =0
Return the type of the solver.
void updatePositionsFromVelocities(float solverdt)
DXFunctions::KernelDesc solveCollisionsAndUpdateVelocitiesKernel
virtual bool onAccelerator()
Return true if data is on the accelerator.
KernelDesc compileComputeShaderFromString(const char *shaderString, const char *shaderName, int constBufferSize, D3D10_SHADER_MACRO *compileMacros=0)
Compile a compute shader kernel from a string and return the appropriate KernelDesc object...
DXFunctions::KernelDesc updateSoftBodiesKernel
virtual btSoftBodyVertexData & getVertexData()
btAlignedObjectArray< LinkNodePair > m_links
btAlignedObjectArray< float > m_perClothDampingFactor
Velocity damping factor.
SoftBody class to maintain information about a soft body instance within a solver.
virtual void setTriangleAt(const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex)
Insert the link described into the correct data structures assuming space has already been allocated ...
btSoftBodyLinkDataDX11 m_linkData
Link data for all cloths.
btDX11Buffer< float > m_dx11PerClothLiftFactor
DXFunctions::KernelDesc prepareLinksKernel
btAlignedObjectArray< int > m_linkAddresses
Link addressing information for each cloth.
#define SAFE_RELEASE(p)
DXFunctions::KernelDesc resetNormalsAndAreasKernel
virtual bool onAccelerator()
Return true if data is on the accelerator.
Class representing a link as a set of three indices into the vertex array.
btSoftBodySolver * getSoftBodySolver()
Definition: btSoftBody.h:913
const btVector3 & getAngularVelocity() const
Definition: btRigidBody.h:359
btDX11Buffer< Vectormath::Aos::Vector3 > m_dx11PerClothWindVelocity
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
const btTransform & getWorldTransform() const
void setY(btScalar _y)
Set the y value.
Definition: btVector3.h:569
virtual bool moveToAccelerator()
Move data from host memory to the accelerator.
DXFunctions::KernelDesc normalizeNormalsAndAreasKernel
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
static char * UpdatePositionsFromVelocitiesHLSLString
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:561
virtual void changedOnCPU()
Call if data has changed on the CPU.
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:59
virtual btSoftBodyLinkData & getLinkData()
btDX11Buffer< Vectormath::Aos::Vector3 > m_dx11Normal
float & getRestLength(int linkIndex)
Return reference to the rest length of link linkIndex as stored on the host.
btAlignedObjectArray< float > m_perClothFriction
Friction coefficient for each cloth.
btAlignedObjectArray< float > m_linksRestLengthSquared
virtual void solveConstraints(float solverdt)
Solve constraints for a set of soft bodies.
btAlignedObjectArray< BatchPair > m_batchStartLengths
Start and length values for computation batches over link data.
btAlignedObjectArray< float > m_linksLengthRatio
btDX11Buffer< CollisionShapeDescription > m_dx11CollisionObjectDetails
ID3D11DeviceContext * m_dx11Context
btAlignedObjectArray< float > m_linksMaterialLinearStiffnessCoefficient
DXFunctions::KernelDesc integrateKernel
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity
Wind velocity to be applied normal to all non-static vertices in the solver.
virtual int getVertexStride() const
Return the vertex stride in number of floats between vertices.
static Vectormath::Aos::Transform3 toTransform3(const btTransform &transform)
virtual void copyBackToSoftBodies(bool bMove=true)
Copy necessary data back to the original soft body source objects.
static char m_dx11LinksCLength(d3dDevice, d3dDeviceContext,&m_linksCLength, false)
const btCollisionShape * getCollisionShape() const
void ApplyClampedForce(float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce)
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
virtual int getVertexOffset() const
Return the vertex offset in floats from the base pointer.
btDX11Buffer< LinkNodePair > m_dx11Links
btAlignedObjectArray< btAcceleratedSoftBodyInterface * > m_softBodySet
Cloths owned by this solver.
virtual void applyForces(float solverdt)
Class describing a link for input into the system.
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
virtual void predictMotion(float solverdt)
Predict motion of soft bodies into next timestep.
Wrapper for vertex data information.
static char m_dx11LinkStrength(d3dDevice, d3dDeviceContext,&m_linkStrength, false)
void executeUpdateSoftBodies(int firstTriangle, int numTriangles)
virtual bool moveFromAccelerator()
Move data from host memory from the accelerator.
btDX11Buffer< float > m_dx11LinksMassLSC
Vectormath::Aos::Vector3 & getNormal(int vertexIndex)
Return a reference to the normal of vertex vertexIndex as stored on the host.
virtual bool moveToAccelerator()
Move data from host memory to the accelerator.
btAlignedObjectArray< float > m_perClothDragFactor
Drag parameter for wind effect on cloth.
void resize(int newsize, const T &fillData=T())
btDX11Buffer< float > m_dx11PerClothMediumDensity
btSoftBodyTriangleDataDX11(ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext)
ID3D11ShaderResourceView *& getSRV()
btAlignedObjectArray< float > m_linksMassLSC
float & getInverseMass(int vertexIndex)
Return a reference to the inverse mass of vertex vertexIndex as stored on the host.
int findLinearSearch(const T &key) const
virtual bool moveToAccelerator()
Move data from host memory to the accelerator.
virtual int getNormalOffset() const
Return the vertex offset in floats from the base pointer.
btDX11Buffer< UIntVector3 > m_dx11PerClothMinBounds
Vectormath::Aos::Point3 & getPosition(int vertexIndex)
Return a reference to the position of vertex vertexIndex as stored on the host.
btSoftBodyVertexDataDX11 m_vertexData
btScalar getFriction() const
virtual float * getBasePointer() const
Return the base pointer in memory to the first vertex.
ID3D11UnorderedAccessView *& getUAV()
static float4 cross(const float4 &a, const float4 &b)
btDX11Buffer< Vectormath::Aos::Vector3 > m_dx11LinksCLength
btAlignedObjectArray< float > m_area
btAlignedObjectArray< CollisionShapeDescription > m_collisionObjectDetails
Collision shapes being passed across to the cloths in this solver.
virtual bool checkInitialized()
Ensure that this solver is initialized.
float getTimeScale()
Return the timescale that the simulation is using.
btDX11Buffer< float > m_dx11LinksRestLengthSquared
btAlignedObjectArray< float > m_perClothLiftFactor
Lift parameter for wind effect on cloth.
btDX11Buffer< Vectormath::Aos::Point3 > m_dx11VertexPosition
btAlignedObjectArray< float > m_linksRestLength
void solveLinksForVelocity(int startLink, int numLinks, float kst)
DXFunctions::KernelDesc updateVelocitiesFromPositionsWithoutVelocitiesKernel
static char m_d3dDeviceContext(d3dDeviceContext)
btAlignedObjectArray< BatchPair > m_batchStartLengths
Start and length values for computation batches over link data.
const btVector3 & getLinearVelocity() const
Definition: btRigidBody.h:356
btScalar air_density
Definition: btSoftBody.h:45
const TriangleNodeSet & getVertexSet(int triangleIndex)
Return the vertex index set for triangle triangleIndex as stored on the host.
btSoftBodyTriangleDataDX11 m_triangleData
float dot(const Quat &quat0, const Quat &quat1)
btVector3 m_gravity
Definition: btSoftBody.h:52
DXFunctions::KernelDesc updateVelocitiesFromPositionsWithVelocitiesKernel
void prepareCollisionConstraints()
Sort the collision object details array and generate indexing into it for the per-cloth collision obj...
btDX11Buffer< btSoftBodyTriangleData::TriangleNodeSet > m_dx11VertexIndices
static char * PrepareLinksHLSLString
btSoftBodyLinkDataDX11(ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext)
The btSoftBody is an class to simulate cloth and volumetric soft bodies.
Definition: btSoftBody.h:71
int findSoftBodyIndex(const btSoftBody *const softBody)
void solveCollisionsAndUpdateVelocities(float isolverdt)
virtual bool moveFromAccelerator()
Move data from host memory from the accelerator.
btDX11Buffer< float > m_dx11PerClothFriction
HRESULT(WINAPI * CompileFromMemoryFunc)(LPCSTR, SIZE_T, LPCSTR, const D3D10_SHADER_MACRO *, LPD3D10INCLUDE, LPCSTR, LPCSTR, UINT, UINT, ID3DX11ThreadPump *, ID3D10Blob **, ID3D10Blob **, HRESULT *)
void setVertexAt(const VertexDescription &vertex, int vertexIndex)
btDX11Buffer< UIntVector3 > m_dx11PerClothMaxBounds
btDX11SoftBodySolver(ID3D11Device *dx11Device, ID3D11DeviceContext *dx11Context, DXFunctions::CompileFromMemoryFunc dx11CompileFromMemory=&D3DX11CompileFromMemory)
bool m_updateSolverConstants
Variable to define whether we need to update solver constants on the next iteration.
void quickSort(const L &CompareFunc)
virtual void optimize(btAlignedObjectArray< btSoftBody * > &softBodies, bool forceUpdate=false)
Optimize soft bodies in this solver.
virtual int getNormalStride() const
Return the vertex stride in number of floats between vertices.
DXFunctions::KernelDesc vSolveLinksKernel
const btCollisionObject * getCollisionObject() const
static char m_dx11LinksRestLengthSquared(d3dDevice, d3dDeviceContext,&m_linksRestLengthSquared, false)
btDX11Buffer< Vectormath::Aos::Vector3 > m_dx11PerClothAcceleration
virtual void createLinks(int numLinks)
Allocate enough space in all link-related arrays to fit numLinks links.
virtual void updateConstants(float timeStep)
tFaceArray m_faces
Definition: btSoftBody.h:656
bool moveFromGPU()
Move the data back from the GPU if it is on there and isn't read only.
btAlignedObjectArray< UIntVector3 > m_perClothMaxBounds
Maximum bounds for each cloth.
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration
Acceleration value to be applied to all non-static vertices in the solver.