Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Rope pin+collision problem.
#1
Hi,

I'm working on a bridge-building style game. One where you draw a line from pointA to pointB and a rope is generated between the two locations. Then if the player draws a line from the first rope the two of them connect together.

In addition to this system, the ropes all should collide with each other. This is the most important aspect for the project to work. In effect, the player is creating structures out of the ropes which interact with each other via collisions and coupling.

Whilst I have the core system working on this and can connect ropes together. I have encountered one issue which I need to be able to fix in order to progress. For me to explain I need to describe how my system functions.


Firstly: How I'm generating ropes/constraints.

[Image: img1.PNG]
This image shows the way I generate ropes, with everything being generated via scripts (no prefabs or premade blueprints). Each Endpoint is an actual GameObject that contains rigidbodies (both Unity and Obi) which allow them to simulate physics/movement.

The rope can collide with everything.
The Endpoints don't collide with anything.

The rope does not use a "Particle Attachment" component. Instead, I directly access "Oni.ConstraintType.Pin" and use that to generate the pin constraint.


Secondly: How ropes are connected together.

[Image: img2.PNG]
This shows how two ropes are connected in the scene.

They both use the same Endpoint/constraint system, but in this example, Rope-1 generates constraints between A and B. Then Rope-2 generates constraints between B and C.

This allows for the ropes to interact with each other's movements (via two-way coupling).

Like before, the same collision rules apply for ropes and Endpoints.


The problem.

[Image: compare.gif]
Because ropes have collision enabled, this means if two (or more) ropes share a single point then the rope Endpoints get stuck in a cycle of detecting an intersection, moving away, then moving back to its pinned position. This causes a jittering effect which I've been trying to eliminate.

As the gif above shows, when ropes have collision switched off, the ropes simulate without any problems. However, this is not something I can do as ropes NEED to be able to collide with each other.

One fix I've attempted is when I pin the rope, I offset its location slightly to stop potential intersections. This gives some nicer results, but I can't use this as a solution as ropes are generated with gaps between them. Also, the pins act independently of each other, as shown below.
(Left is how the ropes start initially. Right is after the pin constraint is created and allowed to simulate)

[Image: unknown.png]

I have tried changing various solver parameters to see if that could help anything. Reducing the updater substeps to a very low amount helps reduce jittering, but this isn't a fix as the shared-point collision still exists and everything stretches too much.



I'm lost for ideas on what the solution is for this system. I somehow need ropes to both ignore and allow collisions at the same time.
Reply
#2
This situation (along with its solution) is described in the pin constraints section of the manual. See "pin constraints and collisions":
http://obi.virtualmethodstudio.com/manua...aints.html

You need to use collision filtering to disable collisions between the pinned particles only. All other particles in the rope can still collide with each other just fine. See:
http://obi.virtualmethodstudio.com/manua...sions.html

You can change collision filters on a per-control point basis in the path editor. If you're creating ropes programmatically, you can pass the filter value to path.AddControlPoint(). This is a 32-bit integer where the 16 most significant bits define the collision mask, and the 16 less significant bits define the category.

You can build the filter yourself using bitwise operations, and there's also helper functions if you don't want to mess with bits yourself. ObiUtils.MakeFilter will create the filter for you given a mask and a category. For instance:


Code:
int filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything,0);

This builds a filter for category 0 that collides with everything.
Reply
#3
(02-08-2021, 07:46 AM)josemendez Wrote: This situation (along with its solution) is described in the pin constraints section of the manual. See "pin constraints and collisions":
http://obi.virtualmethodstudio.com/manua...aints.html

You need to use collision filtering to disable collisions between the pinned particles only. All other particles in the rope can still collide with each other just fine. See:
http://obi.virtualmethodstudio.com/manua...sions.html

You can change collision filters on a per-control point basis in the path editor. If you're creating ropes programmatically, you can pass the filter value to path.AddControlPoint(). This is a 32-bit integer where the 16 most significant bits define the collision mask, and the 16 less significant bits define the category.

You can build the filter yourself using bitwise operations, and there's also helper functions if you don't want to mess with bits yourself. ObiUtils.MakeFilter will create the filter for you given a mask and a category. For instance:


Code:
int filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything,0);

This builds a filter for category 0 that collides with everything.

Thanks for the reply!

I've been using the filter variable already to configure various materials for different types of collisions (for example, structural materials like support beams allow objects to move through them).

I have tried to find a way to specifically access the first and last particle (as those are the ones that get pinned) to be able to change their collisions but I can't figure out how to do this.

