// -*- C++ -*- #include #include "material.h" #include "physics/constraint.h" #include "physics/force.h" #include "physics/particle.h" #include "physics/shape.h" #include "physics/vector.h" #include "seesaw.h" using namespace mbostock; static const float centerOffset = .1f; Seesaw::Seesaw(const Vector& min, const Vector& max, float mass) : origin_((min + max) / 2.f), size_(max - min), drag_(1.f), model_(box_) { left_.inverseMass = 1.f / (mass * .1f); right_.inverseMass = 1.f / (mass * .1f); center_.inverseMass = 1.f / (mass * .8f); reset(); } const Shape& Seesaw::shape() const { return box_; } Model& Seesaw::model() { return model_; } void Seesaw::resetForces() { left_.force = Vector::ZERO(); right_.force = Vector::ZERO(); center_.force = Vector::ZERO(); drag_.apply(left_); drag_.apply(right_); drag_.apply(center_); } void Seesaw::applyForce(UnaryForce& force) { force.apply(left_); force.apply(right_); force.apply(center_); } void Seesaw::applyWeight(float w, const Vector& x) { if (x.x < origin_.x) { left_.force.y -= w * (2 * (origin_.x - x.x) / size_.x); } else { right_.force.y += w * (2 * (origin_.x - x.x) / size_.x); } } void Seesaw::step(const ParticleSimulator& s) { s.step(left_); s.step(right_); s.step(center_); updateBox(); } void Seesaw::updateBox() { Vector x = (right_.position - left_.position) / size_.x; Vector y = -x.cross(Vector::Z()) * size_.y / 2.f; Vector z = Vector::Z() * size_.z / 2.f; box_ = Box( left_.position - z - y, right_.position - z - y, right_.position + z - y, left_.position + z - y, right_.position - z + y, left_.position - z + y, left_.position + z + y, right_.position + z + y); } void Seesaw::constrainInternal() { Vector v = origin_ - (left_.position + right_.position) / 2.f; right_.position += v; left_.position += v; Constraints::distance(right_, origin_, size_.x / 2.f); Constraints::distance(left_, origin_, size_.x / 2.f); Constraints::distance(right_, left_, size_.x); Constraints::distance(center_, origin_, centerOffset); float d = sqrtf(size_.x * size_.x / 4.f + centerOffset * centerOffset); Constraints::distance(left_, center_, d); Constraints::distance(right_, center_, d); } void Seesaw::reset() { left_.position = origin_; left_.position.x -= size_.x / 2.f; right_.position = origin_; right_.position.x += size_.x / 2.f; center_.position = origin_; center_.position.y -= centerOffset; left_.previousPosition = left_.position; right_.previousPosition = right_.position; center_.previousPosition = center_.position; updateBox(); } void Seesaw::setMaterial(const Material& m) { model_.setMaterial(m); } void Seesaw::setTopMaterial(const Material& m) { model_.setTopMaterial(m); } float Seesaw::slip() const { return model_.material().slip(); }