Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Grab the middle of a rope?
#10
Alright I changed some things up, and you were on the right track. Instead of using Linq, Obi has a new method for the constraints called GetFirstBatch(), but the real problem was the colliders hit registration.

Here is the updated code for ObiRope 3.4 and VRTK 3.3.0 alpha. I have also attached the files which is probably easier lol.
This has minimal functionality, a lot of things can be done like attaching 2 particles on grab so the rope doesn't rotate while grabbing with one hand.

Add this to the same gameobject as ObiSolver:

Code:
using System.Collections;
using UnityEngine;
using Obi;
using VRTK;

[System.Serializable]
public class InteractingInfo
{
   [Header("Grab Options")]
   public bool grabbingEnabled = true;

   [Header("Pin Options")]
   public Vector3 pinOffset;
   [Range(0f, 1f)]
   public float stiffness = 1;

   [HideInInspector]
   public bool isTouchingParticle;
   [HideInInspector]
   public int touchingParticle;
   [HideInInspector]
   public int? grabbedParticle;
   [HideInInspector]
   public int? pinIndex;
   [HideInInspector]
   public VRTK_InteractGrab interactGrab;
   [HideInInspector]
   public Collider collider;
   [HideInInspector]
   public ObiCollider obiCollider;
   [HideInInspector]
   public VRTK_ObiInteractableActor currentInteraction;

   public void Clear()
   {
       isTouchingParticle = false;
   }
}

[RequireComponent(typeof(ObiSolver))]
public class VRTK_ObiInteractableSolver : MonoBehaviour
{
   #region Fields


   public Vector3 colliderSize;
   public Vector3 colliderOffset;
   public Vector3 colliderRotation;


   [Header("Controller Info")]

   public InteractingInfo leftControllerInfo = new InteractingInfo();
   public InteractingInfo rightControllerInfo = new InteractingInfo();

   private ObiSolver solver;

   private GameObject leftController;
   private GameObject rightController;

   #endregion


   #region Mono Events

   private void Awake()
   {
       solver = GetComponent<ObiSolver>();

       VRTK_SDKManager.instance.AddBehaviourToToggleOnLoadedSetupChange(this);
   }

   private void OnDestroy()
   {
       VRTK_SDKManager.instance.RemoveBehaviourToToggleOnLoadedSetupChange(this);
   }

   private void Reset()
   {
       colliderSize = new Vector3(0.06f, 0.06f, 0.06f);
       colliderOffset = new Vector3(0, 0, .02f);
       colliderRotation = new Vector3(45, 0, 0);
   }

   private void OnEnable()
   {
       leftController = VRTK.VRTK_DeviceFinder.GetControllerLeftHand(false);
       rightController = VRTK.VRTK_DeviceFinder.GetControllerRightHand(false);

       leftController.GetComponent<VRTK_ControllerEvents>().ControllerModelAvailable += ControllerModelAvailiable;
       rightController.GetComponent<VRTK_ControllerEvents>().ControllerModelAvailable += ControllerModelAvailiable;
       
       if (!ReferenceEquals(solver, null))
       {
           solver.OnCollision += HandleSolverCollision;
       }
   }

   private void OnDisable()
   {
       if (!ReferenceEquals(solver, null))
       {
           solver.OnCollision -= HandleSolverCollision;
       }
   }

   #endregion


   #region Private Methods


