diff --git a/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp b/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp index e807c349e1e7d739f9c64cb9764d5c764f329382..45eb330472b75323b5623aa2c2c2bbc59e815cdf 100644 --- a/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp +++ b/Source/StudyFrameworkPlugin/Private/GazeTracking/SFGazeTracker.cpp @@ -368,6 +368,49 @@ float USFGazeTracker::GetPupilDiameter() return 0.0f; } +FProximityGazingResult USFGazeTracker::ComputeProximityGazingForActor(const AActor* Actor) +{ + checkf(Actor, TEXT("[USFGazeTracker::ComputeProximityGazingForActor] Supplied Actor is nullptr")); + const FBox ActorBox = Actor->GetComponentsBoundingBox(); + if (!ActorBox.IsValid) + { + UE_LOG(LogTemp, Error, TEXT("Cannot get bounding box for actor %s"), *Actor->GetName()); + return FProximityGazingResult(); + } + + // Debug + DrawDebugBox(GetWorld(), ActorBox.GetCenter(), ActorBox.GetExtent(), FColor::Red); + + const FGazeRay Gaze = GetWorldGazeDirection(); + const FVector Base = ActorBox.GetCenter(); + const FVector UserOriginToBox = Base - Gaze.Origin; + const float ProjectionLength = FVector::DotProduct(UserOriginToBox, Gaze.Direction); + if (ProjectionLength < 0.0f) + { // Object is behind the user + return FProximityGazingResult(); + } + + // Angle between the User->Box and the Gaze Direction + const float AngleBetweenRays = acosf(FVector::DotProduct(UserOriginToBox.GetSafeNormal(), Gaze.Direction.GetSafeNormal())); + const float GazeRayLength = ProjectionLength / (1 - AngleBetweenRays); + + // Closest point on the ray to the object + const FVector ProjectedPoint = Gaze.Origin + Gaze.Direction * GazeRayLength; + // Closest point on the box to the ray + const FVector ClosestPointToBox = ActorBox.GetClosestPointTo(ProjectedPoint); + // Angle between the two + const FVector ToBoxEdge = ClosestPointToBox - Gaze.Origin; + const FVector ToGazePoint = ProjectedPoint - Gaze.Origin; + const double Angle = FMath::RadiansToDegrees(acosf(FVector::DotProduct(ToBoxEdge.GetSafeNormal(), ToGazePoint.GetSafeNormal()))); + + constexpr double DebugExtend = 2; + const FVector DebugExtendVector = FVector(DebugExtend, DebugExtend, DebugExtend); + DrawDebugBox(GetWorld(), ProjectedPoint, DebugExtendVector, FColor::Green); + DrawDebugBox(GetWorld(), ClosestPointToBox, DebugExtendVector, FColor::Yellow); + + return FProximityGazingResult(ClosestPointToBox, ProjectedPoint, Angle); +} + FGazeRay USFGazeTracker::GetSranipalGazeRayFromData() { FGazeRay GazeRay; diff --git a/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h b/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h index 7b74ae00a41b78f569a6a80b1cf637db745c8bbd..681fda49be7f54e0a493baa6a188990e985af493 100644 --- a/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h +++ b/Source/StudyFrameworkPlugin/Public/GazeTracking/SFGazeTracker.h @@ -36,6 +36,15 @@ struct FGazeRay FVector Direction = FVector::ForwardVector; }; +USTRUCT(BlueprintType) +struct FProximityGazingResult +{ + GENERATED_BODY() + UPROPERTY(BlueprintReadOnly) FVector NearestPointOnObject = FVector::ZeroVector; + UPROPERTY(BlueprintReadOnly) FVector NearestPointOnRay = FVector::ZeroVector; + UPROPERTY(BlueprintReadOnly) double Angle = 0; +}; + UCLASS() class STUDYFRAMEWORKPLUGIN_API USFGazeTracker : public UObject { @@ -44,8 +53,7 @@ class STUDYFRAMEWORKPLUGIN_API USFGazeTracker : public UObject public: bool Tick(float DeltaTime); - - + void Init(EGazeTrackerMode Mode, bool IgnoreNonGazeTargetActors, float DataGatheringsPerSecond, EGazeTrackingBackend BackendToUse); //returns pair of Origin and Direction, in world coordinates @@ -84,6 +92,9 @@ public: UPROPERTY(BlueprintReadWrite) bool bDebugRenderRayTraces = false; + UFUNCTION(BlueprintCallable) + FProximityGazingResult ComputeProximityGazingForActor(const AActor* Actor); + private: FGazeRay GetSranipalGazeRayFromData();