#include #include "constraint.h" #include "particle.h" #include "shape.h" using namespace mbostock; static Projection p; bool Constraints::minDistance(Particle& a, Vector p, float d) { Vector v = p - a.position; float l = v.length(); if (l < d) { a.position += v * ((l - d) / l); return true; } return false; } bool Constraints::minDistance(Particle& a, Particle& b, float d) { Vector v = b.position - a.position; float l = v.length(); if (l < d) { v *= (l - d) / ((a.inverseMass + b.inverseMass) * l); a.position += v * a.inverseMass; b.position -= v * b.inverseMass; return true; } return false; } bool Constraints::maxDistance(Particle& a, Vector p, float d) { Vector v = p - a.position; float l = v.length(); if (l > d) { a.position += v * ((l - d) / l); return true; } return false; } bool Constraints::maxDistance(Particle& a, Particle& b, float d) { Vector v = b.position - a.position; float l = v.length(); if (l > d) { v *= (l - d) / ((a.inverseMass + b.inverseMass) * l); a.position += v * a.inverseMass; b.position -= v * b.inverseMass; return true; } return false; } bool Constraints::distance(Particle& a, Vector p, float d) { Vector v = p - a.position; float l = v.length(); a.position += v * ((l - d) / l); return l > 0.f; } bool Constraints::distance(Particle& a, Particle& b, float d) { Vector v = b.position - a.position; float l = v.length(); v *= (l - d) / ((a.inverseMass + b.inverseMass) * l); a.position += v * a.inverseMass; b.position -= v * b.inverseMass; return l > 0.f; } bool Constraints::plane(Particle& a, Vector p, Vector n) { float d = n.dot(a.position - p); if (d < 0) { a.position -= n * d; return true; } return false; } bool Constraints::plane(Particle& a, Vector p, Vector n, float kr) { float d = n.dot(a.position - p); if (d < 0) { Vector v = a.position - a.previousPosition; Vector vNormal = n * n.dot(v); Vector vTangent = v - vNormal; a.position -= n * d; a.previousPosition = a.position - vTangent + vNormal * kr; return true; } return false; } /* XXX What if p.length is 0? Use the normal? */ bool Constraints::inside(Particle& a, const Shape& s, float r) { p = s.project(a.position); if (p.length > -r) { a.position = p.x + (p.x - a.position) * (r / p.length); return true; } return false; } bool Constraints::inside(Particle& a, const Shape& s, float r, float kr) { p = s.project(a.position); if (p.length > -r) { Vector v = a.position - a.previousPosition; Vector vNormal = p.normal * p.normal.dot(v); Vector vTangent = v - vNormal; a.position = p.x + (p.x - a.position) * (r / p.length); a.previousPosition = a.position - vTangent + vNormal * kr; return true; } return false; } bool Constraints::outside(Particle& a, const Shape& s, float r) { p = s.project(a.position); if (p.length < r) { a.position = p.x - (p.x - a.position) * (r / p.length); return true; } return false; } bool Constraints::outside(Particle& a, const Shape& s, float r, float kr) { p = s.project(a.position); if (p.length < r) { Vector v = a.position - a.previousPosition; Vector vNormal = p.normal * p.normal.dot(v); Vector vTangent = v - vNormal; a.position = p.x - (p.x - a.position) * (r / p.length); a.previousPosition = a.position - vTangent + vNormal * kr; return true; } return false; } const Projection& Constraints::projection() { return p; }