public void UpdateRailSegment(int index, Vector3[] controlPoints) { RailSegment segment = RailSegments[index]; segment.Curve.SetControlPoints(controlPoints); Definition.CreateGeometry(RailSegments); }
private void PutLastWheelsetOnTrack() { float distance = Definition.DistanceFromFirstToLastWheelset * -FirstWheelsetDirectionOfT; LastWheelsetSegmentT = FirstWheelsetSegmentT; LastWheelsetDirectionOfT = FirstWheelsetDirectionOfT; LastWheelsetSegment = FirstWheelsetSegment.MoveSignedDistance(distance, ref LastWheelsetSegmentT, ref LastWheelsetDirectionOfT); }
public void PutOnTrack(RailSegment firstWheelsetSegment, float firstWheelsetT, bool sameDirectionAsSegment) { FirstWheelsetSegment = firstWheelsetSegment; FirstWheelsetSegmentT = firstWheelsetT; FirstWheelsetDirectionOfT = sameDirectionAsSegment ? 1 : -1; PutLastWheelsetOnTrack(); }
public void RemoveRailSegment(RailSegment segment) { if (!RailSegments.Contains(segment)) { return; } segment.Detach(); RailSegments.Remove(segment); }
public void RestorePreviousParameters() { FirstWheelsetSegment = m_previousFirstWheelsetSegment; FirstWheelsetSegmentT = m_previousFirstWheelsetSegmentT; FirstWheelsetDirectionOfT = m_previousFirstWheelsetDirectionOfT; LastWheelsetSegment = m_previousLastWheelsetSegment; LastWheelsetSegmentT = m_previousLastWheelsetSegmentT; LastWheelsetDirectionOfT = m_previousLastWheelsetDirectionOfT; }
public void Detach() { foreach (ConnectedSegmentInfo connectedSegmentInfo in ConnectedSegmentInfos) { RailSegment connectedSegment = connectedSegmentInfo.RailSegment; int removeIndex = connectedSegment.GetConnectionIndex(this); connectedSegment.ConnectedSegmentInfos.RemoveAt(removeIndex); } ConnectedSegmentInfos.Clear(); }
private int GetConnectionIndex(RailSegment segment) { for (int k = 0; k < ConnectedSegmentInfos.Count; k++) { if (ConnectedSegmentInfos[k].RailSegment == segment) { return(k); } } throw new ArgumentException("Given segment is not connected"); }
private void UpdateLastWheelsetPosition() { if (Definition.Wheelsets.Length == 1) { LastWheelsetSegment = FirstWheelsetSegment; LastWheelsetSegmentT = FirstWheelsetSegmentT; LastWheelsetDirectionOfT = FirstWheelsetDirectionOfT; return; } Vector3 firstWheelsetPosition = FirstWheelsetSegment.GetCurvePositionInWorldSpace(FirstWheelsetSegmentT); Vector3 lastWheelsetPosition = LastWheelsetSegment.GetCurvePositionInWorldSpace(LastWheelsetSegmentT); float wantedDistance = Definition.DistanceFromFirstToLastWheelset; float actualDistance = (firstWheelsetPosition - lastWheelsetPosition).magnitude; float distanceToMove = LastWheelsetDirectionOfT * (actualDistance - wantedDistance); LastWheelsetSegment = LastWheelsetSegment.MoveSignedDistance(distanceToMove, ref LastWheelsetSegmentT, ref LastWheelsetDirectionOfT); }
protected RailPiece(RailPieceDefinition definition, bool copyCurves, bool copyGeometry) { ID = FirstUnusedID++; Definition = definition; GameObject = new GameObject("Rail piece " + ID); // Copy rail segments. Cannot share segments of definition, // because of next and previous fields in rail segments that must // be different for each rail piece instance. RailSegments = new RailSegment[definition.RailSegments.Length]; for (int k = 0; k < RailSegments.Length; k++) { RailSegments[k] = new RailSegment(definition.RailSegments[k], this, copyCurves); } GameObject = (GameObject)Object.Instantiate(definition.GetPrefab()); if (copyGeometry) { } }
public void ConnectSegment(RailSegment segment, bool asPreviousSegment, bool segmentHasSameTDirection) { // Add segment to list of connected segments var segmentInfo = new ConnectedSegmentInfo { RailSegment = segment, AsPrevious = asPreviousSegment, SameTDirection = segmentHasSameTDirection }; ConnectedSegmentInfos.Add(segmentInfo); // Add me to other segment's list of connected segments var otherSegmentInfo = new ConnectedSegmentInfo { RailSegment = this, AsPrevious = asPreviousSegment ? !segmentHasSameTDirection : segmentHasSameTDirection, SameTDirection = segmentHasSameTDirection }; segment.ConnectedSegmentInfos.Add(otherSegmentInfo); }
public void AddRailSegment(RailSegment segment) { if (RailSegments.Contains(segment)) { // If the segment is in the list of rail segments, then // it is already connected to other segments in the list // and also should not be added to the list again return; } // Segment should not be connected to anything Debug.Assert(segment.ConnectedSegmentInfos.Count == 0); // Try to connect the segment to connectors of segments in the system foreach (RailSegment systemSegment in RailSegments) { /* * Matrix systemTransform = systemSegment.WorldTransformation; * Matrix transform = segment.WorldTransformation; * * Vector3 systemCurveStartInWorldSpace = Vector3.Transform(systemSegment.Curve.GetPosition(0), systemTransform); * Vector3 systemCurveDirectionInWorldSpace = Vector3.TransformNormal(systemSegment.Curve.GetTangent(0), systemTransform); * * Vector3 curveStartInWorldSpace = Vector3.Transform(segment.Curve.GetPosition(0), transform); * Vector3 curveDirectionInWorldSpace = Vector3.TransformNormal(segment.Curve.GetTangent(0), transform); * * if (systemCurveStartInWorldSpace.EqualsWithEpsilon(curveStartInWorldSpace, ConnectionEpsilon) && * Vector3.Dot(systemCurveDirectionInWorldSpace, -curveDirectionInWorldSpace) > 0.9f) * { * // Open connectors of both segments at t = 0 connect * // I.E. tail-to-tail connection * systemSegment.ConnectSegment(segment, true, false); * } * * Vector3 curveEndInWorldSpace = Vector3.Transform(segment.Curve.GetPosition(1), transform); * curveDirectionInWorldSpace = Vector3.TransformNormal(segment.Curve.GetTangent(1), transform); * * if (systemCurveStartInWorldSpace.EqualsWithEpsilon(curveEndInWorldSpace, ConnectionEpsilon) && * Vector3.Dot(systemCurveDirectionInWorldSpace, curveDirectionInWorldSpace) > 0.9f) * { * // system segment's connector at t = 0 connects with segment's connector at t = 1 * // I.E. tail-to-head connection * systemSegment.ConnectSegment(segment, true, true); * } * * Vector3 systemCurveEndInWorldSpace = Vector3.Transform(systemSegment.Curve.GetPosition(1), systemTransform); * systemCurveDirectionInWorldSpace = Vector3.TransformNormal(systemSegment.Curve.GetTangent(1), systemTransform); * * curveStartInWorldSpace = Vector3.Transform(segment.Curve.GetPosition(0), transform); * curveDirectionInWorldSpace = Vector3.TransformNormal(segment.Curve.GetTangent(0), transform); * * if (systemCurveEndInWorldSpace.EqualsWithEpsilon(curveStartInWorldSpace, ConnectionEpsilon) && * Vector3.Dot(systemCurveDirectionInWorldSpace, curveDirectionInWorldSpace) > 0.9f) * { * // system segment's connector at t = 1 connects with segment's connector at t = 1 * // I.E. head-to-tail connection * systemSegment.ConnectSegment(segment, false, true); * } * * curveEndInWorldSpace = Vector3.Transform(segment.Curve.GetPosition(1), transform); * curveDirectionInWorldSpace = Vector3.TransformNormal(segment.Curve.GetTangent(1), transform); * * if (systemCurveEndInWorldSpace.EqualsWithEpsilon(curveEndInWorldSpace, ConnectionEpsilon) && * Vector3.Dot(systemCurveDirectionInWorldSpace, -curveDirectionInWorldSpace) > 0.9f) * { * // Open connectors of both segments at t = 1 connect * // I.E. head-to-head connection * systemSegment.ConnectSegment(segment, false, false); * } */ } RailSegments.Add(segment); }
public RailSegment(RailSegment source, RailPiece railPiece, bool copyCurve) { RailPiece = railPiece; Curve = copyCurve ? new BezierCurve3(source.Curve) : source.Curve; }
public RailSegment MoveSignedDistance(float signedDistance, ref float t, ref int directionAlongT) { // Move over the rail segment for the given distance, going to a next or previous // segment if the distance to move is bigger than the distance to the end of the curve of the segment. // If it is, subtract the remaining length on the curve from the distance to travel, set the new // segment as the current segment, and repeat. // The distance to move is signed indicating the direction to move over the segment(s). Positive means // in the same direction as curve parameter t (going from 0 to 1). // Segments can be connected in different ways (head to head, head to tail, etc). Variable XXX // is used to keep track of the direction on the curve. If true, we are moving from current curve parameter // t = <current> to t = 0. If false, we move towards t = 1 float remainingDistance = Math.Abs(signedDistance); bool movePositiveInitial = signedDistance > 0; bool movePositive = movePositiveInitial; RailSegment currentSegment = this; while (remainingDistance > 0) { float curvePosition = currentSegment.Curve.GetLength(0, t); if (movePositive) { // Moving over curve towards t = 1 (positive direction) float remainingCurveLength = Curve.Length - curvePosition; if (remainingDistance <= remainingCurveLength) { // More curve remaining than distance to move. Update time and done curvePosition += remainingDistance; t = currentSegment.Curve.GetTime(curvePosition, 32, CurvePositionTolerance); remainingDistance = 0; } else { // More distance to move than curve length remaining. // Move to end of curve, set next curve as current (if it exists), and continue remainingDistance -= remainingCurveLength; ConnectedSegmentInfo connectedSegmentInfo = GetActiveConnectedSegment(false); if (connectedSegmentInfo.RailSegment != null) { if (connectedSegmentInfo.SameTDirection) { t = 0; } else { movePositive = false; t = 1; } currentSegment = connectedSegmentInfo.RailSegment; } else { // No active next segment: end of track and done currentSegment = null; remainingDistance = 0; t = 1; } } } else { // Moving over curve towards t = 0 (negative direction) if (remainingDistance <= curvePosition) { // More curve remaining than distance to move. Update time and done curvePosition -= remainingDistance; t = currentSegment.Curve.GetTime(curvePosition, 32, CurvePositionTolerance); remainingDistance = 0; } else { // More distance to move than curve length remaining. // Move to start of curve, set previous curve as current (if it exists), and continue remainingDistance -= curvePosition; ConnectedSegmentInfo connectedSegmentInfo = GetActiveConnectedSegment(true); if (connectedSegmentInfo.RailSegment != null) { if (connectedSegmentInfo.SameTDirection) { t = 1; } else { movePositive = true; t = 0; } currentSegment = connectedSegmentInfo.RailSegment; } else { // No active previous segment: end of track and done currentSegment = null; remainingDistance = 0; t = 1; } } } } if (movePositive != movePositiveInitial) { directionAlongT = -directionAlongT; } return(currentSegment); }