Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IceIndexedTriangle.cpp
Go to the documentation of this file.
1 
8 
11 // Precompiled Header
12 #include "Stdafx.h"
13 
14 
15 using namespace Opcode;
16 
18 
26 
29 
34 {
35  Swap(mVRef[1], mVRef[2]);
36 }
37 
39 
44 float IndexedTriangle::Area(const Point* verts) const
46 {
47  if(!verts) return 0.0f;
48  const Point& p0 = verts[0];
49  const Point& p1 = verts[1];
50  const Point& p2 = verts[2];
51  return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f;
52 }
53 
55 
60 float IndexedTriangle::Perimeter(const Point* verts) const
62 {
63  if(!verts) return 0.0f;
64  const Point& p0 = verts[0];
65  const Point& p1 = verts[1];
66  const Point& p2 = verts[2];
67  return p0.Distance(p1)
68  + p0.Distance(p2)
69  + p1.Distance(p2);
70 }
71 
73 
78 float IndexedTriangle::Compacity(const Point* verts) const
80 {
81  if(!verts) return 0.0f;
82  float P = Perimeter(verts);
83  if(P==0.0f) return 0.0f;
84  return (4.0f*PI*Area(verts)/(P*P));
85 }
86 
88 
93 void IndexedTriangle::Normal(const Point* verts, Point& normal) const
95 {
96  if(!verts) return;
97 
98  const Point& p0 = verts[mVRef[0]];
99  const Point& p1 = verts[mVRef[1]];
100  const Point& p2 = verts[mVRef[2]];
101  normal = ((p2-p1)^(p0-p1)).Normalize();
102 }
103 
105 
110 void IndexedTriangle::DenormalizedNormal(const Point* verts, Point& normal) const
112 {
113  if(!verts) return;
114 
115  const Point& p0 = verts[mVRef[0]];
116  const Point& p1 = verts[mVRef[1]];
117  const Point& p2 = verts[mVRef[2]];
118  normal = ((p2-p1)^(p0-p1));
119 }
120 
122 
127 void IndexedTriangle::Center(const Point* verts, Point& center) const
129 {
130  if(!verts) return;
131 
132  const Point& p0 = verts[mVRef[0]];
133  const Point& p1 = verts[mVRef[1]];
134  const Point& p2 = verts[mVRef[2]];
135  center = (p0+p1+p2)*INV3;
136 }
137 
139 
144 void IndexedTriangle::CenteredNormal(const Point* verts, Point& normal) const
146 {
147  if(!verts) return;
148 
149  const Point& p0 = verts[mVRef[0]];
150  const Point& p1 = verts[mVRef[1]];
151  const Point& p2 = verts[mVRef[2]];
152  Point Center = (p0+p1+p2)*INV3;
153  normal = Center + ((p2-p1)^(p0-p1)).Normalize();
154 }
155 
157 
162 void IndexedTriangle::RandomPoint(const Point* verts, Point& random) const
164 {
165  if(!verts) return;
166 
167  // Random barycentric coords
168  float Alpha = UnitRandomFloat();
169  float Beta = UnitRandomFloat();
170  float Gamma = UnitRandomFloat();
171  float OneOverTotal = 1.0f / (Alpha + Beta + Gamma);
172  Alpha *= OneOverTotal;
173  Beta *= OneOverTotal;
174  Gamma *= OneOverTotal;
175 
176  const Point& p0 = verts[mVRef[0]];
177  const Point& p1 = verts[mVRef[1]];
178  const Point& p2 = verts[mVRef[2]];
179  random = Alpha*p0 + Beta*p1 + Gamma*p2;
180 }
181 
183 
189 bool IndexedTriangle::IsVisible(const Point* verts, const Point& source) const
191 {
192  // Checkings
193  if(!verts) return false;
194 
195  const Point& p0 = verts[mVRef[0]];
196  const Point& p1 = verts[mVRef[1]];
197  const Point& p2 = verts[mVRef[2]];
198 
199  // Compute denormalized normal
200  Point Normal = (p2 - p1)^(p0 - p1);
201 
202  // Backface culling
203  return (Normal | source) >= 0.0f;
204 
205 // Same as:
206 // Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
207 // return PL.Distance(source) > PL.d;
208 }
209 
211 
217 bool IndexedTriangle::BackfaceCulling(const Point* verts, const Point& source) const
219 {
220  // Checkings
221  if(!verts) return false;
222 
223  const Point& p0 = verts[mVRef[0]];
224  const Point& p1 = verts[mVRef[1]];
225  const Point& p2 = verts[mVRef[2]];
226 
227  // Compute base
228 // Point Base = (p0 + p1 + p2)*INV3;
229 
230  // Compute denormalized normal
231  Point Normal = (p2 - p1)^(p0 - p1);
232 
233  // Backface culling
234 // return (Normal | (source - Base)) >= 0.0f;
235  return (Normal | (source - p0)) >= 0.0f;
236 
237 // Same as: (but a bit faster)
238 // Plane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]);
239 // return PL.Distance(source)>0.0f;
240 }
241 
243 
249 float IndexedTriangle::ComputeOcclusionPotential(const Point* verts, const Point& view) const
251 {
252  if(!verts) return 0.0f;
253  // Occlusion potential: -(A * (N|V) / d^2)
254  // A = polygon area
255  // N = polygon normal
256  // V = view vector
257  // d = distance viewpoint-center of polygon
258 
259  float A = Area(verts);
260  Point N; Normal(verts, N);
261  Point C; Center(verts, C);
262  float d = view.Distance(C);
263  return -(A*(N|view))/(d*d);
264 }
265 
267 
273 bool IndexedTriangle::ReplaceVertex(udword oldref, udword newref)
275 {
276  if(mVRef[0]==oldref) { mVRef[0] = newref; return true; }
277  else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; }
278  else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; }
279  return false;
280 }
281 
283 
289 {
290  if(mVRef[0]==mVRef[1]) return true;
291  if(mVRef[1]==mVRef[2]) return true;
292  if(mVRef[2]==mVRef[0]) return true;
293  return false;
294 }
295 
297 
302 bool IndexedTriangle::HasVertex(udword ref) const
304 {
305  if(mVRef[0]==ref) return true;
306  if(mVRef[1]==ref) return true;
307  if(mVRef[2]==ref) return true;
308  return false;
309 }
310 
312 
320 {
321  if(mVRef[0]==ref) { *index = 0; return true; }
322  if(mVRef[1]==ref) { *index = 1; return true; }
323  if(mVRef[2]==ref) { *index = 2; return true; }
324  return false;
325 }
326 
328 
334 ubyte IndexedTriangle::FindEdge(udword vref0, udword vref1) const
336 {
337  if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0;
338  else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0;
339  else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1;
340  else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1;
341  else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2;
342  else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2;
343  return 0xff;
344 }
345 
347 
355 {
356  if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2];
357  else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2];
358  else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1];
359  else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1];
360  else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0];
361  else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0];
362  return INVALID_ID;
363 }
364 
366 
377 void IndexedTriangle::GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const
379 {
380  if(edgenb==0)
381  {
382  vref0 = mVRef[0];
383  vref1 = mVRef[1];
384  vref2 = mVRef[2];
385  }
386  else if(edgenb==1)
387  {
388  vref0 = mVRef[0];
389  vref1 = mVRef[2];
390  vref2 = mVRef[1];
391  }
392  else if(edgenb==2)
393  {
394  vref0 = mVRef[1];
395  vref1 = mVRef[2];
396  vref2 = mVRef[0];
397  }
398 }
399 
401 
406 float IndexedTriangle::MinEdgeLength(const Point* verts) const
408 {
409  if(!verts) return 0.0f;
410 
411  float Min = MAX_FLOAT;
412  float Length01 = verts[0].Distance(verts[1]);
413  float Length02 = verts[0].Distance(verts[2]);
414  float Length12 = verts[1].Distance(verts[2]);
415  if(Length01 < Min) Min = Length01;
416  if(Length02 < Min) Min = Length02;
417  if(Length12 < Min) Min = Length12;
418  return Min;
419 }
420 
422 
427 float IndexedTriangle::MaxEdgeLength(const Point* verts) const
429 {
430  if(!verts) return 0.0f;
431 
432  float Max = MIN_FLOAT;
433  float Length01 = verts[0].Distance(verts[1]);
434  float Length02 = verts[0].Distance(verts[2]);
435  float Length12 = verts[1].Distance(verts[2]);
436  if(Length01 > Max) Max = Length01;
437  if(Length02 > Max) Max = Length02;
438  if(Length12 > Max) Max = Length12;
439  return Max;
440 }
441 
443 
450 void IndexedTriangle::ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx) const
452 {
453  // Checkings
454  if(!verts) return;
455 
456  // Get face in local or global space
457  const Point& p0 = verts[mVRef[0]];
458  const Point& p1 = verts[mVRef[1]];
459  const Point& p2 = verts[mVRef[2]];
460 
461  // Compute point coordinates
462  pt = (1.0f - u - v)*p0 + u*p1 + v*p2;
463 
464  // Compute nearest vertex if needed
465  if(nearvtx)
466  {
467  // Compute distance vector
468  Point d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face
469  p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face
470  p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face
471 
472  // Get smallest distance
473  *nearvtx = mVRef[d.SmallestAxis()];
474  }
475 }
476 
477  //**************************************
478  // Angle between two vectors (in radians)
479  // we use this formula
480  // uv = |u||v| cos(u,v)
481  // u ^ v = w
482  // |w| = |u||v| |sin(u,v)|
483  //**************************************
484  float Angle(const Point& u, const Point& v)
485  {
486  float NormU = u.Magnitude(); // |u|
487  float NormV = v.Magnitude(); // |v|
488  float Product = NormU*NormV; // |u||v|
489  if(Product==0.0f) return 0.0f;
490  float OneOverProduct = 1.0f / Product;
491 
492  // Cosinus
493  float Cosinus = (u|v) * OneOverProduct;
494 
495  // Sinus
496  Point w = u^v;
497  float NormW = w.Magnitude();
498 
499  float AbsSinus = NormW * OneOverProduct;
500 
501  // Remove degeneracy
502  if(AbsSinus > 1.0f) AbsSinus = 1.0f;
503  if(AbsSinus < -1.0f) AbsSinus = -1.0f;
504 
505  if(Cosinus>=0.0f) return asinf(AbsSinus);
506  else return (PI-asinf(AbsSinus));
507  }
508 
510 
516 float IndexedTriangle::Angle(const IndexedTriangle& tri, const Point* verts) const
518 {
519  // Checkings
520  if(!verts) return 0.0f;
521 
522  // Compute face normals
523  Point n0, n1;
524  Normal(verts, n0);
525  tri.Normal(verts, n1);
526 
527  // Compute angle
528  float dp = n0|n1;
529  if(dp>1.0f) return 0.0f;
530  if(dp<-1.0f) return PI;
531  return acosf(dp);
532 
533 // return ::Angle(n0,n1);
534 }
535 
537 
542 bool IndexedTriangle::Equal(const IndexedTriangle& tri) const
544 {
545  // Test all vertex references
546  return (HasVertex(tri.mVRef[0]) &&
547  HasVertex(tri.mVRef[1]) &&
548  HasVertex(tri.mVRef[2]));
549 }
550