您的位置:首页 > 产品设计 > UI/UE

UE4读取脑电波MindWave插件(展示如何使用第三方库制作UE4插件)

2017-07-13 14:20 639 查看


MyEEGPlugin.uplugin

{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "MyEEGPlugin",
"Description": "",
"Category": "Other",
"CreatedBy": "",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"Installed": false,
"Modules": [
{
"Name": "MyEEGPlugin",
"Type": "Runtime",
"LoadingPhase": "Default"
}
]
}


MyEEGPlugin.Build.cs

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;
using System.IO;

public class MyEEGPlugin : ModuleRules
{
public MyEEGPlugin(TargetInfo Target)
{

PublicIncludePaths.AddRange(
new string[] {
"MyEEGPlugin/Public"
// ... add public include paths required here ...
}
);

PrivateIncludePaths.AddRange(
new string[] {
"MyEEGPlugin/Private",
// ... add other private include paths required here ...
}
);

PublicDependencyModuleNames.AddRange(
new string[]
{
"Core", "CoreUObject", "Engine", "InputCore", "Projects"
// ... add other public dependencies that you statically link with here ...
}
);

PrivateDependencyModuleNames.AddRange(
new string[]
{
// ... add private dependencies that you statically link with here ...
}
);

DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);

LoadThinkGearLib(Target);//添加第三方库
//LoadAlgoSdkDll(Target);//添加第三方库
}

private string ThirdPartyPath
{
get
{
return Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty/"));
}
}

public void LoadThinkGearLib(TargetInfo Target)
{
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
{
string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "64" : "";
string LibrariesPath = Path.Combine(ThirdPartyPath, "ThinkGear", "lib");

//test your path
System.Console.WriteLine("... LibrariesPath -> " + LibrariesPath);

PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "ThinkGear", "include"));
PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "thinkgear" + PlatformString + ".lib"));
}

//Definitions.Add(string.Format("MY_DEFINE={0}", 0));
}

public void LoadAlgoSdkDll(TargetInfo Target)
{
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
{
string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "64" : "";
string DllPath = Path.Combine(ThirdPartyPath, "bin", "AlgoSdkDll" + PlatformString + ".dll");

PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "EEGAlgoSDK", "include"));
PublicDelayLoadDLLs.Add(DllPath);
//RuntimeDependencies.Add(new RuntimeDependency(DllPath));
}
}

}


MyEEGPlugin.h

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "ModuleManager.h"

class FMyEEGPluginModule : public IModuleInterface
{
public:

/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;

private:
/** Handle to the test dll we will load */
void*    ExampleLibraryHandle;
};


MyEEGPlugin.cpp

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#include "MyEEGPlugin.h"
#include "Core.h"
#include "ModuleManager.h"
#include "IPluginManager.h"
//#include "ExampleLibrary.h"

#define LOCTEXT_NAMESPACE "FMyEEGPluginModule"

void FMyEEGPluginModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module

// Get the base directory of this plugin
FString BaseDir = IPluginManager::Get().FindPlugin("MyEEGPlugin")->GetBaseDir();

// Add on the relative location of the third party dll and load it
FString LibraryPath;
#if PLATFORM_WINDOWS
LibraryPath = FPaths::Combine(*BaseDir, TEXT("Binaries/ThirdParty/MyEEGPluginLibrary/Win64/ExampleLibrary.dll"));
#elif PLATFORM_MAC
LibraryPath = FPaths::Combine(*BaseDir, TEXT("Source/ThirdParty/MyEEGPluginLibrary/Mac/Release/libExampleLibrary.dylib"));
#endif // PLATFORM_WINDOWS

ExampleLibraryHandle = !LibraryPath.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPath) : nullptr;

if (ExampleLibraryHandle)
{
// Call the test function in the third party library that opens a message box
//ExampleLibraryFunction();
}
else
{
//FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("ThirdPartyLibraryError", "Failed to load example third party library"));
}
}

void FMyEEGPluginModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
// we call this function before unloading the module.

// Free the dll handle
FPlatformProcess::FreeDllHandle(ExampleLibraryHandle);
ExampleLibraryHandle = nullptr;
}

#undef LOCTEXT_NAMESPACE

IMPLEMENT_MODULE(FMyEEGPluginModule, MyEEGPlugin)


