public void GenerateRoadPolygon(int steps) { if (RoadPolygons == null) { RoadPolygons = new Ets2Point[0]; } if (RoadPolygons != null && RoadPolygons.Count() == steps) { return; } if (StartNode == null || EndNode == null) { return; } if (Type != Ets2ItemType.Road) { return; } var ps = new Ets2Point[steps]; var sx = StartNode.X; var ex = EndNode.X; var sz = StartNode.Z; var ez = EndNode.Z; var radius = (float)Math.Sqrt((sx - ex) * (sx - ex) + (sz - ez) * (sz - ez)); var tangentSX = (float)Math.Cos(-StartNode.Yaw) * radius; var tangentEX = (float)Math.Cos(-EndNode.Yaw) * radius; var tangentSZ = (float)Math.Sin(-StartNode.Yaw) * radius; var tangentEZ = (float)Math.Sin(-EndNode.Yaw) * radius; for (int k = 0; k < steps; k++) { var s = (float)k / (float)(steps - 1); var x = (float)Ets2CurveHelper.Hermite(s, sx, ex, tangentSX, tangentEX); var z = (float)Ets2CurveHelper.Hermite(s, sz, ez, tangentSZ, tangentEZ); ps[k] = new Ets2Point(x, 0, z, 0); } RoadPolygons = ps; }
/// <summary> /// Generate road curves for a specific lane. The curve is generated with [steps] /// nodes and positioned left or right from the road's middle point. /// Additionally, each extra lane is shifted 4.5 game units outward. /// </summary> /// <param name="steps"></param> /// <param name="leftlane"></param> /// <param name="lane"></param> /// <returns></returns> public IEnumerable <Ets2Point> GenerateRoadCurve(int steps, bool leftlane, int lane) { var ps = new Ets2Point[steps]; var sx = StartNode.X; var ex = EndNode.X; var sz = StartNode.Z; var ez = EndNode.Z; if (steps == 2) { sx += (float)Math.Sin(-StartNode.Yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f); sz += (float)Math.Cos(-StartNode.Yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f); ex += (float)Math.Sin(-EndNode.Yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f); ez += (float)Math.Cos(-EndNode.Yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f); ps[0] = new Ets2Point(sx, 0, sz, StartNode.Yaw); ps[1] = new Ets2Point(ex, 0, ez, EndNode.Yaw); return(ps); } var radius = (float)Math.Sqrt((sx - ex) * (sx - ex) + (sz - ez) * (sz - ez)); var tangentSX = (float)Math.Cos(-StartNode.Yaw) * radius; var tangentEX = (float)Math.Cos(-EndNode.Yaw) * radius; var tangentSZ = (float)Math.Sin(-StartNode.Yaw) * radius; var tangentEZ = (float)Math.Sin(-EndNode.Yaw) * radius; for (int k = 0; k < steps; k++) { var s = (float)k / (float)(steps - 1); var x = (float)Ets2CurveHelper.Hermite(s, sx, ex, tangentSX, tangentEX); var z = (float)Ets2CurveHelper.Hermite(s, sz, ez, tangentSZ, tangentEZ); var tx = (float)Ets2CurveHelper.HermiteTangent(s, sx, ex, tangentSX, tangentEX); var ty = (float)Ets2CurveHelper.HermiteTangent(s, sz, ez, tangentSZ, tangentEZ); var yaw = (float)Math.Atan2(ty, tx); x += (float)Math.Sin(-yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f); z += (float)Math.Cos(-yaw) * (leftlane ? -1 : 1) * (RoadLook.Offset + (0.5f + lane) * 4.5f); ps[k] = new Ets2Point(x, 0, z, yaw); } return(ps); }