Search Unity

Assets Obi Particle Based Physics (Cloth, Rope, Fluid) thread

Discussion in 'Works In Progress' started by arkano22, Jun 30, 2015.

?

Performance vs compatibility

Poll closed Oct 9, 2015.
  1. I don't care about performance, keep my data intact please.

    0 vote(s)
    0.0%
  2. I don't care if I have to re-do some stuff, as long as it runs faster.

    14 vote(s)
    100.0%
  1. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    HI Medto!

    The bridge scene is not included, but it uses Pin Constraints to get the planks attached to the ropes. The "Chain" and "Crane" scenes use pin constraints too to attach rigidbodies to the rope, so take a look at them. Also see:

    http://obi.virtualmethodstudio.com/tutorials/pinconstraints.html
     
  2. Medto

    Medto

    Joined:
    Oct 28, 2015
    Posts:
    8
    Damn , I was trying hard on this with the pin constraint, I suppose I'm doing something wrong, thank you btw
     
  3. maccoy

    maccoy

    Joined:
    Mar 4, 2015
    Posts:
    12
    Goodevening, not sure what happened to my initial message, theyve must have done a rollback due to the hacks but anyway.

    Bought obicloth3....seems pretty straightforward on what to do...waaay. But im running into a problem when i instantiate pieces of clothing with obicloth on them. The skinned piece is behind one frame . Its all good when i have it on the character from the beginning.

    Any ideas on how to fix?
     
  4. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi macoy,

    How are you instantiating these pieces? Using GameObject.Instantiate on a prefab works just fine for me. Can you share the code?
     
  5. maccoy

    maccoy

    Joined:
    Mar 4, 2015
    Posts:
    12
    as i was looking at the code cleaning it up, adding comments as to what i was doing to make it a bit more readable......i suddenly fixed it and it turns out....

    if you do
    GameObject TheClothing = Instantiate(theprefab, transform)as GameObject;
    it all works....no one frame lag on the cloth, it looks fantastic.... but if you do

    GameObject TheClothing =Instantiate(theprefab) as GameObject;
    TheClothing.transform.SetParent(transform);


    it lags behind one frame.

    i wrote that code way back when i didn't know you could set the parent as you instantiated the gameobject, as i was cleaning up the code i changed stuff to the first example and suddenly it worked....


    anyway, great tool youve made, im off to experiment some more with it.
     
  6. james14123

    james14123

    Joined:
    Jan 22, 2017
    Posts:
    20
    Hi
    Will Obi Cloth add the some special material like denim ?
    The parameter of cloth simulation in Blender have the structure parameter which can make cloth like more realistic.
    Or is there maybe any better idea about it?
     
  7. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi there,

    You have independent bend, stretch and damping parameters, which you can tune to create any effect your'e after: denim, silk, leather, etc. Also you can control particle masses, which allows you to freely distribute weight over your cloth, for lighter and heavier regions.

    Cloth simulation in blender probably uses a continuum method such as FEM, strain-based or projective dynamics, which consider whole triangles instead of just the vertices. This allows for finer adjustment of parameters and topology independence, but it is considerably slower to simulate and therefore not ideal for a realtime simulator. It is very unlikely that Obi will switch to a solver of this kind in the future, since in games performance is paramount, and the advantages of doing so are questionable out of the VFX realm.
     
    Last edited: May 4, 2017
  8. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Weird, I cannot reproduce the second case either. Anyway, I´m glad that you figured it out!
     
  9. OnlyVR

    OnlyVR

    Joined:
    Oct 5, 2015
    Posts:
    54
    Yes, Obi Cloth works great in VR(Vive). I will upload the video very soon.
     
  10. OnlyVR

    OnlyVR

    Joined:
    Oct 5, 2015
    Posts:
    54
  11. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
  12. Falagard

    Falagard

    Joined:
    Jan 8, 2014
    Posts:
    43
    Just out of curiosity can you "bake" a mesh from a simulated cloth? I'd like to be able to use Obi cloth to make curtains or a blanket and then make it static and remove the Obi cloth component.
     
  13. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    There's not an out-of-the-box "button" to bake the cloth mesh, but you do have access to the modified mesh every frame. Just a single line of code:

    <your ObiCloth component>.clothMesh

    Then you can do whatever you want to do with this mesh: instantiate it, save it as an asset, you name it.
     
  14. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Hey, I have an issue. So I have been playing with OBI rope to great success. This is something that will cause me a huge headache though:
    For my setup to work, I'm using ropes that have 0 gravity. Sadly I just realized that the gravity is set in the solver and here's the thing: I also wanted to use OBI cloth to interact with my ropes. But since the cloths will have to use the same solver to interact with my ropes, they will have 0 gravity as well, is that correct? What can I do to have OBI objects interact that dont all have the same weight?
    (edit: I'm an idiot, the answer is right a few steps above...)
    (edit 2: Okay using the mass of the particles does not solve the issue for me. I need the rope to be weightless but still retain mass, so it can still affect other physical object with its momentum! I guess I can try to give the cloths huge amount of mass, while setting gravity to low? but then interacting with it will still not have the desired outcome, will it...)
    (edit 3: I tried to use force zones to compensate for gravity, but those only work for solvers too. I'm out of ideas now.)
     
    Last edited: May 13, 2017
  15. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Last edited: May 13, 2017
  16. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Objects of different weights (different masses) will fall at the same speed under the effects of gravity in absence of air friction (which is usually not accounted for in games, with the exception of cloth aerodynamics in Obi). So you won´t be able to affect gravity by changing the object's mass, it's just... physics.

    Given that a "solver" represents a "world" or environment, all the objects in it are affected by the same gravity. Since you need the ropes and the cloth to be affected by different gravitational accelerations, you need them to be in separate solvers. But of course this means they won´t be able to collide or interact with each other.

    The way I see it, your only approach to this would be to implement your own per-particle gravitational acceleration. This requires some simple scripting, however.

    Each actor (cloth, rope, etc) has a "velocities" array. These are velocities of the particles used by the actor. You can modify these velocities and then call actor.PushDataToSolver(ParticleData.VELOCITIES); to make the changes effective.

    Edit: to be more specific: you´ll need to iterate over all the entries in the "velocities" array and do this:
    velocities += myCustomGravity * Time.fixedDeltaTime.
    after the loop, call PushDataToSolver to update the velocities. You have to do all of this in FixedUpdate().
     
    Last edited: May 13, 2017
  17. OnlyVR

    OnlyVR

    Joined:
    Oct 5, 2015
    Posts:
    54
    I just check each point of the cloth in loop. I don't think it can affect the performance because we need to do this just once, when the trigger was pressed first time.

    Below is a fragment of the code. sqrMagnitude defiantly can be removed from the loop.

    currentCollisionMesh = GameObject.Instantiate(cloth.clothMesh);
    Vector3[] vertices = currentCollisionMesh.vertices;

    int closestVertex = -1;
    float minDistance = float.MaxValue;

    for (int k = 0; k < vertices.Length; k++)
    {
    float distance = (this.transform.TransformPoint(vertices[k]) - hand.transform.position).sqrMagnitude;
    if (distance < minDistance)
    {
    minDistance = distance;
    closestVertex = k;
    }
    }
     
    carmofin likes this.
  18. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi OnlyVR!

    This works for cloth (thanks for sharing the code as other people might benefit from it), but for rope you'd have to iterate over particle positions since there's not a direct correspondence between the rope mesh and the particles (ropes might even have no mesh at all).

    The code is quite similar though, but you have to iterate over particles instead of mesh vertices. Also, particle positions are expressed in world space by default so no need to call TransformPoint.
    Code (CSharp):
    1.  
    2. int closestParticle = -1;
    3. float minDistance = float.MaxValue;
    4.  
    5. for (int i = 0; i < rope.particleIndices.Length; ++i)
    6. {
    7.     float distance = (rope.Solver.renderablePositions[particleIndices[i]] - hand.transform.position).sqrMagnitude;
    8.     if (distance < minDistance)
    9.     {
    10.         minDistance = distance;
    11.         closestParticle = i;
    12.     }
    13. }
    14.  
     
    carmofin likes this.
  19. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Thanks, I'll definately give this a shot when I get to it!
     
  20. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Now this looks very helpfull, thank you both so much! I'll go ahead and assume its fine to cast the Vctor4 object by renderablepositions to a Vector3 object, right?
    So lets say I found the closest particle, the question is still how you can access it and make it sticky! Maybe I missed something in the documentation, but I haven't found anything in the Scripting section! Essentially I'm looking for how to set a pin from the rope to the object the script runs on!
     
    Last edited: May 13, 2017
  21. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Ok gave this a try, works beautifully, thank you! No idea how performant it is (oh wait I only have to do this once I guess!), but for now it'll do. Little piece of advice: Don't do this to particales you have fixed and thus have an infintie weight... haha!
     
  22. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    You can set the particle inverse mass and velocity to zero (which is basically what "fixing" a particle does) and its position to whatever you want it to be. To do this for a single particle with affecting any other, and without having to push the entire arrays to the solver (which is expensive) you can use the Oni. SetParticlePositions/ SetParticleVelocities/ SetParticleInverseMasses methods. Take a look at ObiParticleHandle.cs to see how these methods are used.
     
  23. macdude2

    macdude2

    Joined:
    Sep 22, 2010
    Posts:
    685
    Arkano - I'm not seeing the rope constraints (that minimized stretchiness) in the new 3.0 build of Obi Rope. Are they hiding somewhere or is this constraint type no longer included?
     
    Last edited: May 15, 2017
  24. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi Macdude,

    Chain constraints were removed in 3.x because they caused more issues than they resolved (to be more specific: they were too numerically unstable). The preferred approaches now are to: crank up the amount of distance constraint iterations (the solver is much faster so it can handle it), reduce rope resolution (rope geometry is smoothed using a spline so good visuals can be achieved for low-res ropes) and/or use tether constraints.
     
  25. james14123

    james14123

    Joined:
    Jan 22, 2017
    Posts:
    20
    Hi, I tried to use the proxy to make cloth (no thickness) drive the same cloth (have thickness).
    In my case , if i just drive some part , the proxy is perfect.
    But if i choose the whole cloth to drive , the result is as below.
    The Thickness is made by solidify in blender.



    Is there some trouble in my cloth mesh ?

    Thanks !
     
  26. macdude2

    macdude2

    Joined:
    Sep 22, 2010
    Posts:
    685
    Ok, no worries! I'll try doing that!
     
  27. sashahush

    sashahush

    Joined:
    Sep 5, 2012
    Posts:
    75
    Hi there! I've upgraded to the latest OBI cloth and its fantastic. One effect i would like to achieve is very stiff cloth (bendable metal) being teared apart by wind. Would this be possible?
     
  28. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Make sure bend constraint stiffness is 1, max bending is 0, and increase the amount of bend constraints iterations in the solver until it is rigid enough. You might need a lot of iterations if your mesh is dense, so keep an eye on performance.

    The simpler your mesh (i.e. less polygons) the easier it will be for Obi to keep it rigid. Note that cloth != metal, so Obi isn´t designed to simulate such stiff materials (it can approximate them to an extent, though).
     
    sashahush likes this.
  29. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi! Without taking a look at the actual mesh it is hard to tell what's happening. Make sure you have only one skin channel completely painted when binding the meshes.

    Hint: since your "thick" mesh seems quite thin and doesn't have any complex features, you might get away with skipping proxies entirely and just using the backfaces shader on your source mesh.
     
  30. sashahush

    sashahush

    Joined:
    Sep 5, 2012
    Posts:
    75
    Thanks very much for the quick reply!
     
  31. james14123

    james14123

    Joined:
    Jan 22, 2017
    Posts:
    20
  32. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    I had a look at this but I am stumped.

    I assume this is how I get access to a particle, is that correct?
    ObiActor Actor [get, set]
    I feed the int I found from that part of code and thats the correct particle?

    Now even if that is true, how do I get access to the particlehandle of my particular solver?
     
  33. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi Carmofin,

    I´m a bit confused by your question. You quoted a response to another post regarding proxies, and don't see how is it related to accessing particles or handles.

    Can you describe what you're trying to achieve?
     
  34. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Sorry, this is the post I meant!
    I'm still working on being able to grab a rope!

    edit: Eh, my question seems to be answered here: http://obi.virtualmethodstudio.com/tutorials/scriptingparticles.html
    Was this here lst week? I feel a bit dumb...

    edit2: No, this solution will not let you grab something at all! It seems that if you continously push data to the solver, the simulation will stop. Back to square 1....
     
    Last edited: May 20, 2017
  35. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Ok, so I give up. I managed to read everything I could possibly want, but writing it just impossible.
    I turn this on first: actor.Solver.RequireRenderablePositions();
    I wait a frame.
    Then I calculate which particle to stick to my target and set its position to it.
    The I push the Data to the solver, which causes the simulation to reset essentially. If i Do this in the loop, the particle is stuck to my target, but all other particles reset indefinately and the cloth stands still.

    I'm at a total loss at what to do. I do not understand why it isn't possible to just dynamically create a handle, I feel like I'm trying to achieve something that should be really simple :/
     
  36. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi carmofin,

    Have you tried to use the functions I previously suggested? (SetParticlePositions/SetParticleVelocities/SetParticleInverseMasses, etc..) for instance:

    Code (CSharp):
    1. Oni.SetParticlePositions(rope.Solver.OniSolver,new Vector4[]{newPosition},1,rope.particleIndices[particleIndex]);
    this would give the position "newPosition" (in world space) to the particle "particleIndex" in the rope.

    Using PushDataToSolver() pushes ALL particle properties to the solver. If you have only modified 1 particle, then the rest will have the same position they had at startup and calling this will of course reset the cloth pose. This should be used when you want to modify all particles, to speed up memory transfers.

    Take a look at ObiParticleHandle.cs to see an actual example. Note that you can also just create a handle at runtime using this class. You don´t have to roll your own unless you want to do something different than what ObiHandle does. Here's what creating a handle at runtime looks like:

    Code (CSharp):
    1.  
    2. ObiParticleHandle handle = object.AddComponent<ObiParticleHandle>();
    3. handle.Actor = rope;
    4.  
    5. // Add a particle to the handle:
    6. handle.AddParticle(index,worldSpacePosition,rope.invMasses[index]);
    7.  
     
    Last edited: May 20, 2017
  37. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Ahhhh, this simple... Gonna try this right away, thanks for the patient reply...
    To my defense, I did search throgh the API for "Handle" but it didn'T yield any results.
     
  38. carmofin

    carmofin

    Joined:
    May 13, 2017
    Posts:
    10
    Phew, that took me a while, but it works absolutely perfectly now, thanks for all the tips.
    After failing to use handles miserably, I managed to manipulate a particle instead. Interestingly, that is no workable solution. Somehow the particle works rather isolated and barely has any influence on the rest of the mesh.
    So I went back to handles and sure enough, got them to work. Now I can do precisely what I wanted, I'll have to make a video one of these days.
     
    arkano22 likes this.
  39. Zomby138

    Zomby138

    Joined:
    Nov 3, 2009
    Posts:
    652
    I'm having trouble getting my character's cloth to work when I switch them over to ragdoll mode.

    Basically I have a load of rigidbodys in the character that are usually set as kinematic. They have colliders attached that are used in the ObiColliderGroup quite successfully. Then when I want to go into ragdoll mode I turn off kinematic and the character crumples nicely, but the cloth explodes asymptotically in all directions :( then usually crashes the editor a few seconds later.

    It seems to me that if I have rigidbody controlled colliders in the ObiColliderGroup then it behaves ok, until one of those colliders makes it's way inside the cloth, or something... maybe inside the bounding volume. Not sure.

    Have you tried doing cloth on ragdolls?
     
  40. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,406
    Have you guys thought about offloading simulation to a separate thread? We have problems getting 1.x to perform well enough for production use, it renders so much overhead on the render thread that rest of gamelogic are given to little time. I will try to port to 3.x
     
  41. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    1.x wasn´t multithreaded at all, and was written in C#. 2.x was rewritten in C++ and used a simple multithreading scheme in which each cloth was assigned to a different core.

    3.x uses a task-based multithreading scheme with job-stealing that evenly splits the workload of any parallelizable operation across your CPU's logical cores. This means multiple small cloth objects can be updated together in a single thread, or a big cloth mesh can be split in different tasks and updated in multiple threads. As a result, 3.x is around 20 times faster (on my 4-core machine at least) than 1.x, so I´d say switch to 3.x ;)

    Edit: You can take a look at this post to see differences in 3.x:
    http://blog.virtualmethodstudio.com/2017/01/obi-cloth-3-0-for-unity-whats-new/
     
    Last edited: May 24, 2017
  42. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi Zomby,

    Without taking a look at your setup is very difficult to tell what's happening. My guess would be large mass ratios between the ragdoll rigidbodies and the cloth, but cannot tell for sure.
     
  43. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,406
    Sounds like we need to upgrade then, I might have a ton of questions, we init the ropes from code instead of editor, and alot of that is broken in 3.x


    (I talk about 3.x of obi rope, didnt find a obi rope forum thread)
     
  44. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,406
    i need to check which verson we are actually on, I though it was 1.x but its calling a C API underneath so it must be 2.x then? Anyway, it takes several milliseconds on the render thread, so it does not seem multithreaded. And allocates way too much garbage each frame

     
  45. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi Anders,

    The profiler shows that the physics are being updated in FixedUpdate() (as they should). This doesn't mean they are being updated in the render thread, as the Unity profiler cannot show additional threads being run in an external plugin, simply because it doesn't know what the plugin is doing underneath. All the profiler is telling you is that the render thread is waiting for the physics to finish being updated (which cannot be avoided!). Whether the physics are being updated in the same thread, a different thread, or 8 threads, it cannot know.

    If you have 3.x already, add the ObiProfiler component to your solver. This will show you at runtime the actual threads inside the C++ plugin, with timing info for all the tasks being performed.

    I see that your FixedUpdate is being called three times per frame on average. You´d benefit from lowering the max physics timestep in Unity, to bring that down to 1 or 2 at most. You're basically running at 1/3 the performance you could achieve because of this.
     
  46. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,406
    I did that but it completely changed the behavior of our other objects, everything is physics driven in our game. But I will move to 3.x first. Maube you have optimized som of that big 76k garbage you see in my profiler?

    Tip, remove all calls to GetComponent each frame, remove any foreach, remove any code that can cause boxing of value types. All that will generate garbage and the Mono GC in Unity is very, very bad at handling this
     
  47. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi Anders,

    3.x only generates about 2kb per physics update, most of it due to collider related stuff since we have to copy data from Unity's colliders to our own collider representation every frame. Depending on the amount of colliders you have in the ColliderGroup, it will need to allocate more.

    We´ve already done all obvious optimizations in our code. No GetComponents every frame. Foreach is only used in methods that aren´t called every frame but only at edit time (like tether generation).

    Anyway all of this is of very little importance compared to the overhead of the solver itself.

    Edit: Now, if reducing the max timestep makes all your physics go "in slow motion", then your bottleneck is probably the solver. Check the amount of constraint iterations you're using and the resolution of your ropes. Reducing any of them will improve performance. 3.x allows you to decouple physical resolution and rendering resolution, so you can have very smooth ropes made only of a few particles. Fewer particles also reduce the need for high iterations counts, so it's a win-win situation. See the "smoothing" parameter here: http://obi.virtualmethodstudio.com/tutorials/ropesetup.html
     
    Last edited: May 24, 2017
  48. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,406
    Cool, will update to 3.x and we can continue the discussion after that :D
    2k is stilll alot (But not crazy alot like 76k :D). Well, the mono GC in Unity is crap, when it collects alot of data if willl cause a CPU spike. So when it does spike it will create a framedrop, thats why its so important to generate close to zero amount of garbage in unity. Our game allocates just a few bytes each frame. The colliders wont change reference wise between frames in most cases, the values will, but value types are not put on the heap so not a problem. With my limited knowledge of your library I see no reason to allocate 2k :D But let me update to 3.x and profile first
     
  49. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    647
    Hi Anders!

    We´ll make sure to watch our memory consumption closely for the upcoming updates. However (afaik) there's little left to be made in terms of optimization in our code. One always finds new opportunities for slight optimizations each time you look and those can add up to significant gains, so I´ll take the time to dive in our codebase and look for these.
     
    AndersMalmgren likes this.
  50. Zomby138

    Zomby138

    Joined:
    Nov 3, 2009
    Posts:
    652
    How/where do I define the mass of the cloth?
     
unityunity