Imported Upstream version 2.81
[platform/upstream/libbullet.git] / src / BulletMultiThreaded / GpuSoftBodySolvers / DX11 / HLSL / ApplyForces.hlsl
1 MSTRINGIFY(\r
2 \r
3 cbuffer ApplyForcesCB : register( b0 )\r
4 {\r
5         unsigned int numNodes;\r
6         float solverdt;\r
7         float epsilon;\r
8         int padding3;\r
9 };\r
10 \r
11 \r
12 StructuredBuffer<int> g_vertexClothIdentifier : register( t0 );\r
13 StructuredBuffer<float4> g_vertexNormal : register( t1 );\r
14 StructuredBuffer<float> g_vertexArea : register( t2 );\r
15 StructuredBuffer<float> g_vertexInverseMass : register( t3 );\r
16 // TODO: These could be combined into a lift/drag factor array along with medium density\r
17 StructuredBuffer<float> g_clothLiftFactor : register( t4 );\r
18 StructuredBuffer<float> g_clothDragFactor : register( t5 );\r
19 StructuredBuffer<float4> g_clothWindVelocity : register( t6 );\r
20 StructuredBuffer<float4> g_clothAcceleration : register( t7 );\r
21 StructuredBuffer<float> g_clothMediumDensity : register( t8 );\r
22 \r
23 RWStructuredBuffer<float4> g_vertexForceAccumulator : register( u0 );\r
24 RWStructuredBuffer<float4> g_vertexVelocity : register( u1 );\r
25 \r
26 float3 projectOnAxis( float3 v, float3 a )\r
27 {\r
28         return (a*dot(v, a));\r
29 }\r
30 \r
31 [numthreads(128, 1, 1)]\r
32 void \r
33 ApplyForcesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )\r
34 {\r
35         unsigned int nodeID = DTid.x;\r
36         if( nodeID < numNodes )\r
37         {               \r
38                 int clothId = g_vertexClothIdentifier[nodeID];\r
39                 float nodeIM = g_vertexInverseMass[nodeID];\r
40                 \r
41                 if( nodeIM > 0.0f )\r
42                 {\r
43                         float3 nodeV = g_vertexVelocity[nodeID].xyz;\r
44                         float3 normal = g_vertexNormal[nodeID].xyz;\r
45                         float area = g_vertexArea[nodeID];\r
46                         float3 nodeF = g_vertexForceAccumulator[nodeID].xyz;\r
47                         \r
48                         // Read per-cloth values\r
49                         float3 clothAcceleration = g_clothAcceleration[clothId].xyz;\r
50                         float3 clothWindVelocity = g_clothWindVelocity[clothId].xyz;\r
51                         float liftFactor = g_clothLiftFactor[clothId];\r
52                         float dragFactor = g_clothDragFactor[clothId];\r
53                         float mediumDensity = g_clothMediumDensity[clothId];\r
54                 \r
55                         // Apply the acceleration to the cloth rather than do this via a force\r
56                         nodeV += (clothAcceleration*solverdt);\r
57 \r
58                         g_vertexVelocity[nodeID] = float4(nodeV, 0.f);\r
59 \r
60                         float3 relativeWindVelocity = nodeV - clothWindVelocity;\r
61                         float relativeSpeedSquared = dot(relativeWindVelocity, relativeWindVelocity);\r
62                         \r
63                         if( relativeSpeedSquared > epsilon )\r
64                         {\r
65                                 // Correct direction of normal relative to wind direction and get dot product\r
66                                 normal = normal * (dot(normal, relativeWindVelocity) < 0 ? -1.f : 1.f);\r
67                                 float dvNormal = dot(normal, relativeWindVelocity);\r
68                                 if( dvNormal > 0 )\r
69                                 {\r
70                                         float3 force = float3(0.f, 0.f, 0.f);\r
71                                         float c0 = area * dvNormal * relativeSpeedSquared / 2.f;\r
72                                         float c1 = c0 * mediumDensity;\r
73                                         force += normal * (-c1 * liftFactor);\r
74                                         force += normalize(relativeWindVelocity)*(-c1 * dragFactor);\r
75                                         \r
76                                         float dtim = solverdt * nodeIM;\r
77                                         float3 forceDTIM = force * dtim;\r
78                                         \r
79                                         float3 nodeFPlusForce = nodeF + force;\r
80                                         \r
81                                         // m_nodesf[i] -= ProjectOnAxis(m_nodesv[i], force.normalized())/dtim;  \r
82                                         float3 nodeFMinus = nodeF - (projectOnAxis(nodeV, normalize(force))/dtim);\r
83                                         \r
84                                         nodeF = nodeFPlusForce;\r
85                                         if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) )\r
86                                                 nodeF = nodeFMinus;\r
87                                                                         \r
88                                         g_vertexForceAccumulator[nodeID] = float4(nodeF, 0.0f); \r
89                                 }\r
90                         }\r
91                 }\r
92         }\r
93 }\r
94 \r
95 );