Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Rope created at runtime is longer than the distance between the two connection points
#1
[Image: img.png]

Code:
            const string STAND_PARTICLE_GROUP = "PointOnStand";
            const string TARGET_PARTICLE_GROUP = "PointOnTarget";

            int standFilter = Obi.ObiUtils.MakeFilter(Obi.ObiUtils.CollideWithEverything, 0);
            int targetFilter = Obi.ObiUtils.MakeFilter(Obi.ObiUtils.CollideWithNothing, 0);

            var localHit = pointOnStand.transform.InverseTransformPoint(pointOnTarget.position);

            var blueprint = ScriptableObject.CreateInstance<Obi.ObiRopeBlueprint>();
            blueprint.resolution = 0.5f;

            blueprint.path.Clear();
            blueprint.path.AddControlPoint(Vector3.zero, -localHit.normalized, localHit.normalized, Vector3.up, 0.1f, 0.1f, thickness, standFilter, UnityEngine.Color.white, STAND_PARTICLE_GROUP);
            blueprint.path.AddControlPoint(localHit, -localHit.normalized, localHit.normalized, Vector3.up, 0.1f, 0.1f, thickness, targetFilter, UnityEngine.Color.white, TARGET_PARTICLE_GROUP);
            blueprint.path.FlushEvents();

            var generate = blueprint.Generate();
            while (generate.MoveNext()) ;

            var ropeGameObject = new GameObject("Rope",
                typeof(Obi.ObiRope),
                typeof(Obi.ObiPathSmoother),
                typeof(Obi.ObiRopeChainRenderer));

            ropeGameObject.transform.SetParent(solver.transform);

            var ropeChainRenderer = ropeGameObject.GetComponent<Obi.ObiRopeChainRenderer>();
            ropeChainRenderer.linkPrefabs.Add(chainPrefab);
            ropeChainRenderer.sectionTwist = 90;
            ropeChainRenderer.linkScale = Vector3.one;

            var rope = ropeGameObject.GetComponent<Obi.ObiRope>();
            rope.ropeBlueprint = blueprint;

            if (!standEntity.ObiStandColliders.TryGetValue(pointOnStand, out var standObiColliderGO))
            {
                standObiColliderGO = GameObjectPool.For(m_StandObiColliderPrefab).Rent();
                standObiColliderGO.transform.SetParent(pointOnStand.parent);
                standObiColliderGO.transform.localScale = Vector3.one * 0.005f;
                standEntity.ObiStandColliders[pointOnStand] = standObiColliderGO;
            }

            standObiColliderGO.transform.position = pointOnStand.position;
            standObiColliderGO.transform.rotation = pointOnStand.rotation;
            standObiColliderGO.transform.localScale = pointOnStand.localScale;

            var standObiCollider = standObiColliderGO.GetComponent<Obi.ObiColliderBase>();

            var pinConstraints = rope.GetConstraintsByType(Oni.ConstraintType.Pin) as Obi.ObiConstraints<Obi.ObiPinConstraintsBatch>;
            pinConstraints.Clear();
            var batch = new Obi.ObiPinConstraintsBatch();
            batch.AddConstraint(rope.solverIndices[0], standObiCollider, Vector3.zero, Quaternion.identity, 0, 0, float.PositiveInfinity);
            batch.AddConstraint(
                rope.solverIndices[blueprint.activeParticleCount - 1],
                target.GetComponent<Obi.ObiColliderBase>(),
                target.InverseTransformPoint(pointOnTarget.position),
                Quaternion.identity,
                0,
                0,
                float.PositiveInfinity);
            batch.activeConstraintCount = 2;
            pinConstraints.AddBatch(batch);
            rope.SetConstraintsDirty(Oni.ConstraintType.Pin);

I'm basically trying to create a chain between these two objects at runtime. The length of the chain should be the distance between those two red X's which mark "mount points" to create the chain between. The circle object isn't "hanging" down because I currently have the rigidbody set to kinematic.

Any ideas?
Reply
#2
Hi!
There's several possible causes for this (distance constraints stretching scale > 1, poor convergence due to iterations/substeps, among others). Going to assume everything else not shown in your code is set to default settings:

You know the distance between the two control points in a straight line, but what's the distance between them along the path? You're normalizing the path tangents, which means that for any distance that's roughly < 1 (the tangent length) the path will be a "flat curve" -move forward, then backwards, then forwards again- and as a result the rope will be longer than the distance between the points in a straight line.

Have you tried shortening the tangents?
Reply
#3
(06-04-2022, 07:49 AM)josemendez Wrote: Hi!
There's several possible causes for this (distance constraints stretching scale > 1, poor convergence due to iterations/substeps, among others). Going to assume everything else not shown in your code is set to default settings:

You know the distance between the two control points in a straight line, but what's the distance between them along the path? You're normalizing the path tangents, which means that for any distance that's roughly < 1 (the tangent length) the path will be a "flat curve" -move forward, then backwards, then forwards again- and as a result the rope will be longer than the distance between the points in a straight line.

Have you tried shortening the tangents?

Hey, doing what you said worked. I am having a different issue now though, which is:

  1. When creating the object initially, if it's kinematic, it's in the correct position and rope length is correct; however, once it becomes non-kinematic it sags pretty dramatically.
  2. After applying forces to the plate with bullet physics, the plate only moves backward; it does not return to its resting/hanging position. The only way I saw to fix this was to lower the pin relaxation value to 0.25.
[Image: screenshot.png]

I have fixed some of the issues with plate sticking; using 0.45 seems to be the highest relaxation that doesn't cause overly elastic movement. There is still more elasticity than I'd like for a chain. As well I configured the rotation compliance of the pin that's on the plate and set that value to one I found in Obi's source of "10000" to mean free-rotate. This creates a reasonably convincing look. Any advice on reducing the elasticity would still be helpful though.

The initial sagging though I still need to fix somehow.
Reply
#4
Well, I feel pretty dumb :|

I had some big colliders that were big enough I didn't see them when zoomed in. So effectively they've been doing their physics inside of one of the colliders that the objects are mounted to via pins. 

Anyway, it's fixed! Thank you for your help Sonrisa
Reply
#5
(06-04-2022, 11:27 PM)NailEngine Wrote: Anyway, it's fixed! Thank you for your help Sonrisa

No worries!

If excessive elasticity is still an issue, remember that:

- More iterations/substeps (specially substeps) will improve simulation quality and reduce spurious stretchiness. See:
http://obi.virtualmethodstudio.com/manua...gence.html

- In all physics engines, large mass ratios (eg, very heavy object hanging from a comparatively light rope) will increase stretchiness. Make sure objects have comparable masses. Within a 1:10 relationship is a good start.

kind regards,
Reply