Fix one dollar recognizer implementation
This commit is contained in:
@@ -3,18 +3,19 @@
|
|||||||
|
|
||||||
#include "LumiCharacter.h"
|
#include "LumiCharacter.h"
|
||||||
|
|
||||||
#include "Engine/LocalPlayer.h"
|
|
||||||
#include "Engine/UserInterfaceSettings.h"
|
|
||||||
#include "Camera/CameraComponent.h"
|
#include "Camera/CameraComponent.h"
|
||||||
#include "Components/CapsuleComponent.h"
|
#include "Components/CapsuleComponent.h"
|
||||||
#include "GameFramework/SpringArmComponent.h"
|
#include "Engine/LocalPlayer.h"
|
||||||
#include "GameFramework/Controller.h"
|
#include "Engine/UserInterfaceSettings.h"
|
||||||
#include "InputActionValue.h"
|
|
||||||
#include "GameFramework/CharacterMovementComponent.h"
|
#include "GameFramework/CharacterMovementComponent.h"
|
||||||
|
#include "GameFramework/Controller.h"
|
||||||
|
#include "GameFramework/SpringArmComponent.h"
|
||||||
|
#include "InputActionValue.h"
|
||||||
|
#include "WizardingCentral/Logger/LogLumiCharacter.h"
|
||||||
#include "WizardingCentral/Utils/OneDollar/UniStrokeDataTable.h"
|
#include "WizardingCentral/Utils/OneDollar/UniStrokeDataTable.h"
|
||||||
#include "WizardingCentral/Utils/OneDollar/UniStrokeResult.h"
|
#include "WizardingCentral/Utils/OneDollar/UniStrokeResult.h"
|
||||||
|
|
||||||
DEFINE_LOG_CATEGORY(LogLumiCharacter);
|
static const FString SpellTemplatesTablePath = TEXT("/Game/DataTables/SpellTemplates.SpellTemplates");
|
||||||
|
|
||||||
// Sets default values
|
// Sets default values
|
||||||
ALumiCharacter::ALumiCharacter()
|
ALumiCharacter::ALumiCharacter()
|
||||||
@@ -49,7 +50,16 @@ ALumiCharacter::ALumiCharacter()
|
|||||||
// Spell System
|
// Spell System
|
||||||
bIsDrawing = false;
|
bIsDrawing = false;
|
||||||
SpellRecognizer = new FUniStrokeRecognizer();
|
SpellRecognizer = new FUniStrokeRecognizer();
|
||||||
if (SpellTemplatesTable)
|
if (SpellTemplatesTable == nullptr)
|
||||||
|
{
|
||||||
|
SpellTemplatesTable = Cast<UDataTable>(
|
||||||
|
StaticLoadObject(
|
||||||
|
UDataTable::StaticClass(),
|
||||||
|
nullptr,
|
||||||
|
*SpellTemplatesTablePath
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
LoadSpellTemplates();
|
LoadSpellTemplates();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +133,9 @@ void ALumiCharacter::OnJumpActionStarted(const FInputActionValue& Value)
|
|||||||
Jump();
|
Jump();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALumiCharacter::OnJumpActionOngoing(const FInputActionValue& Value) {}
|
void ALumiCharacter::OnJumpActionOngoing(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ALumiCharacter::OnJumpActionCompleted(const FInputActionValue& Value)
|
void ALumiCharacter::OnJumpActionCompleted(const FInputActionValue& Value)
|
||||||
{
|
{
|
||||||
@@ -300,7 +312,7 @@ void ALumiCharacter::LoadSpellTemplates() const
|
|||||||
void ALumiCharacter::CastSpell()
|
void ALumiCharacter::CastSpell()
|
||||||
{
|
{
|
||||||
const TArray<FVector2D>* CurrentPoints = SpellOverlay->GetSpellPoints();
|
const TArray<FVector2D>* CurrentPoints = SpellOverlay->GetSpellPoints();
|
||||||
const FUniStrokeResult Result = SpellRecognizer->Recognize(*CurrentPoints, false);
|
const FUniStrokeResult Result = SpellRecognizer->Recognize(*CurrentPoints);
|
||||||
|
|
||||||
bool bHasMatch = false;
|
bool bHasMatch = false;
|
||||||
if (Result.Score < 0.8f)
|
if (Result.Score < 0.8f)
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ class USpringArmComponent;
|
|||||||
class UCameraComponent;
|
class UCameraComponent;
|
||||||
struct FInputActionValue;
|
struct FInputActionValue;
|
||||||
|
|
||||||
DECLARE_LOG_CATEGORY_EXTERN(LogLumiCharacter, Log, All);
|
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FJumpDelegate);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FJumpDelegate);
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FStanceChangedDelegate,
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FStanceChangedDelegate,
|
||||||
@@ -145,13 +143,24 @@ public:
|
|||||||
OnSpellActionCompleted();
|
OnSpellActionCompleted();
|
||||||
void
|
void
|
||||||
OnSpellPositionActionTriggered(const FInputActionValue& Value);
|
OnSpellPositionActionTriggered(const FInputActionValue& Value);
|
||||||
|
void
|
||||||
|
OnSpellTrainSwitchActionCompleted();
|
||||||
|
|
||||||
void OnSpellTrainSwitchActionCompleted();
|
UFUNCTION(BlueprintCallable, Category = "Spell")
|
||||||
|
void
|
||||||
|
SetIsTraining(const bool bTraining);
|
||||||
|
|
||||||
void SetIsTraining(const bool bTraining);
|
UFUNCTION(BlueprintCallable, Category = "Spell")
|
||||||
void HideTrainWidget();
|
void
|
||||||
void ShowTrainWidget();
|
HideTrainWidget();
|
||||||
void AddSpellTemplateToTable(const FString& Name);
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Spell")
|
||||||
|
void
|
||||||
|
ShowTrainWidget();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Spell")
|
||||||
|
void
|
||||||
|
AddSpellTemplateToTable(const FString& Name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ void ALumiController::GetLumiCharacter(ALumiCharacter*& OutLumiCharacter) const
|
|||||||
OutLumiCharacter = LumiCharacter;
|
OutLumiCharacter = LumiCharacter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALumiCharacter* ALumiController::GetLumiCharacter() const
|
||||||
|
{
|
||||||
|
return LumiCharacter;
|
||||||
|
}
|
||||||
|
|
||||||
void ALumiController::OnPossess(APawn* InPawn)
|
void ALumiController::OnPossess(APawn* InPawn)
|
||||||
{
|
{
|
||||||
Super::OnPossess(InPawn);
|
Super::OnPossess(InPawn);
|
||||||
@@ -99,8 +104,8 @@ void ALumiController::OnPossess(APawn* InPawn)
|
|||||||
{
|
{
|
||||||
EnhancedInputComponent->BindAction(SpellAction,
|
EnhancedInputComponent->BindAction(SpellAction,
|
||||||
ETriggerEvent::Started,
|
ETriggerEvent::Started,
|
||||||
LumiCharacter,
|
this,
|
||||||
&ALumiCharacter::OnSpellActionStarted);
|
&ALumiController::OnSpellActionStarted);
|
||||||
EnhancedInputComponent->BindAction(SpellAction,
|
EnhancedInputComponent->BindAction(SpellAction,
|
||||||
ETriggerEvent::Completed,
|
ETriggerEvent::Completed,
|
||||||
this,
|
this,
|
||||||
@@ -128,12 +133,12 @@ void ALumiController::OnUnPossess()
|
|||||||
|
|
||||||
void ALumiController::OnSpellActionStarted()
|
void ALumiController::OnSpellActionStarted()
|
||||||
{
|
{
|
||||||
ShowMouseCursor();
|
// ShowMouseCursor();
|
||||||
LumiCharacter->OnSpellActionStarted();
|
LumiCharacter->OnSpellActionStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALumiController::OnSpellActionCompleted()
|
void ALumiController::OnSpellActionCompleted()
|
||||||
{
|
{
|
||||||
LumiCharacter->OnSpellActionCompleted();
|
LumiCharacter->OnSpellActionCompleted();
|
||||||
HideMouseCursor();
|
// HideMouseCursor();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,10 @@ public:
|
|||||||
void
|
void
|
||||||
GetLumiCharacter(ALumiCharacter*& OutLumiCharacter) const;
|
GetLumiCharacter(ALumiCharacter*& OutLumiCharacter) const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "LumiController")
|
||||||
|
ALumiCharacter*
|
||||||
|
GetLumiCharacter() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void
|
virtual void
|
||||||
OnPossess(APawn* InPawn) override;
|
OnPossess(APawn* InPawn) override;
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
DECLARE_LOG_CATEGORY_EXTERN(LogLumiCharacter, Log, All);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "UniStrokePoint.h"
|
#include "UniStrokePoint.h"
|
||||||
|
|
||||||
#include "ScreenPass.h"
|
#include "WizardingCentral/Logger/LogLumiCharacter.h"
|
||||||
|
|
||||||
FUniStrokePoint::FUniStrokePoint()
|
FUniStrokePoint::FUniStrokePoint()
|
||||||
{
|
{
|
||||||
@@ -49,9 +49,7 @@ FUniStrokePoint::BoundingBox(const TArray<FUniStrokePoint>& Points)
|
|||||||
{
|
{
|
||||||
// Edge case
|
// Edge case
|
||||||
if (Points.Num() == 0)
|
if (Points.Num() == 0)
|
||||||
{
|
|
||||||
return FUniStrokeRectangle();
|
return FUniStrokeRectangle();
|
||||||
}
|
|
||||||
|
|
||||||
float MinX = Points[0].X;
|
float MinX = Points[0].X;
|
||||||
float MinY = Points[0].Y;
|
float MinY = Points[0].Y;
|
||||||
@@ -86,14 +84,16 @@ FUniStrokePoint::Vectorize(const TArray<FUniStrokePoint>& Points)
|
|||||||
const float Magnitude = FMath::Sqrt(Sum);
|
const float Magnitude = FMath::Sqrt(Sum);
|
||||||
|
|
||||||
for (float& V : Vector)
|
for (float& V : Vector)
|
||||||
{
|
|
||||||
V /= Magnitude;
|
V /= Magnitude;
|
||||||
}
|
|
||||||
|
|
||||||
return Vector;
|
return Vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Proofread this function
|
FString FUniStrokePoint::ToString() const
|
||||||
|
{
|
||||||
|
return FString::Printf(TEXT("X=%.3f Y=%.3f"), X, Y);
|
||||||
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
FUniStrokePoint::OptimalCosineDistance(const TArray<float>& VectorA,
|
FUniStrokePoint::OptimalCosineDistance(const TArray<float>& VectorA,
|
||||||
const TArray<float>& VectorB)
|
const TArray<float>& VectorB)
|
||||||
@@ -173,10 +173,8 @@ FUniStrokePoint::Resample(TArray<FUniStrokePoint>& Points,
|
|||||||
|
|
||||||
// Edge case
|
// Edge case
|
||||||
if (Points.Num() == Num - 1)
|
if (Points.Num() == Num - 1)
|
||||||
{
|
|
||||||
Points.Add(OldPoints.Last());
|
Points.Add(OldPoints.Last());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
float
|
float
|
||||||
FUniStrokePoint::PathLength(const TArray<FUniStrokePoint>& Points)
|
FUniStrokePoint::PathLength(const TArray<FUniStrokePoint>& Points)
|
||||||
@@ -385,9 +383,7 @@ FUniStrokePoint::PathDistance(const TArray<FUniStrokePoint>& PathA,
|
|||||||
{
|
{
|
||||||
// Edge case: Different number of points
|
// Edge case: Different number of points
|
||||||
if (PathA.Num() != PathB.Num())
|
if (PathA.Num() != PathB.Num())
|
||||||
{
|
|
||||||
return TNumericLimits<float>::Max();
|
return TNumericLimits<float>::Max();
|
||||||
}
|
|
||||||
|
|
||||||
// d <- 0
|
// d <- 0
|
||||||
float d = 0;
|
float d = 0;
|
||||||
|
|||||||
@@ -84,6 +84,9 @@ struct WIZARDINGCENTRAL_API FUniStrokePoint
|
|||||||
static TArray<float>
|
static TArray<float>
|
||||||
Vectorize(const TArray<FUniStrokePoint>& Points);
|
Vectorize(const TArray<FUniStrokePoint>& Points);
|
||||||
|
|
||||||
|
FString
|
||||||
|
ToString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float X;
|
float X;
|
||||||
float Y;
|
float Y;
|
||||||
|
|||||||
@@ -12,16 +12,13 @@ FUniStrokeRecognizer::~FUniStrokeRecognizer()
|
|||||||
|
|
||||||
// TODO: Review this function
|
// TODO: Review this function
|
||||||
FUniStrokeResult
|
FUniStrokeResult
|
||||||
FUniStrokeRecognizer::Recognize(const TArray<FVector2D>& VectorPoints,
|
FUniStrokeRecognizer::Recognize(const TArray<FVector2D>& VectorPoints)
|
||||||
const bool& UseProtractor)
|
|
||||||
{
|
{
|
||||||
TArray<FUniStrokePoint> Points = FUniStrokePoint::From(VectorPoints);
|
TArray<FUniStrokePoint> Points = FUniStrokePoint::From(VectorPoints);
|
||||||
|
|
||||||
// Edge case: Not enough points
|
// Edge case: Not enough points
|
||||||
if (Points.Num() < 2 || FUniStrokePoint::PathLength(Points) < 100.0f)
|
if (Points.Num() < 2 || FUniStrokePoint::PathLength(Points) < 100.0f)
|
||||||
{
|
|
||||||
return FUniStrokeResult("Too few points made", 0.0);
|
return FUniStrokeResult("Too few points made", 0.0);
|
||||||
}
|
|
||||||
|
|
||||||
const FUniStrokeTemplate Candidate = FUniStrokeTemplate("", Points);
|
const FUniStrokeTemplate Candidate = FUniStrokeTemplate("", Points);
|
||||||
int TemplateIndex = -1;
|
int TemplateIndex = -1;
|
||||||
@@ -33,12 +30,7 @@ FUniStrokeRecognizer::Recognize(const TArray<FVector2D>& VectorPoints,
|
|||||||
for (int i = 0; i < Templates.Num(); i++)
|
for (int i = 0; i < Templates.Num(); i++)
|
||||||
{
|
{
|
||||||
// d <- DistanceAtBestAngle(points, T, -theta, theta, threshold)
|
// d <- DistanceAtBestAngle(points, T, -theta, theta, threshold)
|
||||||
const float d = UseProtractor
|
const float d = FUniStrokePoint::DistanceAtBestAngle(
|
||||||
? FUniStrokePoint::OptimalCosineDistance(
|
|
||||||
Templates[i].Vector,
|
|
||||||
Candidate.Vector
|
|
||||||
)
|
|
||||||
: FUniStrokePoint::DistanceAtBestAngle(
|
|
||||||
Candidate.Points,
|
Candidate.Points,
|
||||||
Templates[i].Points,
|
Templates[i].Points,
|
||||||
-AngleRange,
|
-AngleRange,
|
||||||
@@ -57,7 +49,8 @@ FUniStrokeRecognizer::Recognize(const TArray<FVector2D>& VectorPoints,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// score <- 1 – b / 0.5 sqrt(size^2 + size^2)
|
// score <- 1 – b / 0.5 sqrt(size^2 + size^2)
|
||||||
const float Score = UseProtractor ? 1.0 - b : 1.0 - b / HalfDiagonal;
|
static const float HalfDiagonal = 0.5 * FMath::Sqrt(2 * FMath::Square(SquareSize));
|
||||||
|
const float Score = 1.0 - b / HalfDiagonal;
|
||||||
|
|
||||||
// return <T', score>
|
// return <T', score>
|
||||||
return TemplateIndex == -1
|
return TemplateIndex == -1
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
#include "UniStrokeRecognizer.generated.h"
|
#include "UniStrokeRecognizer.generated.h"
|
||||||
|
|
||||||
static constexpr int NumTemplates = 16;
|
static constexpr int NumTemplates = 16;
|
||||||
static const float Diagonal = FMath::Sqrt(2 * FMath::Square(SquareSize));
|
|
||||||
static const float HalfDiagonal = 0.5 * Diagonal;
|
|
||||||
static constexpr float AngleRange = FMath::DegreesToRadians(45.0);
|
static constexpr float AngleRange = FMath::DegreesToRadians(45.0);
|
||||||
static constexpr float AnglePrecision = FMath::DegreesToRadians(2.0);
|
static constexpr float AnglePrecision = FMath::DegreesToRadians(2.0);
|
||||||
|
|
||||||
@@ -22,7 +20,7 @@ struct WIZARDINGCENTRAL_API FUniStrokeRecognizer
|
|||||||
~FUniStrokeRecognizer();
|
~FUniStrokeRecognizer();
|
||||||
|
|
||||||
FUniStrokeResult
|
FUniStrokeResult
|
||||||
Recognize(const TArray<FVector2D>& VectorPoints, const bool& UseProtractor);
|
Recognize(const TArray<FVector2D>& VectorPoints);
|
||||||
|
|
||||||
void
|
void
|
||||||
AddTemplate(const FString& Name, const TArray<FVector2D>& VectorPoints);
|
AddTemplate(const FString& Name, const TArray<FVector2D>& VectorPoints);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ FUniStrokeTemplate::FUniStrokeTemplate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
FUniStrokeTemplate::FUniStrokeTemplate(const FString& Name,
|
FUniStrokeTemplate::FUniStrokeTemplate(const FString& Name,
|
||||||
const TArray<FUniStrokePoint>)
|
const TArray<FUniStrokePoint>& Points)
|
||||||
{
|
{
|
||||||
this->Name = Name;
|
this->Name = Name;
|
||||||
this->Points = Points;
|
this->Points = Points;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ struct WIZARDINGCENTRAL_API FUniStrokeTemplate
|
|||||||
|
|
||||||
FUniStrokeTemplate();
|
FUniStrokeTemplate();
|
||||||
FUniStrokeTemplate(const FString& Name,
|
FUniStrokeTemplate(const FString& Name,
|
||||||
const TArray<FUniStrokePoint>);
|
const TArray<FUniStrokePoint>& Points);
|
||||||
~FUniStrokeTemplate();
|
~FUniStrokeTemplate();
|
||||||
|
|
||||||
FString Name;
|
FString Name;
|
||||||
|
|||||||
Reference in New Issue
Block a user