private void UPinit() { if (!_up) { _up = true; _l = new Kn5RenderableList(Kn5Node.CreateBaseNode("L"), null) { LocalMatrix = Matrix.Translation(_swRadius, 0, _swOffset), HighlightDummy = true }; _r = new Kn5RenderableList(Kn5Node.CreateBaseNode("R"), null) { LocalMatrix = Matrix.Translation(-_swRadius, 0, _swOffset), HighlightDummy = true }; _dbg0 = new Kn5RenderableList(Kn5Node.CreateBaseNode("debug"), null) { HighlightDummy = true }; _dbg1 = new Kn5RenderableList(Kn5Node.CreateBaseNode("debug"), null) { HighlightDummy = true }; //_steer.Add(_l); //_steer.Add(_r); _la = new Arm(_driver, true); _ra = new Arm(_driver, false); } }
private static void FixSuspensionNodes(Kn5 kn5) { foreach (var name in SuspensionNodes.Where(name => kn5.FirstByName(name) == null)) { var node = Kn5Node.CreateBaseNode(name); var wheel = kn5.FirstByName(name.Replace("SUSP", "WHEEL"))?.Transform; if (wheel != null) { node.Transform = wheel; } kn5.RootNode.Children.Add(node); } }
public static bool FixSuspension(string acRoot, string carName) { var kn5File = FileUtils.GetMainCarFilename(acRoot, carName); var kn5 = Kn5.FromFile(kn5File); var added = 0; foreach (var name in new [] { "SUSP_LF", "SUSP_RF", "SUSP_LR", "SUSP_RR" }.Where(name => kn5.FirstByName(name) == null)) { kn5.RootNode.Children.Add(Kn5Node.CreateBaseNode(name)); added++; } if (added == 0) { return(false); } kn5.SaveRecyclingOriginal(kn5File); return(true); }
private static async Task PrepareForGenerationAsync(Kn5NodeFilterContext filterContext, IKn5 kn5, CarLodGeneratorStageParams stage, bool printNodes) { var mergeRules = new CarLodGeneratorMergeRules(filterContext, stage); var toMerge = new Dictionary <Kn5Node, List <Tuple <Kn5Node, double, Mat4x4> > >(); var nodeIndices = new Dictionary <Kn5Node, int>(); MergeNode(kn5.RootNode, kn5.RootNode, 1d); foreach (var pair in toMerge) { var mergeData = pair.Value.GroupBy(x => mergeRules.MergeGroup(x.Item1, x.Item2)) .OrderBy(v => mergeRules.GroupOrder(kn5, v, nodeIndices)).Select(v => v.ToList()).ToList(); await Task.Run(() => { foreach (var group in mergeData) { MergeMeshes(pair.Key, group, mergeRules, stage); } }); } foreach (var node in kn5.Nodes.Where(x => x.Children?.Count > 1).ToList()) { var meshesList = node.Children .Where(x => x.NodeClass != Kn5NodeClass.Base) .Select((x, i) => new { x, i = OrderIndex(x, i) }) .OrderBy(x => x.i) .Select(x => x.x).ToList(); if (meshesList.Count > 0) { if (node.Children.Any(x => x.NodeClass == Kn5NodeClass.Base)) { node.Children = node.Children.Where(x => x.NodeClass == Kn5NodeClass.Base) .Prepend(Kn5Node.CreateBaseNode($"__{meshesList[0].Name}_wrap_", meshesList, true)) .Select((x, i) => new { x, i = OrderIndex(x, i) }) .OrderBy(x => x.i) .Select(x => x.x).ToList(); } else { node.Children = meshesList; } } } if (printNodes) { PrintNode(kn5.RootNode, 0, 0); } mergeRules.FinalizeKn5(kn5); var duplicateNames = kn5.Nodes.GroupBy(x => $"{x.NodeClass}/{x.Name}") .Select(x => x.ToList()).Where(x => x.Count > 1).ToList(); foreach (var group in duplicateNames) { AcToolsLogging.Write($"Duplicate name: {group[0].Name} ({group[0].NodeClass})"); foreach (var toRename in group.Skip(1).Select((x, i) => new { x, i })) { toRename.x.Name = $"{toRename.x.Name}___$unique:{toRename.i}"; } } int OrderIndex(Kn5Node node, int index) { return(index + (AnyTransparent(node) ? 1 << 10 : 0)); } void PrintNode(Kn5Node node, int level, int index) { var postfix = node.NodeClass == Kn5NodeClass.Base ? "" : $"{(node.IsTransparent ? ", transparent" : "")}, material: {kn5.GetMaterial(node.MaterialId)?.Name}"; AcToolsLogging.Write( $"{new string('\t', level)}{node.Name} [{node.NodeClass}{postfix}, index: {OrderIndex(node, index)}, aabb: {filterContext.GetAabb3(node)}]"); if (node.NodeClass == Kn5NodeClass.Base) { for (var i = 0; i < node.Children.Count; i++) { PrintNode(node.Children[i], level + 1, i); } } } bool AnyTransparent(Kn5Node node) { return(node.NodeClass == Kn5NodeClass.Base ? node.Children.Any(AnyTransparent) : node.IsTransparent || kn5.GetMaterial(node.MaterialId)?.BlendMode == Kn5MaterialBlendMode.AlphaBlend); } void ApplyPriority(Kn5Node mesh, double priority) { var offset = MoveAsideDistance(priority, stage); for (var i = 0; i < mesh.Vertices.Length; i++) { Apply(ref mesh.Vertices[i]); } mesh.Tag = priority; void Apply(ref Kn5Node.Vertex v) { v.Position[0] = v.Position[0] * (float)priority + offset.X; v.Position[1] = v.Position[1] * (float)priority + offset.Y; v.Position[2] = v.Position[2] * (float)priority + offset.Z; } } bool MergeNode(Kn5Node node, Kn5Node mergeRoot, double priority) { nodeIndices[node] = nodeIndices.Count; if (node != mergeRoot) { if (mergeRules.CanSkipNode(node)) { if (node.NodeClass == Kn5NodeClass.Base && !mergeRules.HasParentWithSameName(node) && !mergeRules.CanRemoveEmptyNode(node)) { node.Children.Clear(); return(true); } return(false); } var priorityAdjustment = mergeRules.CalculateReductionPriority(node); if (priorityAdjustment != 1d && (priorityAdjustment < priority || priority == 1d || node.NodeClass == Kn5NodeClass.Mesh)) { priority = priorityAdjustment; } if (node.NodeClass == Kn5NodeClass.Mesh) { if (mergeRoot != null && mergeRules.CanMerge(node)) { if (!toMerge.ContainsKey(mergeRoot)) { toMerge[mergeRoot] = new List <Tuple <Kn5Node, double, Mat4x4> >(); } toMerge[mergeRoot].Add(Tuple.Create(node, priority, node.CalculateTransformRelativeToParent(mergeRoot))); return(false); } if (priority != 1d) { ApplyPriority(node, priority); } return(true); } if (node.NodeClass == Kn5NodeClass.SkinnedMesh) { return(true); } if (mergeRoot != null) { if (!mergeRules.CanMerge(node)) { mergeRoot = null; } else if (node.Name != mergeRoot.Name && mergeRules.IsNodeMergeRoot(node)) { mergeRoot = node; } } } for (var i = 0; i < node.Children.Count; ++i) { if (!MergeNode(node.Children[i], mergeRoot, priority)) { node.Children.RemoveAt(i); --i; } } return(node.Children.Count > 0 || mergeRoot == node || !mergeRules.CanRemoveEmptyNode(node)); } }