Remove btSoftBodySolver_CPU.*
Move btSoftBodySolverData.h to src/BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h Attempt to re-enable MiniCL version of OpenCLClothDemo (cloth-capsule collision still broken) Add optional OpenCL acceleration to SerializeDemo (just for cloth)
This commit is contained in:
@@ -6,7 +6,6 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
|
||||
SUBDIRS (
|
||||
OpenCL
|
||||
CPU
|
||||
)
|
||||
|
||||
IF( USE_DX11 )
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${BULLET_PHYSICS_SOURCE_DIR}/src
|
||||
${VECTOR_MATH_INCLUDE}
|
||||
)
|
||||
|
||||
|
||||
|
||||
SET(BulletSoftBodyCPUSolvers_SRCS
|
||||
btSoftBodySolver_CPU.cpp
|
||||
)
|
||||
|
||||
SET(BulletSoftBodyCPUSolvers_HDRS
|
||||
btSoftBodySolver_CPU.h
|
||||
btSoftBodySolverData.h
|
||||
)
|
||||
|
||||
|
||||
ADD_LIBRARY(BulletSoftBodySolvers_CPU ${BulletSoftBodyCPUSolvers_SRCS} ${BulletSoftBodyCPUSolvers_HDRS} )
|
||||
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_CPU PROPERTIES VERSION ${BULLET_VERSION})
|
||||
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_CPU PROPERTIES SOVERSION ${BULLET_VERSION})
|
||||
IF (BUILD_SHARED_LIBS)
|
||||
TARGET_LINK_LIBRARIES(BulletSoftBodySolvers_CPU BulletSoftBody)
|
||||
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_CPU DESTINATION .)
|
||||
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
INSTALL(TARGETS BulletSoftBodySolvers_CPU DESTINATION lib${LIB_SUFFIX})
|
||||
#headers are already installed by BulletMultiThreaded library
|
||||
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_CPU PROPERTIES FRAMEWORK true)
|
||||
SET_TARGET_PROPERTIES(BulletSoftBodySolvers_CPU PROPERTIES PUBLIC_HEADER "${BulletSoftBodyCPUSolvers_HDRS}")
|
||||
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
|
||||
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
|
||||
ENDIF (INSTALL_LIBS)
|
||||
@@ -1,979 +0,0 @@
|
||||
/*
|
||||
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 "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
#include "vectormath/vmInclude.h"
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolver_CPU.h"
|
||||
#include "BulletSoftBody/btSoftBody.h"
|
||||
#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
|
||||
|
||||
|
||||
btCPUSoftBodySolver::btCPUSoftBodySolver()
|
||||
{
|
||||
// Initial we will clearly need to update solver constants
|
||||
// For now this is global for the cloths linked with this solver - we should probably make this body specific
|
||||
// for performance in future once we understand more clearly when constants need to be updated
|
||||
m_updateSolverConstants = true;
|
||||
}
|
||||
|
||||
btCPUSoftBodySolver::~btCPUSoftBodySolver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
btSoftBodyLinkData &btCPUSoftBodySolver::getLinkData()
|
||||
{
|
||||
return m_linkData;
|
||||
}
|
||||
|
||||
btSoftBodyVertexData &btCPUSoftBodySolver::getVertexData()
|
||||
{
|
||||
return m_vertexData;
|
||||
}
|
||||
|
||||
btSoftBodyTriangleData &btCPUSoftBodySolver::getTriangleData()
|
||||
{
|
||||
return m_triangleData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static Vectormath::Aos::Vector3 toVector3( const btVector3 &vec )
|
||||
{
|
||||
Vectormath::Aos::Vector3 outVec( vec.getX(), vec.getY(), vec.getZ() );
|
||||
return outVec;
|
||||
}
|
||||
|
||||
static Vectormath::Aos::Transform3 toTransform3( const btTransform &transform )
|
||||
{
|
||||
Vectormath::Aos::Transform3 outTransform;
|
||||
outTransform.setCol(0, toVector3(transform.getBasis().getColumn(0)));
|
||||
outTransform.setCol(1, toVector3(transform.getBasis().getColumn(1)));
|
||||
outTransform.setCol(2, toVector3(transform.getBasis().getColumn(2)));
|
||||
outTransform.setCol(3, toVector3(transform.getOrigin()));
|
||||
return outTransform;
|
||||
}
|
||||
|
||||
void btCPUSoftBodySolver::btAcceleratedSoftBodyInterface::updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound )
|
||||
{
|
||||
float scalarMargin = this->getSoftBody()->getCollisionShape()->getMargin();
|
||||
btVector3 vectorMargin( scalarMargin, scalarMargin, scalarMargin );
|
||||
m_softBody->m_bounds[0] = lowerBound - vectorMargin;
|
||||
m_softBody->m_bounds[1] = upperBound + vectorMargin;
|
||||
}
|
||||
|
||||
|
||||
void btCPUSoftBodySolver::copyBackToSoftBodies()
|
||||
{
|
||||
// Loop over soft bodies, copying all the vertex positions back for each body in turn
|
||||
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
|
||||
{
|
||||
btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[ softBodyIndex ];
|
||||
btSoftBody *softBody = softBodyInterface->getSoftBody();
|
||||
|
||||
int firstVertex = softBodyInterface->getFirstVertex();
|
||||
int numVertices = softBodyInterface->getNumVertices();
|
||||
|
||||
// Copy vertices from solver back into the softbody
|
||||
for( int vertex = 0; vertex < numVertices; ++vertex )
|
||||
{
|
||||
using Vectormath::Aos::Point3;
|
||||
Point3 vertexPosition( getVertexData().getVertexPositions()[firstVertex + vertex] );
|
||||
|
||||
softBody->m_nodes[vertex].m_x.setX( vertexPosition.getX() );
|
||||
softBody->m_nodes[vertex].m_x.setY( vertexPosition.getY() );
|
||||
softBody->m_nodes[vertex].m_x.setZ( vertexPosition.getZ() );
|
||||
|
||||
softBody->m_nodes[vertex].m_n.setX( vertexPosition.getX() );
|
||||
softBody->m_nodes[vertex].m_n.setY( vertexPosition.getY() );
|
||||
softBody->m_nodes[vertex].m_n.setZ( vertexPosition.getZ() );
|
||||
}
|
||||
}
|
||||
} // btCPUSoftBodySolver::copyBackToSoftBodies
|
||||
|
||||
void btCPUSoftBodySolver::optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate )
|
||||
{
|
||||
if( forceUpdate || m_softBodySet.size() != softBodies.size() )
|
||||
{
|
||||
// Have a change in the soft body set so update, reloading all the data
|
||||
getVertexData().clear();
|
||||
getTriangleData().clear();
|
||||
getLinkData().clear();
|
||||
m_softBodySet.resize(0);
|
||||
|
||||
|
||||
for( int softBodyIndex = 0; softBodyIndex < softBodies.size(); ++softBodyIndex )
|
||||
{
|
||||
btSoftBody *softBody = softBodies[ softBodyIndex ];
|
||||
using Vectormath::Aos::Matrix3;
|
||||
using Vectormath::Aos::Point3;
|
||||
|
||||
// Create SoftBody that will store the information within the solver
|
||||
btAcceleratedSoftBodyInterface *newSoftBody = new btAcceleratedSoftBodyInterface( softBody );
|
||||
m_softBodySet.push_back( newSoftBody );
|
||||
|
||||
m_perClothAcceleration.push_back( toVector3(softBody->getWorldInfo()->m_gravity) );
|
||||
m_perClothDampingFactor.push_back(softBody->m_cfg.kDP);
|
||||
m_perClothVelocityCorrectionCoefficient.push_back( softBody->m_cfg.kVCF );
|
||||
m_perClothLiftFactor.push_back( softBody->m_cfg.kLF );
|
||||
m_perClothDragFactor.push_back( softBody->m_cfg.kDG );
|
||||
m_perClothMediumDensity.push_back(softBody->getWorldInfo()->air_density);
|
||||
m_perClothCollisionObjects.push_back( CollisionObjectIndices(-1, -1) );
|
||||
|
||||
// Add space for new vertices and triangles in the default solver for now
|
||||
// TODO: Include space here for tearing too later
|
||||
int firstVertex = getVertexData().getNumVertices();
|
||||
int numVertices = softBody->m_nodes.size();
|
||||
int maxVertices = numVertices;
|
||||
// Allocate space for new vertices in all the vertex arrays
|
||||
getVertexData().createVertices( maxVertices, softBodyIndex );
|
||||
|
||||
int firstTriangle = getTriangleData().getNumTriangles();
|
||||
int numTriangles = softBody->m_faces.size();
|
||||
int maxTriangles = numTriangles;
|
||||
getTriangleData().createTriangles( maxTriangles );
|
||||
|
||||
// Copy vertices from softbody into the solver
|
||||
for( int vertex = 0; vertex < numVertices; ++vertex )
|
||||
{
|
||||
Point3 multPoint(softBody->m_nodes[vertex].m_x.getX(), softBody->m_nodes[vertex].m_x.getY(), softBody->m_nodes[vertex].m_x.getZ());
|
||||
btSoftBodyVertexData::VertexDescription desc;
|
||||
|
||||
// TODO: Position in the softbody might be pre-transformed
|
||||
// or we may need to adapt for the pose.
|
||||
//desc.setPosition( cloth.getMeshTransform()*multPoint );
|
||||
desc.setPosition( multPoint );
|
||||
|
||||
float vertexInverseMass = softBody->m_nodes[vertex].m_im;
|
||||
desc.setInverseMass(vertexInverseMass);
|
||||
getVertexData().setVertexAt( desc, firstVertex + vertex );
|
||||
}
|
||||
|
||||
// Copy triangles similarly
|
||||
// We're assuming here that vertex indices are based on the firstVertex rather than the entire scene
|
||||
for( int triangle = 0; triangle < numTriangles; ++triangle )
|
||||
{
|
||||
// Note that large array storage is relative to the array not to the cloth
|
||||
// So we need to add firstVertex to each value
|
||||
int vertexIndex0 = (softBody->m_faces[triangle].m_n[0] - &(softBody->m_nodes[0]));
|
||||
int vertexIndex1 = (softBody->m_faces[triangle].m_n[1] - &(softBody->m_nodes[0]));
|
||||
int vertexIndex2 = (softBody->m_faces[triangle].m_n[2] - &(softBody->m_nodes[0]));
|
||||
btSoftBodyTriangleData::TriangleDescription newTriangle(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, vertexIndex2 + firstVertex);
|
||||
getTriangleData().setTriangleAt( newTriangle, firstTriangle + triangle );
|
||||
|
||||
// Increase vertex triangle counts for this triangle
|
||||
getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex0)++;
|
||||
getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex1)++;
|
||||
getVertexData().getTriangleCount(newTriangle.getVertexSet().vertex2)++;
|
||||
}
|
||||
|
||||
int firstLink = getLinkData().getNumLinks();
|
||||
int numLinks = softBody->m_links.size();
|
||||
int maxLinks = numLinks;
|
||||
|
||||
// Allocate space for the links
|
||||
getLinkData().createLinks( numLinks );
|
||||
|
||||
// Add the links
|
||||
for( int link = 0; link < numLinks; ++link )
|
||||
{
|
||||
int vertexIndex0 = softBody->m_links[link].m_n[0] - &(softBody->m_nodes[0]);
|
||||
int vertexIndex1 = softBody->m_links[link].m_n[1] - &(softBody->m_nodes[0]);
|
||||
|
||||
btSoftBodyLinkData::LinkDescription newLink(vertexIndex0 + firstVertex, vertexIndex1 + firstVertex, softBody->m_links[link].m_material->m_kLST);
|
||||
newLink.setLinkStrength(1.f);
|
||||
getLinkData().setLinkAt(newLink, firstLink + link);
|
||||
}
|
||||
|
||||
newSoftBody->setFirstVertex( firstVertex );
|
||||
newSoftBody->setFirstTriangle( firstTriangle );
|
||||
newSoftBody->setNumVertices( numVertices );
|
||||
newSoftBody->setMaxVertices( maxVertices );
|
||||
newSoftBody->setNumTriangles( numTriangles );
|
||||
newSoftBody->setMaxTriangles( maxTriangles );
|
||||
newSoftBody->setFirstLink( firstLink );
|
||||
newSoftBody->setNumLinks( numLinks );
|
||||
}
|
||||
|
||||
|
||||
|
||||
updateConstants(0.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void btCPUSoftBodySolver::updateSoftBodies()
|
||||
{
|
||||
using namespace Vectormath::Aos;
|
||||
|
||||
int numVertices = m_vertexData.getNumVertices();
|
||||
int numTriangles = m_triangleData.getNumTriangles();
|
||||
|
||||
// Initialise normal and vertex counts
|
||||
for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
|
||||
{
|
||||
m_vertexData.getArea(vertexIndex) = 0.f;
|
||||
m_vertexData.getNormal(vertexIndex) = Vector3(0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
// Update the areas for the triangles and vertices.
|
||||
for( int triangleIndex = 0; triangleIndex < numTriangles; ++triangleIndex )
|
||||
{
|
||||
float &triangleArea( m_triangleData.getTriangleArea( triangleIndex ) );
|
||||
const btSoftBodyTriangleData::TriangleNodeSet &vertices( m_triangleData.getVertexSet(triangleIndex) );
|
||||
|
||||
Point3 &vertexPosition0( m_vertexData.getPosition( vertices.vertex0 ) );
|
||||
Point3 &vertexPosition1( m_vertexData.getPosition( vertices.vertex1 ) );
|
||||
Point3 &vertexPosition2( m_vertexData.getPosition( vertices.vertex2 ) );
|
||||
|
||||
triangleArea = computeTriangleArea( vertexPosition0, vertexPosition1, vertexPosition2 );
|
||||
|
||||
// Add to areas for vertices and increase the count of the number of triangles affecting the vertex
|
||||
m_vertexData.getArea(vertices.vertex0) += triangleArea;
|
||||
m_vertexData.getArea(vertices.vertex1) += triangleArea;
|
||||
m_vertexData.getArea(vertices.vertex2) += triangleArea;
|
||||
|
||||
Point3 &vertex0( m_vertexData.getPosition(vertices.vertex0) );
|
||||
Point3 &vertex1( m_vertexData.getPosition(vertices.vertex1) );
|
||||
Point3 &vertex2( m_vertexData.getPosition(vertices.vertex2) );
|
||||
|
||||
Vector3 triangleNormal = cross( vertex1-vertex0, vertex2 - vertex0 );
|
||||
|
||||
m_triangleData.getNormal(triangleIndex) = normalize(triangleNormal);
|
||||
|
||||
m_vertexData.getNormal(vertices.vertex0) += triangleNormal;
|
||||
m_vertexData.getNormal(vertices.vertex1) += triangleNormal;
|
||||
m_vertexData.getNormal(vertices.vertex2) += triangleNormal;
|
||||
|
||||
}
|
||||
|
||||
// Normalise the area and normals
|
||||
for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
|
||||
{
|
||||
m_vertexData.getArea(vertexIndex) /= m_vertexData.getTriangleCount(vertexIndex);
|
||||
m_vertexData.getNormal(vertexIndex) = normalize( m_vertexData.getNormal(vertexIndex) );
|
||||
}
|
||||
|
||||
|
||||
// Clear the collision shape array for the next frame
|
||||
m_collisionObjectDetails.clear();
|
||||
|
||||
} // updateSoftBodies
|
||||
|
||||
|
||||
Vectormath::Aos::Vector3 btCPUSoftBodySolver::ProjectOnAxis( const Vectormath::Aos::Vector3 &v, const Vectormath::Aos::Vector3 &a )
|
||||
{
|
||||
return a*Vectormath::Aos::dot(v, a);
|
||||
}
|
||||
|
||||
void btCPUSoftBodySolver::ApplyClampedForce( float solverdt, const Vectormath::Aos::Vector3 &force, const Vectormath::Aos::Vector3 &vertexVelocity, float inverseMass, Vectormath::Aos::Vector3 &vertexForce )
|
||||
{
|
||||
float dtInverseMass = solverdt*inverseMass;
|
||||
if( Vectormath::Aos::lengthSqr(force * dtInverseMass) > Vectormath::Aos::lengthSqr(vertexVelocity) )
|
||||
{
|
||||
vertexForce -= ProjectOnAxis( vertexVelocity, normalize( force ) )/dtInverseMass;
|
||||
} else {
|
||||
vertexForce += force;
|
||||
}
|
||||
}
|
||||
|
||||
bool btCPUSoftBodySolver::checkInitialized()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void btCPUSoftBodySolver::applyForces( float solverdt )
|
||||
{
|
||||
using namespace Vectormath::Aos;
|
||||
|
||||
int numVertices = m_vertexData.getNumVertices();
|
||||
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
|
||||
{
|
||||
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
|
||||
const int startVertex = currentCloth->getFirstVertex();
|
||||
const int numVertices = currentCloth->getNumVertices();
|
||||
|
||||
Vector3 velocityChange = m_perClothAcceleration[clothIndex]*solverdt;
|
||||
for( int vertexIndex = startVertex; vertexIndex < (startVertex + numVertices); ++vertexIndex )
|
||||
{
|
||||
float inverseMass = m_vertexData.getInverseMass( vertexIndex );
|
||||
Vector3 &vertexVelocity( m_vertexData.getVelocity( vertexIndex ) );
|
||||
|
||||
// First apply the global acceleration to all vertices
|
||||
if( inverseMass > 0 )
|
||||
vertexVelocity += velocityChange;
|
||||
|
||||
// If it's a non-static vertex
|
||||
if( m_vertexData.getInverseMass(vertexIndex) > 0 )
|
||||
{
|
||||
// Wind effects on a wind-per-cloth basis
|
||||
float liftFactor = m_perClothLiftFactor[clothIndex];
|
||||
float dragFactor = m_perClothDragFactor[clothIndex];
|
||||
if( (liftFactor > 0.f) || (dragFactor > 0.f) )
|
||||
{
|
||||
Vector3 normal = m_vertexData.getNormal(vertexIndex);
|
||||
Vector3 relativeWindVelocity = m_vertexData.getVelocity(vertexIndex) - m_perClothWindVelocity[clothIndex];
|
||||
float relativeSpeedSquared = lengthSqr(relativeWindVelocity);
|
||||
if( relativeSpeedSquared > FLT_EPSILON )
|
||||
{
|
||||
normal = normal * (dot(normal, relativeWindVelocity) < 0 ? -1.f : +1.f);
|
||||
float dvNormal = dot(normal, relativeWindVelocity);
|
||||
if( dvNormal > 0 )
|
||||
{
|
||||
Vector3 force( 0.f, 0.f, 0.f );
|
||||
float c0 = m_vertexData.getArea(vertexIndex) * dvNormal * relativeSpeedSquared / 2;
|
||||
float c1 = c0 * m_perClothMediumDensity[clothIndex];
|
||||
force += normal * (-c1 * liftFactor);
|
||||
force += normalize(relativeWindVelocity)*(-c1 * dragFactor);
|
||||
|
||||
Vectormath::Aos::Vector3 &vertexForce( m_vertexData.getForceAccumulator(vertexIndex) );
|
||||
ApplyClampedForce( solverdt, force, vertexVelocity, inverseMass, vertexForce );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // btCPUSoftBodySolver::applyForces
|
||||
|
||||
/**
|
||||
* Integrate motion on the solver.
|
||||
*/
|
||||
void btCPUSoftBodySolver::integrate( float solverdt )
|
||||
{
|
||||
using namespace Vectormath::Aos;
|
||||
int numVertices = m_vertexData.getNumVertices();
|
||||
for( int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex )
|
||||
{
|
||||
Point3 &position( m_vertexData.getPosition(vertexIndex) );
|
||||
Point3 &previousPosition( m_vertexData.getPreviousPosition(vertexIndex) );
|
||||
Vector3 &forceAccumulator( m_vertexData.getForceAccumulator(vertexIndex) );
|
||||
Vector3 &velocity( m_vertexData.getVelocity(vertexIndex) );
|
||||
float inverseMass = m_vertexData.getInverseMass(vertexIndex);
|
||||
|
||||
previousPosition = position;
|
||||
velocity += forceAccumulator * inverseMass * solverdt;
|
||||
position += velocity * solverdt;
|
||||
forceAccumulator = Vector3(0.f, 0.f, 0.f);
|
||||
}
|
||||
} // btCPUSoftBodySolver::integrate
|
||||
|
||||
float btCPUSoftBodySolver::computeTriangleArea(
|
||||
const Vectormath::Aos::Point3 &vertex0,
|
||||
const Vectormath::Aos::Point3 &vertex1,
|
||||
const Vectormath::Aos::Point3 &vertex2 )
|
||||
{
|
||||
Vectormath::Aos::Vector3 a = vertex1 - vertex0;
|
||||
Vectormath::Aos::Vector3 b = vertex2 - vertex0;
|
||||
Vectormath::Aos::Vector3 crossProduct = cross(a, b);
|
||||
float area = length( crossProduct );
|
||||
return area;
|
||||
}
|
||||
|
||||
void btCPUSoftBodySolver::updateConstants( float timeStep )
|
||||
{
|
||||
using namespace Vectormath::Aos;
|
||||
|
||||
if( m_updateSolverConstants )
|
||||
{
|
||||
m_updateSolverConstants = false;
|
||||
|
||||
// Will have to redo this if we change the structure (tear, maybe) or various other possible changes
|
||||
|
||||
// Initialise link constants
|
||||
const int numLinks = m_linkData.getNumLinks();
|
||||
for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
|
||||
{
|
||||
btSoftBodyLinkData::LinkNodePair &vertices( m_linkData.getVertexPair(linkIndex) );
|
||||
m_linkData.getRestLength(linkIndex) = length((m_vertexData.getPosition( vertices.vertex0 ) - m_vertexData.getPosition( vertices.vertex1 )));
|
||||
float invMass0 = m_vertexData.getInverseMass(vertices.vertex0);
|
||||
float invMass1 = m_vertexData.getInverseMass(vertices.vertex1);
|
||||
float linearStiffness = m_linkData.getLinearStiffnessCoefficient(linkIndex);
|
||||
float massLSC = (invMass0 + invMass1)/linearStiffness;
|
||||
m_linkData.getMassLSC(linkIndex) = massLSC;
|
||||
float restLength = m_linkData.getRestLength(linkIndex);
|
||||
float restLengthSquared = restLength*restLength;
|
||||
m_linkData.getRestLengthSquared(linkIndex) = restLengthSquared;
|
||||
}
|
||||
}
|
||||
} // btCPUSoftBodySolver::updateConstants
|
||||
|
||||
|
||||
|
||||
|
||||
void btCPUSoftBodySolver::updateBounds()
|
||||
{
|
||||
using Vectormath::Aos::Point3;
|
||||
|
||||
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
|
||||
{
|
||||
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
|
||||
btVector3 startBound(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||
btVector3 endBound(FLT_MIN, FLT_MIN, FLT_MIN);
|
||||
|
||||
const int startVertex = currentCloth->getFirstVertex();
|
||||
const int numVertices = currentCloth->getNumVertices();
|
||||
|
||||
int endVertex = startVertex + numVertices;
|
||||
for(int vertexIndex = startVertex; vertexIndex < endVertex; ++vertexIndex)
|
||||
{
|
||||
btVector3 vertexPosition( m_vertexData.getVertexPositions()[vertexIndex].getX(), m_vertexData.getVertexPositions()[vertexIndex].getY(), m_vertexData.getVertexPositions()[vertexIndex].getZ() );
|
||||
startBound.setX( btMin( startBound.getX(), vertexPosition.getX() ) );
|
||||
startBound.setY( btMin( startBound.getY(), vertexPosition.getY() ) );
|
||||
startBound.setZ( btMin( startBound.getZ(), vertexPosition.getZ() ) );
|
||||
|
||||
endBound.setX( btMax( endBound.getX(), vertexPosition.getX() ) );
|
||||
endBound.setY( btMax( endBound.getY(), vertexPosition.getY() ) );
|
||||
endBound.setZ( btMax( endBound.getZ(), vertexPosition.getZ() ) );
|
||||
}
|
||||
|
||||
m_softBodySet[clothIndex]->updateBounds( startBound, endBound );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class btCPUSB_QuickSortCompare
|
||||
{
|
||||
public:
|
||||
|
||||
bool operator() ( const btCPUCollisionShapeDescription& a, const btCPUCollisionShapeDescription& b )
|
||||
{
|
||||
return ( a.softBodyIdentifier < b.softBodyIdentifier );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort the collision object details array and generate indexing into it for the per-cloth collision object array.
|
||||
*/
|
||||
void btCPUSoftBodySolver::prepareCollisionConstraints()
|
||||
{
|
||||
// First do a simple sort on the collision objects
|
||||
btAlignedObjectArray<int> numObjectsPerClothPrefixSum;
|
||||
btAlignedObjectArray<int> numObjectsPerCloth;
|
||||
numObjectsPerCloth.resize( m_softBodySet.size(), 0 );
|
||||
numObjectsPerClothPrefixSum.resize( m_softBodySet.size(), 0 );
|
||||
|
||||
if (!m_perClothCollisionObjects.size())
|
||||
return;
|
||||
|
||||
m_collisionObjectDetails.quickSort( btCPUSB_QuickSortCompare() );
|
||||
|
||||
// Generating indexing for perClothCollisionObjects
|
||||
// First clear the previous values with the "no collision object for cloth" constant
|
||||
for( int clothIndex = 0; clothIndex < m_perClothCollisionObjects.size(); ++clothIndex )
|
||||
{
|
||||
m_perClothCollisionObjects[clothIndex].firstObject = -1;
|
||||
m_perClothCollisionObjects[clothIndex].endObject = -1;
|
||||
}
|
||||
int currentCloth = 0;
|
||||
int startIndex = 0;
|
||||
for( int collisionObject = 0; collisionObject < m_collisionObjectDetails.size(); ++collisionObject )
|
||||
{
|
||||
int nextCloth = m_collisionObjectDetails[collisionObject].softBodyIdentifier;
|
||||
if( nextCloth != currentCloth )
|
||||
{
|
||||
// Changed cloth in the array
|
||||
// Set the end index and the range is what we need for currentCloth
|
||||
m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
|
||||
m_perClothCollisionObjects[currentCloth].endObject = collisionObject;
|
||||
currentCloth = nextCloth;
|
||||
startIndex = collisionObject;
|
||||
}
|
||||
}
|
||||
|
||||
// And update last cloth
|
||||
m_perClothCollisionObjects[currentCloth].firstObject = startIndex;
|
||||
m_perClothCollisionObjects[currentCloth].endObject = m_collisionObjectDetails.size();
|
||||
|
||||
} // prepareCollisionConstraints
|
||||
|
||||
|
||||
void btCPUSoftBodySolver::solveConstraints( float solverdt )
|
||||
{
|
||||
using Vectormath::Aos::Vector3;
|
||||
using Vectormath::Aos::Point3;
|
||||
using Vectormath::Aos::lengthSqr;
|
||||
using Vectormath::Aos::dot;
|
||||
|
||||
// Prepare links
|
||||
int numLinks = m_linkData.getNumLinks();
|
||||
int numVertices = m_vertexData.getNumVertices();
|
||||
|
||||
float kst = 1.f;
|
||||
|
||||
for( int linkIndex = 0; linkIndex < numLinks; ++linkIndex )
|
||||
{
|
||||
btSoftBodyLinkData::LinkNodePair &nodePair( m_linkData.getVertexPair(linkIndex) );
|
||||
Vector3 currentLength = m_vertexData.getPreviousPosition( nodePair.vertex1 ) - m_vertexData.getPreviousPosition( nodePair.vertex0 );
|
||||
m_linkData.getCurrentLength(linkIndex) = currentLength;
|
||||
|
||||
// If mass at both ends of links is 0 (both static points) then we don't want this information.
|
||||
// In reality this would be a fairly pointless link, but it could have been inserted
|
||||
float linkLengthRatio = 0;
|
||||
if( m_linkData.getMassLSC(linkIndex) > 0 )
|
||||
linkLengthRatio = 1.f/(lengthSqr(currentLength) * m_linkData.getMassLSC(linkIndex));
|
||||
m_linkData.getLinkLengthRatio(linkIndex) = linkLengthRatio;
|
||||
|
||||
}
|
||||
|
||||
|
||||
prepareCollisionConstraints();
|
||||
|
||||
|
||||
for( int iteration = 0; iteration < m_numberOfVelocityIterations ; ++iteration )
|
||||
{
|
||||
// Solve velocity
|
||||
for(int linkIndex = 0; linkIndex < numLinks; ++linkIndex)
|
||||
{
|
||||
|
||||
int vertexIndex0 = m_linkData.getVertexPair(linkIndex).vertex0;
|
||||
int vertexIndex1 = m_linkData.getVertexPair(linkIndex).vertex1;
|
||||
|
||||
float j = -dot(m_linkData.getCurrentLength(linkIndex), m_vertexData.getVelocity(vertexIndex0) - m_vertexData.getVelocity(vertexIndex1)) * m_linkData.getLinkLengthRatio(linkIndex)*kst;
|
||||
|
||||
// If both ends of the link have no mass then this will be zero. Catch that case.
|
||||
// TODO: Should really catch the /0 in the link setup, too
|
||||
//if(psb->m_linksc0[i]>0)
|
||||
{
|
||||
m_vertexData.getVelocity(vertexIndex0) = m_vertexData.getVelocity(vertexIndex0) + m_linkData.getCurrentLength(linkIndex)*j*m_vertexData.getInverseMass(vertexIndex0);
|
||||
m_vertexData.getVelocity(vertexIndex1) = m_vertexData.getVelocity(vertexIndex1) - m_linkData.getCurrentLength(linkIndex)*j*m_vertexData.getInverseMass(vertexIndex1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute new positions from velocity
|
||||
// Also update the previous position so that our position computation is now based on the new position from the velocity solution
|
||||
// rather than based directly on the original positions
|
||||
if( m_numberOfVelocityIterations > 0 )
|
||||
{
|
||||
for(int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
|
||||
{
|
||||
m_vertexData.getPosition(vertexIndex) = m_vertexData.getPreviousPosition(vertexIndex) + m_vertexData.getVelocity(vertexIndex) * solverdt;
|
||||
m_vertexData.getPreviousPosition(vertexIndex) = m_vertexData.getPosition(vertexIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Solve drift
|
||||
for( int iteration = 0; iteration < m_numberOfPositionIterations ; ++iteration )
|
||||
{
|
||||
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
|
||||
{
|
||||
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
|
||||
|
||||
const int startLink = currentCloth->getFirstLink();
|
||||
const int numLinks = currentCloth->getNumLinks();
|
||||
|
||||
int endLink = startLink + numLinks;
|
||||
for(int linkIndex = startLink; linkIndex < endLink; ++linkIndex)
|
||||
{
|
||||
int vertexIndex0 = m_linkData.getVertexPair(linkIndex).vertex0;
|
||||
int vertexIndex1 = m_linkData.getVertexPair(linkIndex).vertex1;
|
||||
|
||||
float massLSC = m_linkData.getMassLSC(linkIndex);
|
||||
if( massLSC > 0.f )
|
||||
{
|
||||
Point3 &vertexPosition0( m_vertexData.getPosition( vertexIndex0 ) );
|
||||
Point3 &vertexPosition1( m_vertexData.getPosition( vertexIndex1 ) );
|
||||
|
||||
Vector3 del = vertexPosition1 - vertexPosition0;
|
||||
float len = lengthSqr(del);
|
||||
float restLength2 = m_linkData.getRestLengthSquared(linkIndex);
|
||||
float k = ((restLength2 - len) / (massLSC * (restLength2 + len) ) )*kst;
|
||||
|
||||
vertexPosition0 -= del*(k*m_vertexData.getInverseMass(vertexIndex0));
|
||||
vertexPosition1 += del*(k*m_vertexData.getInverseMass(vertexIndex1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear forces so that friction is applied correctly
|
||||
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
|
||||
{
|
||||
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
|
||||
|
||||
const int startLink = currentCloth->getFirstLink();
|
||||
const int numLinks = currentCloth->getNumLinks();
|
||||
const int startVertex = currentCloth->getFirstVertex();
|
||||
const int numVertices = currentCloth->getNumVertices();
|
||||
const int lastVertex = startVertex + numVertices;
|
||||
// Update the velocities based on the change in position
|
||||
// TODO: Damping should only be applied to the action of link constraints so the cloth still falls but then moves stiffly once it hits something
|
||||
float velocityCoefficient = (1.f - m_perClothDampingFactor[clothIndex]);
|
||||
float velocityCorrectionCoefficient = m_perClothVelocityCorrectionCoefficient[clothIndex];
|
||||
float isolverDt = 1.f/solverdt;
|
||||
|
||||
for(int vertexIndex = startVertex; vertexIndex < lastVertex; ++vertexIndex)
|
||||
{
|
||||
m_vertexData.getForceAccumulator( vertexIndex ) = Vector3(0.f, 0.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Solve collision constraints
|
||||
// Very simple solver that pushes the vertex out of collision imposters for now
|
||||
// to test integration with the broad phase code.
|
||||
// May also want to put this into position solver loop every n iterations depending on
|
||||
// how it behaves
|
||||
for( int clothIndex = 0; clothIndex < m_softBodySet.size(); ++clothIndex )
|
||||
{
|
||||
btAcceleratedSoftBodyInterface *currentCloth = m_softBodySet[clothIndex];
|
||||
|
||||
float clothFriction = currentCloth->getSoftBody()->getFriction();
|
||||
|
||||
const int startVertex = currentCloth->getFirstVertex();
|
||||
const int numVertices = currentCloth->getNumVertices();
|
||||
int endVertex = startVertex + numVertices;
|
||||
|
||||
float velocityCoefficient = (1.f - m_perClothDampingFactor[clothIndex]);
|
||||
float velocityCorrectionCoefficient = m_perClothVelocityCorrectionCoefficient[clothIndex];
|
||||
float isolverDt = 1.f/solverdt;
|
||||
|
||||
int startObject = m_perClothCollisionObjects[clothIndex].firstObject;
|
||||
int endObject = m_perClothCollisionObjects[clothIndex].endObject;
|
||||
|
||||
if( endObject == startObject )
|
||||
{
|
||||
// No collisions so just do the force update
|
||||
for(int vertexIndex = startVertex; vertexIndex < endVertex; ++vertexIndex)
|
||||
{
|
||||
m_vertexData.getForceAccumulator( vertexIndex ) = Vector3(0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
// Recompute velocity based on updated position inclusive of drift
|
||||
for(int vertexIndex = startVertex; vertexIndex < endVertex; ++vertexIndex)
|
||||
{
|
||||
m_vertexData.getVelocity(vertexIndex) = (m_vertexData.getPosition(vertexIndex) - m_vertexData.getPreviousPosition(vertexIndex)) * velocityCoefficient * isolverDt;
|
||||
}
|
||||
} else {
|
||||
|
||||
for( int collisionObject = startObject; collisionObject < endObject; ++collisionObject )
|
||||
{
|
||||
btCPUCollisionShapeDescription &shapeDescription( m_collisionObjectDetails[collisionObject] );
|
||||
|
||||
float colliderFriction = shapeDescription.friction;
|
||||
|
||||
if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
|
||||
{
|
||||
using namespace Vectormath::Aos;
|
||||
|
||||
float capsuleHalfHeight = shapeDescription.shapeInformation.capsule.halfHeight;
|
||||
float capsuleRadius = shapeDescription.shapeInformation.capsule.radius;
|
||||
int capsuleUpAxis = shapeDescription.shapeInformation.capsule.upAxis;
|
||||
float capsuleMargin = shapeDescription.margin;
|
||||
|
||||
Transform3 worldTransform = shapeDescription.shapeTransform;
|
||||
|
||||
// As this is a GPU comparison solver just iterate over the vertices
|
||||
for( int vertexIndex = startVertex; vertexIndex < endVertex; ++vertexIndex )
|
||||
{
|
||||
// Clear force for vertex first
|
||||
m_vertexData.getForceAccumulator( vertexIndex ) = Vector3(0.f, 0.f, 0.f);
|
||||
|
||||
Point3 vertex( m_vertexData.getPosition( vertexIndex ) );
|
||||
|
||||
// Correctly define the centerline depending on the upAxis
|
||||
Point3 c1(0.f, 0.f, 0.f);
|
||||
Point3 c2(0.f, 0.f, 0.f);
|
||||
if( capsuleUpAxis == 0 ) {
|
||||
c1.setX(-capsuleHalfHeight);
|
||||
c2.setX(capsuleHalfHeight);
|
||||
} else if( capsuleUpAxis == 1 ) {
|
||||
c1.setY(-capsuleHalfHeight);
|
||||
c2.setY(capsuleHalfHeight);
|
||||
} else {
|
||||
c1.setZ(-capsuleHalfHeight);
|
||||
c2.setZ(capsuleHalfHeight);
|
||||
}
|
||||
|
||||
Point3 worldC1 = worldTransform * c1;
|
||||
Point3 worldC2 = worldTransform * c2;
|
||||
Vector3 segment = worldC2 - worldC1;
|
||||
|
||||
// compute distance of tangent to vertex along line segment in capsule
|
||||
float distanceAlongSegment = -( dot( worldC1 - vertex, segment ) / lengthSqr(segment) );
|
||||
|
||||
Point3 closestPoint = (worldC1 + segment * distanceAlongSegment);
|
||||
float distanceFromLine = length(vertex - closestPoint);
|
||||
float distanceFromC1 = length(worldC1 - vertex);
|
||||
float distanceFromC2 = length(worldC2 - vertex);
|
||||
|
||||
// Final distance from collision, point to push from, direction to push in
|
||||
// for impulse force
|
||||
float distance;
|
||||
Point3 sourcePoint;
|
||||
Vector3 normalVector;
|
||||
if( distanceAlongSegment < 0 )
|
||||
{
|
||||
distance = distanceFromC1;
|
||||
sourcePoint = worldC1;
|
||||
normalVector = normalize(vertex - worldC1);
|
||||
} else if( distanceAlongSegment > 1.f ) {
|
||||
distance = distanceFromC2;
|
||||
sourcePoint = worldC2;
|
||||
normalVector = normalize(vertex - worldC2);
|
||||
} else {
|
||||
distance = distanceFromLine;
|
||||
sourcePoint = closestPoint;
|
||||
normalVector = normalize(vertex - closestPoint);
|
||||
}
|
||||
|
||||
Vector3 colliderLinearVelocity( shapeDescription.linearVelocity );
|
||||
Vector3 colliderAngularVelocity( shapeDescription.angularVelocity );
|
||||
Vector3 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, Vector3(vertex) - worldTransform.getTranslation());
|
||||
|
||||
float minDistance = capsuleRadius + capsuleMargin;
|
||||
bool collided = false;
|
||||
|
||||
if( distance < minDistance )
|
||||
{
|
||||
// Project back to surface along normal
|
||||
Vectormath::Aos::Point3 sourcePos = m_vertexData.getPosition( vertexIndex );
|
||||
Vectormath::Aos::Vector3 posChange = (minDistance - distance)*normalVector*0.9;
|
||||
//if( length(posChange) > 1 )
|
||||
// std::cerr << "Poschange: " << length(posChange) << "\n";
|
||||
|
||||
Vectormath::Aos::Point3 newPos = sourcePos + posChange;
|
||||
m_vertexData.getPosition( vertexIndex ) = newPos;
|
||||
//m_vertexData.getPosition( vertexIndex ) = m_vertexData.getPosition( vertexIndex ) + (minDistance - distance)*normalVector*0.9;
|
||||
|
||||
// Experiment with moving back along source vector.
|
||||
// Removes all ability to slide because it projects back along the vector length so it would undo lateral movement.
|
||||
// TODO: This isn't quite right because we should take the movement of the collider into account as well
|
||||
/*Vector3 incomingMoveVector( normalize(m_vertexData.getPreviousPosition(vertexIndex) - m_vertexData.getPosition(vertexIndex)) );
|
||||
Vector3 normalDirectionMoveOut( (minDistance - distance)*normalVector*0.9 );
|
||||
float distanceOnIncomingVector = dot(normalDirectionMoveOut, incomingMoveVector);
|
||||
Vector3 vectorCorrection( distanceOnIncomingVector*incomingMoveVector );
|
||||
m_vertexData.getPosition( vertexIndex ) = m_vertexData.getPosition( vertexIndex ) + vectorCorrection;*/
|
||||
|
||||
|
||||
collided = true;
|
||||
}
|
||||
|
||||
// Update velocity of vertex based on position
|
||||
m_vertexData.getVelocity(vertexIndex) = (m_vertexData.getPosition(vertexIndex) - m_vertexData.getPreviousPosition(vertexIndex)) * velocityCoefficient * isolverDt;
|
||||
|
||||
// If we collided before we are on the surface so have friction
|
||||
if( collided )
|
||||
{
|
||||
// Compute friction
|
||||
|
||||
// TODO: Just vertex velocity not enough, really we need the velocity
|
||||
// relative to closest point on the surface of the collider
|
||||
Vector3 vertexVelocity( m_vertexData.getVelocity(vertexIndex) );
|
||||
Vector3 relativeVelocity( vertexVelocity - velocityOfSurfacePoint );
|
||||
|
||||
|
||||
// First compute vectors for plane perpendicular to normal vector
|
||||
// Cross any vector with normal vector first then cross the normal with it again
|
||||
Vector3 p1(normalize(cross(normalVector, segment)));
|
||||
Vector3 p2(normalize(cross(p1, normalVector)));
|
||||
// Full friction is sum of velocities in each direction of plane.
|
||||
Vector3 frictionVector(p1*dot(relativeVelocity, p1) + p2*dot(relativeVelocity, p2));
|
||||
|
||||
// Real friction is peak friction corrected by friction coefficients.
|
||||
frictionVector = frictionVector*(colliderFriction*clothFriction);
|
||||
|
||||
float approachSpeed = dot( relativeVelocity, normalVector );
|
||||
|
||||
// For now just update vertex position by moving to radius distance along the push vector
|
||||
// Could use this as the basis for simple vector distance constraint for the point later, possibly?
|
||||
// That way in the main solver loop all shape types could be the same... though when
|
||||
// we need to apply bi-directionally it becomes more complicated
|
||||
|
||||
// Add friction vector to the force accumulator
|
||||
Vector3 ¤tForce( m_vertexData.getForceAccumulator( vertexIndex ) );
|
||||
|
||||
// Only apply if the vertex is moving towards the object to reduce jitter error
|
||||
if( approachSpeed <= 0.0 )
|
||||
currentForce -= frictionVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for( int collisionObject = startObject; collisionObject < endObject; ++collisionObject )
|
||||
} // if( endObject == startObject )
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // btCPUSoftBodySolver::solveConstraints
|
||||
|
||||
|
||||
btCPUSoftBodySolver::btAcceleratedSoftBodyInterface *btCPUSoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody )
|
||||
{
|
||||
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
|
||||
{
|
||||
btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
|
||||
if( softBodyInterface->getSoftBody() == softBody )
|
||||
return softBodyInterface;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const btCPUSoftBodySolver::btAcceleratedSoftBodyInterface * const btCPUSoftBodySolver::findSoftBodyInterface( const btSoftBody* const softBody ) const
|
||||
{
|
||||
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
|
||||
{
|
||||
const btAcceleratedSoftBodyInterface *const softBodyInterface = m_softBodySet[softBodyIndex];
|
||||
if( softBodyInterface->getSoftBody() == softBody )
|
||||
return softBodyInterface;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btCPUSoftBodySolver::findSoftBodyIndex( const btSoftBody* const softBody )
|
||||
{
|
||||
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
|
||||
{
|
||||
btAcceleratedSoftBodyInterface *softBodyInterface = m_softBodySet[softBodyIndex];
|
||||
if( softBodyInterface->getSoftBody() == softBody )
|
||||
return softBodyIndex;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void btSoftBodySolverOutputCPUtoCPU::copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer )
|
||||
{
|
||||
// Currently only support CPU output buffers
|
||||
|
||||
const btSoftBodySolver *solver = softBody->getSoftBodySolver();
|
||||
btAssert( solver->getSolverType() == btSoftBodySolver::CPU_SOLVER );
|
||||
const btCPUSoftBodySolver *cpuSolver = static_cast< const btCPUSoftBodySolver * >( solver );
|
||||
const btCPUSoftBodySolver::btAcceleratedSoftBodyInterface * const currentCloth = cpuSolver->findSoftBodyInterface( softBody );
|
||||
const btSoftBodyVertexData &vertexData( cpuSolver->m_vertexData );
|
||||
|
||||
if( vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER )
|
||||
{
|
||||
const int firstVertex = currentCloth->getFirstVertex();
|
||||
const int lastVertex = firstVertex + currentCloth->getNumVertices();
|
||||
const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast< btCPUVertexBufferDescriptor* >(vertexBuffer);
|
||||
float *basePointer = cpuVertexBuffer->getBasePointer();
|
||||
|
||||
if( vertexBuffer->hasVertexPositions() )
|
||||
{
|
||||
const int vertexOffset = cpuVertexBuffer->getVertexOffset();
|
||||
const int vertexStride = cpuVertexBuffer->getVertexStride();
|
||||
float *vertexPointer = basePointer + vertexOffset;
|
||||
|
||||
for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
|
||||
{
|
||||
Vectormath::Aos::Point3 position = vertexData.getPosition(vertexIndex);
|
||||
*(vertexPointer + 0) = position.getX();
|
||||
*(vertexPointer + 1) = position.getY();
|
||||
*(vertexPointer + 2) = position.getZ();
|
||||
vertexPointer += vertexStride;
|
||||
}
|
||||
}
|
||||
if( vertexBuffer->hasNormals() )
|
||||
{
|
||||
const int normalOffset = cpuVertexBuffer->getNormalOffset();
|
||||
const int normalStride = cpuVertexBuffer->getNormalStride();
|
||||
float *normalPointer = basePointer + normalOffset;
|
||||
|
||||
for( int vertexIndex = firstVertex; vertexIndex < lastVertex; ++vertexIndex )
|
||||
{
|
||||
Vectormath::Aos::Vector3 normal = vertexData.getNormal(vertexIndex);
|
||||
*(normalPointer + 0) = normal.getX();
|
||||
*(normalPointer + 1) = normal.getY();
|
||||
*(normalPointer + 2) = normal.getZ();
|
||||
normalPointer += normalStride;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
btAssert( 0=="Invalid vertex buffer descriptor used in CPU output." );
|
||||
}
|
||||
} // btCPUSoftBodySolver::outputToVertexBuffers
|
||||
|
||||
void btCPUSoftBodySolver::processCollision( btSoftBody*, btSoftBody *)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Add the collision object to the set to deal with for a particular soft body
|
||||
void btCPUSoftBodySolver::processCollision( btSoftBody *softBody, btCollisionObject* collisionObject )
|
||||
{
|
||||
int softBodyIndex = findSoftBodyIndex( softBody );
|
||||
|
||||
if( softBodyIndex >= 0 )
|
||||
{
|
||||
btCollisionShape *collisionShape = collisionObject->getCollisionShape();
|
||||
float friction = collisionObject->getFriction();
|
||||
int shapeType = collisionShape->getShapeType();
|
||||
if( shapeType == CAPSULE_SHAPE_PROXYTYPE )
|
||||
{
|
||||
// Add to the list of expected collision objects
|
||||
btCPUCollisionShapeDescription newCollisionShapeDescription;
|
||||
newCollisionShapeDescription.softBodyIdentifier = softBodyIndex;
|
||||
newCollisionShapeDescription.collisionShapeType = shapeType;
|
||||
newCollisionShapeDescription.shapeTransform = toTransform3(collisionObject->getWorldTransform());
|
||||
btCapsuleShape *capsule = static_cast<btCapsuleShape*>( collisionShape );
|
||||
newCollisionShapeDescription.shapeInformation.capsule.radius = capsule->getRadius();
|
||||
newCollisionShapeDescription.shapeInformation.capsule.halfHeight = capsule->getHalfHeight();
|
||||
newCollisionShapeDescription.shapeInformation.capsule.upAxis = capsule->getUpAxis();
|
||||
newCollisionShapeDescription.margin = capsule->getMargin();
|
||||
newCollisionShapeDescription.friction = friction;
|
||||
btRigidBody* body = static_cast< btRigidBody* >( collisionObject );
|
||||
newCollisionShapeDescription.linearVelocity = toVector3(body->getLinearVelocity());
|
||||
newCollisionShapeDescription.angularVelocity = toVector3(body->getAngularVelocity());
|
||||
m_collisionObjectDetails.push_back( newCollisionShapeDescription );
|
||||
} else {
|
||||
btAssert("Unsupported collision shape type\n");
|
||||
}
|
||||
} else {
|
||||
btAssert("Unknown soft body");
|
||||
}
|
||||
} // btCPUSoftBodySolver::processCollision
|
||||
|
||||
|
||||
void btCPUSoftBodySolver::predictMotion( float timeStep )
|
||||
{
|
||||
// Fill the force arrays with current acceleration data etc
|
||||
m_perClothWindVelocity.resize( m_softBodySet.size() );
|
||||
for( int softBodyIndex = 0; softBodyIndex < m_softBodySet.size(); ++softBodyIndex )
|
||||
{
|
||||
btSoftBody *softBody = m_softBodySet[softBodyIndex]->getSoftBody();
|
||||
|
||||
m_perClothWindVelocity[softBodyIndex] = toVector3(softBody->getWindVelocity());
|
||||
}
|
||||
|
||||
|
||||
// Apply forces that we know about to the cloths
|
||||
applyForces( timeStep * getTimeScale() );
|
||||
|
||||
// Itegrate motion for all soft bodies dealt with by the solver
|
||||
integrate( timeStep * getTimeScale() );
|
||||
|
||||
// Update bounds
|
||||
// Will update the bounds for all softBodies being dealt with by the solver and
|
||||
// set the values in the btSoftBody object
|
||||
updateBounds();
|
||||
|
||||
// End prediction work for solvers
|
||||
}
|
||||
|
||||
|
||||
@@ -1,370 +0,0 @@
|
||||
/*
|
||||
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_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
|
||||
#define BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
|
||||
|
||||
#include "vectormath/vmInclude.h"
|
||||
#include "BulletSoftBody/btSoftBodySolvers.h"
|
||||
#include "BulletSoftBody/btSoftBodySolverVertexBuffer.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
|
||||
struct btCPUCollisionShapeDescription
|
||||
{
|
||||
int softBodyIdentifier;
|
||||
int collisionShapeType;
|
||||
Vectormath::Aos::Transform3 shapeTransform;
|
||||
union
|
||||
{
|
||||
struct Sphere
|
||||
{
|
||||
float radius;
|
||||
} sphere;
|
||||
struct Capsule
|
||||
{
|
||||
float radius;
|
||||
float halfHeight;
|
||||
int upAxis;
|
||||
} capsule;
|
||||
} shapeInformation;
|
||||
|
||||
float margin;
|
||||
float friction;
|
||||
Vectormath::Aos::Vector3 linearVelocity;
|
||||
Vectormath::Aos::Vector3 angularVelocity;
|
||||
|
||||
btCPUCollisionShapeDescription()
|
||||
{
|
||||
collisionShapeType = 0;
|
||||
margin = 0;
|
||||
friction = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class btCPUSoftBodySolver : public btSoftBodySolver
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Entry in the collision shape array.
|
||||
* Specifies the shape type, the transform matrix and the necessary details of the collisionShape.
|
||||
*/
|
||||
|
||||
|
||||
// Public because output classes need it. This is a better encapsulation to break in the short term
|
||||
// Than having the solvers themselves need dependencies on DX, CL etc unnecessarily
|
||||
public:
|
||||
|
||||
struct CollisionObjectIndices
|
||||
{
|
||||
CollisionObjectIndices( int f, int e )
|
||||
{
|
||||
firstObject = f;
|
||||
endObject = e;
|
||||
}
|
||||
|
||||
int firstObject;
|
||||
int endObject;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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() const
|
||||
{
|
||||
return m_numVertices;
|
||||
}
|
||||
|
||||
int getNumTriangles() const
|
||||
{
|
||||
return m_numTriangles;
|
||||
}
|
||||
|
||||
int getMaxVertices() const
|
||||
{
|
||||
return m_maxVertices;
|
||||
}
|
||||
|
||||
int getMaxTriangles() const
|
||||
{
|
||||
return m_maxTriangles;
|
||||
}
|
||||
|
||||
int getFirstVertex() const
|
||||
{
|
||||
return m_firstVertex;
|
||||
}
|
||||
|
||||
int getFirstTriangle() const
|
||||
{
|
||||
return m_firstTriangle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the bounds in the btSoftBody object
|
||||
*/
|
||||
void updateBounds( const btVector3 &lowerBound, const btVector3 &upperBound );
|
||||
|
||||
// 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() const
|
||||
{
|
||||
return m_maxLinks;
|
||||
}
|
||||
|
||||
int getNumLinks() const
|
||||
{
|
||||
return m_numLinks;
|
||||
}
|
||||
|
||||
int getFirstLink() const
|
||||
{
|
||||
return m_firstLink;
|
||||
}
|
||||
|
||||
btSoftBody* getSoftBody()
|
||||
{
|
||||
return m_softBody;
|
||||
}
|
||||
|
||||
const btSoftBody* const getSoftBody() const
|
||||
{
|
||||
return m_softBody;
|
||||
}
|
||||
};
|
||||
|
||||
btSoftBodyLinkData m_linkData;
|
||||
btSoftBodyVertexData m_vertexData;
|
||||
btSoftBodyTriangleData m_triangleData;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
|
||||
/** Variable to define whether we need to update solver constants on the next iteration */
|
||||
bool m_updateSolverConstants;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Velocity damping factor */
|
||||
btAlignedObjectArray< float > m_perClothDampingFactor;
|
||||
|
||||
/** Velocity correction coefficient */
|
||||
btAlignedObjectArray< float > m_perClothVelocityCorrectionCoefficient;
|
||||
|
||||
/** Lift parameter for wind effect on cloth. */
|
||||
btAlignedObjectArray< float > m_perClothLiftFactor;
|
||||
|
||||
/** Drag parameter for wind effect on cloth. */
|
||||
btAlignedObjectArray< float > m_perClothDragFactor;
|
||||
|
||||
/** Density of the medium in which each cloth sits */
|
||||
btAlignedObjectArray< float > m_perClothMediumDensity;
|
||||
|
||||
/**
|
||||
* Collision shape details: pair of index of first collision shape for the cloth and number of collision objects.
|
||||
*/
|
||||
btAlignedObjectArray< CollisionObjectIndices > m_perClothCollisionObjects;
|
||||
|
||||
/**
|
||||
* Collision shapes being passed across to the cloths in this solver.
|
||||
*/
|
||||
btAlignedObjectArray< btCPUCollisionShapeDescription > m_collisionObjectDetails;
|
||||
|
||||
|
||||
void prepareCollisionConstraints();
|
||||
|
||||
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 );
|
||||
|
||||
float computeTriangleArea(
|
||||
const Vectormath::Aos::Point3 &vertex0,
|
||||
const Vectormath::Aos::Point3 &vertex1,
|
||||
const Vectormath::Aos::Point3 &vertex2 );
|
||||
|
||||
void applyForces( float solverdt );
|
||||
void integrate( float solverdt );
|
||||
void updateConstants( float timeStep );
|
||||
int findSoftBodyIndex( const btSoftBody* const softBody );
|
||||
|
||||
/** Update the bounds of the soft body objects in the solver */
|
||||
void updateBounds();
|
||||
|
||||
|
||||
public:
|
||||
btCPUSoftBodySolver();
|
||||
|
||||
virtual ~btCPUSoftBodySolver();
|
||||
|
||||
|
||||
virtual SolverTypes getSolverType() const
|
||||
{
|
||||
return CPU_SOLVER;
|
||||
}
|
||||
|
||||
|
||||
virtual btSoftBodyLinkData &getLinkData();
|
||||
|
||||
virtual btSoftBodyVertexData &getVertexData();
|
||||
|
||||
virtual btSoftBodyTriangleData &getTriangleData();
|
||||
|
||||
|
||||
|
||||
btAcceleratedSoftBodyInterface *findSoftBodyInterface( const btSoftBody* const softBody );
|
||||
const btAcceleratedSoftBodyInterface * const findSoftBodyInterface( const btSoftBody* const softBody ) const;
|
||||
|
||||
|
||||
|
||||
virtual bool checkInitialized();
|
||||
|
||||
virtual void updateSoftBodies( );
|
||||
|
||||
virtual void optimize( btAlignedObjectArray< btSoftBody * > &softBodies , bool forceUpdate=false);
|
||||
|
||||
virtual void copyBackToSoftBodies();
|
||||
|
||||
virtual void solveConstraints( float solverdt );
|
||||
|
||||
virtual void predictMotion( float solverdt );
|
||||
|
||||
virtual void processCollision( btSoftBody *, btCollisionObject* );
|
||||
|
||||
virtual void processCollision( btSoftBody*, btSoftBody *);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class to manage movement of data from a solver to a given target.
|
||||
* This version is the CPU to CPU generic version.
|
||||
*/
|
||||
class btSoftBodySolverOutputCPUtoCPU : public btSoftBodySolverOutput
|
||||
{
|
||||
protected:
|
||||
|
||||
public:
|
||||
btSoftBodySolverOutputCPUtoCPU()
|
||||
{
|
||||
}
|
||||
|
||||
/** Output current computed vertex data to the vertex buffers for all cloths in the solver. */
|
||||
virtual void copySoftBodyToVertexBuffer( const btSoftBody * const softBody, btVertexBufferDescriptor *vertexBuffer );
|
||||
};
|
||||
|
||||
#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
|
||||
@@ -8,7 +8,7 @@ SET(DX11_INCLUDE_PATH "${DIRECTX_SDK_BASE_DIR}/Include" CACHE DOCSTRING "Micros
|
||||
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${DX11_INCLUDE_PATH} "../cpu/"
|
||||
${DX11_INCLUDE_PATH} "../Shared/"
|
||||
${VECTOR_MATH_INCLUDE}
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ SET(BulletSoftBodyDX11Solvers_SRCS
|
||||
SET(BulletSoftBodyDX11Solvers_HDRS
|
||||
btSoftBodySolver_DX11.h
|
||||
btSoftBodySolver_DX11SIMDAware.h
|
||||
../cpu/btSoftBodySolverData.h
|
||||
../Shared/btSoftBodySolverData.h
|
||||
btSoftBodySolverVertexData_DX11.h
|
||||
btSoftBodySolverTriangleData_DX11.h
|
||||
btSoftBodySolverLinkData_DX11.h
|
||||
|
||||
@@ -14,7 +14,7 @@ subject to the following restrictions:
|
||||
*/
|
||||
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_DX11.h"
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_DX11.h"
|
||||
|
||||
#ifndef BT_ACCELERATED_SOFT_BODY_LINK_DATA_DX11_SIMDAWARE_H
|
||||
|
||||
@@ -13,7 +13,7 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_DX11.h"
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ subject to the following restrictions:
|
||||
*/
|
||||
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_DX11.h"
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
|
||||
SET(BulletSoftBodyOpenCLSolvers_HDRS
|
||||
../btSoftBodySolver_OpenCL.h
|
||||
../btSoftBodySolver_OpenCLSIMDAware.h
|
||||
../../CPU/btSoftBodySolverData.h
|
||||
../../Shared/btSoftBodySolverData.h
|
||||
../btSoftBodySolverVertexData_OpenCL.h
|
||||
../btSoftBodySolverTriangleData_OpenCL.h
|
||||
../btSoftBodySolverLinkData_OpenCL.h
|
||||
|
||||
@@ -13,7 +13,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
|
||||
|
||||
SET(BulletSoftBodyOpenCLSolvers_HDRS
|
||||
../btSoftBodySolver_OpenCL.h
|
||||
../../CPU/btSoftBodySolverData.h
|
||||
../../Shared/btSoftBodySolverData.h
|
||||
../btSoftBodySolverVertexData_OpenCL.h
|
||||
../btSoftBodySolverTriangleData_OpenCL.h
|
||||
../btSoftBodySolverLinkData_OpenCL.h
|
||||
|
||||
@@ -18,7 +18,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
|
||||
SET(BulletSoftBodyOpenCLSolvers_HDRS
|
||||
../btSoftBodySolver_OpenCL.h
|
||||
../btSoftBodySolver_OpenCLSIMDAware.h
|
||||
../../CPU/btSoftBodySolverData.h
|
||||
../../Shared/btSoftBodySolverData.h
|
||||
../btSoftBodySolverVertexData_OpenCL.h
|
||||
../btSoftBodySolverTriangleData_OpenCL.h
|
||||
../btSoftBodySolverLinkData_OpenCL.h
|
||||
|
||||
@@ -14,7 +14,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
|
||||
|
||||
SET(BulletSoftBodyOpenCLSolvers_HDRS
|
||||
../btSoftBodySolver_OpenCL.h
|
||||
../../CPU/btSoftBodySolverData.h
|
||||
../../Shared/btSoftBodySolverData.h
|
||||
../btSoftBodySolverVertexData_OpenCL.h
|
||||
../btSoftBodySolverTriangleData_OpenCL.h
|
||||
../btSoftBodySolverLinkData_OpenCL.h
|
||||
|
||||
@@ -24,9 +24,12 @@ subject to the following restrictions:
|
||||
#include "../OpenCLC10/UpdateNormals.cl"
|
||||
#include "../OpenCLC10/UpdatePositions.cl"
|
||||
#include "../OpenCLC10/UpdatePositionsFromVelocities.cl"
|
||||
//#include "../OpenCLC10/VSolveLinks.cl"
|
||||
#include "../OpenCLC10/VSolveLinks.cl"
|
||||
//#include "../OpenCLC10/SolveCollisionsAndUpdateVelocities.cl"
|
||||
|
||||
|
||||
MINICL_REGISTER(PrepareLinksKernel)
|
||||
MINICL_REGISTER(VSolveLinksKernel)
|
||||
MINICL_REGISTER(UpdatePositionsFromVelocitiesKernel)
|
||||
MINICL_REGISTER(SolvePositionsFromLinksKernel)
|
||||
MINICL_REGISTER(updateVelocitiesFromPositionsWithVelocitiesKernel)
|
||||
@@ -38,3 +41,208 @@ MINICL_REGISTER(NormalizeNormalsAndAreasKernel)
|
||||
MINICL_REGISTER(UpdateSoftBodiesKernel)
|
||||
|
||||
|
||||
float mydot3a(float4 a, float4 b)
|
||||
{
|
||||
return a.x*b.x + a.y*b.y + a.z*b.z;
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int firstObject;
|
||||
int endObject;
|
||||
} CollisionObjectIndices;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float4 shapeTransform[4]; // column major 4x4 matrix
|
||||
float4 linearVelocity;
|
||||
float4 angularVelocity;
|
||||
|
||||
int softBodyIdentifier;
|
||||
int collisionShapeType;
|
||||
|
||||
|
||||
// Shape information
|
||||
// Compressed from the union
|
||||
float radius;
|
||||
float halfHeight;
|
||||
int upAxis;
|
||||
|
||||
float margin;
|
||||
float friction;
|
||||
|
||||
int padding0;
|
||||
|
||||
} CollisionShapeDescription;
|
||||
|
||||
// From btBroadphaseProxy.h
|
||||
__constant int CAPSULE_SHAPE_PROXYTYPE = 10;
|
||||
|
||||
// Multiply column-major matrix against vector
|
||||
float4 matrixVectorMul( float4 matrix[4], float4 vector )
|
||||
{
|
||||
float4 returnVector;
|
||||
float4 row0 = float4(matrix[0].x, matrix[1].x, matrix[2].x, matrix[3].x);
|
||||
float4 row1 = float4(matrix[0].y, matrix[1].y, matrix[2].y, matrix[3].y);
|
||||
float4 row2 = float4(matrix[0].z, matrix[1].z, matrix[2].z, matrix[3].z);
|
||||
float4 row3 = float4(matrix[0].w, matrix[1].w, matrix[2].w, matrix[3].w);
|
||||
returnVector.x = dot(row0, vector);
|
||||
returnVector.y = dot(row1, vector);
|
||||
returnVector.z = dot(row2, vector);
|
||||
returnVector.w = dot(row3, vector);
|
||||
return returnVector;
|
||||
}
|
||||
|
||||
__kernel void
|
||||
SolveCollisionsAndUpdateVelocitiesKernel(
|
||||
const int numNodes,
|
||||
const float isolverdt,
|
||||
__global int *g_vertexClothIdentifier,
|
||||
__global float4 *g_vertexPreviousPositions,
|
||||
__global float * g_perClothFriction,
|
||||
__global float * g_clothDampingFactor,
|
||||
__global CollisionObjectIndices * g_perClothCollisionObjectIndices,
|
||||
__global CollisionShapeDescription * g_collisionObjectDetails,
|
||||
__global float4 * g_vertexForces,
|
||||
__global float4 *g_vertexVelocities,
|
||||
__global float4 *g_vertexPositions GUID_ARG)
|
||||
{
|
||||
int nodeID = get_global_id(0);
|
||||
float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
if( get_global_id(0) < numNodes )
|
||||
{
|
||||
int clothIdentifier = g_vertexClothIdentifier[nodeID];
|
||||
|
||||
// Abort if this is not a valid cloth
|
||||
if( clothIdentifier < 0 )
|
||||
return;
|
||||
|
||||
|
||||
float4 position (g_vertexPositions[nodeID].xyz, 1.f);
|
||||
float4 previousPosition (g_vertexPreviousPositions[nodeID].xyz, 1.f);
|
||||
|
||||
float clothFriction = g_perClothFriction[clothIdentifier];
|
||||
float dampingFactor = g_clothDampingFactor[clothIdentifier];
|
||||
float velocityCoefficient = (1.f - dampingFactor);
|
||||
float4 difference = position - previousPosition;
|
||||
float4 velocity = difference*velocityCoefficient*isolverdt;
|
||||
|
||||
CollisionObjectIndices collisionObjectIndices = g_perClothCollisionObjectIndices[clothIdentifier];
|
||||
|
||||
int numObjects = collisionObjectIndices.endObject - collisionObjectIndices.firstObject;
|
||||
|
||||
if( numObjects > 0 )
|
||||
{
|
||||
// We have some possible collisions to deal with
|
||||
for( int collision = collisionObjectIndices.firstObject; collision < collisionObjectIndices.endObject; ++collision )
|
||||
{
|
||||
CollisionShapeDescription shapeDescription = g_collisionObjectDetails[collision];
|
||||
float colliderFriction = shapeDescription.friction;
|
||||
|
||||
if( shapeDescription.collisionShapeType == CAPSULE_SHAPE_PROXYTYPE )
|
||||
{
|
||||
// Colliding with a capsule
|
||||
|
||||
float capsuleHalfHeight = shapeDescription.halfHeight;
|
||||
float capsuleRadius = shapeDescription.radius;
|
||||
float capsuleMargin = shapeDescription.margin;
|
||||
int capsuleupAxis = shapeDescription.upAxis;
|
||||
|
||||
// Four columns of worldTransform matrix
|
||||
float4 worldTransform[4];
|
||||
worldTransform[0] = shapeDescription.shapeTransform[0];
|
||||
worldTransform[1] = shapeDescription.shapeTransform[1];
|
||||
worldTransform[2] = shapeDescription.shapeTransform[2];
|
||||
worldTransform[3] = shapeDescription.shapeTransform[3];
|
||||
|
||||
// Correctly define capsule centerline vector
|
||||
float4 c1 (0.f, 0.f, 0.f, 1.f);
|
||||
float4 c2 (0.f, 0.f, 0.f, 1.f);
|
||||
c1.x = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 0 );
|
||||
c1.y = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 1 );
|
||||
c1.z = select( 0.f, -capsuleHalfHeight, capsuleupAxis == 2 );
|
||||
c2.x = -c1.x;
|
||||
c2.y = -c1.y;
|
||||
c2.z = -c1.z;
|
||||
|
||||
|
||||
float4 worldC1 = matrixVectorMul(worldTransform, c1);
|
||||
float4 worldC2 = matrixVectorMul(worldTransform, c2);
|
||||
float4 segment = (worldC2 - worldC1);
|
||||
|
||||
// compute distance of tangent to vertex along line segment in capsule
|
||||
float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) );
|
||||
|
||||
float4 closestPoint = (worldC1 + (segment * distanceAlongSegment));
|
||||
float distanceFromLine = length(position - closestPoint);
|
||||
float distanceFromC1 = length(worldC1 - position);
|
||||
float distanceFromC2 = length(worldC2 - position);
|
||||
|
||||
// Final distance from collision, point to push from, direction to push in
|
||||
// for impulse force
|
||||
float dist;
|
||||
float4 normalVector;
|
||||
if( distanceAlongSegment < 0 )
|
||||
{
|
||||
dist = distanceFromC1;
|
||||
normalVector = float4(normalize(position - worldC1).xyz, 0.f);
|
||||
} else if( distanceAlongSegment > 1.f ) {
|
||||
dist = distanceFromC2;
|
||||
normalVector = float4(normalize(position - worldC2).xyz, 0.f);
|
||||
} else {
|
||||
dist = distanceFromLine;
|
||||
normalVector = float4(normalize(position - closestPoint).xyz, 0.f);
|
||||
}
|
||||
|
||||
float4 colliderLinearVelocity = shapeDescription.linearVelocity;
|
||||
float4 colliderAngularVelocity = shapeDescription.angularVelocity;
|
||||
float4 velocityOfSurfacePoint = colliderLinearVelocity + cross(colliderAngularVelocity, position - float4(worldTransform[0].w, worldTransform[1].w, worldTransform[2].w, 0.f));
|
||||
|
||||
float minDistance = capsuleRadius + capsuleMargin;
|
||||
|
||||
// In case of no collision, this is the value of velocity
|
||||
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
|
||||
|
||||
|
||||
// Check for a collision
|
||||
if( dist < minDistance )
|
||||
{
|
||||
// Project back to surface along normal
|
||||
position = position + float4(normalVector*(minDistance - dist)*0.9f);
|
||||
velocity = (position - previousPosition) * velocityCoefficient * isolverdt;
|
||||
float4 relativeVelocity = velocity - velocityOfSurfacePoint;
|
||||
|
||||
float4 p1 = normalize(cross(normalVector, segment));
|
||||
float4 p2 = normalize(cross(p1, normalVector));
|
||||
// Full friction is sum of velocities in each direction of plane
|
||||
float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2);
|
||||
|
||||
// Real friction is peak friction corrected by friction coefficients
|
||||
frictionVector = frictionVector * (colliderFriction*clothFriction);
|
||||
|
||||
float approachSpeed = dot(relativeVelocity, normalVector);
|
||||
|
||||
if( approachSpeed <= 0.0f )
|
||||
forceOnVertex -= frictionVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_vertexVelocities[nodeID] = float4(velocity.xyz, 0.f);
|
||||
|
||||
// Update external force
|
||||
g_vertexForces[nodeID] = float4(forceOnVertex.xyz, 0.f);
|
||||
|
||||
g_vertexPositions[nodeID] = float4(position.xyz, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MINICL_REGISTER(SolveCollisionsAndUpdateVelocitiesKernel);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ SET(BulletSoftBodyOpenCLSolvers_SRCS
|
||||
|
||||
SET(BulletSoftBodyOpenCLSolvers_HDRS
|
||||
../btSoftBodySolver_OpenCL.h
|
||||
../../CPU/btSoftBodySolverData.h
|
||||
../../Shared/btSoftBodySolverData.h
|
||||
../btSoftBodySolverVertexData_OpenCL.h
|
||||
../btSoftBodySolverTriangleData_OpenCL.h
|
||||
../btSoftBodySolverLinkData_OpenCL.h
|
||||
|
||||
@@ -78,8 +78,8 @@ ApplyForcesKernel(
|
||||
float4 nodeFMinus = nodeF - (projectOnAxis(nodeV, normalize(force))/dtim);
|
||||
|
||||
nodeF = nodeFPlusForce;
|
||||
if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) )
|
||||
nodeF = nodeFMinus;
|
||||
//if( dot(forceDTIM, forceDTIM) > dot(nodeV, nodeV) )
|
||||
// nodeF = nodeFMinus;
|
||||
|
||||
g_vertexForceAccumulator[nodeID] = nodeF;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
MSTRINGIFY(
|
||||
|
||||
#pragma OPENCL EXTENSION cl_amd_printf : enable\n
|
||||
|
||||
float mydot3(float4 a, float4 b)
|
||||
|
||||
float mydot3a(float4 a, float4 b)
|
||||
{
|
||||
return a.x*b.x + a.y*b.y + a.z*b.z;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ SolveCollisionsAndUpdateVelocitiesKernel(
|
||||
__global CollisionShapeDescription * g_collisionObjectDetails,
|
||||
__global float4 * g_vertexForces,
|
||||
__global float4 *g_vertexVelocities,
|
||||
__global float4 *g_vertexPositions)
|
||||
__global float4 *g_vertexPositions GUID_ARG)
|
||||
{
|
||||
int nodeID = get_global_id(0);
|
||||
float4 forceOnVertex = (float4)(0.f, 0.f, 0.f, 0.f);
|
||||
@@ -134,7 +134,7 @@ SolveCollisionsAndUpdateVelocitiesKernel(
|
||||
float4 segment = (worldC2 - worldC1);
|
||||
|
||||
// compute distance of tangent to vertex along line segment in capsule
|
||||
float distanceAlongSegment = -( mydot3( (worldC1 - position), segment ) / mydot3(segment, segment) );
|
||||
float distanceAlongSegment = -( mydot3a( (worldC1 - position), segment ) / mydot3a(segment, segment) );
|
||||
|
||||
float4 closestPoint = (worldC1 + (float4)(segment * distanceAlongSegment));
|
||||
float distanceFromLine = length(position - closestPoint);
|
||||
@@ -178,7 +178,7 @@ SolveCollisionsAndUpdateVelocitiesKernel(
|
||||
float4 p1 = normalize(cross(normalVector, segment));
|
||||
float4 p2 = normalize(cross(p1, normalVector));
|
||||
// Full friction is sum of velocities in each direction of plane
|
||||
float4 frictionVector = p1*mydot3(relativeVelocity, p1) + p2*mydot3(relativeVelocity, p2);
|
||||
float4 frictionVector = p1*mydot3a(relativeVelocity, p1) + p2*mydot3a(relativeVelocity, p2);
|
||||
|
||||
// Real friction is peak friction corrected by friction coefficients
|
||||
frictionVector = frictionVector * (colliderFriction*clothFriction);
|
||||
|
||||
@@ -13,7 +13,7 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_OpenCL.h"
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_OpenCL.h"
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ subject to the following restrictions:
|
||||
*/
|
||||
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_OpenCL.h"
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/CPU/btSoftBodySolverData.h"
|
||||
#include "BulletMultiThreaded/GpuSoftBodySolvers/Shared/btSoftBodySolverData.h"
|
||||
#include "btSoftBodySolverBuffer_OpenCL.h"
|
||||
|
||||
#ifndef BT_SOFT_BODY_SOLVER_VERTEX_DATA_OPENCL_H
|
||||
|
||||
@@ -1642,10 +1642,11 @@ void btOpenCLSoftBodySolver::processCollision( btSoftBody *softBody, btCollision
|
||||
m_collisionObjectDetails.push_back( newCollisionShapeDescription );
|
||||
|
||||
} else {
|
||||
btAssert(0 && "Unsupported collision shape type\n");
|
||||
printf("Unsupported collision shape type\n");
|
||||
//btAssert(0 && "Unsupported collision shape type\n");
|
||||
}
|
||||
} else {
|
||||
btAssert("Unknown soft body");
|
||||
btAssert(0,"Unknown soft body");
|
||||
}
|
||||
} // btOpenCLSoftBodySolver::processCollision
|
||||
|
||||
|
||||
Reference in New Issue
Block a user