Browse Source

Removed isometric bend constraints (they seem to be inferior in every aspect but I want to keep my implementation in the history)

Jorrit Rouwe 1 năm trước cách đây
mục cha
commit
f03c9d3ac2

+ 1 - 62
Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp

@@ -254,52 +254,6 @@ void SoftBodyMotionProperties::ApplyBendConstraints(const SoftBodyUpdateContext
 
 	float inv_dt_sq = 1.0f / Square(inContext.mSubStepDeltaTime);
 
-	for (const IsometricBend &b : mSettings->mIsometricBendConstraints)
-	{
-		Vertex &v0 = mVertices[b.mVertex[0]];
-		Vertex &v1 = mVertices[b.mVertex[1]];
-		Vertex &v2 = mVertices[b.mVertex[2]];
-		Vertex &v3 = mVertices[b.mVertex[3]];
-
-		// Get positions
-		// Setting x0 as origin
-		Vec3 x1 = v1.mPosition - v0.mPosition;
-		Vec3 x2 = v2.mPosition - v0.mPosition;
-		Vec3 x3 = v3.mPosition - v0.mPosition;
-
-		// Calculate constraint equation
-		// C = 0.5 * Sum_i,j(Q_ij * x_i . x_j)
-		// Note that Q is symmetric so we can optimize this to:
-		float c = b.mQ12 * x1.Dot(x2) + b.mQ13 * x1.Dot(x3) + b.mQ23 * x2.Dot(x3) // Off diagonal elements occur twice
-				+ 0.5f * (b.mQ11 * x1.LengthSq() + b.mQ22 * x2.LengthSq() + b.mQ33 * x3.LengthSq()); // Diagonal elements only once
-		if (abs(c) < 1.0e-6f)
-			continue;
-
-		// Calculate gradient of constraint equation, again using Q_ij = Q_ji
-		// del C = Sum_j(Q_ij * x_j)
-		Vec3 d0c = b.mQ01 * x1 + b.mQ02 * x2 + b.mQ03 * x3;
-		Vec3 d1c = b.mQ11 * x1 + b.mQ12 * x2 + b.mQ13 * x3;
-		Vec3 d2c = b.mQ12 * x1 + b.mQ22 * x2 + b.mQ23 * x3;
-		Vec3 d3c = -d0c - d1c - d2c; // The sum of the gradients needs to be zero
-
-		// Get masses
-		float w0 = v0.mInvMass;
-		float w1 = v1.mInvMass;
-		float w2 = v2.mInvMass;
-		float w3 = v3.mInvMass;
-		JPH_ASSERT(w0 > 0.0f || w1 > 0.0f || w2 > 0.0f || w3 > 0.0f);
-
-		// Apply correction
-		float denom = w0 * d0c.LengthSq() + w1 * d1c.LengthSq() + w2 * d2c.LengthSq() + w3 * d3c.LengthSq() + b.mCompliance * inv_dt_sq;
-		if (denom == 0.0f)
-			continue;
-		float lambda = -c / denom;
-		v0.mPosition += lambda * w0 * d0c;
-		v1.mPosition += lambda * w1 * d1c;
-		v2.mPosition += lambda * w2 * d2c;
-		v3.mPosition += lambda * w3 * d3c;
-	}
-
 	for (const DihedralBend &b : mSettings->mDihedralBendConstraints)
 	{
 		Vertex &v0 = mVertices[b.mVertex[0]];
@@ -1019,7 +973,7 @@ void SoftBodyMotionProperties::DrawEdgeConstraints(DebugRenderer *inRenderer, RM
 
 void SoftBodyMotionProperties::DrawBendConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const
 {
-	for (const IsometricBend &b : mSettings->mIsometricBendConstraints)
+	for (const DihedralBend &b : mSettings->mDihedralBendConstraints)
 	{
 		RVec3 x0 = inCenterOfMassTransform * mVertices[b.mVertex[0]].mPosition;
 		RVec3 x1 = inCenterOfMassTransform * mVertices[b.mVertex[1]].mPosition;
@@ -1033,21 +987,6 @@ void SoftBodyMotionProperties::DrawBendConstraints(DebugRenderer *inRenderer, RM
 		inRenderer->DrawLine(c_edge, 0.1_r * c_edge + 0.9_r * c0, Color::sGreen);
 		inRenderer->DrawLine(c_edge, 0.1_r * c_edge + 0.9_r * c1, Color::sGreen);
 	}
-
-	for (const DihedralBend &b : mSettings->mDihedralBendConstraints)
-	{
-		RVec3 x0 = inCenterOfMassTransform * mVertices[b.mVertex[0]].mPosition;
-		RVec3 x1 = inCenterOfMassTransform * mVertices[b.mVertex[1]].mPosition;
-		RVec3 x2 = inCenterOfMassTransform * mVertices[b.mVertex[2]].mPosition;
-		RVec3 x3 = inCenterOfMassTransform * mVertices[b.mVertex[3]].mPosition;
-		RVec3 c_edge = 0.5_r * (x0 + x1);
-		RVec3 c0 = (x0 + x1 + x2) / 3.0_r;
-		RVec3 c1 = (x0 + x1 + x3) / 3.0_r;
-
-		inRenderer->DrawArrow(0.9_r * x0 + 0.1_r * x1, 0.1_r * x0 + 0.9_r * x1, Color::sDarkOrange, 0.01f);
-		inRenderer->DrawLine(c_edge, 0.1_r * c_edge + 0.9_r * c0, Color::sOrange);
-		inRenderer->DrawLine(c_edge, 0.1_r * c_edge + 0.9_r * c1, Color::sOrange);
-	}
 }
 
 void SoftBodyMotionProperties::DrawVolumeConstraints(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform) const

+ 0 - 1
Jolt/Physics/SoftBody/SoftBodyMotionProperties.h

@@ -35,7 +35,6 @@ public:
 	using Vertex = SoftBodyVertex;
 	using Edge = SoftBodySharedSettings::Edge;
 	using Face = SoftBodySharedSettings::Face;
-	using IsometricBend = SoftBodySharedSettings::IsometricBend;
 	using DihedralBend = SoftBodySharedSettings::DihedralBend;
 	using Volume = SoftBodySharedSettings::Volume;
 	using InvBind = SoftBodySharedSettings::InvBind;

+ 0 - 91
Jolt/Physics/SoftBody/SoftBodySharedSettings.cpp

@@ -35,21 +35,6 @@ JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(SoftBodySharedSettings::Edge)
 	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::Edge, mCompliance)
 }
 
-JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(SoftBodySharedSettings::IsometricBend)
-{
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mVertex)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mCompliance)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ01)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ02)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ03)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ11)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ12)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ13)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ22)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ23)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::IsometricBend, mQ33)
-}
-
 JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(SoftBodySharedSettings::DihedralBend)
 {
 	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings::DihedralBend, mVertex)
