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 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; } } } }
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 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); } } }
// each wire length should have a very simple script attached that can do onvisible etc // to turn off the updates, other than that all updates should be done from MegaWire static public MegaWire Create(MegaWire wire, List <GameObject> objs, Material mat, string name, MegaWire copyfrom, float wiresize, float str) { //MegaWire wire = null; if (objs != null && objs.Count > 1) { GameObject newwire = null; if (wire == null) { newwire = new GameObject(); newwire.name = name; wire = newwire.AddComponent <MegaWire>(); wire.material = mat; wire.stretch = str; } else { newwire = wire.gameObject; } wire.poles.Clear(); wire.spans.Clear(); wire.connections.Clear(); wire.poles.Add(objs[0].transform); bool hide = true; if (copyfrom) { hide = copyfrom.hidespans; } // Make the connections, each connection is a new gameobject child of the wire object for (int i = 0; i < objs.Count - 1; i++) { GameObject pole = new GameObject(); if (hide) { pole.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector | HideFlags.NotEditable; } pole.name = name + " Span Mesh " + i; pole.transform.parent = newwire.transform; MegaWireSpan span = pole.AddComponent <MegaWireSpan>(); span.start = objs[i].transform; span.end = objs[i + 1].transform; MeshFilter mf = pole.GetComponent <MeshFilter>(); mf.sharedMesh = new Mesh(); MeshRenderer mr = pole.GetComponent <MeshRenderer>(); Material[] mats = new Material[1]; mats[0] = wire.material; mr.sharedMaterials = mats; span.mesh = mf.sharedMesh; span.mesh.name = name + " Wire Mesh " + i; span.Init(wire); wire.spans.Add(span); wire.poles.Add(objs[i + 1].transform); } MegaWireConnectionHelper helper = objs[0].GetComponent <MegaWireConnectionHelper>(); if (copyfrom) { wire.Copy(copyfrom, helper); } else { // Check if any pole has a helper on it, if so use that if (helper) { wire.Copy(wire, helper); } else { // Add the first connection MegaWireConnectionDef con = new MegaWireConnectionDef(); wire.connections.Add(con); } } if (wiresize != 1.0f) { for (int i = 0; i < wire.connections.Count; i++) { wire.connections[i].radius *= wiresize; } } wire.Init(); } return(wire); }
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 BuildMesh(MegaWire rope, MegaWireSpan span) { }