   private bool SetupController(GameObject controller, bool isLeft)
   {
       if (controller.transform.childCount == 0) return false;

       GameObject colliderObject = new GameObject();
       colliderObject.name = "ObiCollider";
       colliderObject.layer = LayerMask.NameToLayer("Ignore Raycast");
       colliderObject.transform.SetParent(controller.transform);
       colliderObject.transform.localPosition = colliderOffset;
       colliderObject.transform.localRotation = Quaternion.Euler(colliderRotation);

       var collider = colliderObject.AddComponent<BoxCollider>();
       collider.isTrigger = true;
       collider.size = colliderSize;

       var obiCollider = colliderObject.AddComponent<ObiCollider>();

       if (isLeft)
       {
           if (ReferenceEquals(obiCollider, null))
           {
               leftControllerInfo.obiCollider = colliderObject.gameObject.AddComponent<ObiCollider>();
           }
           else
           {
               leftControllerInfo.obiCollider = obiCollider;
           }

           leftControllerInfo.collider = colliderObject.GetComponent<Collider>();

           leftControllerInfo.interactGrab = controller.GetComponent<VRTK_InteractGrab>();
           leftControllerInfo.interactGrab.GrabButtonPressed += HandleGrabButtonPressed;
           leftControllerInfo.interactGrab.GrabButtonReleased += HandleGrabButtonReleased;
       }
       else
       {
           if (ReferenceEquals(obiCollider, null))
           {
               rightControllerInfo.obiCollider = colliderObject.gameObject.AddComponent<ObiCollider>();
           }
           else
           {
               rightControllerInfo.obiCollider = obiCollider;
           }

           rightControllerInfo.collider = colliderObject.GetComponent<Collider>();

           rightControllerInfo.interactGrab = controller.GetComponent<VRTK_InteractGrab>();
           rightControllerInfo.interactGrab.GrabButtonPressed += HandleGrabButtonPressed;
           rightControllerInfo.interactGrab.GrabButtonReleased += HandleGrabButtonReleased;
       }

       return true;
   }

   #endregion


   #region Controller Events

   private void ControllerModelAvailiable(object sender, ControllerInteractionEventArgs e)
   {
       StartCoroutine(ModelLoaded(sender as VRTK_ControllerEvents));
   }

   private IEnumerator ModelLoaded(VRTK_ControllerEvents events)
   {
       yield return new WaitForEndOfFrame();

       bool succeeded = true;

       if (ReferenceEquals(events.gameObject, leftController))
       {
           succeeded = SetupController(events.gameObject as GameObject, true);
       }
       else if (ReferenceEquals(events.gameObject, rightController))
       {
           succeeded = SetupController(events.gameObject as GameObject, false);
       }

       if (!succeeded)
           StartCoroutine(ModelLoaded(events as VRTK_ControllerEvents));
   }

   private void HandleGrabButtonPressed(object sender, ControllerInteractionEventArgs e)
   {
       if (ReferenceEquals(sender, leftControllerInfo.interactGrab) && leftControllerInfo.grabbingEnabled)
       {
           if (leftControllerInfo.isTouchingParticle)
           {
               // Get actor and apply constraint
               leftControllerInfo.currentInteraction.GrabActor(leftControllerInfo);
           }
       }
       else if (ReferenceEquals(sender, rightControllerInfo.interactGrab) && rightControllerInfo.grabbingEnabled)
       {
           if (rightControllerInfo.isTouchingParticle)
           {
               // Get actor and apply constraint
               rightControllerInfo.currentInteraction.GrabActor(rightControllerInfo);
           }
       }
   }

   private void HandleGrabButtonReleased(object sender, ControllerInteractionEventArgs e)
   {
       if (rightControllerInfo.grabbedParticle != null && ReferenceEquals(sender, rightControllerInfo.interactGrab) && rightControllerInfo.grabbingEnabled)
       {
           rightControllerInfo.currentInteraction.ReleaseActor(rightControllerInfo);

           if (leftControllerInfo.pinIndex.HasValue && leftControllerInfo.isTouchingParticle && leftControllerInfo.pinIndex > rightControllerInfo.pinIndex)
               leftControllerInfo.pinIndex--;

           rightControllerInfo.grabbedParticle = null;
           rightControllerInfo.pinIndex = null;

       }
       else if (leftControllerInfo.grabbedParticle != null && ReferenceEquals(sender, leftControllerInfo.interactGrab) && leftControllerInfo.grabbingEnabled)
       {
           leftControllerInfo.currentInteraction.ReleaseActor(leftControllerInfo);

           if (rightControllerInfo.pinIndex.HasValue && rightControllerInfo.isTouchingParticle && rightControllerInfo.pinIndex > leftControllerInfo.pinIndex)
               rightControllerInfo.pinIndex--;

           leftControllerInfo.grabbedParticle = null;
           leftControllerInfo.pinIndex = null;
       }
   }

   #endregion


   #region Obi Solver Events