@@ -97,7 +82,6 @@ JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(SoftBodySharedSettings)
 	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings, mFaces)
 	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings, mEdgeConstraints)
 	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings, mEdgeGroupEndIndices)
-	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings, mIsometricBendConstraints)
 	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings, mDihedralBendConstraints)
 	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings, mVolumeConstraints)
 	JPH_ADD_ATTRIBUTE(SoftBodySharedSettings, mSkinnedConstraints)
@@ -211,20 +195,6 @@ void SoftBodySharedSettings::CreateConstraints(const VertexAttributes *inVertexA
 						add_edge(v_min, v_max, a_min.mBendCompliance, a_max.mBendCompliance);
 					break;
 
-				case EBendType::Isometric:
-					// Test if both opposite vertices are free to move
-					if ((mVertices[vopposite0].mInvMass > 0.0f || mVertices[vopposite1].mInvMass > 0.0f)
-						&& a_min.mBendCompliance < FLT_MAX && a_max.mBendCompliance < FLT_MAX)
-					{
-						// Get the vertices that form the common edge
-						uint32 vedge0 = f0.mVertex[e0.mEdgeIdx % 3];
-						uint32 vedge1 = f0.mVertex[(e0.mEdgeIdx + 1) % 3];
-
-						// Create a bend constraint
-						mIsometricBendConstraints.emplace_back(vedge0, vedge1, vopposite0, vopposite1, 0.5f * (a_min.mBendCompliance + a_max.mBendCompliance));
-					}
-					break;
-
 				case EBendType::Dihedral:
 					// Test if both opposite vertices are free to move
 					if ((mVertices[vopposite0].mInvMass > 0.0f || mVertices[vopposite1].mInvMass > 0.0f)
@@ -276,67 +246,8 @@ void SoftBodySharedSettings::CalculateLRALengths()
 	}
 }
 
