Added GPU SoftBody constraint solvers for DirectX 11 (Direct Compute) and OpenCL, thanks to AMD.
See also http://code.google.com/p/bullet/issues/detail?id=390 Added Demos/DX11ClothDemo (an OpenCL cloth demo will follow soon)
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
SET(DXSDK_DIR $ENV{DXSDK_DIR})
|
||||
SET(DX11_INCLUDE_PATH "${DIRECTX_SDK_BASE_DIR}/Include" CACHE DOCSTRING "Microsoft directX SDK include path")
|
||||
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${DX11_INCLUDE_PATH} "../cpu/"
|
||||
${VECTOR_MATH_INCLUDE}
|
||||
)
|
||||
|
||||
SET(BulletSoftBodyDX11Solvers_SRCS
|
||||
btSoftBodySolver_DX11.cpp
|
||||
)
|
||||
|
||||
SET(BulletSoftBodyDX11Solvers_HDRS
|
||||
btSoftBodySolver_DX11.h
|
||||
../cpu/btSoftBodySolverData.h
|
||||
btSoftBodySolverVertexData_DX11.h
|
||||
btSoftBodySolverTriangleData_DX11.h
|
||||
btSoftBodySolverLinkData_DX11.h
|
||||
btSoftBodySolverBuffer_DX11.h
|
||||
btSoftBodySolverVertexBuffer_DX11.h
|
||||
|
||||
)
|
||||
|
||||
# OpenCL and HLSL Shaders.
|
||||
# Build rules generated to stringify these into headers
|
||||
# which are needed by some of the sources
|
||||
SET(BulletSoftBodyDX11Solvers_Shaders
|
||||
OutputToVertexArray
|
||||
UpdateNormals
|
||||
Integrate
|
||||
UpdatePositions
|
||||
UpdateNodes
|
||||
SolvePositions
|
||||
UpdatePositionsFromVelocities
|
||||
ApplyForces
|
||||
PrepareLinks
|
||||
VSolveLinks
|
||||
)
|
||||
|
||||
foreach(f ${BulletSoftBodyDX11Solvers_Shaders})
|
||||
LIST(APPEND BulletSoftBodyDX11Solvers_HLSL "HLSL/${f}.hlsl")
|
||||
endforeach(f)
|
||||
|
||||
|
||||
|
||||
ADD_LIBRARY(BulletSoftBodySolvers_DX11 ${BulletSoftBodyDX11Solvers_SRCS} ${BulletSoftBodyDX11Solvers_HDRS} ${BulletSoftBodyDX11Solvers_HLSL})
|
||||
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(BulletSoftBody BulletDynamics)
|
||||
ENDIF (BUILD_SHARED_LIBS)
|
||||
|
||||
|
||||
IF (INSTALL_LIBS)
|
||||
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletSoftBodySolvers_DX11 DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletSoftBodySolvers_DX11 DESTINATION lib${LIB_SUFFIX})
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.h")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
|
||||
|
||||
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_DX11 PROPERTIES PUBLIC_HEADER "${BulletSoftBodyDX11Solvers_HDRS}")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_LIBS)
|
||||
@@ -0,0 +1,95 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer ApplyForcesCB : register( b0 )
|
||||
{
|
||||
unsigned int numNodes;
|
||||
float solverdt;
|
||||
float epsilon;
|
||||
int padding3;
|
||||
};
|
||||
|
||||
|
||||
StructuredBuffer<int> g_vertexClothIdentifier : register( t0 );
|
||||
StructuredBuffer<float4> g_vertexNormal : register( t1 );
|
||||
StructuredBuffer<float> g_vertexArea : register( t2 );
|
||||
StructuredBuffer<float> g_vertexInverseMass : register( t3 );
|
||||
// TODO: These could be combined into a lift/drag factor array along with medium density
|
||||
StructuredBuffer<float> g_clothLiftFactor : register( t4 );
|
||||
StructuredBuffer<float> g_clothDragFactor : register( t5 );
|
||||
StructuredBuffer<float4> g_clothWindVelocity : register( t6 );
|
||||
StructuredBuffer<float4> g_clothAcceleration : register( t7 );
|
||||
StructuredBuffer<float> g_clothMediumDensity : register( t8 );
|
||||
|
||||
RWStructuredBuffer<float4> g_vertexForceAccumulator : register( u0 );
|
||||
RWStructuredBuffer<float4> g_vertexVelocity : register( u1 );
|
||||
|
||||
float3 projectOnAxis( float3 v, float3 a )
|
||||
{
|
||||
return (a*dot(v, a));
|
||||
}
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
ApplyForcesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
unsigned int nodeID = DTid.x;
|
||||
if( nodeID < numNodes )
|
||||
{
|
||||
int clothId = g_vertexClothIdentifier[nodeID];
|
||||
float nodeIM = g_vertexInverseMass[nodeID];
|
||||
|
||||
if( nodeIM > 0.0f )
|
||||
{
|
||||
float3 nodeV = g_vertexVelocity[nodeID].xyz;
|
||||
float3 normal = g_vertexNormal[nodeID].xyz;
|
||||
float area = g_vertexArea[nodeID];
|
||||
float3 nodeF = g_vertexForceAccumulator[nodeID].xyz;
|
||||
|
||||
// Read per-cloth values
|
||||
float3 clothAcceleration = g_clothAcceleration[clothId].xyz;
|
||||
float3 clothWindVelocity = g_clothWindVelocity[clothId].xyz;
|
||||
float liftFactor = g_clothLiftFactor[clothId];
|
||||
float dragFactor = g_clothDragFactor[clothId];
|
||||
float mediumDensity = g_clothMediumDensity[clothId];
|
||||
|
||||
// Apply the acceleration to the cloth rather than do this via a force
|
||||
nodeV += (clothAcceleration*solverdt);
|
||||
|
||||
g_vertexVelocity[nodeID] = float4(nodeV, 0.f);
|
||||
|
||||
float3 relativeWindVelocity = nodeV - clothWindVelocity;
|
||||
float relativeSpeedSquared = dot(relativeWindVelocity, relativeWindVelocity);
|
||||
|
||||
if( relativeSpeedSquared > epsilon )
|
||||
{
|
||||
// Correct direction of normal relative to wind direction and get dot product
|
||||
normal = normal * (dot(normal, relativeWindVelocity) < 0 ? -1.f : 1.f);
|
||||
float dvNormal = dot(normal, relativeWindVelocity);
|
||||
if( dvNormal > 0 )
|
||||
{
|
||||
float3 force = float3(0.f, 0.f, 0.f);
|
||||
float c0 = area * dvNormal * relativeSpeedSquared / 2.f;
|
||||
float c1 = c0 * mediumDensity;
|
||||
force += normal * (-c1 * liftFactor);
|
||||
force += normalize(relativeWindVelocity)*(-c1 * dragFactor);
|
||||
|
||||
float dtim = solverdt * nodeIM;
|
||||
float3 forceDTIM = force * dtim;
|
||||
|
||||
float3 nodeFPlusForce = nodeF + force;
|
||||
|
||||
// m_nodesf[i] -= ProjectOnAxis(m_nodesv[i], force.normalized())/dtim;
|
||||
float3 nodeFMinus = nodeF - (projectOnAxis(nodeV, normalize(force))/dtim);
|
||||
|
||||
nodeF = nodeFPlusForce;
|
||||
if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) )
|
||||
nodeF = nodeFMinus;
|
||||
|
||||
g_vertexForceAccumulator[nodeID] = float4(nodeF, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,41 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer IntegrateCB : register( b0 )
|
||||
{
|
||||
int numNodes;
|
||||
float solverdt;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
// Node indices for each link
|
||||
StructuredBuffer<float> g_vertexInverseMasses : register( t0 );
|
||||
|
||||
RWStructuredBuffer<float4> g_vertexPositions : register( u0 );
|
||||
RWStructuredBuffer<float4> g_vertexVelocity : register( u1 );
|
||||
RWStructuredBuffer<float4> g_vertexPreviousPositions : register( u2 );
|
||||
RWStructuredBuffer<float4> g_vertexForceAccumulator : register( u3 );
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
IntegrateKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int nodeID = DTid.x;
|
||||
if( nodeID < numNodes )
|
||||
{
|
||||
float3 position = g_vertexPositions[nodeID].xyz;
|
||||
float3 velocity = g_vertexVelocity[nodeID].xyz;
|
||||
float3 force = g_vertexForceAccumulator[nodeID].xyz;
|
||||
float inverseMass = g_vertexInverseMasses[nodeID];
|
||||
|
||||
g_vertexPreviousPositions[nodeID] = float4(position, 0.f);
|
||||
velocity += force * inverseMass * solverdt;
|
||||
position += velocity * solverdt;
|
||||
|
||||
g_vertexForceAccumulator[nodeID] = float4(0.f, 0.f, 0.f, 0.0f);
|
||||
g_vertexPositions[nodeID] = float4(position, 0.f);
|
||||
g_vertexVelocity[nodeID] = float4(velocity, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,63 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer OutputToVertexArrayCB : register( b0 )
|
||||
{
|
||||
int startNode;
|
||||
int numNodes;
|
||||
int positionOffset;
|
||||
int positionStride;
|
||||
|
||||
int normalOffset;
|
||||
int normalStride;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
|
||||
StructuredBuffer<float4> g_vertexPositions : register( t0 );
|
||||
StructuredBuffer<float4> g_vertexNormals : register( t1 );
|
||||
|
||||
RWBuffer<float> g_vertexBuffer : register( u0 );
|
||||
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
OutputToVertexArrayWithNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int nodeID = DTid.x;
|
||||
if( nodeID < numNodes )
|
||||
{
|
||||
float4 position = g_vertexPositions[nodeID + startNode];
|
||||
float4 normal = g_vertexNormals[nodeID + startNode];
|
||||
|
||||
// Stride should account for the float->float4 conversion
|
||||
int positionDestination = nodeID * positionStride + positionOffset;
|
||||
g_vertexBuffer[positionDestination] = position.x;
|
||||
g_vertexBuffer[positionDestination+1] = position.y;
|
||||
g_vertexBuffer[positionDestination+2] = position.z;
|
||||
|
||||
int normalDestination = nodeID * normalStride + normalOffset;
|
||||
g_vertexBuffer[normalDestination] = normal.x;
|
||||
g_vertexBuffer[normalDestination+1] = normal.y;
|
||||
g_vertexBuffer[normalDestination+2] = normal.z;
|
||||
}
|
||||
}
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
OutputToVertexArrayWithoutNormalsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int nodeID = DTid.x;
|
||||
if( nodeID < numNodes )
|
||||
{
|
||||
float4 position = g_vertexPositions[nodeID + startNode];
|
||||
float4 normal = g_vertexNormals[nodeID + startNode];
|
||||
|
||||
// Stride should account for the float->float4 conversion
|
||||
int positionDestination = nodeID * positionStride + positionOffset;
|
||||
g_vertexBuffer[positionDestination] = position.x;
|
||||
g_vertexBuffer[positionDestination+1] = position.y;
|
||||
g_vertexBuffer[positionDestination+2] = position.z;
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,44 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer PrepareLinksCB : register( b0 )
|
||||
{
|
||||
int numLinks;
|
||||
int padding0;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
// Node indices for each link
|
||||
StructuredBuffer<int2> g_linksVertexIndices : register( t0 );
|
||||
StructuredBuffer<float> g_linksMassLSC : register( t1 );
|
||||
StructuredBuffer<float4> g_nodesPreviousPosition : register( t2 );
|
||||
|
||||
RWStructuredBuffer<float> g_linksLengthRatio : register( u0 );
|
||||
RWStructuredBuffer<float4> g_linksCurrentLength : register( u1 );
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
PrepareLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int linkID = DTid.x;
|
||||
if( linkID < numLinks )
|
||||
{
|
||||
int2 nodeIndices = g_linksVertexIndices[linkID];
|
||||
int node0 = nodeIndices.x;
|
||||
int node1 = nodeIndices.y;
|
||||
|
||||
float4 nodePreviousPosition0 = g_nodesPreviousPosition[node0];
|
||||
float4 nodePreviousPosition1 = g_nodesPreviousPosition[node1];
|
||||
|
||||
float massLSC = g_linksMassLSC[linkID];
|
||||
|
||||
float4 linkCurrentLength = nodePreviousPosition1 - nodePreviousPosition0;
|
||||
|
||||
float linkLengthRatio = dot(linkCurrentLength, linkCurrentLength)*massLSC;
|
||||
linkLengthRatio = 1./linkLengthRatio;
|
||||
|
||||
g_linksCurrentLength[linkID] = linkCurrentLength;
|
||||
g_linksLengthRatio[linkID] = linkLengthRatio;
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,55 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer SolvePositionsFromLinksKernelCB : register( b0 )
|
||||
{
|
||||
int startLink;
|
||||
int numLinks;
|
||||
float kst;
|
||||
float ti;
|
||||
};
|
||||
|
||||
// Node indices for each link
|
||||
StructuredBuffer<int2> g_linksVertexIndices : register( t0 );
|
||||
|
||||
StructuredBuffer<float> g_linksMassLSC : register( t1 );
|
||||
StructuredBuffer<float> g_linksRestLengthSquared : register( t2 );
|
||||
StructuredBuffer<float> g_verticesInverseMass : register( t3 );
|
||||
|
||||
RWStructuredBuffer<float4> g_vertexPositions : register( u0 );
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
SolvePositionsFromLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int linkID = DTid.x + startLink;
|
||||
if( DTid.x < numLinks )
|
||||
{
|
||||
float massLSC = g_linksMassLSC[linkID];
|
||||
float restLengthSquared = g_linksRestLengthSquared[linkID];
|
||||
|
||||
if( massLSC > 0.0f )
|
||||
{
|
||||
int2 nodeIndices = g_linksVertexIndices[linkID];
|
||||
int node0 = nodeIndices.x;
|
||||
int node1 = nodeIndices.y;
|
||||
|
||||
float3 position0 = g_vertexPositions[node0].xyz;
|
||||
float3 position1 = g_vertexPositions[node1].xyz;
|
||||
|
||||
float inverseMass0 = g_verticesInverseMass[node0];
|
||||
float inverseMass1 = g_verticesInverseMass[node1];
|
||||
|
||||
float3 del = position1 - position0;
|
||||
float len = dot(del, del);
|
||||
float k = ((restLengthSquared - len)/(massLSC*(restLengthSquared+len)))*kst;
|
||||
position0 = position0 - del*(k*inverseMass0);
|
||||
position1 = position1 + del*(k*inverseMass1);
|
||||
|
||||
g_vertexPositions[node0] = float4(position0, 0.f);
|
||||
g_vertexPositions[node1] = float4(position1, 0.f);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,48 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer UpdateConstantsCB : register( b0 )
|
||||
{
|
||||
int numLinks;
|
||||
int padding0;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
// Node indices for each link
|
||||
StructuredBuffer<int2> g_linksVertexIndices : register( t0 );
|
||||
StructuredBuffer<float4> g_vertexPositions : register( t1 );
|
||||
StructuredBuffer<float> g_vertexInverseMasses : register( t2 );
|
||||
StructuredBuffer<float> g_linksMaterialLSC : register( t3 );
|
||||
|
||||
RWStructuredBuffer<float> g_linksMassLSC : register( u0 );
|
||||
RWStructuredBuffer<float> g_linksRestLengthSquared : register( u1 );
|
||||
RWStructuredBuffer<float> g_linksRestLengths : register( u2 );
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
UpdateConstantsKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int linkID = DTid.x;
|
||||
if( linkID < numLinks )
|
||||
{
|
||||
int2 nodeIndices = g_linksVertexIndices[linkID];
|
||||
int node0 = nodeIndices.x;
|
||||
int node1 = nodeIndices.y;
|
||||
float linearStiffnessCoefficient = g_linksMaterialLSC[ linkID ];
|
||||
|
||||
float3 position0 = g_vertexPositions[node0].xyz;
|
||||
float3 position1 = g_vertexPositions[node1].xyz;
|
||||
float inverseMass0 = g_vertexInverseMasses[node0];
|
||||
float inverseMass1 = g_vertexInverseMasses[node1];
|
||||
|
||||
float3 difference = position0 - position1;
|
||||
float length2 = dot(difference, difference);
|
||||
float length = sqrt(length2);
|
||||
|
||||
g_linksRestLengths[linkID] = length;
|
||||
g_linksMassLSC[linkID] = (inverseMass0 + inverseMass1)/linearStiffnessCoefficient;
|
||||
g_linksRestLengthSquared[linkID] = length*length;
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,49 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer UpdateVelocitiesFromPositionsWithVelocitiesCB : register( b0 )
|
||||
{
|
||||
int numNodes;
|
||||
float isolverdt;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
|
||||
StructuredBuffer<float4> g_vertexPositions : register( t0 );
|
||||
StructuredBuffer<float4> g_vertexPreviousPositions : register( t1 );
|
||||
StructuredBuffer<int> g_vertexClothIndices : register( t2 );
|
||||
StructuredBuffer<float> g_clothVelocityCorrectionCoefficients : register( t3 );
|
||||
StructuredBuffer<float> g_clothDampingFactor : register( t4 );
|
||||
|
||||
RWStructuredBuffer<float4> g_vertexVelocities : register( u0 );
|
||||
RWStructuredBuffer<float4> g_vertexForces : register( u1 );
|
||||
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
updateVelocitiesFromPositionsWithVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int nodeID = DTid.x;
|
||||
if( nodeID < numNodes )
|
||||
{
|
||||
float3 position = g_vertexPositions[nodeID].xyz;
|
||||
float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz;
|
||||
float3 velocity = g_vertexVelocities[nodeID].xyz;
|
||||
int clothIndex = g_vertexClothIndices[nodeID];
|
||||
float velocityCorrectionCoefficient = g_clothVelocityCorrectionCoefficients[clothIndex];
|
||||
float dampingFactor = g_clothDampingFactor[clothIndex];
|
||||
float velocityCoefficient = (1.f - dampingFactor);
|
||||
|
||||
float3 difference = position - previousPosition;
|
||||
|
||||
velocity += difference*velocityCorrectionCoefficient*isolverdt;
|
||||
|
||||
// Damp the velocity
|
||||
velocity *= velocityCoefficient;
|
||||
|
||||
g_vertexVelocities[nodeID] = float4(velocity, 0.f);
|
||||
g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,98 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer UpdateSoftBodiesCB : register( b0 )
|
||||
{
|
||||
unsigned int numNodes;
|
||||
unsigned int startFace;
|
||||
unsigned int numFaces;
|
||||
float epsilon;
|
||||
};
|
||||
|
||||
|
||||
// Node indices for each link
|
||||
StructuredBuffer<int4> g_triangleVertexIndexSet : register( t0 );
|
||||
StructuredBuffer<float4> g_vertexPositions : register( t1 );
|
||||
StructuredBuffer<int> g_vertexTriangleCount : register( t2 );
|
||||
|
||||
RWStructuredBuffer<float4> g_vertexNormals : register( u0 );
|
||||
RWStructuredBuffer<float> g_vertexArea : register( u1 );
|
||||
RWStructuredBuffer<float4> g_triangleNormals : register( u2 );
|
||||
RWStructuredBuffer<float> g_triangleArea : register( u3 );
|
||||
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
ResetNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
if( DTid.x < numNodes )
|
||||
{
|
||||
g_vertexNormals[DTid.x] = float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
g_vertexArea[DTid.x] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
UpdateSoftBodiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int faceID = DTid.x + startFace;
|
||||
if( DTid.x < numFaces )
|
||||
{
|
||||
int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ];
|
||||
int nodeIndex0 = triangleIndexSet.x;
|
||||
int nodeIndex1 = triangleIndexSet.y;
|
||||
int nodeIndex2 = triangleIndexSet.z;
|
||||
|
||||
float3 node0 = g_vertexPositions[nodeIndex0].xyz;
|
||||
float3 node1 = g_vertexPositions[nodeIndex1].xyz;
|
||||
float3 node2 = g_vertexPositions[nodeIndex2].xyz;
|
||||
float3 nodeNormal0 = g_vertexNormals[nodeIndex0].xyz;
|
||||
float3 nodeNormal1 = g_vertexNormals[nodeIndex1].xyz;
|
||||
float3 nodeNormal2 = g_vertexNormals[nodeIndex2].xyz;
|
||||
float vertexArea0 = g_vertexArea[nodeIndex0];
|
||||
float vertexArea1 = g_vertexArea[nodeIndex1];
|
||||
float vertexArea2 = g_vertexArea[nodeIndex2];
|
||||
|
||||
float3 vector0 = node1 - node0;
|
||||
float3 vector1 = node2 - node0;
|
||||
|
||||
float3 faceNormal = cross(vector0.xyz, vector1.xyz);
|
||||
float triangleArea = length(faceNormal);
|
||||
|
||||
nodeNormal0 = nodeNormal0 + faceNormal;
|
||||
nodeNormal1 = nodeNormal1 + faceNormal;
|
||||
nodeNormal2 = nodeNormal2 + faceNormal;
|
||||
vertexArea0 = vertexArea0 + triangleArea;
|
||||
vertexArea1 = vertexArea1 + triangleArea;
|
||||
vertexArea2 = vertexArea2 + triangleArea;
|
||||
|
||||
g_triangleNormals[faceID] = float4(normalize(faceNormal), 0.f);
|
||||
g_vertexNormals[nodeIndex0] = float4(nodeNormal0, 0.f);
|
||||
g_vertexNormals[nodeIndex1] = float4(nodeNormal1, 0.f);
|
||||
g_vertexNormals[nodeIndex2] = float4(nodeNormal2, 0.f);
|
||||
g_triangleArea[faceID] = triangleArea;
|
||||
g_vertexArea[nodeIndex0] = vertexArea0;
|
||||
g_vertexArea[nodeIndex1] = vertexArea1;
|
||||
g_vertexArea[nodeIndex2] = vertexArea2;
|
||||
}
|
||||
}
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
NormalizeNormalsAndAreasKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
if( DTid.x < numNodes )
|
||||
{
|
||||
float4 normal = g_vertexNormals[DTid.x];
|
||||
float area = g_vertexArea[DTid.x];
|
||||
int numTriangles = g_vertexTriangleCount[DTid.x];
|
||||
|
||||
float vectorLength = length(normal);
|
||||
|
||||
g_vertexNormals[DTid.x] = normalize(normal);
|
||||
g_vertexArea[DTid.x] = area/float(numTriangles);
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,44 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer UpdateVelocitiesFromPositionsWithoutVelocitiesCB : register( b0 )
|
||||
{
|
||||
int numNodes;
|
||||
float isolverdt;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
|
||||
StructuredBuffer<float4> g_vertexPositions : register( t0 );
|
||||
StructuredBuffer<float4> g_vertexPreviousPositions : register( t1 );
|
||||
StructuredBuffer<int> g_vertexClothIndices : register( t2 );
|
||||
StructuredBuffer<float> g_clothDampingFactor : register( t3 );
|
||||
|
||||
RWStructuredBuffer<float4> g_vertexVelocities : register( u0 );
|
||||
RWStructuredBuffer<float4> g_vertexForces : register( u1 );
|
||||
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
updateVelocitiesFromPositionsWithoutVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int nodeID = DTid.x;
|
||||
if( nodeID < numNodes )
|
||||
{
|
||||
float3 position = g_vertexPositions[nodeID].xyz;
|
||||
float3 previousPosition = g_vertexPreviousPositions[nodeID].xyz;
|
||||
float3 velocity = g_vertexVelocities[nodeID].xyz;
|
||||
int clothIndex = g_vertexClothIndices[nodeID];
|
||||
float dampingFactor = g_clothDampingFactor[clothIndex];
|
||||
float velocityCoefficient = (1.f - dampingFactor);
|
||||
|
||||
float3 difference = position - previousPosition;
|
||||
|
||||
velocity = difference*velocityCoefficient*isolverdt;
|
||||
|
||||
g_vertexVelocities[nodeID] = float4(velocity, 0.f);
|
||||
g_vertexForces[nodeID] = float4(0.f, 0.f, 0.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,35 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer UpdatePositionsFromVelocitiesCB : register( b0 )
|
||||
{
|
||||
int numNodes;
|
||||
float solverSDT;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
|
||||
StructuredBuffer<float4> g_vertexVelocities : register( t0 );
|
||||
|
||||
RWStructuredBuffer<float4> g_vertexPreviousPositions : register( u0 );
|
||||
RWStructuredBuffer<float4> g_vertexCurrentPosition : register( u1 );
|
||||
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
UpdatePositionsFromVelocitiesKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int vertexID = DTid.x;
|
||||
if( vertexID < numNodes )
|
||||
{
|
||||
float3 previousPosition = g_vertexPreviousPositions[vertexID].xyz;
|
||||
float3 velocity = g_vertexVelocities[vertexID].xyz;
|
||||
|
||||
float3 newPosition = previousPosition + velocity*solverSDT;
|
||||
|
||||
g_vertexCurrentPosition[vertexID] = float4(newPosition, 0.f);
|
||||
g_vertexPreviousPositions[vertexID] = float4(newPosition, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,55 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
cbuffer VSolveLinksCB : register( b0 )
|
||||
{
|
||||
int startLink;
|
||||
int numLinks;
|
||||
float kst;
|
||||
int padding;
|
||||
};
|
||||
|
||||
// Node indices for each link
|
||||
StructuredBuffer<int2> g_linksVertexIndices : register( t0 );
|
||||
|
||||
StructuredBuffer<float> g_linksLengthRatio : register( t1 );
|
||||
StructuredBuffer<float4> g_linksCurrentLength : register( t2 );
|
||||
StructuredBuffer<float> g_vertexInverseMass : register( t3 );
|
||||
|
||||
RWStructuredBuffer<float4> g_vertexVelocity : register( u0 );
|
||||
|
||||
[numthreads(128, 1, 1)]
|
||||
void
|
||||
VSolveLinksKernel( uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex )
|
||||
{
|
||||
int linkID = DTid.x + startLink;
|
||||
if( DTid.x < numLinks )
|
||||
{
|
||||
int2 nodeIndices = g_linksVertexIndices[linkID];
|
||||
int node0 = nodeIndices.x;
|
||||
int node1 = nodeIndices.y;
|
||||
|
||||
float linkLengthRatio = g_linksLengthRatio[linkID];
|
||||
float3 linkCurrentLength = g_linksCurrentLength[linkID].xyz;
|
||||
|
||||
float3 vertexVelocity0 = g_vertexVelocity[node0].xyz;
|
||||
float3 vertexVelocity1 = g_vertexVelocity[node1].xyz;
|
||||
|
||||
float vertexInverseMass0 = g_vertexInverseMass[node0];
|
||||
float vertexInverseMass1 = g_vertexInverseMass[node1];
|
||||
|
||||
float3 nodeDifference = vertexVelocity0 - vertexVelocity1;
|
||||
float dotResult = dot(linkCurrentLength, nodeDifference);
|
||||
float j = -dotResult*linkLengthRatio*kst;
|
||||
|
||||
float3 velocityChange0 = linkCurrentLength*(j*vertexInverseMass0);
|
||||
float3 velocityChange1 = linkCurrentLength*(j*vertexInverseMass1);
|
||||
|
||||
vertexVelocity0 += velocityChange0;
|
||||
vertexVelocity1 -= velocityChange1;
|
||||
|
||||
g_vertexVelocity[node0] = float4(vertexVelocity0, 0.f);
|
||||
g_vertexVelocity[node1] = float4(vertexVelocity1, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
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.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
|
||||
#define BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
|
||||
|
||||
// DX11 support
|
||||
#include <windows.h>
|
||||
#include <crtdbg.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3dx11.h>
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
#ifndef SAFE_RELEASE
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* DX11 Buffer that tracks a host buffer on use to ensure size-correctness.
|
||||
*/
|
||||
template <typename ElementType> class btDX11Buffer
|
||||
{
|
||||
protected:
|
||||
ID3D11Device* m_d3dDevice;
|
||||
ID3D11DeviceContext* m_d3dDeviceContext;
|
||||
|
||||
ID3D11Buffer* m_Buffer;
|
||||
ID3D11ShaderResourceView* m_SRV;
|
||||
ID3D11UnorderedAccessView* m_UAV;
|
||||
btAlignedObjectArray< ElementType >* m_CPUBuffer;
|
||||
|
||||
// TODO: Separate this from the main class
|
||||
// as read back buffers can be shared between buffers
|
||||
ID3D11Buffer* m_readBackBuffer;
|
||||
|
||||
int m_gpuSize;
|
||||
bool m_onGPU;
|
||||
|
||||
bool m_readOnlyOnGPU;
|
||||
|
||||
bool createBuffer( ID3D11Buffer *preexistingBuffer = 0)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
// Create all CS buffers
|
||||
if( preexistingBuffer )
|
||||
{
|
||||
m_Buffer = preexistingBuffer;
|
||||
} else {
|
||||
D3D11_BUFFER_DESC buffer_desc;
|
||||
ZeroMemory(&buffer_desc, sizeof(buffer_desc));
|
||||
buffer_desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
if( m_readOnlyOnGPU )
|
||||
buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
else
|
||||
buffer_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
|
||||
buffer_desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
||||
|
||||
buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
|
||||
buffer_desc.StructureByteStride = sizeof(ElementType);
|
||||
hr = m_d3dDevice->CreateBuffer(&buffer_desc, NULL, &m_Buffer);
|
||||
if( FAILED( hr ) )
|
||||
return (hr==S_OK);
|
||||
}
|
||||
|
||||
if( m_readOnlyOnGPU )
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
|
||||
ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
|
||||
srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
|
||||
srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
|
||||
hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
|
||||
if( FAILED( hr ) )
|
||||
return (hr==S_OK);
|
||||
} else {
|
||||
// Create SRV
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvbuffer_desc;
|
||||
ZeroMemory(&srvbuffer_desc, sizeof(srvbuffer_desc));
|
||||
srvbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
srvbuffer_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
|
||||
srvbuffer_desc.Buffer.ElementWidth = m_CPUBuffer->size();
|
||||
hr = m_d3dDevice->CreateShaderResourceView(m_Buffer, &srvbuffer_desc, &m_SRV);
|
||||
if( FAILED( hr ) )
|
||||
return (hr==S_OK);
|
||||
|
||||
// Create UAV
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC uavbuffer_desc;
|
||||
ZeroMemory(&uavbuffer_desc, sizeof(uavbuffer_desc));
|
||||
uavbuffer_desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
uavbuffer_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
||||
|
||||
uavbuffer_desc.Buffer.NumElements = m_CPUBuffer->size();
|
||||
hr = m_d3dDevice->CreateUnorderedAccessView(m_Buffer, &uavbuffer_desc, &m_UAV);
|
||||
if( FAILED( hr ) )
|
||||
return (hr==S_OK);
|
||||
|
||||
// Create read back buffer
|
||||
D3D11_BUFFER_DESC readback_buffer_desc;
|
||||
ZeroMemory(&readback_buffer_desc, sizeof(readback_buffer_desc));
|
||||
|
||||
readback_buffer_desc.ByteWidth = m_CPUBuffer->size() * sizeof(ElementType);
|
||||
readback_buffer_desc.Usage = D3D11_USAGE_STAGING;
|
||||
readback_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
readback_buffer_desc.StructureByteStride = sizeof(ElementType);
|
||||
hr = m_d3dDevice->CreateBuffer(&readback_buffer_desc, NULL, &m_readBackBuffer);
|
||||
if( FAILED( hr ) )
|
||||
return (hr==S_OK);
|
||||
}
|
||||
|
||||
m_gpuSize = m_CPUBuffer->size();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
btDX11Buffer( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext, btAlignedObjectArray< ElementType > *CPUBuffer, bool readOnly )
|
||||
{
|
||||
m_d3dDevice = d3dDevice;
|
||||
m_d3dDeviceContext = d3dDeviceContext;
|
||||
m_Buffer = 0;
|
||||
m_SRV = 0;
|
||||
m_UAV = 0;
|
||||
m_readBackBuffer = 0;
|
||||
|
||||
m_CPUBuffer = CPUBuffer;
|
||||
|
||||
m_gpuSize = 0;
|
||||
m_onGPU = false;
|
||||
|
||||
m_readOnlyOnGPU = readOnly;
|
||||
}
|
||||
|
||||
virtual ~btDX11Buffer()
|
||||
{
|
||||
SAFE_RELEASE(m_Buffer);
|
||||
SAFE_RELEASE(m_SRV);
|
||||
SAFE_RELEASE(m_UAV);
|
||||
SAFE_RELEASE(m_readBackBuffer);
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView* &getSRV()
|
||||
{
|
||||
return m_SRV;
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView* &getUAV()
|
||||
{
|
||||
return m_UAV;
|
||||
}
|
||||
|
||||
ID3D11Buffer* &getBuffer()
|
||||
{
|
||||
return m_Buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the data to the GPU if it is not there already.
|
||||
*/
|
||||
bool moveToGPU()
|
||||
{
|
||||
if( (m_CPUBuffer->size() != m_gpuSize) )
|
||||
m_onGPU = false;
|
||||
if( !m_onGPU && m_CPUBuffer->size() > 0 )
|
||||
{
|
||||
// If the buffer doesn't exist or the CPU-side buffer has changed size, create
|
||||
// We should really delete the old one, too, but let's leave that for later
|
||||
if( !m_Buffer || (m_CPUBuffer->size() != m_gpuSize) )
|
||||
{
|
||||
SAFE_RELEASE(m_Buffer);
|
||||
SAFE_RELEASE(m_SRV);
|
||||
SAFE_RELEASE(m_UAV);
|
||||
SAFE_RELEASE(m_readBackBuffer);
|
||||
if( !createBuffer() )
|
||||
{
|
||||
btAssert("Buffer creation failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_BOX destRegion;
|
||||
destRegion.left = 0;
|
||||
destRegion.front = 0;
|
||||
destRegion.top = 0;
|
||||
destRegion.bottom = 1;
|
||||
destRegion.back = 1;
|
||||
destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
|
||||
m_d3dDeviceContext->UpdateSubresource(m_Buffer, 0, &destRegion, &((*m_CPUBuffer)[0]), 0, 0);
|
||||
|
||||
m_onGPU = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the data back from the GPU if it is on there and isn't read only.
|
||||
*/
|
||||
bool moveFromGPU()
|
||||
{
|
||||
if( m_CPUBuffer->size() > 0 )
|
||||
{
|
||||
if( m_onGPU && !m_readOnlyOnGPU )
|
||||
{
|
||||
// Copy back
|
||||
D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
|
||||
//m_pd3dImmediateContext->CopyResource(m_phAngVelReadBackBuffer, m_phAngVel);
|
||||
|
||||
D3D11_BOX destRegion;
|
||||
destRegion.left = 0;
|
||||
destRegion.front = 0;
|
||||
destRegion.top = 0;
|
||||
destRegion.bottom = 1;
|
||||
destRegion.back = 1;
|
||||
|
||||
destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
|
||||
m_d3dDeviceContext->CopySubresourceRegion(
|
||||
m_readBackBuffer,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0 ,
|
||||
m_Buffer,
|
||||
0,
|
||||
&destRegion
|
||||
);
|
||||
|
||||
m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);
|
||||
//memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
|
||||
memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));
|
||||
m_d3dDeviceContext->Unmap(m_readBackBuffer, 0);
|
||||
|
||||
m_onGPU = false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the data back from the GPU without changing its state to be CPU-side.
|
||||
* Useful if we just want to view it on the host for visualization.
|
||||
*/
|
||||
bool copyFromGPU()
|
||||
{
|
||||
if( m_CPUBuffer->size() > 0 )
|
||||
{
|
||||
if( m_onGPU && !m_readOnlyOnGPU )
|
||||
{
|
||||
// Copy back
|
||||
D3D11_MAPPED_SUBRESOURCE MappedResource = {0};
|
||||
|
||||
D3D11_BOX destRegion;
|
||||
destRegion.left = 0;
|
||||
destRegion.front = 0;
|
||||
destRegion.top = 0;
|
||||
destRegion.bottom = 1;
|
||||
destRegion.back = 1;
|
||||
|
||||
destRegion.right = (m_CPUBuffer->size())*sizeof(ElementType);
|
||||
m_d3dDeviceContext->CopySubresourceRegion(
|
||||
m_readBackBuffer,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0 ,
|
||||
m_Buffer,
|
||||
0,
|
||||
&destRegion
|
||||
);
|
||||
|
||||
m_d3dDeviceContext->Map(m_readBackBuffer, 0, D3D11_MAP_READ, 0, &MappedResource);
|
||||
//memcpy(m_hAngVel, MappedResource.pData, (m_maxObjs * sizeof(float) ));
|
||||
memcpy(&((*m_CPUBuffer)[0]), MappedResource.pData, ((m_CPUBuffer->size()) * sizeof(ElementType) ));
|
||||
m_d3dDeviceContext->Unmap(m_readBackBuffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call if data has changed on the CPU.
|
||||
* Can then trigger a move to the GPU as necessary.
|
||||
*/
|
||||
virtual void changedOnCPU()
|
||||
{
|
||||
m_onGPU = false;
|
||||
}
|
||||
}; // class btDX11Buffer
|
||||
|
||||
|
||||
|
||||
#endif // #ifndef BT_SOFT_BODY_SOLVER_BUFFER_DX11_H
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
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.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_DX11.h"
|
||||
|
||||
|
||||
#ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H
|
||||
#define BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
|
||||
class btSoftBodyLinkDataDX11 : public btSoftBodyLinkData
|
||||
{
|
||||
public:
|
||||
bool m_onGPU;
|
||||
ID3D11Device *m_d3dDevice;
|
||||
ID3D11DeviceContext *m_d3dDeviceContext;
|
||||
|
||||
|
||||
btDX11Buffer<LinkNodePair> m_dx11Links;
|
||||
btDX11Buffer<float> m_dx11LinkStrength;
|
||||
btDX11Buffer<float> m_dx11LinksMassLSC;
|
||||
btDX11Buffer<float> m_dx11LinksRestLengthSquared;
|
||||
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11LinksCLength;
|
||||
btDX11Buffer<float> m_dx11LinksLengthRatio;
|
||||
btDX11Buffer<float> m_dx11LinksRestLength;
|
||||
btDX11Buffer<float> m_dx11LinksMaterialLinearStiffnessCoefficient;
|
||||
|
||||
struct BatchPair
|
||||
{
|
||||
int start;
|
||||
int length;
|
||||
|
||||
BatchPair() :
|
||||
start(0),
|
||||
length(0)
|
||||
{
|
||||
}
|
||||
|
||||
BatchPair( int s, int l ) :
|
||||
start( s ),
|
||||
length( l )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Link addressing information for each cloth.
|
||||
* Allows link locations to be computed independently of data batching.
|
||||
*/
|
||||
btAlignedObjectArray< int > m_linkAddresses;
|
||||
|
||||
/**
|
||||
* Start and length values for computation batches over link data.
|
||||
*/
|
||||
btAlignedObjectArray< BatchPair > m_batchStartLengths;
|
||||
|
||||
|
||||
//ID3D11Buffer* readBackBuffer;
|
||||
|
||||
btSoftBodyLinkDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext );
|
||||
|
||||
virtual ~btSoftBodyLinkDataDX11();
|
||||
|
||||
/** Allocate enough space in all link-related arrays to fit numLinks links */
|
||||
virtual void createLinks( int numLinks );
|
||||
|
||||
/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */
|
||||
virtual void setLinkAt( const LinkDescription &link, int linkIndex );
|
||||
|
||||
virtual bool onAccelerator();
|
||||
|
||||
virtual bool moveToAccelerator();
|
||||
|
||||
virtual bool moveFromAccelerator();
|
||||
|
||||
/**
|
||||
* Generate (and later update) the batching for the entire link set.
|
||||
* This redoes a lot of work because it batches the entire set when each cloth is inserted.
|
||||
* In theory we could delay it until just before we need the cloth.
|
||||
* It's a one-off overhead, though, so that is a later optimisation.
|
||||
*/
|
||||
void generateBatches();
|
||||
};
|
||||
|
||||
|
||||
#endif // #ifndef BT_SOFT_BODY_SOLVER_LINK_DATA_DX11_H
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
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.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_DX11.h"
|
||||
|
||||
|
||||
#ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H
|
||||
#define BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
class btSoftBodyTriangleDataDX11 : public btSoftBodyTriangleData
|
||||
{
|
||||
public:
|
||||
bool m_onGPU;
|
||||
ID3D11Device *m_d3dDevice;
|
||||
ID3D11DeviceContext *m_d3dDeviceContext;
|
||||
|
||||
btDX11Buffer<btSoftBodyTriangleData::TriangleNodeSet> m_dx11VertexIndices;
|
||||
btDX11Buffer<float> m_dx11Area;
|
||||
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11Normal;
|
||||
|
||||
struct BatchPair
|
||||
{
|
||||
int start;
|
||||
int length;
|
||||
|
||||
BatchPair() :
|
||||
start(0),
|
||||
length(0)
|
||||
{
|
||||
}
|
||||
|
||||
BatchPair( int s, int l ) :
|
||||
start( s ),
|
||||
length( l )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Link addressing information for each cloth.
|
||||
* Allows link locations to be computed independently of data batching.
|
||||
*/
|
||||
btAlignedObjectArray< int > m_triangleAddresses;
|
||||
|
||||
/**
|
||||
* Start and length values for computation batches over link data.
|
||||
*/
|
||||
btAlignedObjectArray< BatchPair > m_batchStartLengths;
|
||||
|
||||
//ID3D11Buffer* readBackBuffer;
|
||||
|
||||
public:
|
||||
btSoftBodyTriangleDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext );
|
||||
|
||||
virtual ~btSoftBodyTriangleDataDX11();
|
||||
|
||||
|
||||
/** Allocate enough space in all link-related arrays to fit numLinks links */
|
||||
virtual void createTriangles( int numTriangles );
|
||||
|
||||
/** Insert the link described into the correct data structures assuming space has already been allocated by a call to createLinks */
|
||||
virtual void setTriangleAt( const btSoftBodyTriangleData::TriangleDescription &triangle, int triangleIndex );
|
||||
|
||||
virtual bool onAccelerator();
|
||||
virtual bool moveToAccelerator();
|
||||
|
||||
virtual bool moveFromAccelerator();
|
||||
/**
|
||||
* Generate (and later update) the batching for the entire triangle set.
|
||||
* This redoes a lot of work because it batches the entire set when each cloth is inserted.
|
||||
* In theory we could delay it until just before we need the cloth.
|
||||
* It's a one-off overhead, though, so that is a later optimisation.
|
||||
*/
|
||||
void generateBatches();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // #ifndef BT_SOFT_BODY_SOLVER_TRIANGLE_DATA_DX11_H
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
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.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H
|
||||
#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H
|
||||
|
||||
|
||||
#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <crtdbg.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3dx11.h>
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
class btDX11VertexBufferDescriptor : public btVertexBufferDescriptor
|
||||
{
|
||||
protected:
|
||||
/** Context of the DX11 device on which the vertex buffer is stored. */
|
||||
ID3D11DeviceContext* m_context;
|
||||
/** DX11 vertex buffer */
|
||||
ID3D11Buffer* m_vertexBuffer;
|
||||
/** UAV for DX11 buffer */
|
||||
ID3D11UnorderedAccessView* m_vertexBufferUAV;
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* buffer is a pointer to the DX11 buffer to place the vertex data in.
|
||||
* UAV is a pointer to the UAV representation of the buffer laid out in floats.
|
||||
* vertexOffset is the offset in floats to the first vertex.
|
||||
* vertexStride is the stride in floats between vertices.
|
||||
*/
|
||||
btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride )
|
||||
{
|
||||
m_context = context;
|
||||
m_vertexBuffer = buffer;
|
||||
m_vertexBufferUAV = UAV;
|
||||
m_vertexOffset = vertexOffset;
|
||||
m_vertexStride = vertexStride;
|
||||
m_hasVertexPositions = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* buffer is a pointer to the DX11 buffer to place the vertex data in.
|
||||
* UAV is a pointer to the UAV representation of the buffer laid out in floats.
|
||||
* vertexOffset is the offset in floats to the first vertex.
|
||||
* vertexStride is the stride in floats between vertices.
|
||||
* normalOffset is the offset in floats to the first normal.
|
||||
* normalStride is the stride in floats between normals.
|
||||
*/
|
||||
btDX11VertexBufferDescriptor( ID3D11DeviceContext* context, ID3D11Buffer* buffer, ID3D11UnorderedAccessView *UAV, int vertexOffset, int vertexStride, int normalOffset, int normalStride )
|
||||
{
|
||||
m_context = context;
|
||||
m_vertexBuffer = buffer;
|
||||
m_vertexBufferUAV = UAV;
|
||||
m_vertexOffset = vertexOffset;
|
||||
m_vertexStride = vertexStride;
|
||||
m_hasVertexPositions = true;
|
||||
|
||||
m_normalOffset = normalOffset;
|
||||
m_normalStride = normalStride;
|
||||
m_hasNormals = true;
|
||||
}
|
||||
|
||||
virtual ~btDX11VertexBufferDescriptor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of the vertex buffer descriptor.
|
||||
*/
|
||||
virtual BufferTypes getBufferType() const
|
||||
{
|
||||
return DX11_BUFFER;
|
||||
}
|
||||
|
||||
virtual ID3D11DeviceContext* getContext() const
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
virtual ID3D11Buffer* getbtDX11Buffer() const
|
||||
{
|
||||
return m_vertexBuffer;
|
||||
}
|
||||
|
||||
virtual ID3D11UnorderedAccessView* getDX11UAV() const
|
||||
{
|
||||
return m_vertexBufferUAV;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_DX11_H
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
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.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_DX11.h"
|
||||
|
||||
|
||||
#ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H
|
||||
#define BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H
|
||||
|
||||
class btSoftBodyLinkData;
|
||||
class btSoftBodyLinkData::LinkDescription;
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
class btSoftBodyVertexDataDX11 : public btSoftBodyVertexData
|
||||
{
|
||||
protected:
|
||||
bool m_onGPU;
|
||||
ID3D11Device *m_d3dDevice;
|
||||
ID3D11DeviceContext *m_d3dDeviceContext;
|
||||
|
||||
public:
|
||||
btDX11Buffer<int> m_dx11ClothIdentifier;
|
||||
btDX11Buffer<Vectormath::Aos::Point3> m_dx11VertexPosition;
|
||||
btDX11Buffer<Vectormath::Aos::Point3> m_dx11VertexPreviousPosition;
|
||||
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11VertexVelocity;
|
||||
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11VertexForceAccumulator;
|
||||
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11VertexNormal;
|
||||
btDX11Buffer<float> m_dx11VertexInverseMass;
|
||||
btDX11Buffer<float> m_dx11VertexArea;
|
||||
btDX11Buffer<int> m_dx11VertexTriangleCount;
|
||||
|
||||
|
||||
//ID3D11Buffer* readBackBuffer;
|
||||
|
||||
public:
|
||||
btSoftBodyVertexDataDX11( ID3D11Device *d3dDevice, ID3D11DeviceContext *d3dDeviceContext );
|
||||
virtual ~btSoftBodyVertexDataDX11();
|
||||
|
||||
virtual bool onAccelerator();
|
||||
virtual bool moveToAccelerator();
|
||||
|
||||
virtual bool moveFromAccelerator();
|
||||
};
|
||||
|
||||
|
||||
#endif // #ifndef BT_SOFT_BHODY_SOLVER_VERTEX_DATA_DX11_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
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.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "vectormath_aos.h"
|
||||
|
||||
#include "BulletSoftBody/btSoftBodySolvers.h"
|
||||
#include "btSoftBodySolverVertexBuffer_DX11.h"
|
||||
#include "btSoftBodySolverLinkData_DX11.h"
|
||||
#include "btSoftBodySolverVertexData_DX11.h"
|
||||
#include "btSoftBodySolverTriangleData_DX11.h"
|
||||
|
||||
|
||||
#ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H
|
||||
#define BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H
|
||||
|
||||
class btDX11SoftBodySolver : public btSoftBodySolver
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* SoftBody class to maintain information about a soft body instance
|
||||
* within a solver.
|
||||
* This data addresses the main solver arrays.
|
||||
*/
|
||||
class btAcceleratedSoftBodyInterface
|
||||
{
|
||||
protected:
|
||||
/** Current number of vertices that are part of this cloth */
|
||||
int m_numVertices;
|
||||
/** Maximum number of vertices allocated to be part of this cloth */
|
||||
int m_maxVertices;
|
||||
/** Current number of triangles that are part of this cloth */
|
||||
int m_numTriangles;
|
||||
/** Maximum number of triangles allocated to be part of this cloth */
|
||||
int m_maxTriangles;
|
||||
/** Index of first vertex in the world allocated to this cloth */
|
||||
int m_firstVertex;
|
||||
/** Index of first triangle in the world allocated to this cloth */
|
||||
int m_firstTriangle;
|
||||
/** Index of first link in the world allocated to this cloth */
|
||||
int m_firstLink;
|
||||
/** Maximum number of links allocated to this cloth */
|
||||
int m_maxLinks;
|
||||
/** Current number of links allocated to this cloth */
|
||||
int m_numLinks;
|
||||
|
||||
/** The actual soft body this data represents */
|
||||
btSoftBody *m_softBody;
|
||||
|
||||
|
||||
public:
|
||||
btAcceleratedSoftBodyInterface( btSoftBody *softBody ) :
|
||||
m_softBody( softBody )
|
||||
{
|
||||
m_numVertices = 0;
|
||||
m_maxVertices = 0;
|
||||
m_numTriangles = 0;
|
||||
m_maxTriangles = 0;
|
||||
m_firstVertex = 0;
|
||||
m_firstTriangle = 0;
|
||||
m_firstLink = 0;
|
||||
m_maxLinks = 0;
|
||||
m_numLinks = 0;
|
||||
}
|
||||
int getNumVertices()
|
||||
{
|
||||
return m_numVertices;
|
||||
}
|
||||
|
||||
int getNumTriangles()
|
||||
{
|
||||
return m_numTriangles;
|
||||
}
|
||||
|
||||
int getMaxVertices()
|
||||
{
|
||||
return m_maxVertices;
|
||||
}
|
||||
|
||||
int getMaxTriangles()
|
||||
{
|
||||
return m_maxTriangles;
|
||||
}
|
||||
|
||||
int getFirstVertex()
|
||||
{
|
||||
return m_firstVertex;
|
||||
}
|
||||
|
||||
int getFirstTriangle()
|
||||
{
|
||||
return m_firstTriangle;
|
||||
}
|
||||
|
||||
// TODO: All of these set functions will have to do checks and
|
||||
// update the world because restructuring of the arrays will be necessary
|
||||
// Reasonable use of "friend"?
|
||||
void setNumVertices( int numVertices )
|
||||
{
|
||||
m_numVertices = numVertices;
|
||||
}
|
||||
|
||||
void setNumTriangles( int numTriangles )
|
||||
{
|
||||
m_numTriangles = numTriangles;
|
||||
}
|
||||
|
||||
void setMaxVertices( int maxVertices )
|
||||
{
|
||||
m_maxVertices = maxVertices;
|
||||
}
|
||||
|
||||
void setMaxTriangles( int maxTriangles )
|
||||
{
|
||||
m_maxTriangles = maxTriangles;
|
||||
}
|
||||
|
||||
void setFirstVertex( int firstVertex )
|
||||
{
|
||||
m_firstVertex = firstVertex;
|
||||
}
|
||||
|
||||
void setFirstTriangle( int firstTriangle )
|
||||
{
|
||||
m_firstTriangle = firstTriangle;
|
||||
}
|
||||
|
||||
void setMaxLinks( int maxLinks )
|
||||
{
|
||||
m_maxLinks = maxLinks;
|
||||
}
|
||||
|
||||
void setNumLinks( int numLinks )
|
||||
{
|
||||
m_numLinks = numLinks;
|
||||
}
|
||||
|
||||
void setFirstLink( int firstLink )
|
||||
{
|
||||
m_firstLink = firstLink;
|
||||
}
|
||||
|
||||
int getMaxLinks()
|
||||
{
|
||||
return m_maxLinks;
|
||||
}
|
||||
|
||||
int getNumLinks()
|
||||
{
|
||||
return m_numLinks;
|
||||
}
|
||||
|
||||
int getFirstLink()
|
||||
{
|
||||
return m_firstLink;
|
||||
}
|
||||
|
||||
btSoftBody* getSoftBody()
|
||||
{
|
||||
return m_softBody;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void setAcceleration( Vectormath::Aos::Vector3 acceleration )
|
||||
{
|
||||
m_currentSolver->setPerClothAcceleration( m_clothIdentifier, acceleration );
|
||||
}
|
||||
|
||||
void setWindVelocity( Vectormath::Aos::Vector3 windVelocity )
|
||||
{
|
||||
m_currentSolver->setPerClothWindVelocity( m_clothIdentifier, windVelocity );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the density of the air in which the cloth is situated.
|
||||
*/
|
||||
void setAirDensity( btScalar density )
|
||||
{
|
||||
m_currentSolver->setPerClothMediumDensity( m_clothIdentifier, static_cast<float>(density) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collision object to this soft body.
|
||||
*/
|
||||
void addCollisionObject( btCollisionObject *collisionObject )
|
||||
{
|
||||
m_currentSolver->addCollisionObjectForSoftBody( m_clothIdentifier, collisionObject );
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class KernelDesc
|
||||
{
|
||||
protected:
|
||||
|
||||
|
||||
public:
|
||||
ID3D11ComputeShader* kernel;
|
||||
ID3D11Buffer* constBuffer;
|
||||
|
||||
KernelDesc()
|
||||
{
|
||||
kernel = 0;
|
||||
constBuffer = 0;
|
||||
}
|
||||
|
||||
virtual ~KernelDesc()
|
||||
{
|
||||
// TODO: this should probably destroy its kernel but we need to be careful
|
||||
// in case KernelDescs are copied
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct PrepareLinksCB
|
||||
{
|
||||
int numLinks;
|
||||
int padding0;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
struct SolvePositionsFromLinksKernelCB
|
||||
{
|
||||
int startLink;
|
||||
int numLinks;
|
||||
float kst;
|
||||
float ti;
|
||||
};
|
||||
|
||||
struct IntegrateCB
|
||||
{
|
||||
int numNodes;
|
||||
float solverdt;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
struct UpdatePositionsFromVelocitiesCB
|
||||
{
|
||||
int numNodes;
|
||||
float solverSDT;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
struct UpdateVelocitiesFromPositionsWithoutVelocitiesCB
|
||||
{
|
||||
int numNodes;
|
||||
float isolverdt;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
struct UpdateVelocitiesFromPositionsWithVelocitiesCB
|
||||
{
|
||||
int numNodes;
|
||||
float isolverdt;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
struct UpdateSoftBodiesCB
|
||||
{
|
||||
int numNodes;
|
||||
int startFace;
|
||||
int numFaces;
|
||||
float epsilon;
|
||||
};
|
||||
|
||||
|
||||
struct OutputToVertexArrayCB
|
||||
{
|
||||
int startNode;
|
||||
int numNodes;
|
||||
int positionOffset;
|
||||
int positionStride;
|
||||
|
||||
int normalOffset;
|
||||
int normalStride;
|
||||
int padding1;
|
||||
int padding2;
|
||||
};
|
||||
|
||||
|
||||
struct ApplyForcesCB
|
||||
{
|
||||
unsigned int numNodes;
|
||||
float solverdt;
|
||||
float epsilon;
|
||||
int padding3;
|
||||
};
|
||||
|
||||
struct AddVelocityCB
|
||||
{
|
||||
int startNode;
|
||||
int lastNode;
|
||||
float velocityX;
|
||||
float velocityY;
|
||||
float velocityZ;
|
||||
int padding1;
|
||||
int padding2;
|
||||
int padding3;
|
||||
};
|
||||
|
||||
struct VSolveLinksCB
|
||||
{
|
||||
int startLink;
|
||||
int numLinks;
|
||||
float kst;
|
||||
int padding;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
ID3D11Device * m_dx11Device;
|
||||
ID3D11DeviceContext* m_dx11Context;
|
||||
|
||||
|
||||
/** Link data for all cloths. Note that this will be sorted batch-wise for efficient computation and m_linkAddresses will maintain the addressing. */
|
||||
btSoftBodyLinkDataDX11 m_linkData;
|
||||
btSoftBodyVertexDataDX11 m_vertexData;
|
||||
btSoftBodyTriangleDataDX11 m_triangleData;
|
||||
|
||||
/** Variable to define whether we need to update solver constants on the next iteration */
|
||||
bool m_updateSolverConstants;
|
||||
|
||||
bool m_shadersInitialized;
|
||||
|
||||
/**
|
||||
* Cloths owned by this solver.
|
||||
* Only our cloths are in this array.
|
||||
*/
|
||||
btAlignedObjectArray< btAcceleratedSoftBodyInterface * > m_softBodySet;
|
||||
|
||||
/** Acceleration value to be applied to all non-static vertices in the solver.
|
||||
* Index n is cloth n, array sized by number of cloths in the world not the solver.
|
||||
*/
|
||||
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothAcceleration;
|
||||
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11PerClothAcceleration;
|
||||
|
||||
/** Wind velocity to be applied normal to all non-static vertices in the solver.
|
||||
* Index n is cloth n, array sized by number of cloths in the world not the solver.
|
||||
*/
|
||||
btAlignedObjectArray< Vectormath::Aos::Vector3 > m_perClothWindVelocity;
|
||||
btDX11Buffer<Vectormath::Aos::Vector3> m_dx11PerClothWindVelocity;
|
||||
|
||||
/** Velocity damping factor */
|
||||
btAlignedObjectArray< float > m_perClothDampingFactor;
|
||||
btDX11Buffer<float> m_dx11PerClothDampingFactor;
|
||||
|
||||
/** Velocity correction coefficient */
|
||||
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient;
|
||||
btDX11Buffer<float> m_dx11PerClothVelocityCorrectionCoefficient;
|
||||
|
||||
/** Lift parameter for wind effect on cloth. */
|
||||
btAlignedObjectArray< float > m_perClothLiftFactor;
|
||||
btDX11Buffer<float> m_dx11PerClothLiftFactor;
|
||||
|
||||
/** Drag parameter for wind effect on cloth. */
|
||||
btAlignedObjectArray< float > m_perClothDragFactor;
|
||||
btDX11Buffer<float> m_dx11PerClothDragFactor;
|
||||
|
||||
/** Density of the medium in which each cloth sits */
|
||||
btAlignedObjectArray< float > m_perClothMediumDensity;
|
||||
btDX11Buffer<float> m_dx11PerClothMediumDensity;
|
||||
|
||||
KernelDesc prepareLinksKernel;
|
||||
KernelDesc solvePositionsFromLinksKernel;
|
||||
KernelDesc vSolveLinksKernel;
|
||||
KernelDesc integrateKernel;
|
||||
KernelDesc addVelocityKernel;
|
||||
KernelDesc updatePositionsFromVelocitiesKernel;
|
||||
KernelDesc updateVelocitiesFromPositionsWithoutVelocitiesKernel;
|
||||
KernelDesc updateVelocitiesFromPositionsWithVelocitiesKernel;
|
||||
KernelDesc resetNormalsAndAreasKernel;
|
||||
KernelDesc normalizeNormalsAndAreasKernel;
|
||||
KernelDesc updateSoftBodiesKernel;
|
||||
KernelDesc outputToVertexArrayWithNormalsKernel;
|
||||
KernelDesc outputToVertexArrayWithoutNormalsKernel;
|
||||
|
||||
KernelDesc outputToVertexArrayKernel;
|
||||
KernelDesc applyForcesKernel;
|
||||
KernelDesc collideSphereKernel;
|
||||
KernelDesc collideCylinderKernel;
|
||||
|
||||
|
||||
/**
|
||||
* Integrate motion on the solver.
|
||||
*/
|
||||
virtual void integrate( float solverdt );
|
||||
float computeTriangleArea(
|
||||
const Vectormath::Aos::Point3 &vertex0,
|
||||
const Vectormath::Aos::Point3 &vertex1,
|
||||
const Vectormath::Aos::Point3 &vertex2 );
|
||||
|
||||
|
||||
/**
|
||||
* Compile a compute shader kernel from a string and return the appropriate KernelDesc object.
|
||||
*/
|
||||
KernelDesc compileComputeShaderFromString( const char* shaderString, const char* shaderName, int constBufferSize );
|
||||
|
||||
bool buildShaders();
|
||||
|
||||
void resetNormalsAndAreas( int numVertices );
|
||||
|
||||
void normalizeNormalsAndAreas( int numVertices );
|
||||
|
||||
void executeUpdateSoftBodies( int firstTriangle, int numTriangles );
|
||||
|
||||
Vectormath::Aos::Vector3 ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a );
|
||||
|
||||
void ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce );
|
||||
|
||||
virtual void applyForces( float solverdt );
|
||||
|
||||
void updateConstants( float timeStep );
|
||||
|
||||
btAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody );
|
||||
|
||||
//////////////////////////////////////
|
||||
// Kernel dispatches
|
||||
void prepareLinks();
|
||||
|
||||
void updatePositionsFromVelocities( float solverdt );
|
||||
void solveLinksForPosition( int startLink, int numLinks, float kst, float ti );
|
||||
void solveLinksForVelocity( int startLink, int numLinks, float kst );
|
||||
|
||||
void updateVelocitiesFromPositionsWithVelocities( float isolverdt );
|
||||
void updateVelocitiesFromPositionsWithoutVelocities( float isolverdt );
|
||||
|
||||
// End kernel dispatches
|
||||
/////////////////////////////////////
|
||||
|
||||
public:
|
||||
btDX11SoftBodySolver(ID3D11Device * dx11Device, ID3D11DeviceContext* dx11Context);
|
||||
|
||||
virtual ~btDX11SoftBodySolver();
|
||||
|
||||
|
||||
virtual btSoftBodyLinkData &getLinkData();
|
||||
|
||||
virtual btSoftBodyVertexData &getVertexData();
|
||||
|
||||
virtual btSoftBodyTriangleData &getTriangleData();
|
||||
|
||||
|
||||
|
||||
|
||||
virtual bool checkInitialized();
|
||||
|
||||
virtual void updateSoftBodies( );
|
||||
|
||||
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies );
|
||||
|
||||
virtual void solveConstraints( float solverdt );
|
||||
|
||||
virtual void predictMotion( float solverdt );
|
||||
|
||||
virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer );
|
||||
|
||||
};
|
||||
|
||||
#endif // #ifndef BT_ACCELERATED_SOFT_BODY_DX11_SOLVER_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user