public override void Apply(MegaWireConnection soft) { if (active) { moveVector.x = soft.masses[p2].pos.x - soft.masses[p1].pos.x; moveVector.y = soft.masses[p2].pos.y - soft.masses[p1].pos.y; moveVector.z = soft.masses[p2].pos.z - soft.masses[p1].pos.z; if (moveVector.x != 0.0f || moveVector.y != 0.0f || moveVector.z != 0.0f) { float currentLength = moveVector.magnitude; float do1 = 1.0f / currentLength; float l = 0.5f * (currentLength - length) * do1; moveVector.x *= l; moveVector.y *= l; moveVector.z *= l; soft.masses[p1].pos.x += moveVector.x; soft.masses[p1].pos.y += moveVector.y; soft.masses[p1].pos.z += moveVector.z; soft.masses[p2].pos.x -= moveVector.x; soft.masses[p2].pos.y -= moveVector.y; soft.masses[p2].pos.z -= moveVector.z; } } }
public override void Apply(MegaWireConnection soft) { if (active) { soft.masses[p1].pos = tp; } }
public void UpdateOffsets() { for (int s = 0; s < spans.Count; s++) { MegaWireSpan span = spans[s]; for (int c = 0; c < span.connections.Count; c++) { MegaWireConnection con = span.connections[c]; con.inOffset = connections[c].inOffset; con.outOffset = connections[c].outOffset; for (int i = 0; i < con.constraints.Count; i++) { MegaWireConstraint cn = con.constraints[i]; if (cn.GetType() == typeof(MegaWirePointConstraint)) { MegaWirePointConstraint wpc = (MegaWirePointConstraint)cn; if (wpc.p1 == 0) { wpc.offset = con.inOffset; } else { wpc.offset = con.outOffset; } } } } } }
public Vector3 GetPos(float alpha, int strand, bool snap) { alpha = Mathf.Clamp(alpha, 0.0f, 0.9999f); float fa = alpha * (float)spans.Count; int sindex = (int)fa; //(alpha * (float)spans.Count); float aa = fa - (float)sindex; MegaWireSpan span = spans[sindex]; MegaWireConnection con = span.connections[strand]; // may need to knock 2 of as have sentry masses float ma1 = aa * (float)(con.masses.Count - 1); int i = (int)ma1 + 1; //(aa * (float)(con.masses.Count - 2)) + 1; float u = ma1 - (float)(i - 1); if (snap) { if (u > 0.5f) { u = 0.999f; } else { u = 0.0f; } } Vector3 a = con.masspos[i - 1]; Vector3 b = con.masspos[i]; Vector3 c = con.masspos[i + 1]; Vector3 d = con.masspos[i + 2]; return(0.5f * ((-a + 3.0f * b - 3.0f * c + d) * (u * u * u) + (2.0f * a - 5.0f * b + 4.0f * c - d) * (u * u) + (-a + c) * u + 2.0f * b)); }
public void OnSceneGUI() { MegaWire mod = (MegaWire)target; if ( mod.displayGizmo ) { Handles.color = mod.gizmoColor; for ( int i = 0; i < mod.spans.Count; i++ ) { MegaWireSpan span = mod.spans[i]; for ( int c = 0; c < span.connections.Count; c++ ) { MegaWireConnection con = span.connections[c]; Vector3 p = con.masspos[1]; Handles.DotCap(0, p, Quaternion.identity, con.radius); for ( int m = 2; m < con.masspos.Length - 1; m++ ) { p = con.masspos[m]; Handles.DotCap(0, con.masspos[m], Quaternion.identity, con.radius); } // Draw springs int scount = con.springs.Count; if ( mod.stiffnessSprings ) scount = con.masses.Count - 1; for ( int s = 0; s < scount; s++ ) { Vector3 p1 = con.masses[con.springs[s].p1].pos; Vector3 p2 = con.masses[con.springs[s].p2].pos; float w = ((con.springs[s].len - con.springs[s].restlen) / con.springs[s].restlen) * con.springs[s].ks; //con.springs[s].restlen; if ( w >= 0.0f ) Handles.color = Color.Lerp(Color.green, Color.red, w); else Handles.color = Color.Lerp(Color.green, Color.blue, -w); Handles.DrawLine(p1, p2); } } } if ( mod.disableOnDistance ) { Handles.color = mod.gizmoColor; for ( int s = 0; s < mod.spans.Count; s++ ) { Vector3 mp = (mod.spans[s].connections[0].masses[0].pos + mod.spans[s].connections[0].masses[mod.spans[s].connections[0].masses.Count - 1].pos) * 0.5f; Handles.SphereCap(0, mp, Quaternion.identity, mod.disableDist * 2.0f); } } } }
public MegaWireSpring(int _p1, int _p2, float _ks, float _kd, MegaWireConnection con, float stretch) { p1 = _p1; p2 = _p2; ks = _ks; kd = _kd; restlen = (con.masses[p1].pos - con.masses[p2].pos).magnitude * stretch; initlen = restlen; }
public void ChangeStretch(float stretch) { for (int i = 0; i < spans.Count; i++) { MegaWireSpan span = spans[i]; for (int c = 0; c < span.connections.Count; c++) { MegaWireConnection con = span.connections[c]; for (int s = 0; s < con.springs.Count; s++) { con.springs[s].restlen = con.springs[s].initlen * stretch; } } } }
public override void doIntegration1(MegaWireConnection rope, MegaWire wire, float dt) { Vector3 delta; Vector3 frc; doCalculateForces(rope, wire); // Calculate forces, only changes _f float t2 = dt * dt; float oodt = 1.0f / dt; /* Then do correction step by integration with central average (Heun) */ for (int i = 0; i < rope.masses.Count; i++) { Vector3 last = rope.masses[i].pos; //rope.masses[i].pos += wire.airdrag * (rope.masses[i].pos - rope.masses[i].last) + rope.masses[i].force * rope.masses[i].oneovermass * t2; // * t; //rope.masses[i].vel = (rope.masses[i].pos - last) / dt; delta.x = rope.masses[i].pos.x - rope.masses[i].last.x; delta.y = rope.masses[i].pos.y - rope.masses[i].last.y; delta.z = rope.masses[i].pos.z - rope.masses[i].last.z; float m2 = rope.masses[i].oneovermass * t2; frc.x = rope.masses[i].force.x * m2; frc.y = rope.masses[i].force.y * m2; frc.z = rope.masses[i].force.z * m2; //wire.masses[i].pos += wire.airdrag * (delta) + frc; //wire.masses[i].force * wire.masses[i].oneovermass * t2; // * t; rope.masses[i].pos.x += wire.airdrag * delta.x + frc.x; rope.masses[i].pos.y += wire.airdrag * delta.y + frc.y; rope.masses[i].pos.z += wire.airdrag * delta.z + frc.z; rope.masses[i].vel.x = (rope.masses[i].pos.x - last.x) * oodt; rope.masses[i].vel.y = (rope.masses[i].pos.y - last.y) * oodt; rope.masses[i].vel.z = (rope.masses[i].pos.z - last.z) * oodt; rope.masses[i].last = last; } DoConstraints(rope, wire); if (wire.doCollisions) { DoCollisions(rope, wire); } }
void DoConstraints(MegaWireConnection rope, MegaWire wire) { for (int c = 0; c < rope.constraints.Count; c++) { rope.constraints[c].ReActivate(rope, wire.timeStep); } for (int i = 0; i < wire.iters; i++) { for (int c = 0; c < rope.lenconstraints.Count; c++) { rope.lenconstraints[c].Apply(rope); } for (int c = 0; c < rope.constraints.Count; c++) { rope.constraints[c].Apply(rope); } } }
void doCalculateForces(MegaWireConnection rope, MegaWire wire) { Vector3 frc = wire.gravity; frc.x += rope.windFrc.x; frc.y += rope.windFrc.y; frc.z += rope.windFrc.z; for (int i = 0; i < rope.masses.Count; i++) { rope.masses[i].force.x = (rope.masses[i].mass * frc.x) + rope.masses[i].forcec.x; rope.masses[i].force.y = (rope.masses[i].mass * frc.y) + rope.masses[i].forcec.y; rope.masses[i].force.z = (rope.masses[i].mass * frc.z) + rope.masses[i].forcec.z; } for (int i = 0; i < rope.springs.Count; i++) { rope.springs[i].doCalculateSpringForce1(rope); } }
public void ReActivate(MegaWireConnection soft, float t) { tp = obj.TransformPoint(offset); if (!active) { if (reactivate > 0.0f) { reactivate -= 0.01f; //Vector3 delta = tp - soft.masses[p1].pos; soft.masses[p1].pos = easeInOutSine(tp, ps, reactivate / rtime); if (reactivate < 0.0f) { reactivate = 0.0f; active = true; } } } }
public void doCalculateSpringForce1(MegaWireConnection mod) { Vector3 direction = mod.masses[p1].pos - mod.masses[p2].pos; if (direction != Vector3.zero) { float currLength = direction.magnitude; direction = direction.normalized; Vector3 force = -ks * ((currLength - restlen) * direction); mod.masses[p1].force.x += force.x; mod.masses[p1].force.y += force.y; mod.masses[p1].force.z += force.z; mod.masses[p2].force.x -= force.x; mod.masses[p2].force.y -= force.y; mod.masses[p2].force.z -= force.z; len = currLength; } }
void DoCollisions(MegaWireConnection rope, MegaWire wire) { for (int i = 0; i < rope.masses.Count; i++) { if (rope.masses[i].pos.y < wire.floor) { rope.masses[i].pos.y = wire.floor; float VdotN = Vector3.Dot(Vector3.up, rope.masses[i].vel); Vector3 Vn = Vector3.up * VdotN; // CALCULATE Vt //Vector3 Vt = (rope.masses[i].vel - Vn) * rope.floorfriction; // SCALE Vn BY COEFFICIENT OF RESTITUTION Vn *= 0.9f; //rope.bounce; // SET THE VELOCITY TO BE THE NEW IMPULSE rope.masses[i].vel = Vn; //Vt - Vn; rope.masses[i].last = rope.masses[i].pos; } } }
void LateUpdate() { if (wire == null) { if (parent != null) { wire = parent.GetComponentInChildren <MegaWire>(); } } if (wire) { float alpha1 = Mathf.Clamp(alpha, 0.0f, 0.9999f); float fa = alpha1 * (float)wire.spans.Count; int sindex = (int)fa; float aa = fa - (float)sindex; MegaWireSpan span = wire.spans[sindex]; MegaWireConnection con = span.connections[connection]; Vector3 p = con.Interp(aa); transform.position = p + offset; if (align) { Vector3 p1 = con.Interp(aa + 0.001f); Vector3 relativePos = p1 - p; Quaternion rotation = Quaternion.LookRotation(relativePos, Vector3.up); locrot = rotation; wtm.SetTRS(p, rotation, Vector3.one); Quaternion r1 = Quaternion.Euler(rotate); transform.rotation = locrot * r1; } } }
public void doCalculateSpringForce(MegaWireConnection hose) { Vector3 deltaP = hose.masses[p1].pos - hose.masses[p2].pos; float dist = deltaP.magnitude; float Hterm = (dist - restlen) * ks; Vector3 deltaV = hose.masses[p1].vel - hose.masses[p2].vel; float Dterm = (Vector3.Dot(deltaV, deltaP) * kd) / dist; Vector3 springForce = deltaP * (1.0f / dist); springForce *= -(Hterm + Dterm); hose.masses[p1].force.x += springForce.x; hose.masses[p1].force.y += springForce.y; hose.masses[p1].force.z += springForce.z; hose.masses[p2].force.x -= springForce.x; hose.masses[p2].force.y -= springForce.y; hose.masses[p2].force.z -= springForce.z; }
public override void doIntegration1(MegaWireConnection rope, MegaWire wire, float dt) { doCalculateForces(rope, wire); // Calculate forces, only changes _f float t2 = dt * dt; /* Then do correction step by integration with central average (Heun) */ for (int i = 0; i < rope.masses.Count; i++) { Vector3 last = rope.masses[i].pos; rope.masses[i].pos += wire.airdrag * (rope.masses[i].pos - rope.masses[i].last) + rope.masses[i].force * rope.masses[i].oneovermass * t2; // * t; rope.masses[i].vel = (rope.masses[i].pos - last) / dt; rope.masses[i].last = last; } DoConstraints(rope, wire); if (wire.doCollisions) { DoCollisions(rope, wire); } }
public void doCalculateSpringForce1(MegaWireConnection mod) { Vector3 direction; // = mod.masses[p1].pos - mod.masses[p2].pos; direction.x = mod.masses[p1].pos.x - mod.masses[p2].pos.x; direction.y = mod.masses[p1].pos.y - mod.masses[p2].pos.y; direction.z = mod.masses[p1].pos.z - mod.masses[p2].pos.z; //if ( direction != Vector3.zero ) if (direction.x != 0.0f || direction.y != 0.0f || direction.z != 0.0f) { //float currLength = direction.magnitude; float currLength = Mathf.Sqrt((direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z)); //direction = direction.normalized; float ool = 1.0f / currLength; direction.x *= ool; direction.y *= ool; direction.z *= ool; Vector3 force; // = -ks * ((currLength - restlen) * direction); float dl = -ks * (currLength - restlen); force.x = dl * direction.x; force.y = dl * direction.y; force.z = dl * direction.z; mod.masses[p1].force.x += force.x; mod.masses[p1].force.y += force.y; mod.masses[p1].force.z += force.z; mod.masses[p2].force.x -= force.x; mod.masses[p2].force.y -= force.y; mod.masses[p2].force.z -= force.z; len = currLength; } }
public void Init() { for (int s = 0; s < spans.Count; s++) { MegaWireSpan span = spans[s]; span.connections.Clear(); for (int c = 0; c < connections.Count; c++) { MegaWireConnection con = new MegaWireConnection(); con.start = span.start; con.end = span.end; con.inOffset = connections[c].inOffset; con.outOffset = connections[c].outOffset; con.radius = connections[c].radius; span.connections.Add(con); con.Init(this); } } }
public override void BuildMesh(MegaWire rope, MegaWireSpan span) { int wires = span.connections.Count; float lengthuvtile = uvtiley * span.WireLength; Twist = TwistPerUnit * span.WireLength; segments = (int)(span.WireLength * SegsPerUnit); if (segments < 1) { segments = 1; } int vcount = ((segments + 1) * (sides + 1)) * strands * wires; int tcount = ((sides * 2) * segments) * strands * wires; if (span.verts == null || span.verts.Length != vcount) { span.verts = new Vector3[vcount]; } bool buildtris = false; if ((span.uvs == null || span.uvs.Length != vcount) && genuv) { span.uvs = new Vector2[vcount]; rope.builduvs = true; } if (span.tris == null || span.tris.Length != tcount * 3) { span.tris = new int[tcount * 3]; buildtris = true; } if (span.norms == null || span.norms.Length != vcount) { span.norms = new Vector3[vcount]; } int vi = 0; int ti = 0; BuildCrossSection(1.0f); for (int c = 0; c < span.connections.Count; c++) { MegaWireConnection con = span.connections[c]; // TODO: inspector should update radius from def, then user can control per span float off = (rope.connections[c].radius * 0.5f) + offset; float sradius = 0.0f; if (strands == 1) { off = offset; sradius = rope.connections[c].radius; } else { sradius = (rope.connections[c].radius * 0.5f) + strandRadius; } Vector2 uv = Vector2.zero; Vector3 soff = Vector3.zero; int vo; for (int s = 0; s < strands; s++) { if (strands == 1) { vo = vi; if (linInterp) { for (int i = 0; i <= segments; i++) { float alpha = ((float)i / (float)segments); float uvt = alpha * uvtwist; wtm = con.GetDeformMatLin(alpha); for (int v = 0; v <= cross.Length; v++) { Vector3 p = cross[v % cross.Length]; span.verts[vi] = wtm.MultiplyPoint3x4(p * sradius); span.norms[vi] = wtm.MultiplyVector(p); if (genuv && rope.builduvs) { uv.y = alpha * lengthuvtile; uv.x = (((float)v / (float)cross.Length) * uvtilex) + uvt; span.uvs[vi] = uv; } vi++; } } } else { for (int i = 0; i <= segments; i++) { float alpha = ((float)i / (float)segments); float uvt = alpha * uvtwist; wtm = con.GetDeformMat(alpha); for (int v = 0; v <= cross.Length; v++) { Vector3 p = cross[v % cross.Length]; span.verts[vi] = wtm.MultiplyPoint3x4(p * sradius); span.norms[vi] = wtm.MultiplyVector(p); if (genuv && rope.builduvs) { uv.y = alpha * lengthuvtile; uv.x = (((float)v / (float)cross.Length) * uvtilex) + uvt; span.uvs[vi] = uv; } vi++; } } } } else { float ang = ((float)s / (float)strands) * Mathf.PI * 2.0f; soff.x = Mathf.Sin(ang) * off; soff.z = Mathf.Cos(ang) * off; vo = vi; if (linInterp) { for (int i = 0; i <= segments; i++) { float alpha = ((float)i / (float)segments); float uvt = alpha * uvtwist; float tst = (alpha * Twist * Mathf.PI * 2.0f); soff.x = Mathf.Sin(ang + tst) * off; soff.z = Mathf.Cos(ang + tst) * off; wtm = con.GetDeformMatLin(alpha); for (int v = 0; v <= cross.Length; v++) { Vector3 p = cross[v % cross.Length]; span.verts[vi] = wtm.MultiplyPoint3x4((p * sradius) + soff); span.norms[vi] = wtm.MultiplyVector(p); if (genuv && rope.builduvs) { uv.y = alpha * lengthuvtile; uv.x = (((float)v / (float)cross.Length) * uvtilex) + uvt; span.uvs[vi] = uv; } vi++; } } } else { for (int i = 0; i <= segments; i++) { float alpha = ((float)i / (float)segments); float uvt = alpha * uvtwist; float tst = (alpha * Twist * Mathf.PI * 2.0f); soff.x = Mathf.Sin(ang + tst) * off; soff.z = Mathf.Cos(ang + tst) * off; wtm = con.GetDeformMat(alpha); for (int v = 0; v <= cross.Length; v++) { Vector3 p = cross[v % cross.Length]; span.verts[vi] = wtm.MultiplyPoint3x4((p * sradius) + soff); span.norms[vi] = wtm.MultiplyVector(p); if (genuv && rope.builduvs) { uv.y = alpha * lengthuvtile; uv.x = (((float)v / (float)cross.Length) * uvtilex) + uvt; span.uvs[vi] = uv; } vi++; } } } } if (buildtris) { int sc = sides + 1; for (int i = 0; i < segments; i++) { for (int v = 0; v < cross.Length; v++) { int v1 = ((i + 1) * sc) + v + vo; int v2 = ((i + 1) * sc) + ((v + 1) % sc) + vo; int v3 = (i * sc) + v + vo; int v4 = (i * sc) + ((v + 1) % sc) + vo; span.tris[ti++] = v1; //((i + 1) * sc) + v + vo; span.tris[ti++] = v2; //((i + 1) * sc) + ((v + 1) % sc) + vo; span.tris[ti++] = v3; //(i * sc) + v + vo; span.tris[ti++] = v2; //((i + 1) * sc) + ((v + 1) % sc) + vo; span.tris[ti++] = v4; //(i * sc) + ((v + 1) % sc) + vo; span.tris[ti++] = v3; //(i * sc) + v + vo; } } } } } if ((!genuv && rope.builduvs) || buildtris) { #if UNITY_3_5 span.mesh.Clear(); #else span.mesh.Clear(false); #endif } span.mesh.vertices = span.verts; if (genuv && rope.builduvs) { span.mesh.uv = span.uvs; } if ((!genuv && rope.builduvs) || buildtris) { span.mesh.triangles = span.tris; } if (calcBounds) { span.mesh.RecalculateBounds(); } span.mesh.normals = span.norms; if (calcTangents && genuv) { BuildTangents(span.mesh, span.verts, span.uvs, span.mesh.normals, span.tris); } span.vcount = vcount; }
public virtual void doIntegration1(MegaWireConnection rope, MegaWire wire, float dt) { }
void DoCollisions(MegaWireConnection rope, MegaWire wire) { if (wire.useraycast) { int mask = wire.collisionmask.value; RaycastHit hit; float len = wire.collisiondist + wire.collisionoff; Vector3 upd = Vector3.up * wire.collisiondist; for (int i = 0; i < rope.masses.Count; i++) { Vector3 p = rope.masses[i].pos + upd; bool result = Physics.Raycast(p, -Vector3.up, out hit, len, mask); //bool result = Physics.SphereCast(p, 0.1f, -Vector3.up, out hit, len, mask); //Vector3 delta = rope.masses[i].pos - rope.masses[i].last; //bool result = Physics.Raycast(rope.masses[i].last, delta.normalized, out hit, delta.magnitude, mask); if (result) { //Debug.Log("p " + rope.masses[i].pos + " l " + rope.masses[i].last + " h " + hit.point); //Vector3 hp = hit.point + (hit.normal * wire.collisionoff); //Debug.Log("hp " + hit.point + " mhp " + hp); rope.masses[i].pos.x = hit.point.x; rope.masses[i].pos.y = hit.point.y + wire.collisionoff; rope.masses[i].pos.z = hit.point.z; //rope.masses[i].pos = hp; float VdotN = Vector3.Dot(Vector3.up, rope.masses[i].vel); Vector3 Vn = Vector3.up * VdotN; // CALCULATE Vt //Vector3 Vt = (rope.masses[i].vel - Vn) * rope.floorfriction; // SCALE Vn BY COEFFICIENT OF RESTITUTION Vn *= 0.9f; //rope.bounce; // SET THE VELOCITY TO BE THE NEW IMPULSE rope.masses[i].vel = Vn; //Vt - Vn; rope.masses[i].last = rope.masses[i].pos; } } } else { for (int i = 0; i < rope.masses.Count; i++) { if (rope.masses[i].pos.y < wire.floor) { rope.masses[i].pos.y = wire.floor; float VdotN = Vector3.Dot(Vector3.up, rope.masses[i].vel); Vector3 Vn = Vector3.up * VdotN; // CALCULATE Vt //Vector3 Vt = (rope.masses[i].vel - Vn) * rope.floorfriction; // SCALE Vn BY COEFFICIENT OF RESTITUTION Vn *= 0.9f; //rope.bounce; // SET THE VELOCITY TO BE THE NEW IMPULSE rope.masses[i].vel = Vn; //Vt - Vn; rope.masses[i].last = rope.masses[i].pos; } } } }
public virtual void Apply(MegaWireConnection soft) { }