Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Stitch Rope and Cloth
#1
Hello,

I am trying to use ObiStitcher to join a Rope and Cloth together. When I join two cloth softbodies it works as expected (see video)

https://drive.google.com/file/d/13UmvQ7Q...sp=sharing (setup)
https://drive.google.com/file/d/1H-3ShrF...sp=sharing (video)

But when I try to stitch a Rope and Cloth it seems that the stitch happens with the ground for some reason.

https://drive.google.com/file/d/1LAt1LaY...sp=sharing (setup)
https://drive.google.com/file/d/1iP3iU5n...sp=sharing (video)

I can't figure out what I am missing. Can someone please help.

Thanks
Reply
#2
(21-01-2022, 06:15 AM)bubbbles Wrote: Hello,

I am trying to use ObiStitcher to join a Rope and Cloth together. When I join two cloth softbodies it works as expected (see video)

https://drive.google.com/file/d/13UmvQ7Q...sp=sharing (setup)
https://drive.google.com/file/d/1H-3ShrF...sp=sharing (video)

But when I try to stitch a Rope and Cloth it seems that the stitch happens with the ground for some reason.

https://drive.google.com/file/d/1LAt1LaY...sp=sharing (setup)
https://drive.google.com/file/d/1iP3iU5n...sp=sharing (video)

I can't figure out what I am missing. Can someone please help.

Thanks

Hi there,

Just tried this and worked fine for me. Are all three actors (cloth, rope and stitcher) managed by the same solver? Keep in mind that actors in different solvers cannot interact with each other in any way and this includes stitches. Attempting to do this should raise an error message in the stitcher inspector, though.

Also, are you doing this by hand using the stitch editor, or are you creating the stitches programmatically? If so, can you share the code you're using?

Here's a video of my result (no collision detection):
Reply
#3
Hi,

Thanks for the reply.

Yeah I am trying to join them at runtime. But I'm facing the same issue where they don't stitch. Here is the code:

Code:
public ObiRope GenerateRope(Vector3 pointA, ObiCollider start, GameObject cloth)
{
        // Create a rope
        var ropeObject = new GameObject("rope", typeof(ObiRope), typeof(ObiRopeLineRenderer));
        rope = ropeObject.GetComponent<ObiRope>();
        var ropeRenderer = ropeObject.GetComponent<ObiRopeLineRenderer>();
        rope.GetComponent<MeshRenderer>().material = material;
        rope.GetComponent<ObiPathSmoother>().decimation = 0.1f;
        ropeRenderer.uvScale = new Vector2(1, 5);

        obiRopeExtrudedRenderer = ropeObject.AddComponent<ObiRopeExtrudedRenderer>();
        obiRopeExtrudedRenderer.section = section;
        obiRopeExtrudedRenderer.thicknessScale = ropeThicknessMax;

        // Setup a blueprint for the rope:
        var blueprint = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
        blueprint.resolution = blueprintResolution;
        blueprint.thickness = blueprintThickness;
        blueprint.pooledParticles = blueprintPooledParticles;

        // convert both points to the rope's local space:
        pointA = rope.transform.InverseTransformPoint(pointA);
        Vector3 pointB = cloth.GetComponent<ObiActor>().GetParticlePosition(1);
        pointB = rope.transform.InverseTransformPoint(pointB);

        // Procedurally generate the rope path (a simple straight line):
        Vector3 direction = (pointB - pointA) * 0.25f;
        blueprint.path.Clear();
        blueprint.path.AddControlPoint(pointA, -direction, direction, Vector3.up, 0.1f, 0.1f, 1, 1, Color.white, "A");
        blueprint.path.AddControlPoint(pointB, -direction, direction, Vector3.up, 0.1f, 0.1f, 1, 1, Color.white, "B");
        blueprint.path.FlushEvents();

        rope.ropeBlueprint = blueprint;

        rope.transform.parent = solver.transform;

        Material localMaterial = rope.GetComponent<MeshRenderer>().material;
        localMaterial.color = normalColor;

        ObiRopeCursor obiRopeCursor = ropeObject.AddComponent<ObiRopeCursor>();
        obiRopeCursor.cursorMu = 0;

        var myFilter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
        for (int i = 0; i < rope.solverIndices.Length; ++i)
            rope.solver.filters[rope.solverIndices[i]] = myFilter;

        PinRopeToWall(start, new Vector3(0, 0.5f, 0));
        StitchRopeTo(cloth);

        return rope;
}
   

private void PinRopeToWall(ObiCollider bodyA, Vector3 offsetA)
{
        var pinConstraints = rope.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
        pinConstraints.Clear();
        var batch = new ObiPinConstraintsBatch();
        batch.AddConstraint(rope.solverIndices[0], bodyA, offsetA, Quaternion.identity, 0, 999, float.PositiveInfinity);
        batch.activeConstraintCount = 1;
        pinConstraints.AddBatch(batch);
}

private void StitchRopeTo(GameObject cloth)
{
        ObiStitcher stitcher = gameObject.AddComponent<ObiStitcher>();
        stitcher.Actor1 = rope.GetComponent<ObiRope>();
        stitcher.Actor2 = cloth.GetComponent<ObiCloth>();
        stitcher.AddStitch(rope.solverIndices.Length - 1, 0);

        stitcher.PushDataToSolver();
}
Reply
#4
Hi,

You're passing the last particle allocated as the index for your rope, which is incorrect:

Code:
rope.solverIndices.Length - 1;

This does not guarantee it to be an active particle, in fact, by default it will be an inactive one (as it's the last particle of the pool).

Ropes can be resized (new particles added/removed) or torn. Tearable cloth can also be torn. To avoid runtime allocation, this is accomplished by preallocating more particles than needed to simulate the rope/cloth and deactivating the excess particles. Then as the rope needs new particles, inactive particles are activated. Same for tearable cloth.

By default, the size of the preallocation pool is 100 (you can change this size in the rope blueprint, see "pooled particles"): http://obi.virtualmethodstudio.com/manua...setup.html).

This means that if your rope is made of 10 particles, it will allocate 110 particles (from 0 to 109) and only the first 10 are active at first. So by accessing rope.solverIndices.Length - 1; you're getting particle #109 which is inactive: invisible, not part of the simulation, and at 0,0,0.

What you want to use is rope.activeParticleCount - 1. (see ObiActor's API documentation for details). Keep in mind that if you use a cursor to resize the rope or you cut the rope, this particle may *not* be at one end of the rope.

kind regards,
Reply