MyEEGReceiver.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once
#include "Engine.h"
#include "GameFramework/Actor.h"
#include "MyEEGReceiver.generated.h"

UCLASS()
class AMyEEGReceiver : public AActor
{
GENERATED_BODY()

public:
// Sets default values for this actor's properties
AMyEEGReceiver();

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
int rawDataIndex;
int lerpDataIndex;
float totalAngle;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float v;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float s;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float a;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
TArray<float> rawAttentions;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
TArray<float> rawMeditations;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
TArray<float> lerpAttentions;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
TArray<float> lerpMeditations;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float attention1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float attention2;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float meditation1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
float meditation2;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;

/** Called whenever this actor is being removed from a level */
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

UFUNCTION(BlueprintImplementableEvent, Category = "EEG")
void BPEvent_GetNewAttention(float newAttention);

UFUNCTION(BlueprintCallable, Category = "EEG")
void IndexFunc();

UFUNCTION(BlueprintCallable, Category = "EEG")
void ComputeNewPos(float factor, UStaticMeshComponent* cube, float DeltaTime, float scaleFactorAtten=1, float scaleFactorMedi = 1, bool debug=false);

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
int32 LatestMeditation;        //最新放松度
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
int32 LatestAttention;        //最新专注度

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EEG")
bool ShowOnScreenDebugMessages;

FORCEINLINE void ScreenMsg(const FString& Msg)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg);
}
FORCEINLINE void ScreenMsg(const FString& Msg, const int32 Value)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %d"), *Msg, Value));
}
};


MyEEGReceiver.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyEEGPlugin.h"
#include "MyEEGReceiver.h"
#include "thinkgear.h"

#define NUM 3
// Sets default values
AMyEEGReceiver::AMyEEGReceiver()
{
// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;

ShowOnScreenDebugMessages = true;
v = 0; a = 1; s = 0;
rawDataIndex = 0;
lerpDataIndex = 0;
rawAttentions.Init(0, NUM);
rawMeditations.Init(0, NUM);
totalAngle = 0;
}

long raw_data_count = 0;
short *raw_data = NULL;
bool bRunning = false;
bool bInited = false;
char *comPortName = NULL;
int   dllVersion = 0;
int   connectionId = -1;
int   packetsRead = 0;
int   errCode = 0;
bool bConnectedHeadset = false;

// Called when the game starts or when spawned
void AMyEEGReceiver::BeginPlay()
{
Super::BeginPlay();

/* Print driver version number */
dllVersion = TG_GetVersion();
ScreenMsg("ThinkGear DLL version:",dllVersion);
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("ThinkGear DLL version: %d\n"), dllVersion));
/* Get a connection ID handle to ThinkGear */
connectionId = TG_GetNewConnectionId();
if (connectionId < 0) {
ScreenMsg("Failed to new connection ID");
}
else {
/* Attempt to connect the connection ID handle to serial port "COM5" */
/* NOTE: On Windows, COM10 and higher must be preceded by \\.\, as in
*       "\\\\.\\COM12" (must escape backslashes in strings).  COM9
*       and lower do not require the \\.\, but are allowed to include
*       them.  On Mac OS X, COM ports are named like
*       "/dev/tty.MindSet-DevB-1".
*/
comPortName = "\\\\.\\COM6";
errCode = TG_Connect(connectionId,
comPortName,
TG_BAUD_57600,
TG_STREAM_PACKETS);
if (errCode < 0)
{
ScreenMsg("TG_Connect() failed", errCode);
}
else
{
ScreenMsg("TG_Connect OK",connectionId);
}
}

}

// Called every frame
void AMyEEGReceiver::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

