void PhysicsVehicleWheel::transform(Node* node) const { GP_ASSERT(_host); GP_ASSERT(_host->_node); node->setRotation(_orientation); // Use only the component parallel to the defined strut line Vector3 strutLine; getWheelDirection(&strutLine); _host->_node->getMatrix().transformVector(&strutLine); Vector3 wheelPos; getWheelPos(&wheelPos); node->setTranslation(wheelPos + strutLine*(strutLine.dot(_positionDelta) / strutLine.lengthSquared())); }
void PhysicsVehicleWheel::getConnectionDefault(Vector3* result) const { // projected strut length getWheelDirection(result); result->normalize(); float length = 0.58f * getStrutRestLength(); *result *= -length; // nudge wheel contact point to outer edge of tire for stability Vector3 nudge; getWheelAxle(&nudge); nudge *= nudge.dot(_initialOffset); nudge.normalize(); *result += nudge * 0.068f * getWheelRadius(); // rough-in for tire width // offset at bind time *result += _initialOffset; }
void Wheel::calculateForces(double dt) { f = Vector2D(0, 0); force_moment = 0; double mu_par, mu_perp; switch (state) { case WheelState::Broken: mu_par = mu_broken_friction; mu_perp = mu_broken_friction; break; case WheelState::Braking: mu_par = mu_parallel_friction; mu_perp = mu_perpendicular_friction; break; case WheelState::Free: case WheelState::Forward: case WheelState::Backward: default: mu_par = mu_parallel_roll / radius; mu_perp = mu_perpendicular_friction; break; } double vl = v.getLength(); Vector2D w = getWheelDirection(); double v_par = std::abs(v.scalar(w)); double v_perp = sqrt(std::abs(vl * vl - v_par * v_par)); if (v_par > eps) { Vector2D f_par = w; if (f_par.scalar(v) > 0) { f_par.mul(-1); } f_par.mul(distributed_weight * getChangedMu(mu_par)); if (f_par.getLength() > shaking_koef * v_par * (distributed_weight / G) / dt) { f_par.setLength(shaking_koef * v_par * (distributed_weight / G) / dt); }/**/ f.add(f_par); } if (v_perp > eps) { Vector2D f_perp = w; f_perp.rotate(M_PI / 2); if (f_perp.scalar(v) > 0) { f_perp.mul(-1); } f_perp.mul(distributed_weight * getChangedMu(mu_perp)); if (f_perp.getLength() > shaking_koef * v_perp * (distributed_weight / G) / dt) { f_perp.setLength(shaking_koef * v_perp * (distributed_weight / G) / dt); }/**/ force_moment += 10 * r.cross(f_perp); Vector2D p_f_p(f_perp.getLength(), 0); if (p_f_p.scalar(v) > 0) { p_f_p.mul(-1); } double p_v_perp = std::abs(v.scalar(Vector2D(1, 0))); if (p_f_p.getLength() > shaking_koef * p_v_perp * (distributed_weight / G) / dt) { p_f_p.setLength(shaking_koef * p_v_perp * (distributed_weight / G) / dt); } f.add(p_f_p); } if ((state == WheelState::Forward) || (state == WheelState::Backward)) { int force_koef = (state == WheelState::Forward ? 1 : -1); Vector2D acc_force = w; acc_force.mul((force_koef * distributed_torque / radius)); f.add(acc_force); } force_moment += r.cross(f); }