[SOLVED] Soft bodies vertex-to-vertex/tetrahedra constraint

Eaglegor
Posts: 9
Joined: Tue Jun 18, 2013 2:20 pm
Location: Russia, Samara

[SOLVED] Soft bodies vertex-to-vertex/tetrahedra constraint

Post by Eaglegor »

Hello, everybody!

I need implement some soft body joints: one-way vertex-to-vertex joint (vertex of one soft body is pinned to vertex of another soft body), two-way vertex-to-vertex joint (2 vertices of 2 soft bodies are pulled together when the distance between them grows - like spring), one-way vertex-to-tetrahedra joint (vertex of one soft body is pinned to a tetrahedron of another soft body).

I have some thoughts about how to do this. When I implemented these things with a PhysX I used the stand-alone joint object which applied a velocities to vertices once per frame. It worked but only if there was exactly one subiteration per frame. When there were more iterations, vertices were vibrating. I think that's because internal constraints of soft body worked without paying attention to my joint. I could write the same implementation of joints using Bullet but I think that the result will be the same.

I've read some source code related to soft body and have 2 more thoughts about it.

Firstly I could try to derive from a btDefaultSoftBodySolver and extend the solveContraints method i.e. add there calls to my joint's update method.

Secondly I could derive from btSoftBody and extend it's solvers functionality i.e. add my own solver type (something like PSolve_Joints, VSolve_Joints) to the corresponding sequences which would consider the joints influences on the nodes of soft body .

In bullet pdf documentation i've read about soft body constraints:
"It is possible to fix one or more vertices (nodes), making it immovable or to attach one or more vertices of a soft body to a rigid body"
"It is also possible to attach two soft bodies using constraints, see Bullet/Demos/SoftBody"
But when I read the code of SoftDemo.cpp the mouse picking func is the nearest thing related to my task that I have found (maybe I was searching in a wrong places).

It could be nice to get some advice about which method I should better use (or some other directions of thinking).

UPD: I've found the btSoftBody::Joint class but I can't find where the m_joints array is used to apply them.

UPD2: I've found that m_joints is used in solveClusters method. Now the third method is to derive my joint from btSoftBody::Joint and add it to m_joints array (and it seems to be the best method for me now).
Last edited by Eaglegor on Fri Jun 21, 2013 2:55 pm, edited 1 time in total.
Eaglegor
Posts: 9
Joined: Tue Jun 18, 2013 2:20 pm
Location: Russia, Samara

Re: Soft bodies vertex-to-vertex/vertex-to-tetrahedra constr

Post by Eaglegor »

Well, the method with btSoftBody::Joint works good.

In someone needs this, there's a part of my code (one-way vertex-tetra joint):

.h

Code: Select all

class myJoint: public btSoftBody::Joint {
public:
	myJoint(){...};

	// ### Overriden from btSoftBody::Joint #####
	void Prepare(btScalar dt,int iterations){}; // I don't need this
	void Solve(btScalar dt,btScalar sor);
	void Terminate(btScalar dt){}; // I don't need this there
	btSoftBody::Joint::eType::_ Type() const;
	// ##########################################

	~myJoint(){...};
private:

	struct Attach
	{
		size_t attached_vertex_id;
		size_t attached_to_tetrahedra_id;
		btVector3 barycentric_coordinates;
	};
	std::vector<Attach> attachments;

	bool initJoint(){...}; // generating Attach

	btSBObject* main_soft_body;
	btSBObject* attached_soft_body;
};
.cpp

Code: Select all


btSoftBody::Joint::eType::_ myJoint::Type() const{
	return btSoftBody::Joint::eType::Linear;
}

void myJoint::Solve(btScalar dt,btScalar sor){

	for(size_t i=0; i<this->attachments.size(); i++){
		
		Attach& at = this->attachments[i];
		
		const unsigned long *index = &this->main_soft_body->getTetraMeshData()->indices[at.attached_to_tetrahedra_id*4];

		const btVector3 &ta = this->main_soft_body->m_tetras[at.attached_to_tetrahedra_id].m_n[0]->m_x;
		const btVector3 &tb = this->main_soft_body->m_tetras[at.attached_to_tetrahedra_id].m_n[1]->m_x;
		const btVector3 &tc = this->main_soft_body->m_tetras[at.attached_to_tetrahedra_id].m_n[2]->m_x;
		const btVector3 &td = this->main_soft_body->m_tetras[at.attached_to_tetrahedra_id].m_n[3]->m_x;

		this->attached_soft_body->m_nodes[ at.attached_vertex_id ].m_q = Utils::TetrahedraBarycentricToWorld(at.barycentric_coordinates, ta, tb, tc, td);
		this->attached_soft_body->m_nodes[ at.attached_vertex_id ].m_v = btVector3(0,0,0);
		this->attached_soft_body->m_nodes[ at.attached_vertex_id ].m_f = btVector3(0,0,0);

	}
	
}

I think this topic may be closed, but I can't find a way to do it myself.