v = v + a*DeltaTime;
s += v*DeltaTime;
/* Read all currently available Packets, one at a time... */
do {
/* Read a single Packet from the connection */
packetsRead = TG_ReadPackets(connectionId, 1);

/* If TG_ReadPackets() was able to read a Packet of data... */
if (packetsRead == 1) {
//ScreenMsg("TG_ReadPackets");
/* If the Packet containted a new raw wave value... */
if (TG_GetValueStatus(connectionId, TG_DATA_RAW) != 0) {
int rawData = (int)TG_GetValue(connectionId, TG_DATA_RAW);
//ScreenMsg("TG_DATA_RAW",rawData);
} /* end "If Packet contained a raw wave value..." */

if (TG_GetValueStatus(connectionId, TG_DATA_POOR_SIGNAL) != 0) {
int ps=TG_GetValue(connectionId, TG_DATA_POOR_SIGNAL);
//ScreenMsg("TG_DATA_POOR_SIGNAL",ps);
}

if (TG_GetValueStatus(connectionId, TG_DATA_MEDITATION) != 0) {
float medi = TG_GetValue(connectionId, TG_DATA_MEDITATION);
LatestMeditation = (int32)medi;
//ScreenMsg("TG_DATA_MEDITATION", LatestMeditation);
rawMeditations[rawDataIndex] = medi;
float total = 0;
for (int i = 0; i < NUM; i++)
total += rawMeditations[i];
float avg_medi = total / NUM;
lerpMeditations.Add(avg_medi);
}

if (TG_GetValueStatus(connectionId, TG_DATA_ATTENTION) != 0) {
float atten = TG_GetValue(connectionId, TG_DATA_ATTENTION);
LatestAttention = (int32)atten;
rawAttentions[rawDataIndex] = atten;
float total = 0;
for (int i = 0; i < NUM; i++)
total += rawAttentions[i];
float avg_atten = total / NUM;
lerpAttentions.Add(avg_atten);

rawDataIndex++;
if (rawDataIndex == NUM)
{
rawDataIndex = 0;
}

ScreenMsg("avg_atten", avg_atten);
//BPEvent_GetNewAttention(TG_GetValue(connectionId, TG_DATA_ATTENTION));
//float atten=TG_GetValue(connectionId, TG_DATA_ATTENTION);
//float delta = atten - s;
//a = delta;
ScreenMsg("TG_DATA_ATTENTION", LatestAttention);
//ScreenMsg("delta", delta);
//ScreenMsg("s", s);
}

} /* end "If TG_ReadPackets() was able to read a Packet..." */

} while (packetsRead > 0); /* Keep looping until all Packets read */
}

void AMyEEGReceiver::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);

/* Clean up */
TG_FreeConnection(connectionId);
}

void AMyEEGReceiver::IndexFunc()
{
int lerpNum = lerpAttentions.Num();
if (lerpNum ==0)
return;
int idx1 = lerpDataIndex - 1;
int idx2 = lerpDataIndex;
idx1 = FMath::Max(idx1,0);
idx2 = FMath::Min(idx2, lerpNum-1);
attention1 = lerpAttentions[idx1];
attention2 = lerpAttentions[idx2];
meditation1 = lerpMeditations[idx1];
meditation2 = lerpMeditations[idx2];
if (lerpDataIndex < lerpNum-1)
{
lerpDataIndex++;
}
}

void AMyEEGReceiver::ComputeNewPos(float factor, UStaticMeshComponent* cube, float DeltaTime,
float scaleFactorAtten/*=1*/, float scaleFactorMedi/* = 1*/, bool debug/* = false*/)
{
float tmpAtten = FMath::Lerp(attention1, attention2, factor);
float tmpMedit = FMath::Lerp(meditation1, meditation2, factor);
static float testTime = 0;
if (debug)
{
tmpMedit = 50 + sin(testTime) * 50;
tmpAtten = 50 + sin(testTime) * 50; testTime += DeltaTime;
}
float s0 = tmpMedit*DeltaTime*scaleFactorMedi;
FVector oldPos = cube->GetComponentLocation();
float angle = FMath::Atan(s0 / (oldPos.Size()));
FVector normalVec = oldPos.GetSafeNormal();
FVector newPos = normalVec*(10000 + tmpAtten*scaleFactorAtten);
cube->SetWorldLocation(newPos.RotateAngleAxis(FMath::RadiansToDegrees(angle),FVector(0,1,0)));
FRotator Rotator = FRotator::ZeroRotator;
totalAngle += FMath::RadiansToDegrees(angle);
Rotator.Add(-totalAngle, 0, 0);
if (totalAngle >= 360)
{
totalAngle = 0;
}
cube->SetWorldRotation(Rotator);
UTextRenderComponent* text = dynamic_cast<UTextRenderComponent*>(cube->GetChildComponent(0));
if (text)
{
FString t1 = FString::FromInt(tmpAtten);
FString t2 = FString::FromInt(tmpMedit);
FString t3 = FString::FromInt(totalAngle);
FString tmp(", ");
tmp = t1 + tmp + t2;
text->SetText(FText::FromString(tmp));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: