public static IRenderableObject Create(AiLane aiLane, float?fixedWidth) { // four vertices per sector const int verticesPerSector = 4; // actually, I think it’s 65535, but let’s not go there const int maxVertices = 30000; var aiPoints = aiLane.Points; var sectorsNumber = aiPoints.Length - 1; if (sectorsNumber < 1) { return(new InvisibleObject()); } if (sectorsNumber * verticesPerSector <= maxVertices) { return(Create(aiPoints, fixedWidth, 0, aiPoints.Length)); } var pointsPerObject = maxVertices / verticesPerSector + 1; var result = new RenderableList(); for (var i = 0; i < aiPoints.Length; i += pointsPerObject) { result.Add(Create(aiPoints, fixedWidth, i, Math.Min(i + pointsPerObject, aiPoints.Length))); } AcToolsLogging.Write("Objects: " + result.Count); return(result); }
public static async Task Run(TrackObjectBase track, bool aiLane) { string modelsFilename = null, kn5Filename = null, aiLaneFilename = null; if (!aiLane) { modelsFilename = track.ModelsFilename; if (!File.Exists(modelsFilename)) { modelsFilename = null; kn5Filename = Path.Combine(track.Location, track.Id + ".kn5"); if (!File.Exists(kn5Filename)) { ModernDialog.ShowMessage("Model not found"); return; } } } else { aiLaneFilename = track.AiLaneFastFilename; if (!File.Exists(aiLaneFilename)) { ModernDialog.ShowMessage("AI lane not found"); return; } } await PrepareAsync(); TrackMapPreparationRenderer renderer = null; try { using (WaitingDialog.Create("Loading model…")) { renderer = aiLaneFilename == null ? modelsFilename == null ? new TrackMapPreparationRenderer(await Task.Run(() => Kn5.FromFile(kn5Filename))) : new TrackMapPreparationRenderer(await Task.Run(() => TrackComplexModelDescription.CreateLoaded(modelsFilename))) : new TrackMapPreparationRenderer(await Task.Run(() => AiLane.FromFile(aiLaneFilename))); } var wrapper = new TrackMapRendererWrapper(track, renderer); wrapper.Form.Icon = AppIconService.GetAppIcon(); wrapper.Run(); } catch (Exception e) { NonfatalError.Notify("Can’t update map", e); } finally { renderer?.Dispose(); } }
// default error is 8‰ private void TestTrack(string path, float length, float minWidth, float maxWidth, float lengthError = 0.008f, float widthError = 0.1f) { var f = Path.Combine(AcRoot, path); var ai = AiLane.FromFile(f); Assert.AreEqual(length, ai.CalculateLength(), length * lengthError, "Length is wrong"); var w = ai.CalculateWidth(); if (w.Item1 == 0f) { // obsolete format? return; } Assert.AreEqual(minWidth, w.Item1, minWidth * widthError, "Min width is wrong"); Assert.AreEqual(maxWidth, w.Item2, maxWidth * widthError, "Max width is wrong"); }
private void Initialize(IDeviceContextHolder holder) { // TODO: errors handling! // DisposeHelper.Dispose(ref _view); DisposeHelper.Dispose(ref _obj); _dirty = false; if (AiLaneMode) { if (_lane == null) { _lane = AiLane.FromFile(GetAiLaneFastFilename(Filename)); } _obj = AiLaneObject.Create(_lane, AiLaneWidth); _obj.ParentMatrix = Matrix.Identity; _obj.UpdateBoundingBox(); if (MapSize == default(Vector2)) { var size = (_obj.BoundingBox ?? default(BoundingBox)).GetSize(); MapSize = new Vector2(size.X, size.Z); } } else { if (_view == null) { using (var map = Texture2D.FromFile(holder.Device, Filename)) { if (MapSize == default(Vector2)) { MapSize = new Vector2(map.Description.Width, map.Description.Height); } _view = new ShaderResourceView(holder.Device, map); } } } }
public TrackMapPreparationRenderer(AiLane kn5) : base(kn5) { Camera = new CameraOrtho(); }
public TrackMapRenderer(AiLane aiLane) { _aiLane = aiLane; }