diff --git a/Intersection/IntrLine2dBox2d.cs b/Intersection/IntrLine2dBox2d.cs index 32054615941b22002652b43c257042373303b8ae..2d1ea372a5bd91bd523da42b01147e3275afde30 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 8d2fc7008949b3292efbf03eb25a2dbbd9fc9360..775c7ca3a1ed3c9676bad3c3c4f0f94f9c752f71 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 45c3099c4f6b41bf1e568cfc1a8aa364ae513c02..76e5f0f8b662b90f99d2aee4b6f449238349397c 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 3781f885ed6ba8468e5ae8e680b5f0326509dd9a..c64a16f49f43f09540554f79056602875277476f 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)