   private void HandleSolverCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
   {
       if (e == null || e.contacts == null || !rightControllerInfo.grabbingEnabled && !leftControllerInfo.grabbingEnabled) return;

       // Reset every frame
       leftControllerInfo.Clear();
       rightControllerInfo.Clear();

       for (int i = 0; i < e.contacts.Count; ++i)
       {
           var contact = e.contacts[i];
           var pia = solver.particleToActor[e.contacts[i].particle];
           var actor = pia.actor;
           var particleIndex = pia.indexInActor;

           // make sure this is an actual contact
           if (contact.distance < 0.01f)
           {
               Collider collider = ObiColliderBase.idToCollider[contact.other] as Collider;

               if (ReferenceEquals(collider, leftControllerInfo.collider))
               {
                   leftControllerInfo.isTouchingParticle = true;
                   leftControllerInfo.touchingParticle = particleIndex;
                   leftControllerInfo.currentInteraction = actor.gameObject.GetComponent<VRTK_ObiInteractableActor>();
               }
               else if (ReferenceEquals(collider, rightControllerInfo.collider))
               {
                   rightControllerInfo.isTouchingParticle = true;
                   rightControllerInfo.touchingParticle = particleIndex;
                   rightControllerInfo.currentInteraction = actor.gameObject.GetComponent<VRTK_ObiInteractableActor>();
               }
           }
       }
   }

   #endregion

}

Add this to the same gameobject as your ObiActor:

Code:
using UnityEngine;
using Obi;

[RequireComponent(typeof(ObiPinConstraints))]
public class VRTK_ObiInteractableActor : MonoBehaviour
{
   #region Fields

   public bool isGrabbable = true;

   private ObiPinConstraints pinConstraints;

   #endregion


   #region Mono Events

   private void Awake()
   {
       pinConstraints = GetComponent<ObiPinConstraints>();
   }

   private void Reset()
   {
       isGrabbable = true;
   }

   #endregion


   #region Actor Interaction

   public void GrabActor(InteractingInfo interactingInfo)
   {
       if (!isGrabbable) return;

       ObiPinConstraintBatch batch = pinConstraints.GetFirstBatch() as ObiPinConstraintBatch;

       pinConstraints.RemoveFromSolver(null);

       interactingInfo.pinIndex = batch.ConstraintCount;
       interactingInfo.grabbedParticle = interactingInfo.touchingParticle;
       batch.AddConstraint(interactingInfo.grabbedParticle.Value, interactingInfo.obiCollider, interactingInfo.pinOffset, interactingInfo.stiffness);

       pinConstraints.AddToSolver(null);

       pinConstraints.PushDataToSolver();
   }

   public void ReleaseActor(InteractingInfo interactingInfo)
   {
       if (!isGrabbable) return;

       ObiPinConstraintBatch batch = pinConstraints.GetFirstBatch() as ObiPinConstraintBatch;

       pinConstraints.RemoveFromSolver(null);

       if (interactingInfo.pinIndex.HasValue)
           batch.RemoveConstraint(interactingInfo.pinIndex.Value);

       pinConstraints.AddToSolver(null);

       pinConstraints.PushDataToSolver();
   }

   #endregion

}


Attached Files
.cs   VRTK_ObiInteractableActor.cs (Size: 1.62 KB / Downloads: 40)
.cs   VRTK_ObiInteractableSolver.cs (Size: 9.38 KB / Downloads: 27)
Reply


Messages In This Thread
Grab the middle of a rope? - by BlueTel - 24-08-2017, 04:16 PM
RE: Grab the middle of a rope? - by josemendez - 24-08-2017, 05:47 PM
RE: Grab the middle of a rope? - by niZmo - 02-09-2017, 07:56 PM
RE: Grab the middle of a rope? - by Parker - 12-09-2017, 04:12 AM
RE: Grab the middle of a rope? - by niZmo - 12-09-2017, 04:31 AM
RE: Grab the middle of a rope? - by Parker - 12-09-2017, 02:01 PM
RE: Grab the middle of a rope? - by darkcser - 28-04-2018, 10:24 PM
RE: Grab the middle of a rope? - by niZmo - 30-04-2018, 06:42 PM
RE: Grab the middle of a rope? - by BlueTel - 08-09-2017, 04:20 PM
RE: Grab the middle of a rope? - by niZmo - 01-05-2018, 06:08 AM
RE: Grab the middle of a rope? - by darkcser - 02-05-2018, 05:19 AM
RE: Grab the middle of a rope? - by niZmo - 03-05-2018, 12:54 AM
RE: Grab the middle of a rope? - by darkcser - 04-05-2018, 04:13 PM
RE: Grab the middle of a rope? - by darkcser - 05-05-2018, 07:42 PM