/** Updates this hand model. */ public override void UpdateHand() { #if UNITY_EDITOR if (!EditorApplication.isPlaying) { return; } #endif float deadzone = DEAD_ZONE_FRACTION * _hand.Fingers[1].Bone((Bone.BoneType) 1).Width; for (int fingerIndex = 0; fingerIndex < N_FINGERS; fingerIndex++) { for (int jointIndex = 0; jointIndex < N_ACTIVE_BONES; jointIndex++) { Bone bone = _hand.Fingers[fingerIndex].Bone((Bone.BoneType)(jointIndex + 1)); int boneArrayIndex = fingerIndex * N_ACTIVE_BONES + jointIndex; InteractionBrushBone brushBone = _brushBones[boneArrayIndex]; Rigidbody body = brushBone.capsuleBody; // This hack works best when we set a fixed rotation for bones. Otherwise // most friction is lost as the bones roll on contact. body.MoveRotation(bone.Rotation.ToQuaternion()); if (brushBone.updateTriggering() == false) { // Calculate how far off the mark the brushes are. float targetingError = (brushBone.lastTarget - body.position).magnitude / bone.Width; float massScale = Mathf.Clamp(1.0f - (targetingError * 2.0f), 0.1f, 1.0f); body.mass = _perBoneMass * massScale; if (targetingError >= DISLOCATION_FRACTION) { brushBone.startTriggering(); } } // Add a deadzone to avoid vibration. Vector3 delta = bone.Center.ToVector3() - body.position; float deltaLen = delta.magnitude; if (deltaLen <= deadzone) { body.velocity = Vector3.zero; brushBone.lastTarget = body.position; } else { delta *= (deltaLen - deadzone) / deltaLen; body.velocity = delta / Time.fixedDeltaTime; brushBone.lastTarget = body.position + delta; } } } }
private void UpdateBone(Bone bone, int boneArrayIndex, float deadzone) { InteractionBrushBone brushBone = _brushBones[boneArrayIndex]; Rigidbody body = brushBone.body; // This hack works best when we set a fixed rotation for bones. Otherwise // most friction is lost as the bones roll on contact. body.MoveRotation(bone.Rotation.ToQuaternion()); // Calculate how far off the mark the brushes are. float targetingError = Vector3.Distance(brushBone.lastTarget, body.position) / bone.Width; float massScale = Mathf.Clamp(1.0f - (targetingError * 2.0f), 0.1f, 1.0f) * Mathf.Clamp(_hand.PalmVelocity.Magnitude * 10f, 1f, 10f); body.mass = _perBoneMass * massScale * brushBone.massOfLastTouchedObject; //If these conditions are met, stop using brush hands to contact objects and switch to "Soft Contact" if (!_softContactEnabled && targetingError >= DISLOCATION_FRACTION && _hand.PalmVelocity.Magnitude < 1.5f && boneArrayIndex != N_ACTIVE_BONES * N_FINGERS) { enableSoftContact(); return; } // Add a deadzone to avoid vibration. Vector3 delta = bone.Center.ToVector3() - body.position; float deltaLen = delta.magnitude; if (deltaLen <= deadzone) { body.velocity = Vector3.zero; brushBone.lastTarget = body.position; } else { delta *= (deltaLen - deadzone) / deltaLen; brushBone.lastTarget = body.position + delta; delta /= Time.fixedDeltaTime; body.velocity = (delta / delta.magnitude) * Mathf.Clamp(delta.magnitude, 0f, 6f); } }
private InteractionBrushBone BeginBone(Bone bone, GameObject brushGameObject, int boneArrayIndex, Collider collider_) { brushGameObject.layer = gameObject.layer; brushGameObject.transform.localScale = Vector3.one; InteractionBrushBone brushBone = brushGameObject.GetComponent <InteractionBrushBone>(); brushBone.col = collider_; if (_manager != null) { brushBone.manager = _manager; } _brushBones[boneArrayIndex] = brushBone; Transform capsuleTransform = brushGameObject.transform; capsuleTransform.SetParent(_handParent.transform, false); Rigidbody body = brushGameObject.GetComponent <Rigidbody>(); body.freezeRotation = true; brushBone.body = body; body.useGravity = false; body.collisionDetectionMode = _collisionDetection; if (collider_ is BoxCollider) { body.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } body.mass = _perBoneMass; body.position = bone != null?bone.Center.ToVector3() : _hand.PalmPosition.ToVector3(); body.rotation = bone != null?bone.Rotation.ToQuaternion() : _hand.Rotation.ToQuaternion(); brushBone.lastTarget = bone != null?bone.Center.ToVector3() : _hand.PalmPosition.ToVector3(); return(brushBone); }
/** Start using this hand model to represent a tracked hand. */ public override void BeginHand() { base.BeginHand(); if (handBegun) { for (int i = _brushBones.Length; i-- != 0;) { _brushBones[i].gameObject.SetActive(true); _brushBones[i].transform.position = _hand.PalmPosition.ToVector3(); } _handParent.SetActive(true); enableSoftContact(); return; } #if UNITY_EDITOR if (!EditorApplication.isPlaying) { return; } // We also require a material for friction to be able to work. if (_material == null || _material.bounciness != 0.0f || _material.bounceCombine != PhysicMaterialCombine.Minimum) { Debug.LogError("An InteractionBrushHand must have a material with 0 bounciness and a bounceCombine of Minimum. Name: " + gameObject.name); } checkContactState(); #endif _handParent = new GameObject(gameObject.name); if (_manager != null) { _handParent.transform.parent = _manager.transform; } // Prevent hand from moving when you turn your head. #if UNITY_EDITOR _handParent.AddComponent <RuntimeColliderGizmos>(); #endif _brushBones = new InteractionBrushBone[N_FINGERS * N_ACTIVE_BONES + 1]; for (int fingerIndex = 0; fingerIndex < N_FINGERS; fingerIndex++) { for (int jointIndex = 0; jointIndex < N_ACTIVE_BONES; jointIndex++) { Bone bone = _hand.Fingers[fingerIndex].Bone((Bone.BoneType)(jointIndex) + 1); // +1 to skip first bone. int boneArrayIndex = fingerIndex * N_ACTIVE_BONES + jointIndex; GameObject brushGameObject = new GameObject(gameObject.name, typeof(CapsuleCollider), typeof(Rigidbody), typeof(InteractionBrushBone)); brushGameObject.transform.position = bone.Center.ToVector3(); brushGameObject.transform.rotation = bone.Rotation.ToQuaternion(); CapsuleCollider capsule = brushGameObject.GetComponent <CapsuleCollider>(); capsule.direction = 2; capsule.radius = bone.Width * 0.5f; capsule.height = bone.Length + bone.Width; capsule.material = _material; InteractionBrushBone brushBone = BeginBone(bone, brushGameObject, boneArrayIndex, capsule); brushBone.lastTarget = bone.Center.ToVector3(); } } // Palm is attached to the third metacarpal and derived from it. { Bone bone = _hand.Fingers[(int)Finger.FingerType.TYPE_MIDDLE].Bone(Bone.BoneType.TYPE_METACARPAL); int boneArrayIndex = N_FINGERS * N_ACTIVE_BONES; GameObject brushGameObject = new GameObject(gameObject.name, typeof(BoxCollider), typeof(Rigidbody), typeof(InteractionBrushBone)); brushGameObject.transform.position = _hand.PalmPosition.ToVector3(); brushGameObject.transform.rotation = _hand.Rotation.ToQuaternion(); BoxCollider box = brushGameObject.GetComponent <BoxCollider>(); box.center = new Vector3(_hand.IsLeft ? -0.005f : 0.005f, bone.Width * -0.1f, -0.015f); box.size = new Vector3(bone.Length, bone.Width, bone.Length); box.material = _material; BeginBone(null, brushGameObject, boneArrayIndex, box); } //Add joints between each of the hand's rigidbodies to ensure they do not separate addHandJoints(); handBegun = true; }
/** Start using this hand model to represent a tracked hand. */ public override void BeginHand() { base.BeginHand(); #if UNITY_EDITOR if (!EditorApplication.isPlaying) { return; } // We also require a material for friction to be able to work. if (_material == null || _material.bounciness != 0.0f || _material.bounceCombine != PhysicMaterialCombine.Minimum) { Debug.LogError("An InteractionBrushHand must have a material with 0 bounciness and a bounceCombine of Minimum. Name: " + gameObject.name); } checkContactState(); #endif _handParent = new GameObject(gameObject.name); _handParent.transform.parent = null; // Prevent hand from moving when you turn your head. _brushBones = new InteractionBrushBone[N_FINGERS * N_ACTIVE_BONES]; for (int fingerIndex = 0; fingerIndex < N_FINGERS; fingerIndex++) { for (int jointIndex = 0; jointIndex < N_ACTIVE_BONES; jointIndex++) { Bone bone = _hand.Fingers[fingerIndex].Bone((Bone.BoneType)(jointIndex + 1)); // +1 to skip first bone. int boneArrayIndex = fingerIndex * N_ACTIVE_BONES + jointIndex; GameObject brushGameObject = new GameObject(gameObject.name, typeof(CapsuleCollider), typeof(Rigidbody), typeof(InteractionBrushBone)); brushGameObject.layer = gameObject.layer; brushGameObject.transform.localScale = Vector3.one; InteractionBrushBone brushBone = brushGameObject.GetComponent <InteractionBrushBone>(); brushBone.manager = _manager; _brushBones[boneArrayIndex] = brushBone; Transform capsuleTransform = brushGameObject.transform; capsuleTransform.SetParent(_handParent.transform, false); CapsuleCollider capsule = brushGameObject.GetComponent <CapsuleCollider>(); capsule.direction = 2; capsule.radius = bone.Width * 0.5f; capsule.height = bone.Length + bone.Width; capsule.material = _material; brushBone.capsuleCollider = capsule; Rigidbody body = brushGameObject.GetComponent <Rigidbody>(); brushBone.capsuleBody = body; body.position = bone.Center.ToVector3(); body.rotation = bone.Rotation.ToQuaternion(); body.freezeRotation = true; body.useGravity = false; body.mass = _perBoneMass; body.collisionDetectionMode = _collisionDetection; brushBone.lastTarget = bone.Center.ToVector3(); } } }