From dd0ba84cbe25cdb719a3e853572347a4d0269658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=80=90=E7=A8=8B=E5=BA=8F=E3=80=91=E7=A8=8B=E4=B8=80?= =?UTF-8?q?=E5=B3=B0?= <649669121@qq.com> Date: Thu, 10 Nov 2022 15:15:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B03d=E7=9B=B4=E7=BA=BF=E4=B8=8E?= =?UTF-8?q?Box3d=E7=9A=84=E7=9B=B8=E4=BA=A4=E6=A3=80=E6=B5=8B=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Intersection/IntrLine2dBox2d.cs | 13 +--- Intersection/IntrLine3dBox3d.cs | 119 +++++++++++++++++++++++++++++++- Math/Box3d.cs | 9 +++ Math/Line2d.cs | 9 ++- 4 files changed, 134 insertions(+), 16 deletions(-) diff --git a/Intersection/IntrLine2dBox2d.cs b/Intersection/IntrLine2dBox2d.cs index 3205461..2d1ea37 100644 --- a/Intersection/IntrLine2dBox2d.cs +++ b/Intersection/IntrLine2dBox2d.cs @@ -25,22 +25,15 @@ namespace Oroxylum public IntrLine2dBox2d(Line2d line, Box2d box) { - LineParam0 = 0; - LineParam1 = 0; + LineParam0 = -float.MaxValue; + LineParam1 = float.MaxValue; Point0 = 0; Point1 = 0; Result = E_IntersectionResult.NotComputed; Type = E_IntersectionType.Empty; Quantity = 0; - float2 direction = line.Direction; - - if (!direction.IsNormalized()) - direction = math.normalize(direction); - - LineParam0 = -float.MaxValue; - LineParam1 = float.MaxValue; - DoClipping(ref LineParam0, ref LineParam1, line.Origin, direction, box, + DoClipping(ref LineParam0, ref LineParam1, line.Origin, line.Direction, box, true, ref Quantity, ref Point0, ref Point1, ref Type); Result = (Type != E_IntersectionType.Empty) ? diff --git a/Intersection/IntrLine3dBox3d.cs b/Intersection/IntrLine3dBox3d.cs index 8d2fc70..775c7ca 100644 --- a/Intersection/IntrLine3dBox3d.cs +++ b/Intersection/IntrLine3dBox3d.cs @@ -8,14 +8,127 @@ */ +using Unity.Mathematics; + namespace Oroxylum { /// /// 相交计算结果:3d直线与3dBox /// - public class IntrLine3dBox3d + public struct IntrLine3dBox3d { + public int Quantity; + public E_IntersectionResult Result; + public E_IntersectionType Type; + public float LineParam0, LineParam1; + public float3 Point0; + public float3 Point1; + + public IntrLine3dBox3d(Line3d line, Box3d box) + { + Result = E_IntersectionResult.NotComputed; + Type = E_IntersectionType.Empty; + LineParam0 = -float.MaxValue; + LineParam1 = float.MaxValue; + Point0 = 0; + Point1 = 1; + Quantity = 0; + + DoClipping(ref LineParam0, ref LineParam1, line.Origin, line.Direction, box, + true, ref Quantity, ref Point0, ref Point1, ref Type); + + Result = (Type != E_IntersectionType.Empty) ? + E_IntersectionResult.Intersects : E_IntersectionResult.NoIntersection; + } + + public static bool DoClipping(ref float t0, ref float t1, + float3 origin, float3 direction, + Box3d box, bool solid, ref int quantity, + ref float3 point0, ref float3 point1, + ref E_IntersectionType intrType) + { + // Convert linear component to box coordinates. + float3 diff = origin - box.Center; + float3 BOrigin = new float3( + diff.Dot(box.AxisX), + diff.Dot(box.AxisY), + diff.Dot(box.AxisZ) + ); + float3 BDirection = new float3( + direction.Dot(box.AxisX), + direction.Dot(box.AxisY), + direction.Dot(box.AxisZ) + ); + + double saveT0 = t0, saveT1 = t1; + bool notAllClipped = + Clip(+BDirection.x, -BOrigin.x - box.Extent.x, ref t0, ref t1) && + Clip(-BDirection.x, +BOrigin.x - box.Extent.x, ref t0, ref t1) && + Clip(+BDirection.y, -BOrigin.y - box.Extent.y, ref t0, ref t1) && + Clip(-BDirection.y, +BOrigin.y - box.Extent.y, ref t0, ref t1) && + Clip(+BDirection.z, -BOrigin.z - box.Extent.z, ref t0, ref t1) && + Clip(-BDirection.z, +BOrigin.z - box.Extent.z, ref t0, ref t1); + + if (notAllClipped && (solid || t0 != saveT0 || t1 != saveT1)) + { + if (t1 > t0) + { + intrType = E_IntersectionType.LineSegment; + quantity = 2; + point0 = origin + t0 * direction; + point1 = origin + t1 * direction; + } + else + { + intrType = E_IntersectionType.Point; + quantity = 1; + point0 = origin + t0 * direction; + } + } + else + { + quantity = 0; + intrType = E_IntersectionType.Empty; + } + + return intrType != E_IntersectionType.Empty; + } + + private static bool Clip(float denom, float numer, ref float t0, ref float t1) + { + // Return value is 'true' if line segment intersects the current test + // plane. Otherwise 'false' is returned in which case the line segment + // is entirely clipped. + + if (denom > 0) + { + if (numer - denom * t1 > OMath.ZeroTolerance) + { + return false; + } + if (numer > denom * t0) + { + t0 = numer / denom; + } + return true; + } + else if (denom < 0) + { + if (numer - denom * t0 > OMath.ZeroTolerance) + { + return false; + } + if (numer > denom * t1) + { + t1 = numer / denom; + } + return true; + } + else + { + return numer <= 0; + } + } - } -} +} \ No newline at end of file diff --git a/Math/Box3d.cs b/Math/Box3d.cs index 45c3099..76e5f0f 100644 --- a/Math/Box3d.cs +++ b/Math/Box3d.cs @@ -8,6 +8,8 @@ */ +using Unity.Mathematics; + namespace Oroxylum { /// @@ -15,6 +17,13 @@ namespace Oroxylum /// public struct Box3d { + public float3 Center; + public float3 Extent; + + public float3 AxisX => new float3(1.0f, 0.0f, 0.0f); + public float3 AxisY => new float3(0.0f, 1.0f, 0.0f); + public float3 AxisZ => new float3(0.0f, 0.0f, 1.0f); + } diff --git a/Math/Line2d.cs b/Math/Line2d.cs index 3781f88..c64a16f 100644 --- a/Math/Line2d.cs +++ b/Math/Line2d.cs @@ -18,13 +18,16 @@ namespace Oroxylum public struct Line2d { public float2 Origin; - public float2 Direction; + /// + /// 直线方向,已经 normalize + /// + public float2 Direction; public Line2d(float2 origin, float2 direction) { this.Origin = origin; - this.Direction = direction; + this.Direction = math.normalize(direction); } public static Line2d FromPoints(float2 p0, float2 p1) @@ -37,7 +40,7 @@ namespace Oroxylum public float2 ClosestPoint(float2 p) { float t = (p - Origin).Dot(Direction); - return Origin + t * Direction; + return Origin + (t * Direction); } public double DistanceSquared(float2 p) -- GitLab