public override void Apply(MegaRope soft) { //Vector3 d1 = soft.masses[p1].pos - soft.masses[p2].pos; //Vector3 d2 = soft.masses[p3].pos - soft.masses[p2].pos; //float ang = Vector3.Dot(d1, d2); }
public override void Apply(MegaRope soft) { if (active) { //calculate direction soft.masses[p1].pos = obj.position; soft.masses[p1].last = soft.masses[p1].pos; Vector3 direction = soft.masses[p2].pos - soft.masses[p1].pos; //calculate current length float currentLength = direction.magnitude; //check for zero vector if (direction != Vector3.zero) { //normalize direction vector direction.Normalize(); //move to goal positions Vector3 moveVector = 1.0f * (currentLength - length) * direction; //soft.masses[p1].pos += moveVector; soft.masses[p2].pos += -moveVector; soft.masses[p2].last = soft.masses[p2].pos; } } }
void Collide(int i, float dt, MegaRope rope) { return; #if false RaycastHit hit; //if ( Physics.SphereCast(masses[i].pos, ropeRadius, Vector3.up, out hit, 0.0f, layer) ) //{ //masses[i].pos = hit.point + (hit.normal * (ropeRadius * 1.01f)); //Response(i, hit); //} Vector3 dir = masses[i].vel.normalized; Vector3 start = masses[i].last - (Vector3.down * 10.0f); //if ( Physics.SphereCast(masses[i].last, ropeRadius, dir, out hit, masses[i].vel.magnitude * dt, layer) ) //if ( Physics.SphereCast(start, ropeRadius, dir, out hit, (masses[i].vel.magnitude * dt) + 10.0f, layer) ) if (Physics.SphereCast(start, ropeRadius, Vector3.down, out hit, (masses[i].vel.magnitude * dt) + 20.0f, layer)) { if (hit.distance < 10.0f) { masses[i].pos = hit.point + (hit.normal * (ropeRadius * 1.01f)); Response(i, hit); } } #endif }
void Collide(int i, float dt, MegaRope rope) { return; #if false RaycastHit hit; //if ( Physics.SphereCast(masses[i].pos, ropeRadius, Vector3.up, out hit, 0.0f, layer) ) //{ //masses[i].pos = hit.point + (hit.normal * (ropeRadius * 1.01f)); //Response(i, hit); //} Vector3 dir = masses[i].vel.normalized; Vector3 start = masses[i].last - (Vector3.down * 10.0f); //if ( Physics.SphereCast(masses[i].last, ropeRadius, dir, out hit, masses[i].vel.magnitude * dt, layer) ) //if ( Physics.SphereCast(start, ropeRadius, dir, out hit, (masses[i].vel.magnitude * dt) + 10.0f, layer) ) if ( Physics.SphereCast(start, ropeRadius, Vector3.down, out hit, (masses[i].vel.magnitude * dt) + 20.0f, layer) ) { if ( hit.distance < 10.0f ) { masses[i].pos = hit.point + (hit.normal * (ropeRadius * 1.01f)); Response(i, hit); } } #endif }
public override void Apply(MegaRope soft) { //Vector3 d1 = soft.masses[p1].pos - soft.masses[p2].pos; //Vector3 d2 = soft.masses[p3].pos - soft.masses[p2].pos; //float ang = Vector3.Dot(d1, d2); }
public override void Apply(MegaRope soft) { if (active) { soft.masses[p1].pos = obj.position + obj.localToWorldMatrix.MultiplyVector(off); } }
public override void Apply(MegaRope soft) { if (active) { soft.masses[p1].pos = obj.position; } }
public MegaRopeSpring(int _p1, int _p2, float _ks, float _kd, MegaRope hose) { p1 = _p1; p2 = _p2; ks = _ks; kd = _kd; restlen = (hose.masses[p1].pos - hose.masses[p2].pos).magnitude; // * stretch; }
public MegaRopeSpring(int _p1, int _p2, float _ks, float _kd, MegaRope hose) { p1 = _p1; p2 = _p2; ks = _ks; kd = _kd; restlen = (hose.masses[p1].pos - hose.masses[p2].pos).magnitude; // * stretch; }
// Satisfy constraints void DoConstraints(MegaRope rope) { for (int i = 0; i < rope.iters; i++) { for (int c = 0; c < rope.constraints.Count; c++) { rope.constraints[c].Apply(rope); //this); } } }
public override void Apply(MegaRope soft) { // If alpha < 0.0f or > 1.0f then constraint is inactive // If shape is closed? if (shape != null) { Vector3 pos = shape.InterpCurve3D(0, alpha, true); soft.masses[p1].pos = pos; } }
void BuildObjectLinks(MegaRope rope) { float len = rope.RopeLength; if (LinkSize < 0.1f) { LinkSize = 0.1f; } // Assume z axis for now float linklen = (linkOff1.y - linkOff.y) * linkScale.x * LinkSize; //Length - linkOff.y int lc = (int)(len / linklen); if (lc != linkcount || rebuild) { InitLinkObjects(rope); } if (LinkObj1 == null || LinkObj1.Count == 0) { return; } Quaternion linkrot1 = Quaternion.Euler(LinkRot); Quaternion linkrot2 = Quaternion.Euler(LinkRot1); Vector3 poff = linkPivot; poff.Scale(linkScale * LinkSize); float lastalpha = 0.0f; Vector3 pos = Vector3.zero; for (int i = 0; i < linkcount; i++) { if (linkobjs[i]) { float alpha = (float)(i + 1) / (float)linkcount; Quaternion lq = GetLinkQuat(alpha, lastalpha, out pos, rope); lastalpha = alpha; if ((i & 1) == 1) { lq = lq * linkrot1; } else { lq = lq * linkrot2; } linkobjs[i].position = pos; linkobjs[i].rotation = lq; linkobjs[i].localScale = linkScale * LinkSize; } } }
Vector3 Deform(Vector3 p, float off, MegaRope rope, float alpha) { Vector3 np = rope.Interp(alpha); //tm.MultiplyPoint3x4(rope.Interp(alpha)); T = rope.Velocity(alpha).normalized; wtm = rope.CalcFrame(T, ref N, ref B); //wtm.SetRow(3, np); MegaMatrix.SetTrans(ref wtm, np); return(p); }
Quaternion GetLinkQuat(float alpha, float last, out Vector3 ps, MegaRope rope) { ps = rope.Interp(last); Vector3 ps1 = rope.Interp(alpha); //ps + Velocity(alpha); Vector3 relativePos = ps1 - ps; // This is Vel? Quaternion rotation = Quaternion.LookRotation(relativePos, rope.ropeup); //vertices[p + 1].point - vertices[p].point); return(rotation); //wtm; }
void doCalculateForces(MegaRope rope) { for (int i = 0; i < rope.masses.Count; i++) { rope.masses[i].force = rope.masses[i].mass * rope.gravity; rope.masses[i].force += -rope.masses[i].vel * rope.airdrag; // Should be vel sqr } for (int i = 0; i < rope.springs.Count; i++) { rope.springs[i].doCalculateSpringForce(rope); } }
void Response(int i, RaycastHit hit, MegaRope rope) { // CALCULATE Vn float VdotN = Vector3.Dot(hit.normal, rope.masses[i].vel); Vector3 Vn = hit.normal * VdotN; // CALCULATE Vt //Vector3 Vt = (rope.masses[i].vel - Vn) * rope.floorfriction; // SCALE Vn BY COEFFICIENT OF RESTITUTION Vn *= rope.bounce; // SET THE VELOCITY TO BE THE NEW IMPULSE rope.masses[i].vel = Vn; //Vt - Vn; }
Matrix4x4 GetLinkMat(float alpha, float last, MegaRope rope) { Vector3 ps = rope.Interp(last); Vector3 ps1 = rope.Interp(alpha); //ps + Velocity(alpha); Vector3 relativePos = ps1 - ps; // This is Vel? Quaternion rotation = Quaternion.LookRotation(relativePos, rope.ropeup); //vertices[p + 1].point - vertices[p].point); wtm.SetTRS(ps, rotation, Vector3.one); wtm = mat * wtm; // * roll; return(wtm); }
void CollideCapsule(int i, float dt, MegaRope rope) { if ( i < rope.masses.Count - 1 ) { // cast a ray from last pos to current against colliders RaycastHit hit; if ( Physics.CapsuleCast(rope.masses[i].pos, rope.masses[i + 1].pos, rope.radius, rope.masses[i].vel.normalized, out hit, 0.1f, rope.layer) ) { rope.masses[i].pos = hit.point + (hit.normal * (rope.radius * 1.01f)); //masses[i + 1].pos = hit.point + (hit.normal * (ropeRadius * 1.01f)); Response(i, hit, rope); } } }
void CollideCapsule(int i, float dt, MegaRope rope) { if (i < rope.masses.Count - 1) { // cast a ray from last pos to current against colliders RaycastHit hit; if (Physics.CapsuleCast(rope.masses[i].pos, rope.masses[i + 1].pos, rope.radius, rope.masses[i].vel.normalized, out hit, 0.1f, rope.layer.value)) { rope.masses[i].pos = hit.point + (hit.normal * (rope.radius * 1.01f)); //masses[i + 1].pos = hit.point + (hit.normal * (ropeRadius * 1.01f)); Response(i, hit, rope); } } }
public override void Apply(MegaRope soft) { if ( active ) { //calculate direction //Vector3 direction = soft.masses[p2].pos - soft.masses[p1].pos; 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; //calculate current length //float currentLength = direction.magnitude; //check for zero vector //if ( direction != Vector3.zero ) //if ( direction.x != 0.0f || direction.y != 0.0f || direction.z != 0.0f ) if ( moveVector.x != 0.0f || moveVector.y != 0.0f || moveVector.z != 0.0f ) { float currentLength = moveVector.magnitude; float do1 = 1.0f / currentLength; //normalize direction vector //direction.Normalize(); //move to goal positions //Vector3 moveVector = 0.5f * (currentLength - length) * direction; float l = 0.5f * (currentLength - length) * do1; moveVector.x *= l; // * direction.x; moveVector.y *= l; // * direction.y; moveVector.z *= l; // * direction.z; 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; //soft.masses[p1].pos += moveVector; //soft.masses[p2].pos += -moveVector; //soft.masses[p1].last = soft.masses[p1].pos; //soft.masses[p2].last = soft.masses[p2].pos; } } }
public override void Apply(MegaRope soft) { if (active) { //calculate direction //Vector3 direction = soft.masses[p2].pos - soft.masses[p1].pos; 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; //calculate current length //float currentLength = direction.magnitude; //check for zero vector //if ( direction != Vector3.zero ) //if ( direction.x != 0.0f || direction.y != 0.0f || direction.z != 0.0f ) if (moveVector.x != 0.0f || moveVector.y != 0.0f || moveVector.z != 0.0f) { float currentLength = moveVector.magnitude; float do1 = 1.0f / currentLength; //normalize direction vector //direction.Normalize(); //move to goal positions //Vector3 moveVector = 0.5f * (currentLength - length) * direction; float l = 0.5f * (currentLength - length) * do1; moveVector.x *= l; // * direction.x; moveVector.y *= l; // * direction.y; moveVector.z *= l; // * direction.z; 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; //soft.masses[p1].pos += moveVector; //soft.masses[p2].pos += -moveVector; //soft.masses[p1].last = soft.masses[p1].pos; //soft.masses[p2].last = soft.masses[p2].pos; } } }
public void doCalculateSpringForceOld(MegaRope hose) { Vector3 r12 = (hose.masses[p1].pos - hose.masses[p2].pos); // distance vector float r12d = r12.magnitude; // distance vector length if (r12d != 0.0f) { float or12d = 1.0f / r12d; Vector3 v12 = (hose.masses[p1].vel - hose.masses[p2].vel); float f = ((r12d - restlen) * ks) + (Vector3.Dot(v12, r12) * kd * or12d); /// r12d; Vector3 F = r12 * or12d * f; hose.masses[p1].force -= F; hose.masses[p2].force += F; } }
void SelfCollide1(MegaRope rope) { float rad = rope.radius * 2.0f; //(rope.radius * rope.radius); for (int i = 0; i < rope.masses.Count; i++) { Vector3 p = rope.masses[i].pos; Vector3 lp = rope.masses[i].last; if (Vector3.Distance(p, lp) > rad) { Debug.Log("Mass " + i + " moved too much"); } for (int j = i + 2; j < rope.masses.Count; j++) { //float dsqr = Vector3.SqrMagnitude(rope.masses[j].pos - p); float dsqr = Vector3.Magnitude(rope.masses[j].pos - p); if (dsqr < rad) { //Debug.Log("Mass " + i + " hit mass " + j + " dist " + dsqr); Vector3 delta = (rope.masses[j].pos - p).normalized; //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = mid - (delta * rope.radius); //rope.masses[i].pos = p; //rope.masses[j].pos = mid + (delta * rope.radius); if (p.y > rope.masses[j].pos.y) { //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); p = rope.masses[j].pos - (delta * rad); rope.masses[i].pos = p; rope.masses[i].last = p; } else { //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = p - (delta * rad); rope.masses[j].pos = p + (delta * rad); rope.masses[j].last = p + (delta * rad); } } } } }
public void doCalculateSpringForce(MegaRope hose) { Vector3 deltaP = hose.masses[p1].pos - hose.masses[p2].pos; float dist = deltaP.magnitude; //VectorLength(&deltaP); // Magnitude of deltaP float Hterm = (dist - restlen) * ks; // Ks * (dist - rest) Vector3 deltaV = hose.masses[p1].vel - hose.masses[p2].vel; float Dterm = (Vector3.Dot(deltaV, deltaP) * kd) / dist; // Damping Term Vector3 springForce = deltaP * (1.0f / dist); springForce *= -(Hterm + Dterm); hose.masses[p1].force += springForce; hose.masses[p2].force -= springForce; }
void DoCollisions1(MegaRope rope, float dt) { RaycastHit hit; Vector3 dir = Vector3.zero; for (int i = 0; i < rope.masses.Count; i++) { if (Mathf.Abs(rope.masses[i].vel.sqrMagnitude) < 0.0001f) { dir = Vector3.down; } else { dir = rope.masses[i].vel.normalized; } Vector3 start = rope.masses[i].pos - (dir * 10.0f); rope.masses[i].collide = false; if (Physics.CheckSphere(rope.masses[i].pos, rope.radius, rope.layer)) { Collider[] cols = Physics.OverlapSphere(rope.masses[i].pos, rope.radius, rope.layer); for (int c = 0; c < cols.Length; c++) { Vector3 cp = cols[c].Raycast.ClosestPointOnBounds(rope.masses[i].pos); } if (Physics.SphereCast(rope.masses[i].last, rope.radius, dir, out hit, (rope.masses[i].vel * dt).magnitude, rope.layer)) { if (hit.distance < rope.radius) //10.0f ) { rope.masses[i].pos = hit.point + (hit.normal * (rope.radius * 1.001f)); Response(i, hit, rope); rope.masses[i].collide = true; } } } } }
void doCalculateForces(MegaRope rope) { for (int i = 0; i < rope.masses.Count; i++) { //rope.masses[i].force = rope.masses[i].mass * rope.gravity; rope.masses[i].force.x = rope.masses[i].mass * rope.gravity.x; rope.masses[i].force.y = rope.masses[i].mass * rope.gravity.y; rope.masses[i].force.z = rope.masses[i].mass * rope.gravity.z; //rope.masses[i].force += -rope.masses[i].vel * rope.airdrag; // Should be vel sqr //rope.masses[i].force += rope.masses[i].forcec; } for (int i = 0; i < rope.springs.Count; i++) { rope.springs[i].doCalculateSpringForce1(rope); } }
public override void doIntegration1(MegaRope rope, float dt) { doCalculateForces(rope); // Calculate forces, only changes _f /* Then do correction step by integration with central average (Heun) */ for ( int i = 0; i < rope.masses.Count; i++ ) { rope.masses[i].last = rope.masses[i].pos; rope.masses[i].vel += dt * rope.masses[i].force * rope.masses[i].oneovermass; rope.masses[i].pos += rope.masses[i].vel * dt; rope.masses[i].vel *= rope.friction; } DoConstraints(rope); if ( rope.DoCollide ) DoCollisions(rope, dt); if ( rope.SelfCollide ) SelfCollide(rope); }
void DoCollisions(MegaRope rope, float dt) { RaycastHit hit; for (int i = 0; i < rope.masses.Count; i++) { Vector3 start = rope.masses[i].last - (Vector3.down * 10.0f); if (Physics.CheckSphere(rope.masses[i].last, rope.radius, rope.layer.value)) { if (Physics.SphereCast(start, rope.radius, Vector3.down, out hit, (rope.masses[i].vel.magnitude * dt) + 20.0f, rope.layer.value)) { if (hit.distance < 10.0f) { rope.masses[i].pos = hit.point + (hit.normal * (rope.radius * 1.001f)); Response(i, hit, rope); } } } } }
void DoCollisions1(MegaRope rope, float dt) { RaycastHit hit; for (int i = 0; i < rope.masses.Count; i++) { //Vector3 start = rope.masses[i].pos - (rope.masses[i].vel * 10.0f); if (Physics.CheckSphere(rope.masses[i].pos, rope.radius, rope.layer.value)) { if (Physics.SphereCast(rope.masses[i].last, rope.radius, rope.masses[i].vel.normalized, out hit, (rope.masses[i].vel.magnitude * dt) * 2.0f, rope.layer.value)) { //Debug.Log("d " + hit.distance); //if ( hit.distance < 10.01f ) { rope.masses[i].pos = hit.point + (hit.normal * (rope.radius * 1.05f)); Response(i, hit, rope); } } } } }
public void Rebuild(MegaRope rope) { if (source) { Mesh smesh = MegaUtils.GetSharedMesh(source); if (smesh) { bounds = smesh.bounds; sverts = smesh.vertices; overts = new Vector3[smesh.vertexCount]; rope.mesh.Clear(); rope.mesh.vertices = smesh.vertices; rope.mesh.normals = smesh.normals; rope.mesh.uv = smesh.uv; //rope.mesh.uv1 = smesh.uv1; rope.mesh.subMeshCount = smesh.subMeshCount; for (int i = 0; i < smesh.subMeshCount; i++) { rope.mesh.SetTriangles(smesh.GetTriangles(i), i); } MeshRenderer mr = source.GetComponent <MeshRenderer>(); MeshRenderer mr1 = rope.GetComponent <MeshRenderer>(); if (mr1 != null && mr != null) { mr1.sharedMaterials = mr.sharedMaterials; } // Calc the alphas BuildNormalMapping(smesh, true); BuildMesh(rope); } } }
public void doCalculateSpringForce1(MegaRope mod) { //get the direction vector Vector3 direction = mod.masses[p1].pos - mod.masses[p2].pos; //check for zero vector if (direction != Vector3.zero) { //get length float currLength = direction.magnitude; //normalize direction = direction.normalized; //add spring force Vector3 force = -ks * ((currLength - restlen) * direction); //add spring damping force //float v = (currLength - len) / mod.timeStep; //force += -kd * v * direction; //apply the equal and opposite forces to the objects mod.masses[p1].force += force; mod.masses[p2].force -= force; len = currLength; } }
public override void doIntegration1(MegaRope rope, float dt) { doCalculateForces(rope); // 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 += rope.airdrag * (rope.masses[i].pos - rope.masses[i].last) + rope.masses[i].force * rope.masses[i].oneovermass * t2; // * t; //masses[i].pos += airdrag * masses[i].pos - masses[i].last + masses[i].force * masses[i].oneovermass * t2; // * t; //masses[i].pos = masses[i].pos + (masses[i].pos - masses[i].last) * (t / lastt) + masses[i].force * masses[i].oneovermass * t * t; rope.masses[i].vel = (rope.masses[i].pos - last) / dt; rope.masses[i].last = last; } if (rope.SelfCollide) { SelfCollide(rope); } DoConstraints(rope); if (rope.DoCollide) { DoCollisions(rope, dt); } if (rope.SelfCollide) { SelfCollide(rope); } }
public override void doIntegration1(MegaRope rope, float dt) { doCalculateForces(rope); // Calculate forces, only changes _f /* Then do correction step by integration with central average (Heun) */ for (int i = 0; i < rope.masses.Count; i++) { rope.masses[i].last = rope.masses[i].pos; rope.masses[i].vel += dt * rope.masses[i].force * rope.masses[i].oneovermass; rope.masses[i].pos += rope.masses[i].vel * dt; rope.masses[i].vel *= rope.friction; } DoConstraints(rope); if (rope.DoCollide) { DoCollisions(rope, dt); } if (rope.SelfCollide) { SelfCollide(rope); } }
Vector3 Deform(Vector3 p, float off, MegaRope rope, float alpha) { Vector3 np = rope.Interp(alpha); //tm.MultiplyPoint3x4(rope.Interp(alpha)); T = rope.Velocity(alpha).normalized; wtm = rope.CalcFrame(T, ref N, ref B); //wtm.SetRow(3, np); MegaMatrix.SetTrans(ref wtm, np); return p; }
void doCalculateForces(MegaRope rope) { for ( int i = 0; i < rope.masses.Count; i++ ) { rope.masses[i].force = rope.masses[i].mass * rope.gravity; rope.masses[i].force += -rope.masses[i].vel * rope.airdrag; // Should be vel sqr } for ( int i = 0; i < rope.springs.Count; i++ ) rope.springs[i].doCalculateSpringForce(rope); }
public void doCalculateSpringForceOld(MegaRope hose) { Vector3 r12 = (hose.masses[p1].pos - hose.masses[p2].pos); // distance vector float r12d = r12.magnitude; // distance vector length if ( r12d != 0.0f ) { float or12d = 1.0f / r12d; Vector3 v12 = (hose.masses[p1].vel - hose.masses[p2].vel); float f = ((r12d - restlen) * ks) + (Vector3.Dot(v12, r12) * kd * or12d); /// r12d; Vector3 F = r12 * or12d * f; hose.masses[p1].force -= F; hose.masses[p2].force += F; } }
void SelfCollide1(MegaRope rope) { float rad = rope.radius * 2.0f; //(rope.radius * rope.radius); for ( int i = 0; i < rope.masses.Count; i++ ) { Vector3 p = rope.masses[i].pos; Vector3 lp = rope.masses[i].last; if ( Vector3.Distance(p, lp) > rad ) { Debug.Log("Mass " + i + " moved too much"); } for ( int j = i + 2; j < rope.masses.Count; j++ ) { //float dsqr = Vector3.SqrMagnitude(rope.masses[j].pos - p); float dsqr = Vector3.Magnitude(rope.masses[j].pos - p); if ( dsqr < rad ) { //Debug.Log("Mass " + i + " hit mass " + j + " dist " + dsqr); Vector3 delta = (rope.masses[j].pos - p).normalized; //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = mid - (delta * rope.radius); //rope.masses[i].pos = p; //rope.masses[j].pos = mid + (delta * rope.radius); if ( p.y > rope.masses[j].pos.y ) { //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); p = rope.masses[j].pos - (delta * rad); rope.masses[i].pos = p; rope.masses[i].last = p; } else { //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = p - (delta * rad); rope.masses[j].pos = p + (delta * rad); rope.masses[j].last = p + (delta * rad); } } } } }
public override void doIntegration1(MegaRope rope, float dt) { doCalculateForces(rope); // 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 += rope.airdrag * (rope.masses[i].pos - rope.masses[i].last) + rope.masses[i].force * rope.masses[i].oneovermass * t2; // * t; //masses[i].pos += airdrag * masses[i].pos - masses[i].last + masses[i].force * masses[i].oneovermass * t2; // * t; //masses[i].pos = masses[i].pos + (masses[i].pos - masses[i].last) * (t / lastt) + masses[i].force * masses[i].oneovermass * t * t; rope.masses[i].vel = (rope.masses[i].pos - last) / dt; rope.masses[i].last = last; } if ( rope.SelfCollide ) SelfCollide(rope); DoConstraints(rope); if ( rope.DoCollide ) DoCollisions(rope, dt); if ( rope.SelfCollide ) SelfCollide(rope); }
public virtual void BuildMesh(MegaRope rope) { }
public override void Apply(MegaRope soft) { // If alpha < 0.0f or > 1.0f then constraint is inactive // If shape is closed? if ( shape != null ) { Vector3 pos = shape.InterpCurve3D(0, alpha, true); soft.masses[p1].pos = pos; } }
public override void Apply(MegaRope soft) { // find distance bewteen attach point on rbody and place on rope, and apply a spring force to the rbody and to the masses }
void SelfCollide(MegaRope rope) { float rad = rope.radius * 2.0f; //(rope.radius * rope.radius); // Check for gaps betweem masses //for ( int i = 0; i < rope.masses.Count - 1; i++ ) //{ // float dst = Vector3.Distance(rope.masses[i].pos, rope.masses[i + 1].pos); // if ( dst > rad ) // { // Debug.Log("gap " + i); // } //} for (int i = 0; i < rope.masses.Count; i++) { Vector3 p = rope.masses[i].pos; //Vector3 lp = rope.masses[i].last; //float pspd = rope.masses[i].vel.magnitude; //Vector3.Distance(p, lp); for (int j = i + 2; j < rope.masses.Count; j++) { //float dsqr = Vector3.SqrMagnitude(rope.masses[j].pos - p); float dsqr = Vector3.Magnitude(rope.masses[j].pos - p); if (dsqr < rad) { //Debug.Log("Mass " + i + " hit mass " + j + " dist " + dsqr); Vector3 delta = (rope.masses[j].pos - p).normalized; //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = mid - (delta * rope.radius); //rope.masses[i].pos = p; //rope.masses[j].pos = mid + (delta * rope.radius); //float hspd = Vector3.Distance(rope.masses[j].pos, rope.masses[j].vel; if (rope.masses[i].collide) { rope.masses[j].pos = p + (delta * rad); rope.masses[j].last = p + (delta * rad); } else { if (rope.masses[j].collide) { p = rope.masses[j].pos - (delta * rad); rope.masses[i].pos = p; rope.masses[i].last = p; } else { Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); p = mid + (delta * rope.radius); rope.masses[j].pos = p; rope.masses[j].last = p; p = mid - (delta * rope.radius); rope.masses[i].pos = p; rope.masses[i].last = p; } } } } } }
// Dont need to self collide with n masses either side void SelfCollide2(MegaRope rope) { float rad = rope.radius * 2.0f; //(rope.radius * rope.radius); rad *= rad; // Check for gaps betweem masses //for ( int i = 0; i < rope.masses.Count - 1; i++ ) //{ // float dst = Vector3.Distance(rope.masses[i].pos, rope.masses[i + 1].pos); // if ( dst > rad ) // { // Debug.Log("gap " + i); // } //} Vector3 delta = Vector3.zero; for (int i = 0; i < rope.masses.Count; i++) { Vector3 p = rope.masses[i].pos; Vector3 lp = rope.masses[i].last; //float pspd = rope.masses[i].vel.magnitude; //Vector3.Distance(p, lp); Vector3 delta1 = (p - lp).normalized; for (int j = i + 2; j < rope.masses.Count; j++) { Vector3 p1 = rope.masses[j].pos; delta.x = p1.x - p.x; delta.y = p1.y - p.y; delta.z = p1.z - p.z; float dsqr = delta.sqrMagnitude; //Vector3.SqrMagnitude(rope.masses[j].pos - p); //float dsqr = Vector3.Magnitude(rope.masses[j].pos - p); if (dsqr < rad) { float do1 = 1.0f / Mathf.Sqrt(dsqr); delta.x *= do1; delta.y *= do1; delta.z *= do1; //Debug.Log("Mass " + i + " hit mass " + j + " dist " + dsqr); //Vector3 delta = (rope.masses[j].pos - p).normalized; //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = mid - (delta * rope.radius); //rope.masses[i].pos = p; //rope.masses[j].pos = mid + (delta * rope.radius); //float hspd = Vector3.Distance(rope.masses[j].pos, rope.masses[j].vel; if (rope.masses[i].collide) { rope.masses[j].pos = p + (delta * rad); rope.masses[j].last = p + (delta * rad); } else { if (rope.masses[j].collide) { p = rope.masses[j].pos - (delta * rad); rope.masses[i].pos = p; rope.masses[i].last = p; } else { // back each mass back along its path until they dont touch Vector3 delta2 = (rope.masses[j].pos - rope.masses[j].last).normalized; int max = 8; while (dsqr < rad) { float ds = (rad - dsqr); // * 0.5f; p -= delta1 * ds; rope.masses[j].pos -= delta2 * ds; dsqr = Vector3.Magnitude(rope.masses[j].pos - p); max--; if (max < 0) { break; } } //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = mid + (delta * rope.radius); rope.masses[i].pos = p; rope.masses[i].last = p; //p = mid - (delta * rope.radius); //rope.masses[i].pos = p; rope.masses[j].last = rope.masses[j].pos; } } } } } }
// dist3D_Segment_to_Segment(): // Input: two 3D line segments S1 and S2 // Return: the shortest distance between S1 and S2 public static float GetDist(MegaRope rope, MegaRopeSpring S1, MegaRopeSpring S2) { Vector3 u = rope.masses[S1.p2].pos - rope.masses[S1.p1].pos; Vector3 v = rope.masses[S2.p2].pos - rope.masses[S2.p1].pos; Vector3 w = rope.masses[S1.p1].pos - rope.masses[S2.p1].pos; float a = Vector3.Dot(u, u); // always >= 0 float b = Vector3.Dot(u, v); float c = Vector3.Dot(v, v); // always >= 0 float d = Vector3.Dot(u, w); float e = Vector3.Dot(v, w); float D = a * c - b * b; // always >= 0 float sc, sN, sD = D; // sc = sN / sD, default sD = D >= 0 float tc, tN, tD = D; // tc = tN / tD, default tD = D >= 0 // compute the line parameters of the two closest points if ( D < 0.0000001f ) { // the lines are almost parallel sN = 0.0f; // force using point P0 on segment S1 sD = 1.0f; // to prevent possible division by 0.0 later tN = e; tD = c; } else { // get the closest points on the infinite lines sN = (b * e - c * d); tN = (a * e - b * d); if ( sN < 0.0 ) { // sc < 0 => the s=0 edge is visible sN = 0.0f; tN = e; tD = c; } else { if ( sN > sD ) { // sc > 1 => the s=1 edge is visible sN = sD; tN = e + b; tD = c; } } } if ( tN < 0.0f ) { // tc < 0 => the t=0 edge is visible tN = 0.0f; // recompute sc for this edge if ( -d < 0.0f ) sN = 0.0f; else { if ( -d > a ) sN = sD; else { sN = -d; sD = a; } } } else { if ( tN > tD ) { // tc > 1 => the t=1 edge is visible tN = tD; // recompute sc for this edge if ( (-d + b) < 0.0 ) sN = 0; else { if ( (-d + b) > a ) sN = sD; else { sN = (-d + b); sD = a; } } } } // finally do the division to get sc and tc sc = (Mathf.Abs(sN) < 0.0000001f ? 0.0f : sN / sD); tc = (Mathf.Abs(tN) < 0.0000001f ? 0.0f : tN / tD); // get the difference of the two closest points Vector3 dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc) return dP.magnitude; //norm(dP); // return the closest distance }
void DoCollisions1(MegaRope rope, float dt) { RaycastHit hit; for ( int i = 0; i < rope.masses.Count; i++ ) { //Vector3 start = rope.masses[i].pos - (rope.masses[i].vel * 10.0f); if ( Physics.CheckSphere(rope.masses[i].pos, rope.radius, rope.layer) ) { if ( Physics.SphereCast(rope.masses[i].last, rope.radius, rope.masses[i].vel.normalized, out hit, (rope.masses[i].vel.magnitude * dt) * 2.0f, rope.layer) ) { //Debug.Log("d " + hit.distance); //if ( hit.distance < 10.01f ) { rope.masses[i].pos = hit.point + (hit.normal * (rope.radius * 1.05f)); Response(i, hit, rope); } } } } }
void doCalculateForces(MegaRope rope) { for ( int i = 0; i < rope.masses.Count; i++ ) { //rope.masses[i].force = rope.masses[i].mass * rope.gravity; rope.masses[i].force.x = rope.masses[i].mass * rope.gravity.x; rope.masses[i].force.y = rope.masses[i].mass * rope.gravity.y; rope.masses[i].force.z = rope.masses[i].mass * rope.gravity.z; //rope.masses[i].force += -rope.masses[i].vel * rope.airdrag; // Should be vel sqr //rope.masses[i].force += rope.masses[i].forcec; } for ( int i = 0; i < rope.springs.Count; i++ ) rope.springs[i].doCalculateSpringForce1(rope); }
void Response(int i, RaycastHit hit, MegaRope rope) { // CALCULATE Vn float VdotN = Vector3.Dot(hit.normal, rope.masses[i].vel); Vector3 Vn = hit.normal * VdotN; // CALCULATE Vt //Vector3 Vt = (rope.masses[i].vel - Vn) * rope.floorfriction; // SCALE Vn BY COEFFICIENT OF RESTITUTION Vn *= 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 void Rebuild(MegaRope rope) { if ( source ) { Mesh smesh = MegaUtils.GetSharedMesh(source); if ( smesh ) { bounds = smesh.bounds; sverts = smesh.vertices; overts = new Vector3[smesh.vertexCount]; rope.mesh.Clear(); rope.mesh.vertices = smesh.vertices; rope.mesh.normals = smesh.normals; rope.mesh.uv = smesh.uv; //rope.mesh.uv1 = smesh.uv1; rope.mesh.subMeshCount = smesh.subMeshCount; for ( int i = 0; i < smesh.subMeshCount; i++ ) { rope.mesh.SetTriangles(smesh.GetTriangles(i), i); } MeshRenderer mr = source.GetComponent<MeshRenderer>(); MeshRenderer mr1 = rope.GetComponent<MeshRenderer>(); if ( mr1 != null && mr != null ) mr1.sharedMaterials = mr.sharedMaterials; // Calc the alphas BuildNormalMapping(smesh, true); BuildMesh(rope); } } }
void DoConstraints(MegaRope rope) { for ( int i = 0; i < rope.iters; i++ ) { for ( int c = 0; c < rope.constraints.Count; c++ ) { rope.constraints[c].Apply(rope); //this); } } }
public override void Apply(MegaRope soft) { if ( active ) soft.masses[p1].pos = obj.position + obj.localToWorldMatrix.MultiplyVector(off); }
void SelfCollide(MegaRope rope) { float rad = rope.radius * 2.0f; //(rope.radius * rope.radius); // Check for gaps betweem masses //for ( int i = 0; i < rope.masses.Count - 1; i++ ) //{ // float dst = Vector3.Distance(rope.masses[i].pos, rope.masses[i + 1].pos); // if ( dst > rad ) // { // Debug.Log("gap " + i); // } //} for ( int i = 0; i < rope.masses.Count; i++ ) { Vector3 p = rope.masses[i].pos; //Vector3 lp = rope.masses[i].last; //float pspd = rope.masses[i].vel.magnitude; //Vector3.Distance(p, lp); for ( int j = i + 2; j < rope.masses.Count; j++ ) { //float dsqr = Vector3.SqrMagnitude(rope.masses[j].pos - p); float dsqr = Vector3.Magnitude(rope.masses[j].pos - p); if ( dsqr < rad ) { //Debug.Log("Mass " + i + " hit mass " + j + " dist " + dsqr); Vector3 delta = (rope.masses[j].pos - p).normalized; //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = mid - (delta * rope.radius); //rope.masses[i].pos = p; //rope.masses[j].pos = mid + (delta * rope.radius); //float hspd = Vector3.Distance(rope.masses[j].pos, rope.masses[j].vel; if ( rope.masses[i].collide ) { rope.masses[j].pos = p + (delta * rad); rope.masses[j].last = p + (delta * rad); } else { if ( rope.masses[j].collide ) { p = rope.masses[j].pos - (delta * rad); rope.masses[i].pos = p; rope.masses[i].last = p; } else { Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); p = mid + (delta * rope.radius); rope.masses[j].pos = p; rope.masses[j].last = p; p = mid - (delta * rope.radius); rope.masses[i].pos = p; rope.masses[i].last = p; } } } } } }
public override void Apply(MegaRope soft) { if ( active ) soft.masses[p1].pos = obj.position; }
// Dont need to self collide with n masses either side void SelfCollide2(MegaRope rope) { float rad = rope.radius * 2.0f; //(rope.radius * rope.radius); rad *= rad; // Check for gaps betweem masses //for ( int i = 0; i < rope.masses.Count - 1; i++ ) //{ // float dst = Vector3.Distance(rope.masses[i].pos, rope.masses[i + 1].pos); // if ( dst > rad ) // { // Debug.Log("gap " + i); // } //} Vector3 delta = Vector3.zero; for ( int i = 0; i < rope.masses.Count; i++ ) { Vector3 p = rope.masses[i].pos; Vector3 lp = rope.masses[i].last; //float pspd = rope.masses[i].vel.magnitude; //Vector3.Distance(p, lp); Vector3 delta1 = (p - lp).normalized; for ( int j = i + 2; j < rope.masses.Count; j++ ) { Vector3 p1 = rope.masses[j].pos; delta.x = p1.x - p.x; delta.y = p1.y - p.y; delta.z = p1.z - p.z; float dsqr = delta.sqrMagnitude; //Vector3.SqrMagnitude(rope.masses[j].pos - p); //float dsqr = Vector3.Magnitude(rope.masses[j].pos - p); if ( dsqr < rad ) { float do1 = 1.0f / Mathf.Sqrt(dsqr); delta.x *= do1; delta.y *= do1; delta.z *= do1; //Debug.Log("Mass " + i + " hit mass " + j + " dist " + dsqr); //Vector3 delta = (rope.masses[j].pos - p).normalized; //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = mid - (delta * rope.radius); //rope.masses[i].pos = p; //rope.masses[j].pos = mid + (delta * rope.radius); //float hspd = Vector3.Distance(rope.masses[j].pos, rope.masses[j].vel; if ( rope.masses[i].collide ) { rope.masses[j].pos = p + (delta * rad); rope.masses[j].last = p + (delta * rad); } else { if ( rope.masses[j].collide ) { p = rope.masses[j].pos - (delta * rad); rope.masses[i].pos = p; rope.masses[i].last = p; } else { // back each mass back along its path until they dont touch Vector3 delta2 = (rope.masses[j].pos - rope.masses[j].last).normalized; int max = 8; while ( dsqr < rad ) { float ds = (rad - dsqr);// * 0.5f; p -= delta1 * ds; rope.masses[j].pos -= delta2 * ds; dsqr = Vector3.Magnitude(rope.masses[j].pos - p); max--; if ( max < 0 ) break; } //Vector3 mid = (p + rope.masses[j].pos) * 0.5f; //(delta * 0.5f); //p = mid + (delta * rope.radius); rope.masses[i].pos = p; rope.masses[i].last = p; //p = mid - (delta * rope.radius); //rope.masses[i].pos = p; rope.masses[j].last = rope.masses[j].pos; } } } } } }
public virtual void doIntegration1(MegaRope rope, float dt) { }
void DoCollisions1(MegaRope rope, float dt) { RaycastHit hit; Vector3 dir = Vector3.zero; for ( int i = 0; i < rope.masses.Count; i++ ) { if ( Mathf.Abs(rope.masses[i].vel.sqrMagnitude) < 0.0001f ) { dir = Vector3.down; } else dir = rope.masses[i].vel.normalized; Vector3 start = rope.masses[i].pos - (dir * 10.0f); rope.masses[i].collide = false; if ( Physics.CheckSphere(rope.masses[i].pos, rope.radius, rope.layer) ) { Collider[] cols = Physics.OverlapSphere(rope.masses[i].pos, rope.radius, rope.layer); for ( int c = 0; c < cols.Length; c++ ) { Vector3 cp = cols[c].Raycast.ClosestPointOnBounds(rope.masses[i].pos); } if ( Physics.SphereCast(rope.masses[i].last, rope.radius, dir, out hit, (rope.masses[i].vel * dt).magnitude, rope.layer) ) { if ( hit.distance < rope.radius ) //10.0f ) { rope.masses[i].pos = hit.point + (hit.normal * (rope.radius * 1.001f)); Response(i, hit, rope); rope.masses[i].collide = true; } } } } }
public override void Apply(MegaRope soft) { if ( active ) { //calculate direction soft.masses[p1].pos = obj.position; soft.masses[p1].last = soft.masses[p1].pos; Vector3 direction = soft.masses[p2].pos - soft.masses[p1].pos; //calculate current length float currentLength = direction.magnitude; //check for zero vector if ( direction != Vector3.zero ) { //normalize direction vector direction.Normalize(); //move to goal positions Vector3 moveVector = 1.0f * (currentLength - length) * direction; //soft.masses[p1].pos += moveVector; soft.masses[p2].pos += -moveVector; soft.masses[p2].last = soft.masses[p2].pos; } } }
public virtual void doIntegration1(MegaRope rope, float dt) { }
public virtual void Apply(MegaRope soft) { }
void DoCollisions(MegaRope rope, float dt) { RaycastHit hit; for ( int i = 0; i < rope.masses.Count; i++ ) { Vector3 start = rope.masses[i].last - (Vector3.down * 10.0f); if ( Physics.CheckSphere(rope.masses[i].last, rope.radius, rope.layer) ) { if ( Physics.SphereCast(start, rope.radius, Vector3.down, out hit, (rope.masses[i].vel.magnitude * dt) + 20.0f, rope.layer) ) { if ( hit.distance < 10.0f ) { rope.masses[i].pos = hit.point + (hit.normal * (rope.radius * 1.001f)); Response(i, hit, rope); } } } } }
// This will take a selected object and deform that along the spline public override void BuildMesh(MegaRope rope) { // Option to stretch the mesh to fit, and end to start from if ( source ) { if ( overts == null ) { Rebuild(rope); //Mesh smesh = MegaUtils.GetMesh(source); //bounds = smesh.bounds; //sverts = smesh.vertices; //verts = new Vector3[smesh.vertexCount]; } // Calc frames if ( frames == null || frames.Length != numframes + 1 ) { frames = new Matrix4x4[numframes + 1]; } wtm = rope.GetDeformMat(0.0f); T = wtm.MultiplyPoint3x4(rope.Velocity(0.0f).normalized); // Calc vector to use for cp based on velocity of first point Vector3 cp = wtm.MultiplyPoint3x4(tm.MultiplyPoint3x4(Vector3.right)); N = (cp - wtm.MultiplyPoint3x4(rope.Interp(0.0f))).normalized; B = Vector3.Cross(T, N); frames[0] = wtm; for ( int i = 0; i <= numframes; i++ ) { float alpha = (float)i / (float)numframes; if ( i == 0 ) { alpha = 0.001f; } T = rope.Velocity(alpha).normalized; frames[i] = rope.CalcFrame(T, ref N, ref B); } int ax = (int)meshaxis; Vector3 sscl = scale; //StartScale * GlobalScale; //Vector3 soff = Vector3.Scale(offset, sscl); tm = Matrix4x4.identity; //wtm = rope.GetDeformMat(0.0f); //T = wtm.MultiplyPoint3x4(rope.Velocity(0.0f).normalized); // Calc vector to use for cp based on velocity of first point //Vector3 cp = wtm.MultiplyPoint3x4(tm.MultiplyPoint3x4(Vector3.right)); //N = (cp - wtm.MultiplyPoint3x4(rope.Interp(0.0f))).normalized; //B = Vector3.Cross(T, N); float off = 0.0f; float min = bounds.min[ax]; float sz = bounds.size[ax]; //float alpha = 0.0f; //Debug.Log("min " + min + "sz " + sz); off -= bounds.min[(int)meshaxis] * sscl[ax]; if ( !stretchtofit ) { sz = rope.RopeLength; } for ( int i = 0; i < sverts.Length; i++ ) { Vector3 p = sverts[i]; float alpha = Mathf.Clamp01((p[ax] - min) / sz); // can pre calc //if ( alpha > 1.0f || alpha < 0.0f ) //{ // Debug.Log("Alpha " + alpha + " val " + p[ax]); //} MegaMatrix.SetTrans(ref frames[(int)(alpha * numframes)], rope.Interp(alpha)); p[ax] = 0.0f; p.x *= scale.x; p.y *= scale.y; p.z *= scale.z; //p = Deform(p, off, rope, alpha); overts[i] = frames[(int)(alpha * numframes)].MultiplyPoint3x4(p); } // Going to need Mega Normal calculator here potentially rope.mesh.vertices = overts; rope.mesh.RecalculateBounds(); //rope.mesh.RecalculateNormals(); RecalcNormals(rope.mesh, overts); } }