UE4读取脑电波MindWave插件(展示如何使用第三方库制作UE4插件)
Posted 酷熊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4读取脑电波MindWave插件(展示如何使用第三方库制作UE4插件)相关的知识,希望对你有一定的参考价值。
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)); } }
以上是关于UE4读取脑电波MindWave插件(展示如何使用第三方库制作UE4插件)的主要内容,如果未能解决你的问题,请参考以下文章