Linking softbodys (e.g: rope <-> patch)

TheKing
Posts: 13
Joined: Sun Sep 11, 2011 2:02 pm

Linking softbodys (e.g: rope <-> patch)

Post by TheKing »

Hi,

I want to link some softbodies in a special way. Look at this screenshot:

Image

The 5 colored flags you see are all softbody-patches created with bullet, and the brown line is a softbody-rope. The flags are currently hold in place as their 11th and and last node has a mass of 0. However, they should be fixed along the rope. How can I do that? I tried using appendAnchor with a pointer-convertion [ (btRigidBody*)m_btSoftBody ], but it didn't seem to work. Can somebody tell me how this is done, given that I have these two objects:

btSoftBody m_Flag;
btSoftBody m_Rope;

I want the flag to be fixed with its 11th node to the flags 2nd node and its last node to the flags 3rd node. Any help would be really appreciated!
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by Flix »

Never tried, but there are other posts available about this:
http://bulletphysics.org/Bullet/phpBB3/ ... appendLink
Basically you're supposed to use: appendLink instead of: appendAnchor and pass the pointer of a Node of a different soft body.
Hope it works.
TheKing
Posts: 13
Joined: Sun Sep 11, 2011 2:02 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by TheKing »

Thanks, using appendLink seems to be what I was looking for! However, I'm having other issues:

- If the patch and the rope, like in my picture, are too far away, they get linked correctly, but the nodes still stay in relation to where they have originally been. However I want the flag to be directly attached to the rope. How can I move certain nodes to the position of another node? directly setting m_patchnode.m_x = m_ropenode.m_x didn't work..

- Only one node seems to be linked correctly, even if I do this:

Code: Select all

	btSoftBody* sb1 = m_Cloths[0].GetSoftBody();
	btSoftBody* sb2 = m_Ropes[0].GetSoftBody();

	sb1->appendLink(&sb1->m_nodes[11], &sb2->m_nodes[1]);
	sb1->appendLink(&sb1->m_nodes[sb1->m_nodes.size()-1], &sb2->m_nodes[3]);
Of course I need my flag to being attached to the rope on >=2 nodes, however with the code supplied aboth only 1 node gets connected. Is this a bug, or do I have to do something special?#

Thanks in advance for any help!
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by Flix »

