From 652f1c3a6551e48359f90f18a8431bd8ef9788b9 Mon Sep 17 00:00:00 2001 From: "DGD-PC\\ddoak" Date: Sat, 9 Jun 2018 19:59:06 +0100 Subject: [PATCH] Ring stacking - spring constraint improvements added multiple spring constraints / ring 6 x 2 (corresponding to monomers) more closely models physical interactions WIP - TODO address issues with flipper and ring manipulation as before scene defaults to old method --- Assets/Fishtank.cs | 186 +++++++++++++++++++++++++++++++++------------ Assets/Ring.cs | 81 +++++++++++++------- 2 files changed, 192 insertions(+), 75 deletions(-) diff --git a/Assets/Fishtank.cs b/Assets/Fishtank.cs index 93d7be9..eea1e7a 100644 --- a/Assets/Fishtank.cs +++ b/Assets/Fishtank.cs @@ -124,7 +124,7 @@ public class Fishtank : MonoBehaviour private bool myHand1TouchPressedLastLastUpdate = false; // debouncing public bool ringsUseSpringConstraints = false; // if true, enables use of spring constraints for ring stacking - public float ringMinSpringStrength = 5f; + public float ringMinSpringStrength = 0f; void FindPairs() @@ -666,7 +666,7 @@ void PushTogether() float GetSpringFromDistance(float dist) { float calcSpringStrength; - calcSpringStrength = 0.75f * (1.0f / (dist * dist)); + calcSpringStrength = 1.0f * (1.0f / (dist * dist)); //Debug.Log("distance = " + dist + " spring = " + calcSpringStrength); calcSpringStrength = Mathf.Max(calcSpringStrength, ringMinSpringStrength); return calcSpringStrength; @@ -678,20 +678,11 @@ void PushRingsWithSprings(GameObject go) { float bestRotationOffsetAngle = 0.0f; + float ringStackRotation = 8.09f; var ring = go.GetComponent(); ring.dockedToDonor = false; ring.dockedToAcceptor = false; - var rb = ring.GetComponent(); - { - // set approriate (empirical) drag values - rb.drag = 1; - rb.angularDrag = 1; - - ring.sjDonorToAcceptor.damper = 50; - ring.sjAcceptorToDonor.damper = 50; - } - if (ring.partnerAcceptor != null) { { @@ -701,16 +692,14 @@ void PushRingsWithSprings(GameObject go) var distanceFromAcceptorPos = Vector3.Distance(go.transform.position, acceptorPos); var acceptorRing = ring.partnerAcceptor; - ring.sjDonorToAcceptor.connectedBody = acceptorRing.GetComponent(); - ring.sjDonorToAcceptor.spring = GetSpringFromDistance(distanceFromAcceptorPos); - { - bestRotationOffsetAngle = GetBestRotationOffsetAngle(acceptor.rotation, go); - //Debug.Log("bestRotationOffsetAngle (acceptor) is " + bestRotationOffsetAngle); - targetRotation = acceptor.rotation * Quaternion.Euler(new Vector3(0, bestRotationOffsetAngle, 0)); - } + bestRotationOffsetAngle = GetBestRotationOffsetAngle(acceptor.rotation, go); + //Debug.Log("bestRotationOffsetAngle (acceptor) is " + bestRotationOffsetAngle); + + SetAcceptorConstraints(ring, bestRotationOffsetAngle - ringStackRotation); - go.transform.rotation = Quaternion.RotateTowards(go.transform.rotation, targetRotation, Time.deltaTime * Random.Range(0.1f, 0.5f) * pairingRotationVelocity); + //targetRotation = acceptor.rotation * Quaternion.Euler(new Vector3(0, bestRotationOffsetAngle, 0)); + //go.transform.rotation = Quaternion.RotateTowards(go.transform.rotation, targetRotation, Time.deltaTime * Random.Range(0.1f, 0.5f) * pairingRotationVelocity); if (distanceFromAcceptorPos < stackForceDistance) { @@ -728,9 +717,8 @@ void PushRingsWithSprings(GameObject go) } else { - // no acceptor - switch off corresponding spring constraint - ring.sjDonorToAcceptor.connectedBody = null; - ring.sjDonorToAcceptor.spring = 0f; + // no acceptor - switch off corresponding spring constraints + SwitchOffAcceptorConstraints(ring); } if (ring.partnerDonor != null) @@ -741,31 +729,20 @@ void PushRingsWithSprings(GameObject go) var distanceFromDonorPos = Vector3.Distance(go.transform.position, donorPos); var donorRing = ring.partnerDonor; - ring.sjAcceptorToDonor.connectedBody = donorRing.GetComponent(); - ring.sjAcceptorToDonor.spring = GetSpringFromDistance(distanceFromDonorPos); - //var angle = Quaternion.Angle(go.transform.rotation, targetRotation); - //Debug.Log(go.name + " is " + angle + " from donor target rotation "); + bestRotationOffsetAngle = GetBestRotationOffsetAngle(donor.rotation, go); + //Debug.Log("bestRotationOffsetAngle (donor) is " + bestRotationOffsetAngle); - { - bestRotationOffsetAngle = GetBestRotationOffsetAngle(donor.rotation, go); - //Debug.Log("bestRotationOffsetAngle (donor) is " + bestRotationOffsetAngle); - targetRotation = donor.rotation * Quaternion.Euler(new Vector3(0, bestRotationOffsetAngle, 0)); - } + SetDonorConstraints(ring, bestRotationOffsetAngle + ringStackRotation); - go.transform.rotation = Quaternion.RotateTowards(go.transform.rotation, targetRotation, Time.deltaTime * Random.Range(0.1f, 0.5f) * pairingRotationVelocity); + //targetRotation = donor.rotation * Quaternion.Euler(new Vector3(0, bestRotationOffsetAngle, 0)); + //go.transform.rotation = Quaternion.RotateTowards(go.transform.rotation, targetRotation, Time.deltaTime * Random.Range(0.1f, 0.5f) * pairingRotationVelocity); if (distanceFromDonorPos < stackForceDistance) { // update docked flags - used for nanowires ring.dockedToDonor = true; } - if (distanceFromDonorPos < (stackForceDistance / 2.0f)) - { - // force transform to straighten stack - go.transform.position = Vector3.MoveTowards(go.transform.position, donorPos, Time.deltaTime * pairingForcingVelocity); - } - if (cheat) { @@ -776,10 +753,124 @@ void PushRingsWithSprings(GameObject go) else { // no donor - switch off corresponding spring constraint - ring.sjAcceptorToDonor.connectedBody = null; - ring.sjAcceptorToDonor.spring = 0f; + SwitchOffDonorConstraints(ring); + + } + + } + } + + void DrawLine(Vector3 start, Vector3 end, Color color, float duration = 0.2f) + { + GameObject myLine = new GameObject(); + myLine.transform.position = start; + myLine.AddComponent(); + LineRenderer lr = myLine.GetComponent(); + lr.material = new Material(Shader.Find("Particles/Alpha Blended Premultiply")); + lr.SetColors(color, color); + lr.SetWidth(0.02f, 0.02f); + lr.SetPosition(0, start); + lr.SetPosition(1, end); + GameObject.Destroy(myLine, duration); + } + + void SetAcceptorConstraints(Ring ringD, float rotationOffsetAngle) + { + var ringA = ringD.partnerAcceptor; + + for (int i = 0; i < 6; i++) + { + var sj = ringD.sjDonorToAcceptorArr[i]; + + sj.connectedBody = ringA.GetComponent(); + + float connectedAnchorX = ringD.radius * (Mathf.Sin((i * (Mathf.Deg2Rad * 60.0f)) + (Mathf.Deg2Rad * rotationOffsetAngle))); + float connectedAnchorY = 0f; + float connectedAnchorZ = ringD.radius * (Mathf.Cos((i * (Mathf.Deg2Rad * 60.0f)) + (Mathf.Deg2Rad * rotationOffsetAngle))); + + sj.connectedAnchor = new Vector3(connectedAnchorX, connectedAnchorY, connectedAnchorZ); + //sj.connectedAnchor = new Vector3(ringD.radius * (Mathf.Sin(i * (60.0f * Mathf.Deg2Rad))), 0f, ringD.radius * (Mathf.Cos(i * (60.0f * Mathf.Deg2Rad)))); + + sj.damper = 50; + + var startPoint = ringD.transform.position + ringD.transform.TransformVector(sj.anchor); + var endPoint = sj.connectedBody.transform.position + sj.connectedBody.transform.TransformVector(sj.connectedAnchor); + + var currentSpringVector = endPoint - startPoint; + sj.spring = GetSpringFromDistance(Vector3.Magnitude(currentSpringVector)); + + Color constraintColor = Color.green; + if (Vector3.Distance(startPoint, endPoint) >= (sj.minDistance + sj.tolerance)) + { + constraintColor = Color.red; + } + if (Vector3.Distance(startPoint, endPoint) <= (sj.maxDistance - sj.tolerance)) + { + constraintColor = Color.yellow; } + //DrawLine(startPoint, endPoint, constraintColor, 0.02f); + } + } + + void SetDonorConstraints(Ring ringA, float rotationOffsetAngle) + { + var ringD = ringA.partnerDonor; + + for (int i = 0; i < 6; i++) + { + var sj = ringA.sjAcceptorToDonorArr[i]; + + sj.connectedBody = ringD.GetComponent(); + + float connectedAnchorX = ringA.radius * (Mathf.Sin((i * (Mathf.Deg2Rad * 60.0f)) + (Mathf.Deg2Rad * rotationOffsetAngle))); + float connectedAnchorY = 0f; + float connectedAnchorZ = ringA.radius * (Mathf.Cos((i * (Mathf.Deg2Rad * 60.0f)) + (Mathf.Deg2Rad * rotationOffsetAngle))); + + sj.connectedAnchor = new Vector3(connectedAnchorX, connectedAnchorY, connectedAnchorZ); + //sj.connectedAnchor = new Vector3(ringA.radius * (Mathf.Sin(i * (60.0f * Mathf.Deg2Rad))), 0f, ringA.radius * (Mathf.Cos(i * (60.0f * Mathf.Deg2Rad)))); + + sj.damper = 50; + + var startPoint = ringA.transform.position + ringA.transform.TransformVector(sj.anchor); + var endPoint = sj.connectedBody.transform.position + sj.connectedBody.transform.TransformVector(sj.connectedAnchor); + + var currentSpringVector = endPoint - startPoint; + sj.spring = GetSpringFromDistance(Vector3.Magnitude(currentSpringVector)); + + Color constraintColor = Color.green; + if (Vector3.Distance(startPoint, endPoint) >= (sj.minDistance + sj.tolerance)) + { + constraintColor = Color.red; + } + if (Vector3.Distance(startPoint, endPoint) <= (sj.maxDistance - sj.tolerance)) + { + constraintColor = Color.yellow; + } + + //DrawLine(startPoint, endPoint, constraintColor, 0.02f); + } + } + + void SwitchOffAcceptorConstraints(Ring ringD) + { + for (int i = 0; i < 6; i++) + { + var sj = ringD.sjDonorToAcceptorArr[i]; + sj.connectedBody = null; + sj.damper = 0; + sj.spring = 0f; + } + } + + void SwitchOffDonorConstraints(Ring ringA) + { + for (int i = 0; i < 6; i++) + { + var sj = ringA.sjAcceptorToDonorArr[i]; + sj.connectedBody = null; + sj.damper = 0; + sj.spring = 0f; } } @@ -799,13 +890,10 @@ void PushRingsDirectly(GameObject go) rb.angularDrag = 1; // switch all spring constraints off - ring.sjDonorToAcceptor.connectedBody = null; - ring.sjDonorToAcceptor.spring = 0f; - ring.sjDonorToAcceptor.damper = 0; + SwitchOffAcceptorConstraints(ring); + SwitchOffDonorConstraints(ring); + - ring.sjAcceptorToDonor.connectedBody = null; - ring.sjAcceptorToDonor.spring = 0f; - ring.sjAcceptorToDonor.damper = 0; } if (ring.partnerAcceptor != null) @@ -983,8 +1071,8 @@ private void AddRandomMotion(GameObject go) { //RB spring constraint damper interferes with rb movement var ring = go.GetComponent(); - ring.sjDonorToAcceptor.damper = 0; - ring.sjAcceptorToDonor.damper = 0; + SwitchOffAcceptorConstraints(ring); + SwitchOffDonorConstraints(ring); } } diff --git a/Assets/Ring.cs b/Assets/Ring.cs index 6ef1098..6b5ef6e 100644 --- a/Assets/Ring.cs +++ b/Assets/Ring.cs @@ -58,9 +58,13 @@ public class Ring: MonoBehaviour public Color colorMeshPart0; public Color colorMeshPart1; - public SpringJoint sjDonorToAcceptor; - public SpringJoint sjAcceptorToDonor; + //public SpringJoint sjDonorToAcceptor; + //public SpringJoint sjAcceptorToDonor; + public SpringJoint[] sjDonorToAcceptorArr; + public SpringJoint[] sjAcceptorToDonorArr; + + public float radius = 1.0f; // radius for ring constraints void Start() { @@ -94,32 +98,57 @@ void Start() myRingLight.intensity = 0.0f; } + void InitRadialSpringJoint (SpringJoint sj, int i, float anchorY) + { + sj.connectedBody = null; // + sj.anchor = new Vector3(radius * (Mathf.Sin(i * (60.0f * Mathf.Deg2Rad))), anchorY, radius * (Mathf.Cos(i * (60.0f * Mathf.Deg2Rad)))); + sj.autoConfigureConnectedAnchor = false; + sj.connectedAnchor = new Vector3(0f, 0f, 0f); + sj.spring = 0f; + sj.damper = 0; + sj.minDistance = 0f; + sj.maxDistance = 0f; + sj.tolerance = 0.01f; + sj.enableCollision = true; + } + void InitialiseSpringJoints() { - sjDonorToAcceptor = gameObject.AddComponent(typeof(SpringJoint)) as SpringJoint; - sjDonorToAcceptor.connectedBody = null; // - sjDonorToAcceptor.anchor = new Vector3(0f, 0.39f, 0f); //0.39 is equivalent to transform in ring prefab - sjDonorToAcceptor.autoConfigureConnectedAnchor = false; - sjDonorToAcceptor.connectedAnchor = new Vector3(0f, 0f, 0f); - sjDonorToAcceptor.spring = 0f; - sjDonorToAcceptor.damper = 50; - sjDonorToAcceptor.minDistance = 0f; - sjDonorToAcceptor.maxDistance = 0f; - sjDonorToAcceptor.tolerance = 0.01f; - sjDonorToAcceptor.enableCollision = true; - - - sjAcceptorToDonor = gameObject.AddComponent(typeof(SpringJoint)) as SpringJoint; - sjAcceptorToDonor.connectedBody = null; // - sjAcceptorToDonor.anchor = new Vector3(0f, -0.39f, 0f); - sjAcceptorToDonor.autoConfigureConnectedAnchor = false; - sjAcceptorToDonor.connectedAnchor = new Vector3(0f, 0f, 0f); - sjAcceptorToDonor.spring = 0f; - sjAcceptorToDonor.damper = 50; - sjAcceptorToDonor.minDistance = 0f; - sjAcceptorToDonor.maxDistance = 0f; - sjAcceptorToDonor.tolerance = 0.01f; - sjAcceptorToDonor.enableCollision = true; + sjDonorToAcceptorArr = new SpringJoint[6]; + sjAcceptorToDonorArr = new SpringJoint[6]; + + for (int i = 0; i < 6; i++) + { + sjDonorToAcceptorArr[i] = gameObject.AddComponent(typeof(SpringJoint)) as SpringJoint; + InitRadialSpringJoint(sjDonorToAcceptorArr[i], i, 0.39f); //0.39 is equivalent to transform in ring prefab + sjAcceptorToDonorArr[i] = gameObject.AddComponent(typeof(SpringJoint)) as SpringJoint; + InitRadialSpringJoint(sjAcceptorToDonorArr[i], i, -0.39f); + } + + //sjDonorToAcceptor = gameObject.AddComponent(typeof(SpringJoint)) as SpringJoint; + //sjDonorToAcceptor.connectedBody = null; // + //sjDonorToAcceptor.anchor = new Vector3(0f, 0.39f, 0f); //0.39 is equivalent to transform in ring prefab + //sjDonorToAcceptor.autoConfigureConnectedAnchor = false; + //sjDonorToAcceptor.connectedAnchor = new Vector3(0f, 0f, 0f); + //sjDonorToAcceptor.spring = 0f; + //sjDonorToAcceptor.damper = 50; + //sjDonorToAcceptor.minDistance = 0f; + //sjDonorToAcceptor.maxDistance = 0f; + //sjDonorToAcceptor.tolerance = 0.01f; + //sjDonorToAcceptor.enableCollision = true; + + + //sjAcceptorToDonor = gameObject.AddComponent(typeof(SpringJoint)) as SpringJoint; + //sjAcceptorToDonor.connectedBody = null; // + //sjAcceptorToDonor.anchor = new Vector3(0f, -0.39f, 0f); + //sjAcceptorToDonor.autoConfigureConnectedAnchor = false; + //sjAcceptorToDonor.connectedAnchor = new Vector3(0f, 0f, 0f); + //sjAcceptorToDonor.spring = 0f; + //sjAcceptorToDonor.damper = 50; + //sjAcceptorToDonor.minDistance = 0f; + //sjAcceptorToDonor.maxDistance = 0f; + //sjAcceptorToDonor.tolerance = 0.01f; + //sjAcceptorToDonor.enableCollision = true; //sjDonor2Acceptor.tag = "chain";