void SplineTrack::merge(IMeshBufferPtr buf) const { Vector<float> off = make_vector( static_cast<float>(origin.x), height, static_cast<float>(origin.y)); buf->merge(rail_buf, off, 0.0f); // Draw the sleepers const float sleeper_sep = 0.25f; float delta = 0; int n = 0; do { ++n; delta = ((curve.length - sleeper_sep) / n) - sleeper_sep; } while (delta > sleeper_sep / n); for (int i = 0; i <= n; i++) { float pos = (sleeper_sep / 2) + i * (sleeper_sep + delta); float u_curve_delta; Vector<float> v = curve.linear(pos / curve.length, &u_curve_delta); const Vector<float> deriv = curve.deriv(u_curve_delta); const float angle = rad_to_deg<float>(atanf(deriv.z / deriv.x)); merge_sleeper(buf, off + v, -angle); } }
void SlopeTrack::merge(IMeshBufferPtr buf) const { Vector<float> off = make_vector( static_cast<float>(origin.x), height, static_cast<float>(origin.y)); float y_angle = axis == axis::Y ? -90.0f : 0.0f; off += rotateY(make_vector(-0.5f, 0.0f, 0.0f), y_angle); buf->merge(rail_buf, off, y_angle); // Draw the sleepers for (float t = 0.1f; t < 1.0f; t += 0.25f) { float u_curve_value; const Vector<float> curve_value = curve.linear(t, &u_curve_value); #if 0 // Should the sleepers be at the same angle as the slope? const Vector<float> deriv = curve.deriv(u_curve_value); const float angle = rad_to_deg<float>(atanf(deriv.y / deriv.x)); #endif Vector<float> v = make_vector(curve_value.x, curve_value.y, 0.0f); merge_sleeper(buf, off + rotateY(v, y_angle), y_angle); } }
void SlopeTrack::transform(const track::TravelToken& token, float delta) const { assert(delta < length && delta >= 0.0f); #if 0 debug() << "f(0)=" << curve(0.0f) << " f(0.5)=" << curve(0.5f) << " f(1.0)=" << curve(1.0f); debug() << "f'(0)=" << curve.deriv(0.0f) << " f'(0.5)=" << curve.deriv(0.5f) << " f'(1.0)=" << curve.deriv(1.0f); #endif if (token.direction == -axis) delta = length - delta; const float curve_delta = delta / length; float u_curve_delta; const Vector<float> curve_value = curve.linear(curve_delta, &u_curve_delta); const float x_trans = axis == axis::X ? curve_value.x : 0.0f; const float y_trans =curve_value.y; const float z_trans = axis == axis::Y ? curve_value.x : 0.0f; glTranslated(static_cast<double>(origin.x) + x_trans, height + y_trans, static_cast<double>(origin.y) + z_trans); if (axis == axis::Y) glRotated(-90.0, 0.0, 1.0, 0.0); glTranslated(-0.5, 0.0, 0.0); if (token.direction == -axis) glRotated(-180.0, 0.0, 1.0, 0.0); const Vector<float> deriv = curve.deriv(u_curve_delta); const float angle = rad_to_deg<float>(atanf(deriv.y / deriv.x)); if (token.direction == -axis) glRotatef(-angle, 0.0f, 0.0f, 1.0f); else glRotatef(angle, 0.0f, 0.0f, 1.0f); }
float SlopeTrack::gradient(const track::TravelToken& token, float delta) const { assert(delta < length && delta >= 0.0f); if (token.direction == -axis) delta = length - delta; return curve.deriv(delta / length).y; }
float SplineTrack::rotation_at(float curve_delta) const { assert(curve_delta >= 0.0f && curve_delta <= 1.0f); const Vector<float> deriv = curve.deriv(curve_delta); // Derivation of angle depends on quadrant if (deriv.z >= 0 && deriv.x > 0) return rad_to_deg<float>(atanf(deriv.z / deriv.x)); else if (deriv.z > 0 && deriv.x <= 0) return 90 - rad_to_deg<float>(atanf(deriv.x / deriv.z)); else if (deriv.z <= 0 && deriv.x <= 0) return 270 - rad_to_deg<float>(atanf(deriv.x / deriv.z)); else if (deriv.z <= 0 && deriv.x > 0) return rad_to_deg<float>(atanf(deriv.z / deriv.x)); else assert(false); }
void Points::transform(const track::TravelToken& a_token, float delta) const { const float len = segment_length(a_token); assert(delta < len); if (myX == a_token.position.x && myY == a_token.position.y && state == NOT_TAKEN) { if (a_token.direction == my_axis && (my_axis == -axis::X || my_axis == -axis::Y)) delta -= 1.0f; const float x_trans = my_axis == axis::X ? delta : (my_axis == -axis::X ? -delta : 0.0f); const float y_trans = my_axis == axis::Y ? delta : (my_axis == -axis::Y ? -delta : 0.0f); glTranslatef(static_cast<float>(myX) + x_trans, height, static_cast<float>(myY) + y_trans); if (my_axis == axis::Y || my_axis == -axis::Y) glRotated(-90.0, 0.0, 1.0, 0.0); glTranslated(-0.5, 0.0, 0.0); } else if (a_token.position == straight_endpoint()) { delta = 2.0f - delta; if (a_token.direction == -my_axis && (my_axis == axis::X || my_axis == axis::Y)) delta += 1.0f; const float x_trans = my_axis == axis::X ? delta : (my_axis == -axis::X ? -delta : 0.0f); const float y_trans = my_axis == axis::Y ? delta : (my_axis == -axis::Y ? -delta : 0.0f); glTranslatef(static_cast<float>(myX) + x_trans, height, static_cast<float>(myY) + y_trans); if (my_axis == axis::Y || my_axis == -axis::Y) glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); glTranslatef(-0.5f, 0.0f, 0.0f); } else if (a_token.position == displaced_endpoint() || state == TAKEN) { // Curving onto the straight section float x_trans, y_trans, rotate; // We have a slight problem in that the domain of the curve // function is [0,1] but the delta is in [0,len] so we have // to compress the delta into [0,1] here const float curve_delta = delta / len; bool backwards = a_token.position == displaced_endpoint(); const float f_value = backwards ? 1.0f - curve_delta : curve_delta; float u_f_value; const VectorF curve_value = my_curve.linear(f_value, &u_f_value); // Calculate the angle that the tangent to the curve at this // point makes to (one of) the axis at this point const VectorF deriv = my_curve.deriv(u_f_value); const float angle = rad_to_deg<float>(atanf(deriv.z / deriv.x)); if (my_axis == -axis::X) { x_trans = 1.0f - curve_value.x; y_trans = reflected ? curve_value.z : -curve_value.z; rotate = reflected ? angle : -angle; } else if (my_axis == axis::X) { x_trans = curve_value.x; y_trans = reflected ? -curve_value.z : curve_value.z; rotate = reflected ? angle : -angle; } else if (my_axis == -axis::Y) { x_trans = reflected ? -curve_value.z : curve_value.z; y_trans = 1.0f - curve_value.x; rotate = reflected ? angle : -angle; } else if (my_axis == axis::Y) { x_trans = reflected ? curve_value.z: -curve_value.z; y_trans = curve_value.x; rotate = reflected ? angle : -angle; } else assert(false); glTranslatef( static_cast<float>(myX) + x_trans, height, static_cast<float>(myY) + y_trans); if (my_axis == axis::Y || my_axis == -axis::Y) glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); glTranslatef(-0.5f, 0.0f, 0.0f); glRotatef(rotate, 0.0f, 1.0f, 0.0f); } else assert(false); if (a_token.direction == -axis::X || a_token.direction == -axis::Y) glRotated(-180.0, 0.0, 1.0, 0.0); }