public Node(GraphArray <T> graph) { m_Graph = graph; m_Begin = uint.MaxValue; m_End = uint.MaxValue; m_Marker = false; }
public void UnmarkNodes(GraphArray <Triangle> G) { foreach (GraphArray <Triangle> .Node t in G) { t.Marked = false; } }
private void MarkTriAsTaken(uint i) { //Mark the triangle node m_Triangles[i].Marked = true; //Remove triangle from priority queue if it isn't yet if (!m_TriHeap.Removed(i)) { m_TriHeap.Erase(i); } //Adjust the degree of available neighbour triangles GraphArray <Triangle> .Node Node = m_Triangles[i]; for (uint x = Node.m_Begin; x < Node.m_End; x++) { GraphArray <Triangle> .Arc Link = Node.Arcs[(int)x]; uint j = Link.Terminal.m_Elem.m_Index; if (!m_Triangles[j].Marked && !m_TriHeap.Removed(j)) { uint NewDegree = m_TriHeap[j]; NewDegree = NewDegree - 1; m_TriHeap.Update(j, NewDegree); //Update the candidate list if cache is enabled if (Cache && NewDegree > 0) { m_Candidates.Add(j); } } } }
private void BuildStrip(Strip Strip) { uint Start = Strip.Start; bool ClockWise = false; TriOrder Order = Strip.Order; //Create a new strip Primitive p = new Primitive(PrimType.TriangleStrip); m_PrimitivesVector.Add(p); AddTriangle(m_Triangles[Start].m_Elem, Order, true); MarkTriAsTaken(Start); //Loop while we can further extend the strip GraphArray <Triangle> .Node Node = m_Triangles[Start]; for (uint Size = 1; Size < Strip.Size; Size++) { GraphArray <Triangle> .Arc Link = LinkToNeighbour(Node, ClockWise, ref Order, true); Debug.Assert(Link != null); //Go to the next triangle Node = Link.Terminal; MarkTriAsTaken(Node.m_Elem.m_Index); ClockWise = !ClockWise; } }
// Optimized (overloaded) functions public void Swap(GraphArray <T> Right) { List <Node> n = m_Nodes; List <Arc> a = m_Arcs; m_Nodes = Right.m_Nodes; m_Arcs = Right.m_Arcs; Right.m_Nodes = n; Right.m_Arcs = a; }
void LinkNeighbours(GraphArray <Triangle> Triangles, List <TriEdge> EdgeMap, TriEdge Edge) { //Find the first edge equal to Edge //See if there are any other edges that are equal //(if so, it means that more than 2 triangles are sharing the same edge, //which is unlikely but not impossible) for (int i = BinarySearch <TriEdge>(EdgeMap, Edge, EdgeComp); i < EdgeMap.Count && Edge == EdgeMap[i]; i++) { Triangles.InsertArc(Edge.TriPos, EdgeMap[i].TriPos); } //Note: degenerated triangles will also point themselves as neighbour triangles }
private Strip ExtendToStrip(uint Start, TriOrder Order) { TriOrder StartOrder = Order; m_CurrentNodes = new List <ushort>(); _checkNodes = true; //Begin a new strip Triangle tri = m_Triangles[Start].m_Elem; tri.SetStripID(++m_StripID); AddTriangle(tri, Order, false); TryAddNode(tri.A); TryAddNode(tri.B); TryAddNode(tri.C); uint Size = 1; bool ClockWise = false; //Loop while we can further extend the strip for (uint i = Start; i < m_Triangles.Count && (!Cache || Size + 2 < CacheSize); Size++) { GraphArray <Triangle> .Node Node = m_Triangles[i]; GraphArray <Triangle> .Arc Link = LinkToNeighbour(Node, ClockWise, ref Order, false); // Is it the end of the strip? if (Link == null) { Size--; i = m_Triangles.Count; } else { i = (Node = Link.Terminal).m_Elem.m_Index; Node.m_Elem.SetStripID(m_StripID); ClockWise = !ClockWise; } } _checkNodes = false; m_CurrentNodes.Clear(); return(new Strip(Start, StartOrder, Size)); }
public TriStripper(uint[] TriIndices, ushort[] NodeIds, int[] ImpTable) { m_ImpTable = ImpTable; m_Nodes = NodeIds; m_Triangles = new GraphArray <Triangle>((uint)TriIndices.Length / 3); m_StripID = 0; m_FirstRun = true; m_PrimitivesVector = new List <Primitive>(); m_TriHeap = new HeapArray(CompareType.Less); m_Candidates = new List <uint>(); m_Cache = new CacheSimulator(); m_BackCache = new CacheSimulator(); SetCacheSize(); SetMinStripSize(); SetBackwardSearch(); SetPushCacheHits(); MakeConnectivityGraph(m_Triangles, TriIndices); }
private GraphArray <Triangle> .Arc BackLinkToNeighbour(GraphArray <Triangle> .Node Node, bool ClockWise, ref TriOrder Order) { TriangleEdge Edge = FirstEdge(Node.m_Elem, Order); for (uint i = Node.m_Begin; i < Node.m_End; i++) { GraphArray <Triangle> .Arc Link = Node.Arcs[(int)i]; //Get the reference to the possible previous triangle Triangle Tri = Link.Terminal.m_Elem; //Check whether it's already been used if (Tri.StripID != m_StripID && !Link.Terminal.Marked) { //Does the current candidate triangle match the required position for the strip? if (Edge.B == Tri.A && Edge.A == Tri.B && TryAddNode(Tri.C)) { Order = ClockWise ? TriOrder.CAB : TriOrder.BCA; BackAddIndex(Tri.C); return(Link); } if (Edge.B == Tri.B && Edge.A == Tri.C && TryAddNode(Tri.A)) { Order = ClockWise ? TriOrder.ABC : TriOrder.CAB; BackAddIndex(Tri.A); return(Link); } if (Edge.B == Tri.C && Edge.A == Tri.A && TryAddNode(Tri.B)) { Order = ClockWise ? TriOrder.BCA : TriOrder.ABC; BackAddIndex(Tri.B); return(Link); } } } return(null); }
void MakeConnectivityGraph(GraphArray <Triangle> Triangles, uint[] Indices) { Debug.Assert(Triangles.Count == (Indices.Length / 3)); //Fill the triangle data for (int i = 0; i < Triangles.Count; i++) { Triangles[(uint)i].m_Elem = new Triangle( Indices[i * 3 + 0], Indices[i * 3 + 1], Indices[i * 3 + 2]) { m_Index = (uint)i } } ; //Build an edge lookup table List <TriEdge> EdgeMap = new List <TriEdge>(); for (uint i = 0; i < Triangles.Count; i++) { Triangle Tri = Triangles[i].m_Elem; EdgeMap.Add(new TriEdge(Tri.A, Tri.B, i)); EdgeMap.Add(new TriEdge(Tri.B, Tri.C, i)); EdgeMap.Add(new TriEdge(Tri.C, Tri.A, i)); } EdgeMap.Sort(EdgeComp); //Link neighbour triangles together using the lookup table for (uint i = 0; i < Triangles.Count; i++) { Triangle Tri = Triangles[i].m_Elem; LinkNeighbours(Triangles, EdgeMap, new TriEdge(Tri.B, Tri.A, i)); LinkNeighbours(Triangles, EdgeMap, new TriEdge(Tri.C, Tri.B, i)); LinkNeighbours(Triangles, EdgeMap, new TriEdge(Tri.A, Tri.C, i)); } }
private Strip BackExtendToStrip(uint Start, TriOrder Order, bool ClockWise) { m_CurrentNodes = new List <ushort>(); _checkNodes = true; //Begin a new strip Triangle tri = m_Triangles[Start].m_Elem; uint b = LastEdge(tri, Order).B; if (TryAddNode(b)) { tri.SetStripID(++m_StripID); BackAddIndex(b); } else { _checkNodes = false; m_CurrentNodes.Clear(); return(null); } uint Size = 1; GraphArray <Triangle> .Node Node = null; //Loop while we can further extend the strip for (uint i = Start; !Cache || ((Size + 2) < CacheSize); Size++) { Node = m_Triangles[i]; var Link = BackLinkToNeighbour(Node, ClockWise, ref Order); //Is it the end of the strip? if (Link == null) { break; } else { i = (Node = Link.Terminal).m_Elem.m_Index; Node.m_Elem.SetStripID(m_StripID); ClockWise = !ClockWise; } } _checkNodes = false; m_CurrentNodes.Clear(); //We have to start from a counterclockwise triangle. //Simply return an empty strip in the case where the first triangle is clockwise. //Even though we could discard the first triangle and start from the next counterclockwise triangle, //this often leads to more lonely triangles afterward. if (ClockWise) { return(null); } if (Cache) { m_Cache.Merge(m_BackCache, Size); m_BackCache.Reset(); } return(new Strip(Node.m_Elem.m_Index, Order, Size)); }