TheKing wrote:Is this a bug, or do I have to do something special?
No idea (as I told you, I've never tried this myself).
I think there are methods to translate a btSoftBody (and more generally to transform them):

Code: Select all

	/* Transform															*/ 
	void				transform(		const btTransform& trs);
	/* Translate															*/ 
	void				translate(		const btVector3& trs);
	/* Rotate															*/ 
	void				rotate(	const btQuaternion& rot);
	/* Scale																*/ 
	void				scale(	const btVector3& scl);
You may try one of them (maybe calling it soon after you build your patches).
TheKing
Posts: 13
Joined: Sun Sep 11, 2011 2:02 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by TheKing »

Thanks, translate worked out fine. There is yet another issue: The links stretch a lot if huge forces are applied. For example if I set the wind to 15 the flags are dragged about 2 or more world units away from the rope. See the screenshot:

Image

I'm pretty sure this is just some setting in the softbody or dynamics world. What do I have to do to fix the links totally together? Or is it a bug?
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by Flix »

TheKing wrote:What do I have to do to fix the links totally together?
Well, I've not been using soft bodies for some time now, so I don't remember exactly every aspect of the appendLink method... Anyway I'm quite sure that you can change some elastic constants of the links somehow (you can probably browse the forum to find out how to do it). Unluckily I don't remember if this can be done on a per link basis or not... (maybe you can add a new material for these links only and set the new properties for it, but I've never tried this approach and I don't know if it works).

P.S. With a rigid body chain as rope, you can probably use this method that is related to appendAnchor: http://bulletphysics.org/Bullet/phpBB3/ ... +body+hard.

P.S.2. How did you solve the other problem you had:
TheKing wrote:Of course I need my flag to being attached to the rope on >=2 nodes, however with the code supplied aboth only 1 node gets connected. Is this a bug, or do I have to do something special?
.
TheKing
Posts: 13
Joined: Sun Sep 11, 2011 2:02 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by TheKing »

Flix wrote:Well, I've not been using soft bodies for some time now, so I don't remember exactly every aspect of the appendLink method... Anyway I'm quite sure that you can change some elastic constants of the links somehow (you can probably browse the forum to find out how to do it). Unluckily I don't remember if this can be done on a per link basis or not... (maybe you can add a new material for these links only and set the new properties for it, but I've never tried this approach and I don't know if it works).
Yes, you are right, you can set a material on per-link-basis. I tried playing with the material-values, but it didn't work. This is my code:

Code: Select all

void CSoftPhysic::CreateLink(int ClothID, int RopeID, int RopeNode)
{
	btSoftBody* sb1 = m_Cloths[ClothID].GetSoftBody();
	btSoftBody* sb2 = m_Ropes[RopeID].GetSoftBody();
        //try configuring link not to be stretching too much
	btSoftBody::Material* pm=sb1->appendMaterial();
	pm->m_kLST		=	1.0;
	pm->m_kAST      =   1.0;
	pm->m_kVST      =   1.0;
        //append links
	sb1->appendLink(&sb1->m_nodes[11], &sb2->m_nodes[RopeNode], pm);
	sb1->appendLink(&sb1->m_nodes[sb1->m_nodes.size()-1], &sb2->m_nodes[RopeNode+1], pm);
        //move cloth to its correct position
	btVector3 pos = btVector3(m_Cloths[ClothID].GetPosition().x, m_Cloths[ClothID].GetPosition().y, m_Cloths[ClothID].GetPosition().z);
	btVector3 dist = sb2->m_nodes[RopeNode].m_x - pos;
	sb1->translate(dist);
}
Setting m_kLST to < 1.0 makes the link stretch even more, but setting it to > 1.0 only results in the flags jittering around. Changing the other to values doesn't change much. Any ideas? I've uploaded a little video showing the behavior of the patches with a wind of (15, 0, 0) and without any wind. Hope this helps you helping me solving my issue..^^

http://www.youtube.com/watch?v=ZVYkuuV4XBc

Flix wrote:P.S. With a rigid body chain as rope, you can probably use this method that is related to appendAnchor:
Thanks for the tip, but as long as possible, I'd like to use only softbodys for the rope.. using a rigid body chain is my very last option.
Flix wrote:P.S.2. How did you solve the other problem you had:
Well, I don't really know, I just kept playing around with setLink and appearently now, as you can see in my video, the flags are linked with two of their nodes.

Any more ideas?
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by Flix »

Very strange behavior indeed :?

Well, I don't have any real solution for you. I think I would play around with the masses (bigger mass for the rope, far smaller for the flags), with pose-matching stuff and with the number of iterations of the soft bodies (making them bigger). I don't remember the exact properties now, but I'm sure you can find them easily. I don't know it this will solve your (huge) offset problem (the flags are so distant from the rope that I wonder if btSoftBody::translate works correctly...).
Also it seems that one of your 2 junctions is more elastic than the other!

Good luck!

[Edit]Another thing that I was thinking:
Additional care should be taken so that the junction nodes are placed EXACTLY at the same place: this way the length of the junction links is zero, and hopefully the flag should stay near the rope.[/Edit]
TheKing
Posts: 13
Joined: Sun Sep 11, 2011 2:02 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by TheKing »

Thanks, you gave me a good hint, actually btSoftBody::translate was used incorrectly by me (my calculations were a bit offset). Anyway even with this fixed using links didn't work. I spend all day and night trying to fix this, but eventually I found a thread in the forum stating that you could use appendAnchor with a "dummy" rigid-body to link between two soft bodys. I did so, and it works way better than using links! However, it still isn't perfect, but I quess using/debugging anchors is a lot easier, so lets go.. this is what it looks like now:

Image

Well, its not perfect, but way to go.. It still makes me wonder why the anchor stretches? I have set kAHR to 1.0, I even tried hard-coding the kAHR-value to 1.0. Could there be any reason for this? Here is my code:

Code: Select all

void CSoftPhysic::CreateLink(int ClothID, int RopeID, int RopeNode)
{
//get soft bodys
	btSoftBody* sb1 = m_Cloths[ClothID].GetSoftBody();
	btSoftBody* sb2 = m_Ropes[RopeID].GetSoftBody();
//translate patch to rope
	btVector3 pos = btVector3(m_Cloths[ClothID].GetPosition().x, m_Cloths[ClothID].GetPosition().y, m_Cloths[ClothID].GetPosition().z);
	btVector3 dist = sb2->m_nodes[RopeNode].m_x - pos;
	sb1->translate(dist);

//create dummy rigid body1
	m_GroundShape = new btSphereShape(0.01f);
	btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,0,0)));
	btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,groundMotionState,m_GroundShape,btVector3(0,0,0));
	btRigidBody* GroundRigidBody = new btRigidBody(groundRigidBodyCI);
	GroundRigidBody->setMassProps(10, btVector3(0.0, 0.0, 0.0));
//translate rb1 to rope
	pos = GroundRigidBody->getWorldTransform().getOrigin();
	dist = sb2->m_nodes[RopeNode+1].m_x - pos;
	GroundRigidBody->translate(dist);

