1 /*
2  Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
3 
4  Bullet Continuous Collision Detection and Physics Library
5  Copyright (c) 2019 Google Inc. http://bulletphysics.org
6  This software is provided 'as-is', without any express or implied warranty.
7  In no event will the authors be held liable for any damages arising from the use of this software.
8  Permission is granted to anyone to use this software for any purpose,
9  including commercial applications, and to alter it and redistribute it freely,
10  subject to the following restrictions:
11  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.
12  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13  3. This notice may not be removed or altered from any source distribution.
14  */
15 
16 #ifndef BT_DEFORMABLE_CONTACT_CONSTRAINT_H
17 #define BT_DEFORMABLE_CONTACT_CONSTRAINT_H
18 #include "btSoftBody.h"
19 
20 // btDeformableContactConstraint is an abstract class specifying the method that each type of contact constraint needs to implement
21 class btDeformableContactConstraint
22 {
23 public:
24 	// True if the friction is static
25 	// False if the friction is dynamic
26 	bool m_static;
27 	const btContactSolverInfo* m_infoGlobal;
28 
29 	// normal of the contact
30 	btVector3 m_normal;
31 
btDeformableContactConstraint(const btVector3 & normal,const btContactSolverInfo & infoGlobal)32 	btDeformableContactConstraint(const btVector3& normal, const btContactSolverInfo& infoGlobal) : m_static(false), m_normal(normal), m_infoGlobal(&infoGlobal)
33 	{
34 	}
35 
btDeformableContactConstraint(bool isStatic,const btVector3 & normal,const btContactSolverInfo & infoGlobal)36 	btDeformableContactConstraint(bool isStatic, const btVector3& normal, const btContactSolverInfo& infoGlobal) : m_static(isStatic), m_normal(normal), m_infoGlobal(&infoGlobal)
37 	{
38 	}
39 
btDeformableContactConstraint()40 	btDeformableContactConstraint() : m_static(false) {}
41 
btDeformableContactConstraint(const btDeformableContactConstraint & other)42 	btDeformableContactConstraint(const btDeformableContactConstraint& other)
43 		: m_static(other.m_static), m_normal(other.m_normal), m_infoGlobal(other.m_infoGlobal)
44 	{
45 	}
46 
~btDeformableContactConstraint()47 	virtual ~btDeformableContactConstraint() {}
48 
49 	// solve the constraint with inelastic impulse and return the error, which is the square of normal component of velocity diffrerence
50 	// the constraint is solved by calculating the impulse between object A and B in the contact and apply the impulse to both objects involved in the contact
51 	virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal) = 0;
52 
53 	// get the velocity of the object A in the contact
54 	virtual btVector3 getVa() const = 0;
55 
56 	// get the velocity of the object B in the contact
57 	virtual btVector3 getVb() const = 0;
58 
59 	// get the velocity change of the soft body node in the constraint
60 	virtual btVector3 getDv(const btSoftBody::Node*) const = 0;
61 
62 	// apply impulse to the soft body node and/or face involved
63 	virtual void applyImpulse(const btVector3& impulse) = 0;
64 
65 	// scale the penetration depth by erp
66 	virtual void setPenetrationScale(btScalar scale) = 0;
67 };
68 
69 //
70 // Constraint that a certain node in the deformable objects cannot move
71 class btDeformableStaticConstraint : public btDeformableContactConstraint
72 {
73 public:
74 	btSoftBody::Node* m_node;
75 
btDeformableStaticConstraint(btSoftBody::Node * node,const btContactSolverInfo & infoGlobal)76 	btDeformableStaticConstraint(btSoftBody::Node* node, const btContactSolverInfo& infoGlobal) : m_node(node), btDeformableContactConstraint(false, btVector3(0, 0, 0), infoGlobal)
77 	{
78 	}
btDeformableStaticConstraint()79 	btDeformableStaticConstraint() {}
btDeformableStaticConstraint(const btDeformableStaticConstraint & other)80 	btDeformableStaticConstraint(const btDeformableStaticConstraint& other)
81 		: m_node(other.m_node), btDeformableContactConstraint(other)
82 	{
83 	}
84 
~btDeformableStaticConstraint()85 	virtual ~btDeformableStaticConstraint() {}
86 
solveConstraint(const btContactSolverInfo & infoGlobal)87 	virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal)
88 	{
89 		return 0;
90 	}
91 
getVa()92 	virtual btVector3 getVa() const
93 	{
94 		return btVector3(0, 0, 0);
95 	}
96 
getVb()97 	virtual btVector3 getVb() const
98 	{
99 		return btVector3(0, 0, 0);
100 	}
101 
getDv(const btSoftBody::Node * n)102 	virtual btVector3 getDv(const btSoftBody::Node* n) const
103 	{
104 		return btVector3(0, 0, 0);
105 	}
106 
applyImpulse(const btVector3 & impulse)107 	virtual void applyImpulse(const btVector3& impulse) {}
setPenetrationScale(btScalar scale)108 	virtual void setPenetrationScale(btScalar scale) {}
109 };
110 
111 //
112 // Anchor Constraint between rigid and deformable node
113 class btDeformableNodeAnchorConstraint : public btDeformableContactConstraint
114 {
115 public:
116 	const btSoftBody::DeformableNodeRigidAnchor* m_anchor;
117 
118 	btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& c, const btContactSolverInfo& infoGlobal);
119 	btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other);
btDeformableNodeAnchorConstraint()120 	btDeformableNodeAnchorConstraint() {}
~btDeformableNodeAnchorConstraint()121 	virtual ~btDeformableNodeAnchorConstraint()
122 	{
123 	}
124 	virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
125 
126 	// object A is the rigid/multi body, and object B is the deformable node/face
127 	virtual btVector3 getVa() const;
128 	// get the velocity of the deformable node in contact
129 	virtual btVector3 getVb() const;
getDv(const btSoftBody::Node * n)130 	virtual btVector3 getDv(const btSoftBody::Node* n) const
131 	{
132 		return btVector3(0, 0, 0);
133 	}
134 	virtual void applyImpulse(const btVector3& impulse);
135 
setPenetrationScale(btScalar scale)136 	virtual void setPenetrationScale(btScalar scale) {}
137 };
138 
139 //
140 // Constraint between rigid/multi body and deformable objects
141 class btDeformableRigidContactConstraint : public btDeformableContactConstraint
142 {
143 public:
144 	btVector3 m_total_normal_dv;
145 	btVector3 m_total_tangent_dv;
146 	btScalar m_penetration;
147 	btScalar m_total_split_impulse;
148 	bool m_binding;
149 	const btSoftBody::DeformableRigidContact* m_contact;
150 
151 	btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal);
152 	btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other);
btDeformableRigidContactConstraint()153 	btDeformableRigidContactConstraint() : m_binding(false) {}
~btDeformableRigidContactConstraint()154 	virtual ~btDeformableRigidContactConstraint()
155 	{
156 	}
157 
158 	// object A is the rigid/multi body, and object B is the deformable node/face
159 	virtual btVector3 getVa() const;
160 
161 	// get the split impulse velocity of the deformable face at the contact point
162 	virtual btVector3 getSplitVb() const = 0;
163 
164 	// get the split impulse velocity of the rigid/multibdoy at the contaft
165 	virtual btVector3 getSplitVa() const;
166 
167 	virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
168 
setPenetrationScale(btScalar scale)169 	virtual void setPenetrationScale(btScalar scale)
170 	{
171 		m_penetration *= scale;
172 	}
173 
174 	btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
175 
176 	virtual void applySplitImpulse(const btVector3& impulse) = 0;
177 };
178 
179 //
180 // Constraint between rigid/multi body and deformable objects nodes
181 class btDeformableNodeRigidContactConstraint : public btDeformableRigidContactConstraint
182 {
183 public:
184 	// the deformable node in contact
185 	btSoftBody::Node* m_node;
186 
187 	btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal);
188 	btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other);
btDeformableNodeRigidContactConstraint()189 	btDeformableNodeRigidContactConstraint() {}
~btDeformableNodeRigidContactConstraint()190 	virtual ~btDeformableNodeRigidContactConstraint()
191 	{
192 	}
193 
194 	// get the velocity of the deformable node in contact
195 	virtual btVector3 getVb() const;
196 
197 	// get the split impulse velocity of the deformable face at the contact point
198 	virtual btVector3 getSplitVb() const;
199 
200 	// get the velocity change of the input soft body node in the constraint
201 	virtual btVector3 getDv(const btSoftBody::Node*) const;
202 
203 	// cast the contact to the desired type
getContact()204 	const btSoftBody::DeformableNodeRigidContact* getContact() const
205 	{
206 		return static_cast<const btSoftBody::DeformableNodeRigidContact*>(m_contact);
207 	}
208 
209 	virtual void applyImpulse(const btVector3& impulse);
210 
211 	virtual void applySplitImpulse(const btVector3& impulse);
212 };
213 
214 //
215 // Constraint between rigid/multi body and deformable objects faces
216 class btDeformableFaceRigidContactConstraint : public btDeformableRigidContactConstraint
217 {
218 public:
219 	btSoftBody::Face* m_face;
220 	bool m_useStrainLimiting;
221 	btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting);
222 	btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other);
btDeformableFaceRigidContactConstraint()223 	btDeformableFaceRigidContactConstraint() : m_useStrainLimiting(false) {}
~btDeformableFaceRigidContactConstraint()224 	virtual ~btDeformableFaceRigidContactConstraint()
225 	{
226 	}
227 
228 	// get the velocity of the deformable face at the contact point
229 	virtual btVector3 getVb() const;
230 
231 	// get the split impulse velocity of the deformable face at the contact point
232 	virtual btVector3 getSplitVb() const;
233 
234 	// get the velocity change of the input soft body node in the constraint
235 	virtual btVector3 getDv(const btSoftBody::Node*) const;
236 
237 	// cast the contact to the desired type
getContact()238 	const btSoftBody::DeformableFaceRigidContact* getContact() const
239 	{
240 		return static_cast<const btSoftBody::DeformableFaceRigidContact*>(m_contact);
241 	}
242 
243 	virtual void applyImpulse(const btVector3& impulse);
244 
245 	virtual void applySplitImpulse(const btVector3& impulse);
246 };
247 
248 //
249 // Constraint between  deformable objects faces and deformable objects nodes
250 class btDeformableFaceNodeContactConstraint : public btDeformableContactConstraint
251 {
252 public:
253 	btSoftBody::Node* m_node;
254 	btSoftBody::Face* m_face;
255 	const btSoftBody::DeformableFaceNodeContact* m_contact;
256 	btVector3 m_total_normal_dv;
257 	btVector3 m_total_tangent_dv;
258 
259 	btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal);
btDeformableFaceNodeContactConstraint()260 	btDeformableFaceNodeContactConstraint() {}
~btDeformableFaceNodeContactConstraint()261 	virtual ~btDeformableFaceNodeContactConstraint() {}
262 
263 	virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
264 
265 	// get the velocity of the object A in the contact
266 	virtual btVector3 getVa() const;
267 
268 	// get the velocity of the object B in the contact
269 	virtual btVector3 getVb() const;
270 
271 	// get the velocity change of the input soft body node in the constraint
272 	virtual btVector3 getDv(const btSoftBody::Node*) const;
273 
274 	// cast the contact to the desired type
getContact()275 	const btSoftBody::DeformableFaceNodeContact* getContact() const
276 	{
277 		return static_cast<const btSoftBody::DeformableFaceNodeContact*>(m_contact);
278 	}
279 
280 	virtual void applyImpulse(const btVector3& impulse);
281 
setPenetrationScale(btScalar scale)282 	virtual void setPenetrationScale(btScalar scale) {}
283 };
284 #endif /* BT_DEFORMABLE_CONTACT_CONSTRAINT_H */
285