Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Scripting rod forces
#11
(25-08-2025, 12:12 PM)josemendez Wrote: Yes, there's solver and actor constraint batches. These are completely different. When you create an actor, its constraints are grouped into batches. When you add an actor to a solver (so it becomes part of the simulation), a copy of each constraint batch in the actor is created and merged with *all other existing constraints in the solver*, including those belonging to other actors to maximize parallelism.

As a result:
- Actor batches contain constraint data at rest for a specific actor.
- Solver batches contain current constraint data for all constraints in the simulation, at any point during simulation.
- The number of solver batches and the number of constraints in each solver batch is different than its actor counterparts, and are accessed differently.

Oh ok, I checked docs before, but I understood it works in the same way as positions, I mean that only solver holds the data, so I assumed GetConstraint from actor is just proxy to the one managed by solver. So to sum up - solver has real data we operate on, while actor has "original copy" of initial rest state.
I assume, in case of indices (to get particle position) I could use both of them (batch.particleIndices or solverBatch.particleIndices), but when it comes to lambda I need the one from solver as it changes over time.

Quote:Is there difference between GetBatch(j) and batches[j]?

I assume both of them are bassicaly the same thing.

(25-08-2025, 12:12 PM)josemendez Wrote: Entirely depends on what you're using them for. Just like in Unity you sometimes use deltaTime, but some other times you use fixedDeltaTime.

Hah, I asked silly question. I came up with this, because my logic was that I need to use simulation delta (simulationTime), but lambda and that other example confused me, and I assumed I am missing something important. Your answers to all other bits clarified everything, especially the part with broken example and steps.

(25-08-2025, 12:12 PM)josemendez Wrote: Lambda values are set to zero at the start of each substep, and accumulated between iterations. However, while time advances from one substep to the next, it does not advance between iterations: iterations simply refine the solution for the current substep.

What is better way to get rigid rod (close to truth) in this case?
Documentation says: 
"The quality improvement you get by reducing the timestep duration is greater than you'd get by using more iterations, and they both have similar performance cost."

I mean, number of particles affects the end result, so for example if I twist/push one particle, then to propagate this force to other parts of the rod (or any other actor) requires more time and iterations. What is better: 5 substeps and 10 iterations, or 1 substep and 50 iterations? I guess the first one should be better, but at the same time it increases the cost of all other aspects of simulation. However let's assume, there is only one actor and I want to get as good result as possible.

(25-08-2025, 12:12 PM)josemendez Wrote: I'd recommend reading the "how it works" section of the manual, as it goes in-depth about timesteps, substeps and iterations:
https://obi.virtualmethodstudio.com/manu...gence.html

These articles are also useful for reference:
https://matthias-research.github.io/page...s/XPBD.pdf
https://mmacklin.com/smallsteps.pdf

I already checked the whole manual, but those two other links is nice addition, thanks!
Reply
#12
(25-08-2025, 02:11 PM)Qriva0 Wrote: What is better: 5 substeps and 10 iterations, or 1 substep and 50 iterations? I guess the first one should be better,

The best possible configuration in terms of convergence speed/quality is N substeps, and only 1 iteration. This is what the article I shared demonstrates:

Quote:We make the surprising observation that performing a single large time step with n constraint solver iterations is less effective than computing n smaller time steps, each with a single constraint solver iteration.

In other words: it's costlier to correct constraint error caused by using large time steps (which is what iterations do) than to keep the error from growing in the first place, by using a smaller timestep (more substeps). To correct the error caused by using only 1 substep instead of say, 4 substeps, you need a lot more than 4 iterations.

(25-08-2025, 02:11 PM)Qriva0 Wrote: but at the same time it increases the cost of all other aspects of simulation. However let's assume, there is only one actor and I want to get as good result as possible.

"All other aspects" is just integration - moving state forward in time, which is dirt cheap. Because of this the cost of substeps = N, iterations = 1 and substeps = 1, iterations = N is basically the same. Collision detection is only performed once per full step, and the resulting contact constraints reused for all substeps/iterations.

For this reason, the manual recommends to start by setting all iteration counts to 1 and adjusting substeps first.