//append anchor between 1st node->rb->rope
	sb1->appendAnchor(11, GroundRigidBody, btVector3(0, 0, 0), true);
	sb2->appendAnchor(RopeNode+1, GroundRigidBody, btVector3(0, 0, 0), true);

//create second rb
	btDefaultMotionState* groundMotionState2 = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,0,0)));
	btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI2(0,groundMotionState2,m_GroundShape,btVector3(0,0,0));
	btRigidBody* GroundRigidBody2 = new btRigidBody(groundRigidBodyCI2);
	GroundRigidBody2->setMassProps(1, btVector3(0.0, 0.0, 0.0));

//translate rb to rope
	pos = GroundRigidBody2->getWorldTransform().getOrigin();
	dist = sb2->m_nodes[RopeNode].m_x - pos;
	GroundRigidBody2->translate(dist);

//append anchor between 2nd patch node->rb2->rope
	sb1->appendAnchor(sb1->m_nodes.size()-1, GroundRigidBody2, btVector3(0, 0, 0), true);
	sb2->appendAnchor(RopeNode, GroundRigidBody2, btVector3(0, 0, 0), true);
}
Does anyone sees a mistake here? Well at least this time its not as bad, because, using a simple hack called every frame for every patch, I can make the flags at least seem to be fixed to the rope:

Image

Code: Select all

       btVector3 pos1 = psb->m_nodes[11].m_x;
		btVector3 pos2 = m_Ropes[0].GetSoftBody()->m_nodes[i].m_x;
		btVector3 dist = pos2 - pos1;
		ii->SetPosition(dist.x(), 1+dist.y(), dist.z());
It's almost like I'm expecting it, but as you might be able to see the flags second node isn't always aligned to the rope. If the anchor wouldn stretch, neither this "hack" nor that issue would be needed. Any ideas?

However, there is a second issue that has nothing to do with the one above. Though the current state isn't perfect, its acceptable to work with. So comes my next problem: For now I'm using a 24 units long rope with 16 segments. The flags are fixed on each two following nodes: 0-1, 1-2, 2-3, .. with their own corners (node 11 and node size-1). However I want the flags to be fixed on all of upper nodes, not only on the upper corners. So I tried increasing the resolution of the rope (my flags resolution is 12*16, so that equals to 192 res for the rope):

Image

As you can see, the rope stretches like crazy (ignore the bunch of flags on the right side of the rope, that will be fixed afterwards). What can I do to increase the resolution of the rope, while keeping the same length AND having it stretch similarly?
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by Flix »

Some thoughts:

In your code your two "dummy" rigid bodies seem to have mass of 10 and 1 Kg (why it's different?). In your last issue you seem to append many of them to your new rope: no wonder it stretches a lot...

It seems to me that these bodies re not dummy at all (they're just normal rigid bodies without local inertia). I would try:
->Setting their gravity to zero (after you add them to the world).
->Setting them without contact response AND when adding them to the world, using a collision filter mask so that they can't collide with anything else (probably 0 should work). This last point is just for performance so that the new bodies are discarded early in the collision detection phases.
->Tuning their masses so that the anchor works well (or in extreme cases their gravity can be set slightly <0 to force the flag to stay in an upper position... (although I wouldn't recommended it)).

You may also consider some variations:
1) Maybe you can change the shape of your dummy bodies so that one of them can be linked to more than one flag node in different points of the dummy rigid body (as long as graphically the flag edge seems close to he rope).
2) You may use a rigid rope directly instead of dummy rigid bodies in between soft bodies (this is probably the way I'd do it, if soft links are impossible to fix).
The overhead of the rope contraints (point to point should work) must be compared with the lack of the soft rope and all the dummy rigid bodies you're using. Your solution has the advantage that you can tweak the dummy rigid body masses as you like...
3) This is something I've not completely sure of... In the soft body demos there are "soft contraints" that are used (with motors) in the "bunny vehicle" demo and in another "strange vehicle" demo as well (and in other demos too without motors AFAIR). Maybe such "soft contraints" can be used instead of simply appending links (in a full "soft body" environment; i.e. without using rigid bodies at all). The drawback is that I don't know it it works at all in your case and you may need A LOT of these contraints (= bad performance).

My thoughts about it are over... :?
TheKing
Posts: 13
Joined: Sun Sep 11, 2011 2:02 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by TheKing »

Thank you for all the suggestion, however I finally solved the problem with a quite different approach:

First of all I reduced the resolution of my flags. Instead of 16x12 I use 16x3 now which is easier to handle and, in my opinion, even looks better. I still use append-anchor now, but with a low-res rope (16 for a length of 24). Now I only fix the top two corners with rigid bodys (oh, they are dummy after all - I never add them to the dynamics world. adding them doesn't change their behavior regarding my issue, though..) to two corresponding nodes of the rope - 16/15, 15/14, .. . Now, I use a quite ugly hack: To fix the general offset of the flags, I correct the position of the cloth in the rendering pipeline so that the upper left corner is effectively aligned to the ropes node it should be linked to anyway (well, if it doesn't want to work normally..). Now, still the other two upper nodes aren't quite aligned to the rope. To fix this, I simply take the ropes other node - now for the flags upper right corner, I simply handle that over as its rendering position (manipulating the body itself isn't a good idea). For the upper middle node, I do the same thing, but take the middle between rope node 16 and 15. Now it looks like the flag is aligned to the rope:

Image

Though this is not 100% physically accurate, I'm more than happy. It looks really good now, having a lower resolution for the flags was a perfect idea, the higher resolutions behavior with wind always annoyed me.. There is little to no jittering, and that only if the rope has a too short length. The rope is behaving fine, though I have to rethink rendering (maybe I'll render it as cylinders instead of lines, at least I need textures). Well, finally :D

