| | | 1 | | //======================================================================= |
| | | 2 | | // VoxelContactManifold.cs |
| | | 3 | | //======================================================================= |
| | | 4 | | // MIT License, Copyright (c) 2024-present David Oravsky (mrdav30) |
| | | 5 | | // See LICENSE file in the project root for full license information. |
| | | 6 | | //======================================================================= |
| | | 7 | | |
| | | 8 | | using FixedMathSharp; |
| | | 9 | | using GridForge.Spatial; |
| | | 10 | | |
| | | 11 | | namespace GridForge.Grids.Topology; |
| | | 12 | | |
| | | 13 | | /// <summary> |
| | | 14 | | /// Classifies the exact shared geometry of two closed cell prisms. |
| | | 15 | | /// </summary> |
| | | 16 | | public enum VoxelContactKind : byte |
| | | 17 | | { |
| | | 18 | | /// <summary>The prisms do not intersect.</summary> |
| | | 19 | | Separated, |
| | | 20 | | /// <summary>The prisms share one point.</summary> |
| | | 21 | | Point, |
| | | 22 | | /// <summary>The prisms share a positive-length line.</summary> |
| | | 23 | | Edge, |
| | | 24 | | /// <summary>The prisms share a positive-area face.</summary> |
| | | 25 | | Face, |
| | | 26 | | /// <summary>The prism interiors overlap in three dimensions.</summary> |
| | | 27 | | VolumeOverlap |
| | | 28 | | } |
| | | 29 | | |
| | | 30 | | /// <summary> |
| | | 31 | | /// Identifies the world-plane orientation of a face contact. |
| | | 32 | | /// </summary> |
| | | 33 | | public enum VoxelContactFaceKind : byte |
| | | 34 | | { |
| | | 35 | | /// <summary>The manifold is not a face.</summary> |
| | | 36 | | None, |
| | | 37 | | /// <summary>A horizontal footprint segment extruded through a vertical interval.</summary> |
| | | 38 | | Vertical, |
| | | 39 | | /// <summary>A convex XZ polygon on a shared Y plane.</summary> |
| | | 40 | | Horizontal |
| | | 41 | | } |
| | | 42 | | |
| | | 43 | | /// <summary> |
| | | 44 | | /// Describes exact point, edge, face, or volume contact between two cell prisms. |
| | | 45 | | /// </summary> |
| | | 46 | | public readonly struct VoxelContactManifold |
| | | 47 | | { |
| | | 48 | | /// <summary>The source cell identity.</summary> |
| | | 49 | | public WorldVoxelIndex Source { get; } |
| | | 50 | | |
| | | 51 | | /// <summary>The target cell identity.</summary> |
| | | 52 | | public WorldVoxelIndex Target { get; } |
| | | 53 | | |
| | | 54 | | /// <summary>The target-center displacement from the source center.</summary> |
| | | 55 | | public Vector3d SourceToTarget { get; } |
| | | 56 | | |
| | | 57 | | /// <summary>The exact contact classification.</summary> |
| | | 58 | | public VoxelContactKind Kind { get; } |
| | | 59 | | |
| | | 60 | | /// <summary>The face orientation when <see cref="Kind"/> is <see cref="VoxelContactKind.Face"/>.</summary> |
| | | 61 | | public VoxelContactFaceKind FaceKind { get; } |
| | | 62 | | |
| | | 63 | | /// <summary>The lower bound of the shared vertical interval or horizontal face plane.</summary> |
| | | 64 | | public Fixed64 VerticalMin { get; } |
| | | 65 | | |
| | | 66 | | /// <summary>The upper bound of the shared vertical interval or horizontal face plane.</summary> |
| | | 67 | | public Fixed64 VerticalMax { get; } |
| | | 68 | | |
| | | 69 | | /// <summary>The first endpoint of a vertical face's exact XZ contact segment.</summary> |
| | | 70 | | public Vector2d HorizontalSegmentStart { get; } |
| | | 71 | | |
| | | 72 | | /// <summary>The second endpoint of a vertical face's exact XZ contact segment.</summary> |
| | | 73 | | public Vector2d HorizontalSegmentEnd { get; } |
| | | 74 | | |
| | | 75 | | /// <summary>The exact overlap polygon for a horizontal face or volume overlap.</summary> |
| | | 76 | | public GridConvexPolygon2d HorizontalPolygon { get; } |
| | | 77 | | |
| | | 78 | | /// <summary>The face area, or horizontal overlap area for a volume overlap.</summary> |
| | | 79 | | public Fixed64 CheckedArea { get; } |
| | | 80 | | |
| | | 81 | | /// <summary>Whether <see cref="CheckedArea"/> is representable without saturation.</summary> |
| | | 82 | | public bool IsAreaRepresentable { get; } |
| | | 83 | | |
| | | 84 | | /// <summary>Whether this manifold can be considered as an automatic portal before agent clearance checks.</summary> |
| | | 85 | | public bool IsPositiveAreaFace => |
| | 2456 | 86 | | Kind == VoxelContactKind.Face |
| | 2456 | 87 | | && IsAreaRepresentable |
| | 2456 | 88 | | && CheckedArea > Fixed64.Zero; |
| | | 89 | | |
| | | 90 | | /// <summary>The exact width of a vertical face contact segment.</summary> |
| | 6 | 91 | | public Fixed64 VerticalFaceWidth => FaceKind == VoxelContactFaceKind.Vertical |
| | 6 | 92 | | ? Vector2d.Distance(HorizontalSegmentStart, HorizontalSegmentEnd) |
| | 6 | 93 | | : Fixed64.Zero; |
| | | 94 | | |
| | | 95 | | /// <summary>The exact height of a vertical face contact interval.</summary> |
| | 6 | 96 | | public Fixed64 VerticalFaceHeight => FaceKind == VoxelContactFaceKind.Vertical |
| | 6 | 97 | | ? VerticalMax - VerticalMin |
| | 6 | 98 | | : Fixed64.Zero; |
| | | 99 | | |
| | | 100 | | internal VoxelContactManifold( |
| | | 101 | | WorldVoxelIndex source, |
| | | 102 | | WorldVoxelIndex target, |
| | | 103 | | Vector3d sourceToTarget, |
| | | 104 | | VoxelContactKind kind, |
| | | 105 | | VoxelContactFaceKind faceKind, |
| | | 106 | | Fixed64 verticalMin, |
| | | 107 | | Fixed64 verticalMax, |
| | | 108 | | Vector2d horizontalSegmentStart, |
| | | 109 | | Vector2d horizontalSegmentEnd, |
| | | 110 | | GridConvexPolygon2d horizontalPolygon, |
| | | 111 | | Fixed64 checkedArea, |
| | | 112 | | bool isAreaRepresentable) |
| | | 113 | | { |
| | 2645 | 114 | | Source = source; |
| | 2645 | 115 | | Target = target; |
| | 2645 | 116 | | SourceToTarget = sourceToTarget; |
| | 2645 | 117 | | Kind = kind; |
| | 2645 | 118 | | FaceKind = faceKind; |
| | 2645 | 119 | | VerticalMin = verticalMin; |
| | 2645 | 120 | | VerticalMax = verticalMax; |
| | 2645 | 121 | | HorizontalSegmentStart = horizontalSegmentStart; |
| | 2645 | 122 | | HorizontalSegmentEnd = horizontalSegmentEnd; |
| | 2645 | 123 | | HorizontalPolygon = horizontalPolygon; |
| | 2645 | 124 | | CheckedArea = checkedArea; |
| | 2645 | 125 | | IsAreaRepresentable = isAreaRepresentable; |
| | 2645 | 126 | | } |
| | | 127 | | } |