Soft Body 是 Bullet 引擎中用于布料、软体等形变仿真的类。


1、软体的基本组成元素 Node 、Link、Face、Tetra 以及 Material

在 soft body 中,一般是由点、线、面、四面体单元等基本元素构成。下面将分别介绍一下,各个元素的代码,以及使用方法。

1.1、Node

Node 是软体中的节点类,其定义为:

/* Node			*/
struct Node : Feature
{
	btVector3 m_x;       // Position
	btVector3 m_q;       // Previous step position/Test position
	btVector3 m_v;       // Velocity
        btVector3 m_vsplit;  // Temporary Velocity in addintion to velocity used in split impulse
        btVector3 m_vn;      // Previous step velocity
	btVector3 m_f;       // Force accumulator
	btVector3 m_n;       // Normal
	btScalar m_im;       // 1/mass
	btScalar m_area;     // Area
	btDbvtNode* m_leaf;  // Leaf data
	bool m_constrained;   // constrained node
	int m_battach : 1;   // Attached
        int index;
};

其中,包含了(当前时刻的)位置 m_x 前一时刻的位置 m_q 、(当前时刻的)速度 m_v 、某速度 m_vsplit 、前一时刻的速度 m_vn 、所受的合力 m_f 、法向量 m_n (不知道做什么的)、质量的倒数 m_im 、面积 m_area 、btDvtNode 、约束标志位 m_constrained 、固定标志位 m_battach 、节点编号 index 。以及材料参数 Feature::m_material

大致也能明白这些参数/信息是什么。

连线类的定义为:

/* Link			*/
ATTRIBUTE_ALIGNED16(struct)
Link : Feature
{
	btVector3 m_c3;      // gradient
	Node* m_n[2];        // Node pointers
	btScalar m_rl;       // Rest length
	int m_bbending : 1;  // Bending link
	btScalar m_c0;       // (ima+imb)*kLST
	btScalar m_c1;       // rl^2
	btScalar m_c2;       // |gradient|^2/c0

	BT_DECLARE_ALIGNED_ALLOCATOR();
	};

连线类 Link 包含了连线的两个顶点(指针)、gradient、初始长度、一些参数、以及材料参数 Feature::m_material

具体的一些参数的用法,后面再细究吧。可能有的也不一定会用到。因为,不同的算法,所用到的参数也不尽相同。

1.3、Face

三角形面片类的定义为:

/* Face			*/
struct Face : Feature
{
	Node* m_n[3];        // Node pointers
	btVector3 m_normal;  // Normal
	btScalar m_ra;       // Rest area
	btDbvtNode* m_leaf;  // Leaf data
        btVector4 m_pcontact; // barycentric weights of the persistent contact
        btVector3 m_n0, m_n1, m_vn;
        int m_index;
};

三角形面片类 Face 包含了三个顶点(指针)、法向量、初始面积、btDvtNode*m_pcontact 应该是碰撞点在三角形面片中的质心坐标(barycentric weights)、m_n0、m_n1、m_n2(应该是三个顶点的法向量?)、编号 m_index 、以及材料参数 Feature::m_material

大致也能明白这些信息。个别信息的用处,后面再慢慢细究吧。

1.4、Tetra

四面体单元类其定义为:

/* Tetra		*/
struct Tetra : Feature
{
	Node* m_n[4];        // Node pointers
	btScalar m_rv;       // Rest volume
	btDbvtNode* m_leaf;  // Leaf data
	btVector3 m_c0[4];   // gradients
	btScalar m_c1;       // (4*kVST)/(im0+im1+im2+im3)
	btScalar m_c2;       // m_c1/sum(|g0..3|^2)
        btMatrix3x3 m_Dm_inverse; // rest Dm^-1
        btMatrix3x3 m_F;
        btScalar m_element_measure;
};

也就是说,Tetra 包含了四面体单元顶点(指针)、初始体积、btDbvtNode*(不知道做什么的)、gradient、某某变量、invDm、形变梯度 (oldsymbol{F}) 、某某变量、材料参数 Feature::m_material

这些也基本上包含了软体形变仿真中四面体单元相关的变量。只是,有几个变量还不太清楚是做什么的。

1.5、Mateiral

材料参数的定义如下

/* Material		*/
struct Material : Element
{
	btScalar m_kLST;  // Linear stiffness coefficient [0,1]
	btScalar m_kAST;  // Area/Angular stiffness coefficient [0,1]
	btScalar m_kVST;  // Volume stiffness coefficient [0,1]
	int m_flags;      // Flags
};

具体,这个材料参数是用来做什么的,后续再看吧


2 软体的建立及初始化

btSoftBody 中,软体的节点、网格、面片等数据,存储在以下成员变量中:

tNodeArray m_nodes;                // Nodes
tNodeArray m_renderNodes;          // Nodes
tLinkArray m_links;                // Links
tFaceArray m_faces;                // Faces
tFaceArray m_renderFaces;          // Faces
tTetraArray m_tetras;              // Tetras

btAlignedObjectArray<btVector3> m_X;   // initial positions

btSoftBody 的建立及初始化过程可以参见 btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(..)

2.1、构造函数

首先,读取节点的位置,并由此新建一个 btSoftBody 对象:

btSoftBody* psb = new btSoftBody(&worldInfo, nnode, &pos[0], 0);

btSoftBody 的构造函数中,初始化了一系列的内部参数;新建并初始化了材料 Material m_materials ;新建了 N 个 Node ,存入节点位置等信息,并将初始节点位置放入 m_X 中;在 m_ndbvt 中插入节点,并将该节点的指针放入节点的 n.m_leaf 中;更新 m_bounds (这个估计跟 AABB 类似,就是一个边界包围盒吧);更新 m_quads (不知道是用来做什么的)

2.2、添加面片 Face

通过函数 btSoftBody::appendFace(...) 向软体对象中添加三角形面片。通常情况下,添加四面体单元时,已经添加过边线了,这里就不需要再重复添加表面网格的边线。

2.3、添加四面体单元 Tetra

通过函数 btSoftBody::appendTetra(...) 向软体对象中添加四面体单元。此外,还需要添加四面体单元的四条边线 Line ,即通过 btSoftBody::appendLink(...) 向软体对象中添加边线。

2.4、进一步初始化

添加完软体对象的网格数据后,还需要进一步初始化,比如,计算四面体单元的 invDm。


3、btDbvt Tree

在 Bullet 物理引擎中,对于 btDbvt 类的定义及说明如下:

///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
struct btDbvt
{ ... }

也就是说,这个本质上是一个用于碰撞检测(broad phase)的 AABB tree 。关于它是如何实现的,就先不讨论了。在 btSoftBody 中,相关的 AABB tree 有如下这些:

btDbvt m_ndbvt;                    // Nodes tree
btDbvt m_fdbvt;                    // Faces tree
btDbvntNode* m_fdbvnt;              // Faces tree with normals
btDbvt m_cdbvt;                    // Clusters tree

4、btSoftBody 的其他成员变量

AnchorRContactSContactJointCluster 、等等


5、位移预计算 btSoftBody::predictMotion

参见 Bullet 学习笔记之 btSoftBody::predictMotion


6、约束计算 btSoftBody::solveClusters

参见 Bullet 学习笔记之 btSoftBody::predictMotion


7、碰撞处理 btSoftBody::defaultCollisionHandler(btSoftBody* psb)

参见 Bullet 学习笔记之 btSoftBody::predictMotion


8、总结

待续