2017-08-01 14:30:58 +02:00
/*
Bullet Continuous Collision Detection and Physics Library
2022-01-06 23:37:49 +01:00
Copyright ( c ) 2003 - 2006 Erwin Coumans https : //bulletphysics.org
2017-08-01 14:30:58 +02:00
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 .
*/
///btSoftBody implementation by Nathanael Presson
# include "btSoftBodyInternals.h"
# include "BulletSoftBody/btSoftBodySolvers.h"
# include "btSoftBodyData.h"
# include "LinearMath/btSerializer.h"
2021-09-29 15:47:08 +02:00
# include "LinearMath/btImplicitQRSVD.h"
2020-01-08 18:05:43 +01:00
# include "LinearMath/btAlignedAllocator.h"
2017-08-01 14:30:58 +02:00
# include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
# include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
2020-01-08 18:05:43 +01:00
# include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
# include "BulletCollision/CollisionShapes/btTriangleShape.h"
# include <iostream>
2021-09-29 15:47:08 +02:00
//
static inline btDbvtNode * buildTreeBottomUp ( btAlignedObjectArray < btDbvtNode * > & leafNodes , btAlignedObjectArray < btAlignedObjectArray < int > > & adj )
{
int N = leafNodes . size ( ) ;
if ( N = = 0 )
{
return NULL ;
}
while ( N > 1 )
{
btAlignedObjectArray < bool > marked ;
btAlignedObjectArray < btDbvtNode * > newLeafNodes ;
btAlignedObjectArray < std : : pair < int , int > > childIds ;
btAlignedObjectArray < btAlignedObjectArray < int > > newAdj ;
marked . resize ( N ) ;
for ( int i = 0 ; i < N ; + + i )
marked [ i ] = false ;
// pair adjacent nodes into new(parent) node
for ( int i = 0 ; i < N ; + + i )
{
if ( marked [ i ] )
continue ;
bool merged = false ;
for ( int j = 0 ; j < adj [ i ] . size ( ) ; + + j )
{
int n = adj [ i ] [ j ] ;
if ( ! marked [ adj [ i ] [ j ] ] )
{
btDbvtNode * node = new ( btAlignedAlloc ( sizeof ( btDbvtNode ) , 16 ) ) btDbvtNode ( ) ;
node - > parent = NULL ;
node - > childs [ 0 ] = leafNodes [ i ] ;
node - > childs [ 1 ] = leafNodes [ n ] ;
leafNodes [ i ] - > parent = node ;
leafNodes [ n ] - > parent = node ;
newLeafNodes . push_back ( node ) ;
childIds . push_back ( std : : make_pair ( i , n ) ) ;
merged = true ;
marked [ n ] = true ;
break ;
}
}
if ( ! merged )
{
newLeafNodes . push_back ( leafNodes [ i ] ) ;
childIds . push_back ( std : : make_pair ( i , - 1 ) ) ;
}
marked [ i ] = true ;
}
// update adjacency matrix
newAdj . resize ( newLeafNodes . size ( ) ) ;
for ( int i = 0 ; i < newLeafNodes . size ( ) ; + + i )
{
for ( int j = i + 1 ; j < newLeafNodes . size ( ) ; + + j )
{
bool neighbor = false ;
const btAlignedObjectArray < int > & leftChildNeighbors = adj [ childIds [ i ] . first ] ;
for ( int k = 0 ; k < leftChildNeighbors . size ( ) ; + + k )
{
if ( leftChildNeighbors [ k ] = = childIds [ j ] . first | | leftChildNeighbors [ k ] = = childIds [ j ] . second )
{
neighbor = true ;
break ;
}
}
if ( ! neighbor & & childIds [ i ] . second ! = - 1 )
{
const btAlignedObjectArray < int > & rightChildNeighbors = adj [ childIds [ i ] . second ] ;
for ( int k = 0 ; k < rightChildNeighbors . size ( ) ; + + k )
{
if ( rightChildNeighbors [ k ] = = childIds [ j ] . first | | rightChildNeighbors [ k ] = = childIds [ j ] . second )
{
neighbor = true ;
break ;
}
}
}
if ( neighbor )
{
newAdj [ i ] . push_back ( j ) ;
newAdj [ j ] . push_back ( i ) ;
}
}
}
leafNodes = newLeafNodes ;
//this assignment leaks memory, the assignment doesn't do a deep copy, for now a manual copy
//adj = newAdj;
adj . clear ( ) ;
adj . resize ( newAdj . size ( ) ) ;
for ( int i = 0 ; i < newAdj . size ( ) ; i + + )
{
for ( int j = 0 ; j < newAdj [ i ] . size ( ) ; j + + )
{
adj [ i ] . push_back ( newAdj [ i ] [ j ] ) ;
}
}
N = leafNodes . size ( ) ;
}
return leafNodes [ 0 ] ;
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
btSoftBody : : btSoftBody ( btSoftBodyWorldInfo * worldInfo , int node_count , const btVector3 * x , const btScalar * m )
: m_softBodySolver ( 0 ) , m_worldInfo ( worldInfo )
{
/* Init */
2017-08-01 14:30:58 +02:00
initDefaults ( ) ;
2019-01-03 14:26:51 +01:00
/* Default material */
Material * pm = appendMaterial ( ) ;
pm - > m_kLST = 1 ;
pm - > m_kAST = 1 ;
pm - > m_kVST = 1 ;
pm - > m_flags = fMaterial : : Default ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
/* Nodes */
const btScalar margin = getCollisionShape ( ) - > getMargin ( ) ;
2017-08-01 14:30:58 +02:00
m_nodes . resize ( node_count ) ;
2021-09-29 15:47:08 +02:00
m_X . resize ( node_count ) ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = node_count ; i < ni ; + + i )
{
Node & n = m_nodes [ i ] ;
2017-08-01 14:30:58 +02:00
ZeroInitialize ( n ) ;
2019-01-03 14:26:51 +01:00
n . m_x = x ? * x + + : btVector3 ( 0 , 0 , 0 ) ;
n . m_q = n . m_x ;
n . m_im = m ? * m + + : 1 ;
n . m_im = n . m_im > 0 ? 1 / n . m_im : 0 ;
n . m_leaf = m_ndbvt . insert ( btDbvtVolume : : FromCR ( n . m_x , margin ) , & n ) ;
n . m_material = pm ;
2021-09-29 15:47:08 +02:00
m_X [ i ] = n . m_x ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
updateBounds ( ) ;
2021-09-29 15:47:08 +02:00
setCollisionQuadrature ( 3 ) ;
m_fdbvnt = 0 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
btSoftBody : : btSoftBody ( btSoftBodyWorldInfo * worldInfo )
: m_worldInfo ( worldInfo )
2017-08-01 14:30:58 +02:00
{
initDefaults ( ) ;
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : initDefaults ( )
{
m_internalType = CO_SOFT_BODY ;
m_cfg . aeromodel = eAeroModel : : V_Point ;
m_cfg . kVCF = 1 ;
m_cfg . kDG = 0 ;
m_cfg . kLF = 0 ;
m_cfg . kDP = 0 ;
m_cfg . kPR = 0 ;
m_cfg . kVC = 0 ;
m_cfg . kDF = ( btScalar ) 0.2 ;
m_cfg . kMT = 0 ;
m_cfg . kCHR = ( btScalar ) 1.0 ;
m_cfg . kKHR = ( btScalar ) 0.1 ;
m_cfg . kSHR = ( btScalar ) 1.0 ;
m_cfg . kAHR = ( btScalar ) 0.7 ;
m_cfg . kSRHR_CL = ( btScalar ) 0.1 ;
m_cfg . kSKHR_CL = ( btScalar ) 1 ;
m_cfg . kSSHR_CL = ( btScalar ) 0.5 ;
m_cfg . kSR_SPLT_CL = ( btScalar ) 0.5 ;
m_cfg . kSK_SPLT_CL = ( btScalar ) 0.5 ;
m_cfg . kSS_SPLT_CL = ( btScalar ) 0.5 ;
m_cfg . maxvolume = ( btScalar ) 1 ;
m_cfg . timescale = 1 ;
m_cfg . viterations = 0 ;
m_cfg . piterations = 1 ;
m_cfg . diterations = 0 ;
m_cfg . citerations = 4 ;
2021-09-29 15:47:08 +02:00
m_cfg . drag = 0 ;
m_cfg . m_maxStress = 0 ;
2019-01-03 14:26:51 +01:00
m_cfg . collisions = fCollision : : Default ;
m_pose . m_bvolume = false ;
m_pose . m_bframe = false ;
m_pose . m_volume = 0 ;
m_pose . m_com = btVector3 ( 0 , 0 , 0 ) ;
2017-08-01 14:30:58 +02:00
m_pose . m_rot . setIdentity ( ) ;
m_pose . m_scl . setIdentity ( ) ;
2019-01-03 14:26:51 +01:00
m_tag = 0 ;
m_timeacc = 0 ;
m_bUpdateRtCst = true ;
m_bounds [ 0 ] = btVector3 ( 0 , 0 , 0 ) ;
m_bounds [ 1 ] = btVector3 ( 0 , 0 , 0 ) ;
2017-08-01 14:30:58 +02:00
m_worldTransform . setIdentity ( ) ;
setSolver ( eSolverPresets : : Positions ) ;
2019-01-03 14:26:51 +01:00
/* Collision shape */
2017-08-01 14:30:58 +02:00
///for now, create a collision shape internally
m_collisionShape = new btSoftBodyCollisionShape ( this ) ;
m_collisionShape - > setMargin ( 0.25f ) ;
2019-01-03 14:26:51 +01:00
2021-09-29 15:47:08 +02:00
m_worldTransform . setIdentity ( ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
m_windVelocity = btVector3 ( 0 , 0 , 0 ) ;
2017-08-01 14:30:58 +02:00
m_restLengthScale = btScalar ( 1.0 ) ;
2021-09-29 15:47:08 +02:00
m_dampingCoefficient = 1.0 ;
m_sleepingThreshold = .04 ;
2020-01-08 18:05:43 +01:00
m_useSelfCollision = false ;
2021-09-29 15:47:08 +02:00
m_collisionFlags = 0 ;
m_softSoftCollision = false ;
m_maxSpeedSquared = 0 ;
m_repulsionStiffness = 0.5 ;
m_gravityFactor = 1 ;
m_cacheBarycenter = false ;
m_fdbvnt = 0 ;
2022-05-17 00:02:51 +02:00
// reduced flag
m_reducedModel = false ;
2017-08-01 14:30:58 +02:00
}
//
btSoftBody : : ~ btSoftBody ( )
{
//for now, delete the internal shape
2019-01-03 14:26:51 +01:00
delete m_collisionShape ;
2017-08-01 14:30:58 +02:00
int i ;
releaseClusters ( ) ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_materials . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
btAlignedFree ( m_materials [ i ] ) ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_joints . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
btAlignedFree ( m_joints [ i ] ) ;
2021-09-29 15:47:08 +02:00
if ( m_fdbvnt )
delete m_fdbvnt ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
bool btSoftBody : : checkLink ( int node0 , int node1 ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
return ( checkLink ( & m_nodes [ node0 ] , & m_nodes [ node1 ] ) ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
bool btSoftBody : : checkLink ( const Node * node0 , const Node * node1 ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Node * n [ ] = { node0 , node1 } ;
for ( int i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Link & l = m_links [ i ] ;
if ( ( l . m_n [ 0 ] = = n [ 0 ] & & l . m_n [ 1 ] = = n [ 1 ] ) | |
( l . m_n [ 0 ] = = n [ 1 ] & & l . m_n [ 1 ] = = n [ 0 ] ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
return ( true ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
return ( false ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
bool btSoftBody : : checkFace ( int node0 , int node1 , int node2 ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Node * n [ ] = { & m_nodes [ node0 ] ,
& m_nodes [ node1 ] ,
& m_nodes [ node2 ] } ;
for ( int i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Face & f = m_faces [ i ] ;
int c = 0 ;
for ( int j = 0 ; j < 3 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( ( f . m_n [ j ] = = n [ 0 ] ) | |
( f . m_n [ j ] = = n [ 1 ] ) | |
( f . m_n [ j ] = = n [ 2 ] ) )
c | = 1 < < j ;
else
break ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
if ( c = = 7 ) return ( true ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
return ( false ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
btSoftBody : : Material * btSoftBody : : appendMaterial ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Material * pm = new ( btAlignedAlloc ( sizeof ( Material ) , 16 ) ) Material ( ) ;
if ( m_materials . size ( ) > 0 )
* pm = * m_materials [ 0 ] ;
2017-08-01 14:30:58 +02:00
else
ZeroInitialize ( * pm ) ;
m_materials . push_back ( pm ) ;
2019-01-03 14:26:51 +01:00
return ( pm ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendNote ( const char * text ,
const btVector3 & o ,
const btVector4 & c ,
Node * n0 ,
Node * n1 ,
Node * n2 ,
Node * n3 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Note n ;
2017-08-01 14:30:58 +02:00
ZeroInitialize ( n ) ;
2019-01-03 14:26:51 +01:00
n . m_rank = 0 ;
n . m_text = text ;
n . m_offset = o ;
n . m_coords [ 0 ] = c . x ( ) ;
n . m_coords [ 1 ] = c . y ( ) ;
n . m_coords [ 2 ] = c . z ( ) ;
n . m_coords [ 3 ] = c . w ( ) ;
n . m_nodes [ 0 ] = n0 ;
n . m_rank + = n0 ? 1 : 0 ;
n . m_nodes [ 1 ] = n1 ;
n . m_rank + = n1 ? 1 : 0 ;
n . m_nodes [ 2 ] = n2 ;
n . m_rank + = n2 ? 1 : 0 ;
n . m_nodes [ 3 ] = n3 ;
n . m_rank + = n3 ? 1 : 0 ;
2017-08-01 14:30:58 +02:00
m_notes . push_back ( n ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendNote ( const char * text ,
const btVector3 & o ,
Node * feature )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendNote ( text , o , btVector4 ( 1 , 0 , 0 , 0 ) , feature ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendNote ( const char * text ,
const btVector3 & o ,
Link * feature )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
static const btScalar w = 1 / ( btScalar ) 2 ;
appendNote ( text , o , btVector4 ( w , w , 0 , 0 ) , feature - > m_n [ 0 ] ,
feature - > m_n [ 1 ] ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendNote ( const char * text ,
const btVector3 & o ,
Face * feature )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
static const btScalar w = 1 / ( btScalar ) 3 ;
appendNote ( text , o , btVector4 ( w , w , w , 0 ) , feature - > m_n [ 0 ] ,
feature - > m_n [ 1 ] ,
feature - > m_n [ 2 ] ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendNode ( const btVector3 & x , btScalar m )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_nodes . capacity ( ) = = m_nodes . size ( ) )
2017-08-01 14:30:58 +02:00
{
pointersToIndices ( ) ;
2019-01-03 14:26:51 +01:00
m_nodes . reserve ( m_nodes . size ( ) * 2 + 1 ) ;
2017-08-01 14:30:58 +02:00
indicesToPointers ( ) ;
}
2019-01-03 14:26:51 +01:00
const btScalar margin = getCollisionShape ( ) - > getMargin ( ) ;
2017-08-01 14:30:58 +02:00
m_nodes . push_back ( Node ( ) ) ;
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ m_nodes . size ( ) - 1 ] ;
2017-08-01 14:30:58 +02:00
ZeroInitialize ( n ) ;
2019-01-03 14:26:51 +01:00
n . m_x = x ;
n . m_q = n . m_x ;
n . m_im = m > 0 ? 1 / m : 0 ;
n . m_material = m_materials [ 0 ] ;
n . m_leaf = m_ndbvt . insert ( btDbvtVolume : : FromCR ( n . m_x , margin ) , & n ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendLink ( int model , Material * mat )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link l ;
if ( model > = 0 )
l = m_links [ model ] ;
2017-08-01 14:30:58 +02:00
else
2019-01-03 14:26:51 +01:00
{
ZeroInitialize ( l ) ;
l . m_material = mat ? mat : m_materials [ 0 ] ;
}
2017-08-01 14:30:58 +02:00
m_links . push_back ( l ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendLink ( int node0 ,
int node1 ,
Material * mat ,
bool bcheckexist )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendLink ( & m_nodes [ node0 ] , & m_nodes [ node1 ] , mat , bcheckexist ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendLink ( Node * node0 ,
Node * node1 ,
Material * mat ,
bool bcheckexist )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( ( ! bcheckexist ) | | ( ! checkLink ( node0 , node1 ) ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendLink ( - 1 , mat ) ;
Link & l = m_links [ m_links . size ( ) - 1 ] ;
l . m_n [ 0 ] = node0 ;
l . m_n [ 1 ] = node1 ;
l . m_rl = ( l . m_n [ 0 ] - > m_x - l . m_n [ 1 ] - > m_x ) . length ( ) ;
m_bUpdateRtCst = true ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendFace ( int model , Material * mat )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Face f ;
if ( model > = 0 )
{
f = m_faces [ model ] ;
}
2017-08-01 14:30:58 +02:00
else
2019-01-03 14:26:51 +01:00
{
ZeroInitialize ( f ) ;
f . m_material = mat ? mat : m_materials [ 0 ] ;
}
2021-09-29 15:47:08 +02:00
m_faces . push_back ( f ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendFace ( int node0 , int node1 , int node2 , Material * mat )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( node0 = = node1 )
2017-08-01 14:30:58 +02:00
return ;
2019-01-03 14:26:51 +01:00
if ( node1 = = node2 )
2017-08-01 14:30:58 +02:00
return ;
2019-01-03 14:26:51 +01:00
if ( node2 = = node0 )
2017-08-01 14:30:58 +02:00
return ;
2019-01-03 14:26:51 +01:00
appendFace ( - 1 , mat ) ;
Face & f = m_faces [ m_faces . size ( ) - 1 ] ;
btAssert ( node0 ! = node1 ) ;
btAssert ( node1 ! = node2 ) ;
btAssert ( node2 ! = node0 ) ;
f . m_n [ 0 ] = & m_nodes [ node0 ] ;
f . m_n [ 1 ] = & m_nodes [ node1 ] ;
f . m_n [ 2 ] = & m_nodes [ node2 ] ;
f . m_ra = AreaOf ( f . m_n [ 0 ] - > m_x ,
f . m_n [ 1 ] - > m_x ,
f . m_n [ 2 ] - > m_x ) ;
m_bUpdateRtCst = true ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendTetra ( int model , Material * mat )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Tetra t ;
if ( model > = 0 )
t = m_tetras [ model ] ;
2017-08-01 14:30:58 +02:00
else
2019-01-03 14:26:51 +01:00
{
ZeroInitialize ( t ) ;
t . m_material = mat ? mat : m_materials [ 0 ] ;
}
m_tetras . push_back ( t ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendTetra ( int node0 ,
int node1 ,
int node2 ,
int node3 ,
Material * mat )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendTetra ( - 1 , mat ) ;
Tetra & t = m_tetras [ m_tetras . size ( ) - 1 ] ;
t . m_n [ 0 ] = & m_nodes [ node0 ] ;
t . m_n [ 1 ] = & m_nodes [ node1 ] ;
t . m_n [ 2 ] = & m_nodes [ node2 ] ;
t . m_n [ 3 ] = & m_nodes [ node3 ] ;
t . m_rv = VolumeOf ( t . m_n [ 0 ] - > m_x , t . m_n [ 1 ] - > m_x , t . m_n [ 2 ] - > m_x , t . m_n [ 3 ] - > m_x ) ;
m_bUpdateRtCst = true ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendAnchor ( int node , btRigidBody * body , bool disableCollisionBetweenLinkedBodies , btScalar influence )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btVector3 local = body - > getWorldTransform ( ) . inverse ( ) * m_nodes [ node ] . m_x ;
appendAnchor ( node , body , local , disableCollisionBetweenLinkedBodies , influence ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendAnchor ( int node , btRigidBody * body , const btVector3 & localPivot , bool disableCollisionBetweenLinkedBodies , btScalar influence )
2017-08-01 14:30:58 +02:00
{
if ( disableCollisionBetweenLinkedBodies )
{
2019-01-03 14:26:51 +01:00
if ( m_collisionDisabledObjects . findLinearSearch ( body ) = = m_collisionDisabledObjects . size ( ) )
2017-08-01 14:30:58 +02:00
{
m_collisionDisabledObjects . push_back ( body ) ;
}
}
2019-01-03 14:26:51 +01:00
Anchor a ;
a . m_node = & m_nodes [ node ] ;
a . m_body = body ;
a . m_local = localPivot ;
a . m_node - > m_battach = 1 ;
2017-08-01 14:30:58 +02:00
a . m_influence = influence ;
m_anchors . push_back ( a ) ;
}
2020-01-08 18:05:43 +01:00
//
void btSoftBody : : appendDeformableAnchor ( int node , btRigidBody * body )
{
2021-09-29 15:47:08 +02:00
DeformableNodeRigidAnchor c ;
btSoftBody : : Node & n = m_nodes [ node ] ;
const btScalar ima = n . m_im ;
const btScalar imb = body - > getInvMass ( ) ;
btVector3 nrm ;
const btCollisionShape * shp = body - > getCollisionShape ( ) ;
const btTransform & wtr = body - > getWorldTransform ( ) ;
btScalar dst =
m_worldInfo - > m_sparsesdf . Evaluate (
wtr . invXform ( m_nodes [ node ] . m_x ) ,
shp ,
nrm ,
0 ) ;
c . m_cti . m_colObj = body ;
c . m_cti . m_normal = wtr . getBasis ( ) * nrm ;
c . m_cti . m_offset = dst ;
c . m_node = & m_nodes [ node ] ;
const btScalar fc = m_cfg . kDF * body - > getFriction ( ) ;
c . m_c2 = ima ;
c . m_c3 = fc ;
c . m_c4 = body - > isStaticOrKinematicObject ( ) ? m_cfg . kKHR : m_cfg . kCHR ;
static const btMatrix3x3 iwiStatic ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
const btMatrix3x3 & iwi = body - > getInvInertiaTensorWorld ( ) ;
const btVector3 ra = n . m_x - wtr . getOrigin ( ) ;
c . m_c0 = ImpulseMatrix ( 1 , ima , imb , iwi , ra ) ;
c . m_c1 = ra ;
c . m_local = body - > getWorldTransform ( ) . inverse ( ) * m_nodes [ node ] . m_x ;
c . m_node - > m_battach = 1 ;
m_deformableAnchors . push_back ( c ) ;
}
void btSoftBody : : removeAnchor ( int node )
{
const btSoftBody : : Node & n = m_nodes [ node ] ;
for ( int i = 0 ; i < m_deformableAnchors . size ( ) ; )
{
const DeformableNodeRigidAnchor & c = m_deformableAnchors [ i ] ;
if ( c . m_node = = & n )
{
m_deformableAnchors . removeAtIndex ( i ) ;
}
else
{
i + + ;
}
}
2020-01-08 18:05:43 +01:00
}
//
void btSoftBody : : appendDeformableAnchor ( int node , btMultiBodyLinkCollider * link )
{
2021-09-29 15:47:08 +02:00
DeformableNodeRigidAnchor c ;
btSoftBody : : Node & n = m_nodes [ node ] ;
const btScalar ima = n . m_im ;
btVector3 nrm ;
const btCollisionShape * shp = link - > getCollisionShape ( ) ;
const btTransform & wtr = link - > getWorldTransform ( ) ;
btScalar dst =
m_worldInfo - > m_sparsesdf . Evaluate (
wtr . invXform ( m_nodes [ node ] . m_x ) ,
shp ,
nrm ,
0 ) ;
c . m_cti . m_colObj = link ;
c . m_cti . m_normal = wtr . getBasis ( ) * nrm ;
c . m_cti . m_offset = dst ;
c . m_node = & m_nodes [ node ] ;
const btScalar fc = m_cfg . kDF * link - > getFriction ( ) ;
c . m_c2 = ima ;
c . m_c3 = fc ;
c . m_c4 = link - > isStaticOrKinematicObject ( ) ? m_cfg . kKHR : m_cfg . kCHR ;
btVector3 normal = c . m_cti . m_normal ;
btVector3 t1 = generateUnitOrthogonalVector ( normal ) ;
btVector3 t2 = btCross ( normal , t1 ) ;
btMultiBodyJacobianData jacobianData_normal , jacobianData_t1 , jacobianData_t2 ;
findJacobian ( link , jacobianData_normal , c . m_node - > m_x , normal ) ;
findJacobian ( link , jacobianData_t1 , c . m_node - > m_x , t1 ) ;
findJacobian ( link , jacobianData_t2 , c . m_node - > m_x , t2 ) ;
btScalar * J_n = & jacobianData_normal . m_jacobians [ 0 ] ;
btScalar * J_t1 = & jacobianData_t1 . m_jacobians [ 0 ] ;
btScalar * J_t2 = & jacobianData_t2 . m_jacobians [ 0 ] ;
btScalar * u_n = & jacobianData_normal . m_deltaVelocitiesUnitImpulse [ 0 ] ;
btScalar * u_t1 = & jacobianData_t1 . m_deltaVelocitiesUnitImpulse [ 0 ] ;
btScalar * u_t2 = & jacobianData_t2 . m_deltaVelocitiesUnitImpulse [ 0 ] ;
btMatrix3x3 rot ( normal . getX ( ) , normal . getY ( ) , normal . getZ ( ) ,
t1 . getX ( ) , t1 . getY ( ) , t1 . getZ ( ) ,
t2 . getX ( ) , t2 . getY ( ) , t2 . getZ ( ) ) ; // world frame to local frame
const int ndof = link - > m_multiBody - > getNumDofs ( ) + 6 ;
btMatrix3x3 local_impulse_matrix = ( Diagonal ( n . m_im ) + OuterProduct ( J_n , J_t1 , J_t2 , u_n , u_t1 , u_t2 , ndof ) ) . inverse ( ) ;
c . m_c0 = rot . transpose ( ) * local_impulse_matrix * rot ;
c . jacobianData_normal = jacobianData_normal ;
c . jacobianData_t1 = jacobianData_t1 ;
c . jacobianData_t2 = jacobianData_t2 ;
c . t1 = t1 ;
c . t2 = t2 ;
const btVector3 ra = n . m_x - wtr . getOrigin ( ) ;
c . m_c1 = ra ;
c . m_local = link - > getWorldTransform ( ) . inverse ( ) * m_nodes [ node ] . m_x ;
c . m_node - > m_battach = 1 ;
m_deformableAnchors . push_back ( c ) ;
2020-01-08 18:05:43 +01:00
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendLinearJoint ( const LJoint : : Specs & specs , Cluster * body0 , Body body1 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
LJoint * pj = new ( btAlignedAlloc ( sizeof ( LJoint ) , 16 ) ) LJoint ( ) ;
pj - > m_bodies [ 0 ] = body0 ;
pj - > m_bodies [ 1 ] = body1 ;
pj - > m_refs [ 0 ] = pj - > m_bodies [ 0 ] . xform ( ) . inverse ( ) * specs . position ;
pj - > m_refs [ 1 ] = pj - > m_bodies [ 1 ] . xform ( ) . inverse ( ) * specs . position ;
pj - > m_cfm = specs . cfm ;
pj - > m_erp = specs . erp ;
pj - > m_split = specs . split ;
2017-08-01 14:30:58 +02:00
m_joints . push_back ( pj ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendLinearJoint ( const LJoint : : Specs & specs , Body body )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendLinearJoint ( specs , m_clusters [ 0 ] , body ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendLinearJoint ( const LJoint : : Specs & specs , btSoftBody * body )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendLinearJoint ( specs , m_clusters [ 0 ] , body - > m_clusters [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendAngularJoint ( const AJoint : : Specs & specs , Cluster * body0 , Body body1 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
AJoint * pj = new ( btAlignedAlloc ( sizeof ( AJoint ) , 16 ) ) AJoint ( ) ;
pj - > m_bodies [ 0 ] = body0 ;
pj - > m_bodies [ 1 ] = body1 ;
pj - > m_refs [ 0 ] = pj - > m_bodies [ 0 ] . xform ( ) . inverse ( ) . getBasis ( ) * specs . axis ;
pj - > m_refs [ 1 ] = pj - > m_bodies [ 1 ] . xform ( ) . inverse ( ) . getBasis ( ) * specs . axis ;
pj - > m_cfm = specs . cfm ;
pj - > m_erp = specs . erp ;
pj - > m_split = specs . split ;
pj - > m_icontrol = specs . icontrol ;
2017-08-01 14:30:58 +02:00
m_joints . push_back ( pj ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendAngularJoint ( const AJoint : : Specs & specs , Body body )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendAngularJoint ( specs , m_clusters [ 0 ] , body ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : appendAngularJoint ( const AJoint : : Specs & specs , btSoftBody * body )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendAngularJoint ( specs , m_clusters [ 0 ] , body - > m_clusters [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : addForce ( const btVector3 & force )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i ) addForce ( force , i ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : addForce ( const btVector3 & force , int node )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ node ] ;
if ( n . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
n . m_f + = force ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : addAeroForceToNode ( const btVector3 & windVelocity , int nodeIndex )
2017-08-01 14:30:58 +02:00
{
btAssert ( nodeIndex > = 0 & & nodeIndex < m_nodes . size ( ) ) ;
const btScalar dt = m_sst . sdt ;
const btScalar kLF = m_cfg . kLF ;
const btScalar kDG = m_cfg . kDG ;
//const btScalar kPR = m_cfg.kPR;
//const btScalar kVC = m_cfg.kVC;
2019-01-03 14:26:51 +01:00
const bool as_lift = kLF > 0 ;
const bool as_drag = kDG > 0 ;
2017-08-01 14:30:58 +02:00
const bool as_aero = as_lift | | as_drag ;
const bool as_vaero = as_aero & & ( m_cfg . aeromodel < btSoftBody : : eAeroModel : : F_TwoSided ) ;
Node & n = m_nodes [ nodeIndex ] ;
2019-01-03 14:26:51 +01:00
if ( n . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : sMedium medium ;
2017-08-01 14:30:58 +02:00
EvaluateMedium ( m_worldInfo , n . m_x , medium ) ;
medium . m_velocity = windVelocity ;
medium . m_density = m_worldInfo - > air_density ;
2019-01-03 14:26:51 +01:00
/* Aerodynamics */
if ( as_vaero )
{
const btVector3 rel_v = n . m_v - medium . m_velocity ;
2017-08-01 14:30:58 +02:00
const btScalar rel_v_len = rel_v . length ( ) ;
2019-01-03 14:26:51 +01:00
const btScalar rel_v2 = rel_v . length2 ( ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
if ( rel_v2 > SIMD_EPSILON )
2017-08-01 14:30:58 +02:00
{
const btVector3 rel_v_nrm = rel_v . normalized ( ) ;
2019-01-03 14:26:51 +01:00
btVector3 nrm = n . m_n ;
2017-08-01 14:30:58 +02:00
if ( m_cfg . aeromodel = = btSoftBody : : eAeroModel : : V_TwoSidedLiftDrag )
{
2019-01-03 14:26:51 +01:00
nrm * = ( btScalar ) ( ( btDot ( nrm , rel_v ) < 0 ) ? - 1 : + 1 ) ;
2017-08-01 14:30:58 +02:00
btVector3 fDrag ( 0 , 0 , 0 ) ;
btVector3 fLift ( 0 , 0 , 0 ) ;
btScalar n_dot_v = nrm . dot ( rel_v_nrm ) ;
btScalar tri_area = 0.5f * n . m_area ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
fDrag = 0.5f * kDG * medium . m_density * rel_v2 * tri_area * n_dot_v * ( - rel_v_nrm ) ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
// Check angle of attack
2021-09-29 15:47:08 +02:00
// cos(10º) = 0.98480
2019-01-03 14:26:51 +01:00
if ( 0 < n_dot_v & & n_dot_v < 0.98480f )
fLift = 0.5f * kLF * medium . m_density * rel_v_len * tri_area * btSqrt ( 1.0f - n_dot_v * n_dot_v ) * ( nrm . cross ( rel_v_nrm ) . cross ( rel_v_nrm ) ) ;
2017-08-01 14:30:58 +02:00
// Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
2019-01-03 14:26:51 +01:00
btVector3 del_v_by_fDrag = fDrag * n . m_im * m_sst . sdt ;
2017-08-01 14:30:58 +02:00
btScalar del_v_by_fDrag_len2 = del_v_by_fDrag . length2 ( ) ;
btScalar v_len2 = n . m_v . length2 ( ) ;
if ( del_v_by_fDrag_len2 > = v_len2 & & del_v_by_fDrag_len2 > 0 )
{
btScalar del_v_by_fDrag_len = del_v_by_fDrag . length ( ) ;
btScalar v_len = n . m_v . length ( ) ;
2019-01-03 14:26:51 +01:00
fDrag * = btScalar ( 0.8 ) * ( v_len / del_v_by_fDrag_len ) ;
2017-08-01 14:30:58 +02:00
}
n . m_f + = fDrag ;
n . m_f + = fLift ;
}
else if ( m_cfg . aeromodel = = btSoftBody : : eAeroModel : : V_Point | | m_cfg . aeromodel = = btSoftBody : : eAeroModel : : V_OneSided | | m_cfg . aeromodel = = btSoftBody : : eAeroModel : : V_TwoSided )
{
if ( m_cfg . aeromodel = = btSoftBody : : eAeroModel : : V_TwoSided )
2019-01-03 14:26:51 +01:00
nrm * = ( btScalar ) ( ( btDot ( nrm , rel_v ) < 0 ) ? - 1 : + 1 ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
const btScalar dvn = btDot ( rel_v , nrm ) ;
/* Compute forces */
if ( dvn > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btVector3 force ( 0 , 0 , 0 ) ;
const btScalar c0 = n . m_area * dvn * rel_v2 / 2 ;
const btScalar c1 = c0 * medium . m_density ;
force + = nrm * ( - c1 * kLF ) ;
force + = rel_v . normalized ( ) * ( - c1 * kDG ) ;
2017-08-01 14:30:58 +02:00
ApplyClampedForce ( n , force , dt ) ;
}
2019-01-03 14:26:51 +01:00
}
2017-08-01 14:30:58 +02:00
}
}
}
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : addAeroForceToFace ( const btVector3 & windVelocity , int faceIndex )
2017-08-01 14:30:58 +02:00
{
const btScalar dt = m_sst . sdt ;
const btScalar kLF = m_cfg . kLF ;
const btScalar kDG = m_cfg . kDG ;
2019-01-03 14:26:51 +01:00
// const btScalar kPR = m_cfg.kPR;
// const btScalar kVC = m_cfg.kVC;
const bool as_lift = kLF > 0 ;
const bool as_drag = kDG > 0 ;
2017-08-01 14:30:58 +02:00
const bool as_aero = as_lift | | as_drag ;
const bool as_faero = as_aero & & ( m_cfg . aeromodel > = btSoftBody : : eAeroModel : : F_TwoSided ) ;
2019-01-03 14:26:51 +01:00
if ( as_faero )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : Face & f = m_faces [ faceIndex ] ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
btSoftBody : : sMedium medium ;
const btVector3 v = ( f . m_n [ 0 ] - > m_v + f . m_n [ 1 ] - > m_v + f . m_n [ 2 ] - > m_v ) / 3 ;
const btVector3 x = ( f . m_n [ 0 ] - > m_x + f . m_n [ 1 ] - > m_x + f . m_n [ 2 ] - > m_x ) / 3 ;
EvaluateMedium ( m_worldInfo , x , medium ) ;
2017-08-01 14:30:58 +02:00
medium . m_velocity = windVelocity ;
medium . m_density = m_worldInfo - > air_density ;
2019-01-03 14:26:51 +01:00
const btVector3 rel_v = v - medium . m_velocity ;
2017-08-01 14:30:58 +02:00
const btScalar rel_v_len = rel_v . length ( ) ;
2019-01-03 14:26:51 +01:00
const btScalar rel_v2 = rel_v . length2 ( ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
if ( rel_v2 > SIMD_EPSILON )
2017-08-01 14:30:58 +02:00
{
const btVector3 rel_v_nrm = rel_v . normalized ( ) ;
2019-01-03 14:26:51 +01:00
btVector3 nrm = f . m_normal ;
2017-08-01 14:30:58 +02:00
if ( m_cfg . aeromodel = = btSoftBody : : eAeroModel : : F_TwoSidedLiftDrag )
{
2019-01-03 14:26:51 +01:00
nrm * = ( btScalar ) ( ( btDot ( nrm , rel_v ) < 0 ) ? - 1 : + 1 ) ;
2017-08-01 14:30:58 +02:00
btVector3 fDrag ( 0 , 0 , 0 ) ;
btVector3 fLift ( 0 , 0 , 0 ) ;
btScalar n_dot_v = nrm . dot ( rel_v_nrm ) ;
btScalar tri_area = 0.5f * f . m_ra ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
fDrag = 0.5f * kDG * medium . m_density * rel_v2 * tri_area * n_dot_v * ( - rel_v_nrm ) ;
// Check angle of attack
2021-09-29 15:47:08 +02:00
// cos(10º) = 0.98480
2019-01-03 14:26:51 +01:00
if ( 0 < n_dot_v & & n_dot_v < 0.98480f )
fLift = 0.5f * kLF * medium . m_density * rel_v_len * tri_area * btSqrt ( 1.0f - n_dot_v * n_dot_v ) * ( nrm . cross ( rel_v_nrm ) . cross ( rel_v_nrm ) ) ;
2017-08-01 14:30:58 +02:00
fDrag / = 3 ;
fLift / = 3 ;
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 3 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( f . m_n [ j ] - > m_im > 0 )
2017-08-01 14:30:58 +02:00
{
// Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
2019-01-03 14:26:51 +01:00
btVector3 del_v_by_fDrag = fDrag * f . m_n [ j ] - > m_im * m_sst . sdt ;
2017-08-01 14:30:58 +02:00
btScalar del_v_by_fDrag_len2 = del_v_by_fDrag . length2 ( ) ;
btScalar v_len2 = f . m_n [ j ] - > m_v . length2 ( ) ;
if ( del_v_by_fDrag_len2 > = v_len2 & & del_v_by_fDrag_len2 > 0 )
{
btScalar del_v_by_fDrag_len = del_v_by_fDrag . length ( ) ;
btScalar v_len = f . m_n [ j ] - > m_v . length ( ) ;
2019-01-03 14:26:51 +01:00
fDrag * = btScalar ( 0.8 ) * ( v_len / del_v_by_fDrag_len ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
f . m_n [ j ] - > m_f + = fDrag ;
2017-08-01 14:30:58 +02:00
f . m_n [ j ] - > m_f + = fLift ;
}
}
}
else if ( m_cfg . aeromodel = = btSoftBody : : eAeroModel : : F_OneSided | | m_cfg . aeromodel = = btSoftBody : : eAeroModel : : F_TwoSided )
{
if ( m_cfg . aeromodel = = btSoftBody : : eAeroModel : : F_TwoSided )
2019-01-03 14:26:51 +01:00
nrm * = ( btScalar ) ( ( btDot ( nrm , rel_v ) < 0 ) ? - 1 : + 1 ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
const btScalar dvn = btDot ( rel_v , nrm ) ;
/* Compute forces */
if ( dvn > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btVector3 force ( 0 , 0 , 0 ) ;
const btScalar c0 = f . m_ra * dvn * rel_v2 ;
const btScalar c1 = c0 * medium . m_density ;
force + = nrm * ( - c1 * kLF ) ;
force + = rel_v . normalized ( ) * ( - c1 * kDG ) ;
force / = 3 ;
for ( int j = 0 ; j < 3 ; + + j ) ApplyClampedForce ( * f . m_n [ j ] , force , dt ) ;
2017-08-01 14:30:58 +02:00
}
}
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : addVelocity ( const btVector3 & velocity )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i ) addVelocity ( velocity , i ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Set velocity for the entire body */
void btSoftBody : : setVelocity ( const btVector3 & velocity )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ i ] ;
if ( n . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
n . m_v = velocity ;
2021-09-29 15:47:08 +02:00
n . m_vn = velocity ;
2017-08-01 14:30:58 +02:00
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : addVelocity ( const btVector3 & velocity , int node )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ node ] ;
if ( n . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
n . m_v + = velocity ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : setMass ( int node , btScalar mass )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ node ] . m_im = mass > 0 ? 1 / mass : 0 ;
m_bUpdateRtCst = true ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
btScalar btSoftBody : : getMass ( int node ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
return ( m_nodes [ node ] . m_im > 0 ? 1 / m_nodes [ node ] . m_im : 0 ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
btScalar btSoftBody : : getTotalMass ( ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btScalar mass = 0 ;
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
mass + = getMass ( i ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
return ( mass ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : setTotalMass ( btScalar mass , bool fromfaces )
2017-08-01 14:30:58 +02:00
{
int i ;
2019-01-03 14:26:51 +01:00
if ( fromfaces )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_nodes . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_im = 0 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_faces . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Face & f = m_faces [ i ] ;
const btScalar twicearea = AreaOf ( f . m_n [ 0 ] - > m_x ,
f . m_n [ 1 ] - > m_x ,
f . m_n [ 2 ] - > m_x ) ;
for ( int j = 0 ; j < 3 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
f . m_n [ j ] - > m_im + = twicearea ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_nodes . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_im = 1 / m_nodes [ i ] . m_im ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
const btScalar tm = getTotalMass ( ) ;
const btScalar itm = 1 / tm ;
for ( i = 0 ; i < m_nodes . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_im / = itm * mass ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
m_bUpdateRtCst = true ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : setTotalDensity ( btScalar density )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
setTotalMass ( getVolume ( ) * density , true ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : setVolumeMass ( btScalar mass )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btAlignedObjectArray < btScalar > ranks ;
ranks . resize ( m_nodes . size ( ) , 0 ) ;
int i ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_nodes . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_im = 0 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_tetras . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Tetra & t = m_tetras [ i ] ;
for ( int j = 0 ; j < 4 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
t . m_n [ j ] - > m_im + = btFabs ( t . m_rv ) ;
ranks [ int ( t . m_n [ j ] - & m_nodes [ 0 ] ) ] + = 1 ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_nodes . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_nodes [ i ] . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_im = ranks [ i ] / m_nodes [ i ] . m_im ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
setTotalMass ( mass , false ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : setVolumeDensity ( btScalar density )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btScalar volume = 0 ;
for ( int i = 0 ; i < m_tetras . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Tetra & t = m_tetras [ i ] ;
for ( int j = 0 ; j < 4 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
volume + = btFabs ( t . m_rv ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
setVolumeMass ( volume * density / 6 ) ;
2017-08-01 14:30:58 +02:00
}
2021-09-29 15:47:08 +02:00
//
btVector3 btSoftBody : : getLinearVelocity ( )
{
btVector3 total_momentum = btVector3 ( 0 , 0 , 0 ) ;
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
{
btScalar mass = m_nodes [ i ] . m_im = = 0 ? 0 : 1.0 / m_nodes [ i ] . m_im ;
total_momentum + = mass * m_nodes [ i ] . m_v ;
}
btScalar total_mass = getTotalMass ( ) ;
return total_mass = = 0 ? total_momentum : total_momentum / total_mass ;
}
//
void btSoftBody : : setLinearVelocity ( const btVector3 & linVel )
{
btVector3 old_vel = getLinearVelocity ( ) ;
btVector3 diff = linVel - old_vel ;
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
m_nodes [ i ] . m_v + = diff ;
}
//
void btSoftBody : : setAngularVelocity ( const btVector3 & angVel )
{
btVector3 old_vel = getLinearVelocity ( ) ;
btVector3 com = getCenterOfMass ( ) ;
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
{
m_nodes [ i ] . m_v = angVel . cross ( m_nodes [ i ] . m_x - com ) + old_vel ;
}
}
//
btTransform btSoftBody : : getRigidTransform ( )
{
btVector3 t = getCenterOfMass ( ) ;
btMatrix3x3 S ;
S . setZero ( ) ;
// Get rotation that minimizes L2 difference: \sum_i || RX_i + t - x_i ||
// It's important to make sure that S has the correct signs.
// SVD is only unique up to the ordering of singular values.
// SVD will manipulate U and V to ensure the ordering of singular values. If all three singular
// vaues are negative, SVD will permute colums of U to make two of them positive.
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
{
S - = OuterProduct ( m_X [ i ] , t - m_nodes [ i ] . m_x ) ;
}
btVector3 sigma ;
btMatrix3x3 U , V ;
singularValueDecomposition ( S , U , sigma , V ) ;
btMatrix3x3 R = V * U . transpose ( ) ;
btTransform trs ;
trs . setIdentity ( ) ;
trs . setOrigin ( t ) ;
trs . setBasis ( R ) ;
return trs ;
}
//
void btSoftBody : : transformTo ( const btTransform & trs )
{
// get the current best rigid fit
btTransform current_transform = getRigidTransform ( ) ;
// apply transform in material space
btTransform new_transform = trs * current_transform . inverse ( ) ;
transform ( new_transform ) ;
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : transform ( const btTransform & trs )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar margin = getCollisionShape ( ) - > getMargin ( ) ;
ATTRIBUTE_ALIGNED16 ( btDbvtVolume )
vol ;
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ i ] ;
n . m_x = trs * n . m_x ;
n . m_q = trs * n . m_q ;
n . m_n = trs . getBasis ( ) * n . m_n ;
vol = btDbvtVolume : : FromCR ( n . m_x , margin ) ;
m_ndbvt . update ( n . m_leaf , vol ) ;
2017-08-01 14:30:58 +02:00
}
updateNormals ( ) ;
updateBounds ( ) ;
updateConstants ( ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : translate ( const btVector3 & trs )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btTransform t ;
2017-08-01 14:30:58 +02:00
t . setIdentity ( ) ;
t . setOrigin ( trs ) ;
transform ( t ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : rotate ( const btQuaternion & rot )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btTransform t ;
2017-08-01 14:30:58 +02:00
t . setIdentity ( ) ;
t . setRotation ( rot ) ;
transform ( t ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : scale ( const btVector3 & scl )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar margin = getCollisionShape ( ) - > getMargin ( ) ;
ATTRIBUTE_ALIGNED16 ( btDbvtVolume )
vol ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ i ] ;
n . m_x * = scl ;
n . m_q * = scl ;
vol = btDbvtVolume : : FromCR ( n . m_x , margin ) ;
m_ndbvt . update ( n . m_leaf , vol ) ;
2017-08-01 14:30:58 +02:00
}
updateNormals ( ) ;
updateBounds ( ) ;
updateConstants ( ) ;
2021-09-29 15:47:08 +02:00
initializeDmInverse ( ) ;
2017-08-01 14:30:58 +02:00
}
//
btScalar btSoftBody : : getRestLengthScale ( )
{
return m_restLengthScale ;
}
//
void btSoftBody : : setRestLengthScale ( btScalar restLengthScale )
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link & l = m_links [ i ] ;
l . m_rl = l . m_rl / m_restLengthScale * restLengthScale ;
l . m_c1 = l . m_rl * l . m_rl ;
2017-08-01 14:30:58 +02:00
}
m_restLengthScale = restLengthScale ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
if ( getActivationState ( ) = = ISLAND_SLEEPING )
activate ( ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : setPose ( bool bvolume , bool bframe )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_pose . m_bvolume = bvolume ;
m_pose . m_bframe = bframe ;
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
/* Weights */
const btScalar omass = getTotalMass ( ) ;
const btScalar kmass = omass * m_nodes . size ( ) * 1000 ;
btScalar tmass = omass ;
2017-08-01 14:30:58 +02:00
m_pose . m_wgh . resize ( m_nodes . size ( ) ) ;
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_nodes [ i ] . m_im < = 0 ) tmass + = kmass ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ i ] ;
m_pose . m_wgh [ i ] = n . m_im > 0 ? 1 / ( m_nodes [ i ] . m_im * tmass ) : kmass / tmass ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Pos */
const btVector3 com = evaluateCom ( ) ;
2017-08-01 14:30:58 +02:00
m_pose . m_pos . resize ( m_nodes . size ( ) ) ;
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_pose . m_pos [ i ] = m_nodes [ i ] . m_x - com ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
m_pose . m_volume = bvolume ? getVolume ( ) : 0 ;
m_pose . m_com = com ;
2017-08-01 14:30:58 +02:00
m_pose . m_rot . setIdentity ( ) ;
m_pose . m_scl . setIdentity ( ) ;
2019-01-03 14:26:51 +01:00
/* Aqq */
m_pose . m_aqq [ 0 ] =
m_pose . m_aqq [ 1 ] =
m_pose . m_aqq [ 2 ] = btVector3 ( 0 , 0 , 0 ) ;
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
{
const btVector3 & q = m_pose . m_pos [ i ] ;
const btVector3 mq = m_pose . m_wgh [ i ] * q ;
m_pose . m_aqq [ 0 ] + = mq . x ( ) * q ;
m_pose . m_aqq [ 1 ] + = mq . y ( ) * q ;
m_pose . m_aqq [ 2 ] + = mq . z ( ) * q ;
}
m_pose . m_aqq = m_pose . m_aqq . inverse ( ) ;
2017-08-01 14:30:58 +02:00
updateConstants ( ) ;
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : resetLinkRestLengths ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link & l = m_links [ i ] ;
l . m_rl = ( l . m_n [ 0 ] - > m_x - l . m_n [ 1 ] - > m_x ) . length ( ) ;
l . m_c1 = l . m_rl * l . m_rl ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
btScalar btSoftBody : : getVolume ( ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btScalar vol = 0 ;
if ( m_nodes . size ( ) > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
const btVector3 org = m_nodes [ 0 ] . m_x ;
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Face & f = m_faces [ i ] ;
vol + = btDot ( f . m_n [ 0 ] - > m_x - org , btCross ( f . m_n [ 1 ] - > m_x - org , f . m_n [ 2 ] - > m_x - org ) ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
vol / = ( btScalar ) 6 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
return ( vol ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
int btSoftBody : : clusterCount ( ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
return ( m_clusters . size ( ) ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
btVector3 btSoftBody : : clusterCom ( const Cluster * cluster )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btVector3 com ( 0 , 0 , 0 ) ;
for ( int i = 0 , ni = cluster - > m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
com + = cluster - > m_nodes [ i ] - > m_x * cluster - > m_masses [ i ] ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
return ( com * cluster - > m_imass ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
btVector3 btSoftBody : : clusterCom ( int cluster ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
return ( clusterCom ( m_clusters [ cluster ] ) ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
btVector3 btSoftBody : : clusterVelocity ( const Cluster * cluster , const btVector3 & rpos )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
return ( cluster - > m_lv + btCross ( cluster - > m_av , rpos ) ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : clusterVImpulse ( Cluster * cluster , const btVector3 & rpos , const btVector3 & impulse )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 li = cluster - > m_imass * impulse ;
const btVector3 ai = cluster - > m_invwi * btCross ( rpos , impulse ) ;
cluster - > m_vimpulses [ 0 ] + = li ;
cluster - > m_lv + = li ;
cluster - > m_vimpulses [ 1 ] + = ai ;
cluster - > m_av + = ai ;
2017-08-01 14:30:58 +02:00
cluster - > m_nvimpulses + + ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : clusterDImpulse ( Cluster * cluster , const btVector3 & rpos , const btVector3 & impulse )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 li = cluster - > m_imass * impulse ;
const btVector3 ai = cluster - > m_invwi * btCross ( rpos , impulse ) ;
cluster - > m_dimpulses [ 0 ] + = li ;
cluster - > m_dimpulses [ 1 ] + = ai ;
2017-08-01 14:30:58 +02:00
cluster - > m_ndimpulses + + ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : clusterImpulse ( Cluster * cluster , const btVector3 & rpos , const Impulse & impulse )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( impulse . m_asVelocity ) clusterVImpulse ( cluster , rpos , impulse . m_velocity ) ;
if ( impulse . m_asDrift ) clusterDImpulse ( cluster , rpos , impulse . m_drift ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : clusterVAImpulse ( Cluster * cluster , const btVector3 & impulse )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 ai = cluster - > m_invwi * impulse ;
cluster - > m_vimpulses [ 1 ] + = ai ;
cluster - > m_av + = ai ;
2017-08-01 14:30:58 +02:00
cluster - > m_nvimpulses + + ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : clusterDAImpulse ( Cluster * cluster , const btVector3 & impulse )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 ai = cluster - > m_invwi * impulse ;
cluster - > m_dimpulses [ 1 ] + = ai ;
2017-08-01 14:30:58 +02:00
cluster - > m_ndimpulses + + ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : clusterAImpulse ( Cluster * cluster , const Impulse & impulse )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( impulse . m_asVelocity ) clusterVAImpulse ( cluster , impulse . m_velocity ) ;
if ( impulse . m_asDrift ) clusterDAImpulse ( cluster , impulse . m_drift ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : clusterDCImpulse ( Cluster * cluster , const btVector3 & impulse )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
cluster - > m_dimpulses [ 0 ] + = impulse * cluster - > m_imass ;
2017-08-01 14:30:58 +02:00
cluster - > m_ndimpulses + + ;
}
struct NodeLinks
{
2019-01-03 14:26:51 +01:00
btAlignedObjectArray < int > m_links ;
2017-08-01 14:30:58 +02:00
} ;
//
2019-01-03 14:26:51 +01:00
int btSoftBody : : generateBendingConstraints ( int distance , Material * mat )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int i , j ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
if ( distance > 1 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
/* Build graph */
const int n = m_nodes . size ( ) ;
const unsigned inf = ( ~ ( unsigned ) 0 ) > > 1 ;
unsigned * adj = new unsigned [ n * n ] ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
# define IDX(_x_, _y_) ((_y_)*n + (_x_))
for ( j = 0 ; j < n ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < n ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( i ! = j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
adj [ IDX ( i , j ) ] = adj [ IDX ( j , i ) ] = inf ;
2017-08-01 14:30:58 +02:00
}
else
{
2019-01-03 14:26:51 +01:00
adj [ IDX ( i , j ) ] = adj [ IDX ( j , i ) ] = 0 ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_links . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int ia = ( int ) ( m_links [ i ] . m_n [ 0 ] - & m_nodes [ 0 ] ) ;
const int ib = ( int ) ( m_links [ i ] . m_n [ 1 ] - & m_nodes [ 0 ] ) ;
adj [ IDX ( ia , ib ) ] = 1 ;
adj [ IDX ( ib , ia ) ] = 1 ;
2017-08-01 14:30:58 +02:00
}
//special optimized case for distance == 2
if ( distance = = 2 )
{
btAlignedObjectArray < NodeLinks > nodeLinks ;
/* Build node links */
nodeLinks . resize ( m_nodes . size ( ) ) ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_links . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int ia = ( int ) ( m_links [ i ] . m_n [ 0 ] - & m_nodes [ 0 ] ) ;
const int ib = ( int ) ( m_links [ i ] . m_n [ 1 ] - & m_nodes [ 0 ] ) ;
if ( nodeLinks [ ia ] . m_links . findLinearSearch ( ib ) = = nodeLinks [ ia ] . m_links . size ( ) )
2017-08-01 14:30:58 +02:00
nodeLinks [ ia ] . m_links . push_back ( ib ) ;
2019-01-03 14:26:51 +01:00
if ( nodeLinks [ ib ] . m_links . findLinearSearch ( ia ) = = nodeLinks [ ib ] . m_links . size ( ) )
2017-08-01 14:30:58 +02:00
nodeLinks [ ib ] . m_links . push_back ( ia ) ;
}
2019-01-03 14:26:51 +01:00
for ( int ii = 0 ; ii < nodeLinks . size ( ) ; ii + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int i = ii ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( int jj = 0 ; jj < nodeLinks [ ii ] . m_links . size ( ) ; jj + + )
2017-08-01 14:30:58 +02:00
{
int k = nodeLinks [ ii ] . m_links [ jj ] ;
2019-01-03 14:26:51 +01:00
for ( int kk = 0 ; kk < nodeLinks [ k ] . m_links . size ( ) ; kk + + )
2017-08-01 14:30:58 +02:00
{
int j = nodeLinks [ k ] . m_links [ kk ] ;
2019-01-03 14:26:51 +01:00
if ( i ! = j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const unsigned sum = adj [ IDX ( i , k ) ] + adj [ IDX ( k , j ) ] ;
btAssert ( sum = = 2 ) ;
if ( adj [ IDX ( i , j ) ] > sum )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
adj [ IDX ( i , j ) ] = adj [ IDX ( j , i ) ] = sum ;
2017-08-01 14:30:58 +02:00
}
}
}
}
}
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
///generic Floyd's algorithm
2019-01-03 14:26:51 +01:00
for ( int k = 0 ; k < n ; + + k )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( j = 0 ; j < n ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( i = j + 1 ; i < n ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const unsigned sum = adj [ IDX ( i , k ) ] + adj [ IDX ( k , j ) ] ;
if ( adj [ IDX ( i , j ) ] > sum )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
adj [ IDX ( i , j ) ] = adj [ IDX ( j , i ) ] = sum ;
2017-08-01 14:30:58 +02:00
}
}
}
}
}
2019-01-03 14:26:51 +01:00
/* Build links */
int nlinks = 0 ;
for ( j = 0 ; j < n ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( i = j + 1 ; i < n ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( adj [ IDX ( i , j ) ] = = ( unsigned ) distance )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
appendLink ( i , j , mat ) ;
m_links [ m_links . size ( ) - 1 ] . m_bbending = 1 ;
2017-08-01 14:30:58 +02:00
+ + nlinks ;
}
}
}
2019-01-03 14:26:51 +01:00
delete [ ] adj ;
return ( nlinks ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
return ( 0 ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : randomizeConstraints ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
unsigned long seed = 243703 ;
# define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSwap ( m_links [ i ] , m_links [ NEXTRAND % ni ] ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSwap ( m_faces [ i ] , m_faces [ NEXTRAND % ni ] ) ;
2017-08-01 14:30:58 +02:00
}
# undef NEXTRAND
}
2022-05-17 00:02:51 +02:00
void btSoftBody : : updateState ( const btAlignedObjectArray < btVector3 > & q , const btAlignedObjectArray < btVector3 > & v )
{
int node_count = m_nodes . size ( ) ;
btAssert ( node_count = = q . size ( ) ) ;
btAssert ( node_count = = v . size ( ) ) ;
for ( int i = 0 ; i < node_count ; i + + )
{
Node & n = m_nodes [ i ] ;
n . m_x = q [ i ] ;
n . m_q = q [ i ] ;
n . m_v = v [ i ] ;
n . m_vn = v [ i ] ;
}
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : releaseCluster ( int index )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Cluster * c = m_clusters [ index ] ;
if ( c - > m_leaf ) m_cdbvt . remove ( c - > m_leaf ) ;
2017-08-01 14:30:58 +02:00
c - > ~ Cluster ( ) ;
btAlignedFree ( c ) ;
m_clusters . remove ( c ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : releaseClusters ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
while ( m_clusters . size ( ) > 0 ) releaseCluster ( 0 ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
int btSoftBody : : generateClusters ( int k , int maxiterations )
2017-08-01 14:30:58 +02:00
{
int i ;
releaseClusters ( ) ;
2019-01-03 14:26:51 +01:00
m_clusters . resize ( btMin ( k , m_nodes . size ( ) ) ) ;
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
{
m_clusters [ i ] = new ( btAlignedAlloc ( sizeof ( Cluster ) , 16 ) ) Cluster ( ) ;
m_clusters [ i ] - > m_collide = true ;
}
k = m_clusters . size ( ) ;
if ( k > 0 )
{
/* Initialize */
btAlignedObjectArray < btVector3 > centers ;
btVector3 cog ( 0 , 0 , 0 ) ;
int i ;
for ( i = 0 ; i < m_nodes . size ( ) ; + + i )
{
cog + = m_nodes [ i ] . m_x ;
m_clusters [ ( i * 29873 ) % m_clusters . size ( ) ] - > m_nodes . push_back ( & m_nodes [ i ] ) ;
}
cog / = ( btScalar ) m_nodes . size ( ) ;
centers . resize ( k , cog ) ;
/* Iterate */
const btScalar slope = 16 ;
bool changed ;
int iterations = 0 ;
do
{
const btScalar w = 2 - btMin < btScalar > ( 1 , iterations / slope ) ;
changed = false ;
iterations + + ;
2017-08-01 14:30:58 +02:00
int i ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < k ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btVector3 c ( 0 , 0 , 0 ) ;
for ( int j = 0 ; j < m_clusters [ i ] - > m_nodes . size ( ) ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
c + = m_clusters [ i ] - > m_nodes [ j ] - > m_x ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
if ( m_clusters [ i ] - > m_nodes . size ( ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
c / = ( btScalar ) m_clusters [ i ] - > m_nodes . size ( ) ;
c = centers [ i ] + ( c - centers [ i ] ) * w ;
changed | = ( ( c - centers [ i ] ) . length2 ( ) > SIMD_EPSILON ) ;
centers [ i ] = c ;
2017-08-01 14:30:58 +02:00
m_clusters [ i ] - > m_nodes . resize ( 0 ) ;
2019-01-03 14:26:51 +01:00
}
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_nodes . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 nx = m_nodes [ i ] . m_x ;
int kbest = 0 ;
btScalar kdist = ClusterMetric ( centers [ 0 ] , nx ) ;
for ( int j = 1 ; j < k ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar d = ClusterMetric ( centers [ j ] , nx ) ;
if ( d < kdist )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
kbest = j ;
kdist = d ;
2017-08-01 14:30:58 +02:00
}
}
m_clusters [ kbest ] - > m_nodes . push_back ( & m_nodes [ i ] ) ;
2019-01-03 14:26:51 +01:00
}
} while ( changed & & ( iterations < maxiterations ) ) ;
/* Merge */
btAlignedObjectArray < int > cids ;
cids . resize ( m_nodes . size ( ) , - 1 ) ;
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < m_clusters [ i ] - > m_nodes . size ( ) ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
cids [ int ( m_clusters [ i ] - > m_nodes [ j ] - & m_nodes [ 0 ] ) ] = i ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_faces . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int idx [ ] = { int ( m_faces [ i ] . m_n [ 0 ] - & m_nodes [ 0 ] ) ,
int ( m_faces [ i ] . m_n [ 1 ] - & m_nodes [ 0 ] ) ,
int ( m_faces [ i ] . m_n [ 2 ] - & m_nodes [ 0 ] ) } ;
for ( int j = 0 ; j < 3 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int cid = cids [ idx [ j ] ] ;
for ( int q = 1 ; q < 3 ; + + q )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int kid = idx [ ( j + q ) % 3 ] ;
if ( cids [ kid ] ! = cid )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_clusters [ cid ] - > m_nodes . findLinearSearch ( & m_nodes [ kid ] ) = = m_clusters [ cid ] - > m_nodes . size ( ) )
2017-08-01 14:30:58 +02:00
{
m_clusters [ cid ] - > m_nodes . push_back ( & m_nodes [ kid ] ) ;
}
}
}
}
}
2019-01-03 14:26:51 +01:00
/* Master */
if ( m_clusters . size ( ) > 1 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Cluster * pmaster = new ( btAlignedAlloc ( sizeof ( Cluster ) , 16 ) ) Cluster ( ) ;
pmaster - > m_collide = false ;
2017-08-01 14:30:58 +02:00
pmaster - > m_nodes . reserve ( m_nodes . size ( ) ) ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i ) pmaster - > m_nodes . push_back ( & m_nodes [ i ] ) ;
2017-08-01 14:30:58 +02:00
m_clusters . push_back ( pmaster ) ;
2019-01-03 14:26:51 +01:00
btSwap ( m_clusters [ 0 ] , m_clusters [ m_clusters . size ( ) - 1 ] ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Terminate */
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_clusters [ i ] - > m_nodes . size ( ) = = 0 )
2017-08-01 14:30:58 +02:00
{
releaseCluster ( i - - ) ;
}
}
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
//create a cluster for each tetrahedron (if tetrahedra exist) or each face
if ( m_tetras . size ( ) )
{
m_clusters . resize ( m_tetras . size ( ) ) ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_clusters [ i ] = new ( btAlignedAlloc ( sizeof ( Cluster ) , 16 ) ) Cluster ( ) ;
m_clusters [ i ] - > m_collide = true ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_tetras . size ( ) ; i + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 4 ; j + + )
2017-08-01 14:30:58 +02:00
{
m_clusters [ i ] - > m_nodes . push_back ( m_tetras [ i ] . m_n [ j ] ) ;
}
}
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
m_clusters . resize ( m_faces . size ( ) ) ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_clusters [ i ] = new ( btAlignedAlloc ( sizeof ( Cluster ) , 16 ) ) Cluster ( ) ;
m_clusters [ i ] - > m_collide = true ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_faces . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 3 ; + + j )
2017-08-01 14:30:58 +02:00
{
m_clusters [ i ] - > m_nodes . push_back ( m_faces [ i ] . m_n [ j ] ) ;
}
}
}
}
if ( m_clusters . size ( ) )
{
initializeClusters ( ) ;
updateClusters ( ) ;
//for self-collision
2019-01-03 14:26:51 +01:00
m_clusterConnectivity . resize ( m_clusters . size ( ) * m_clusters . size ( ) ) ;
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int c0 = 0 ; c0 < m_clusters . size ( ) ; c0 + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_clusters [ c0 ] - > m_clusterIndex = c0 ;
for ( int c1 = 0 ; c1 < m_clusters . size ( ) ; c1 + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
bool connected = false ;
2017-08-01 14:30:58 +02:00
Cluster * cla = m_clusters [ c0 ] ;
Cluster * clb = m_clusters [ c1 ] ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; ! connected & & i < cla - > m_nodes . size ( ) ; i + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < clb - > m_nodes . size ( ) ; j + + )
2017-08-01 14:30:58 +02:00
{
if ( cla - > m_nodes [ i ] = = clb - > m_nodes [ j ] )
{
2019-01-03 14:26:51 +01:00
connected = true ;
2017-08-01 14:30:58 +02:00
break ;
}
}
}
2019-01-03 14:26:51 +01:00
m_clusterConnectivity [ c0 + c1 * m_clusters . size ( ) ] = connected ;
2017-08-01 14:30:58 +02:00
}
}
}
}
2019-01-03 14:26:51 +01:00
return ( m_clusters . size ( ) ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : refine ( ImplicitFn * ifn , btScalar accurary , bool cut )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Node * nbase = & m_nodes [ 0 ] ;
int ncount = m_nodes . size ( ) ;
btSymMatrix < int > edges ( ncount , - 2 ) ;
int newnodes = 0 ;
int i , j , k , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
/* Filter out */
for ( i = 0 ; i < m_links . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link & l = m_links [ i ] ;
if ( l . m_bbending )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( ! SameSign ( ifn - > Eval ( l . m_n [ 0 ] - > m_x ) , ifn - > Eval ( l . m_n [ 1 ] - > m_x ) ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSwap ( m_links [ i ] , m_links [ m_links . size ( ) - 1 ] ) ;
m_links . pop_back ( ) ;
- - i ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
}
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Fill edges */
for ( i = 0 ; i < m_links . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link & l = m_links [ i ] ;
edges ( int ( l . m_n [ 0 ] - nbase ) , int ( l . m_n [ 1 ] - nbase ) ) = - 1 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_faces . size ( ) ; + + i )
{
Face & f = m_faces [ i ] ;
edges ( int ( f . m_n [ 0 ] - nbase ) , int ( f . m_n [ 1 ] - nbase ) ) = - 1 ;
edges ( int ( f . m_n [ 1 ] - nbase ) , int ( f . m_n [ 2 ] - nbase ) ) = - 1 ;
edges ( int ( f . m_n [ 2 ] - nbase ) , int ( f . m_n [ 0 ] - nbase ) ) = - 1 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Intersect */
for ( i = 0 ; i < ncount ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( j = i + 1 ; j < ncount ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( edges ( i , j ) = = - 1 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & a = m_nodes [ i ] ;
Node & b = m_nodes [ j ] ;
const btScalar t = ImplicitSolve ( ifn , a . m_x , b . m_x , accurary ) ;
if ( t > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 x = Lerp ( a . m_x , b . m_x , t ) ;
const btVector3 v = Lerp ( a . m_v , b . m_v , t ) ;
btScalar m = 0 ;
if ( a . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( b . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar ma = 1 / a . m_im ;
const btScalar mb = 1 / b . m_im ;
const btScalar mc = Lerp ( ma , mb , t ) ;
const btScalar f = ( ma + mb ) / ( ma + mb + mc ) ;
a . m_im = 1 / ( ma * f ) ;
b . m_im = 1 / ( mb * f ) ;
m = mc * f ;
2017-08-01 14:30:58 +02:00
}
else
2019-01-03 14:26:51 +01:00
{
a . m_im / = 0.5f ;
m = 1 / a . m_im ;
}
2017-08-01 14:30:58 +02:00
}
else
{
2019-01-03 14:26:51 +01:00
if ( b . m_im > 0 )
{
b . m_im / = 0.5f ;
m = 1 / b . m_im ;
}
2017-08-01 14:30:58 +02:00
else
2019-01-03 14:26:51 +01:00
m = 0 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
appendNode ( x , m ) ;
edges ( i , j ) = m_nodes . size ( ) - 1 ;
m_nodes [ edges ( i , j ) ] . m_v = v ;
2017-08-01 14:30:58 +02:00
+ + newnodes ;
}
}
}
}
2019-01-03 14:26:51 +01:00
nbase = & m_nodes [ 0 ] ;
/* Refine links */
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link & feat = m_links [ i ] ;
const int idx [ ] = { int ( feat . m_n [ 0 ] - nbase ) ,
int ( feat . m_n [ 1 ] - nbase ) } ;
if ( ( idx [ 0 ] < ncount ) & & ( idx [ 1 ] < ncount ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int ni = edges ( idx [ 0 ] , idx [ 1 ] ) ;
if ( ni > 0 )
2017-08-01 14:30:58 +02:00
{
appendLink ( i ) ;
2019-01-03 14:26:51 +01:00
Link * pft [ ] = { & m_links [ i ] ,
& m_links [ m_links . size ( ) - 1 ] } ;
pft [ 0 ] - > m_n [ 0 ] = & m_nodes [ idx [ 0 ] ] ;
pft [ 0 ] - > m_n [ 1 ] = & m_nodes [ ni ] ;
pft [ 1 ] - > m_n [ 0 ] = & m_nodes [ ni ] ;
pft [ 1 ] - > m_n [ 1 ] = & m_nodes [ idx [ 1 ] ] ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
/* Refine faces */
for ( i = 0 ; i < m_faces . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Face & feat = m_faces [ i ] ;
const int idx [ ] = { int ( feat . m_n [ 0 ] - nbase ) ,
int ( feat . m_n [ 1 ] - nbase ) ,
int ( feat . m_n [ 2 ] - nbase ) } ;
for ( j = 2 , k = 0 ; k < 3 ; j = k + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( ( idx [ j ] < ncount ) & & ( idx [ k ] < ncount ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int ni = edges ( idx [ j ] , idx [ k ] ) ;
if ( ni > 0 )
2017-08-01 14:30:58 +02:00
{
appendFace ( i ) ;
2019-01-03 14:26:51 +01:00
const int l = ( k + 1 ) % 3 ;
Face * pft [ ] = { & m_faces [ i ] ,
& m_faces [ m_faces . size ( ) - 1 ] } ;
pft [ 0 ] - > m_n [ 0 ] = & m_nodes [ idx [ l ] ] ;
pft [ 0 ] - > m_n [ 1 ] = & m_nodes [ idx [ j ] ] ;
pft [ 0 ] - > m_n [ 2 ] = & m_nodes [ ni ] ;
pft [ 1 ] - > m_n [ 0 ] = & m_nodes [ ni ] ;
pft [ 1 ] - > m_n [ 1 ] = & m_nodes [ idx [ k ] ] ;
pft [ 1 ] - > m_n [ 2 ] = & m_nodes [ idx [ l ] ] ;
appendLink ( ni , idx [ l ] , pft [ 0 ] - > m_material ) ;
- - i ;
break ;
2017-08-01 14:30:58 +02:00
}
}
}
}
2019-01-03 14:26:51 +01:00
/* Cut */
if ( cut )
{
btAlignedObjectArray < int > cnodes ;
const int pcount = ncount ;
int i ;
ncount = m_nodes . size ( ) ;
cnodes . resize ( ncount , 0 ) ;
/* Nodes */
for ( i = 0 ; i < ncount ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 x = m_nodes [ i ] . m_x ;
if ( ( i > = pcount ) | | ( btFabs ( ifn - > Eval ( x ) ) < accurary ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 v = m_nodes [ i ] . m_v ;
btScalar m = getMass ( i ) ;
if ( m > 0 )
{
m * = 0.5f ;
m_nodes [ i ] . m_im / = 0.5f ;
}
appendNode ( x , m ) ;
cnodes [ i ] = m_nodes . size ( ) - 1 ;
m_nodes [ cnodes [ i ] ] . m_v = v ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
nbase = & m_nodes [ 0 ] ;
/* Links */
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int id [ ] = { int ( m_links [ i ] . m_n [ 0 ] - nbase ) ,
int ( m_links [ i ] . m_n [ 1 ] - nbase ) } ;
int todetach = 0 ;
if ( cnodes [ id [ 0 ] ] & & cnodes [ id [ 1 ] ] )
2017-08-01 14:30:58 +02:00
{
appendLink ( i ) ;
2019-01-03 14:26:51 +01:00
todetach = m_links . size ( ) - 1 ;
2017-08-01 14:30:58 +02:00
}
else
{
2019-01-03 14:26:51 +01:00
if ( ( ( ifn - > Eval ( m_nodes [ id [ 0 ] ] . m_x ) < accurary ) & &
( ifn - > Eval ( m_nodes [ id [ 1 ] ] . m_x ) < accurary ) ) )
todetach = i ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
if ( todetach )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link & l = m_links [ todetach ] ;
for ( int j = 0 ; j < 2 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int cn = cnodes [ int ( l . m_n [ j ] - nbase ) ] ;
if ( cn ) l . m_n [ j ] = & m_nodes [ cn ] ;
}
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
/* Faces */
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node * * n = m_faces [ i ] . m_n ;
if ( ( ifn - > Eval ( n [ 0 ] - > m_x ) < accurary ) & &
( ifn - > Eval ( n [ 1 ] - > m_x ) < accurary ) & &
( ifn - > Eval ( n [ 2 ] - > m_x ) < accurary ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 3 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int cn = cnodes [ int ( n [ j ] - nbase ) ] ;
if ( cn ) n [ j ] = & m_nodes [ cn ] ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
/* Clean orphans */
int nnodes = m_nodes . size ( ) ;
btAlignedObjectArray < int > ranks ;
btAlignedObjectArray < int > todelete ;
ranks . resize ( nnodes , 0 ) ;
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 2 ; + + j ) ranks [ int ( m_links [ i ] . m_n [ j ] - nbase ) ] + + ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 3 ; + + j ) ranks [ int ( m_faces [ i ] . m_n [ j ] - nbase ) ] + + ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_links . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int id [ ] = { int ( m_links [ i ] . m_n [ 0 ] - nbase ) ,
int ( m_links [ i ] . m_n [ 1 ] - nbase ) } ;
const bool sg [ ] = { ranks [ id [ 0 ] ] = = 1 ,
ranks [ id [ 1 ] ] = = 1 } ;
if ( sg [ 0 ] | | sg [ 1 ] )
2017-08-01 14:30:58 +02:00
{
- - ranks [ id [ 0 ] ] ;
- - ranks [ id [ 1 ] ] ;
2019-01-03 14:26:51 +01:00
btSwap ( m_links [ i ] , m_links [ m_links . size ( ) - 1 ] ) ;
m_links . pop_back ( ) ;
- - i ;
2017-08-01 14:30:58 +02:00
}
}
#if 0
for ( i = nnodes - 1 ; i > = 0 ; - - i )
{
if ( ! ranks [ i ] ) todelete . push_back ( i ) ;
}
if ( todelete . size ( ) )
{
btAlignedObjectArray < int > & map = ranks ;
for ( int i = 0 ; i < nnodes ; + + i ) map [ i ] = i ;
PointersToIndices ( this ) ;
for ( int i = 0 , ni = todelete . size ( ) ; i < ni ; + + i )
{
int j = todelete [ i ] ;
int & a = map [ j ] ;
int & b = map [ - - nnodes ] ;
m_ndbvt . remove ( m_nodes [ a ] . m_leaf ) ; m_nodes [ a ] . m_leaf = 0 ;
btSwap ( m_nodes [ a ] , m_nodes [ b ] ) ;
j = a ; a = b ; b = j ;
}
IndicesToPointers ( this , & map [ 0 ] ) ;
m_nodes . resize ( nnodes ) ;
}
# endif
}
2019-01-03 14:26:51 +01:00
m_bUpdateRtCst = true ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
bool btSoftBody : : cutLink ( const Node * node0 , const Node * node1 , btScalar position )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
return ( cutLink ( int ( node0 - & m_nodes [ 0 ] ) , int ( node1 - & m_nodes [ 0 ] ) , position ) ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
bool btSoftBody : : cutLink ( int node0 , int node1 , btScalar position )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
bool done = false ;
int i , ni ;
// const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
const btVector3 x = Lerp ( m_nodes [ node0 ] . m_x , m_nodes [ node1 ] . m_x , position ) ;
const btVector3 v = Lerp ( m_nodes [ node0 ] . m_v , m_nodes [ node1 ] . m_v , position ) ;
const btScalar m = 1 ;
appendNode ( x , m ) ;
appendNode ( x , m ) ;
Node * pa = & m_nodes [ node0 ] ;
Node * pb = & m_nodes [ node1 ] ;
Node * pn [ 2 ] = { & m_nodes [ m_nodes . size ( ) - 2 ] ,
& m_nodes [ m_nodes . size ( ) - 1 ] } ;
pn [ 0 ] - > m_v = v ;
pn [ 1 ] - > m_v = v ;
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int mtch = MatchEdge ( m_links [ i ] . m_n [ 0 ] , m_links [ i ] . m_n [ 1 ] , pa , pb ) ;
if ( mtch ! = - 1 )
2017-08-01 14:30:58 +02:00
{
appendLink ( i ) ;
2019-01-03 14:26:51 +01:00
Link * pft [ ] = { & m_links [ i ] , & m_links [ m_links . size ( ) - 1 ] } ;
pft [ 0 ] - > m_n [ 1 ] = pn [ mtch ] ;
pft [ 1 ] - > m_n [ 0 ] = pn [ 1 - mtch ] ;
done = true ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int k = 2 , l = 0 ; l < 3 ; k = l + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int mtch = MatchEdge ( m_faces [ i ] . m_n [ k ] , m_faces [ i ] . m_n [ l ] , pa , pb ) ;
if ( mtch ! = - 1 )
2017-08-01 14:30:58 +02:00
{
appendFace ( i ) ;
2019-01-03 14:26:51 +01:00
Face * pft [ ] = { & m_faces [ i ] , & m_faces [ m_faces . size ( ) - 1 ] } ;
pft [ 0 ] - > m_n [ l ] = pn [ mtch ] ;
pft [ 1 ] - > m_n [ k ] = pn [ 1 - mtch ] ;
appendLink ( pn [ 0 ] , pft [ 0 ] - > m_n [ ( l + 1 ) % 3 ] , pft [ 0 ] - > m_material , true ) ;
appendLink ( pn [ 1 ] , pft [ 0 ] - > m_n [ ( l + 1 ) % 3 ] , pft [ 0 ] - > m_material , true ) ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
if ( ! done )
2017-08-01 14:30:58 +02:00
{
m_ndbvt . remove ( pn [ 0 ] - > m_leaf ) ;
m_ndbvt . remove ( pn [ 1 ] - > m_leaf ) ;
m_nodes . pop_back ( ) ;
m_nodes . pop_back ( ) ;
}
2019-01-03 14:26:51 +01:00
return ( done ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
bool btSoftBody : : rayTest ( const btVector3 & rayFrom ,
const btVector3 & rayTo ,
sRayCast & results )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_faces . size ( ) & & m_fdbvt . empty ( ) )
2017-08-01 14:30:58 +02:00
initializeFaceTree ( ) ;
2019-01-03 14:26:51 +01:00
results . body = this ;
2017-08-01 14:30:58 +02:00
results . fraction = 1.f ;
2019-01-03 14:26:51 +01:00
results . feature = eFeature : : None ;
results . index = - 1 ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
return ( rayTest ( rayFrom , rayTo , results . fraction , results . feature , results . index , false ) ! = 0 ) ;
2017-08-01 14:30:58 +02:00
}
2021-09-29 15:47:08 +02:00
bool btSoftBody : : rayFaceTest ( const btVector3 & rayFrom ,
const btVector3 & rayTo ,
sRayCast & results )
{
if ( m_faces . size ( ) = = 0 )
return false ;
else
{
if ( m_fdbvt . empty ( ) )
initializeFaceTree ( ) ;
}
results . body = this ;
results . fraction = 1.f ;
results . index = - 1 ;
return ( rayFaceTest ( rayFrom , rayTo , results . fraction , results . index ) ! = 0 ) ;
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : setSolver ( eSolverPresets : : _ preset )
2017-08-01 14:30:58 +02:00
{
m_cfg . m_vsequence . clear ( ) ;
m_cfg . m_psequence . clear ( ) ;
m_cfg . m_dsequence . clear ( ) ;
2019-01-03 14:26:51 +01:00
switch ( preset )
{
case eSolverPresets : : Positions :
m_cfg . m_psequence . push_back ( ePSolver : : Anchors ) ;
m_cfg . m_psequence . push_back ( ePSolver : : RContacts ) ;
m_cfg . m_psequence . push_back ( ePSolver : : SContacts ) ;
m_cfg . m_psequence . push_back ( ePSolver : : Linear ) ;
break ;
case eSolverPresets : : Velocities :
m_cfg . m_vsequence . push_back ( eVSolver : : Linear ) ;
m_cfg . m_psequence . push_back ( ePSolver : : Anchors ) ;
m_cfg . m_psequence . push_back ( ePSolver : : RContacts ) ;
m_cfg . m_psequence . push_back ( ePSolver : : SContacts ) ;
m_cfg . m_dsequence . push_back ( ePSolver : : Linear ) ;
break ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : predictMotion ( btScalar dt )
2017-08-01 14:30:58 +02:00
{
2021-09-29 15:47:08 +02:00
int i , ni ;
/* Update */
if ( m_bUpdateRtCst )
{
m_bUpdateRtCst = false ;
updateConstants ( ) ;
m_fdbvt . clear ( ) ;
if ( m_cfg . collisions & fCollision : : VF_SS )
{
initializeFaceTree ( ) ;
}
}
2017-08-01 14:30:58 +02:00
2021-09-29 15:47:08 +02:00
/* Prepare */
m_sst . sdt = dt * m_cfg . timescale ;
m_sst . isdt = 1 / m_sst . sdt ;
m_sst . velmrg = m_sst . sdt * 3 ;
m_sst . radmrg = getCollisionShape ( ) - > getMargin ( ) ;
m_sst . updmrg = m_sst . radmrg * ( btScalar ) 0.25 ;
/* Forces */
addVelocity ( m_worldInfo - > m_gravity * m_sst . sdt ) ;
applyForces ( ) ;
/* Integrate */
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
{
Node & n = m_nodes [ i ] ;
n . m_q = n . m_x ;
btVector3 deltaV = n . m_f * n . m_im * m_sst . sdt ;
{
btScalar maxDisplacement = m_worldInfo - > m_maxDisplacement ;
btScalar clampDeltaV = maxDisplacement / m_sst . sdt ;
for ( int c = 0 ; c < 3 ; c + + )
{
if ( deltaV [ c ] > clampDeltaV )
{
deltaV [ c ] = clampDeltaV ;
}
if ( deltaV [ c ] < - clampDeltaV )
{
deltaV [ c ] = - clampDeltaV ;
}
}
}
n . m_v + = deltaV ;
n . m_x + = n . m_v * m_sst . sdt ;
n . m_f = btVector3 ( 0 , 0 , 0 ) ;
}
/* Clusters */
updateClusters ( ) ;
/* Bounds */
updateBounds ( ) ;
/* Nodes */
ATTRIBUTE_ALIGNED16 ( btDbvtVolume )
vol ;
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
{
Node & n = m_nodes [ i ] ;
vol = btDbvtVolume : : FromCR ( n . m_x , m_sst . radmrg ) ;
m_ndbvt . update ( n . m_leaf ,
vol ,
n . m_v * m_sst . velmrg ,
m_sst . updmrg ) ;
}
/* Faces */
if ( ! m_fdbvt . empty ( ) )
{
for ( int i = 0 ; i < m_faces . size ( ) ; + + i )
{
Face & f = m_faces [ i ] ;
const btVector3 v = ( f . m_n [ 0 ] - > m_v +
f . m_n [ 1 ] - > m_v +
f . m_n [ 2 ] - > m_v ) /
3 ;
vol = VolumeOf ( f , m_sst . radmrg ) ;
m_fdbvt . update ( f . m_leaf ,
vol ,
v * m_sst . velmrg ,
m_sst . updmrg ) ;
}
}
/* Pose */
updatePose ( ) ;
/* Match */
if ( m_pose . m_bframe & & ( m_cfg . kMT > 0 ) )
{
const btMatrix3x3 posetrs = m_pose . m_rot ;
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
{
Node & n = m_nodes [ i ] ;
if ( n . m_im > 0 )
{
const btVector3 x = posetrs * m_pose . m_pos [ i ] + m_pose . m_com ;
n . m_x = Lerp ( n . m_x , x , m_cfg . kMT ) ;
}
}
}
/* Clear contacts */
m_rcontacts . resize ( 0 ) ;
m_scontacts . resize ( 0 ) ;
/* Optimize dbvt's */
m_ndbvt . optimizeIncremental ( 1 ) ;
m_fdbvt . optimizeIncremental ( 1 ) ;
m_cdbvt . optimizeIncremental ( 1 ) ;
}
2020-01-08 18:05:43 +01:00
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : solveConstraints ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
/* Apply clusters */
2017-08-01 14:30:58 +02:00
applyClusters ( false ) ;
2019-01-03 14:26:51 +01:00
/* Prepare links */
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link & l = m_links [ i ] ;
l . m_c3 = l . m_n [ 1 ] - > m_q - l . m_n [ 0 ] - > m_q ;
l . m_c2 = 1 / ( l . m_c3 . length2 ( ) * l . m_c0 ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Prepare anchors */
for ( i = 0 , ni = m_anchors . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Anchor & a = m_anchors [ i ] ;
const btVector3 ra = a . m_body - > getWorldTransform ( ) . getBasis ( ) * a . m_local ;
a . m_c0 = ImpulseMatrix ( m_sst . sdt ,
a . m_node - > m_im ,
a . m_body - > getInvMass ( ) ,
a . m_body - > getInvInertiaTensorWorld ( ) ,
ra ) ;
a . m_c1 = ra ;
a . m_c2 = m_sst . sdt * a . m_node - > m_im ;
2017-08-01 14:30:58 +02:00
a . m_body - > activate ( ) ;
}
2019-01-03 14:26:51 +01:00
/* Solve velocities */
if ( m_cfg . viterations > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
/* Solve */
for ( int isolve = 0 ; isolve < m_cfg . viterations ; + + isolve )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int iseq = 0 ; iseq < m_cfg . m_vsequence . size ( ) ; + + iseq )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
getSolver ( m_cfg . m_vsequence [ iseq ] ) ( this , 1 ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
/* Update */
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ i ] ;
n . m_x = n . m_q + n . m_v * m_sst . sdt ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
/* Solve positions */
if ( m_cfg . piterations > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int isolve = 0 ; isolve < m_cfg . piterations ; + + isolve )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar ti = isolve / ( btScalar ) m_cfg . piterations ;
for ( int iseq = 0 ; iseq < m_cfg . m_psequence . size ( ) ; + + iseq )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
getSolver ( m_cfg . m_psequence [ iseq ] ) ( this , 1 , ti ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
const btScalar vc = m_sst . isdt * ( 1 - m_cfg . kDP ) ;
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ i ] ;
n . m_v = ( n . m_x - n . m_q ) * vc ;
n . m_f = btVector3 ( 0 , 0 , 0 ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
/* Solve drift */
if ( m_cfg . diterations > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar vcf = m_cfg . kVCF * m_sst . isdt ;
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ i ] ;
n . m_q = n . m_x ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( int idrift = 0 ; idrift < m_cfg . diterations ; + + idrift )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int iseq = 0 ; iseq < m_cfg . m_dsequence . size ( ) ; + + iseq )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
getSolver ( m_cfg . m_dsequence [ iseq ] ) ( this , 1 , 0 ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = m_nodes [ i ] ;
n . m_v + = ( n . m_x - n . m_q ) * vcf ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
/* Apply clusters */
2017-08-01 14:30:58 +02:00
dampClusters ( ) ;
applyClusters ( true ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : staticSolve ( int iterations )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int isolve = 0 ; isolve < iterations ; + + isolve )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int iseq = 0 ; iseq < m_cfg . m_psequence . size ( ) ; + + iseq )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
getSolver ( m_cfg . m_psequence [ iseq ] ) ( this , 1 , 0 ) ;
2017-08-01 14:30:58 +02:00
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : solveCommonConstraints ( btSoftBody * * /*bodies*/ , int /*count*/ , int /*iterations*/ )
2017-08-01 14:30:58 +02:00
{
/// placeholder
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : solveClusters ( const btAlignedObjectArray < btSoftBody * > & bodies )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int nb = bodies . size ( ) ;
int iterations = 0 ;
2017-08-01 14:30:58 +02:00
int i ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < nb ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
iterations = btMax ( iterations , bodies [ i ] - > m_cfg . citerations ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < nb ; + + i )
2017-08-01 14:30:58 +02:00
{
bodies [ i ] - > prepareClusters ( iterations ) ;
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < iterations ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar sor = 1 ;
for ( int j = 0 ; j < nb ; + + j )
2017-08-01 14:30:58 +02:00
{
bodies [ j ] - > solveClusters ( sor ) ;
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < nb ; + + i )
2017-08-01 14:30:58 +02:00
{
bodies [ i ] - > cleanupClusters ( ) ;
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : integrateMotion ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
/* Update */
2017-08-01 14:30:58 +02:00
updateNormals ( ) ;
}
//
2019-01-03 14:26:51 +01:00
btSoftBody : : RayFromToCaster : : RayFromToCaster ( const btVector3 & rayFrom , const btVector3 & rayTo , btScalar mxt )
2017-08-01 14:30:58 +02:00
{
m_rayFrom = rayFrom ;
2019-01-03 14:26:51 +01:00
m_rayNormalizedDirection = ( rayTo - rayFrom ) ;
2017-08-01 14:30:58 +02:00
m_rayTo = rayTo ;
2019-01-03 14:26:51 +01:00
m_mint = mxt ;
m_face = 0 ;
m_tests = 0 ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : RayFromToCaster : : Process ( const btDbvtNode * leaf )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : Face & f = * ( btSoftBody : : Face * ) leaf - > data ;
const btScalar t = rayFromToTriangle ( m_rayFrom , m_rayTo , m_rayNormalizedDirection ,
f . m_n [ 0 ] - > m_x ,
f . m_n [ 1 ] - > m_x ,
f . m_n [ 2 ] - > m_x ,
m_mint ) ;
if ( ( t > 0 ) & & ( t < m_mint ) )
{
m_mint = t ;
m_face = & f ;
2017-08-01 14:30:58 +02:00
}
+ + m_tests ;
}
//
2019-01-03 14:26:51 +01:00
btScalar btSoftBody : : RayFromToCaster : : rayFromToTriangle ( const btVector3 & rayFrom ,
const btVector3 & rayTo ,
const btVector3 & rayNormalizedDirection ,
const btVector3 & a ,
const btVector3 & b ,
const btVector3 & c ,
btScalar maxt )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
static const btScalar ceps = - SIMD_EPSILON * 10 ;
static const btScalar teps = SIMD_EPSILON * 10 ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
const btVector3 n = btCross ( b - a , c - a ) ;
const btScalar d = btDot ( a , n ) ;
const btScalar den = btDot ( rayNormalizedDirection , n ) ;
if ( ! btFuzzyZero ( den ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar num = btDot ( rayFrom , n ) - d ;
const btScalar t = - num / den ;
if ( ( t > teps ) & & ( t < maxt ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 hit = rayFrom + rayNormalizedDirection * t ;
if ( ( btDot ( n , btCross ( a - hit , b - hit ) ) > ceps ) & &
( btDot ( n , btCross ( b - hit , c - hit ) ) > ceps ) & &
( btDot ( n , btCross ( c - hit , a - hit ) ) > ceps ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
return ( t ) ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
return ( - 1 ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : pointersToIndices ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
# define PTR2IDX(_p_, _b_) reinterpret_cast<btSoftBody::Node*>((_p_) - (_b_))
btSoftBody : : Node * base = m_nodes . size ( ) ? & m_nodes [ 0 ] : 0 ;
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_nodes [ i ] . m_leaf )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_leaf - > data = * ( void * * ) & i ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_links [ i ] . m_n [ 0 ] = PTR2IDX ( m_links [ i ] . m_n [ 0 ] , base ) ;
m_links [ i ] . m_n [ 1 ] = PTR2IDX ( m_links [ i ] . m_n [ 1 ] , base ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_faces [ i ] . m_n [ 0 ] = PTR2IDX ( m_faces [ i ] . m_n [ 0 ] , base ) ;
m_faces [ i ] . m_n [ 1 ] = PTR2IDX ( m_faces [ i ] . m_n [ 1 ] , base ) ;
m_faces [ i ] . m_n [ 2 ] = PTR2IDX ( m_faces [ i ] . m_n [ 2 ] , base ) ;
if ( m_faces [ i ] . m_leaf )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_faces [ i ] . m_leaf - > data = * ( void * * ) & i ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_anchors . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_anchors [ i ] . m_node = PTR2IDX ( m_anchors [ i ] . m_node , base ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_notes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < m_notes [ i ] . m_rank ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_notes [ i ] . m_nodes [ j ] = PTR2IDX ( m_notes [ i ] . m_nodes [ j ] , base ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
# undef PTR2IDX
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : indicesToPointers ( const int * map )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
# define IDX2PTR(_p_, _b_) map ? (&(_b_)[map[(((char*)_p_) - (char*)0)]]) : (&(_b_)[(((char*)_p_) - (char*)0)])
btSoftBody : : Node * base = m_nodes . size ( ) ? & m_nodes [ 0 ] : 0 ;
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_nodes [ i ] . m_leaf )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_leaf - > data = & m_nodes [ i ] ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_links [ i ] . m_n [ 0 ] = IDX2PTR ( m_links [ i ] . m_n [ 0 ] , base ) ;
m_links [ i ] . m_n [ 1 ] = IDX2PTR ( m_links [ i ] . m_n [ 1 ] , base ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_faces [ i ] . m_n [ 0 ] = IDX2PTR ( m_faces [ i ] . m_n [ 0 ] , base ) ;
m_faces [ i ] . m_n [ 1 ] = IDX2PTR ( m_faces [ i ] . m_n [ 1 ] , base ) ;
m_faces [ i ] . m_n [ 2 ] = IDX2PTR ( m_faces [ i ] . m_n [ 2 ] , base ) ;
if ( m_faces [ i ] . m_leaf )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_faces [ i ] . m_leaf - > data = & m_faces [ i ] ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_anchors . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_anchors [ i ] . m_node = IDX2PTR ( m_anchors [ i ] . m_node , base ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_notes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < m_notes [ i ] . m_rank ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_notes [ i ] . m_nodes [ j ] = IDX2PTR ( m_notes [ i ] . m_nodes [ j ] , base ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
# undef IDX2PTR
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
int btSoftBody : : rayTest ( const btVector3 & rayFrom , const btVector3 & rayTo ,
btScalar & mint , eFeature : : _ & feature , int & index , bool bcountonly ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int cnt = 0 ;
btVector3 dir = rayTo - rayFrom ;
if ( bcountonly | | m_fdbvt . empty ( ) )
{ /* Full search */
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btSoftBody : : Face & f = m_faces [ i ] ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
const btScalar t = RayFromToCaster : : rayFromToTriangle ( rayFrom , rayTo , dir ,
f . m_n [ 0 ] - > m_x ,
f . m_n [ 1 ] - > m_x ,
f . m_n [ 2 ] - > m_x ,
mint ) ;
if ( t > 0 )
2017-08-01 14:30:58 +02:00
{
+ + cnt ;
2019-01-03 14:26:51 +01:00
if ( ! bcountonly )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
feature = btSoftBody : : eFeature : : Face ;
index = i ;
mint = t ;
2017-08-01 14:30:58 +02:00
}
}
}
}
else
2019-01-03 14:26:51 +01:00
{ /* Use dbvt */
RayFromToCaster collider ( rayFrom , rayTo , mint ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
btDbvt : : rayTest ( m_fdbvt . m_root , rayFrom , rayTo , collider ) ;
if ( collider . m_face )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
mint = collider . m_mint ;
feature = btSoftBody : : eFeature : : Face ;
index = ( int ) ( collider . m_face - & m_faces [ 0 ] ) ;
cnt = 1 ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < m_tetras . size ( ) ; i + + )
2017-08-01 14:30:58 +02:00
{
const btSoftBody : : Tetra & tet = m_tetras [ i ] ;
2019-01-03 14:26:51 +01:00
int tetfaces [ 4 ] [ 3 ] = { { 0 , 1 , 2 } , { 0 , 1 , 3 } , { 1 , 2 , 3 } , { 0 , 2 , 3 } } ;
for ( int f = 0 ; f < 4 ; f + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int index0 = tetfaces [ f ] [ 0 ] ;
int index1 = tetfaces [ f ] [ 1 ] ;
int index2 = tetfaces [ f ] [ 2 ] ;
btVector3 v0 = tet . m_n [ index0 ] - > m_x ;
btVector3 v1 = tet . m_n [ index1 ] - > m_x ;
btVector3 v2 = tet . m_n [ index2 ] - > m_x ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
const btScalar t = RayFromToCaster : : rayFromToTriangle ( rayFrom , rayTo , dir ,
v0 , v1 , v2 ,
mint ) ;
if ( t > 0 )
2017-08-01 14:30:58 +02:00
{
+ + cnt ;
2019-01-03 14:26:51 +01:00
if ( ! bcountonly )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
feature = btSoftBody : : eFeature : : Tetra ;
index = i ;
mint = t ;
2017-08-01 14:30:58 +02:00
}
}
}
}
2019-01-03 14:26:51 +01:00
return ( cnt ) ;
2017-08-01 14:30:58 +02:00
}
2021-09-29 15:47:08 +02:00
int btSoftBody : : rayFaceTest ( const btVector3 & rayFrom , const btVector3 & rayTo ,
btScalar & mint , int & index ) const
{
int cnt = 0 ;
{ /* Use dbvt */
RayFromToCaster collider ( rayFrom , rayTo , mint ) ;
btDbvt : : rayTest ( m_fdbvt . m_root , rayFrom , rayTo , collider ) ;
if ( collider . m_face )
{
mint = collider . m_mint ;
index = ( int ) ( collider . m_face - & m_faces [ 0 ] ) ;
cnt = 1 ;
}
}
return ( cnt ) ;
}
2017-08-01 14:30:58 +02:00
//
2021-09-29 15:47:08 +02:00
static inline btDbvntNode * copyToDbvnt ( const btDbvtNode * n )
{
if ( n = = 0 )
return 0 ;
btDbvntNode * root = new btDbvntNode ( n ) ;
if ( n - > isinternal ( ) )
{
btDbvntNode * c0 = copyToDbvnt ( n - > childs [ 0 ] ) ;
root - > childs [ 0 ] = c0 ;
btDbvntNode * c1 = copyToDbvnt ( n - > childs [ 1 ] ) ;
root - > childs [ 1 ] = c1 ;
}
return root ;
}
static inline void calculateNormalCone ( btDbvntNode * root )
{
if ( ! root )
return ;
if ( root - > isleaf ( ) )
{
const btSoftBody : : Face * face = ( btSoftBody : : Face * ) root - > data ;
root - > normal = face - > m_normal ;
root - > angle = 0 ;
}
else
{
btVector3 n0 ( 0 , 0 , 0 ) , n1 ( 0 , 0 , 0 ) ;
btScalar a0 = 0 , a1 = 0 ;
if ( root - > childs [ 0 ] )
{
calculateNormalCone ( root - > childs [ 0 ] ) ;
n0 = root - > childs [ 0 ] - > normal ;
a0 = root - > childs [ 0 ] - > angle ;
}
if ( root - > childs [ 1 ] )
{
calculateNormalCone ( root - > childs [ 1 ] ) ;
n1 = root - > childs [ 1 ] - > normal ;
a1 = root - > childs [ 1 ] - > angle ;
}
root - > normal = ( n0 + n1 ) . safeNormalize ( ) ;
root - > angle = btMax ( a0 , a1 ) + btAngle ( n0 , n1 ) * 0.5 ;
}
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : initializeFaceTree ( )
2017-08-01 14:30:58 +02:00
{
2021-09-29 15:47:08 +02:00
BT_PROFILE ( " btSoftBody::initializeFaceTree " ) ;
2017-08-01 14:30:58 +02:00
m_fdbvt . clear ( ) ;
2021-09-29 15:47:08 +02:00
// create leaf nodes;
btAlignedObjectArray < btDbvtNode * > leafNodes ;
leafNodes . resize ( m_faces . size ( ) ) ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < m_faces . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Face & f = m_faces [ i ] ;
2021-09-29 15:47:08 +02:00
ATTRIBUTE_ALIGNED16 ( btDbvtVolume )
vol = VolumeOf ( f , 0 ) ;
btDbvtNode * node = new ( btAlignedAlloc ( sizeof ( btDbvtNode ) , 16 ) ) btDbvtNode ( ) ;
node - > parent = NULL ;
node - > data = & f ;
node - > childs [ 1 ] = 0 ;
node - > volume = vol ;
leafNodes [ i ] = node ;
f . m_leaf = node ;
}
btAlignedObjectArray < btAlignedObjectArray < int > > adj ;
adj . resize ( m_faces . size ( ) ) ;
// construct the adjacency list for triangles
for ( int i = 0 ; i < adj . size ( ) ; + + i )
{
for ( int j = i + 1 ; j < adj . size ( ) ; + + j )
{
int dup = 0 ;
for ( int k = 0 ; k < 3 ; + + k )
{
for ( int l = 0 ; l < 3 ; + + l )
{
if ( m_faces [ i ] . m_n [ k ] = = m_faces [ j ] . m_n [ l ] )
{
+ + dup ;
break ;
}
}
if ( dup = = 2 )
{
adj [ i ] . push_back ( j ) ;
adj [ j ] . push_back ( i ) ;
}
}
}
}
m_fdbvt . m_root = buildTreeBottomUp ( leafNodes , adj ) ;
if ( m_fdbvnt )
delete m_fdbvnt ;
m_fdbvnt = copyToDbvnt ( m_fdbvt . m_root ) ;
updateFaceTree ( false , false ) ;
rebuildNodeTree ( ) ;
}
//
void btSoftBody : : rebuildNodeTree ( )
{
m_ndbvt . clear ( ) ;
btAlignedObjectArray < btDbvtNode * > leafNodes ;
leafNodes . resize ( m_nodes . size ( ) ) ;
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
{
Node & n = m_nodes [ i ] ;
ATTRIBUTE_ALIGNED16 ( btDbvtVolume )
vol = btDbvtVolume : : FromCR ( n . m_x , 0 ) ;
btDbvtNode * node = new ( btAlignedAlloc ( sizeof ( btDbvtNode ) , 16 ) ) btDbvtNode ( ) ;
node - > parent = NULL ;
node - > data = & n ;
node - > childs [ 1 ] = 0 ;
node - > volume = vol ;
leafNodes [ i ] = node ;
n . m_leaf = node ;
2017-08-01 14:30:58 +02:00
}
2021-09-29 15:47:08 +02:00
btAlignedObjectArray < btAlignedObjectArray < int > > adj ;
adj . resize ( m_nodes . size ( ) ) ;
btAlignedObjectArray < int > old_id ;
old_id . resize ( m_nodes . size ( ) ) ;
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
old_id [ i ] = m_nodes [ i ] . index ;
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
m_nodes [ i ] . index = i ;
for ( int i = 0 ; i < m_links . size ( ) ; + + i )
{
Link & l = m_links [ i ] ;
adj [ l . m_n [ 0 ] - > index ] . push_back ( l . m_n [ 1 ] - > index ) ;
adj [ l . m_n [ 1 ] - > index ] . push_back ( l . m_n [ 0 ] - > index ) ;
}
m_ndbvt . m_root = buildTreeBottomUp ( leafNodes , adj ) ;
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
m_nodes [ i ] . index = old_id [ i ] ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
btVector3 btSoftBody : : evaluateCom ( ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btVector3 com ( 0 , 0 , 0 ) ;
if ( m_pose . m_bframe )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
com + = m_nodes [ i ] . m_x * m_pose . m_wgh [ i ] ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
return ( com ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
bool btSoftBody : : checkContact ( const btCollisionObjectWrapper * colObjWrap ,
2021-09-29 15:47:08 +02:00
const btVector3 & x ,
btScalar margin ,
btSoftBody : : sCti & cti ) const
{
btVector3 nrm ;
const btCollisionShape * shp = colObjWrap - > getCollisionShape ( ) ;
// const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
//const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
const btTransform & wtr = colObjWrap - > getWorldTransform ( ) ;
//todo: check which transform is needed here
btScalar dst =
m_worldInfo - > m_sparsesdf . Evaluate (
wtr . invXform ( x ) ,
shp ,
nrm ,
margin ) ;
if ( dst < 0 )
{
cti . m_colObj = colObjWrap - > getCollisionObject ( ) ;
cti . m_normal = wtr . getBasis ( ) * nrm ;
cti . m_offset = - btDot ( cti . m_normal , x - cti . m_normal * dst ) ;
return ( true ) ;
}
return ( false ) ;
2020-01-08 18:05:43 +01:00
}
//
bool btSoftBody : : checkDeformableContact ( const btCollisionObjectWrapper * colObjWrap ,
2021-09-29 15:47:08 +02:00
const btVector3 & x ,
btScalar margin ,
btSoftBody : : sCti & cti , bool predict ) const
2017-08-01 14:30:58 +02:00
{
btVector3 nrm ;
2019-01-03 14:26:51 +01:00
const btCollisionShape * shp = colObjWrap - > getCollisionShape ( ) ;
2021-09-29 15:47:08 +02:00
const btCollisionObject * tmpCollisionObj = colObjWrap - > getCollisionObject ( ) ;
// use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
// but resolve contact at x_n
btTransform wtr = ( predict ) ? ( colObjWrap - > m_preTransform ! = NULL ? tmpCollisionObj - > getInterpolationWorldTransform ( ) * ( * colObjWrap - > m_preTransform ) : tmpCollisionObj - > getInterpolationWorldTransform ( ) )
: colObjWrap - > getWorldTransform ( ) ;
2019-01-03 14:26:51 +01:00
btScalar dst =
m_worldInfo - > m_sparsesdf . Evaluate (
2017-08-01 14:30:58 +02:00
wtr . invXform ( x ) ,
shp ,
nrm ,
margin ) ;
2021-09-29 15:47:08 +02:00
2020-01-08 18:05:43 +01:00
if ( ! predict )
2017-08-01 14:30:58 +02:00
{
cti . m_colObj = colObjWrap - > getCollisionObject ( ) ;
2019-01-03 14:26:51 +01:00
cti . m_normal = wtr . getBasis ( ) * nrm ;
2021-09-29 15:47:08 +02:00
cti . m_offset = dst ;
2017-08-01 14:30:58 +02:00
}
2021-09-29 15:47:08 +02:00
if ( dst < 0 )
return true ;
2019-01-03 14:26:51 +01:00
return ( false ) ;
2017-08-01 14:30:58 +02:00
}
2020-01-08 18:05:43 +01:00
//
// Compute barycentric coordinates (u, v, w) for
// point p with respect to triangle (a, b, c)
static void getBarycentric ( const btVector3 & p , btVector3 & a , btVector3 & b , btVector3 & c , btVector3 & bary )
{
2021-09-29 15:47:08 +02:00
btVector3 v0 = b - a , v1 = c - a , v2 = p - a ;
btScalar d00 = v0 . dot ( v0 ) ;
btScalar d01 = v0 . dot ( v1 ) ;
btScalar d11 = v1 . dot ( v1 ) ;
btScalar d20 = v2 . dot ( v0 ) ;
btScalar d21 = v2 . dot ( v1 ) ;
btScalar denom = d00 * d11 - d01 * d01 ;
bary . setY ( ( d11 * d20 - d01 * d21 ) / denom ) ;
bary . setZ ( ( d00 * d21 - d01 * d20 ) / denom ) ;
bary . setX ( btScalar ( 1 ) - bary . getY ( ) - bary . getZ ( ) ) ;
2020-01-08 18:05:43 +01:00
}
//
bool btSoftBody : : checkDeformableFaceContact ( const btCollisionObjectWrapper * colObjWrap ,
2021-09-29 15:47:08 +02:00
Face & f ,
btVector3 & contact_point ,
btVector3 & bary ,
btScalar margin ,
btSoftBody : : sCti & cti , bool predict ) const
{
btVector3 nrm ;
const btCollisionShape * shp = colObjWrap - > getCollisionShape ( ) ;
const btCollisionObject * tmpCollisionObj = colObjWrap - > getCollisionObject ( ) ;
// use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
// but resolve contact at x_n
btTransform wtr = ( predict ) ? ( colObjWrap - > m_preTransform ! = NULL ? tmpCollisionObj - > getInterpolationWorldTransform ( ) * ( * colObjWrap - > m_preTransform ) : tmpCollisionObj - > getInterpolationWorldTransform ( ) )
: colObjWrap - > getWorldTransform ( ) ;
btScalar dst ;
btGjkEpaSolver2 : : sResults results ;
2020-01-08 18:05:43 +01:00
2022-05-17 00:02:51 +02:00
// #define USE_QUADRATURE 1
2020-01-08 18:05:43 +01:00
2021-09-29 15:47:08 +02:00
// use collision quadrature point
2020-01-08 18:05:43 +01:00
# ifdef USE_QUADRATURE
2021-09-29 15:47:08 +02:00
{
dst = SIMD_INFINITY ;
btVector3 local_nrm ;
for ( int q = 0 ; q < m_quads . size ( ) ; + + q )
{
btVector3 p ;
if ( predict )
p = BaryEval ( f . m_n [ 0 ] - > m_q , f . m_n [ 1 ] - > m_q , f . m_n [ 2 ] - > m_q , m_quads [ q ] ) ;
else
p = BaryEval ( f . m_n [ 0 ] - > m_x , f . m_n [ 1 ] - > m_x , f . m_n [ 2 ] - > m_x , m_quads [ q ] ) ;
btScalar local_dst = m_worldInfo - > m_sparsesdf . Evaluate (
wtr . invXform ( p ) ,
shp ,
local_nrm ,
margin ) ;
if ( local_dst < dst )
{
if ( local_dst < 0 & & predict )
return true ;
dst = local_dst ;
contact_point = p ;
bary = m_quads [ q ] ;
nrm = local_nrm ;
}
if ( ! predict )
{
cti . m_colObj = colObjWrap - > getCollisionObject ( ) ;
cti . m_normal = wtr . getBasis ( ) * nrm ;
cti . m_offset = dst ;
}
}
return ( dst < 0 ) ;
}
2020-01-08 18:05:43 +01:00
# endif
2021-09-29 15:47:08 +02:00
// collision detection using x*
btTransform triangle_transform ;
triangle_transform . setIdentity ( ) ;
triangle_transform . setOrigin ( f . m_n [ 0 ] - > m_q ) ;
btTriangleShape triangle ( btVector3 ( 0 , 0 , 0 ) , f . m_n [ 1 ] - > m_q - f . m_n [ 0 ] - > m_q , f . m_n [ 2 ] - > m_q - f . m_n [ 0 ] - > m_q ) ;
btVector3 guess ( 0 , 0 , 0 ) ;
const btConvexShape * csh = static_cast < const btConvexShape * > ( shp ) ;
btGjkEpaSolver2 : : SignedDistance ( & triangle , triangle_transform , csh , wtr , guess , results ) ;
dst = results . distance - 2.0 * csh - > getMargin ( ) - margin ; // margin padding so that the distance = the actual distance between face and rigid - margin of rigid - margin of deformable
if ( dst > = 0 )
return false ;
// Use consistent barycenter to recalculate distance.
if ( this - > m_cacheBarycenter )
{
if ( f . m_pcontact [ 3 ] ! = 0 )
{
for ( int i = 0 ; i < 3 ; + + i )
bary [ i ] = f . m_pcontact [ i ] ;
contact_point = BaryEval ( f . m_n [ 0 ] - > m_x , f . m_n [ 1 ] - > m_x , f . m_n [ 2 ] - > m_x , bary ) ;
const btConvexShape * csh = static_cast < const btConvexShape * > ( shp ) ;
btGjkEpaSolver2 : : SignedDistance ( contact_point , margin , csh , wtr , results ) ;
cti . m_colObj = colObjWrap - > getCollisionObject ( ) ;
dst = results . distance ;
cti . m_normal = results . normal ;
cti . m_offset = dst ;
//point-convex CD
wtr = colObjWrap - > getWorldTransform ( ) ;
btTriangleShape triangle2 ( btVector3 ( 0 , 0 , 0 ) , f . m_n [ 1 ] - > m_x - f . m_n [ 0 ] - > m_x , f . m_n [ 2 ] - > m_x - f . m_n [ 0 ] - > m_x ) ;
triangle_transform . setOrigin ( f . m_n [ 0 ] - > m_x ) ;
btGjkEpaSolver2 : : SignedDistance ( & triangle2 , triangle_transform , csh , wtr , guess , results ) ;
dst = results . distance - csh - > getMargin ( ) - margin ;
return true ;
}
}
// Use triangle-convex CD.
wtr = colObjWrap - > getWorldTransform ( ) ;
btTriangleShape triangle2 ( btVector3 ( 0 , 0 , 0 ) , f . m_n [ 1 ] - > m_x - f . m_n [ 0 ] - > m_x , f . m_n [ 2 ] - > m_x - f . m_n [ 0 ] - > m_x ) ;
triangle_transform . setOrigin ( f . m_n [ 0 ] - > m_x ) ;
btGjkEpaSolver2 : : SignedDistance ( & triangle2 , triangle_transform , csh , wtr , guess , results ) ;
contact_point = results . witnesses [ 0 ] ;
getBarycentric ( contact_point , f . m_n [ 0 ] - > m_x , f . m_n [ 1 ] - > m_x , f . m_n [ 2 ] - > m_x , bary ) ;
for ( int i = 0 ; i < 3 ; + + i )
f . m_pcontact [ i ] = bary [ i ] ;
dst = results . distance - csh - > getMargin ( ) - margin ;
cti . m_colObj = colObjWrap - > getCollisionObject ( ) ;
cti . m_normal = results . normal ;
cti . m_offset = dst ;
return true ;
2020-01-08 18:05:43 +01:00
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : updateNormals ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 zv ( 0 , 0 , 0 ) ;
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_n = zv ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : Face & f = m_faces [ i ] ;
const btVector3 n = btCross ( f . m_n [ 1 ] - > m_x - f . m_n [ 0 ] - > m_x ,
f . m_n [ 2 ] - > m_x - f . m_n [ 0 ] - > m_x ) ;
2020-01-08 18:05:43 +01:00
f . m_normal = n ;
f . m_normal . safeNormalize ( ) ;
2019-01-03 14:26:51 +01:00
f . m_n [ 0 ] - > m_n + = n ;
f . m_n [ 1 ] - > m_n + = n ;
f . m_n [ 2 ] - > m_n + = n ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
btScalar len = m_nodes [ i ] . m_n . length ( ) ;
2019-01-03 14:26:51 +01:00
if ( len > SIMD_EPSILON )
2017-08-01 14:30:58 +02:00
m_nodes [ i ] . m_n / = len ;
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : updateBounds ( )
2017-08-01 14:30:58 +02:00
{
/*if( m_acceleratedSoftBody )
{
// If we have an accelerated softbody we need to obtain the bounds correctly
// For now (slightly hackily) just have a very large AABB
// TODO: Write get bounds kernel
// If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
// probably do a test and exchange reasonably efficiently.
m_bounds [ 0 ] = btVector3 ( - 1000 , - 1000 , - 1000 ) ;
m_bounds [ 1 ] = btVector3 ( 1000 , 1000 , 1000 ) ;
} else { */
2021-09-29 15:47:08 +02:00
// if (m_ndbvt.m_root)
// {
// const btVector3& mins = m_ndbvt.m_root->volume.Mins();
// const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
// const btScalar csm = getCollisionShape()->getMargin();
// const btVector3 mrg = btVector3(csm,
// csm,
// csm) *
// 1; // ??? to investigate...
// m_bounds[0] = mins - mrg;
// m_bounds[1] = maxs + mrg;
// if (0 != getBroadphaseHandle())
// {
// m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
// m_bounds[0],
// m_bounds[1],
// m_worldInfo->m_dispatcher);
// }
// }
// else
// {
// m_bounds[0] =
// m_bounds[1] = btVector3(0, 0, 0);
// }
if ( m_nodes . size ( ) )
{
btVector3 mins = m_nodes [ 0 ] . m_x ;
btVector3 maxs = m_nodes [ 0 ] . m_x ;
for ( int i = 1 ; i < m_nodes . size ( ) ; + + i )
{
for ( int d = 0 ; d < 3 ; + + d )
{
if ( m_nodes [ i ] . m_x [ d ] > maxs [ d ] )
maxs [ d ] = m_nodes [ i ] . m_x [ d ] ;
if ( m_nodes [ i ] . m_x [ d ] < mins [ d ] )
mins [ d ] = m_nodes [ i ] . m_x [ d ] ;
}
}
const btScalar csm = getCollisionShape ( ) - > getMargin ( ) ;
const btVector3 mrg = btVector3 ( csm ,
csm ,
csm ) ;
m_bounds [ 0 ] = mins - mrg ;
m_bounds [ 1 ] = maxs + mrg ;
if ( 0 ! = getBroadphaseHandle ( ) )
{
m_worldInfo - > m_broadphase - > setAabb ( getBroadphaseHandle ( ) ,
m_bounds [ 0 ] ,
m_bounds [ 1 ] ,
m_worldInfo - > m_dispatcher ) ;
}
}
else
{
m_bounds [ 0 ] =
m_bounds [ 1 ] = btVector3 ( 0 , 0 , 0 ) ;
}
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : updatePose ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_pose . m_bframe )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : Pose & pose = m_pose ;
const btVector3 com = evaluateCom ( ) ;
/* Com */
pose . m_com = com ;
/* Rotation */
btMatrix3x3 Apq ;
const btScalar eps = SIMD_EPSILON ;
Apq [ 0 ] = Apq [ 1 ] = Apq [ 2 ] = btVector3 ( 0 , 0 , 0 ) ;
Apq [ 0 ] . setX ( eps ) ;
Apq [ 1 ] . setY ( eps * 2 ) ;
Apq [ 2 ] . setZ ( eps * 3 ) ;
for ( int i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 a = pose . m_wgh [ i ] * ( m_nodes [ i ] . m_x - com ) ;
const btVector3 & b = pose . m_pos [ i ] ;
Apq [ 0 ] + = a . x ( ) * b ;
Apq [ 1 ] + = a . y ( ) * b ;
Apq [ 2 ] + = a . z ( ) * b ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
btMatrix3x3 r , s ;
PolarDecompose ( Apq , r , s ) ;
pose . m_rot = r ;
pose . m_scl = pose . m_aqq * r . transpose ( ) * Apq ;
if ( m_cfg . maxvolume > 1 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar idet = Clamp < btScalar > ( 1 / pose . m_scl . determinant ( ) ,
1 , m_cfg . maxvolume ) ;
pose . m_scl = Mul ( pose . m_scl , idet ) ;
2017-08-01 14:30:58 +02:00
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : updateArea ( bool averageArea )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
/* Face area */
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Face & f = m_faces [ i ] ;
f . m_ra = AreaOf ( f . m_n [ 0 ] - > m_x , f . m_n [ 1 ] - > m_x , f . m_n [ 2 ] - > m_x ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Node area */
2017-08-01 14:30:58 +02:00
if ( averageArea )
{
2019-01-03 14:26:51 +01:00
btAlignedObjectArray < int > counts ;
counts . resize ( m_nodes . size ( ) , 0 ) ;
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_area = 0 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : Face & f = m_faces [ i ] ;
for ( int j = 0 ; j < 3 ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int index = ( int ) ( f . m_n [ j ] - & m_nodes [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
counts [ index ] + + ;
2019-01-03 14:26:51 +01:00
f . m_n [ j ] - > m_area + = btFabs ( f . m_ra ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( counts [ i ] > 0 )
m_nodes [ i ] . m_area / = ( btScalar ) counts [ i ] ;
2017-08-01 14:30:58 +02:00
else
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_area = 0 ;
2017-08-01 14:30:58 +02:00
}
}
else
{
// initialize node area as zero
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_area = 0 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : Face & f = m_faces [ i ] ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 3 ; + + j )
2017-08-01 14:30:58 +02:00
{
f . m_n [ j ] - > m_area + = f . m_ra ;
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
m_nodes [ i ] . m_area * = 0.3333333f ;
}
}
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : updateLinkConstants ( )
{
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
/* Links */
for ( i = 0 , ni = m_links . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Link & l = m_links [ i ] ;
Material & m = * l . m_material ;
l . m_c0 = ( l . m_n [ 0 ] - > m_im + l . m_n [ 1 ] - > m_im ) / m . m_kLST ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : updateConstants ( )
2017-08-01 14:30:58 +02:00
{
resetLinkRestLengths ( ) ;
updateLinkConstants ( ) ;
updateArea ( ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : initializeClusters ( )
2017-08-01 14:30:58 +02:00
{
int i ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Cluster & c = * m_clusters [ i ] ;
c . m_imass = 0 ;
2017-08-01 14:30:58 +02:00
c . m_masses . resize ( c . m_nodes . size ( ) ) ;
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < c . m_nodes . size ( ) ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( c . m_nodes [ j ] - > m_im = = 0 )
2017-08-01 14:30:58 +02:00
{
c . m_containsAnchor = true ;
2019-01-03 14:26:51 +01:00
c . m_masses [ j ] = BT_LARGE_FLOAT ;
}
else
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
c . m_masses [ j ] = btScalar ( 1. ) / c . m_nodes [ j ] - > m_im ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
c . m_imass + = c . m_masses [ j ] ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
c . m_imass = btScalar ( 1. ) / c . m_imass ;
c . m_com = btSoftBody : : clusterCom ( & c ) ;
c . m_lv = btVector3 ( 0 , 0 , 0 ) ;
c . m_av = btVector3 ( 0 , 0 , 0 ) ;
c . m_leaf = 0 ;
/* Inertia */
btMatrix3x3 & ii = c . m_locii ;
ii [ 0 ] = ii [ 1 ] = ii [ 2 ] = btVector3 ( 0 , 0 , 0 ) ;
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = c . m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 k = c . m_nodes [ i ] - > m_x - c . m_com ;
const btVector3 q = k * k ;
const btScalar m = c . m_masses [ i ] ;
ii [ 0 ] [ 0 ] + = m * ( q [ 1 ] + q [ 2 ] ) ;
ii [ 1 ] [ 1 ] + = m * ( q [ 0 ] + q [ 2 ] ) ;
ii [ 2 ] [ 2 ] + = m * ( q [ 0 ] + q [ 1 ] ) ;
ii [ 0 ] [ 1 ] - = m * k [ 0 ] * k [ 1 ] ;
ii [ 0 ] [ 2 ] - = m * k [ 0 ] * k [ 2 ] ;
ii [ 1 ] [ 2 ] - = m * k [ 1 ] * k [ 2 ] ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
ii [ 1 ] [ 0 ] = ii [ 0 ] [ 1 ] ;
ii [ 2 ] [ 0 ] = ii [ 0 ] [ 2 ] ;
ii [ 2 ] [ 1 ] = ii [ 1 ] [ 2 ] ;
2017-08-01 14:30:58 +02:00
ii = ii . inverse ( ) ;
2019-01-03 14:26:51 +01:00
/* Frame */
2017-08-01 14:30:58 +02:00
c . m_framexform . setIdentity ( ) ;
c . m_framexform . setOrigin ( c . m_com ) ;
c . m_framerefs . resize ( c . m_nodes . size ( ) ) ;
{
int i ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < c . m_framerefs . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
c . m_framerefs [ i ] = c . m_nodes [ i ] - > m_x - c . m_com ;
2017-08-01 14:30:58 +02:00
}
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : updateClusters ( )
2017-08-01 14:30:58 +02:00
{
BT_PROFILE ( " UpdateClusters " ) ;
int i ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : Cluster & c = * m_clusters [ i ] ;
const int n = c . m_nodes . size ( ) ;
2017-08-01 14:30:58 +02:00
//const btScalar invn=1/(btScalar)n;
2019-01-03 14:26:51 +01:00
if ( n )
{
/* Frame */
const btScalar eps = btScalar ( 0.0001 ) ;
btMatrix3x3 m , r , s ;
m [ 0 ] = m [ 1 ] = m [ 2 ] = btVector3 ( 0 , 0 , 0 ) ;
m [ 0 ] [ 0 ] = eps * 1 ;
m [ 1 ] [ 1 ] = eps * 2 ;
m [ 2 ] [ 2 ] = eps * 3 ;
c . m_com = clusterCom ( & c ) ;
for ( int i = 0 ; i < c . m_nodes . size ( ) ; + + i )
{
const btVector3 a = c . m_nodes [ i ] - > m_x - c . m_com ;
const btVector3 & b = c . m_framerefs [ i ] ;
m [ 0 ] + = a [ 0 ] * b ;
m [ 1 ] + = a [ 1 ] * b ;
m [ 2 ] + = a [ 2 ] * b ;
}
PolarDecompose ( m , r , s ) ;
2017-08-01 14:30:58 +02:00
c . m_framexform . setOrigin ( c . m_com ) ;
2019-01-03 14:26:51 +01:00
c . m_framexform . setBasis ( r ) ;
/* Inertia */
# if 1 /* Constant */
c . m_invwi = c . m_framexform . getBasis ( ) * c . m_locii * c . m_framexform . getBasis ( ) . transpose ( ) ;
2017-08-01 14:30:58 +02:00
# else
2019-01-03 14:26:51 +01:00
#if 0 /* Sphere */
2017-08-01 14:30:58 +02:00
const btScalar rk = ( 2 * c . m_extents . length2 ( ) ) / ( 5 * c . m_imass ) ;
const btVector3 inertia ( rk , rk , rk ) ;
const btVector3 iin ( btFabs ( inertia [ 0 ] ) > SIMD_EPSILON ? 1 / inertia [ 0 ] : 0 ,
btFabs ( inertia [ 1 ] ) > SIMD_EPSILON ? 1 / inertia [ 1 ] : 0 ,
btFabs ( inertia [ 2 ] ) > SIMD_EPSILON ? 1 / inertia [ 2 ] : 0 ) ;
c . m_invwi = c . m_xform . getBasis ( ) . scaled ( iin ) * c . m_xform . getBasis ( ) . transpose ( ) ;
2019-01-03 14:26:51 +01:00
# else /* Actual */
c . m_invwi [ 0 ] = c . m_invwi [ 1 ] = c . m_invwi [ 2 ] = btVector3 ( 0 , 0 , 0 ) ;
for ( int i = 0 ; i < n ; + + i )
{
const btVector3 k = c . m_nodes [ i ] - > m_x - c . m_com ;
const btVector3 q = k * k ;
const btScalar m = 1 / c . m_nodes [ i ] - > m_im ;
c . m_invwi [ 0 ] [ 0 ] + = m * ( q [ 1 ] + q [ 2 ] ) ;
c . m_invwi [ 1 ] [ 1 ] + = m * ( q [ 0 ] + q [ 2 ] ) ;
c . m_invwi [ 2 ] [ 2 ] + = m * ( q [ 0 ] + q [ 1 ] ) ;
c . m_invwi [ 0 ] [ 1 ] - = m * k [ 0 ] * k [ 1 ] ;
c . m_invwi [ 0 ] [ 2 ] - = m * k [ 0 ] * k [ 2 ] ;
c . m_invwi [ 1 ] [ 2 ] - = m * k [ 1 ] * k [ 2 ] ;
}
c . m_invwi [ 1 ] [ 0 ] = c . m_invwi [ 0 ] [ 1 ] ;
c . m_invwi [ 2 ] [ 0 ] = c . m_invwi [ 0 ] [ 2 ] ;
c . m_invwi [ 2 ] [ 1 ] = c . m_invwi [ 1 ] [ 2 ] ;
c . m_invwi = c . m_invwi . inverse ( ) ;
2017-08-01 14:30:58 +02:00
# endif
# endif
2019-01-03 14:26:51 +01:00
/* Velocities */
c . m_lv = btVector3 ( 0 , 0 , 0 ) ;
c . m_av = btVector3 ( 0 , 0 , 0 ) ;
2017-08-01 14:30:58 +02:00
{
int i ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < n ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 v = c . m_nodes [ i ] - > m_v * c . m_masses [ i ] ;
c . m_lv + = v ;
c . m_av + = btCross ( c . m_nodes [ i ] - > m_x - c . m_com , v ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
c . m_lv = c . m_imass * c . m_lv * ( 1 - c . m_ldamping ) ;
c . m_av = c . m_invwi * c . m_av * ( 1 - c . m_adamping ) ;
c . m_vimpulses [ 0 ] =
c . m_vimpulses [ 1 ] = btVector3 ( 0 , 0 , 0 ) ;
c . m_dimpulses [ 0 ] =
c . m_dimpulses [ 1 ] = btVector3 ( 0 , 0 , 0 ) ;
c . m_nvimpulses = 0 ;
c . m_ndimpulses = 0 ;
/* Matching */
if ( c . m_matching > 0 )
{
for ( int j = 0 ; j < c . m_nodes . size ( ) ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = * c . m_nodes [ j ] ;
const btVector3 x = c . m_framexform * c . m_framerefs [ j ] ;
n . m_x = Lerp ( n . m_x , x , c . m_matching ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
}
/* Dbvt */
if ( c . m_collide )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btVector3 mi = c . m_nodes [ 0 ] - > m_x ;
btVector3 mx = mi ;
for ( int j = 1 ; j < n ; + + j )
2017-08-01 14:30:58 +02:00
{
mi . setMin ( c . m_nodes [ j ] - > m_x ) ;
mx . setMax ( c . m_nodes [ j ] - > m_x ) ;
2019-01-03 14:26:51 +01:00
}
ATTRIBUTE_ALIGNED16 ( btDbvtVolume )
bounds = btDbvtVolume : : FromMM ( mi , mx ) ;
if ( c . m_leaf )
m_cdbvt . update ( c . m_leaf , bounds , c . m_lv * m_sst . sdt * 3 , m_sst . radmrg ) ;
2017-08-01 14:30:58 +02:00
else
2019-01-03 14:26:51 +01:00
c . m_leaf = m_cdbvt . insert ( bounds , & c ) ;
2017-08-01 14:30:58 +02:00
}
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : cleanupClusters ( )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < m_joints . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
m_joints [ i ] - > Terminate ( m_sst . sdt ) ;
2019-01-03 14:26:51 +01:00
if ( m_joints [ i ] - > m_delete )
2017-08-01 14:30:58 +02:00
{
btAlignedFree ( m_joints [ i ] ) ;
m_joints . remove ( m_joints [ i - - ] ) ;
2019-01-03 14:26:51 +01:00
}
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : prepareClusters ( int iterations )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < m_joints . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_joints [ i ] - > Prepare ( m_sst . sdt , iterations ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : solveClusters ( btScalar sor )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = m_joints . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_joints [ i ] - > Solve ( m_sst . sdt , sor ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : applyClusters ( bool drift )
2017-08-01 14:30:58 +02:00
{
BT_PROFILE ( " ApplyClusters " ) ;
2019-01-03 14:26:51 +01:00
// const btScalar f0=m_sst.sdt;
2017-08-01 14:30:58 +02:00
//const btScalar f1=f0/2;
btAlignedObjectArray < btVector3 > deltas ;
btAlignedObjectArray < btScalar > weights ;
2019-01-03 14:26:51 +01:00
deltas . resize ( m_nodes . size ( ) , btVector3 ( 0 , 0 , 0 ) ) ;
weights . resize ( m_nodes . size ( ) , 0 ) ;
2017-08-01 14:30:58 +02:00
int i ;
2019-01-03 14:26:51 +01:00
if ( drift )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Cluster & c = * m_clusters [ i ] ;
if ( c . m_ndimpulses )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
c . m_dimpulses [ 0 ] / = ( btScalar ) c . m_ndimpulses ;
c . m_dimpulses [ 1 ] / = ( btScalar ) c . m_ndimpulses ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Cluster & c = * m_clusters [ i ] ;
if ( 0 < ( drift ? c . m_ndimpulses : c . m_nvimpulses ) )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 v = ( drift ? c . m_dimpulses [ 0 ] : c . m_vimpulses [ 0 ] ) * m_sst . sdt ;
const btVector3 w = ( drift ? c . m_dimpulses [ 1 ] : c . m_vimpulses [ 1 ] ) * m_sst . sdt ;
for ( int j = 0 ; j < c . m_nodes . size ( ) ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const int idx = int ( c . m_nodes [ j ] - & m_nodes [ 0 ] ) ;
const btVector3 & x = c . m_nodes [ j ] - > m_x ;
const btScalar q = c . m_masses [ j ] ;
deltas [ idx ] + = ( v + btCross ( w , x - c . m_com ) ) * q ;
weights [ idx ] + = q ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < deltas . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( weights [ i ] > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_x + = deltas [ i ] / weights [ i ] ;
2017-08-01 14:30:58 +02:00
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : dampClusters ( )
2017-08-01 14:30:58 +02:00
{
int i ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < m_clusters . size ( ) ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Cluster & c = * m_clusters [ i ] ;
if ( c . m_ndamping > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < c . m_nodes . size ( ) ; + + j )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & n = * c . m_nodes [ j ] ;
if ( n . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 vx = c . m_lv + btCross ( c . m_av , c . m_nodes [ j ] - > m_q - c . m_com ) ;
if ( vx . length2 ( ) < = n . m_v . length2 ( ) )
{
n . m_v + = c . m_ndamping * ( vx - n . m_v ) ;
}
2017-08-01 14:30:58 +02:00
}
}
}
}
}
2020-01-08 18:05:43 +01:00
void btSoftBody : : setSpringStiffness ( btScalar k )
{
2021-09-29 15:47:08 +02:00
for ( int i = 0 ; i < m_links . size ( ) ; + + i )
{
m_links [ i ] . Feature : : m_material - > m_kLST = k ;
}
m_repulsionStiffness = k ;
}
void btSoftBody : : setGravityFactor ( btScalar gravFactor )
{
m_gravityFactor = gravFactor ;
}
void btSoftBody : : setCacheBarycenter ( bool cacheBarycenter )
{
m_cacheBarycenter = cacheBarycenter ;
2020-01-08 18:05:43 +01:00
}
void btSoftBody : : initializeDmInverse ( )
{
2021-09-29 15:47:08 +02:00
btScalar unit_simplex_measure = 1. / 6. ;
for ( int i = 0 ; i < m_tetras . size ( ) ; + + i )
{
Tetra & t = m_tetras [ i ] ;
btVector3 c1 = t . m_n [ 1 ] - > m_x - t . m_n [ 0 ] - > m_x ;
btVector3 c2 = t . m_n [ 2 ] - > m_x - t . m_n [ 0 ] - > m_x ;
btVector3 c3 = t . m_n [ 3 ] - > m_x - t . m_n [ 0 ] - > m_x ;
btMatrix3x3 Dm ( c1 . getX ( ) , c2 . getX ( ) , c3 . getX ( ) ,
c1 . getY ( ) , c2 . getY ( ) , c3 . getY ( ) ,
c1 . getZ ( ) , c2 . getZ ( ) , c3 . getZ ( ) ) ;
t . m_element_measure = Dm . determinant ( ) * unit_simplex_measure ;
t . m_Dm_inverse = Dm . inverse ( ) ;
// calculate the first three columns of P^{-1}
btVector3 a = t . m_n [ 0 ] - > m_x ;
btVector3 b = t . m_n [ 1 ] - > m_x ;
btVector3 c = t . m_n [ 2 ] - > m_x ;
btVector3 d = t . m_n [ 3 ] - > m_x ;
btScalar det = 1 / ( a [ 0 ] * b [ 1 ] * c [ 2 ] - a [ 0 ] * b [ 1 ] * d [ 2 ] - a [ 0 ] * b [ 2 ] * c [ 1 ] + a [ 0 ] * b [ 2 ] * d [ 1 ] + a [ 0 ] * c [ 1 ] * d [ 2 ] - a [ 0 ] * c [ 2 ] * d [ 1 ] + a [ 1 ] * ( - b [ 0 ] * c [ 2 ] + b [ 0 ] * d [ 2 ] + b [ 2 ] * c [ 0 ] - b [ 2 ] * d [ 0 ] - c [ 0 ] * d [ 2 ] + c [ 2 ] * d [ 0 ] ) + a [ 2 ] * ( b [ 0 ] * c [ 1 ] - b [ 0 ] * d [ 1 ] + b [ 1 ] * ( d [ 0 ] - c [ 0 ] ) + c [ 0 ] * d [ 1 ] - c [ 1 ] * d [ 0 ] ) - b [ 0 ] * c [ 1 ] * d [ 2 ] + b [ 0 ] * c [ 2 ] * d [ 1 ] + b [ 1 ] * c [ 0 ] * d [ 2 ] - b [ 1 ] * c [ 2 ] * d [ 0 ] - b [ 2 ] * c [ 0 ] * d [ 1 ] + b [ 2 ] * c [ 1 ] * d [ 0 ] ) ;
btScalar P11 = - b [ 2 ] * c [ 1 ] + d [ 2 ] * c [ 1 ] + b [ 1 ] * c [ 2 ] + b [ 2 ] * d [ 1 ] - c [ 2 ] * d [ 1 ] - b [ 1 ] * d [ 2 ] ;
btScalar P12 = b [ 2 ] * c [ 0 ] - d [ 2 ] * c [ 0 ] - b [ 0 ] * c [ 2 ] - b [ 2 ] * d [ 0 ] + c [ 2 ] * d [ 0 ] + b [ 0 ] * d [ 2 ] ;
btScalar P13 = - b [ 1 ] * c [ 0 ] + d [ 1 ] * c [ 0 ] + b [ 0 ] * c [ 1 ] + b [ 1 ] * d [ 0 ] - c [ 1 ] * d [ 0 ] - b [ 0 ] * d [ 1 ] ;
btScalar P21 = a [ 2 ] * c [ 1 ] - d [ 2 ] * c [ 1 ] - a [ 1 ] * c [ 2 ] - a [ 2 ] * d [ 1 ] + c [ 2 ] * d [ 1 ] + a [ 1 ] * d [ 2 ] ;
btScalar P22 = - a [ 2 ] * c [ 0 ] + d [ 2 ] * c [ 0 ] + a [ 0 ] * c [ 2 ] + a [ 2 ] * d [ 0 ] - c [ 2 ] * d [ 0 ] - a [ 0 ] * d [ 2 ] ;
btScalar P23 = a [ 1 ] * c [ 0 ] - d [ 1 ] * c [ 0 ] - a [ 0 ] * c [ 1 ] - a [ 1 ] * d [ 0 ] + c [ 1 ] * d [ 0 ] + a [ 0 ] * d [ 1 ] ;
btScalar P31 = - a [ 2 ] * b [ 1 ] + d [ 2 ] * b [ 1 ] + a [ 1 ] * b [ 2 ] + a [ 2 ] * d [ 1 ] - b [ 2 ] * d [ 1 ] - a [ 1 ] * d [ 2 ] ;
btScalar P32 = a [ 2 ] * b [ 0 ] - d [ 2 ] * b [ 0 ] - a [ 0 ] * b [ 2 ] - a [ 2 ] * d [ 0 ] + b [ 2 ] * d [ 0 ] + a [ 0 ] * d [ 2 ] ;
btScalar P33 = - a [ 1 ] * b [ 0 ] + d [ 1 ] * b [ 0 ] + a [ 0 ] * b [ 1 ] + a [ 1 ] * d [ 0 ] - b [ 1 ] * d [ 0 ] - a [ 0 ] * d [ 1 ] ;
btScalar P41 = a [ 2 ] * b [ 1 ] - c [ 2 ] * b [ 1 ] - a [ 1 ] * b [ 2 ] - a [ 2 ] * c [ 1 ] + b [ 2 ] * c [ 1 ] + a [ 1 ] * c [ 2 ] ;
btScalar P42 = - a [ 2 ] * b [ 0 ] + c [ 2 ] * b [ 0 ] + a [ 0 ] * b [ 2 ] + a [ 2 ] * c [ 0 ] - b [ 2 ] * c [ 0 ] - a [ 0 ] * c [ 2 ] ;
btScalar P43 = a [ 1 ] * b [ 0 ] - c [ 1 ] * b [ 0 ] - a [ 0 ] * b [ 1 ] - a [ 1 ] * c [ 0 ] + b [ 1 ] * c [ 0 ] + a [ 0 ] * c [ 1 ] ;
btVector4 p1 ( P11 * det , P21 * det , P31 * det , P41 * det ) ;
btVector4 p2 ( P12 * det , P22 * det , P32 * det , P42 * det ) ;
btVector4 p3 ( P13 * det , P23 * det , P33 * det , P43 * det ) ;
t . m_P_inv [ 0 ] = p1 ;
t . m_P_inv [ 1 ] = p2 ;
t . m_P_inv [ 2 ] = p3 ;
}
}
static btScalar Dot4 ( const btVector4 & a , const btVector4 & b )
{
return a [ 0 ] * b [ 0 ] + a [ 1 ] * b [ 1 ] + a [ 2 ] * b [ 2 ] + a [ 3 ] * b [ 3 ] ;
2020-01-08 18:05:43 +01:00
}
void btSoftBody : : updateDeformation ( )
{
2021-09-29 15:47:08 +02:00
btQuaternion q ;
for ( int i = 0 ; i < m_tetras . size ( ) ; + + i )
{
btSoftBody : : Tetra & t = m_tetras [ i ] ;
btVector3 c1 = t . m_n [ 1 ] - > m_q - t . m_n [ 0 ] - > m_q ;
btVector3 c2 = t . m_n [ 2 ] - > m_q - t . m_n [ 0 ] - > m_q ;
btVector3 c3 = t . m_n [ 3 ] - > m_q - t . m_n [ 0 ] - > m_q ;
btMatrix3x3 Ds ( c1 . getX ( ) , c2 . getX ( ) , c3 . getX ( ) ,
c1 . getY ( ) , c2 . getY ( ) , c3 . getY ( ) ,
c1 . getZ ( ) , c2 . getZ ( ) , c3 . getZ ( ) ) ;
t . m_F = Ds * t . m_Dm_inverse ;
btSoftBody : : TetraScratch & s = m_tetraScratches [ i ] ;
s . m_F = t . m_F ;
s . m_J = t . m_F . determinant ( ) ;
btMatrix3x3 C = t . m_F . transpose ( ) * t . m_F ;
s . m_trace = C [ 0 ] . getX ( ) + C [ 1 ] . getY ( ) + C [ 2 ] . getZ ( ) ;
s . m_cofF = t . m_F . adjoint ( ) . transpose ( ) ;
btVector3 a = t . m_n [ 0 ] - > m_q ;
btVector3 b = t . m_n [ 1 ] - > m_q ;
btVector3 c = t . m_n [ 2 ] - > m_q ;
btVector3 d = t . m_n [ 3 ] - > m_q ;
btVector4 q1 ( a [ 0 ] , b [ 0 ] , c [ 0 ] , d [ 0 ] ) ;
btVector4 q2 ( a [ 1 ] , b [ 1 ] , c [ 1 ] , d [ 1 ] ) ;
btVector4 q3 ( a [ 2 ] , b [ 2 ] , c [ 2 ] , d [ 2 ] ) ;
btMatrix3x3 B ( Dot4 ( q1 , t . m_P_inv [ 0 ] ) , Dot4 ( q1 , t . m_P_inv [ 1 ] ) , Dot4 ( q1 , t . m_P_inv [ 2 ] ) ,
Dot4 ( q2 , t . m_P_inv [ 0 ] ) , Dot4 ( q2 , t . m_P_inv [ 1 ] ) , Dot4 ( q2 , t . m_P_inv [ 2 ] ) ,
Dot4 ( q3 , t . m_P_inv [ 0 ] ) , Dot4 ( q3 , t . m_P_inv [ 1 ] ) , Dot4 ( q3 , t . m_P_inv [ 2 ] ) ) ;
q . setRotation ( btVector3 ( 0 , 0 , 1 ) , 0 ) ;
B . extractRotation ( q , 0.01 ) ; // precision of the rotation is not very important for visual correctness.
btMatrix3x3 Q ( q ) ;
s . m_corotation = Q ;
}
2020-01-08 18:05:43 +01:00
}
void btSoftBody : : advanceDeformation ( )
{
2021-09-29 15:47:08 +02:00
updateDeformation ( ) ;
for ( int i = 0 ; i < m_tetras . size ( ) ; + + i )
{
m_tetraScratchesTn [ i ] = m_tetraScratches [ i ] ;
}
2020-01-08 18:05:43 +01:00
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : Joint : : Prepare ( btScalar dt , int )
2017-08-01 14:30:58 +02:00
{
m_bodies [ 0 ] . activate ( ) ;
m_bodies [ 1 ] . activate ( ) ;
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : LJoint : : Prepare ( btScalar dt , int iterations )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
static const btScalar maxdrift = 4 ;
Joint : : Prepare ( dt , iterations ) ;
m_rpos [ 0 ] = m_bodies [ 0 ] . xform ( ) * m_refs [ 0 ] ;
m_rpos [ 1 ] = m_bodies [ 1 ] . xform ( ) * m_refs [ 1 ] ;
m_drift = Clamp ( m_rpos [ 0 ] - m_rpos [ 1 ] , maxdrift ) * m_erp / dt ;
m_rpos [ 0 ] - = m_bodies [ 0 ] . xform ( ) . getOrigin ( ) ;
m_rpos [ 1 ] - = m_bodies [ 1 ] . xform ( ) . getOrigin ( ) ;
m_massmatrix = ImpulseMatrix ( m_bodies [ 0 ] . invMass ( ) , m_bodies [ 0 ] . invWorldInertia ( ) , m_rpos [ 0 ] ,
m_bodies [ 1 ] . invMass ( ) , m_bodies [ 1 ] . invWorldInertia ( ) , m_rpos [ 1 ] ) ;
if ( m_split > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_sdrift = m_massmatrix * ( m_drift * m_split ) ;
m_drift * = 1 - m_split ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
m_drift / = ( btScalar ) iterations ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : LJoint : : Solve ( btScalar dt , btScalar sor )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 va = m_bodies [ 0 ] . velocity ( m_rpos [ 0 ] ) ;
const btVector3 vb = m_bodies [ 1 ] . velocity ( m_rpos [ 1 ] ) ;
const btVector3 vr = va - vb ;
btSoftBody : : Impulse impulse ;
impulse . m_asVelocity = 1 ;
impulse . m_velocity = m_massmatrix * ( m_drift + vr * m_cfm ) * sor ;
m_bodies [ 0 ] . applyImpulse ( - impulse , m_rpos [ 0 ] ) ;
m_bodies [ 1 ] . applyImpulse ( impulse , m_rpos [ 1 ] ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : LJoint : : Terminate ( btScalar dt )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_split > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_bodies [ 0 ] . applyDImpulse ( - m_sdrift , m_rpos [ 0 ] ) ;
m_bodies [ 1 ] . applyDImpulse ( m_sdrift , m_rpos [ 1 ] ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : AJoint : : Prepare ( btScalar dt , int iterations )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
static const btScalar maxdrift = SIMD_PI / 16 ;
2017-08-01 14:30:58 +02:00
m_icontrol - > Prepare ( this ) ;
2019-01-03 14:26:51 +01:00
Joint : : Prepare ( dt , iterations ) ;
m_axis [ 0 ] = m_bodies [ 0 ] . xform ( ) . getBasis ( ) * m_refs [ 0 ] ;
m_axis [ 1 ] = m_bodies [ 1 ] . xform ( ) . getBasis ( ) * m_refs [ 1 ] ;
m_drift = NormalizeAny ( btCross ( m_axis [ 1 ] , m_axis [ 0 ] ) ) ;
m_drift * = btMin ( maxdrift , btAcos ( Clamp < btScalar > ( btDot ( m_axis [ 0 ] , m_axis [ 1 ] ) , - 1 , + 1 ) ) ) ;
m_drift * = m_erp / dt ;
m_massmatrix = AngularImpulseMatrix ( m_bodies [ 0 ] . invWorldInertia ( ) , m_bodies [ 1 ] . invWorldInertia ( ) ) ;
if ( m_split > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_sdrift = m_massmatrix * ( m_drift * m_split ) ;
m_drift * = 1 - m_split ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
m_drift / = ( btScalar ) iterations ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : AJoint : : Solve ( btScalar dt , btScalar sor )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 va = m_bodies [ 0 ] . angularVelocity ( ) ;
const btVector3 vb = m_bodies [ 1 ] . angularVelocity ( ) ;
const btVector3 vr = va - vb ;
const btScalar sp = btDot ( vr , m_axis [ 0 ] ) ;
const btVector3 vc = vr - m_axis [ 0 ] * m_icontrol - > Speed ( this , sp ) ;
btSoftBody : : Impulse impulse ;
impulse . m_asVelocity = 1 ;
impulse . m_velocity = m_massmatrix * ( m_drift + vc * m_cfm ) * sor ;
2017-08-01 14:30:58 +02:00
m_bodies [ 0 ] . applyAImpulse ( - impulse ) ;
2019-01-03 14:26:51 +01:00
m_bodies [ 1 ] . applyAImpulse ( impulse ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : AJoint : : Terminate ( btScalar dt )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_split > 0 )
2017-08-01 14:30:58 +02:00
{
m_bodies [ 0 ] . applyDAImpulse ( - m_sdrift ) ;
2019-01-03 14:26:51 +01:00
m_bodies [ 1 ] . applyDAImpulse ( m_sdrift ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : CJoint : : Prepare ( btScalar dt , int iterations )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Joint : : Prepare ( dt , iterations ) ;
const bool dodrift = ( m_life = = 0 ) ;
m_delete = ( + + m_life ) > m_maxlife ;
if ( dodrift )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_drift = m_drift * m_erp / dt ;
if ( m_split > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_sdrift = m_massmatrix * ( m_drift * m_split ) ;
m_drift * = 1 - m_split ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
m_drift / = ( btScalar ) iterations ;
2017-08-01 14:30:58 +02:00
}
else
{
2019-01-03 14:26:51 +01:00
m_drift = m_sdrift = btVector3 ( 0 , 0 , 0 ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : CJoint : : Solve ( btScalar dt , btScalar sor )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 va = m_bodies [ 0 ] . velocity ( m_rpos [ 0 ] ) ;
const btVector3 vb = m_bodies [ 1 ] . velocity ( m_rpos [ 1 ] ) ;
const btVector3 vrel = va - vb ;
const btScalar rvac = btDot ( vrel , m_normal ) ;
btSoftBody : : Impulse impulse ;
impulse . m_asVelocity = 1 ;
impulse . m_velocity = m_drift ;
if ( rvac < 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btVector3 iv = m_normal * rvac ;
const btVector3 fv = vrel - iv ;
impulse . m_velocity + = iv + fv * m_friction ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
impulse . m_velocity = m_massmatrix * impulse . m_velocity * sor ;
if ( m_bodies [ 0 ] . m_soft = = m_bodies [ 1 ] . m_soft )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( ( impulse . m_velocity . getX ( ) = = impulse . m_velocity . getX ( ) ) & & ( impulse . m_velocity . getY ( ) = = impulse . m_velocity . getY ( ) ) & &
( impulse . m_velocity . getZ ( ) = = impulse . m_velocity . getZ ( ) ) )
2017-08-01 14:30:58 +02:00
{
if ( impulse . m_asVelocity )
{
2019-01-03 14:26:51 +01:00
if ( impulse . m_velocity . length ( ) < m_bodies [ 0 ] . m_soft - > m_maxSelfCollisionImpulse )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_bodies [ 0 ] . applyImpulse ( - impulse * m_bodies [ 0 ] . m_soft - > m_selfCollisionImpulseFactor , m_rpos [ 0 ] ) ;
m_bodies [ 1 ] . applyImpulse ( impulse * m_bodies [ 0 ] . m_soft - > m_selfCollisionImpulseFactor , m_rpos [ 1 ] ) ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_bodies [ 0 ] . applyImpulse ( - impulse , m_rpos [ 0 ] ) ;
m_bodies [ 1 ] . applyImpulse ( impulse , m_rpos [ 1 ] ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : CJoint : : Terminate ( btScalar dt )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( m_split > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_bodies [ 0 ] . applyDImpulse ( - m_sdrift , m_rpos [ 0 ] ) ;
m_bodies [ 1 ] . applyDImpulse ( m_sdrift , m_rpos [ 1 ] ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : applyForces ( )
2017-08-01 14:30:58 +02:00
{
BT_PROFILE ( " SoftBody applyForces " ) ;
2019-01-03 14:26:51 +01:00
// const btScalar dt = m_sst.sdt;
const btScalar kLF = m_cfg . kLF ;
const btScalar kDG = m_cfg . kDG ;
const btScalar kPR = m_cfg . kPR ;
const btScalar kVC = m_cfg . kVC ;
const bool as_lift = kLF > 0 ;
const bool as_drag = kDG > 0 ;
const bool as_pressure = kPR ! = 0 ;
const bool as_volume = kVC > 0 ;
const bool as_aero = as_lift | |
as_drag ;
2017-08-01 14:30:58 +02:00
//const bool as_vaero = as_aero &&
// (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
//const bool as_faero = as_aero &&
// (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
2019-01-03 14:26:51 +01:00
const bool use_medium = as_aero ;
const bool use_volume = as_pressure | |
as_volume ;
btScalar volume = 0 ;
btScalar ivolumetp = 0 ;
btScalar dvolumetv = 0 ;
btSoftBody : : sMedium medium ;
if ( use_volume )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
volume = getVolume ( ) ;
ivolumetp = 1 / btFabs ( volume ) * kPR ;
dvolumetv = ( m_pose . m_volume - volume ) * kVC ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Per vertex forces */
int i , ni ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
for ( i = 0 , ni = m_nodes . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBody : : Node & n = m_nodes [ i ] ;
if ( n . m_im > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
if ( use_medium )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
/* Aerodynamics */
2017-08-01 14:30:58 +02:00
addAeroForceToNode ( m_windVelocity , i ) ;
}
2019-01-03 14:26:51 +01:00
/* Pressure */
if ( as_pressure )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
n . m_f + = n . m_n * ( n . m_area * ivolumetp ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
/* Volume */
if ( as_volume )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
n . m_f + = n . m_n * ( n . m_area * dvolumetv ) ;
2017-08-01 14:30:58 +02:00
}
}
}
2019-01-03 14:26:51 +01:00
/* Per face forces */
for ( i = 0 , ni = m_faces . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
// btSoftBody::Face& f=m_faces[i];
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
/* Aerodynamics */
addAeroForceToFace ( m_windVelocity , i ) ;
2017-08-01 14:30:58 +02:00
}
}
2020-01-08 18:05:43 +01:00
//
void btSoftBody : : setMaxStress ( btScalar maxStress )
{
2021-09-29 15:47:08 +02:00
m_cfg . m_maxStress = maxStress ;
2020-01-08 18:05:43 +01:00
}
//
void btSoftBody : : interpolateRenderMesh ( )
{
2021-09-29 15:47:08 +02:00
if ( m_z . size ( ) > 0 )
{
for ( int i = 0 ; i < m_renderNodes . size ( ) ; + + i )
{
const Node * p0 = m_renderNodesParents [ i ] [ 0 ] ;
const Node * p1 = m_renderNodesParents [ i ] [ 1 ] ;
const Node * p2 = m_renderNodesParents [ i ] [ 2 ] ;
btVector3 normal = btCross ( p1 - > m_x - p0 - > m_x , p2 - > m_x - p0 - > m_x ) ;
btVector3 unit_normal = normal . normalized ( ) ;
RenderNode & n = m_renderNodes [ i ] ;
n . m_x . setZero ( ) ;
for ( int j = 0 ; j < 3 ; + + j )
2020-01-08 18:05:43 +01:00
{
n . m_x + = m_renderNodesParents [ i ] [ j ] - > m_x * m_renderNodesInterpolationWeights [ i ] [ j ] ;
}
2021-09-29 15:47:08 +02:00
n . m_x + = m_z [ i ] * unit_normal ;
}
}
else
{
for ( int i = 0 ; i < m_renderNodes . size ( ) ; + + i )
{
RenderNode & n = m_renderNodes [ i ] ;
n . m_x . setZero ( ) ;
for ( int j = 0 ; j < 4 ; + + j )
{
if ( m_renderNodesParents [ i ] . size ( ) )
{
n . m_x + = m_renderNodesParents [ i ] [ j ] - > m_x * m_renderNodesInterpolationWeights [ i ] [ j ] ;
}
}
}
}
2020-01-08 18:05:43 +01:00
}
void btSoftBody : : setCollisionQuadrature ( int N )
{
2021-09-29 15:47:08 +02:00
for ( int i = 0 ; i < = N ; + + i )
{
for ( int j = 0 ; i + j < = N ; + + j )
{
m_quads . push_back ( btVector3 ( btScalar ( i ) / btScalar ( N ) , btScalar ( j ) / btScalar ( N ) , btScalar ( N - i - j ) / btScalar ( N ) ) ) ;
}
}
2020-01-08 18:05:43 +01:00
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : PSolve_Anchors ( btSoftBody * psb , btScalar kst , btScalar ti )
2017-08-01 14:30:58 +02:00
{
BT_PROFILE ( " PSolve_Anchors " ) ;
2019-01-03 14:26:51 +01:00
const btScalar kAHR = psb - > m_cfg . kAHR * kst ;
const btScalar dt = psb - > m_sst . sdt ;
for ( int i = 0 , ni = psb - > m_anchors . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const Anchor & a = psb - > m_anchors [ i ] ;
const btTransform & t = a . m_body - > getWorldTransform ( ) ;
Node & n = * a . m_node ;
const btVector3 wa = t * a . m_local ;
const btVector3 va = a . m_body - > getVelocityInLocalPoint ( a . m_c1 ) * dt ;
const btVector3 vb = n . m_x - n . m_q ;
const btVector3 vr = ( va - vb ) + ( wa - n . m_x ) * kAHR ;
const btVector3 impulse = a . m_c0 * vr * a . m_influence ;
n . m_x + = impulse * a . m_c2 ;
a . m_body - > applyImpulse ( - impulse , a . m_c1 ) ;
2017-08-01 14:30:58 +02:00
}
}
//
void btSoftBody : : PSolve_RContacts ( btSoftBody * psb , btScalar kst , btScalar ti )
{
BT_PROFILE ( " PSolve_RContacts " ) ;
2019-01-03 14:26:51 +01:00
const btScalar dt = psb - > m_sst . sdt ;
const btScalar mrg = psb - > getCollisionShape ( ) - > getMargin ( ) ;
2017-08-01 14:30:58 +02:00
btMultiBodyJacobianData jacobianData ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = psb - > m_rcontacts . size ( ) ; i < ni ; + + i )
{
const RContact & c = psb - > m_rcontacts [ i ] ;
const sCti & cti = c . m_cti ;
if ( cti . m_colObj - > hasContactResponse ( ) )
{
btVector3 va ( 0 , 0 , 0 ) ;
btRigidBody * rigidCol = 0 ;
btMultiBodyLinkCollider * multibodyLinkCol = 0 ;
2022-05-17 00:02:51 +02:00
btScalar * deltaV = NULL ;
2019-01-03 14:26:51 +01:00
if ( cti . m_colObj - > getInternalType ( ) = = btCollisionObject : : CO_RIGID_BODY )
{
rigidCol = ( btRigidBody * ) btRigidBody : : upcast ( cti . m_colObj ) ;
va = rigidCol ? rigidCol - > getVelocityInLocalPoint ( c . m_c1 ) * dt : btVector3 ( 0 , 0 , 0 ) ;
}
2017-08-01 14:30:58 +02:00
else if ( cti . m_colObj - > getInternalType ( ) = = btCollisionObject : : CO_FEATHERSTONE_LINK )
2019-01-03 14:26:51 +01:00
{
multibodyLinkCol = ( btMultiBodyLinkCollider * ) btMultiBodyLinkCollider : : upcast ( cti . m_colObj ) ;
if ( multibodyLinkCol )
{
const int ndof = multibodyLinkCol - > m_multiBody - > getNumDofs ( ) + 6 ;
jacobianData . m_jacobians . resize ( ndof ) ;
jacobianData . m_deltaVelocitiesUnitImpulse . resize ( ndof ) ;
btScalar * jac = & jacobianData . m_jacobians [ 0 ] ;
multibodyLinkCol - > m_multiBody - > fillContactJacobianMultiDof ( multibodyLinkCol - > m_link , c . m_node - > m_x , cti . m_normal , jac , jacobianData . scratch_r , jacobianData . scratch_v , jacobianData . scratch_m ) ;
deltaV = & jacobianData . m_deltaVelocitiesUnitImpulse [ 0 ] ;
multibodyLinkCol - > m_multiBody - > calcAccelerationDeltasMultiDof ( & jacobianData . m_jacobians [ 0 ] , deltaV , jacobianData . scratch_r , jacobianData . scratch_v ) ;
btScalar vel = 0.0 ;
for ( int j = 0 ; j < ndof ; + + j )
{
vel + = multibodyLinkCol - > m_multiBody - > getVelocityVector ( ) [ j ] * jac [ j ] ;
}
va = cti . m_normal * vel * dt ;
}
}
const btVector3 vb = c . m_node - > m_x - c . m_node - > m_q ;
const btVector3 vr = vb - va ;
const btScalar dn = btDot ( vr , cti . m_normal ) ;
if ( dn < = SIMD_EPSILON )
{
const btScalar dp = btMin ( ( btDot ( c . m_node - > m_x , cti . m_normal ) + cti . m_offset ) , mrg ) ;
const btVector3 fv = vr - ( cti . m_normal * dn ) ;
2017-08-01 14:30:58 +02:00
// c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
2019-01-03 14:26:51 +01:00
const btVector3 impulse = c . m_c0 * ( ( vr - ( fv * c . m_c3 ) + ( cti . m_normal * ( dp * c . m_c4 ) ) ) * kst ) ;
2017-08-01 14:30:58 +02:00
c . m_node - > m_x - = impulse * c . m_c2 ;
2019-01-03 14:26:51 +01:00
if ( cti . m_colObj - > getInternalType ( ) = = btCollisionObject : : CO_RIGID_BODY )
{
if ( rigidCol )
rigidCol - > applyImpulse ( impulse , c . m_c1 ) ;
}
else if ( cti . m_colObj - > getInternalType ( ) = = btCollisionObject : : CO_FEATHERSTONE_LINK )
{
if ( multibodyLinkCol )
{
double multiplier = 0.5 ;
multibodyLinkCol - > m_multiBody - > applyDeltaVeeMultiDof ( deltaV , - impulse . length ( ) * multiplier ) ;
}
}
2017-08-01 14:30:58 +02:00
}
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : PSolve_SContacts ( btSoftBody * psb , btScalar , btScalar ti )
2017-08-01 14:30:58 +02:00
{
BT_PROFILE ( " PSolve_SContacts " ) ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = psb - > m_scontacts . size ( ) ; i < ni ; + + i )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const SContact & c = psb - > m_scontacts [ i ] ;
const btVector3 & nr = c . m_normal ;
Node & n = * c . m_node ;
Face & f = * c . m_face ;
const btVector3 p = BaryEval ( f . m_n [ 0 ] - > m_x ,
f . m_n [ 1 ] - > m_x ,
f . m_n [ 2 ] - > m_x ,
c . m_weights ) ;
const btVector3 q = BaryEval ( f . m_n [ 0 ] - > m_q ,
f . m_n [ 1 ] - > m_q ,
f . m_n [ 2 ] - > m_q ,
c . m_weights ) ;
const btVector3 vr = ( n . m_x - n . m_q ) - ( p - q ) ;
btVector3 corr ( 0 , 0 , 0 ) ;
btScalar dot = btDot ( vr , nr ) ;
if ( dot < 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar j = c . m_margin - ( btDot ( nr , n . m_x ) - btDot ( nr , p ) ) ;
corr + = c . m_normal * j ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
corr - = ProjectOnPlane ( vr , nr ) * c . m_friction ;
n . m_x + = corr * c . m_cfm [ 0 ] ;
f . m_n [ 0 ] - > m_x - = corr * ( c . m_cfm [ 1 ] * c . m_weights . x ( ) ) ;
f . m_n [ 1 ] - > m_x - = corr * ( c . m_cfm [ 1 ] * c . m_weights . y ( ) ) ;
f . m_n [ 2 ] - > m_x - = corr * ( c . m_cfm [ 1 ] * c . m_weights . z ( ) ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : PSolve_Links ( btSoftBody * psb , btScalar kst , btScalar ti )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
BT_PROFILE ( " PSolve_Links " ) ;
for ( int i = 0 , ni = psb - > m_links . size ( ) ; i < ni ; + + i )
{
Link & l = psb - > m_links [ i ] ;
if ( l . m_c0 > 0 )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
Node & a = * l . m_n [ 0 ] ;
Node & b = * l . m_n [ 1 ] ;
const btVector3 del = b . m_x - a . m_x ;
const btScalar len = del . length2 ( ) ;
if ( l . m_c1 + len > SIMD_EPSILON )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
const btScalar k = ( ( l . m_c1 - len ) / ( l . m_c0 * ( l . m_c1 + len ) ) ) * kst ;
a . m_x - = del * ( k * a . m_im ) ;
b . m_x + = del * ( k * b . m_im ) ;
2017-08-01 14:30:58 +02:00
}
}
}
}
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : VSolve_Links ( btSoftBody * psb , btScalar kst )
2017-08-01 14:30:58 +02:00
{
BT_PROFILE ( " VSolve_Links " ) ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 , ni = psb - > m_links . size ( ) ; i < ni ; + + i )
{
Link & l = psb - > m_links [ i ] ;
Node * * n = l . m_n ;
const btScalar j = - btDot ( l . m_c3 , n [ 0 ] - > m_v - n [ 1 ] - > m_v ) * l . m_c2 * kst ;
n [ 0 ] - > m_v + = l . m_c3 * ( j * n [ 0 ] - > m_im ) ;
n [ 1 ] - > m_v - = l . m_c3 * ( j * n [ 1 ] - > m_im ) ;
2017-08-01 14:30:58 +02:00
}
}
//
2019-01-03 14:26:51 +01:00
btSoftBody : : psolver_t btSoftBody : : getSolver ( ePSolver : : _ solver )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
switch ( solver )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
case ePSolver : : Anchors :
return ( & btSoftBody : : PSolve_Anchors ) ;
case ePSolver : : Linear :
return ( & btSoftBody : : PSolve_Links ) ;
case ePSolver : : RContacts :
return ( & btSoftBody : : PSolve_RContacts ) ;
case ePSolver : : SContacts :
return ( & btSoftBody : : PSolve_SContacts ) ;
2017-08-01 14:30:58 +02:00
default :
{
}
}
2019-01-03 14:26:51 +01:00
return ( 0 ) ;
2017-08-01 14:30:58 +02:00
}
//
2019-01-03 14:26:51 +01:00
btSoftBody : : vsolver_t btSoftBody : : getSolver ( eVSolver : : _ solver )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
switch ( solver )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
case eVSolver : : Linear :
return ( & btSoftBody : : VSolve_Links ) ;
2017-08-01 14:30:58 +02:00
default :
{
}
}
2019-01-03 14:26:51 +01:00
return ( 0 ) ;
2017-08-01 14:30:58 +02:00
}
2020-01-08 18:05:43 +01:00
void btSoftBody : : setSelfCollision ( bool useSelfCollision )
{
2021-09-29 15:47:08 +02:00
m_useSelfCollision = useSelfCollision ;
2020-01-08 18:05:43 +01:00
}
bool btSoftBody : : useSelfCollision ( )
{
2021-09-29 15:47:08 +02:00
return m_useSelfCollision ;
2020-01-08 18:05:43 +01:00
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : defaultCollisionHandler ( const btCollisionObjectWrapper * pcoWrap )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
switch ( m_cfg . collisions & fCollision : : RVSmask )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
case fCollision : : SDF_RS :
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftColliders : : CollideSDF_RS docollide ;
btRigidBody * prb1 = ( btRigidBody * ) btRigidBody : : upcast ( pcoWrap - > getCollisionObject ( ) ) ;
btTransform wtr = pcoWrap - > getWorldTransform ( ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
const btTransform ctr = pcoWrap - > getWorldTransform ( ) ;
const btScalar timemargin = ( wtr . getOrigin ( ) - ctr . getOrigin ( ) ) . length ( ) ;
const btScalar basemargin = getCollisionShape ( ) - > getMargin ( ) ;
btVector3 mins ;
btVector3 maxs ;
ATTRIBUTE_ALIGNED16 ( btDbvtVolume )
volume ;
pcoWrap - > getCollisionShape ( ) - > getAabb ( pcoWrap - > getWorldTransform ( ) ,
mins ,
maxs ) ;
volume = btDbvtVolume : : FromMM ( mins , maxs ) ;
volume . Expand ( btVector3 ( basemargin , basemargin , basemargin ) ) ;
docollide . psb = this ;
2017-08-01 14:30:58 +02:00
docollide . m_colObj1Wrap = pcoWrap ;
docollide . m_rigidBody = prb1 ;
2019-01-03 14:26:51 +01:00
docollide . dynmargin = basemargin + timemargin ;
docollide . stamargin = basemargin ;
m_ndbvt . collideTV ( m_ndbvt . m_root , volume , docollide ) ;
2017-08-01 14:30:58 +02:00
}
break ;
2019-01-03 14:26:51 +01:00
case fCollision : : CL_RS :
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftColliders : : CollideCL_RS collider ;
collider . ProcessColObj ( this , pcoWrap ) ;
2017-08-01 14:30:58 +02:00
}
break ;
2021-09-29 15:47:08 +02:00
case fCollision : : SDF_RD :
{
btRigidBody * prb1 = ( btRigidBody * ) btRigidBody : : upcast ( pcoWrap - > getCollisionObject ( ) ) ;
2022-01-06 23:37:49 +01:00
if ( this - > isActive ( ) )
2021-09-29 15:47:08 +02:00
{
const btTransform wtr = pcoWrap - > getWorldTransform ( ) ;
const btScalar timemargin = 0 ;
const btScalar basemargin = getCollisionShape ( ) - > getMargin ( ) ;
btVector3 mins ;
btVector3 maxs ;
ATTRIBUTE_ALIGNED16 ( btDbvtVolume )
volume ;
pcoWrap - > getCollisionShape ( ) - > getAabb ( wtr ,
mins ,
maxs ) ;
volume = btDbvtVolume : : FromMM ( mins , maxs ) ;
volume . Expand ( btVector3 ( basemargin , basemargin , basemargin ) ) ;
if ( m_cfg . collisions & fCollision : : SDF_RDN )
{
btSoftColliders : : CollideSDF_RD docollideNode ;
docollideNode . psb = this ;
docollideNode . m_colObj1Wrap = pcoWrap ;
docollideNode . m_rigidBody = prb1 ;
docollideNode . dynmargin = basemargin + timemargin ;
docollideNode . stamargin = basemargin ;
m_ndbvt . collideTV ( m_ndbvt . m_root , volume , docollideNode ) ;
}
2017-08-01 14:30:58 +02:00
2021-09-29 15:47:08 +02:00
if ( ( ( pcoWrap - > getCollisionObject ( ) - > getInternalType ( ) = = CO_RIGID_BODY ) & & ( m_cfg . collisions & fCollision : : SDF_RDF ) ) | | ( ( pcoWrap - > getCollisionObject ( ) - > getInternalType ( ) = = CO_FEATHERSTONE_LINK ) & & ( m_cfg . collisions & fCollision : : SDF_MDF ) ) )
{
btSoftColliders : : CollideSDF_RDF docollideFace ;
docollideFace . psb = this ;
docollideFace . m_colObj1Wrap = pcoWrap ;
docollideFace . m_rigidBody = prb1 ;
docollideFace . dynmargin = basemargin + timemargin ;
docollideFace . stamargin = basemargin ;
m_fdbvt . collideTV ( m_fdbvt . m_root , volume , docollideFace ) ;
}
}
}
break ;
}
2020-01-08 18:05:43 +01:00
}
2017-08-01 14:30:58 +02:00
//
2019-01-03 14:26:51 +01:00
void btSoftBody : : defaultCollisionHandler ( btSoftBody * psb )
2017-08-01 14:30:58 +02:00
{
2021-09-29 15:47:08 +02:00
BT_PROFILE ( " Deformable Collision " ) ;
2019-01-03 14:26:51 +01:00
const int cf = m_cfg . collisions & psb - > m_cfg . collisions ;
switch ( cf & fCollision : : SVSmask )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
case fCollision : : CL_SS :
2017-08-01 14:30:58 +02:00
{
//support self-collision if CL_SELF flag set
2019-01-03 14:26:51 +01:00
if ( this ! = psb | | psb - > m_cfg . collisions & fCollision : : CL_SELF )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftColliders : : CollideCL_SS docollide ;
docollide . ProcessSoftSoft ( this , psb ) ;
2017-08-01 14:30:58 +02:00
}
}
break ;
2019-01-03 14:26:51 +01:00
case fCollision : : VF_SS :
2017-08-01 14:30:58 +02:00
{
//only self-collision for Cluster, not Vertex-Face yet
2019-01-03 14:26:51 +01:00
if ( this ! = psb )
{
btSoftColliders : : CollideVF_SS docollide ;
/* common */
docollide . mrg = getCollisionShape ( ) - > getMargin ( ) +
psb - > getCollisionShape ( ) - > getMargin ( ) ;
/* psb0 nodes vs psb1 faces */
docollide . psb [ 0 ] = this ;
docollide . psb [ 1 ] = psb ;
docollide . psb [ 0 ] - > m_ndbvt . collideTT ( docollide . psb [ 0 ] - > m_ndbvt . m_root ,
docollide . psb [ 1 ] - > m_fdbvt . m_root ,
docollide ) ;
/* psb1 nodes vs psb0 faces */
docollide . psb [ 0 ] = psb ;
docollide . psb [ 1 ] = this ;
docollide . psb [ 0 ] - > m_ndbvt . collideTT ( docollide . psb [ 0 ] - > m_ndbvt . m_root ,
docollide . psb [ 1 ] - > m_fdbvt . m_root ,
docollide ) ;
2017-08-01 14:30:58 +02:00
}
}
break ;
2021-09-29 15:47:08 +02:00
case fCollision : : VF_DD :
{
if ( ! psb - > m_softSoftCollision )
return ;
if ( psb - > isActive ( ) | | this - > isActive ( ) )
{
if ( this ! = psb )
{
btSoftColliders : : CollideVF_DD docollide ;
/* common */
docollide . mrg = getCollisionShape ( ) - > getMargin ( ) +
psb - > getCollisionShape ( ) - > getMargin ( ) ;
/* psb0 nodes vs psb1 faces */
if ( psb - > m_tetras . size ( ) > 0 )
docollide . useFaceNormal = true ;
else
docollide . useFaceNormal = false ;
docollide . psb [ 0 ] = this ;
docollide . psb [ 1 ] = psb ;
docollide . psb [ 0 ] - > m_ndbvt . collideTT ( docollide . psb [ 0 ] - > m_ndbvt . m_root ,
docollide . psb [ 1 ] - > m_fdbvt . m_root ,
docollide ) ;
/* psb1 nodes vs psb0 faces */
if ( this - > m_tetras . size ( ) > 0 )
docollide . useFaceNormal = true ;
else
docollide . useFaceNormal = false ;
docollide . psb [ 0 ] = psb ;
docollide . psb [ 1 ] = this ;
docollide . psb [ 0 ] - > m_ndbvt . collideTT ( docollide . psb [ 0 ] - > m_ndbvt . m_root ,
docollide . psb [ 1 ] - > m_fdbvt . m_root ,
docollide ) ;
}
else
{
if ( psb - > useSelfCollision ( ) )
{
btSoftColliders : : CollideFF_DD docollide ;
docollide . mrg = 2 * getCollisionShape ( ) - > getMargin ( ) ;
docollide . psb [ 0 ] = this ;
docollide . psb [ 1 ] = psb ;
if ( this - > m_tetras . size ( ) > 0 )
docollide . useFaceNormal = true ;
else
docollide . useFaceNormal = false ;
/* psb0 faces vs psb0 faces */
calculateNormalCone ( this - > m_fdbvnt ) ;
this - > m_fdbvt . selfCollideT ( m_fdbvnt , docollide ) ;
}
}
}
}
break ;
2019-01-03 14:26:51 +01:00
default :
2017-08-01 14:30:58 +02:00
{
}
}
}
2021-09-29 15:47:08 +02:00
void btSoftBody : : geometricCollisionHandler ( btSoftBody * psb )
{
if ( psb - > isActive ( ) | | this - > isActive ( ) )
{
if ( this ! = psb )
{
btSoftColliders : : CollideCCD docollide ;
/* common */
docollide . mrg = SAFE_EPSILON ; // for rounding error instead of actual margin
docollide . dt = psb - > m_sst . sdt ;
/* psb0 nodes vs psb1 faces */
if ( psb - > m_tetras . size ( ) > 0 )
docollide . useFaceNormal = true ;
else
docollide . useFaceNormal = false ;
docollide . psb [ 0 ] = this ;
docollide . psb [ 1 ] = psb ;
docollide . psb [ 0 ] - > m_ndbvt . collideTT ( docollide . psb [ 0 ] - > m_ndbvt . m_root ,
docollide . psb [ 1 ] - > m_fdbvt . m_root ,
docollide ) ;
/* psb1 nodes vs psb0 faces */
if ( this - > m_tetras . size ( ) > 0 )
docollide . useFaceNormal = true ;
else
docollide . useFaceNormal = false ;
docollide . psb [ 0 ] = psb ;
docollide . psb [ 1 ] = this ;
docollide . psb [ 0 ] - > m_ndbvt . collideTT ( docollide . psb [ 0 ] - > m_ndbvt . m_root ,
docollide . psb [ 1 ] - > m_fdbvt . m_root ,
docollide ) ;
}
else
{
if ( psb - > useSelfCollision ( ) )
{
btSoftColliders : : CollideCCD docollide ;
docollide . mrg = SAFE_EPSILON ;
docollide . psb [ 0 ] = this ;
docollide . psb [ 1 ] = psb ;
docollide . dt = psb - > m_sst . sdt ;
if ( this - > m_tetras . size ( ) > 0 )
docollide . useFaceNormal = true ;
else
docollide . useFaceNormal = false ;
/* psb0 faces vs psb0 faces */
calculateNormalCone ( this - > m_fdbvnt ) ; // should compute this outside of this scope
this - > m_fdbvt . selfCollideT ( m_fdbvnt , docollide ) ;
}
}
}
}
2019-01-03 14:26:51 +01:00
void btSoftBody : : setWindVelocity ( const btVector3 & velocity )
2017-08-01 14:30:58 +02:00
{
m_windVelocity = velocity ;
}
const btVector3 & btSoftBody : : getWindVelocity ( )
{
return m_windVelocity ;
}
2019-01-03 14:26:51 +01:00
int btSoftBody : : calculateSerializeBufferSize ( ) const
2017-08-01 14:30:58 +02:00
{
int sz = sizeof ( btSoftBodyData ) ;
return sz ;
}
2019-01-03 14:26:51 +01:00
///fills the dataBuffer and returns the struct name (and 0 on failure)
const char * btSoftBody : : serialize ( void * dataBuffer , class btSerializer * serializer ) const
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
btSoftBodyData * sbd = ( btSoftBodyData * ) dataBuffer ;
2017-08-01 14:30:58 +02:00
btCollisionObject : : serialize ( & sbd - > m_collisionObjectData , serializer ) ;
2019-01-03 14:26:51 +01:00
btHashMap < btHashPtr , int > m_nodeIndexMap ;
2017-08-01 14:30:58 +02:00
sbd - > m_numMaterials = m_materials . size ( ) ;
2019-01-03 14:26:51 +01:00
sbd - > m_materials = sbd - > m_numMaterials ? ( SoftBodyMaterialData * * ) serializer - > getUniquePointer ( ( void * ) & m_materials ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( sbd - > m_materials )
{
int sz = sizeof ( SoftBodyMaterialData * ) ;
int numElem = sbd - > m_numMaterials ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
2017-08-01 14:30:58 +02:00
//SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
SoftBodyMaterialData * * memPtr = ( SoftBodyMaterialData * * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
btSoftBody : : Material * mat = m_materials [ i ] ;
* memPtr = mat ? ( SoftBodyMaterialData * ) serializer - > getUniquePointer ( ( void * ) mat ) : 0 ;
if ( ! serializer - > findPointer ( mat ) )
{
//serialize it here
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sizeof ( SoftBodyMaterialData ) , 1 ) ;
2017-08-01 14:30:58 +02:00
SoftBodyMaterialData * memPtr = ( SoftBodyMaterialData * ) chunk - > m_oldPtr ;
memPtr - > m_flags = mat - > m_flags ;
memPtr - > m_angularStiffness = mat - > m_kAST ;
memPtr - > m_linearStiffness = mat - > m_kLST ;
memPtr - > m_volumeStiffness = mat - > m_kVST ;
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftBodyMaterialData " , BT_SBMATERIAL_CODE , mat ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftBodyMaterialData " , BT_ARRAY_CODE , ( void * ) & m_materials ) ;
2017-08-01 14:30:58 +02:00
}
sbd - > m_numNodes = m_nodes . size ( ) ;
2019-01-03 14:26:51 +01:00
sbd - > m_nodes = sbd - > m_numNodes ? ( SoftBodyNodeData * ) serializer - > getUniquePointer ( ( void * ) & m_nodes ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( sbd - > m_nodes )
{
int sz = sizeof ( SoftBodyNodeData ) ;
int numElem = sbd - > m_numNodes ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
2017-08-01 14:30:58 +02:00
SoftBodyNodeData * memPtr = ( SoftBodyNodeData * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_nodes [ i ] . m_f . serializeFloat ( memPtr - > m_accumulatedForce ) ;
2017-08-01 14:30:58 +02:00
memPtr - > m_area = m_nodes [ i ] . m_area ;
memPtr - > m_attach = m_nodes [ i ] . m_battach ;
memPtr - > m_inverseMass = m_nodes [ i ] . m_im ;
2019-01-03 14:26:51 +01:00
memPtr - > m_material = m_nodes [ i ] . m_material ? ( SoftBodyMaterialData * ) serializer - > getUniquePointer ( ( void * ) m_nodes [ i ] . m_material ) : 0 ;
2017-08-01 14:30:58 +02:00
m_nodes [ i ] . m_n . serializeFloat ( memPtr - > m_normal ) ;
m_nodes [ i ] . m_x . serializeFloat ( memPtr - > m_position ) ;
m_nodes [ i ] . m_q . serializeFloat ( memPtr - > m_previousPosition ) ;
m_nodes [ i ] . m_v . serializeFloat ( memPtr - > m_velocity ) ;
2019-01-03 14:26:51 +01:00
m_nodeIndexMap . insert ( & m_nodes [ i ] , i ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftBodyNodeData " , BT_SBNODE_CODE , ( void * ) & m_nodes ) ;
2017-08-01 14:30:58 +02:00
}
sbd - > m_numLinks = m_links . size ( ) ;
2019-01-03 14:26:51 +01:00
sbd - > m_links = sbd - > m_numLinks ? ( SoftBodyLinkData * ) serializer - > getUniquePointer ( ( void * ) & m_links [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( sbd - > m_links )
{
int sz = sizeof ( SoftBodyLinkData ) ;
int numElem = sbd - > m_numLinks ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
2017-08-01 14:30:58 +02:00
SoftBodyLinkData * memPtr = ( SoftBodyLinkData * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
memPtr - > m_bbending = m_links [ i ] . m_bbending ;
2019-01-03 14:26:51 +01:00
memPtr - > m_material = m_links [ i ] . m_material ? ( SoftBodyMaterialData * ) serializer - > getUniquePointer ( ( void * ) m_links [ i ] . m_material ) : 0 ;
memPtr - > m_nodeIndices [ 0 ] = m_links [ i ] . m_n [ 0 ] ? m_links [ i ] . m_n [ 0 ] - & m_nodes [ 0 ] : - 1 ;
memPtr - > m_nodeIndices [ 1 ] = m_links [ i ] . m_n [ 1 ] ? m_links [ i ] . m_n [ 1 ] - & m_nodes [ 0 ] : - 1 ;
btAssert ( memPtr - > m_nodeIndices [ 0 ] < m_nodes . size ( ) ) ;
btAssert ( memPtr - > m_nodeIndices [ 1 ] < m_nodes . size ( ) ) ;
2017-08-01 14:30:58 +02:00
memPtr - > m_restLength = m_links [ i ] . m_rl ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftBodyLinkData " , BT_ARRAY_CODE , ( void * ) & m_links [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
sbd - > m_numFaces = m_faces . size ( ) ;
2019-01-03 14:26:51 +01:00
sbd - > m_faces = sbd - > m_numFaces ? ( SoftBodyFaceData * ) serializer - > getUniquePointer ( ( void * ) & m_faces [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( sbd - > m_faces )
{
int sz = sizeof ( SoftBodyFaceData ) ;
int numElem = sbd - > m_numFaces ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
2017-08-01 14:30:58 +02:00
SoftBodyFaceData * memPtr = ( SoftBodyFaceData * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
memPtr - > m_material = m_faces [ i ] . m_material ? ( SoftBodyMaterialData * ) serializer - > getUniquePointer ( ( void * ) m_faces [ i ] . m_material ) : 0 ;
m_faces [ i ] . m_normal . serializeFloat ( memPtr - > m_normal ) ;
for ( int j = 0 ; j < 3 ; j + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
memPtr - > m_nodeIndices [ j ] = m_faces [ i ] . m_n [ j ] ? m_faces [ i ] . m_n [ j ] - & m_nodes [ 0 ] : - 1 ;
2017-08-01 14:30:58 +02:00
}
memPtr - > m_restArea = m_faces [ i ] . m_ra ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftBodyFaceData " , BT_ARRAY_CODE , ( void * ) & m_faces [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
sbd - > m_numTetrahedra = m_tetras . size ( ) ;
2019-01-03 14:26:51 +01:00
sbd - > m_tetrahedra = sbd - > m_numTetrahedra ? ( SoftBodyTetraData * ) serializer - > getUniquePointer ( ( void * ) & m_tetras [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( sbd - > m_tetrahedra )
{
int sz = sizeof ( SoftBodyTetraData ) ;
int numElem = sbd - > m_numTetrahedra ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
2017-08-01 14:30:58 +02:00
SoftBodyTetraData * memPtr = ( SoftBodyTetraData * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 4 ; j + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_tetras [ i ] . m_c0 [ j ] . serializeFloat ( memPtr - > m_c0 [ j ] ) ;
2020-01-08 18:05:43 +01:00
memPtr - > m_nodeIndices [ j ] = m_tetras [ i ] . m_n [ j ] ? m_tetras [ i ] . m_n [ j ] - & m_nodes [ 0 ] : - 1 ;
2017-08-01 14:30:58 +02:00
}
memPtr - > m_c1 = m_tetras [ i ] . m_c1 ;
memPtr - > m_c2 = m_tetras [ i ] . m_c2 ;
2019-01-03 14:26:51 +01:00
memPtr - > m_material = m_tetras [ i ] . m_material ? ( SoftBodyMaterialData * ) serializer - > getUniquePointer ( ( void * ) m_tetras [ i ] . m_material ) : 0 ;
2017-08-01 14:30:58 +02:00
memPtr - > m_restVolume = m_tetras [ i ] . m_rv ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftBodyTetraData " , BT_ARRAY_CODE , ( void * ) & m_tetras [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
sbd - > m_numAnchors = m_anchors . size ( ) ;
2019-01-03 14:26:51 +01:00
sbd - > m_anchors = sbd - > m_numAnchors ? ( SoftRigidAnchorData * ) serializer - > getUniquePointer ( ( void * ) & m_anchors [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( sbd - > m_anchors )
{
int sz = sizeof ( SoftRigidAnchorData ) ;
int numElem = sbd - > m_numAnchors ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
2017-08-01 14:30:58 +02:00
SoftRigidAnchorData * memPtr = ( SoftRigidAnchorData * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
m_anchors [ i ] . m_c0 . serializeFloat ( memPtr - > m_c0 ) ;
m_anchors [ i ] . m_c1 . serializeFloat ( memPtr - > m_c1 ) ;
memPtr - > m_c2 = m_anchors [ i ] . m_c2 ;
m_anchors [ i ] . m_local . serializeFloat ( memPtr - > m_localFrame ) ;
2019-01-03 14:26:51 +01:00
memPtr - > m_nodeIndex = m_anchors [ i ] . m_node ? m_anchors [ i ] . m_node - & m_nodes [ 0 ] : - 1 ;
memPtr - > m_rigidBody = m_anchors [ i ] . m_body ? ( btRigidBodyData * ) serializer - > getUniquePointer ( ( void * ) m_anchors [ i ] . m_body ) : 0 ;
2017-08-01 14:30:58 +02:00
btAssert ( memPtr - > m_nodeIndex < m_nodes . size ( ) ) ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftRigidAnchorData " , BT_ARRAY_CODE , ( void * ) & m_anchors [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
sbd - > m_config . m_dynamicFriction = m_cfg . kDF ;
sbd - > m_config . m_baumgarte = m_cfg . kVCF ;
sbd - > m_config . m_pressure = m_cfg . kPR ;
sbd - > m_config . m_aeroModel = this - > m_cfg . aeromodel ;
sbd - > m_config . m_lift = m_cfg . kLF ;
sbd - > m_config . m_drag = m_cfg . kDG ;
sbd - > m_config . m_positionIterations = m_cfg . piterations ;
sbd - > m_config . m_driftIterations = m_cfg . diterations ;
sbd - > m_config . m_clusterIterations = m_cfg . citerations ;
sbd - > m_config . m_velocityIterations = m_cfg . viterations ;
sbd - > m_config . m_maxVolume = m_cfg . maxvolume ;
sbd - > m_config . m_damping = m_cfg . kDP ;
sbd - > m_config . m_poseMatch = m_cfg . kMT ;
sbd - > m_config . m_collisionFlags = m_cfg . collisions ;
sbd - > m_config . m_volume = m_cfg . kVC ;
sbd - > m_config . m_rigidContactHardness = m_cfg . kCHR ;
sbd - > m_config . m_kineticContactHardness = m_cfg . kKHR ;
sbd - > m_config . m_softContactHardness = m_cfg . kSHR ;
sbd - > m_config . m_anchorHardness = m_cfg . kAHR ;
sbd - > m_config . m_timeScale = m_cfg . timescale ;
sbd - > m_config . m_maxVolume = m_cfg . maxvolume ;
sbd - > m_config . m_softRigidClusterHardness = m_cfg . kSRHR_CL ;
sbd - > m_config . m_softKineticClusterHardness = m_cfg . kSKHR_CL ;
sbd - > m_config . m_softSoftClusterHardness = m_cfg . kSSHR_CL ;
sbd - > m_config . m_softRigidClusterImpulseSplit = m_cfg . kSR_SPLT_CL ;
sbd - > m_config . m_softKineticClusterImpulseSplit = m_cfg . kSK_SPLT_CL ;
sbd - > m_config . m_softSoftClusterImpulseSplit = m_cfg . kSS_SPLT_CL ;
//pose for shape matching
{
sbd - > m_pose = ( SoftBodyPoseData * ) serializer - > getUniquePointer ( ( void * ) & m_pose ) ;
int sz = sizeof ( SoftBodyPoseData ) ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , 1 ) ;
2017-08-01 14:30:58 +02:00
SoftBodyPoseData * memPtr = ( SoftBodyPoseData * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
m_pose . m_aqq . serializeFloat ( memPtr - > m_aqq ) ;
memPtr - > m_bframe = m_pose . m_bframe ;
memPtr - > m_bvolume = m_pose . m_bvolume ;
m_pose . m_com . serializeFloat ( memPtr - > m_com ) ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
memPtr - > m_numPositions = m_pose . m_pos . size ( ) ;
2019-01-03 14:26:51 +01:00
memPtr - > m_positions = memPtr - > m_numPositions ? ( btVector3FloatData * ) serializer - > getUniquePointer ( ( void * ) & m_pose . m_pos [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( memPtr - > m_numPositions )
{
int numElem = memPtr - > m_numPositions ;
int sz = sizeof ( btVector3Data ) ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
2017-08-01 14:30:58 +02:00
btVector3FloatData * memPtr = ( btVector3FloatData * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
m_pose . m_pos [ i ] . serializeFloat ( * memPtr ) ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " btVector3FloatData " , BT_ARRAY_CODE , ( void * ) & m_pose . m_pos [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
memPtr - > m_restVolume = m_pose . m_volume ;
m_pose . m_rot . serializeFloat ( memPtr - > m_rot ) ;
m_pose . m_scl . serializeFloat ( memPtr - > m_scale ) ;
memPtr - > m_numWeigts = m_pose . m_wgh . size ( ) ;
2019-01-03 14:26:51 +01:00
memPtr - > m_weights = memPtr - > m_numWeigts ? ( float * ) serializer - > getUniquePointer ( ( void * ) & m_pose . m_wgh [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( memPtr - > m_numWeigts )
{
int numElem = memPtr - > m_numWeigts ;
int sz = sizeof ( float ) ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
float * memPtr = ( float * ) chunk - > m_oldPtr ;
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
* memPtr = m_pose . m_wgh [ i ] ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " float " , BT_ARRAY_CODE , ( void * ) & m_pose . m_wgh [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftBodyPoseData " , BT_ARRAY_CODE , ( void * ) & m_pose ) ;
2017-08-01 14:30:58 +02:00
}
//clusters for convex-cluster collision detection
sbd - > m_numClusters = m_clusters . size ( ) ;
2019-01-03 14:26:51 +01:00
sbd - > m_clusters = sbd - > m_numClusters ? ( SoftBodyClusterData * ) serializer - > getUniquePointer ( ( void * ) m_clusters [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( sbd - > m_numClusters )
{
int numElem = sbd - > m_numClusters ;
int sz = sizeof ( SoftBodyClusterData ) ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
SoftBodyClusterData * memPtr = ( SoftBodyClusterData * ) chunk - > m_oldPtr ;
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
memPtr - > m_adamping = m_clusters [ i ] - > m_adamping ;
2017-08-01 14:30:58 +02:00
m_clusters [ i ] - > m_av . serializeFloat ( memPtr - > m_av ) ;
memPtr - > m_clusterIndex = m_clusters [ i ] - > m_clusterIndex ;
memPtr - > m_collide = m_clusters [ i ] - > m_collide ;
m_clusters [ i ] - > m_com . serializeFloat ( memPtr - > m_com ) ;
memPtr - > m_containsAnchor = m_clusters [ i ] - > m_containsAnchor ;
m_clusters [ i ] - > m_dimpulses [ 0 ] . serializeFloat ( memPtr - > m_dimpulses [ 0 ] ) ;
m_clusters [ i ] - > m_dimpulses [ 1 ] . serializeFloat ( memPtr - > m_dimpulses [ 1 ] ) ;
m_clusters [ i ] - > m_framexform . serializeFloat ( memPtr - > m_framexform ) ;
memPtr - > m_idmass = m_clusters [ i ] - > m_idmass ;
memPtr - > m_imass = m_clusters [ i ] - > m_imass ;
m_clusters [ i ] - > m_invwi . serializeFloat ( memPtr - > m_invwi ) ;
memPtr - > m_ldamping = m_clusters [ i ] - > m_ldamping ;
m_clusters [ i ] - > m_locii . serializeFloat ( memPtr - > m_locii ) ;
m_clusters [ i ] - > m_lv . serializeFloat ( memPtr - > m_lv ) ;
memPtr - > m_matching = m_clusters [ i ] - > m_matching ;
memPtr - > m_maxSelfCollisionImpulse = m_clusters [ i ] - > m_maxSelfCollisionImpulse ;
memPtr - > m_ndamping = m_clusters [ i ] - > m_ndamping ;
memPtr - > m_ldamping = m_clusters [ i ] - > m_ldamping ;
memPtr - > m_adamping = m_clusters [ i ] - > m_adamping ;
memPtr - > m_selfCollisionImpulseFactor = m_clusters [ i ] - > m_selfCollisionImpulseFactor ;
memPtr - > m_numFrameRefs = m_clusters [ i ] - > m_framerefs . size ( ) ;
memPtr - > m_numMasses = m_clusters [ i ] - > m_masses . size ( ) ;
memPtr - > m_numNodes = m_clusters [ i ] - > m_nodes . size ( ) ;
memPtr - > m_nvimpulses = m_clusters [ i ] - > m_nvimpulses ;
m_clusters [ i ] - > m_vimpulses [ 0 ] . serializeFloat ( memPtr - > m_vimpulses [ 0 ] ) ;
m_clusters [ i ] - > m_vimpulses [ 1 ] . serializeFloat ( memPtr - > m_vimpulses [ 1 ] ) ;
memPtr - > m_ndimpulses = m_clusters [ i ] - > m_ndimpulses ;
2019-01-03 14:26:51 +01:00
memPtr - > m_framerefs = memPtr - > m_numFrameRefs ? ( btVector3FloatData * ) serializer - > getUniquePointer ( ( void * ) & m_clusters [ i ] - > m_framerefs [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( memPtr - > m_framerefs )
{
int numElem = memPtr - > m_numFrameRefs ;
int sz = sizeof ( btVector3FloatData ) ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
btVector3FloatData * memPtr = ( btVector3FloatData * ) chunk - > m_oldPtr ;
for ( int j = 0 ; j < numElem ; j + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
m_clusters [ i ] - > m_framerefs [ j ] . serializeFloat ( * memPtr ) ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " btVector3FloatData " , BT_ARRAY_CODE , ( void * ) & m_clusters [ i ] - > m_framerefs [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
memPtr - > m_masses = memPtr - > m_numMasses ? ( float * ) serializer - > getUniquePointer ( ( void * ) & m_clusters [ i ] - > m_masses [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( memPtr - > m_masses )
{
int numElem = memPtr - > m_numMasses ;
int sz = sizeof ( float ) ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
float * memPtr = ( float * ) chunk - > m_oldPtr ;
for ( int j = 0 ; j < numElem ; j + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
* memPtr = m_clusters [ i ] - > m_masses [ j ] ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " float " , BT_ARRAY_CODE , ( void * ) & m_clusters [ i ] - > m_masses [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
memPtr - > m_nodeIndices = memPtr - > m_numNodes ? ( int * ) serializer - > getUniquePointer ( ( void * ) & m_clusters [ i ] - > m_nodes ) : 0 ;
if ( memPtr - > m_nodeIndices )
2017-08-01 14:30:58 +02:00
{
int numElem = memPtr - > m_numMasses ;
int sz = sizeof ( int ) ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
int * memPtr = ( int * ) chunk - > m_oldPtr ;
for ( int j = 0 ; j < numElem ; j + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
int * indexPtr = m_nodeIndexMap . find ( m_clusters [ i ] - > m_nodes [ j ] ) ;
btAssert ( indexPtr ) ;
* memPtr = * indexPtr ;
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " int " , BT_ARRAY_CODE , ( void * ) & m_clusters [ i ] - > m_nodes ) ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " SoftBodyClusterData " , BT_ARRAY_CODE , ( void * ) m_clusters [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
sbd - > m_numJoints = m_joints . size ( ) ;
2019-01-03 14:26:51 +01:00
sbd - > m_joints = m_joints . size ( ) ? ( btSoftBodyJointData * ) serializer - > getUniquePointer ( ( void * ) & m_joints [ 0 ] ) : 0 ;
2017-08-01 14:30:58 +02:00
if ( sbd - > m_joints )
{
int sz = sizeof ( btSoftBodyJointData ) ;
int numElem = m_joints . size ( ) ;
2019-01-03 14:26:51 +01:00
btChunk * chunk = serializer - > allocate ( sz , numElem ) ;
2017-08-01 14:30:58 +02:00
btSoftBodyJointData * memPtr = ( btSoftBodyJointData * ) chunk - > m_oldPtr ;
2019-01-03 14:26:51 +01:00
for ( int i = 0 ; i < numElem ; i + + , memPtr + + )
2017-08-01 14:30:58 +02:00
{
memPtr - > m_jointType = ( int ) m_joints [ i ] - > Type ( ) ;
m_joints [ i ] - > m_refs [ 0 ] . serializeFloat ( memPtr - > m_refs [ 0 ] ) ;
m_joints [ i ] - > m_refs [ 1 ] . serializeFloat ( memPtr - > m_refs [ 1 ] ) ;
memPtr - > m_cfm = m_joints [ i ] - > m_cfm ;
memPtr - > m_erp = float ( m_joints [ i ] - > m_erp ) ;
memPtr - > m_split = float ( m_joints [ i ] - > m_split ) ;
memPtr - > m_delete = m_joints [ i ] - > m_delete ;
2019-01-03 14:26:51 +01:00
for ( int j = 0 ; j < 4 ; j + + )
2017-08-01 14:30:58 +02:00
{
memPtr - > m_relPosition [ 0 ] . m_floats [ j ] = 0.f ;
memPtr - > m_relPosition [ 1 ] . m_floats [ j ] = 0.f ;
}
memPtr - > m_bodyA = 0 ;
memPtr - > m_bodyB = 0 ;
if ( m_joints [ i ] - > m_bodies [ 0 ] . m_soft )
{
memPtr - > m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER ;
memPtr - > m_bodyA = serializer - > getUniquePointer ( ( void * ) m_joints [ i ] - > m_bodies [ 0 ] . m_soft ) ;
}
if ( m_joints [ i ] - > m_bodies [ 0 ] . m_collisionObject )
{
memPtr - > m_bodyAtype = BT_JOINT_COLLISION_OBJECT ;
memPtr - > m_bodyA = serializer - > getUniquePointer ( ( void * ) m_joints [ i ] - > m_bodies [ 0 ] . m_collisionObject ) ;
}
if ( m_joints [ i ] - > m_bodies [ 0 ] . m_rigid )
{
memPtr - > m_bodyAtype = BT_JOINT_RIGID_BODY ;
memPtr - > m_bodyA = serializer - > getUniquePointer ( ( void * ) m_joints [ i ] - > m_bodies [ 0 ] . m_rigid ) ;
}
if ( m_joints [ i ] - > m_bodies [ 1 ] . m_soft )
{
memPtr - > m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER ;
memPtr - > m_bodyB = serializer - > getUniquePointer ( ( void * ) m_joints [ i ] - > m_bodies [ 1 ] . m_soft ) ;
}
if ( m_joints [ i ] - > m_bodies [ 1 ] . m_collisionObject )
{
memPtr - > m_bodyBtype = BT_JOINT_COLLISION_OBJECT ;
memPtr - > m_bodyB = serializer - > getUniquePointer ( ( void * ) m_joints [ i ] - > m_bodies [ 1 ] . m_collisionObject ) ;
}
if ( m_joints [ i ] - > m_bodies [ 1 ] . m_rigid )
{
memPtr - > m_bodyBtype = BT_JOINT_RIGID_BODY ;
memPtr - > m_bodyB = serializer - > getUniquePointer ( ( void * ) m_joints [ i ] - > m_bodies [ 1 ] . m_rigid ) ;
}
}
2019-01-03 14:26:51 +01:00
serializer - > finalizeChunk ( chunk , " btSoftBodyJointData " , BT_ARRAY_CODE , ( void * ) & m_joints [ 0 ] ) ;
2017-08-01 14:30:58 +02:00
}
return btSoftBodyDataName ;
}
2020-01-08 18:05:43 +01:00
void btSoftBody : : updateDeactivation ( btScalar timeStep )
{
2021-09-29 15:47:08 +02:00
if ( ( getActivationState ( ) = = ISLAND_SLEEPING ) | | ( getActivationState ( ) = = DISABLE_DEACTIVATION ) )
return ;
2020-01-08 18:05:43 +01:00
2021-09-29 15:47:08 +02:00
if ( m_maxSpeedSquared < m_sleepingThreshold * m_sleepingThreshold )
{
m_deactivationTime + = timeStep ;
}
else
{
m_deactivationTime = btScalar ( 0. ) ;
setActivationState ( 0 ) ;
}
2020-01-08 18:05:43 +01:00
}
void btSoftBody : : setZeroVelocity ( )
{
2021-09-29 15:47:08 +02:00
for ( int i = 0 ; i < m_nodes . size ( ) ; + + i )
{
m_nodes [ i ] . m_v . setZero ( ) ;
}
2020-01-08 18:05:43 +01:00
}
bool btSoftBody : : wantsSleeping ( )
{
2021-09-29 15:47:08 +02:00
if ( getActivationState ( ) = = DISABLE_DEACTIVATION )
return false ;
2020-01-08 18:05:43 +01:00
2021-09-29 15:47:08 +02:00
//disable deactivation
if ( gDisableDeactivation | | ( gDeactivationTime = = btScalar ( 0. ) ) )
return false ;
2020-01-08 18:05:43 +01:00
2021-09-29 15:47:08 +02:00
if ( ( getActivationState ( ) = = ISLAND_SLEEPING ) | | ( getActivationState ( ) = = WANTS_DEACTIVATION ) )
return true ;
2020-01-08 18:05:43 +01:00
2021-09-29 15:47:08 +02:00
if ( m_deactivationTime > gDeactivationTime )
{
return true ;
}
return false ;
2020-01-08 18:05:43 +01:00
}