root/trunk/x42view.net/Helpers.Adjacency.cs

Revision 421, 6.0 kB (checked in by phill, 1 year ago)

o Fixed bounds-related packed position track bug.

Line 
1 /******************************************************************************
2         x42view.net - .x42 viewer and auditing tool
3         Copyright (C) 2007 HermitWorks Entertainment Corporation
4
5         This program is free software; you can redistribute it and/or modify it
6         under the terms of the GNU General Public License as published by the Free
7         Software Foundation; either version 2 of the License, or (at your option)
8         any later version.
9
10         This program is distributed in the hope that it will be useful, but
11         WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12         or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13         for more details.
14
15         You should have received a copy of the GNU General Public License along
16         with this program; if not, write to the
17        
18                 Free Software Foundation, Inc.
19                 51 Franklin Street, Fifth Floor
20                 Boston, MA  02110-1301, USA.
21 ******************************************************************************/
22
23 using System;
24 using System.Collections.Generic;
25
26 namespace x42view
27 {
28         partial class Helpers
29         {
30                 public static ushort[] GetTriangleIndices( Libx42.Group g )
31                 {
32                         switch( g.PrimitiveType )
33                         {
34                         case Libx42.PrimitiveType.TriangleList:
35                                 return g.Indices.ToArray();
36
37                         case Libx42.PrimitiveType.TriangleStrip:
38                         case Libx42.PrimitiveType.TriangleFan:
39                                 break;
40
41                         default:
42                                 throw new InvalidOperationException();
43                         }
44
45                         int iRet = 0;
46                         ushort[] ret = new ushort[g.PrimitiveCount * 3];
47
48                         PrimitiveIterator iter = new PrimitiveIterator( g );
49                         while( iter.MoveNext() )
50                         {
51                                 ret[iRet++] = iter.Current( 0 );
52                                 ret[iRet++] = iter.Current( 1 );
53                                 ret[iRet++] = iter.Current( 2 );
54                         }
55
56                         return ret;
57                 }
58
59                 public sealed class Adjacency
60                 {
61                         public struct AdjEntry
62                         {
63                                 public int OtherTriangle;
64                                
65                                 public int ThisEdge;
66                                 public int OtherEdge;
67
68                                 public AdjEntry( int otherTri, int thisEdge, int otherEdge )
69                                 {
70                                         OtherTriangle = otherTri;
71                                         ThisEdge = thisEdge;
72                                         OtherEdge = otherEdge;
73                                 }
74                         }
75
76                         public struct TriEntry
77                         {
78                                 public int AdjIndex;
79                                 public int AdjLength;
80
81                                 public TriEntry( int adjIndex, int adjLength )
82                                 {
83                                         AdjIndex = adjIndex;
84                                         AdjLength = adjLength;
85                                 }
86                         }
87
88                         public struct Edge : IComparable<Edge>, IEquatable<Edge>
89                         {
90                                 public int Triangle;
91
92                                 public ushort First;
93                                 public ushort Second;
94
95                                 public Edge Reverse()
96                                 {
97                                         Edge ret;
98
99                                         ret.Triangle = Triangle;
100                                         ret.First = Second;
101                                         ret.Second = First;
102
103                                         return ret;
104                                 }
105
106                                 public int CompareTo( Edge other )
107                                 {
108                                         int dF = First - other.First;
109                                         if( dF != 0 )
110                                                 return dF;
111
112                                         int dS = Second - other.Second;
113                                         if( dS != 0 )
114                                                 return dS;
115
116                                         return Triangle - other.Triangle;
117                                 }
118
119                                 public bool Equals( Edge other )
120                                 {
121                                         return CompareTo( other ) == 0;
122                                 }
123                         }
124
125                         private sealed class EndPointComparer : IComparer<Edge>
126                         {
127                                 public int Compare( Edge x, Edge y )
128                                 {
129                                         int dF = x.First - y.First;
130                                         if( dF != 0 )
131                                                 return dF;
132
133                                         return x.Second - y.Second;
134                                 }
135                         }
136
137                         private List<TriEntry> entries = new List<TriEntry>();
138                         public List<TriEntry> Entries
139                         {
140                                 get { return entries; }
141                         }
142
143                         private List<AdjEntry> values = new List<AdjEntry>();
144                         public List<AdjEntry> Values
145                         {
146                                 get { return values; }
147                         }
148
149                         private List<Edge> edges = new List<Edge>();
150                         public List<Edge> Edges
151                         {
152                                 get { return edges; }
153                         }
154
155                         private List<int> borderEdges = new List<int>();
156                         public List<int> BorderEdges
157                         {
158                                 get { return borderEdges; }
159                         }
160
161                         public int NumTris
162                         {
163                                 get { return entries.Count; }
164                         }
165
166                         public Adjacency( ushort[] tris )
167                         {
168                                 int numTris = tris.Length / 3;
169
170                                 edges.Capacity = numTris * 3;
171
172                                 //for each triangle
173                                 for( int t = 0; t < numTris; t++ )
174                                 {
175                                         //skip degenerates
176                                         if( tris[t * 3 + 0] == tris[t * 3 + 1] ||
177                                                 tris[t * 3 + 1] == tris[t * 3 + 2] ||
178                                                 tris[t * 3 + 2] == tris[t * 3 + 0] )
179                                                 continue;
180
181                                         //for each edge
182                                         for( int e = 0; e < 3; e++ )
183                                         {
184                                                 ushort es = tris[t * 3 + e];
185                                                 ushort ee = tris[t * 3 + ((e + 1) % 3)];
186
187                                                 Edge edge = new Edge();
188                                                 edge.Triangle = t;
189                                                 edge.First = es;
190                                                 edge.Second = ee;
191
192                                                 //throw it into the list
193                                                 edges.Add( edge );
194                                         }
195                                 }
196
197                                 edges.Sort();
198
199                                 //build adjacency (ignore Triangle in future comparisons)
200                                 EndPointComparer comparer = new EndPointComparer();
201                                 List<List<AdjEntry>> tmpAdj = new List<List<AdjEntry>>( numTris );
202                                 for( int t = 0; t < numTris; t++ )
203                                         tmpAdj.Add( new List<AdjEntry>( 3 ) );
204
205                                 for( int i = 0; i < edges.Count; i++ )
206                                 {
207                                         Edge ei = edges[i];
208
209                                         //quick look-ahead for non-manifold type evil
210                                         for( int j = i + 1; j < edges.Count; j++ )
211                                         {
212                                                 Edge ej = edges[j];
213
214                                                 if( comparer.Compare( ei, ej ) != 0 )
215                                                         break;
216
217                                                 tmpAdj[ei.Triangle].Add( new AdjEntry( ej.Triangle, i, j ) ); //should this be in here at all?
218                                         }
219
220                                         Edge er = ei.Reverse();
221                                        
222                                         int idx = edges.BinarySearch( er, comparer );
223
224                                         //if there's more than one this might not point to the first, seek back
225                                         while( idx > 0 && comparer.Compare( edges[idx - 1], er ) == 0 )
226                                                 idx--;
227
228                                         if( idx < 0 )
229                                         {
230                                                 borderEdges.Add( i );
231                                                 continue;
232                                         }
233
234                                         //add all the edges that match er
235                                         for( int j = idx; j < edges.Count; j++ )
236                                         {
237                                                 Edge ej = edges[j];
238
239                                                 if( comparer.Compare( er, ej ) != 0 )
240                                                         break;
241
242                                                 tmpAdj[ei.Triangle].Add( new AdjEntry( ej.Triangle, i, j ) ); //should this be in here at all?
243                                         }
244                                 }
245                                
246                                 //pack tmpAdj down into a single array to save some space
247                                 values.Capacity = tris.Length;
248                                 entries.Capacity = numTris;
249
250                                 for( int t = 0; t < tmpAdj.Count; t++ )
251                                 {
252                                         entries.Add( new TriEntry( values.Count, tmpAdj[t].Count ) );
253                                         values.AddRange( tmpAdj[t] );
254                                 }
255                         }
256                 }
257         }
258 }
Note: See TracBrowser for help on using the browser.