• 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
    "), 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));
        }
    }
  • 相关阅读:
    Python
    Django
    Markdown基础教程
    LR之Oracle 2tier协议录制Oracle脚本
    Python实现自动连接密码本破解wifi
    LoadRunner替换url字符串(可以同时替换多个)
    LoadRunner接口HTTP请求中中文乱码解决方案
    在WSL2中安装ArchLinux
    解决FastJson中"$ref重复引用"的问题方法
    java 后台通过IO流把文件传到前端并下载
  • 原文地址:https://www.cnblogs.com/coolbear/p/7160262.html
Copyright © 2020-2023  润新知