@@ -354,6 +354,7 @@ static void rectToFourPoints(
354354 const CollideInfo *a, // z is ignored
355355 Coord2D pts[]
356356);
357+
357358static void testRotatedPointsAgainstRect (
358359 const Coord2D *pts, // an array of 4
359360 const CollideInfo *a,
@@ -368,10 +369,16 @@ static void testRotatedPointsAgainstRect(
368369 Int *avgTot,
369370 Real *minDistSqr
370371);*/
372+ static Real fast_getBoundaryLength (
373+ Real x1,
374+ Real x2,
375+ Real y1,
376+ Real y2
377+ );
371378static void testSphereAgainstRect (
372379 const Coord2D *pts, // an array of 4
373380 const CollideInfo *a,
374- Real angle,
381+ // Real angle,
375382 Real &distance
376383);
377384
@@ -561,11 +568,35 @@ static void testRotatedPointsAgainstRect(
561568 }
562569}*/
563570
571+ // -----------------------------------------------------------------------------
572+ static Real fast_getBoundaryLength (Real x1, Real x2, Real y1, Real y2)
573+ {
574+ // Fast approximation of Boundary length, generally if one line has the length of only 10% or less of the other line, we take the longest line as the boundary.
575+ // Has an error rate of approx 0.5%.
576+ // Example: A line of dx = 5, and dy = 0.5, would give h = 5.025, we take dx directly
577+ Real dx = fabs (x1 - x2);
578+ Real dy = fabs (y1 - y2);
579+
580+ // Longest line and shortest between x and y
581+ Real dmax = max (dx, dy);
582+ Real dmin = min (dx, dy);
583+ Real maxTolerance = 0 .1f * dmax;
584+ Real distTolerance = max (20 .0f , 0 .5f * maxTolerance);
585+
586+ // Two conditions:
587+ // - the difference must be less than a maximum of 20 units, or 5% of the maximum length (to be not more than 1 whole unit)
588+ // - the min length must be 10% or less than the max length
589+ if (dmin < distTolerance && dmin <= maxTolerance)
590+ return dmax;
591+ else
592+ return sqrtf (dx*dx + dy*dy);
593+ }
594+
564595// -----------------------------------------------------------------------------
565596static void testSphereAgainstRect (
566597 const Coord2D *pts, // an array of 4
567598 const CollideInfo *a,
568- Real angle,
599+ // Real angle,
569600 Real &distance
570601)
571602{
@@ -624,43 +655,49 @@ static void testSphereAgainstRect(
624655 dist[i] = sqr (pts->x - a->position .x ) + sqr (pts->y - a->position .y );
625656 }
626657
627- Real minDist = HUGE_DIST_SQR;
628- Int minIdx, lastMinIdx;
629- for (Int i = 0 ; i < 4 ; i++)
658+ Real minDist;
659+ Int minIdx;
660+ Int lastMinIdx = -1 ;
661+ while ( TRUE )
630662 {
631- if (minDist > dist[i])
663+ minDist = HUGE_DIST_SQR;
664+ minIdx = 4 ;
665+ for (Int idx = 0 ; idx < 4 ; idx++)
666+ {
667+ if (minDist > dist[idx] && idx != lastMinIdx)
668+ {
669+ minDist = dist[idx];
670+ minIdx = idx;
671+ }
672+ }
673+ if (x1 == 0 .0f && y1 == 0 .0f )
632674 {
633- minDist = dist[i];
634- minIdx = i;
675+ x1 = points[minIdx].x ;
676+ y1 = points[minIdx].y ;
677+ lastMinIdx = minIdx;
635678 }
636- }
637- x1 = points[minIdx].x ;
638- y1 = points[minIdx].y ;
639-
640- lastMinIdx = minIdx;
641- minIdx = 4 ;
642- minDist = HUGE_DIST_SQR;
643- for (Int i = 0 ; i < 4 ; i++)
644- {
645- if (minDist > dist[i] && i != lastMinIdx)
679+ else
646680 {
647- minDist = dist[i];
648- minIdx = i;
681+ x2 = points[minIdx].x ;
682+ y2 = points[minIdx].y ;
683+ break ;
649684 }
650685 }
651- x2 = points[minIdx].x ;
652- y2 = points[minIdx].y ;
653686
654687 DEBUG_ASSERTCRASH (minIdx <= 3 , (" Hmm, this should not be possible." ));
655688
656689 // Get the Triangle length of all 3 points
657- Real boundary_h_Sqr = sqr (x1 - x2) + sqr (y1 - y2);
658- Real boundary_1_Sqr = sqr (x1 - a->position .x ) + sqr (y1 - a->position .y );
659- Real boundary_2_Sqr = sqr (x2 - a->position .x ) + sqr (y2 - a->position .y );
690+ // Real boundary_h = fast_getBoundaryLength(x1, x2, y1, y2);
691+ // Real boundary_1 = fast_getBoundaryLength(x1, a->position.x, y1, a->position.y);
692+ // Real boundary_2 = fast_getBoundaryLength(x2, a->position.x, y2, a->position.y);
693+
694+ // Real boundary_h = sqrtf(sqr(x1 - x2) + sqr(y1 - y2));
695+ // Real boundary_1 = sqrtf(sqr(x1 - a->position.x) + sqr(y1 - a->position.y));
696+ // Real boundary_2 = sqrtf(sqr(x2 - a->position.x) + sqr(y2 - a->position.y));
660697
661- Real boundary_h = sqrtf (boundary_h_Sqr );
662- Real boundary_1 = sqrtf (boundary_1_Sqr );
663- Real boundary_2 = sqrtf (boundary_2_Sqr );
698+ Real boundary_h = Hypot ( fabs (x1-x2), fabs (y1-y2) );
699+ Real boundary_1 = Hypot ( fabs (x1 - a-> position . x ), fabs (y1 - a-> position . y ) );
700+ Real boundary_2 = Hypot ( fabs (x2 - a-> position . x ), fabs (y2 - a-> position . y ) );
664701
665702 // Heron's formula
666703 Real semiPeri = (boundary_h + boundary_1 + boundary_2) * 0.5 ;
@@ -758,9 +795,8 @@ static Bool xy_collideTest_Rect_Circle(const CollideInfo *a, const CollideInfo *
758795 Coord2D pts[4 ];
759796 rectToFourPoints (a, pts);
760797
761- Real dir = atan2 (diff.y , diff.x );
762798 Real distance = 0 .0f ;
763- testSphereAgainstRect (pts, b, dir, distance);
799+ testSphereAgainstRect (pts, b, distance);
764800
765801 // DEBUG_LOG(("Radius: %f Distance: %f", b->geom.getMajorRadius(), distance));
766802
@@ -3707,7 +3743,7 @@ Object *PartitionManager::getClosestObjects(
37073743 useNewStructureCheck = TRUE ;
37083744 GeometryInfo geometry ( GEOMETRY_SPHERE, TRUE , maxDist, maxDist, maxDist );
37093745 if (!geomCollidesWithGeom (objPos, geometry, 0 .0f , thisObj->getPosition (), geomInfo, thisObj->getOrientation (), distProc == distCalcProc_BoundaryAndBoundary_2D ? SKIP_HEIGHT_CHECK : BOUNDARY_HEIGHT_CHECK, &thisDistSqr))
3710- continue ;
3746+ continue ;
37113747 // DEBUG_LOG(("geomCollidesWithGeom Not Passed. Object: %s Radius: %f, DistSqr: %f", thisObj->getTemplate()->getName().str(), maxDist, thisDistSqr));
37123748
37133749 // DEBUG_LOG(("Passed. Object: %s Radius: %f, DistSqr: %f", thisObj->getTemplate()->getName().str(), maxDist, thisDistSqr));
@@ -6897,9 +6933,8 @@ Bool PartitionFilterAcceptByObjectCustomStatus::allow(Object *objOther)
68976933 {
68986934 for (std::vector<AsciiString>::const_iterator it = m_mustBeClear.begin (); it != m_mustBeClear.end (); ++it)
68996935 {
6900- allow = objOther->testCustomStatus ( *it );
6901- if (!allow)
6902- break ;
6936+ if (objOther->testCustomStatus ( *it ))
6937+ return FALSE ;
69036938 }
69046939 }
69056940 return allow;
0 commit comments