UE4读取脑电波MindWave插件(展示如何使用第三方库制作UE4插件)
MyEEGPlugin.uplugin
{
"FileVersion": ,
"Version": ,
"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) ? "" : "";
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) ? "" : "";
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=, float scaleFactorMedi = , 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(-, .f, FColor::Red, *Msg);
}
FORCEINLINE void ScreenMsg(const FString& Msg, const int32 Value)
{
if (!ShowOnScreenDebugMessages) return;
GEngine->AddOnScreenDebugMessage(-, .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 = ; a = ; s = ;
rawDataIndex = ;
lerpDataIndex = ;
rawAttentions.Init(, NUM);
rawMeditations.Init(, NUM);
totalAngle = ;
} long raw_data_count = ;
short *raw_data = NULL;
bool bRunning = false;
bool bInited = false;
char *comPortName = NULL;
int dllVersion = ;
int connectionId = -;
int packetsRead = ;
int errCode = ;
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 < ) {
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 < )
{
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, ); /* If TG_ReadPackets() was able to read a Packet of data... */
if (packetsRead == ) {
//ScreenMsg("TG_ReadPackets");
/* If the Packet containted a new raw wave value... */
if (TG_GetValueStatus(connectionId, TG_DATA_RAW) != ) {
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) != ) {
int ps=TG_GetValue(connectionId, TG_DATA_POOR_SIGNAL);
//ScreenMsg("TG_DATA_POOR_SIGNAL",ps);
} if (TG_GetValueStatus(connectionId, TG_DATA_MEDITATION) != ) {
float medi = TG_GetValue(connectionId, TG_DATA_MEDITATION);
LatestMeditation = (int32)medi;
//ScreenMsg("TG_DATA_MEDITATION", LatestMeditation);
rawMeditations[rawDataIndex] = medi;
float total = ;
for (int i = ; i < NUM; i++)
total += rawMeditations[i];
float avg_medi = total / NUM;
lerpMeditations.Add(avg_medi);
} if (TG_GetValueStatus(connectionId, TG_DATA_ATTENTION) != ) {
float atten = TG_GetValue(connectionId, TG_DATA_ATTENTION);
LatestAttention = (int32)atten;
rawAttentions[rawDataIndex] = atten;
float total = ;
for (int i = ; i < NUM; i++)
total += rawAttentions[i];
float avg_atten = total / NUM;
lerpAttentions.Add(avg_atten); rawDataIndex++;
if (rawDataIndex == NUM)
{
rawDataIndex = ;
} 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 > ); /* 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 ==)
return;
int idx1 = lerpDataIndex - ;
int idx2 = lerpDataIndex;
idx1 = FMath::Max(idx1,);
idx2 = FMath::Min(idx2, lerpNum-);
attention1 = lerpAttentions[idx1];
attention2 = lerpAttentions[idx2];
meditation1 = lerpMeditations[idx1];
meditation2 = lerpMeditations[idx2];
if (lerpDataIndex < lerpNum-)
{
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 = ;
if (debug)
{
tmpMedit = + sin(testTime) * ;
tmpAtten = + sin(testTime) * ; 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*( + tmpAtten*scaleFactorAtten);
cube->SetWorldLocation(newPos.RotateAngleAxis(FMath::RadiansToDegrees(angle),FVector(,,)));
FRotator Rotator = FRotator::ZeroRotator;
totalAngle += FMath::RadiansToDegrees(angle);
Rotator.Add(-totalAngle, , );
if (totalAngle >= )
{
totalAngle = ;
}
cube->SetWorldRotation(Rotator);
UTextRenderComponent* text = dynamic_cast<UTextRenderComponent*>(cube->GetChildComponent());
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插件)的更多相关文章
- 常用iOS第三方库以及XCode插件介绍
第三方库 CocoaPod CocoaPod并不是iOS上的第三方库 而是大名鼎鼎的第三方库的管理工具 在CocoaPod没有出现之前 第三方库的管理是非常痛苦的 尤其是一些大型的库(比如nimbus ...
- 个人常用iOS第三方库以及XCode插件介绍
第三方库 CocoaPod CocoaPod并不是iOS上的第三方库 而是大名鼎鼎的第三方库的管理工具 在CocoaPod没有出现之前 第三方库的管理是非常痛苦的 尤其是一些大型的库(比如nimbus ...
- 【转】个人常用iOS第三方库以及XCode插件介绍 -- 不错
原文网址:http://adad184.com/2015/07/08/my-favorite-libraries-and-plugins/ 第三方库是现在的程序员离不开的东西 不光是APP开发 基本上 ...
- iOS之第三方库以及XCode插件介绍
前言 第三方库是现在的程序员离不开的东西 不光是APP开发 基本上所有的商业项目 都会或多或少的使用到第三方库 Github上Star>100的开源库数量如下 可以看到JS以绝对的优势排名第一 ...
- python 技巧 之 pyCharm快速添加第三方库和插件
学习python有几个月,安装第三方库都是通过 pip install 或者 easy_install.每次都要打开命令行感觉太麻烦.还好Pycharm提供了安装第三方库和安装插件的功能. 首先打开P ...
- UE4读取scv文件 -- 数据驱动游戏性元素
官方文档链接:http://docs.unrealengine.com/latest/CHN/Gameplay/DataDriven/index.html 略懒,稍微麻烦重复的工作,总希望能找人帮忙一 ...
- 使用python制作ArcGIS插件(6)案例分析
利用ArcPy制作航空制图插件 By 李远祥 这是笔者两年多前写的一个面向航路图做的一个插件,基本上将航路图的制作进行流程化,制作成为可交互的插件,只要有航路和机场的信息,就可以直接生成一个航路图,每 ...
- iOS 第三方库、插件、知名博客总结
iOS 第三方库.插件.知名博客总结 用到的组件 1.通过CocoaPods安装 项目名称 项目信息 AFNetworking 网络请求组件 FMDB 本地数据库组件 SDWebImage 多个缩略图 ...
- UE4使用第三方库读写xml文件
原文链接:http://gad.qq.com/article/detail/7181031 本文首发腾讯GAD开发者平台,未经允许,不得转载 在游戏开发过程中,读写xml几乎已经成为不可或缺的功能,但 ...
随机推荐
- vim添加复制(crtl+c),粘贴(ctrl+v)ctrl+A 等快捷键
1 在 /usr/share/vim/vimrc文件中添加 source $VIMRUNTIME/mswin.vim 2 mswin.vim位置在 /usr/share/vim/vim72/ ...
- pionter指针小结
第七章.指针和函数的关系 可以把一个指针声明成为一个指向函数的指针. intfun1(char*,int); int(*pfun1)(char*,int); pfun1=fun1; .... .... ...
- SQL server 2005如何设置一个或几个字段唯一约束?
--建立是在三个字段上的唯一约束 alter table Tab add constraint uq_id unique(shipType, shipsession, Territory)
- Accumulator
Accumulator简介 Accumulator是spark提供的累加器,顾名思义,该变量只能够增加. 只有driver能获取到Accumulator的值(使用value方法),Task只能对其做增 ...
- Jdbc获取oracle中guid主键
上代码 String sql = "BEGIN insert into itil_task_plan (PLAN_CODE) values (?) returning id into ?; ...
- MyEclipse SVN 下面切换用户的解决方案
configuration\org.eclipse.core.runtime\.keyring 删除MyEclipse下面的文件. 或者修改服务器端的用户密码.
- yarn是什么?为什么会产生yarn,它解决了什么问题?以及yarn的执行流程
yarn是什么?为什么会产生yarn,它解决了什么问题? 答:yarn是作业调度和集群资源管理的一个框架. 首先对之前的Hadoop 和 MRv1 简单介绍如下: Hadoop 集群可从单一节点 ...
- 修改jdk
(一)修改jdk的path: (二)修改eclipse里面的jre环境 (三)修改具体项目的jre环境 build path -> config build path (四)修改服务运行环境
- e586. Drawing Simple Shapes
There are two ways to draw basic shapes like circles, ovals, lines, arcs, squares, rectangles, round ...
- OpenCV_基于局部自适应阈值的图像二值化
在图像处理应用中二值化操作是一个很常用的处理方式,例如零器件图片的处理.文本图片和验证码图片中字符的提取.车牌识别中的字符分割,以及视频图像中的运动目标检测中的前景分割,等等. 较为常用的图像二值化方 ...