// ReoptimizeLinkOrder minimizes the cases where links L and L+1 share a common node. public static void ReoptimizeLinkOrder(SoftBody psb) { AlignedLinkArray links = psb.Links; AlignedNodeArray nodes = psb.Nodes; int nLinks = links.Count; int nNodes = nodes.Count; List <Link> readyList = new List <Link>(); Dictionary <Link, Link> linkBuffer = new Dictionary <Link, Link>(); Dictionary <Link, LinkDep> linkDeps = new Dictionary <Link, LinkDep>(); Dictionary <Node, Link> nodeWrittenAt = new Dictionary <Node, Link>(); Dictionary <Link, Link> linkDepA = new Dictionary <Link, Link>(); // Link calculation input is dependent upon prior calculation #N Dictionary <Link, Link> linkDepB = new Dictionary <Link, Link>(); foreach (Link link in links) { Node ar = link.Nodes[0]; Node br = link.Nodes[1]; linkBuffer.Add(link, new Link(btSoftBody_Link_new2(link.Native))); LinkDep linkDep; if (nodeWrittenAt.ContainsKey(ar)) { linkDepA[link] = nodeWrittenAt[ar]; linkDeps.TryGetValue(nodeWrittenAt[ar], out linkDep); linkDeps[nodeWrittenAt[ar]] = new LinkDep() { Next = linkDep, Value = link }; } if (nodeWrittenAt.ContainsKey(br)) { linkDepB[link] = nodeWrittenAt[br]; linkDeps.TryGetValue(nodeWrittenAt[br], out linkDep); linkDeps[nodeWrittenAt[br]] = new LinkDep() { Next = linkDep, Value = link, LinkB = true }; } if (!linkDepA.ContainsKey(link) && !linkDepB.ContainsKey(link)) { readyList.Add(link); } // Update the nodes to mark which ones are calculated by this link nodeWrittenAt[ar] = link; nodeWrittenAt[br] = link; } int i = 0; while (readyList.Count != 0) { Link link = readyList[0]; links[i++] = linkBuffer[link]; readyList.RemoveAt(0); LinkDep linkDep; linkDeps.TryGetValue(link, out linkDep); while (linkDep != null) { link = linkDep.Value; if (linkDep.LinkB) { linkDepB.Remove(link); } else { linkDepA.Remove(link); } // Add this dependent link calculation to the ready list if *both* inputs are clear if (!linkDepA.ContainsKey(link) && !linkDepB.ContainsKey(link)) { readyList.Add(link); } linkDep = linkDep.Next; } } foreach (Link link in linkBuffer.Values) { btSoftBody_Link_delete(link.Native); } }
// ReoptimizeLinkOrder minimizes the cases where links L and L+1 share a common node. public static void ReoptimizeLinkOrder(SoftBody psb) { AlignedLinkArray links = psb.Links; AlignedNodeArray nodes = psb.Nodes; int nLinks = links.Count; int nNodes = nodes.Count; List<Link> readyList = new List<Link>(); Dictionary<Link, Link> linkBuffer = new Dictionary<Link, Link>(); Dictionary<Link, LinkDep> linkDeps = new Dictionary<Link, LinkDep>(); Dictionary<Node, Link> nodeWrittenAt = new Dictionary<Node, Link>(); Dictionary<Link, Link> linkDepA = new Dictionary<Link, Link>(); // Link calculation input is dependent upon prior calculation #N Dictionary<Link, Link> linkDepB = new Dictionary<Link, Link>(); foreach (Link link in links) { Node ar = link.Nodes[0]; Node br = link.Nodes[1]; linkBuffer.Add(link, new Link(btSoftBody_Link_new2(link._native))); LinkDep linkDep; if (nodeWrittenAt.ContainsKey(ar)) { linkDepA[link] = nodeWrittenAt[ar]; linkDeps.TryGetValue(nodeWrittenAt[ar], out linkDep); linkDeps[nodeWrittenAt[ar]] = new LinkDep() { Next = linkDep, Value = link}; } if (nodeWrittenAt.ContainsKey(br)) { linkDepB[link] = nodeWrittenAt[br]; linkDeps.TryGetValue(nodeWrittenAt[br], out linkDep); linkDeps[nodeWrittenAt[br]] = new LinkDep() { Next = linkDep, Value = link, LinkB = true }; } if (!linkDepA.ContainsKey(link) && !linkDepB.ContainsKey(link)) { readyList.Add(link); } // Update the nodes to mark which ones are calculated by this link nodeWrittenAt[ar] = link; nodeWrittenAt[br] = link; } int i = 0; while (readyList.Count != 0) { Link link = readyList[0]; links[i++] = linkBuffer[link]; readyList.RemoveAt(0); LinkDep linkDep; linkDeps.TryGetValue(link, out linkDep); while (linkDep != null) { link = linkDep.Value; if (linkDep.LinkB) { linkDepB.Remove(link); } else { linkDepA.Remove(link); } // Add this dependent link calculation to the ready list if *both* inputs are clear if (!linkDepA.ContainsKey(link) && !linkDepB.ContainsKey(link)) { readyList.Add(link); } linkDep = linkDep.Next; } } foreach (Link link in linkBuffer.Values) { btSoftBody_Element_delete(link._native); } }