Go to the documentation of this file.00001
00002
00008
00009
00011
00012 #include "Stdafx.h"
00013
00014 using namespace IceMaths;
00015
00017
00025
00026
00028
00031
00032 void IndexedTriangle::Flip()
00033 {
00034 Swap(mVRef[1], mVRef[2]);
00035 }
00036
00038
00043
00044 float IndexedTriangle::Area(const Point* verts) const
00045 {
00046 if(!verts) return 0.0f;
00047 const Point& p0 = verts[0];
00048 const Point& p1 = verts[1];
00049 const Point& p2 = verts[2];
00050 return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f;
00051 }
00052
00054
00059
00060 float IndexedTriangle::Perimeter(const Point* verts) const
00061 {
00062 if(!verts) return 0.0f;
00063 const Point& p0 = verts[0];
00064 const Point& p1 = verts[1];
00065 const Point& p2 = verts[2];
00066 return p0.Distance(p1)
00067 + p0.Distance(p2)
00068 + p1.Distance(p2);
00069 }
00070
00072
00077
00078 float IndexedTriangle::Compacity(const Point* verts) const
00079 {
00080 if(!verts) return 0.0f;
00081 float P = Perimeter(verts);
00082 if(P==0.0f) return 0.0f;
00083 return (4.0f*PI*Area(verts)/(P*P));
00084 }
00085
00087
00092
00093 void IndexedTriangle::Normal(const Point* verts, Point& normal) const
00094 {
00095 if(!verts) return;
00096
00097 const Point& p0 = verts[mVRef[0]];
00098 const Point& p1 = verts[mVRef[1]];
00099 const Point& p2 = verts[mVRef[2]];
00100 normal = ((p2-p1)^(p0-p1)).Normalize();
00101 }
00102
00104
00109
00110 void IndexedTriangle::DenormalizedNormal(const Point* verts, Point& normal) const
00111 {
00112 if(!verts) return;
00113
00114 const Point& p0 = verts[mVRef[0]];
00115 const Point& p1 = verts[mVRef[1]];
00116 const Point& p2 = verts[mVRef[2]];
00117 normal = ((p2-p1)^(p0-p1));
00118 }
00119
00121
00126
00127 void IndexedTriangle::Center(const Point* verts, Point& center) const
00128 {
00129 if(!verts) return;
00130
00131 const Point& p0 = verts[mVRef[0]];
00132 const Point& p1 = verts[mVRef[1]];
00133 const Point& p2 = verts[mVRef[2]];
00134 center = (p0+p1+p2)*INV3;
00135 }
00136
00138
00143
00144 void IndexedTriangle::CenteredNormal(const Point* verts, Point& normal) const
00145 {
00146 if(!verts) return;
00147
00148 const Point& p0 = verts[mVRef[0]];
00149 const Point& p1 = verts[mVRef[1]];
00150 const Point& p2 = verts[mVRef[2]];
00151 Point Center = (p0+p1+p2)*INV3;
00152 normal = Center + ((p2-p1)^(p0-p1)).Normalize();
00153 }
00154
00156
00161
00162 void IndexedTriangle::RandomPoint(const Point* verts, Point& random) const
00163 {
00164 if(!verts) return;
00165
00166
00167 float Alpha = UnitRandomFloat();
00168 float Beta = UnitRandomFloat();
00169 float Gamma = UnitRandomFloat();
00170 float OneOverTotal = 1.0f / (Alpha + Beta + Gamma);
00171 Alpha *= OneOverTotal;
00172 Beta *= OneOverTotal;
00173 Gamma *= OneOverTotal;
00174
00175 const Point& p0 = verts[mVRef[0]];
00176 const Point& p1 = verts[mVRef[1]];
00177 const Point& p2 = verts[mVRef[2]];
00178 random = Alpha*p0 + Beta*p1 + Gamma*p2;
00179 }
00180
00182
00188
00189 bool IndexedTriangle::IsVisible(const Point* verts, const Point& source) const
00190 {
00191
00192 if(!verts) return false;
00193
00194 const Point& p0 = verts[mVRef[0]];
00195 const Point& p1 = verts[mVRef[1]];
00196 const Point& p2 = verts[mVRef[2]];
00197
00198
00199 Point Normal = (p2 - p1)^(p0 - p1);
00200
00201
00202 return (Normal | source) >= 0.0f;
00203
00204
00205
00206
00207 }
00208
00210
00216
00217 bool IndexedTriangle::BackfaceCulling(const Point* verts, const Point& source) const
00218 {
00219
00220 if(!verts) return false;
00221
00222 const Point& p0 = verts[mVRef[0]];
00223 const Point& p1 = verts[mVRef[1]];
00224 const Point& p2 = verts[mVRef[2]];
00225
00226
00227
00228
00229
00230 Point Normal = (p2 - p1)^(p0 - p1);
00231
00232
00233
00234 return (Normal | (source - p0)) >= 0.0f;
00235
00236
00237
00238
00239 }
00240
00242
00248
00249 float IndexedTriangle::ComputeOcclusionPotential(const Point* verts, const Point& view) const
00250 {
00251 if(!verts) return 0.0f;
00252
00253
00254
00255
00256
00257
00258 float A = Area(verts);
00259 Point N; Normal(verts, N);
00260 Point C; Center(verts, C);
00261 float d = view.Distance(C);
00262 return -(A*(N|view))/(d*d);
00263 }
00264
00266
00272
00273 bool IndexedTriangle::ReplaceVertex(udword oldref, udword newref)
00274 {
00275 if(mVRef[0]==oldref) { mVRef[0] = newref; return true; }
00276 else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; }
00277 else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; }
00278 return false;
00279 }
00280
00282
00286
00287 bool IndexedTriangle::IsDegenerate() const
00288 {
00289 if(mVRef[0]==mVRef[1]) return true;
00290 if(mVRef[1]==mVRef[2]) return true;
00291 if(mVRef[2]==mVRef[0]) return true;
00292 return false;
00293 }
00294
00296
00301
00302 bool IndexedTriangle::HasVertex(udword ref) const
00303 {
00304 if(mVRef[0]==ref) return true;
00305 if(mVRef[1]==ref) return true;
00306 if(mVRef[2]==ref) return true;
00307 return false;
00308 }
00309
00311
00317
00318 bool IndexedTriangle::HasVertex(udword ref, udword* index) const
00319 {
00320 if(mVRef[0]==ref) { *index = 0; return true; }
00321 if(mVRef[1]==ref) { *index = 1; return true; }
00322 if(mVRef[2]==ref) { *index = 2; return true; }
00323 return false;
00324 }
00325
00327
00333
00334 ubyte IndexedTriangle::FindEdge(udword vref0, udword vref1) const
00335 {
00336 if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0;
00337 else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0;
00338 else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1;
00339 else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1;
00340 else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2;
00341 else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2;
00342 return 0xff;
00343 }
00344
00346
00352
00353 udword IndexedTriangle::OppositeVertex(udword vref0, udword vref1) const
00354 {
00355 if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2];
00356 else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2];
00357 else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1];
00358 else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1];
00359 else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0];
00360 else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0];
00361 return INVALID_ID;
00362 }
00363
00365
00376
00377 void IndexedTriangle::GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const
00378 {
00379 if(edgenb==0)
00380 {
00381 vref0 = mVRef[0];
00382 vref1 = mVRef[1];
00383 vref2 = mVRef[2];
00384 }
00385 else if(edgenb==1)
00386 {
00387 vref0 = mVRef[0];
00388 vref1 = mVRef[2];
00389 vref2 = mVRef[1];
00390 }
00391 else if(edgenb==2)
00392 {
00393 vref0 = mVRef[1];
00394 vref1 = mVRef[2];
00395 vref2 = mVRef[0];
00396 }
00397 }
00398
00400
00405
00406 float IndexedTriangle::MinEdgeLength(const Point* verts) const
00407 {
00408 if(!verts) return 0.0f;
00409
00410 float Min = MAX_FLOAT;
00411 float Length01 = verts[0].Distance(verts[1]);
00412 float Length02 = verts[0].Distance(verts[2]);
00413 float Length12 = verts[1].Distance(verts[2]);
00414 if(Length01 < Min) Min = Length01;
00415 if(Length02 < Min) Min = Length02;
00416 if(Length12 < Min) Min = Length12;
00417 return Min;
00418 }
00419
00421
00426
00427 float IndexedTriangle::MaxEdgeLength(const Point* verts) const
00428 {
00429 if(!verts) return 0.0f;
00430
00431 float Max = MIN_FLOAT;
00432 float Length01 = verts[0].Distance(verts[1]);
00433 float Length02 = verts[0].Distance(verts[2]);
00434 float Length12 = verts[1].Distance(verts[2]);
00435 if(Length01 > Max) Max = Length01;
00436 if(Length02 > Max) Max = Length02;
00437 if(Length12 > Max) Max = Length12;
00438 return Max;
00439 }
00440
00442
00449
00450 void IndexedTriangle::ComputePoint(const Point* verts, float u, float v, Point& pt, udword* nearvtx) const
00451 {
00452
00453 if(!verts) return;
00454
00455
00456 const Point& p0 = verts[mVRef[0]];
00457 const Point& p1 = verts[mVRef[1]];
00458 const Point& p2 = verts[mVRef[2]];
00459
00460
00461 pt = (1.0f - u - v)*p0 + u*p1 + v*p2;
00462
00463
00464 if(nearvtx)
00465 {
00466
00467 Point d(p0.SquareDistance(pt),
00468 p1.SquareDistance(pt),
00469 p2.SquareDistance(pt));
00470
00471
00472 *nearvtx = mVRef[d.SmallestAxis()];
00473 }
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483 float Angle(const Point& u, const Point& v)
00484 {
00485 float NormU = u.Magnitude();
00486 float NormV = v.Magnitude();
00487 float Product = NormU*NormV;
00488 if(Product==0.0f) return 0.0f;
00489 float OneOverProduct = 1.0f / Product;
00490
00491
00492 float Cosinus = (u|v) * OneOverProduct;
00493
00494
00495 Point w = u^v;
00496 float NormW = w.Magnitude();
00497
00498 float AbsSinus = NormW * OneOverProduct;
00499
00500
00501 if(AbsSinus > 1.0f) AbsSinus = 1.0f;
00502 if(AbsSinus < -1.0f) AbsSinus = -1.0f;
00503
00504 if(Cosinus>=0.0f) return asinf(AbsSinus);
00505 else return (PI-asinf(AbsSinus));
00506 }
00507
00509
00515
00516 float IndexedTriangle::Angle(const IndexedTriangle& tri, const Point* verts) const
00517 {
00518
00519 if(!verts) return 0.0f;
00520
00521
00522 Point n0, n1;
00523 Normal(verts, n0);
00524 tri.Normal(verts, n1);
00525
00526
00527 float dp = n0|n1;
00528 if(dp>1.0f) return 0.0f;
00529 if(dp<-1.0f) return PI;
00530 return acosf(dp);
00531
00532
00533 }
00534
00536
00541
00542 bool IndexedTriangle::Equal(const IndexedTriangle& tri) const
00543 {
00544
00545 return (HasVertex(tri.mVRef[0]) &&
00546 HasVertex(tri.mVRef[1]) &&
00547 HasVertex(tri.mVRef[2]));
00548 }