//-------------------------------------------------------------------------------------------------------------------------- // Collision Detection / Force Feedback #region Collision // Called when this object enters the collider of another object void OnTriggerEnter(Collider col) { if (this.touchedObject == null) { SenseGlove_Material material = col.GetComponent <SenseGlove_Material>(); SenseGlove_Interactable interactable = col.GetComponent <SenseGlove_Interactable>(); if (material || interactable) { // SenseGlove_Debugger.Log("Touching " + col.name + "; material = " + (material != null) + ", interactable = " + (interactable != null)); this.touchedObject = col.gameObject; this.touchedScript = interactable; this.touchedMaterial = material; this.touchedDeform = col.GetComponent <SenseGlove_MeshDeform>(); if (this.handModel.forceFeedback == ForceFeedbackType.Simple && material) { this.motorLevel = material.maxForce; } else if (this.handModel.forceFeedback == ForceFeedbackType.MaterialBased) { this.FindForceDirection(col); this.motorLevel = 0; //still 0 since OP == EO } if (material && material.hapticFeedback) { this.buzzLevel = material.hapticMagnitude; this.buzzTime = material.hapticDuration; } } } }
// Called when this object enters the collider of another object protected virtual void OnTriggerEnter(Collider col) { if (this.touchedObject == null && this.handModel != null) { GameObject gObj = col.attachedRigidbody != null ? col.attachedRigidbody.gameObject : col.gameObject; SenseGlove_Material material = gObj.GetComponent <SenseGlove_Material>(); if (material) { this.Attach(material); if (this.handModel.forceFeedback == ForceFeedbackType.Simple && material) { this.motorLevel = material.maxForce; } else if (this.handModel.forceFeedback == ForceFeedbackType.MaterialBased) { this.FindForceDirection(col); this.motorLevel = 0; //still 0 since OP == EO } if (material && material.hapticFeedback) { this.buzzLevel = material.hapticMagnitude; this.buzzTime = material.hapticDuration; } } } }
/// <summary> Convert a SenseGlove_Material into a MaterialProps, which can be passed between scripts or stored later on. </summary> /// <param name="material"></param> public MaterialProps(SenseGlove_Material material) { this.maxForce = material.maxForce; this.maxForceDist = material.maxForceDist; this.yieldDist = material.yieldDistance; this.hapticForce = material.hapticMagnitude; this.hapticDur = material.hapticDuration; }
/// <summary> Attach a material script to this feedback script. </summary> /// <param name="material"></param> public void Attach(SenseGlove_Material material) { this.touchedMaterial = material; this.touchedObject = material.gameObject; //this.touchedScript = this.touchedObject.GetComponent<SenseGlove_Interactable>(); this.touchedDeform = this.touchedObject.GetComponent <SenseGlove_MeshDeform>(); Collider[] cols = this.touchedObject.GetComponents <Collider>(); if (cols.Length > 0) { this.touchedCollider = cols[0]; //one of the colliders as a refrence. Assumed that if one of them is disabled, all of the are. } }
//-------------------------------------------------------------------------------------------- // Monobehaviour #region Monobehaviour // Use this for initialization protected virtual void Start() { this.wholeDeform = this.wholeObject.GetComponent <SenseGlove_MeshDeform>(); this.wholeMaterial = this.wholeObject.GetComponent <SenseGlove_Material>(); this.wholeMaterial.MaterialBreaks += WholeMaterial_MaterialBreaks; this.wholeObject.SaveTransform(); if (this.brokenObject) { this.brokenDeform = this.brokenObject.GetComponent <SenseGlove_MeshDeform>(); this.brokenMaterial = this.brokenObject.GetComponent <SenseGlove_Material>(); this.brokenObject.SaveTransform(); } this.UnBreak(); }
// Called during a physics update. void FixedUpdate() { if (touch != null) { touch.isTrigger = true; } //ensure the touch collider is always kinematic. if (this.touchedObject != null && !this.touchedObject.activeInHierarchy) { this.touchedObject = null; this.touchedMaterial = null; this.touchedDeform = null; this.motorLevel = 0; this.dist = 0; } }
/// <summary> Detach the connected bject and its force feedback </summary> public void Detach() { if (this.touchedDeform != null) { this.touchedDeform.ResetMesh(); } this.touchedObject = null; this.touchedMaterial = null; this.touchedDeform = null; this.touchedCollider = null; this.motorLevel = 0; this.buzzLevel = 0; this.dist = 0; }
//-------------------------------------------------------------------------------------- // Class Methods /// <summary> Set uo the script refrences and material properties. </summary> protected void Setup() { this.eggCount = this.LoadCount(); this.UpdateText(); this.eggText.gameObject.SetActive(false); this.eggMaterial = this.checkEgg.wholeObject.GetComponent <SenseGlove_Material>(); if (eggMaterial != null) { eggMaterial.MaterialBreaks += EggCounter_MaterialBreaks; this.eggForce = eggMaterial.maxForce; this.eggForceDist = eggMaterial.maxForceDist; this.eggFingers = eggMaterial.minimumFingers; } }
/// <summary> Set the object at the specified index active or inactive. </summary> /// <param name="i"></param> /// <param name="active"></param> private void SetObject(int i, bool active) { if (index >= 0 && index < this.objectsToSwap.Count) { this.objectsToSwap[i].SetActive(active); SenseGlove_Material mat = this.objectsToSwap[i].GetComponent <SenseGlove_Material>(); if (mat) { mat.UnBreak(); } SenseGlove_Breakable breakable = this.objectsToSwap[i].GetComponent <SenseGlove_Breakable>(); if (breakable) { breakable.UnBreak(); } } }
//-------------------------------------------------------------------------------------------------------------------------- // Collision Detection / Force Feedback // Called when this object enters the collider of another object void OnTriggerEnter(Collider col) { SenseGlove_Material material = col.GetComponent <SenseGlove_Material>(); SenseGlove_Interactable interactable = col.GetComponent <SenseGlove_Interactable>(); if (material || interactable) { //if (!this.IsTouching(col.gameObject)) //{ // //touching a new object! //} this.touchedObject = col.gameObject; if (this.handModel.forceFeedback == ForceFeedbackType.Simple) { if (this.handModel.forceFeedback == ForceFeedbackType.Simple) { if (material) { this.motorLevel = material.passiveForce; } else { this.motorLevel = SenseGlove_Material.defaultPassiveForce; } } } else if (this.handModel.forceFeedback == ForceFeedbackType.MaterialBased) { this.entryPos = this.touch.transform.position; Vector3 closest = col.ClosestPoint(this.entryPos); //if something went wrong with ClosestPoint, it returns the entryPos. if (!closest.Equals(this.entryPos)) { this.entryPoint = closest; } else { // Debug.Log("WARNING: ClosestPoint == Origin, resulting in a DIV0 exception. Use an alterantive method?"); this.entryPoint = closest; } this.motorLevel = 0; //still 0 since OP == EO } } }
/// <summary> Calculate the force feedback levels based on material properties. </summary> /// <param name="col"></param> /// <remarks>Placed in a separate method so that one can control when it is called in Unity's execution order.</remarks> private void CalculateMaterialBased(GameObject obj, SenseGlove_Material material, SenseGlove_Interactable interactable, bool showLines = false) { Vector3 O = obj.transform.TransformPoint(this.entryOrigin); //O origin of collider on touch Vector3 E = obj.transform.TransformPoint(this.entryPoint); //E point where the collider touched the object Vector3 P = this.transform.position; //P current collider position if (showLines) { Debug.DrawLine(O, E); Debug.DrawLine(O, P); } Vector3 OE = (E - O).normalized; Vector3 OP = P - O; if (OP.magnitude > 0 && OE.magnitude > 0) { float cos = Vector3.Dot(OE, OP) / (/*OE.magnitude */ OP.magnitude); //removed OE.magnitude since it is normalized now. this.dist = OP.magnitude * cos; } else { this.dist = 0; } //we have calculated the distance, now for the material (if any is present) if (material != null) { this.motorLevel = material.CalculateForce(this.dist, this.scriptIndex); if (dist > 0 && this.touchedDeform != null) { Vector3 deformPoint = this.transform.position; if (dist > this.touchedDeform.maxDisplacement) { deformPoint = O + (OE * this.touchedDeform.maxDisplacement); } this.touchedDeform.AddDeformation(-OE, deformPoint, this.dist); } } }
/// <summary> Calculates the force on the finger based on material properties. </summary> /// <param name="displacement"></param> /// <param name="fingerIndex"></param> /// <returns></returns> public int CalculateForce(float displacement, int fingerIndex) { if (this.breakable) { if (!this.isBroken) { // SenseGlove_Debugger.Log("Disp:\t" + displacement + ",\t i:\t"+fingerIndex); if (!this.mustBeGrabbed || (this.mustBeGrabbed && this.myInteractable.IsInteracting())) { // SenseGlove_Debugger.Log("mustBeGrabbed = " + this.mustBeGrabbed + ", isInteracting: " + this.myInteractable.IsInteracting()); if (fingerIndex >= 0 && fingerIndex < 5) { bool shouldBreak = displacement >= this.yieldDistance; if (shouldBreak && !this.raisedBreak[fingerIndex]) { this.brokenBy++; } else if (!shouldBreak && this.raisedBreak[fingerIndex]) { this.brokenBy--; } this.raisedBreak[fingerIndex] = shouldBreak; // SenseGlove_Debugger.Log(displacement + " --> raisedBreak[" + fingerIndex + "] = " + this.raisedBreak[fingerIndex]+" --> "+this.brokenBy); if (this.brokenBy >= this.minimumFingers && (!this.requiresThumb || (this.requiresThumb && this.raisedBreak[0]))) { this.OnMaterialBreak(); } } } } else { return(0); } } return((int)SenseGloveCs.Values.Wrap(SenseGlove_Material.CalculateResponseForce(displacement, this.maxForce, this.maxForceDist), 0, this.maxForce)); }
// Called every FixedUpdate while this collider is inside another collider. void OnTriggerStay(Collider col) { if (this.IsTouching(col.gameObject)) //Check if we're still on the same object? { //any object that we are touching has either an Interactable and/or a material //Calculate Motor Level SenseGlove_Material material = col.GetComponent <SenseGlove_Material>(); SenseGlove_Interactable interactable = col.GetComponent <SenseGlove_Interactable>(); if (this.handModel.forceFeedback == ForceFeedbackType.Simple) { if (material) { this.motorLevel = material.passiveForce; } else if (interactable) { this.motorLevel = SenseGlove_Material.defaultPassiveForce; } } else if (this.handModel.forceFeedback == ForceFeedbackType.MaterialBased) { //transform the position of the SenseGlove_Touch to the //O touch point when it was created //E touch point on the collider //P current finger position Vector3 OE = this.entryPoint - this.entryPos; Vector3 OP = this.transform.position - this.entryPos; Debug.DrawLine(this.entryPos, this.transform.position); Debug.DrawLine(this.entryPos, this.entryPoint); if (OE.magnitude == 0) // If OE.magnitude is 0, then something went wrong with Collider.ClosestPoint, which returns O. { //check if we are outside of the collider now... Vector3 thisPos = this.transform.position; Vector3 clostest = col.ClosestPoint(thisPos); if (!thisPos.Equals(clostest)) { this.entryPoint = clostest; this.entryPos = thisPos; } return; //try again next frame } if (OP.magnitude == 0) // If OP.magnitude is 0, then then 0 == P, meaning we are back onto the entry position. in that case this.dist = 0. { this.dist = 0; } else { float cos = Vector3.Dot(OE, OP) / (OE.magnitude * OP.magnitude);; this.dist = OP.magnitude * cos; } if (material) { this.motorLevel = material.CalculateForce(this.dist); } else if (interactable) { this.motorLevel = SenseGlove_Material.CalculateDefault(this.dist); } } } }