-static float sCotangent(Vec3Arg inV1, Vec3Arg inV2)
-{
-	float dot = inV1.Dot(inV2);
-	float cross = inV1.Cross(inV2).Length();
-	return dot / cross;
-}
-
 void SoftBodySharedSettings::CalculateBendConstraintConstants()
 {
-	for (IsometricBend &b : mIsometricBendConstraints)
-	{
-		// Get positions
-		Vec3 x0 = Vec3(mVertices[b.mVertex[0]].mPosition);
-		Vec3 x1 = Vec3(mVertices[b.mVertex[1]].mPosition);
-		Vec3 x2 = Vec3(mVertices[b.mVertex[2]].mPosition);
-		Vec3 x3 = Vec3(mVertices[b.mVertex[3]].mPosition);
-
-		/*
-		Figure in section 2 of "A Quadratic Bending Model for Inextensible Surfaces"
-		   x2
-		e1/  \e3
-		 /    \
-		x0----x1
-		 \ e0 /
-		e2\  /e4
-		   x3
-		*/
-
-		// Calculate edges
-		Vec3 e0 = x1 - x0;
-		Vec3 e1 = x2 - x0;
-		Vec3 e2 = x3 - x0;
-		Vec3 e3 = x2 - x1;
-		Vec3 e4 = x3 - x1;
-
-		// Calculate cotangents
-		float c02 = sCotangent(e0, e2);
-		float c03 = sCotangent(-e0, e3);
-		float c04 = sCotangent(-e0, e4);
-		float c01 = sCotangent(e0, e1);
-
-		// 2x area of both triangles
-		float two_a0 = e0.Cross(e1).Length();
-		float two_a1 = e0.Cross(e2).Length();
-
-		// Calculate Q, note that this matrix is symmetric so we don't need to store all elements
-		Vec4 k0(c03 + c04, c01 + c02, -c01 - c03, -c02 - c04);
-		Mat44 k0_dot_k0_t(k0.GetX() * k0, k0.GetY() * k0, k0.GetZ() * k0, k0.GetW() * k0);
-		Mat44 q = (6.0f / (two_a0 + two_a1)) * k0_dot_k0_t;
-		// q00 is not used since we set x0 to be the origin
-		b.mQ01 = q(0, 1);
-		b.mQ02 = q(0, 2);
-		b.mQ03 = q(0, 3);
-		b.mQ11 = q(1, 1);
-		b.mQ12 = q(1, 2);
-		b.mQ13 = q(1, 3);
-		b.mQ22 = q(2, 2);
-		b.mQ23 = q(2, 3);
-		b.mQ33 = q(3, 3);
-	}
-
 	for (DihedralBend &b : mDihedralBendConstraints)
 	{
 		// Get positions
@@ -518,7 +429,6 @@ void SoftBodySharedSettings::SaveBinaryState(StreamOut &inStream) const
 	inStream.Write(mFaces);
 	inStream.Write(mEdgeConstraints);
 	inStream.Write(mEdgeGroupEndIndices);
-	inStream.Write(mIsometricBendConstraints);
 	inStream.Write(mDihedralBendConstraints);
 	inStream.Write(mVolumeConstraints);
 	inStream.Write(mSkinnedConstraints);
@@ -539,7 +449,6 @@ void SoftBodySharedSettings::RestoreBinaryState(StreamIn &inStream)
 	inStream.Read(mFaces);
 	inStream.Read(mEdgeConstraints);
 	inStream.Read(mEdgeGroupEndIndices);
-	inStream.Read(mIsometricBendConstraints);
 	inStream.Read(mDihedralBendConstraints);
 	inStream.Read(mVolumeConstraints);
 	inStream.Read(mSkinnedConstraints);

+ 2 - 38
Jolt/Physics/SoftBody/SoftBodySharedSettings.h

@@ -22,7 +22,6 @@ public:
 	{
 		None,														///< No bend constraints will be created
 		Distance,													///< A simple distance constraint
-		Isometric,													///< An isometric bend constraint (better but much more expensive)
 		Dihedral,													///< A dihedral bend constraint (most expensive, but also supports triangles that are initially not in the same plane)
 	};
 
@@ -51,7 +50,7 @@ public:
 	/// Calculate the max lengths for the long range attachment constraints
 	void				CalculateLRALengths();
 
-	/// Calculate the Q values for the isometric bend constraints (if you use CreateConstraint, this is already done)
+	/// Calculate the constants for the bend constraints (if you use CreateConstraints, this is already done)
 	void				CalculateBendConstraintConstants();
 
 	/// Calculates the initial volume of all tetrahedra of this soft body
@@ -138,41 +137,7 @@ public:
 		float			mRestLength = 1.0f;							///< Rest length of the spring
 		float			mCompliance = 0.0f;							///< Inverse of the stiffness of the spring
 	};
-
-	/**
-	 * An isometric bend constraint keeps the angle between 2 triangles that share an edge constant:
-	 * 
-	 *        x2
-	 *       /  \
-	 *      / t0 \
-	 *     x0----x1
-	 *      \ t1 /
-	 *       \  /
-	 *        x3
-	 * 
-	 * x0..x3 are the vertices, t0 and t1 are the triangles that share the edge x0..x1
-	 * 
-	 * Based on:
-	 * - "Discrete Quadratic Curvature Energies" - Max Wardetzky et al.
-	 * - "A Quadratic Bending Model for Inextensible Surfaces" - Miklos Bergou et al.
-	 * 
-	 * Warning: Only works when the rest pose of the triangles is in a plane. Also assumes no stretching.
-	 */
-	struct JPH_EXPORT IsometricBend
-	{
-		JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, IsometricBend)
-
-		/// Constructor
-						IsometricBend() = default;
-						IsometricBend(uint32 inVertex1, uint32 inVertex2, uint32 inVertex3, uint32 inVertex4, float inCompliance = 0.0f) : mVertex { inVertex1, inVertex2, inVertex3, inVertex4 }, mCompliance(inCompliance) { }
-
-		uint32			mVertex[4];									///< Indices of the vertices of the 2 triangles that share an edge (the first 2 vertices are the shared edge)
-		float			mCompliance = 0.0f;							///< Inverse of the stiffness of the constraint
-		float			mQ01 { 0 }, mQ02 { 0 }, mQ03 { 0 };			///< The Q matrix that defines the rest shape of the bend constraint and is calculated by CalculateBendConstraintQs()
-		float			mQ11 { 0 }, mQ12 { 0 }, mQ13 { 0 };
-		float			mQ22 { 0 }, mQ23 { 0 }, mQ33 { 0 };
-	};
-
+		
 	/**
 	 * A dihedral bend constraint
 	 * 
@@ -299,7 +264,6 @@ public:
 	Array<Vertex>		mVertices;									///< The list of vertices or particles of the body
 	Array<Face>			mFaces;										///< The list of faces of the body
 	Array<Edge>			mEdgeConstraints;							///< The list of edges or springs of the body
-	Array<IsometricBend>mIsometricBendConstraints;					///< The list of isometric bend constraints of the body
 	Array<DihedralBend>	mDihedralBendConstraints;					///< The list of dihedral bend constraints of the body
 	Array<Volume>		mVolumeConstraints;							///< The list of volume constraints of the body that keep the volume of tetrahedra in the soft body constant
 	Array<Skinned>		mSkinnedConstraints;						///< The list of vertices that are constrained to a skinned vertex

+ 1 - 1
Samples/Tests/SoftBody/SoftBodyBendConstraintTest.cpp

@@ -35,7 +35,7 @@ void SoftBodyBendConstraintTest::Initialize()
 	}
 
 	{
-		// Cloth with isometric bend constraints
+		// Cloth with dihedral bend constraints
 		Ref<SoftBodySharedSettings> cloth_settings = SoftBodyCreator::CreateCloth(cNumVerticesX, cNumVerticesZ, cVertexSpacing, inv_mass, SoftBodySharedSettings::EBendType::Dihedral);
 		SoftBodyCreationSettings cloth(cloth_settings, RVec3(5.0f, 5.0f, 0), Quat::sIdentity(), Layers::MOVING);
 		mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);