1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 /**
3 * Contains a handy indexed triangle class.
4 * \file IceIndexedTriangle.cpp
5 * \author Pierre Terdiman
6 * \date January, 17, 2000
7 */
8 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11 // Precompiled Header
12 #include "Stdafx.h"
13
14 using namespace IceMaths;
15
16 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17 /**
18 * Contains an indexed triangle class.
19 *
20 * \class Triangle
21 * \author Pierre Terdiman
22 * \version 1.0
23 * \date 08.15.98
24 */
25 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26
27 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28 /**
29 * Flips the winding order.
30 */
31 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Flip()32 void IndexedTriangle::Flip()
33 {
34 Swap(mVRef[1], mVRef[2]);
35 }
36
37 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
38 /**
39 * Computes the triangle area.
40 * \param verts [in] the list of indexed vertices
41 * \return the area
42 */
43 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Area(const Point * verts) const44 float IndexedTriangle::Area(const Point* verts) const
45 {
46 if(!verts) return 0.0f;
47 const Point& p0 = verts[0];
48 const Point& p1 = verts[1];
49 const Point& p2 = verts[2];
50 return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f;
51 }
52
53 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54 /**
55 * Computes the triangle perimeter.
56 * \param verts [in] the list of indexed vertices
57 * \return the perimeter
58 */
59 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Perimeter(const Point * verts) const60 float IndexedTriangle::Perimeter(const Point* verts) const
61 {
62 if(!verts) return 0.0f;
63 const Point& p0 = verts[0];
64 const Point& p1 = verts[1];
65 const Point& p2 = verts[2];
66 return p0.Distance(p1)
67 + p0.Distance(p2)
68 + p1.Distance(p2);
69 }
70
71 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
72 /**
73 * Computes the triangle compacity.
74 * \param verts [in] the list of indexed vertices
75 * \return the compacity
76 */
77 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Compacity(const Point * verts) const78 float IndexedTriangle::Compacity(const Point* verts) const
79 {
80 if(!verts) return 0.0f;
81 float P = Perimeter(verts);
82 if(P==0.0f) return 0.0f;
83 return (4.0f*PI*Area(verts)/(P*P));
84 }
85
86 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87 /**
88 * Computes the triangle normal.
89 * \param verts [in] the list of indexed vertices
90 * \param normal [out] the computed normal
91 */
92 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Normal(const Point * verts,Point & normal) const93 void IndexedTriangle::Normal(const Point* verts, Point& normal) const
94 {
95 if(!verts) return;
96
97 const Point& p0 = verts[mVRef[0]];
98 const Point& p1 = verts[mVRef[1]];
99 const Point& p2 = verts[mVRef[2]];
100 normal = ((p2-p1)^(p0-p1)).Normalize();
101 }
102
103 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104 /**
105 * Computes the triangle denormalized normal.
106 * \param verts [in] the list of indexed vertices
107 * \param normal [out] the computed normal
108 */
109 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DenormalizedNormal(const Point * verts,Point & normal) const110 void IndexedTriangle::DenormalizedNormal(const Point* verts, Point& normal) const
111 {
112 if(!verts) return;
113
114 const Point& p0 = verts[mVRef[0]];
115 const Point& p1 = verts[mVRef[1]];
116 const Point& p2 = verts[mVRef[2]];
117 normal = ((p2-p1)^(p0-p1));
118 }
119
120 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
121 /**
122 * Computes the triangle center.
123 * \param verts [in] the list of indexed vertices
124 * \param center [out] the computed center
125 */
126 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Center(const Point * verts,Point & center) const127 void IndexedTriangle::Center(const Point* verts, Point& center) const
128 {
129 if(!verts) return;
130
131 const Point& p0 = verts[mVRef[0]];
132 const Point& p1 = verts[mVRef[1]];
133 const Point& p2 = verts[mVRef[2]];
134 center = (p0+p1+p2)*INV3;
135 }
136
137 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
138 /**
139 * Computes the centered normal
140 * \param verts [in] the list of indexed vertices
141 * \param normal [out] the computed centered normal
142 */
143 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CenteredNormal(const Point * verts,Point & normal) const144 void IndexedTriangle::CenteredNormal(const Point* verts, Point& normal) const
145 {
146 if(!verts) return;
147
148 const Point& p0 = verts[mVRef[0]];
149 const Point& p1 = verts[mVRef[1]];
150 const Point& p2 = verts[mVRef[2]];
151 Point Center = (p0+p1+p2)*INV3;
152 normal = Center + ((p2-p1)^(p0-p1)).Normalize();
153 }
154
155 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156 /**
157 * Computes a random point within the triangle.
158 * \param verts [in] the list of indexed vertices
159 * \param normal [out] the computed centered normal
160 */
161 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RandomPoint(const Point * verts,Point & random) const162 void IndexedTriangle::RandomPoint(const Point* verts, Point& random) const
163 {
164 if(!verts) return;
165
166 // Random barycentric coords
167 float Alpha = UnitRandomFloat();
168 float Beta = UnitRandomFloat();
169 float Gamma = UnitRandomFloat();
170 float OneOverTotal = 1.0f / (Alpha + Beta + Gamma);
171 Alpha *= OneOverTotal;
172 Beta *= OneOverTotal;
173 Gamma *= OneOverTotal;
174
175 const Point& p0 = verts[mVRef[0]];
176 const Point& p1 = verts[mVRef[1]];
177 const Point& p2 = verts[mVRef[2]];
178 random = Alpha*p0 + Beta*p1 + Gamma*p2;
179 }
180
181 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182 /**
183 * Computes backface culling.
184 * \param verts [in] the list of indexed vertices
185 * \param source [in] source point (in local space) from which culling must be computed
186 * \return true if the triangle is visible from the source point
187 */
188 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IsVisible(const Point * verts,const Point & source) const189 bool IndexedTriangle::IsVisible(const Point* verts, const Point& source) const
190 {
191 // Checkings
192 if(!verts) return false;
193
194 const Point& p0 = verts[mVRef[0]];
195 const Point& p1 = verts[mVRef[1]];
196 const Point& p2 = verts[mVRef[2]];
197
198 // Compute denormalized normal
199 Point Normal = (p2 - p1)^(p0 - p1);
200
201 // Backface culling
202 return (Normal | source) >= 0.0f;
203
204 // Same as:
205 // Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
206 // return PL.Distance(source) > PL.d;
207 }
208
209 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
210 /**
211 * Computes backface culling.
212 * \param verts [in] the list of indexed vertices
213 * \param source [in] source point (in local space) from which culling must be computed
214 * \return true if the triangle is visible from the source point
215 */
216 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BackfaceCulling(const Point * verts,const Point & source) const217 bool IndexedTriangle::BackfaceCulling(const Point* verts, const Point& source) const
218 {
219 // Checkings
220 if(!verts) return false;
221
222 const Point& p0 = verts[mVRef[0]];
223 const Point& p1 = verts[mVRef[1]];
224 const Point& p2 = verts[mVRef[2]];
225
226 // Compute base
227 // Point Base = (p0 + p1 + p2)*INV3;
228
229 // Compute denormalized normal
230 Point Normal = (p2 - p1)^(p0 - p1);
231
232 // Backface culling
233 // return (Normal | (source - Base)) >= 0.0f;
234 return (Normal | (source - p0)) >= 0.0f;
235
236 // Same as: (but a bit faster)
237 // Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
238 // return PL.Distance(source)>0.0f;
239 }
240
241 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
242 /**
243 * Computes the occlusion potential of the triangle.
244 * \param verts [in] the list of indexed vertices
245 * \param source [in] source point (in local space) from which occlusion potential must be computed
246 * \return the occlusion potential
247 */
248 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ComputeOcclusionPotential(const Point * verts,const Point & view) const249 float IndexedTriangle::ComputeOcclusionPotential(const Point* verts, const Point& view) const
250 {
251 if(!verts) return 0.0f;
252 // Occlusion potential: -(A * (N|V) / d^2)
253 // A = polygon area
254 // N = polygon normal
255 // V = view vector
256 // d = distance viewpoint-center of polygon
257
258 float A = Area(verts);
259 Point N; Normal(verts, N);
260 Point C; Center(verts, C);
261 float d = view.Distance(C);
262 return -(A*(N|view))/(d*d);
263 }
264
265 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
266 /**
267 * Replaces a vertex reference with another one.
268 * \param oldref [in] the vertex reference to replace
269 * \param newref [in] the new vertex reference
270 * \return true if success, else false if the input vertex reference doesn't belong to the triangle
271 */
272 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ReplaceVertex(dTriIndex oldref,dTriIndex newref)273 bool IndexedTriangle::ReplaceVertex(dTriIndex oldref, dTriIndex newref)
274 {
275 if(mVRef[0]==oldref) { mVRef[0] = newref; return true; }
276 else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; }
277 else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; }
278 return false;
279 }
280
281 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282 /**
283 * Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle.
284 * \return true if the triangle is degenerate
285 */
286 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IsDegenerate() const287 bool IndexedTriangle::IsDegenerate() const
288 {
289 if(mVRef[0]==mVRef[1]) return true;
290 if(mVRef[1]==mVRef[2]) return true;
291 if(mVRef[2]==mVRef[0]) return true;
292 return false;
293 }
294
295 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
296 /**
297 * Checks whether the input vertex reference belongs to the triangle or not.
298 * \param ref [in] the vertex reference to look for
299 * \return true if the triangle contains the vertex reference
300 */
301 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HasVertex(dTriIndex ref) const302 bool IndexedTriangle::HasVertex(dTriIndex ref) const
303 {
304 if(mVRef[0]==ref) return true;
305 if(mVRef[1]==ref) return true;
306 if(mVRef[2]==ref) return true;
307 return false;
308 }
309
310 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
311 /**
312 * Checks whether the input vertex reference belongs to the triangle or not.
313 * \param ref [in] the vertex reference to look for
314 * \param index [out] the corresponding index in the triangle
315 * \return true if the triangle contains the vertex reference
316 */
317 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HasVertex(dTriIndex ref,dTriIndex * index) const318 bool IndexedTriangle::HasVertex(dTriIndex ref, dTriIndex* index) const
319 {
320 if(mVRef[0]==ref) { *index = 0; return true; }
321 if(mVRef[1]==ref) { *index = 1; return true; }
322 if(mVRef[2]==ref) { *index = 2; return true; }
323 return false;
324 }
325
326 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
327 /**
328 * Finds an edge in a tri, given two vertex references.
329 * \param vref0 [in] the edge's first vertex reference
330 * \param vref1 [in] the edge's second vertex reference
331 * \return the edge number between 0 and 2, or 0xff if input refs are wrong.
332 */
333 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FindEdge(dTriIndex vref0,dTriIndex vref1) const334 ubyte IndexedTriangle::FindEdge(dTriIndex vref0, dTriIndex vref1) const
335 {
336 if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0;
337 else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0;
338 else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1;
339 else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1;
340 else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2;
341 else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2;
342 return 0xff;
343 }
344
345 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
346 /**
347 * Gets the last reference given the first two.
348 * \param vref0 [in] the first vertex reference
349 * \param vref1 [in] the second vertex reference
350 * \return the last reference, or INVALID_ID if input refs are wrong.
351 */
352 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
OppositeVertex(dTriIndex vref0,dTriIndex vref1) const353 dTriIndex IndexedTriangle::OppositeVertex(dTriIndex vref0, dTriIndex vref1) const
354 {
355 if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2];
356 else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2];
357 else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1];
358 else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1];
359 else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0];
360 else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0];
361 return (dTriIndex)INVALID_ID;
362 }
363
364 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
365 /**
366 * Gets the three sorted vertex references according to an edge number.
367 * edgenb = 0 => edge 0-1, returns references 0, 1, 2
368 * edgenb = 1 => edge 0-2, returns references 0, 2, 1
369 * edgenb = 2 => edge 1-2, returns references 1, 2, 0
370 *
371 * \param edgenb [in] the edge number, 0, 1 or 2
372 * \param vref0 [out] the returned first vertex reference
373 * \param vref1 [out] the returned second vertex reference
374 * \param vref2 [out] the returned third vertex reference
375 */
376 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
GetVRefs(ubyte edgenb,dTriIndex & vref0,dTriIndex & vref1,dTriIndex & vref2) const377 void IndexedTriangle::GetVRefs(ubyte edgenb, dTriIndex& vref0, dTriIndex& vref1, dTriIndex& vref2) const
378 {
379 if(edgenb==0)
380 {
381 vref0 = mVRef[0];
382 vref1 = mVRef[1];
383 vref2 = mVRef[2];
384 }
385 else if(edgenb==1)
386 {
387 vref0 = mVRef[0];
388 vref1 = mVRef[2];
389 vref2 = mVRef[1];
390 }
391 else if(edgenb==2)
392 {
393 vref0 = mVRef[1];
394 vref1 = mVRef[2];
395 vref2 = mVRef[0];
396 }
397 }
398
399 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
400 /**
401 * Computes the triangle's smallest edge length.
402 * \param verts [in] the list of indexed vertices
403 * \return the smallest edge length
404 */
405 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MinEdgeLength(const Point * verts) const406 float IndexedTriangle::MinEdgeLength(const Point* verts) const
407 {
408 if(!verts) return 0.0f;
409
410 float Min = MAX_FLOAT;
411 float Length01 = verts[0].Distance(verts[1]);
412 float Length02 = verts[0].Distance(verts[2]);
413 float Length12 = verts[1].Distance(verts[2]);
414 if(Length01 < Min) Min = Length01;
415 if(Length02 < Min) Min = Length02;
416 if(Length12 < Min) Min = Length12;
417 return Min;
418 }
419
420 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
421 /**
422 * Computes the triangle's largest edge length.
423 * \param verts [in] the list of indexed vertices
424 * \return the largest edge length
425 */
426 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MaxEdgeLength(const Point * verts) const427 float IndexedTriangle::MaxEdgeLength(const Point* verts) const
428 {
429 if(!verts) return 0.0f;
430
431 float Max = MIN_FLOAT;
432 float Length01 = verts[0].Distance(verts[1]);
433 float Length02 = verts[0].Distance(verts[2]);
434 float Length12 = verts[1].Distance(verts[2]);
435 if(Length01 > Max) Max = Length01;
436 if(Length02 > Max) Max = Length02;
437 if(Length12 > Max) Max = Length12;
438 return Max;
439 }
440
441 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
442 /**
443 * Computes a point on the triangle according to the stabbing information.
444 * \param verts [in] the list of indexed vertices
445 * \param u,v [in] point's barycentric coordinates
446 * \param pt [out] point on triangle
447 * \param nearvtx [out] index of nearest vertex
448 */
449 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ComputePoint(const Point * verts,float u,float v,Point & pt,dTriIndex * nearvtx) const450 void IndexedTriangle::ComputePoint(const Point* verts, float u, float v, Point& pt, dTriIndex* nearvtx) const
451 {
452 // Checkings
453 if(!verts) return;
454
455 // Get face in local or global space
456 const Point& p0 = verts[mVRef[0]];
457 const Point& p1 = verts[mVRef[1]];
458 const Point& p2 = verts[mVRef[2]];
459
460 // Compute point coordinates
461 pt = (1.0f - u - v)*p0 + u*p1 + v*p2;
462
463 // Compute nearest vertex if needed
464 if(nearvtx)
465 {
466 // Compute distance vector
467 Point d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
468 p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
469 p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
470
471 // Get smallest distance
472 *nearvtx = mVRef[d.SmallestAxis()];
473 }
474 }
475
476 //**************************************
477 // Angle between two vectors (in radians)
478 // we use this formula
479 // uv = |u||v| cos(u,v)
480 // u ^ v = w
481 // |w| = |u||v| |sin(u,v)|
482 //**************************************
Angle(const Point & u,const Point & v)483 float Angle(const Point& u, const Point& v)
484 {
485 float NormU = u.Magnitude(); // |u|
486 float NormV = v.Magnitude(); // |v|
487 float Product = NormU*NormV; // |u||v|
488 if(Product==0.0f) return 0.0f;
489 float OneOverProduct = 1.0f / Product;
490
491 // Cosinus
492 float Cosinus = (u|v) * OneOverProduct;
493
494 // Sinus
495 Point w = u^v;
496 float NormW = w.Magnitude();
497
498 float AbsSinus = NormW * OneOverProduct;
499
500 // Remove degeneracy
501 if(AbsSinus > 1.0f) AbsSinus = 1.0f;
502 if(AbsSinus < -1.0f) AbsSinus = -1.0f;
503
504 if(Cosinus>=0.0f) return asinf(AbsSinus);
505 else return (PI-asinf(AbsSinus));
506 }
507
508 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
509 /**
510 * Computes the angle between two triangles.
511 * \param tri [in] the other triangle
512 * \param verts [in] the list of indexed vertices
513 * \return the angle in radians
514 */
515 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Angle(const IndexedTriangle & tri,const Point * verts) const516 float IndexedTriangle::Angle(const IndexedTriangle& tri, const Point* verts) const
517 {
518 // Checkings
519 if(!verts) return 0.0f;
520
521 // Compute face normals
522 Point n0, n1;
523 Normal(verts, n0);
524 tri.Normal(verts, n1);
525
526 // Compute angle
527 float dp = n0|n1;
528 if(dp>1.0f) return 0.0f;
529 if(dp<-1.0f) return PI;
530 return acosf(dp);
531
532 // return ::Angle(n0,n1);
533 }
534
535 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
536 /**
537 * Checks a triangle is the same as another one.
538 * \param tri [in] the other triangle
539 * \return true if same triangle
540 */
541 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Equal(const IndexedTriangle & tri) const542 bool IndexedTriangle::Equal(const IndexedTriangle& tri) const
543 {
544 // Test all vertex references
545 return (HasVertex(tri.mVRef[0]) &&
546 HasVertex(tri.mVRef[1]) &&
547 HasVertex(tri.mVRef[2]));
548 }
549