Skip to content

Commit

Permalink
Ring stacking - spring constraint improvements
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ddoak committed Jun 9, 2018
1 parent b4336c2 commit 652f1c3
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 75 deletions.
186 changes: 137 additions & 49 deletions Assets/Fishtank.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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;
Expand All @@ -678,20 +678,11 @@ void PushRingsWithSprings(GameObject go)
{

float bestRotationOffsetAngle = 0.0f;
float ringStackRotation = 8.09f;
var ring = go.GetComponent<Ring>();
ring.dockedToDonor = false;
ring.dockedToAcceptor = false;

var rb = ring.GetComponent<Rigidbody>();
{
// set approriate (empirical) drag values
rb.drag = 1;
rb.angularDrag = 1;

ring.sjDonorToAcceptor.damper = 50;
ring.sjAcceptorToDonor.damper = 50;
}

if (ring.partnerAcceptor != null)
{
{
Expand All @@ -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<Rigidbody>();
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)
{
Expand All @@ -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)
Expand All @@ -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<Rigidbody>();
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)
{
Expand All @@ -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>();
LineRenderer lr = myLine.GetComponent<LineRenderer>();
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<Rigidbody>();

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<Rigidbody>();

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;
}
}

Expand All @@ -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)
Expand Down Expand Up @@ -983,8 +1071,8 @@ private void AddRandomMotion(GameObject go)
{
//RB spring constraint damper interferes with rb movement
var ring = go.GetComponent<Ring>();
ring.sjDonorToAcceptor.damper = 0;
ring.sjAcceptorToDonor.damper = 0;
SwitchOffAcceptorConstraints(ring);
SwitchOffDonorConstraints(ring);
}
}

Expand Down
81 changes: 55 additions & 26 deletions Assets/Ring.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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";
Expand Down

0 comments on commit 652f1c3

Please sign in to comment.