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几乎已经成为不可或缺的功能,但 ...
随机推荐
- 面向对象 之 [C++面试题]
说到面向对象,大家第一反应应该就是它的三大特性:封装性.继承性和多态性.那么我们先简单的了解一下这三大特性: (1)封装性:封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的 ...
- 基于jQuery带进度条全屏图片轮播代码
基于jQuery带进度条全屏图片轮播代码.这是一款基于jQuery实现的oppo手机官网首页带进度条全屏图片轮播特效.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div ...
- java——关于异常处理机制的简单原理和应用
异常处理机制的简单原理和应用 一.Execption可以分为java标准定义的异常和程序员自定义异常2种 (1)一种是当程序违反了java语规则的时候,JAVA虚拟机就会将发生的错误表示为一个异常.这 ...
- 一、drupal 安装汉化
下载 Drupal 7: 下载语言包文件:到 http://localize.drupal.org/translate/languages/zh-hans 页面下载对应版本的语言包(.po文件) 安装 ...
- linux取随机数shell版本
#!/bin/bash aa=$(-) ..} do useradd $i echo $aa|passwd --stdin $i echo "${i} ${aa}" >> ...
- Entity Framework应用:使用Code First模式管理存储过程
在EF中使用存储过程和使用视图是很相似的,一般会使用Database对象上的两个方法:SqlQuery和ExecuteSqlCommand.为了从存储过程中读取很多数据行,我们只需要定义一个类,我们会 ...
- DataGridView使用技巧三:不显示最下面的新行、判断新增行
一.DataGridView不显示下面的新行 通常DataGridView的最下面一行是用户新追加的行(行头显示*).如果不想让用户新追加行即不想显示该新行,可以将DataGridView对象的All ...
- node-webkit连接mysql
一.安装node.js mysql驱动库 node-webkit里面没有mysql模块的,我们需要安装mysql模块.我们可以使用npm(Node package manager)进行安装.这里使用到 ...
- LoadRunner性能分析指标解释
Transactions(用户事务分析) 用户事务分析是站在用户角度进行的基础性能分析. 1.Transation Sunmmary(事务综述) 对事务进行综合分析是性能分析的第一步,通过分析测试时间 ...
- Windoows窗口程序一
编写窗口程序的步骤: .定义WinMain入口函数 .定义窗口处理函数(处理消息)WindowProc .注册窗口类RegisterClass .创建窗口(在内存中创建窗口)CreateWindow ...