1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "[Math/MathFunc.h]"19 #include "[Math/float2.h]"20 #include "[Math/float3.h]"21 #include "[Math/float3x3.h]"22 #include "[Math/float3x4.h]"23 #include "[Math/float4x4.h]"24 #include "[Math/Quat.h]"25 #include "[Geometry/Capsule.h]"26 #include "[Geometry/Frustum.h]"27 #include "[Geometry/Triangle.h]"28 #include "[Geometry/Plane.h]"29 #include "[Geometry/Polygon.h]"30 #include "[Geometry/Polyhedron.h]"31 #include "[Geometry/Line.h]"32 #include "[Geometry/LineSegment.h]"33 #include "[Geometry/Ray.h]"34 #include "[Geometry/Sphere.h]"35 #include "[Geometry/AABB.h]"36 #include "[Geometry/OBB.h]"37 #include "[Algorithm/Random/LCG.h]"38 39 [MATH_BEGIN_NAMESPACE]40 41 [Triangle::Triangle](const [float3] &a_, const [float3] &b_, const [float3] &c_)42 :a(a_), b(b_), c(c_)43 {44 }45 46 [float3] [Triangle::BarycentricUVW](const [float3] &point) const47 {48 49 50 [float3] v0 = [b] - [a];51 [float3] v1 = [c] - [a];52 [float3] v2 = point - [a];53 float d00 = [Dot](v0, v0);54 float d01 = [Dot](v0, v1);55 float d11 = [Dot](v1, v1);56 float d20 = [Dot](v2, v0);57 float d21 = [Dot](v2, v1);58 float denom = 1.f / (d00 * d11 - d01 * d01);59 float v = (d11 * d20 - d01 * d21) * denom;60 float w = (d00 * d21 - d01 * d20) * denom;61 float u = 1.0f - v - w;62 return [float3](u, v, w);63 }64 65 [float2] [Triangle::BarycentricUV](const [float3] &point) const66 {67 [float3] uvw = [BarycentricUVW](point);68 return [float2](uvw.[y], uvw.[z]);69 }70 71 bool [Triangle::BarycentricInsideTriangle](const [float3] &barycentric)72 {73 return barycentric.[x] >= 0.f && barycentric.[y] >= 0.f && barycentric.[z] >= 0.f &&74 [EqualAbs](barycentric.[x] + barycentric.[y] + barycentric.[z], 1.f);75 }76 77 [float3] [Triangle::Point](float u, float v, float w) const78 {79 return u * [a] + v * [b] + w * [c];80 }81 82 [float3] [Triangle::Point](const [float3] &b) const83 {84 return [Point](b.[x], b.[y], b.[z]);85 }86 87 [float3] [Triangle::Point](const [float2] &b) const88 {89 return [Point](b.[x], b.[y]);90 }91 92 [float3] [Triangle::Centroid]() const93 {94 return ([a] + [b] + [c]) / 3.f;95 }96 97 float [Triangle::Area]() const98 {99 return 0.5f * [Cross]([b]-[a], [c]-[a]).[Length]();100 }101 102 float [Triangle::Perimeter]() const103 {104 return [a].[Distance]([b]) + [b].[Distance]([c]) + [c].[Distance]([a]);105 }106 107 [LineSegment] [Triangle::Edge](int i) const108 {109 [assume](0 <= i);110 [assume](i <= 2);111 if (i == 0)112 return [LineSegment]([a], [b]);113 else if (i == 1)114 return [LineSegment]([b], [c]);115 else if (i == 2)116 return [LineSegment]([c], [a]);117 else118 return [LineSegment]([float3::nan], [float3::nan]);119 }120 121 [float3] [Triangle::Vertex](int i) const122 {123 [assume](0 <= i);124 [assume](i <= 2);125 if (i == 0)126 return [a];127 else if (i == 1)128 return [b];129 else if (i == 2)130 return [c];131 else132 return [float3::nan];133 }134 135 [Plane] [Triangle::PlaneCCW]() const136 {137 return [Plane]([a], [b], [c]);138 }139 140 [Plane] [Triangle::PlaneCW]() const141 {142 return [Plane]([a], [c], [b]);143 }144 145 [float3] [Triangle::NormalCCW]() const146 {147 return [UnnormalizedNormalCCW]().[Normalized]();148 }149 150 [float3] [Triangle::NormalCW]() const151 {152 return [UnnormalizedNormalCW]().[Normalized]();153 }154 155 [float3] [Triangle::UnnormalizedNormalCCW]() const156 {157 return [Cross]([b]-[a], [c]-[a]);158 }159 160 [float3] [Triangle::UnnormalizedNormalCW]() const161 {162 return [Cross]([c]-[a], [b]-[a]);163 }164 165 [Polygon] [Triangle::ToPolygon]() const166 {167 [Polygon] p;168 p.[p].push_back([a]);169 p.[p].push_back([b]);170 p.[p].push_back([c]);171 return p;172 }173 174 [Polyhedron] [Triangle::ToPolyhedron]() const175 {176 return [ToPolygon]().[ToPolyhedron]();177 }178 179 float [Triangle::Area2D](const [float2] &p1, const [float2] &p2, const [float2] &p3)180 {181 return (p1.[x] - p2.[x]) * (p2.[y] - p3.[y]) - (p2.[x] - p3.[x]) * (p1.[y] - p2.[y]);182 }183 184 float [Triangle::SignedArea](const [float3] &pt, const [float3] &a, const [float3] &b, const [float3] &c)185 {186 return [Dot]([Cross](b-pt, c-pt), [Cross](b-a, c-a).Normalized());187 }188 189 bool [Triangle::IsFinite]() const190 {191 return a.[IsFinite]() && b.[IsFinite]() && c.[IsFinite]();192 }193 194 bool [Triangle::IsDegenerate](float epsilon) const195 {196 return [IsDegenerate](a, b, c);197 }198 199 bool [Triangle::IsDegenerate](const [float3] &a, const [float3] &b, const [float3] &c, float epsilon)200 {201 return a.[Equals](b, epsilon) || a.[Equals](c, epsilon) || b.[Equals](c, epsilon);202 }203 204 bool [Triangle::Contains](const [float3] &point, float triangleThickness) const205 {206 if ([PlaneCCW]().[Distance](point) > triangleThickness) 207 return false; 208 209 [float3] br = [BarycentricUVW](point);210 return br.[y] >= 0.f && br.[z] >= 0.f && (br.[y] + br.[z]) <= 1.f;211 }212 213 bool [Triangle::Contains](const [LineSegment] &lineSegment, float triangleThickness) const214 {215 return [Contains](lineSegment.[a], triangleThickness) && [Contains](lineSegment.[b], triangleThickness);216 }217 218 bool [Triangle::Contains](const [Triangle] &triangle, float triangleThickness) const219 {220 return [Contains](triangle.[a], triangleThickness) && [Contains](triangle.[b], triangleThickness)221 && [Contains](triangle.[c], triangleThickness);222 }223 224 225 226 227 228 229 230 231 232 233 234 235 float [Triangle::Distance](const [float3] &point) const236 {237 return [ClosestPoint](point).[Distance](point);238 }239 240 float [Triangle::Distance](const [Sphere] &sphere) const241 {242 return [Max](0.f, [Distance](sphere.[pos]) - sphere.[r]);243 }244 245 246 247 248 249 250 251 252 253 254 255 256 257 bool [Triangle::IntersectLineTri](const [float3] &linePos, const [float3] &lineDir,258 const [float3] &v0, const [float3] &v1, const [float3] &v2,259 float &u, float &v, float &t)260 {261 [float3] vE1, vE2;262 [float3] vT, vP, vQ;263 264 const float epsilon = 1[e]-6f;265 266 267 vE1 = v1 - v0;268 vE2 = v2 - v0;269 270 271 vP = [Cross](lineDir, vE2);272 273 274 const float det = [Dot](vE1, vP);275 276 277 if (fabs(det) <= epsilon)278 return false;279 const float recipDet = 1.f / det;280 281 282 vT = linePos - v0;283 284 285 u = [Dot](vT, vP) * recipDet;286 if (u < 0.f || u > 1.f)287 return false; 288 289 290 vQ = [Cross](vT, vE1);291 292 293 v = [Dot](lineDir, vQ) * recipDet;294 if (v < 0.f || u + v > 1.f) 295 return false;296 297 298 299 300 t = [Dot](vE2, vQ) * recipDet;301 return true;302 303 }304 305 306 bool [Triangle::Intersects](const [LineSegment] &l, float *d, [float3] *intersectionPoint) const307 {308 309 310 311 float u, v, t;312 bool success = [IntersectLineTri](l.[a], l.[Dir](), [a], [b], [c], u, v, t);313 if (!success)314 return false;315 float length = l.[LengthSq]();316 if (t < 0.f || t*t >= length)317 return false;318 length = sqrtf(length);319 if (d)320 {321 float len = t / length;322 *d = len;323 if (intersectionPoint)324 *intersectionPoint = l.[GetPoint](len);325 }326 else if (intersectionPoint)327 *intersectionPoint = l.[GetPoint](t / length);328 return true;329 }330 331 bool [Triangle::Intersects](const [Line] &l, float *d, [float3] *intersectionPoint) const332 {333 float u, v, t;334 bool success = [IntersectLineTri](l.[pos], l.[dir], a, b, c, u, v, t);335 if (!success)336 return false;337 if (d)338 *d = t;339 if (intersectionPoint)340 *intersectionPoint = l.[GetPoint](t);341 return success;342 }343 344 bool [Triangle::Intersects](const [Ray] &r, float *d, [float3] *intersectionPoint) const345 {346 float u, v, t;347 bool success = [IntersectLineTri](r.[pos], r.[dir], a, b, c, u, v, t);348 if (!success || t <= 0.f)349 return false;350 if (d)351 *d = t;352 if (intersectionPoint)353 *intersectionPoint = r.[GetPoint](t);354 return success;355 }356 357 bool [Triangle::Intersects](const [Plane] &plane) const358 {359 return plane.[Intersects](*this);360 }361 362 363 364 bool [Triangle::Intersects](const [Sphere] &sphere, [float3] *closestPointOnTriangle) const365 {366 [float3] pt = [ClosestPoint](sphere.[pos]);367 368 if (closestPointOnTriangle)369 *closestPointOnTriangle = pt;370 371 return pt.[DistanceSq](sphere.[pos]) <= sphere.[r] * sphere.[r];372 }373 374 bool [Triangle::Intersects](const [Sphere] &sphere) const375 {376 return [Intersects](sphere, 0);377 }378 379 static void FindIntersectingLineSegments(const [Triangle] &t, float da, float db, float dc, [LineSegment] &l1, [LineSegment] &l2)380 {381 if (da*db > 0.f)382 {383 l1 = [LineSegment](t.[a], t.[c]);384 l2 = [LineSegment](t.[b], t.[c]);385 }386 else if (db*dc > 0.f)387 {388 l1 = [LineSegment](t.[a], t.[b]);389 l1 = [LineSegment](t.[a], t.[c]);390 }391 else392 {393 l1 = [LineSegment](t.[a], t.[b]);394 l1 = [LineSegment](t.[b], t.[c]);395 }396 }397 398 399 400 401 402 bool [Triangle::Intersects](const [Triangle] &t2, [LineSegment] *outLine) const403 {404 405 [Plane] p1 = this->[PlaneCCW]();406 float t2da = p1.[SignedDistance](t2.[a]);407 float t2db = p1.[SignedDistance](t2.[b]);408 float t2dc = p1.[SignedDistance](t2.[c]);409 if (t2da*t2db > 0.f && t2da*t2dc > 0.f)410 return false;411 412 [Plane] p2 = t2.[PlaneCCW]();413 float t1da = p2.[SignedDistance](this->a);414 float t1db = p2.[SignedDistance](this->b);415 float t1dc = p2.[SignedDistance](this->c);416 if (t1da*t1db > 0.f && t1da*t1dc > 0.f)417 return false;418 419 420 [Line] l;421 bool success = p1.[Intersects](p2, &l);422 [assume](success); 423 if (!success)424 return false;425 426 427 [LineSegment] l1a, l1b;428 [LineSegment] l2a, l2b;429 FindIntersectingLineSegments(*this, t1da, t1db, t1dc, l1a, l1b);430 FindIntersectingLineSegments(t2, t2da, t2db, t2dc, l2a, l2b);431 432 433 float d1a, d1b, d2a, d2b;434 l.[Distance](l1a, &d1a);435 l.[Distance](l1b, &d1b);436 l.[Distance](l2a, &d2a);437 l.[Distance](l2b, &d2b);438 if (d1a > d1b)439 [Swap](d1a, d1b);440 if (d2a > d2b)441 [Swap](d2a, d2b);442 float rStart = [Max](d1a, d2a);443 float rEnd = [Min](d1b, d2b);444 if (rStart <= rEnd)445 {446 if (outLine)447 *outLine = [LineSegment](l.[GetPoint](rStart), l.[GetPoint](rEnd));448 return true;449 }450 return false;451 }452 453 bool [RangesOverlap](float start1, float end1, float start2, float end2)454 {455 return end1 >= start2 && end2 >= start1;456 }457 458 459 bool [Triangle::Intersects](const [AABB] &aabb) const460 {461 462 463 464 465 float t1, t2, a1, a2;466 const [float3] [e][3] = { [float3](1,0,0), [float3](0,1,0), [float3](0,0,1) };467 468 for(int i = 0; i < 3; ++i)469 {470 [ProjectToAxis](e[i], t1, t2);471 aabb.[ProjectToAxis](e[i], a1, a2);472 if ()473 return false;474 }475 476 [float3] n = [UnnormalizedNormalCCW]();477 [ProjectToAxis](n, t1, t2);478 aabb.[ProjectToAxis](n, a1, a2);479 if ()480 return false;481 482 const [float3] t[3] = { b-[a], c-[a], c-b };483 484 for(int i = 0; i < 3; ++i)485 for(int j = 0; j < 3; ++j)486 {487 [float3] axis = [Cross](e[i], t[j]);488 float len = axis.[LengthSq]();489 if (len <= 1e-4f)490 continue; 491 492 [ProjectToAxis](axis, t1, t2);493 aabb.[ProjectToAxis](axis, a1, a2);494 if ()495 return false;496 }497 498 499 return true;500 }501 502 bool [Triangle::Intersects](const [OBB] &obb) const503 {504 return obb.[Intersects](*this);505 }506 507 bool [Triangle::Intersects](const [Polygon] &polygon) const508 {509 return polygon.[Intersects](*this);510 }511 512 bool [Triangle::Intersects](const [Frustum] &frustum) const513 {514 return frustum.[Intersects](*this);515 }516 517 bool [Triangle::Intersects](const [Polyhedron] &polyhedron) const518 {519 return polyhedron.[Intersects](*this);520 }521 522 bool [Triangle::Intersects](const [Capsule] &capsule) const523 {524 return capsule.[Intersects](*this);525 }526 527 void [Triangle::ProjectToAxis](const [float3] &axis, float &dMin, float &dMax) const528 {529 dMin = dMax = [Dot](axis, a);530 float t = [Dot](axis, b);531 dMin = [Min](t, dMin);532 dMax = [Max](t, dMax);533 t = [Dot](axis, c);534 dMin = [Min](t, dMin);535 dMax = [Max](t, dMax);536 }537 538 539 [float3] [Triangle::ClosestPoint](const [float3] &p) const540 {541 542 543 544 [float3] ab = b - [a];545 [float3] ac = c - [a];546 [float3] ap = p - [a];547 float d1 = [Dot](ab, ap);548 float d2 = [Dot](ac, ap);549 if (d1 <= 0.f && d2 <= 0.f)550 return [a]; 551 552 553 [float3] bp = p - [b];554 float d3 = [Dot](ab, bp);555 float d4 = [Dot](ac, bp);556 if (d3 >= 0.f && d4 <= d3)557 return [b]; 558 559 560 float vc = d1*d4 - d3*d2;561 if (vc <= 0.f && d1 >= 0.f && d3 <= 0.f)562 {563 float v = d1 / (d1 - d3);564 return a + v * ab; 565 }566 567 568 [float3] cp = p - [c];569 float d5 = [Dot](ab, cp);570 float d6 = [Dot](ac, cp);571 if (d6 >= 0.f && d5 <= d6)572 return [c]; 573 574 575 float vb = d5*d2 - d1*d6;576 if (vb <= 0.f && d2 >= 0.f && d6 <= 0.f)577 {578 float w = d2 / (d2 - d6);579 return a + w * ac; 580 }581 582 583 float va = d3*d6 - d5*d4;584 if (va <= 0.f && d4 - d3 >= 0.f && d5 - d6 >= 0.f)585 {586 float w = (d4 - d3) / (d4 - d3 + d5 - d6);587 return b + w * (c - [b]); 588 }589 590 591 float denom = 1.f / (va + vb + vc);592 float v = vb * denom;593 float w = vc * denom;594 return a + ab * v + ac * w;595 }596 597 598 [float3] [Triangle::ClosestPoint](const [LineSegment] &lineSegment, [float3] *otherPt) const599 {600 601 [float3] closestToA = [ClosestPoint](lineSegment.[a]);602 [float3] closestToB = [ClosestPoint](lineSegment.[b]);603 float d;604 [float3] closestToSegment = [ClosestPointToTriangleEdge](lineSegment, 0, 0, &d);605 [float3] segmentPt = lineSegment.[GetPoint](d);606 float distA = closestToA.[DistanceSq](lineSegment.[a]);607 float distB = closestToB.[DistanceSq](lineSegment.[b]);608 float distC = closestToSegment.[DistanceSq](segmentPt);609 if (distA <= distB && distA <= distC)610 {611 if (otherPt)612 *otherPt = lineSegment.[a];613 return closestToA;614 }615 else if (distB <= distC)616 {617 if (otherPt)618 *otherPt = lineSegment.[b];619 return closestToB;620 }621 else622 {623 if (otherPt)624 *otherPt = segmentPt;625 return closestToSegment;626 }627 }628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 bool aProjectsInsideTriangle = BarycentricInsideTriangle(line.a);643 bool bProjectsInsideTriangle = BarycentricInsideTriangle(line.b);644 645 if (aProjectsInsideTriangle && bProjectsInsideTriangle)646 {647 // We tested above for intersection, so cannot intersect now.648 if (d1 <= d2)649 {650 if (otherPt)651 *otherPt = line.a;652 return p.Project(line.a);653 }654 else655 {656 if (otherPt)657 *otherPt = line.b;658 return p.Project(line.b);659 }660 }661 LineSegment ab(a, b);662 LineSegment ac(a, c);663 LineSegment bc(b, c);664 665 float tab, tac, tbc;666 float tab2, tac2, tbc2;667 668 float dab = ab.Distance(line, &tab, &tab2);669 float dac = ac.Distance(line, &tac, &tac2);670 float dbc = bc.Distance(line, &tbc, &tbc2);671 672 if (dab <= dac && dab <= dbc && dab <= d1 && dab <= d2)673 {674 if (otherPt)675 *otherPt = line.GetPoint(tab2);676 return ab.GetPoint(tab);677 }678 else if (dac <= dbc && dac <= d1 && dac <= d2)679 {680 if (otherPt)681 *otherPt = line.GetPoint(tac2);682 return ab.GetPoint(tac);683 }684 else if (dbc <= d1 && dbc <= d2)685 {686 if (otherPt)687 *otherPt = line.GetPoint(tbc2);688 return ab.GetPoint(tbc);689 }690 else if (d1 <= d2)691 {692 if (otherPt)693 *otherPt = line.a;694 return p.Project(line.a);695 }696 else697 {698 if (otherPt)699 *otherPt = line.b;700 return p.Project(line.b);701 }702 }703 */704 705 [float3] [Triangle::ClosestPointToTriangleEdge](const [Line] &other, float *outU, float *outV, float *outD) const706 {707 708 709 float d1, d2, d3;710 [float3] pt1 = [Edge](0).[ClosestPoint](other, 0, &d1);711 [float3] pt2 = [Edge](1).[ClosestPoint](other, 0, &d2);712 [float3] pt3 = [Edge](2).[ClosestPoint](other, 0, &d3);713 float dist1 = pt1.[DistanceSq](other.[GetPoint](d1));714 float dist2 = pt2.[DistanceSq](other.[GetPoint](d2));715 float dist3 = pt3.[DistanceSq](other.[GetPoint](d3));716 if (dist1 <= dist2 && dist1 <= dist3)717 {718 if (outU) *outU = [BarycentricUV](pt1).[x];719 if (outV) *outV = [BarycentricUV](pt1).[y];720 if (outD) *outD = d1;721 return pt1;722 }723 else if (dist2 <= dist3)724 {725 if (outU) *outU = [BarycentricUV](pt2).[x];726 if (outV) *outV = [BarycentricUV](pt2).[y];727 if (outD) *outD = d2;728 return pt2;729 }730 else731 {732 if (outU) *outU = [BarycentricUV](pt3).[x];733 if (outV) *outV = [BarycentricUV](pt3).[y];734 if (outD) *outD = d3;735 return pt3;736 }737 }738 739 [float3] [Triangle::ClosestPointToTriangleEdge](const [LineSegment] &lineSegment, float *outU, float *outV, float *outD) const740 {741 742 743 float d1, d2, d3;744 [float3] pt1 = [Edge](0).[ClosestPoint](lineSegment, 0, &d1);745 [float3] pt2 = [Edge](1).[ClosestPoint](lineSegment, 0, &d2);746 [float3] pt3 = [Edge](2).[ClosestPoint](lineSegment, 0, &d3);747 float dist1 = pt1.[DistanceSq](lineSegment.[GetPoint](d1));748 float dist2 = pt2.[DistanceSq](lineSegment.[GetPoint](d2));749 float dist3 = pt3.[DistanceSq](lineSegment.[GetPoint](d3));750 if (dist1 <= dist2 && dist1 <= dist3)751 {752 if (outU) *outU = [BarycentricUV](pt1).[x];753 if (outV) *outV = [BarycentricUV](pt1).[y];754 if (outD) *outD = d1;755 return pt1;756 }757 else if (dist2 <= dist3)758 {759 if (outU) *outU = [BarycentricUV](pt2).[x];760 if (outV) *outV = [BarycentricUV](pt2).[y];761 if (outD) *outD = d2;762 return pt2;763 }764 else765 {766 if (outU) *outU = [BarycentricUV](pt3).[x];767 if (outV) *outV = [BarycentricUV](pt3).[y];768 if (outD) *outD = d3;769 return pt3;770 }771 }772 773 774 [float3] [Triangle::ClosestPoint](const [Line] &other, float *outU, float *outV, float *outD) const775 {776 777 778 779 780 781 782 783 784 [float3] e0 = b-[a];785 [float3] e1 = c-[a];786 [float3] d = other.[dir];787 788 const float d_e0e0 = [Dot](e0, e0);789 const float d_e0e1 = [Dot](e0, e1);790 const float d_e0d = [Dot](e0, d);791 const float d_e1e1 = [Dot](e1, e1);792 const float d_e1d = [Dot](e1, d);793 const float d_dd = [Dot](d, d);794 795 [float3x3] m;796 m[0][0] = d_e0e0; m[0][1] = d_e0e1; m[0][2] = -d_e0d;797 m[1][0] = d_e0e1; m[1][1] = d_e1e1; m[1][2] = -d_e1d;798 m[2][0] = -d_e0d; m[2][1] = -d_e1d; m[2][2] = d_dd;799 800 801 bool inv = m.[Inverse]();802 if (!inv)803 return [ClosestPointToTriangleEdge](other, outU, outV, outD);804 805 [float3] v_m_p = a - other.[pos];806 float v_m_p_e0 = v_m_p.[Dot](e0);807 float v_m_p_e1 = v_m_p.[Dot](e1);808 float v_m_p_d = v_m_p.[Dot](d);809 [float3] b = [float3](-v_m_p_e0, -v_m_p_e1, v_m_p_d);810 [float3] uvt = m * [b];811 812 813 814 815 float u = uvt.[x];816 float v = uvt.[y];817 float t = uvt.[z];818 if (u < 0)819 {820 if (outU) *outU = 0;821 822 823 float m00 = m[2][2];824 float m01 = -m[2][1];825 float m10 = -m[1][2];826 float m11 = m[1][1];827 float det = m00*m11 - m01*m10;828 829 830 v = m00*b[1] + m01*b[2];831 t = m10*b[1] + m11*b[2];832 if (outD) *outD = t;833 834 835 if (v <= 0)836 {837 if (outV) *outV = 0;838 t = v_m_p_d / d_dd;839 return [Point](0, 0);840 }841 else if (v >= 1)842 {843 if (outV) *outV = 1;844 t = (v_m_p_d - d_e1d) / d_dd;845 return [Point](0, 1);846 }847 else 848 {849 if (outV) *outV = v;850 return [Point](0, v);851 }852 }853 else if (v <= 0)854 {855 if (outV) *outV = 0;856 857 858 float m00 = m[2][2];859 float m01 = -m[2][0];860 float m10 = -m[0][2];861 float m11 = m[0][0];862 float det = 1.f / (m00*m11 - m01*m10);863 864 865 u = (m00*b[0] + m01*b[2]) * det;866 t = (m10*b[0] + m11*b[2]) * det;867 if (outD) *outD = t;868 869 870 if (u <= 0)871 {872 if (outU) *outU = 0;873 t = v_m_p_d / d_dd;874 return [Point](0, 0);875 }876 else if (u >= 1)877 {878 if (outU) *outU = 1;879 t = (v_m_p_d - d_e0d) / d_dd;880 return [Point](1, 0);881 }882 else 883 {884 if (outU) *outU = u;885 return [Point](u, 0);886 }887 }888 else if (u + v >= 1.f)889 {890 891 float m00 = d_e0e0 + d_e1e1 - 2.f * d_e0e1;892 float m01 = -d_e0d + d_e1d;893 float m10 = -d_e0d + d_e1d;894 float m11 = d_dd;895 float det = 1.f / (m00*m11 - m01*m10);896 897 float b0 = d_e1e1 - d_e0e1 + v_m_p_e0 - v_m_p_e1;898 float b1 = d_e1d + v_m_p_d;899 900 [Swap](m00, m11);901 [Swap](m01, m10);902 m01 = -m01;903 m10 = -m10;904 905 906 u = (m00*b0 + m01*b1) * det;907 t = (m10*b0 + m11*b1) * det;908 if (outD) *outD = t;909 910 911 if (u <= 0)912 {913 if (outU) *outU = 0;914 if (outV) *outV = 1;915 t = (d_e1d + v_m_p_d) / d_dd;916 return [Point](0, 1);917 }918 else if (u >= 1)919 {920 if (outU) *outU = 1;921 if (outV) *outV = 0;922 t = (v_m_p_d + d_e0d) / d_dd;923 return [Point](1, 0);924 }925 else 926 {927 if (outU) *outU = u;928 if (outV) *outV = 1.f - u;929 return [Point](u, 1.f - u);930 }931 }932 else 933 {934 if (outU) *outU = u;935 if (outV) *outV = v;936 if (outD) *outD = t;937 return [Point](u, v);938 }939 }940 941 942 [float3] [Triangle::ClosestPoint](const [Triangle] &other, [float3] *otherPt) const943 {944 945 946 947 948 [LineSegment] l;949 bool success = this->[Intersects](other, &l);950 if (success)951 {952 [float3] cp = l.[CenterPoint]();953 if (otherPt)954 *otherPt = cp;955 return cp;956 }957 958 [float3] closestThis = this->[ClosestPoint](other.[a]);959 [float3] closestOther = other.[a];960 float closestDSq = closestThis.[DistanceSq](closestOther);961 962 [float3] pt = this->[ClosestPoint](other.[b]);963 float dSq = pt.[DistanceSq](other.[b]);964 if (dSq < closestDSq) closestThis = pt, closestOther = other.[b], closestDSq = dSq;965 966 pt = this->[ClosestPoint](other.[c]);967 dSq = pt.[DistanceSq](other.[c]);968 if (dSq < closestDSq) closestThis = pt, closestOther = other.[c], closestDSq = dSq;969 970 [LineSegment] l1[3] = { [LineSegment](a,b), [LineSegment](a,c), [LineSegment](b,c) };971 [LineSegment] l2[3] = { [LineSegment](other.[a],other.[b]), [LineSegment](other.[a],other.[c]), [LineSegment](other.[b],other.[c]) };972 float d, d2;973 for(int i = 0; i < 3; ++i)974 for(int j = 0; j < 3; ++j)975 {976 float dist = l1[i].[Distance](l2[j], &d, &d2);977 if (dist*dist < closestDSq)978 {979 closestThis = l1[i].[GetPoint](d);980 closestOther = l2[j].[GetPoint](d2);981 closestDSq = dist*dist;982 }983 }984 985 if (otherPt)986 *otherPt = closestOther;987 return closestThis;988 }989 990 [float3] [Triangle::RandomPointInside]([LCG] &rng) const991 {992 993 float s = rng.[Float]();994 float t = rng.[Float]();995 if (s + t > 1.f)996 {997 s = 1.f - s;998 t = 1.f - t;999 }1000 return [Point](s, t);1001 }1002 1003 [float3] [Triangle::RandomVertex]([LCG] &rng) const1004 {1005 return [Vertex](rng.[Int](0, 2));1006 }1007 1008 [float3] [Triangle::RandomPointOnEdge]([LCG] &rng) const1009 {1010 [assume](![IsDegenerate]());1011 float ab = a.[Distance](b);1012 float bc = b.Distance(c);1013 float ca = c.Distance(a);1014 float r = rng.[Float](0, ab + bc + ca);1015 if (r < ab)1016 return a + (b-[a]) * r / ab;1017 r -= ab;1018 if (r < bc)1019 return b + (c-[b]) * r / bc;1020 r -= bc;1021 return c + (a-[c]) * r / ca;1022 }1023 1024 [Triangle] [operator *](const [float3x3] &transform, const [Triangle] &t)1025 {1026 return [Triangle](transform*t.[a], transform*t.[b], transform*t.[c]);1027 }1028 1029 [Triangle] [operator *](const [float3x4] &transform, const [Triangle] &t)1030 {1031 return [Triangle](transform.[MulPos](t.[a]), transform.[MulPos](t.[b]), transform.[MulPos](t.[c]));1032 }1033 1034 [Triangle] [operator *](const [float4x4] &transform, const [Triangle] &t)1035 {1036 return [Triangle](transform.[MulPos](t.[a]), transform.[MulPos](t.[b]), transform.[MulPos](t.[c]));1037 }1038 1039 [Triangle] [operator *](const [Quat] &transform, const [Triangle] &t)1040 {1041 return [Triangle](transform*t.[a], transform*t.[b], transform*t.[c]);1042 }1043 1044 #ifdef MATH_ENABLE_STL_SUPPORT1045 std::string Triangle::ToString() const1046 {1047 char str[256];1048 sprintf(str, "Triangle(a:(%.2f, %.2f, %.2f) b:(%.2f, %.2f, %.2f) c:(%.2f, %.2f, %.2f))", 1049 a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z);1050 return str;1051 }1052 #endif1053 1054 [MATH_END_NAMESPACE] Go back to previous page