Now, there is just one lost thing that bugs me: The flags have no collision response to each other. Self-collision is fine, the low-res flags won't really collide with itself much (while the high-res did very often). However they aren't colliding with each other, though I know that they should do, as I've tried the softbody demo that comes with bullet. Here is the code that setup my dynamics world:

Code: Select all

	m_Dispatcher=0;
	
	m_GroundShape = new btSphereShape(0.01f);

	///register some softbody collision algorithms on top of the default btDefaultCollisionConfiguration
	this->m_CollisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();


	m_Dispatcher = new	btCollisionDispatcher(m_CollisionConfiguration);
	m_SoftBodyInfo.m_dispatcher = m_Dispatcher;

	////////////////////////////
	///Register softbody versus softbody collision algorithm


	///Register softbody versus rigidbody collision algorithm


	////////////////////////////

	btVector3 worldAabbMin(-1000,-1000,-1000);
	btVector3 worldAabbMax(1000,1000,1000);

	m_Broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);

	m_SoftBodyInfo.m_broadphase = m_Broadphase;

	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver();

	m_Solver = solver;

	btDiscreteDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_Dispatcher,m_Broadphase,m_Solver,m_CollisionConfiguration);
	m_DiscreteDynamicsWorld = world;
	m_DiscreteDynamicsWorld->setInternalTickCallback(0,this,true);

	m_DiscreteDynamicsWorld->getDispatchInfo().m_enableSPU = true;
	m_DiscreteDynamicsWorld->setGravity(btVector3(0,-10,0));
	m_SoftBodyInfo.m_gravity.setValue(0,-10,0);
	m_SoftBodyInfo.air_density = 1.0f;

	m_SoftBodyInfo.m_sparsesdf.Initialize();
It is more or less the exact code out of the demo. In the update step, I just call m_DiscreteDynamicsWorld->stepSimulation(1.0f/60.f,1); . Do I eigther have to add some code to the setup or call some other method? I'd be really glad if that problem was fixed, as I'd be finished with softbodies by then :D Any ideas?
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Linking softbodys (e.g: rope <-> patch)

Post by Flix »

TheKing wrote:I finally solved the problem
I'm happy you did it, and from the image you sent it looks good :D
TheKing wrote:[...]oh, they are dummy after all - I never add them to the dynamics world[...]
My bad, I should have paid more attention to what you wrote :oops: . Interesting technique. Good to know.
TheKing wrote:The rope is behaving fine, though I have to rethink rendering (maybe I'll render it as cylinders instead of lines, at least I need textures).
Another less exensive option can be using a chain of billboards quads with textures on them. And if the rope movement looks too "segmented", you can render it using the midpoint between nodes instead of the actual nodes, 'cause their oscillation is usually smaller, although you probably would have to accomodate your "rendering hacks" again if you do it...
TheKing wrote:Self-collision is fine, the low-res flags won't really collide with itself much (while the high-res did very often). However they aren't colliding with each other, though I know that they should do, as I've tried the softbody demo that comes with bullet.
Very strange, in that soft body demo there's a small cloth falling on a bigger one without problems... Are you sure you're replicating all the exact parameters, including maybe the number of iterations, aerodynamic properties, clusters (if they're really needed), etc ? You may try this test: you build two flags inside the some btSoftBody (without links between each other); this way the contact between the two bodies become self-collisions and you can check it things works or not (due to mesh topology problems, or other stuff). Hope somebody can post a better (and real) answer...