This is a rough idea of the order my rope script goes through (it's very similar to the RopeNet script):
  • Create the rope blueprint
  • Set int filter
  • blueprint.AddControlPoint(filter goes here)
  • Then pin the points, and use ObiPinConstraintsBatch with AddConstraint(rope.solverIndices[0]...)
The closest thing I've come too is thinking is I need to use something like "rope.solverIndices[index value]" as, from what I can tell, this corresponds to each particle on the rope (and potentially they store the collision profile), but I can't actually access their filter data.

My thinking is a generate the rope with the filter profile I need, and then I do something like
  • rope.path.point[value of particle to change].filter = ObiUtils.MakeFilter(ObiUtils.CollideWithNothing, 0);
This way only that specific particle loses it's collision, but the rest remain intact.
Reply
#4
(06-08-2021, 05:38 PM)WinterXYZ Wrote: Thanks for the reply!

I've been using the filter variable already to configure various materials for different types of collisions (for example, structural materials like support beams allow objects to move through them).

I have tried to find a way to specifically access the first and last particle (as those are the ones that get pinned) to be able to change their collisions but I can't figure out how to do this.

This is a rough idea of the order my rope script goes through (it's very similar to the RopeNet script):
  • Create the rope blueprint
  • Set int filter
  • blueprint.AddControlPoint(filter goes here)
  • Then pin the points, and use ObiPinConstraintsBatch with AddConstraint(rope.solverIndices[0]...)
The closest thing I've come too is thinking is I need to use something like "rope.solverIndices[index value]" as, from what I can tell, this corresponds to each particle on the rope (and potentially they store the collision profile), but I can't actually access their filter data.

My thinking is a generate the rope with the filter profile I need, and then I do something like
  • rope.path.point[value of particle to change].filter = ObiUtils.MakeFilter(ObiUtils.CollideWithNothing, 0);
This way only that specific particle loses it's collision, but the rest remain intact.
Hi, I'm having a similar problem to this. Did you ever find out how to chalge the collision filter on a specific particle, or find any other solution?
Reply
#5
(22-06-2022, 09:55 PM)Destro26 Wrote: Hi, I'm having a similar problem to this. Did you ever find out how to chalge the collision filter on a specific particle, or find any other solution?

Hi!

You can change the filter for a specific particle, just like you can change any other particle property like position, velocity, mass, etc. Just write into the solver.filters array, see:
http://obi.virtualmethodstudio.com/manua...icles.html

This is usually not necessary since you can simply add more control points to your path and set the filters up in editor (initial filter values for each particle are picked from the closest control point along the rope).
Reply
#6
(23-06-2022, 07:10 AM)josemendez Wrote: Hi!

You can change the filter for a specific particle, just like you can change any other particle property like position, velocity, mass, etc. Just write into the solver.filters array, see:
http://obi.virtualmethodstudio.com/manua...icles.html

This is usually not necessary since you can simply add more control points to your path and set the filters up in editor (initial filter values for each particle are picked from the closest control point along the rope).
Thank you, I was able to get it working by using solver.filters. I am creating the rope at runtime so i'm not able to set up filters in the editor.

For anyone who needs it, this code turned off the collision of the first particle in the rope
Code:
int filterNoCollision = ObiUtils.MakeFilter(ObiUtils.CollideWithNothing, 0);
rope.solver.filters[rope.elements[0].particle1] = filterNoCollision;
One more question: when particles are added to the rope with the ChangeLength what control point do they use set their values (i.e filter, mass)?
Reply
#7
(23-06-2022, 09:13 PM)Destro26 Wrote: Thank you, I was able to get it working by using solver.filters. I am creating the rope at runtime so i'm not able to set up filters in the editor.

Even if you create the rope at runtime, you still have to provide a list of control points and their properties. Only difference is that instead of setting the filters using the editor UI, you pass them as a parameter to the AddControlPoint() function.

Unless you're doing some funky per-particle processing after blueprint generation, there should be no need to use solver.filters directly. It's not wrong in any way to overwrite the values in solver.filters tough, if you prefer it or if it's more comfortable.

(23-06-2022, 09:13 PM)Destro26 Wrote: One more question: when particles are added to the rope with the ChangeLength what control point do they use set their values (i.e filter, mass)?

Once a rope has been instantiated, the blueprint it came from has no effect on it. It's a one way road:  blueprint->rope (similar to prefabs).
ChangeLength() picks up the properties of the new particles from its source mu:

http://obi.virtualmethodstudio.com/manua...ursor.html

Quote:Source Mu: This is the normalized position from where particles will be copied from when adding new particles. 0 will place it at the start of the rope, 1 will place it at the end. Any value it between will place it in the particle closest to that value.

cheers!
Reply