Also note that using more substeps dissipates a lot less energy than using iterations and will result in more lively simulations, so what substeps/iterations combination to use can also be a bit of a stylistic choice.

kind regards,
Reply
#13
Thank you very much! 
It really helps, I am going to try different configurations to see what fits best Gran sonrisa
Reply
#14
Hi again, I tested various solutions and I wanted to confirm several things.

1. The problem I want to solve is controlling/pushing the cable (rod), but from the middle part, not the tip. 
There are two obstacles on my way, first one is the fact that pushing it requires forces to propagate and it can make the cable very wiggly or stretch even with big amount of substeps (15-20), and second one is keeping the cable fixed by some particle and this is related to second point:

2. Changing particle position teleports it and it does not apply any forces, however if there are other particles, then the whole actor can gain valocity because constraints try to keep particles in their proper positions. In this case does that mean that I should not move rod by changing position of single particle? If yes, then how to move particle via velocity, and keep it pushed, so it does not pull back from forces or collision? Adding velocity or externalForces will stack, while overriding velocity will cancel all other forces plus when I stop movement then velocity is 0, but constraints still apply some and rod moves back. In the end I think I want something like pinhole with maximum friction.

3. Is there any other way to keep rod a bit more stiff without chain constraint? The problem with chain is that it does not allow to calculate tension correctly, but more important it's simply unstable, because it tries to find proper position no matter what and rod shakes or does other undesired movements.

4. I think you mentioned that Obi 7.2 should have elasticity for rod control points, is that still planned for next version? If yes, is there any ETA?
Reply
#15
(08-09-2025, 04:01 PM)Qriva0 Wrote: Hi again, I tested various solutions and I wanted to confirm several things.

1. The problem I want to solve is controlling/pushing the cable (rod), but from the middle part, not the tip. 
There are two obstacles on my way, first one is the fact that pushing it requires forces to propagate and it can make the cable very wiggly or stretch even with big amount of substeps (15-20), and second one is keeping the cable fixed by some particle and this is related to second point:

2. Changing particle position teleports it and it does not apply any forces, however if there are other particles, then the whole actor can gain valocity because constraints try to keep particles in their proper positions. In this case does that mean that I should not move rod by changing position of single particle? If yes, then how to move particle via velocity, and keep it pushed, so it does not pull back from forces or collision? Adding velocity or externalForces will stack, while overriding velocity will cancel all other forces plus when I stop movement then velocity is 0, but constraints still apply some and rod moves back. In the end I think I want something like pinhole with maximum friction.
Not sure whether there is any difference but I could add force at the middle of Obi rod with no problem.(Checkout my post, it's a fishing game where I can pull the rod though it's not shown in the gif: https://obi.virtualmethodstudio.com/foru...-4511.html). Could you post a screenshot/video to show the problem and how do you "add force"?
Reply
#16
(09-09-2025, 02:46 AM)chenji Wrote: Not sure whether there is any difference but I could add force at the middle of Obi rope with no problem.(Checkout my post, it's a fishing game where I can pull the rod though it's not shown in the gif: https://obi.virtualmethodstudio.com/foru...-4511.html). Could you post a screenshot/video to show the problem and how do you "add force"?

To be more precise, it's not like it does not work at all, but result seems to be not stable and "physical" in some way?
For example collision is kind of "forced" against various surfaces, especially if it's soft body or cloth, forcing to break constraints and in result less stable.

When it comes to adding force, yes I can add force, but it's not enough to keep rod in place where it supposed to be, so position must be corrected, but it also does not seem fully right, because when movement is a bit faster it kind of breaks (when particle delta is close or larger than distance between particles), I just pull/pull single particle, there is too much violence I guess  Gran sonrisa

I also tried propagate forces in selected part of cable - this helps, but in general I am not satisfied and I want to know how to move it properly or what could be good trick to make it work better.
Reply
#17
(09-09-2025, 09:56 AM)Qriva0 Wrote: To be more precise, it's not like it does not work at all, but result seems to be not stable and "physical" in some way?
For example collision is kind of "forced" against various surfaces, especially if it's soft body or cloth, forcing to break constraints and in result less stable.

When it comes to adding force, yes I can add force, but it's not enough to keep rod in place where it supposed to be, so position must be corrected, but it also does not seem fully right, because when movement is a bit faster it kind of breaks (when particle delta is close or larger than distance between particles), I just pull/pull single particle, there is too much violence I guess  Gran sonrisa

I also tried propagate forces in selected part of cable - this helps, but in general I am not satisfied and I want to know how to move it properly or what could be good trick to make it work better.
I'm not sure why you have to add force on one particle. Here is what I did:
1. Have an object that is a dynamically attachment of a Obi Rod.
2. Use Unity's AddForceAtPosition to add force at any position to this object
3. Make sure World linear inertia scale/angular inertia scale is set collectly in the Obi solver

If you're not using Unity's AddForceAtPosition you probably need to do something like this. It's copied from AI consult, which I have not tried myself so just FYI:

using Obi;
using UnityEngine;

public class ObiForceAtPosition : MonoBehaviour
{
public ObiActor obiActor; // 你的ObiRope/ObiRod等
public float forceRadius = 1.0f; // 力的作用半径

// 在指定位置施加力
public void AddForceAtPosition(Vector3 force, Vector3 position, ForceMode mode)
{
if (obiActor == null || obiActor.solver == null)
return;

ObiSolver solver = obiActor.solver;

// 遍历所有粒子
foreach (int particleIndex in obiActor.particleIndices)
{
// 获取粒子在世界空间的位置
Vector3 particlePos = solver.transform.TransformPoint(solver.positions[particleIndex]);
float distance = Vector3.Distance(position, particlePos);

// 如果粒子在作用范围内
if (distance <= forceRadius)
{
// 线性衰减权重 (1 -> 0)
float weight = 1 - (distance / forceRadius);
Vector3 particleForce = force * weight;

// 施加力到粒子
solver.ApplyImpulse(particleIndex, particleForce, Vector3.zero);
}
}
}

// 示例:在鼠标点击位置施加力
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
AddForceAtPosition(Vector3.up * 10, hit.point, ForceMode.Impulse);
}
}
}
}
Reply
#18
(08-09-2025, 04:01 PM)Qriva0 Wrote: Hi again, I tested various solutions and I wanted to confirm several things.

1. The problem I want to solve is controlling/pushing the cable (rod), but from the middle part, not the tip. 
There are two obstacles on my way, first one is the fact that pushing it requires forces to propagate and it can make the cable very wiggly or stretch even with big amount of substeps (15-20),

Hi,

Modifying the velocity of the particle is the proper way to do this. This can be done by either writing into the velocities array, or writing into the externalForces array (forces get reset to zero after each step, and they result in an acceleration that depends on the mass of the particle, but at the end of the day they also modify the velocity).

(08-09-2025, 04:01 PM)Qriva0 Wrote: and second one is keeping the cable fixed by some particle and this is related to second point:

2. Changing particle position teleports it and it does not apply any forces, however if there are other particles, then the whole actor can gain valocity because constraints try to keep particles in their proper positions. In this case does that mean that I should not move rod by changing position of single particle? If yes, then how to move particle via velocity, and keep it pushed, so it does not pull back from forces or collision? Adding velocity or externalForces will stack, while overriding velocity will cancel all other forces plus when I stop movement then velocity is 0, but constraints still apply some and rod moves back. In the end I think I want something like pinhole with maximum friction.

If I understood correctly, you just want to just override the position of a particle? this can be done by setting the particle's inverse mass to zero. This will cause it to ignore forces (both internal/due to constraints and external) and you can just set its position. Reverting the inverse mass to its original value resumes dynamics simulation for the particle. This is how static attachments work internally. See: https://obi.virtualmethodstudio.com/manu...icles.html

(08-09-2025, 04:01 PM)Qriva0 Wrote: 3. Is there any other way to keep rod a bit more stiff without chain constraint? The problem with chain is that it does not allow to calculate tension correctly, but more important it's simply unstable, because it tries to find proper position no matter what and rod shakes or does other undesired movements.

