private void Start() { SlaveHandModel hand = model.proxyHand.slave; hand.palmCollisionNotifier.onRbEnter.AddListener(OnEnter_Special); hand.palmCollisionNotifier.onRbExit.AddListener(OnExit_Special); hand.thumb.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Special); hand.thumb.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Special); hand.index.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Default); hand.index.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Default); hand.middle.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Default); hand.middle.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Default); hand.ring.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Default); hand.ring.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Default); hand.pinky.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Default); hand.pinky.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Default); hand.handTrigger.onEnterRigidbody.AddListener(OnEnter_Hover); hand.handTrigger.onExitRigidbody.AddListener(OnExit_Hover); }
public static void IgnoreEveryBoneCollisions(Rigidbody rb, SlaveHandModel hand, bool ignore, bool includeRbGroup) { SlaveBoneModel bone; List <Collider> rbColliders = new List <Collider>(rb.GetComponentsInChildren <Collider>()); RigidbodyGroup rbGroup = rb.GetComponent <RigidbodyGroup>(); if (rbGroup && includeRbGroup) { for (int i = 0; i < rbGroup.rigidbodies.Length; i++) { rbColliders.AddRange(GetColliders(rbGroup.rigidbodies[i])); } } for (int i = 0; i < rbColliders.Count; i++) { for (int j = 0; j < hand.bones.Length; j++) { if (hand.bones[j] is SlaveBoneModel) { bone = hand.bones[j] as SlaveBoneModel; if (bone.colliderRef != null) { Physics.IgnoreCollision(rbColliders[i], bone.colliderRef, ignore); } } } } }
private void Start() { SlaveHandModel hand = model.proxyHand.slave; if (hand.palmCollisionNotifier) { hand.palmCollisionNotifier.onRbEnter.AddListener(OnEnter_Special); hand.palmCollisionNotifier.onRbExit.AddListener(OnExit_Special); } else { Debug.LogError("InteractorModule requires a slave hand with palmCollisionNotifier"); validStart = false; } if (hand.thumb) { hand.thumb.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Special); hand.thumb.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Special); } else { Debug.LogError("InteractorModule requires a slave hand with CollisionNotifier attached to a thumb finger tip (slave hand)"); validStart = false; } if (hand.index) { hand.index.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Default); hand.index.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Default); } else { Debug.LogError("InteractorModule requires a slave hand with CollisionNotifier attached to a index finger tip (slave hand)"); validStart = false; } if (hand.middle) { hand.middle.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Default); hand.middle.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Default); } if (hand.ring) { hand.ring.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Default); hand.ring.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Default); } if (hand.pinky) { hand.pinky.fingerTipCollisionNotifier.onRbEnter.AddListener(OnEnter_Default); hand.pinky.fingerTipCollisionNotifier.onRbExit.AddListener(OnExit_Default); } hand.handTrigger.onEnterRigidbody.AddListener(OnEnter_Hover); hand.handTrigger.onExitRigidbody.AddListener(OnExit_Hover); }
public static void SetCollisionDetectionForBones(SlaveHandModel hand, bool detectCollisions) { SlaveBoneModel slaveBone; for (int i = 0; i < hand.bones.Length; i++) { if (hand.bones[i] is SlaveBoneModel) { slaveBone = hand.bones[i] as SlaveBoneModel; if (slaveBone.rigidbodyRef != null) { slaveBone.rigidbodyRef.detectCollisions = detectCollisions; } } } }
public static void IgnoreFingerTipsCollisions(Rigidbody rb, SlaveHandModel hand, bool ignore) { SlaveBoneModel bone; Collider[] rbColliders = rb.GetComponentsInChildren <Collider>(); for (int i = 0; i < rbColliders.Length; i++) { for (int f = 0; f < hand.fingers.Length; f++) { if (hand.fingers[f].distal is SlaveBoneModel) { bone = hand.fingers[f].distal as SlaveBoneModel; if (bone.colliderRef != null) { Physics.IgnoreCollision(rbColliders[i], bone.colliderRef, ignore); } } } } }
public static void IgnoreBoneCollisions(Rigidbody rb, SlaveHandModel hand, bool ignore) { SlaveBoneModel bone; Collider[] rbColliders = rb.GetComponentsInChildren <Collider>(); for (int i = 0; i < rbColliders.Length; i++) { for (int j = 0; j < hand.bones.Length; j++) { if (hand.bones[j] is SlaveBoneModel) { bone = hand.bones[j] as SlaveBoneModel; if (bone.colliderRef != null) { Physics.IgnoreCollision(rbColliders[i], bone.colliderRef, ignore); } } } } }
void SetupProxyHandModule() { // CustomHand > [Modules] > ProxyHandModule GameObject proxyHandModule = Instantiate(proxyHandModulePrefab, modules.transform.position, modules.transform.rotation); proxyHandModule.transform.parent = modules.transform; proxyHandModule.transform.name = "ProxyHandModule." + handType.ToString(); phModel = proxyHandModule.GetComponentInChildren <ProxyHandModel>(); // CustomHand > [Modules] > ProxyHandModule > ProxyHandModel > Master GameObject masterHandModelObj = BasicHelpers.InstantiateEmptyChild(phModel.gameObject); masterHandModelObj.name = "Master." + handType.ToString(); masterHandModel = masterHandModelObj.AddComponent <MasterHandModel>(); // CustomHand > [Modules] > ProxyHandModule > ProxyHandModel > Slave GameObject slaveHandModelObj = BasicHelpers.InstantiateEmptyChild(phModel.gameObject); slaveHandModelObj.name = "Slave." + handType.ToString(); slaveHandModel = slaveHandModelObj.AddComponent <SlaveHandModel>(); // CustomHand > [Modules] > ProxyHandModule > ProxyHandModel > Ghost GameObject ghostHandModelObj = BasicHelpers.InstantiateEmptyChild(phModel.gameObject); ghostHandModelObj.name = "Ghost." + handType.ToString(); ghostHandModel = ghostHandModelObj.AddComponent <HandModel>(); // Make HandModels accessible from ProxyHandModel phModel.master = masterHandModel; phModel.slave = slaveHandModel; phModel.ghost = ghostHandModel; // Make ProxyHandModel accessible from HandModel masterHandModel.proxyHand = phModel; slaveHandModel.proxyHand = phModel; ghostHandModel.proxyHand = phModel; }
void SetupPhysics(SlaveHandModel slaveHand, Transform wristOffset, Vector3 meanPoint, float palmRadius, float fingerRadius) { // Wrist collider GameObject palmObj = BasicHelpers.InstantiateEmptyChild(wristOffset.gameObject); palmObj.name = "Palm.Collider"; palmObj.transform.position = meanPoint; MeshCollider palm = palmObj.AddComponent <MeshCollider>(); palm.sharedMesh = defaultPalmMesh; palm.convex = true; palm.material = skinPhysMat; Vector3 localScale = new Vector3(2.0f * palmRadius, fingerRadius, 2.0f * palmRadius); palmObj.transform.localScale = localScale; // Wrist rb Rigidbody wristRb = wristOffset.gameObject.AddComponent <Rigidbody>(); wristRb.useGravity = false; wristRb.interpolation = RigidbodyInterpolation.Interpolate; wristRb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; // Wrist joint ConfigurableJoint wristJoint = wristRb.gameObject.AddComponent <ConfigurableJoint>(); ConfigureJoint(wristJoint, Space.World); // Palm collision notifier CollisionNotifier palmNotifier = wristRb.gameObject.AddComponent <CollisionNotifier>(); // Add refs (slaveHand.wrist as SlaveBoneModel).colliderRef = palm; (slaveHand.wrist as SlaveBoneModel).rigidbodyRef = wristRb; (slaveHand.wrist as SlaveBoneModel).jointRef = wristJoint; slaveHand.palmCollisionNotifier = palmNotifier; // Bones for (int f = 0; f < slaveHand.fingers.Length; f++) { for (int b = 0; b < slaveHand.fingers[f].bones.Length; b++) { Transform parent = slaveHand.fingers[f].bones[b].transformRef; Transform child; if (b == slaveHand.fingers[f].bones.Length - 1) { child = slaveHand.fingers[f].fingerTip; } else { child = slaveHand.fingers[f].bones[b + 1].transformRef; } // Bone collider GameObject capsuleObj = BasicHelpers.InstantiateEmptyChild(parent.gameObject); capsuleObj.transform.position = (parent.position + child.position) / 2.0f; capsuleObj.transform.name = parent.name + ".Collider"; // Collider alignment capsuleObj.transform.LookAt(child.position); CapsuleCollider capsule = capsuleObj.AddComponent <CapsuleCollider>(); capsule.direction = 2; // Along Z axis (as we use .lookAt()) capsule.height = Vector3.Distance(parent.position, child.position); capsule.radius = fingerRadius; // Phys material capsule.material = skinPhysMat; // Bone rb Rigidbody boneRb = slaveHand.fingers[f].bones[b].transformRef.gameObject.AddComponent <Rigidbody>(); boneRb.useGravity = false; boneRb.interpolation = RigidbodyInterpolation.Interpolate; boneRb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; // Bone joint ConfigurableJoint boneJoint = boneRb.gameObject.AddComponent <ConfigurableJoint>(); if (b == 0) { boneJoint.connectedBody = (slaveHand.wrist as SlaveBoneModel).rigidbodyRef; } else { boneJoint.connectedBody = (slaveHand.fingers[f].bones[b - 1] as SlaveBoneModel).rigidbodyRef; } ConfigureJoint(boneJoint, Space.Self); // Add refs (slaveHand.fingers[f].bones[b] as SlaveBoneModel).colliderRef = capsule; (slaveHand.fingers[f].bones[b] as SlaveBoneModel).rigidbodyRef = boneRb; (slaveHand.fingers[f].bones[b] as SlaveBoneModel).jointRef = boneJoint; } //Generate CollisionNotifiers CollisionNotifier notifier = slaveHand.fingers[f].distal.transformRef.gameObject.AddComponent <CollisionNotifier>(); slaveHand.fingers[f].fingerTipCollisionNotifier = notifier; } }
void FixHand(HandModel handModel, Side side, Transform wristOffset) { // Check errors if (handModel.fingers.Length == 0) { Debug.LogError("Fingers array is empty!"); return; } // Not all hands need an offset if (!wristOffset) { wristOffset = handModel.wrist.transformRef; } // Pinch center if (!handModel.pinchCenter) { GameObject pinchCenter = BasicHelpers.InstantiateEmptyChild(handModel.wrist.transformRef.parent.gameObject); pinchCenter.name = "PinchCenter"; PositionConstraint pinchPosConstraint = pinchCenter.AddComponent <PositionConstraint>(); ConstraintSource indexTipSource = new ConstraintSource(); indexTipSource.sourceTransform = handModel.index.fingerTip; indexTipSource.weight = 1.0f; ConstraintSource thumbTipSource = new ConstraintSource(); thumbTipSource.sourceTransform = handModel.thumb.fingerTip; thumbTipSource.weight = 1.0f; pinchPosConstraint.AddSource(indexTipSource); pinchPosConstraint.AddSource(thumbTipSource); pinchPosConstraint.translationOffset = Vector3.zero; pinchPosConstraint.constraintActive = true; handModel.pinchCenter = pinchCenter.transform; } // Throat center if (!handModel.throatCenter) { GameObject throatCenter = BasicHelpers.InstantiateEmptyChild(handModel.wrist.transformRef.parent.gameObject); throatCenter.name = "ThroatCenter"; PositionConstraint throatPosConstraint = throatCenter.AddComponent <PositionConstraint>(); ConstraintSource indexBaseSource = new ConstraintSource(); indexBaseSource.sourceTransform = handModel.index.fingerBase; indexBaseSource.weight = 1.0f; ConstraintSource thumbBaseSource = new ConstraintSource(); thumbBaseSource.sourceTransform = handModel.thumb.fingerBase; thumbBaseSource.weight = 1.0f; throatPosConstraint.AddSource(indexBaseSource); throatPosConstraint.AddSource(thumbBaseSource); throatPosConstraint.translationOffset = Vector3.zero; throatPosConstraint.constraintActive = true; handModel.throatCenter = throatCenter.transform; } // meanPoint meanPoint = Vector3.zero; for (int f = 0; f < handModel.fingers.Length; f++) { meanPoint += handModel.fingers[f].fingerBase.position; } meanPoint = meanPoint / handModel.fingers.Length; // palmRadius float meanDistance = 0.0f; for (int f = 0; f < handModel.fingers.Length; f++) { meanDistance += Vector3.Distance(meanPoint, handModel.fingers[f].fingerBase.position); } meanDistance = meanDistance / handModel.fingers.Length; palmRadius = meanDistance; // Palm center if (!handModel.palmCenter) { GameObject palmCenter = BasicHelpers.InstantiateEmptyChild(wristOffset.gameObject); palmCenter.name = "PalmCenter"; palmCenter.transform.position = meanPoint; if (side == Side.L) { palmCenter.transform.position += new Vector3(0.0f, fingerRadius, 0.0f); palmCenter.transform.localRotation = Quaternion.Euler(new Vector3(-90.0f, 0.0f, 0.0f)); } else { palmCenter.transform.position -= new Vector3(0.0f, fingerRadius, 0.0f); palmCenter.transform.localRotation = Quaternion.Euler(new Vector3(-90.0f, 0.0f, 180.0f)); } handModel.palmCenter = palmCenter.transform; } // Palm normal (depends on palmCenter) if (!handModel.palmNormal) { GameObject palmNormal = BasicHelpers.InstantiateEmptyChild(wristOffset.gameObject); palmNormal.name = "PalmNormal"; palmNormal.transform.position = handModel.palmCenter.position; if (side == Side.L) { palmNormal.transform.localRotation = Quaternion.Euler(new Vector3(-90.0f, 0.0f, 0.0f)); } else { palmNormal.transform.localRotation = Quaternion.Euler(new Vector3(90.0f, 0.0f, 0.0f)); } handModel.palmNormal = palmNormal.transform; } // Palm interior/exterior (depend on PalmCenter and palmRadius) if (!handModel.palmInterior) { GameObject palmInterior = BasicHelpers.InstantiateEmptyChild(wristOffset.gameObject); palmInterior.name = "PalmInterior"; palmInterior.transform.position = handModel.palmCenter.position; palmInterior.transform.rotation = handModel.palmCenter.rotation; palmInterior.transform.position += handModel.palmCenter.up * palmRadius; handModel.palmInterior = palmInterior.transform; } if (!handModel.palmExterior) { GameObject palmExterior = BasicHelpers.InstantiateEmptyChild(wristOffset.gameObject); palmExterior.name = "PalmExterior"; palmExterior.transform.position = handModel.palmCenter.position; palmExterior.transform.rotation = handModel.palmCenter.rotation; palmExterior.transform.position -= handModel.palmCenter.up * palmRadius; handModel.palmExterior = palmExterior.transform; } // Ray line (depend on PalmCenter) if (!handModel.ray) { GameObject ray = BasicHelpers.InstantiateEmptyChild(wristOffset.gameObject); ray.name = "Ray"; ray.transform.position = handModel.palmCenter.position; LineRenderer lineRenderer = ray.AddComponent <LineRenderer>(); lineRenderer.useWorldSpace = false; lineRenderer.SetPositions(new Vector3[] { Vector3.zero, new Vector3(0.0f, 0.0f, 0.5f) }); lineRenderer.material = rayMat; lineRenderer.startWidth = rayWidth; lineRenderer.endWidth = rayWidth; handModel.ray = ray.transform; } if (handModel is SlaveHandModel) { SlaveHandModel slaveHandModel = handModel as SlaveHandModel; // Palm trigger (depend on PalmCenter and palmRadius) if (!slaveHandModel.palmTrigger) { GameObject palmTrigger = BasicHelpers.InstantiateEmptyChild(wristOffset.gameObject); palmTrigger.name = "PalmTrigger"; palmTrigger.transform.position = handModel.palmCenter.position; SphereCollider trigger = palmTrigger.AddComponent <SphereCollider>(); trigger.isTrigger = true; trigger.radius = palmRadius; TriggerNotifier notifier = palmTrigger.AddComponent <TriggerNotifier>(); notifier.ignoreChildren = handModel.wrist.transformRef.parent; slaveHandModel.palmTrigger = notifier; } // Hand trigger (depend on PalmCenter and palmRadius) if (!slaveHandModel.handTrigger) { GameObject handTrigger = BasicHelpers.InstantiateEmptyChild(wristOffset.gameObject); handTrigger.name = "HandTrigger"; handTrigger.transform.position = handModel.palmCenter.position; SphereCollider trigger = handTrigger.AddComponent <SphereCollider>(); trigger.isTrigger = true; trigger.radius = Vector3.Distance(meanPoint, BasicHelpers.FurthestPoint(meanPoint, GetFingerTips(slaveHandModel))) + 0.02f; TriggerNotifier notifier = handTrigger.AddComponent <TriggerNotifier>(); notifier.ignoreChildren = handModel.wrist.transformRef.parent; slaveHandModel.handTrigger = notifier; } } // Colliders, Rigidbodies and Joitsn if needed if (handModel is SlaveHandModel) { // Setup colliders, rbs and joints for slave SetupPhysics(handModel as SlaveHandModel, wristOffset, meanPoint, palmRadius, fingerRadius); } }
void SetupSlaveHandModel(SlaveHandModel handModel, Transform slaveWrist) { // CustomHand > [Modules] > ProxyHandModule > ProxyHandModel > Slave > Wrist GameObject wristBoneModelObj = BasicHelpers.InstantiateEmptyChild(handModel.gameObject); wristBoneModelObj.name = "Wrist"; SlaveBoneModel wristBone = wristBoneModelObj.AddComponent <SlaveBoneModel>(); wristBone.transformRef = slaveWrist; handModel.wrist = wristBone; /* SLAVE BONE MODEL SPECIFIC */ wristBone.masterBone = handModel.proxyHand.master.wrist as MasterBoneModel; /* */ // Set SkinnedMR handModel.skinnedMR = slaveWrist.GetComponent <SkinnedMeshRenderer>(); List <FingerModel> fingers = new List <FingerModel>(); int f = 0; for (int i = 0; i < slaveWrist.childCount; i++) { // If childCount is 0, then it's not a finger if (slaveWrist.GetChild(i).childCount == 0) { continue; } // CustomHand > [Modules] > ProxyHandModule > ProxyHandModel > Slave > Finger GameObject fingerModelObj = BasicHelpers.InstantiateEmptyChild(handModel.gameObject); fingerModelObj.name = "Finger" + f; FingerModel fingerModel = fingerModelObj.AddComponent <FingerModel>(); List <BoneModel> bones = new List <BoneModel>(); Transform[] fingerTransforms = GetFingerTransforms(slaveWrist.GetChild(i)); for (int b = 0; b < fingerTransforms.Length; b++) { if (fingerTransforms[b].childCount == 0) { fingerModel.fingerTip = fingerTransforms[b]; continue; } // CustomHand > [Modules] > ProxyHandModule > ProxyHandModel > Slave > Finger > Bone GameObject boneModelObj = BasicHelpers.InstantiateEmptyChild(fingerModelObj); boneModelObj.transform.name = "Bone" + b; SlaveBoneModel slaveBone = boneModelObj.AddComponent <SlaveBoneModel>(); slaveBone.transformRef = fingerTransforms[b]; /* SLAVE BONE MODEL SPECIFIC */ // Simple automatic rig mapping if (handModel.proxyHand.master.fingers[f] != null && handModel.proxyHand.master.fingers[f].bones[b] != null) { slaveBone.masterBone = handModel.proxyHand.master.fingers[f].bones[b] as MasterBoneModel; } /* */ bones.Add(slaveBone); } fingerModel.fingerBase = bones[0].transformRef; fingerModel.distal = bones[bones.Count - 1]; fingerModel.bones = bones.ToArray(); fingers.Add(fingerModel); if (i == indexSiblingIndex) { fingerModel.name = "Index"; handModel.index = fingerModel; } if (i == thumbSiblingIndex) { fingerModel.name = "Thumb"; handModel.thumb = fingerModel; /* SLAVE BONE MODEL SPECIFIC */ // Thumb is usually a finger with special participation in hand physics and grabbign detection for (int b = 0; b < fingerModel.bones.Length; b++) { (fingerModel.bones[b] as SlaveBoneModel).isSpecial = true; } /* */ } // Increase finger counter f++; } handModel.fingers = fingers.ToArray(); }