@@ -39,11 +39,10 @@ public MinimalTriangle(Func<int, int, Vector3Float> vertexFunc, int faceIndex)
3939 double distanceFromOrigin = vertex ( 0 ) . Dot ( planeNormal ) ;
4040 Plane = new PlaneFloat ( new Vector3Float ( planeNormal ) , ( float ) distanceFromOrigin ) ;
4141
42- center = new Vector3Float ( ( vertex ( 0 ) + vertex ( 1 ) + vertex ( 2 ) ) / 3 ) ;
43- var aabbMinXYZ = vertex ( 0 ) . ComponentMin ( vertex ( 1 ) ) . ComponentMin ( vertex ( 2 ) ) ;
44- var aabbMaxXYZ = vertex ( 0 ) . ComponentMax ( vertex ( 1 ) ) . ComponentMax ( vertex ( 2 ) ) ;
45- var aabb = new AxisAlignedBoundingBox ( aabbMinXYZ , aabbMaxXYZ ) ;
46- aabbSize = new Vector3Float ( aabb . Size ) ;
42+ var aabbMin = vertex ( 0 ) . ComponentMin ( vertex ( 1 ) ) . ComponentMin ( vertex ( 2 ) ) ;
43+ var aabbMax = vertex ( 0 ) . ComponentMax ( vertex ( 1 ) ) . ComponentMax ( vertex ( 2 ) ) ;
44+ center = new Vector3Float ( ( aabbMin + aabbMax ) / 2 ) ;
45+ aabbSize = aabbMax - aabbMin ;
4746
4847 var normalLengths = new [ ] { Math . Abs ( planeNormal . X ) , Math . Abs ( planeNormal . Y ) , Math . Abs ( planeNormal . Z ) } ;
4948 MajorAxis = ( byte ) normalLengths . Select ( ( v , i ) => new { Axis = i , Value = Math . Abs ( v ) } ) . OrderBy ( o => o . Value ) . Last ( ) . Axis ;
@@ -101,7 +100,8 @@ public int FindSideOfLine(Vector2 sidePoint0, Vector2 sidePoint1, Vector2 testPo
101100
102101 public AxisAlignedBoundingBox GetAxisAlignedBoundingBox ( )
103102 {
104- return new AxisAlignedBoundingBox ( center - aabbSize , center + aabbSize ) ;
103+ Vector3Float halfSize = aabbSize / 2 ;
104+ return new AxisAlignedBoundingBox ( center - halfSize , center + halfSize ) ;
105105 }
106106
107107 public double GetAxisCenter ( int axis )
@@ -243,24 +243,30 @@ public override string ToString()
243243
244244 private bool Check2DHitOnMajorAxis ( double x , double y )
245245 {
246- // check the bounding rect
247- if ( x >= boundsOnMajorAxis . Left && x <= boundsOnMajorAxis . Right &&
248- y >= boundsOnMajorAxis . Bottom && y <= boundsOnMajorAxis . Top )
246+ // quick reject against projected triangle bounds
247+ const double boundsEpsilon = 1e-8 ;
248+ if ( ! ( x >= boundsOnMajorAxis . Left - boundsEpsilon && x <= boundsOnMajorAxis . Right + boundsEpsilon
249+ && y >= boundsOnMajorAxis . Bottom - boundsEpsilon && y <= boundsOnMajorAxis . Top + boundsEpsilon ) )
249250 {
250- Vector2 vertex0 = new Vector2 ( vertex ( 0 ) [ xForMajorAxis ] , vertex ( 0 ) [ yForMajorAxis ] ) ;
251- Vector2 vertex1 = new Vector2 ( vertex ( 1 ) [ xForMajorAxis ] , vertex ( 1 ) [ yForMajorAxis ] ) ;
252- Vector2 vertex2 = new Vector2 ( vertex ( 2 ) [ xForMajorAxis ] , vertex ( 2 ) [ yForMajorAxis ] ) ;
253- Vector2 hitPosition = new Vector2 ( x , y ) ;
254- int sumOfLineSides = FindSideOfLine ( vertex0 , vertex1 , hitPosition ) ;
255- sumOfLineSides += FindSideOfLine ( vertex1 , vertex2 , hitPosition ) ;
256- sumOfLineSides += FindSideOfLine ( vertex2 , vertex0 , hitPosition ) ;
257- if ( sumOfLineSides == - 3 || sumOfLineSides == 3 )
258- {
259- return true ;
260- }
251+ return false ;
261252 }
262253
263- return false ;
254+ Vector2 v0 = new Vector2 ( vertex ( 0 ) [ xForMajorAxis ] , vertex ( 0 ) [ yForMajorAxis ] ) ;
255+ Vector2 v1 = new Vector2 ( vertex ( 1 ) [ xForMajorAxis ] , vertex ( 1 ) [ yForMajorAxis ] ) ;
256+ Vector2 v2 = new Vector2 ( vertex ( 2 ) [ xForMajorAxis ] , vertex ( 2 ) [ yForMajorAxis ] ) ;
257+ Vector2 p = new Vector2 ( x , y ) ;
258+
259+ // Robust edge-inclusive test. This avoids misses when the ray lands exactly
260+ // on a shared edge/vertex (common with AABB-center clicks on pointed geometry).
261+ const double epsilon = 1e-9 ;
262+ double c0 = Vector2 . Cross ( p - v0 , v1 - v0 ) ;
263+ double c1 = Vector2 . Cross ( p - v1 , v2 - v1 ) ;
264+ double c2 = Vector2 . Cross ( p - v2 , v0 - v2 ) ;
265+
266+ bool hasNeg = c0 < - epsilon || c1 < - epsilon || c2 < - epsilon ;
267+ bool hasPos = c0 > epsilon || c1 > epsilon || c2 > epsilon ;
268+
269+ return ! ( hasNeg && hasPos ) ;
264270 }
265271
266272 private Vector3Float vertex ( int i )
0 commit comments