Chain constraints use a direct solver that calculates a position change for all particles simultaneously, so that they meet a global length constraint. This can be unstable if the solution isn't "near" the current state of the rod, or if there's simply no solution to the problem.

The alternative is using an iterative solver, which is how most other constraints (distance, stretch/shear, bend/twist, etc) in Obi work. These can yield approximate/good enough solutions even if they can't find *the* solution. Unfortunately this means you must rely on substeps/iterations to keep it stiff. Still, a moderate amount of substeps should yield rather stiff rods/ropes unless extreme forces, lengths, or resolutions are involved. Could you explain a bit more about your use case?

(08-09-2025, 04:01 PM)Qriva0 Wrote: 4. I think you mentioned that Obi 7.2 should have elasticity for rod control points, is that still planned for next version? If yes, is there any ETA?

Yes, still planned. ETA is end of October. There's many more changes coming to 7.2.

kind regards,
Reply
#19
(09-09-2025, 02:18 PM)josemendez Wrote: Modifying the velocity of the particle is the proper way to do this. This can be done by either writing into the velocities array, or writing into the externalForces array (forces get reset to zero after each step, and they result in an acceleration that depends on the mass of the particle, but at the end of the day they also modify the velocity).

Yeah, I tried both methods. The problem is that I don't move rod by pressing the keyboard arrow, but I try to keep it in sync with some depth value - for instance it's 10 meters at some point, but several frames later it will be 11 and rod should reflect that by moving 1m forward. There are two problems with that.
First one is pullback. I don't want my cable to go back on collision and that is the reason why I tried to "pin" particle - to disallow pullback from tension. I also thought about calculating tension to detect such a case and disable further movements against collider, because moving particle position directly forces constraints to break.
Second is related to first one. When movement is stopped, then velocity is 0 and other forces, constraints, collisions can move rod in general and it's not in sync anymore. I guess I would need to change approach to moving rod particle by invisible line, something like softbody dragon demo?

(09-09-2025, 02:18 PM)josemendez Wrote: If I understood correctly, you just want to just override the position of a particle? this can be done by setting the particle's inverse mass to zero. This will cause it to ignore forces (both internal/due to constraints and external) and you can just set its position. Reverting the inverse mass to its original value resumes dynamics simulation for the particle. This is how static attachments work internally. See: https://obi.virtualmethodstudio.com/manu...icles.html

I wanted, but that causes a lot of not physical things to happen, jitters or breaking constraints. Does pinhole do that actually? I think it does not.

(09-09-2025, 02:18 PM)josemendez Wrote: The alternative is using an iterative solver, which is how most other constraints (distance, stretch/shear, bend/twist, etc) in Obi work. These can yield approximate/good enough solutions even if they can't find *the* solution. Unfortunately this means you must rely on substeps/iterations to keep it stiff. Still, a moderate amount of substeps should yield rather stiff rods/ropes unless extreme forces, lengths, or resolutions are involved. Could you explain a bit more about your use case?

This is what I did, I increased solver substeps and iterations, but my rod is quite long and sometimes there might be sudden force shift (not sure to call it extreme), so in the end it's still not enough and the effect is that particles "float" or wiggle with delay. In my case rod is some kind of stiff cable and when I pull it I need the whole thing to move at the same time. You know, when you pull a plastic cable in reality it does not strech much, but the whole length moves at the same time.
My current solution do this problem is adding forces along the rope (according to particle orientations), not perfect, but definitely better than nothing. However I still  wonder if there is anything else I could do.

(09-09-2025, 02:18 PM)josemendez Wrote: Yes, still planned. ETA is end of October. There's many more changes coming to 7.2.

Nice! This is great news!
Reply
#20
(Yesterday, 09:39 AM)Qriva0 Wrote: Yeah, I tried both methods. The problem is that I don't move rod by pressing the keyboard arrow, but I try to keep it in sync with some depth value - for instance it's 10 meters at some point, but several frames later it will be 11 and rod should reflect that by moving 1m forward.
What are you trying to simulate with Obi rod? Maybe tell us a real world counterpart would be helpful.
Reply