├── .gitignore ├── Config ├── DefaultEditor.ini ├── DefaultEngine.ini └── DefaultGame.ini ├── Content ├── BP_Epic.uasset ├── BP_RadToEpicRemapAsset.uasset ├── BP_Radical.uasset ├── EpicGames_Mannequin │ ├── Animations │ │ ├── AnimBP_EpicGames_Mannequin_Skeleton.uasset │ │ ├── P_EpicGames_Mannequin_RADiCAL-T-Pose.uasset │ │ └── SK_EpicGames_Mannequin_Skeleton_Sequence.uasset │ ├── Materials │ │ ├── M_UE4Man_Body.uasset │ │ ├── M_UE4Man_ChestLogo.uasset │ │ └── MaterialLayers │ │ │ ├── ML_GlossyBlack_Latex_UE4.uasset │ │ │ ├── ML_Plastic_Shiny_Beige.uasset │ │ │ ├── ML_Plastic_Shiny_Beige_LOGO.uasset │ │ │ ├── ML_SoftMetal_UE4.uasset │ │ │ ├── T_ML_Aluminum01.uasset │ │ │ ├── T_ML_Aluminum01_N.uasset │ │ │ ├── T_ML_Rubber_Blue_01_D.uasset │ │ │ └── T_ML_Rubber_Blue_01_N.uasset │ ├── Mesh │ │ ├── SK_EpicGames_Mannequin.uasset │ │ ├── SK_EpicGames_Mannequin_PhysicsAsset.uasset │ │ └── SK_EpicGames_Mannequin_Skeleton.uasset │ └── Textures │ │ ├── UE4Man_Logo_N.uasset │ │ ├── UE4_LOGO_CARD.uasset │ │ ├── UE4_Mannequin_MAT_MASKA.uasset │ │ └── UE4_Mannequin__normals.uasset ├── Mixamo │ ├── A_Mixamo_T-Pose.uasset │ ├── AnimBP_Mixamo.uasset │ ├── SKEL_Mixamo.uasset │ ├── SK_Mixamo.uasset │ └── lambert2.uasset ├── RADiCAL_Mannequin │ ├── A_RADiCAL_3-1_T-Pose.uasset │ ├── AnimBP_RADiCAL_3-1.uasset │ ├── M_UE4Man_Body.uasset │ ├── NewMaterial.uasset │ ├── SKEL_RADiCAL_3-1.uasset │ └── SK_RADiCAL_3-1.uasset └── TestMap.umap ├── Mixamo_Mesh.fbx ├── RADiCAL_3-1_Mesh.FBX ├── README.md ├── Source ├── UnrealLLSample_31.Target.cs ├── UnrealLLSample_31 │ ├── RadToEpicRemapAsset.cpp │ ├── RadToEpicRemapAsset.h │ ├── RadToMixamoRemapAsset.cpp │ ├── RadToMixamoRemapAsset.h │ ├── RadToRadRemapAsset.cpp │ ├── RadToRadRemapAsset.h │ ├── RadicalLiveLinkRemapAssetBase.cpp │ ├── RadicalLiveLinkRemapAssetBase.h │ ├── UnrealLLSample_31.Build.cs │ ├── UnrealLLSample_31.cpp │ └── UnrealLLSample_31.h └── UnrealLLSample_31Editor.Target.cs ├── Tutorial_Images └── install_dotnet.png └── UnrealLLSample_31.uproject /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2015 user specific files 2 | .vs/ 3 | .idea/ 4 | 5 | # Compiled Object files 6 | *.slo 7 | *.lo 8 | *.o 9 | *.obj 10 | 11 | # Precompiled Headers 12 | *.gch 13 | *.pch 14 | 15 | # Compiled Dynamic libraries 16 | *.so 17 | *.dylib 18 | *.dll 19 | 20 | # Fortran module files 21 | *.mod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | *.ipa 34 | 35 | # These project files can be generated by the engine 36 | *.xcodeproj 37 | *.xcworkspace 38 | *.sln 39 | *.suo 40 | *.opensdf 41 | *.sdf 42 | *.VC.db 43 | *.VC.opendb 44 | 45 | # Precompiled Assets 46 | SourceArt/**/*.png 47 | SourceArt/**/*.tga 48 | 49 | # Binary Files 50 | Binaries/* 51 | Plugins/*/Binaries/* 52 | 53 | # Builds 54 | Build/* 55 | 56 | # Whitelist PakBlacklist-.txt files 57 | !Build/*/ 58 | Build/*/** 59 | !Build/*/PakBlacklist*.txt 60 | 61 | # Don't ignore icon files in Build 62 | !Build/**/*.ico 63 | 64 | # Built data for maps 65 | *_BuiltData.uasset 66 | 67 | # Configuration files generated by the Editor 68 | Saved/* 69 | 70 | # Compiled source files for the engine to use 71 | Intermediate/* 72 | Plugins/*/Intermediate/* 73 | 74 | # Cache files for the editor to use 75 | DerivedDataCache/* 76 | -------------------------------------------------------------------------------- /Config/DefaultEditor.ini: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | 2 | 3 | [/Script/HardwareTargeting.HardwareTargetingSettings] 4 | TargetedHardwareClass=Desktop 5 | AppliedTargetedHardwareClass=Desktop 6 | DefaultGraphicsPerformance=Maximum 7 | AppliedDefaultGraphicsPerformance=Maximum 8 | 9 | [/Script/Engine.Engine] 10 | +ActiveGameNameRedirects=(OldGameName="TP_BlankBP",NewGameName="/Script/UnrealLLSample_31") 11 | +ActiveGameNameRedirects=(OldGameName="/Script/TP_BlankBP",NewGameName="/Script/UnrealLLSample_31") 12 | 13 | [/Script/EngineSettings.GameMapsSettings] 14 | EditorStartupMap=/Game/TestMap.TestMap 15 | GameDefaultMap=/Game/TestMap.TestMap 16 | 17 | -------------------------------------------------------------------------------- /Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | 2 | 3 | [/Script/EngineSettings.GeneralProjectSettings] 4 | ProjectID=10B79974493AC7C6042AB1877528F0BA 5 | -------------------------------------------------------------------------------- /Content/BP_Epic.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/BP_Epic.uasset -------------------------------------------------------------------------------- /Content/BP_RadToEpicRemapAsset.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/BP_RadToEpicRemapAsset.uasset -------------------------------------------------------------------------------- /Content/BP_Radical.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/BP_Radical.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Animations/AnimBP_EpicGames_Mannequin_Skeleton.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Animations/AnimBP_EpicGames_Mannequin_Skeleton.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Animations/P_EpicGames_Mannequin_RADiCAL-T-Pose.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Animations/P_EpicGames_Mannequin_RADiCAL-T-Pose.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Animations/SK_EpicGames_Mannequin_Skeleton_Sequence.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Animations/SK_EpicGames_Mannequin_Skeleton_Sequence.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/M_UE4Man_Body.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/M_UE4Man_Body.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/M_UE4Man_ChestLogo.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/M_UE4Man_ChestLogo.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/MaterialLayers/ML_GlossyBlack_Latex_UE4.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/MaterialLayers/ML_GlossyBlack_Latex_UE4.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/MaterialLayers/ML_Plastic_Shiny_Beige.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/MaterialLayers/ML_Plastic_Shiny_Beige.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/MaterialLayers/ML_Plastic_Shiny_Beige_LOGO.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/MaterialLayers/ML_Plastic_Shiny_Beige_LOGO.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/MaterialLayers/ML_SoftMetal_UE4.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/MaterialLayers/ML_SoftMetal_UE4.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/MaterialLayers/T_ML_Aluminum01.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/MaterialLayers/T_ML_Aluminum01.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/MaterialLayers/T_ML_Aluminum01_N.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/MaterialLayers/T_ML_Aluminum01_N.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/MaterialLayers/T_ML_Rubber_Blue_01_D.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/MaterialLayers/T_ML_Rubber_Blue_01_D.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Materials/MaterialLayers/T_ML_Rubber_Blue_01_N.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Materials/MaterialLayers/T_ML_Rubber_Blue_01_N.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Mesh/SK_EpicGames_Mannequin.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Mesh/SK_EpicGames_Mannequin.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Mesh/SK_EpicGames_Mannequin_PhysicsAsset.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Mesh/SK_EpicGames_Mannequin_PhysicsAsset.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Mesh/SK_EpicGames_Mannequin_Skeleton.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Mesh/SK_EpicGames_Mannequin_Skeleton.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Textures/UE4Man_Logo_N.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Textures/UE4Man_Logo_N.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Textures/UE4_LOGO_CARD.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Textures/UE4_LOGO_CARD.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Textures/UE4_Mannequin_MAT_MASKA.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Textures/UE4_Mannequin_MAT_MASKA.uasset -------------------------------------------------------------------------------- /Content/EpicGames_Mannequin/Textures/UE4_Mannequin__normals.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/EpicGames_Mannequin/Textures/UE4_Mannequin__normals.uasset -------------------------------------------------------------------------------- /Content/Mixamo/A_Mixamo_T-Pose.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/Mixamo/A_Mixamo_T-Pose.uasset -------------------------------------------------------------------------------- /Content/Mixamo/AnimBP_Mixamo.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/Mixamo/AnimBP_Mixamo.uasset -------------------------------------------------------------------------------- /Content/Mixamo/SKEL_Mixamo.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/Mixamo/SKEL_Mixamo.uasset -------------------------------------------------------------------------------- /Content/Mixamo/SK_Mixamo.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/Mixamo/SK_Mixamo.uasset -------------------------------------------------------------------------------- /Content/Mixamo/lambert2.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/Mixamo/lambert2.uasset -------------------------------------------------------------------------------- /Content/RADiCAL_Mannequin/A_RADiCAL_3-1_T-Pose.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/RADiCAL_Mannequin/A_RADiCAL_3-1_T-Pose.uasset -------------------------------------------------------------------------------- /Content/RADiCAL_Mannequin/AnimBP_RADiCAL_3-1.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/RADiCAL_Mannequin/AnimBP_RADiCAL_3-1.uasset -------------------------------------------------------------------------------- /Content/RADiCAL_Mannequin/M_UE4Man_Body.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/RADiCAL_Mannequin/M_UE4Man_Body.uasset -------------------------------------------------------------------------------- /Content/RADiCAL_Mannequin/NewMaterial.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/RADiCAL_Mannequin/NewMaterial.uasset -------------------------------------------------------------------------------- /Content/RADiCAL_Mannequin/SKEL_RADiCAL_3-1.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/RADiCAL_Mannequin/SKEL_RADiCAL_3-1.uasset -------------------------------------------------------------------------------- /Content/RADiCAL_Mannequin/SK_RADiCAL_3-1.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/RADiCAL_Mannequin/SK_RADiCAL_3-1.uasset -------------------------------------------------------------------------------- /Content/TestMap.umap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Content/TestMap.umap -------------------------------------------------------------------------------- /Mixamo_Mesh.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Mixamo_Mesh.fbx -------------------------------------------------------------------------------- /RADiCAL_3-1_Mesh.FBX: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/RADiCAL_3-1_Mesh.FBX -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Live Link to Unreal Sample Project 2 | 3 | This project has example code for live streaming pose data from Radical Studio to Unreal Engine (version 4.25). Note: to open this sample project, you must have **Visual Studio** and the **Game Development with C++** module installed. See [this guide](https://docs.unrealengine.com/en-US/Programming/Development/VisualStudioSetup/index.html) for more information. 4 | 5 | You will also additionally need .NET SDK installed to build the project. You can modify your Visual Studio installation as follows: 6 | ![.NET installation](Tutorial_Images/install_dotnet.png) 7 | 8 | See the `BP_RADiCAL` and `AnimBP_RADiCAL_3-1` assets for a demonstration of real-time LiveLink retargeting to the RADiCAL skeleton (v3.1). 9 | 10 | The can be retargeted in real-time to the Epic skeleton as well, which allows you to use Marketplace characters that are rigged using the Epic skeleton. See the `BP_Epic` and `AnimBP_EpicGames_Mannequin_Skeleton` assets for more details. 11 | 12 | There is also a work-in-progress example of retargeting to the Mixamo skeleton (see `AnimBP_Mixamo`), which shows how to manipulate the live link data in the Event Graph and pass it into the AnimGraph for individual bone transforms. 13 | 14 | Using post-recording Animation Retargeting, recorded Live Link data can also be retargeted to other skeletons with good results. 15 | 16 | ### Live Link Setup 17 | After starting the Live Link stream from Radical Studio, open the UE4 editor and go to Window -> Live Link. Go to Source -> Message Bus Source -> select the `RadLiveLink` source. There will be a random alphanumeric string appended to the name, to differentiate between multiple Live Link sources on the network (e.g. other instances of Radical Studio). You can now close this window. 18 | 19 | ### Live Link Preview 20 | The Live Link data can be previewed inside the Skeleton, Skeletal Mesh, Blueprint or Animation Blueprint windows for a given skeletal asset. On the right side, go to Preview Scene Settings, under Animation, change the Preview Controller to Live Link Preview Controller. Then, change the Live Link Subject Name to `RadicalPose`. 21 | For Retarget Asset, select the corresponding blueprint Remap Asset file for that skeleton. For example, for the Radical skeleton, choose the `RadToRadRemap` asset. For the Epic skeleton, choose the `BP_RadToEpicRemapAsset`. 22 | 23 | ### Remap Assets 24 | In order to use skeletons other than the Radical skeleton, we need to remap the Radical skeleton's bone names to their counterparts on other skeletons. For example, if you open the `BP_RadToEpicRemap` asset and go to the `GetRemappedBoneName` function, you can see a big switch statement that performs the remapping. For Mixamo, the skeleton bone names match the RADiCAL skeleton bone names, so this step is unnecessary. 25 | 26 | ### Rotation conversions 27 | To account for some of the differences between the Radical Studio coordinate frame and Unreal, we have flipped the incoming LiveLink data's rotation and position axes. You can inspect the conversions at the `RadicalLiveLinkRemapAssetBase` class and its child classes. We expect that other skeletons will require different rotation adjustments, including swapping axes. We exposed three overridable methods to implement the root bone position, root bone rotation, and non-root bone rotation conversions. Please note that the AI output in Radical Studio uses the hip bone as a root, so position data should be mapped to the hips (or pelvis) in the target skeleton. 28 | 29 | ### Real-time Remapping/Retargeting 30 | To remap the LiveLink data (which matches RADiCAL 3.1 skeleton structure) to other skeletons, modifications to the bone rotations may be required. The incoming LiveLink data contains rotation offsets from the RADiCAL's base T-pose, and hip position. For the Epic skeleton, we tweaked the arm rotations in the AnimBP, as the Epic skeleton uses an A pose by default. For the Mixamo skeleton, there are more complex differences, such as an inverted rotation for the the `LeftUpLeg` bone's Y axis (among others). 31 | 32 | ### Post-recording Remapping/Retargeting 33 | Unreal provides built-in tools for retargeting existing animations (i.e. animations created with Take Recorder, or imported FBX) to other skeletons. Once the animation asset is produced, you can retarget to any other skeleton by setting up the Retarget Manager and ensuring that both the source and target skeletons have a T-Pose. Please see our [FBX Retargeting Project](https://github.com/get-rad/Unreal_FBX_Retarget) for more details. 34 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class UnrealLLSample_31Target : TargetRules 7 | { 8 | public UnrealLLSample_31Target(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Game; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | 13 | ExtraModuleNames.AddRange( new string[] { "UnrealLLSample_31" } ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/RadToEpicRemapAsset.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "RadToEpicRemapAsset.h" 5 | 6 | FVector URadToEpicRemapAsset::ConvertRootPosition(FVector LLPosition) const 7 | { 8 | // Unreal uses cm, so apply x100 conversion factor 9 | return 100 * FVector( 10 | LLPosition.X, 11 | LLPosition.Z, 12 | LLPosition.Y 13 | ); 14 | } 15 | 16 | FQuat URadToEpicRemapAsset::ConvertRootRotation(FQuat LLRotation) const 17 | { 18 | return FQuat( 19 | -LLRotation.Y, 20 | -LLRotation.Z, 21 | LLRotation.X, 22 | LLRotation.W 23 | ); 24 | 25 | return FQuat( 26 | -LLRotation.X, 27 | LLRotation.Z, 28 | -LLRotation.Y, 29 | LLRotation.W 30 | ); 31 | } 32 | 33 | FQuat URadToEpicRemapAsset::ConvertBoneRotation(FQuat LLRotation) const 34 | { 35 | return FQuat( 36 | -LLRotation.X, 37 | LLRotation.Y, 38 | -LLRotation.Z, 39 | LLRotation.W 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/RadToEpicRemapAsset.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RadicalLiveLinkRemapAssetBase.h" 7 | 8 | #include "RadToEpicRemapAsset.generated.h" 9 | 10 | /** 11 | * 12 | */ 13 | UCLASS() 14 | class UNREALLLSAMPLE_31_API URadToEpicRemapAsset : public URadicalLiveLinkRemapAssetBase 15 | { 16 | GENERATED_BODY() 17 | 18 | protected: 19 | virtual FVector ConvertRootPosition(FVector LLPosition) const override; 20 | 21 | virtual FQuat ConvertRootRotation(FQuat LLRotation) const override; 22 | 23 | virtual FQuat ConvertBoneRotation(FQuat LLRotation) const override; 24 | 25 | virtual FName GetTargetRootName() const override { return "pelvis";} 26 | }; 27 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/RadToMixamoRemapAsset.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "RadToMixamoRemapAsset.h" 5 | 6 | FVector URadToMixamoRemapAsset::ConvertRootPosition(FVector LLPosition) const 7 | { 8 | // Unreal uses cm, so apply x100 conversion factor 9 | return 100 * FVector( 10 | LLPosition.X, 11 | -LLPosition.Y, 12 | LLPosition.Z 13 | ); 14 | } 15 | 16 | FQuat URadToMixamoRemapAsset::ConvertRootRotation(FQuat LLRotation) const 17 | { 18 | return FQuat( 19 | -LLRotation.Y, 20 | -LLRotation.X, 21 | -LLRotation.Z, 22 | LLRotation.W 23 | ); 24 | } 25 | 26 | FQuat URadToMixamoRemapAsset::ConvertBoneRotation(FQuat LLRotation) const 27 | { 28 | return FQuat( 29 | -LLRotation.X, 30 | LLRotation.Y, 31 | -LLRotation.Z, 32 | LLRotation.W 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/RadToMixamoRemapAsset.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RadicalLiveLinkRemapAssetBase.h" 7 | #include "RadToMixamoRemapAsset.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UNREALLLSAMPLE_31_API URadToMixamoRemapAsset : public URadicalLiveLinkRemapAssetBase 14 | { 15 | GENERATED_BODY() 16 | virtual FVector ConvertRootPosition(FVector LLPosition) const override; 17 | 18 | virtual FQuat ConvertRootRotation(FQuat LLRotation) const override; 19 | 20 | virtual FQuat ConvertBoneRotation(FQuat LLRotation) const override; 21 | }; 22 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/RadToRadRemapAsset.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "RadToRadRemapAsset.h" 5 | 6 | FVector URadToRadRemapAsset::ConvertRootPosition(FVector LLPosition) const 7 | { 8 | // Unreal uses cm, so apply x100 conversion factor 9 | return 100 * FVector( 10 | LLPosition.X, 11 | -LLPosition.Y, 12 | LLPosition.Z 13 | ); 14 | 15 | } 16 | 17 | FQuat URadToRadRemapAsset::ConvertRootRotation(FQuat LLRotation) const 18 | { 19 | return FQuat( 20 | -LLRotation.X, 21 | LLRotation.Y, 22 | -LLRotation.Z, 23 | LLRotation.W 24 | ); 25 | } 26 | 27 | FQuat URadToRadRemapAsset::ConvertBoneRotation(FQuat LLRotation) const 28 | { 29 | return FQuat( 30 | -LLRotation.X, 31 | LLRotation.Y, 32 | -LLRotation.Z, 33 | LLRotation.W 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/RadToRadRemapAsset.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "RadicalLiveLinkRemapAssetBase.h" 7 | 8 | #include "RadToRadRemapAsset.generated.h" 9 | 10 | /** 11 | * 12 | */ 13 | UCLASS() 14 | class UNREALLLSAMPLE_31_API URadToRadRemapAsset : public URadicalLiveLinkRemapAssetBase 15 | { 16 | GENERATED_BODY() 17 | 18 | protected: 19 | virtual FVector ConvertRootPosition(FVector LLPosition) const override; 20 | 21 | virtual FQuat ConvertRootRotation(FQuat LLRotation) const override; 22 | 23 | virtual FQuat ConvertBoneRotation(FQuat LLRotation) const override; 24 | }; 25 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/RadicalLiveLinkRemapAssetBase.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "RadicalLiveLinkRemapAssetBase.h" 5 | 6 | 7 | #include "Roles/LiveLinkAnimationTypes.h" 8 | #include "BonePose.h" 9 | 10 | 11 | // Take Live Link data and apply it to skeleton bones in UE4. 12 | void URadicalLiveLinkRemapAssetBase::BuildPoseFromAnimationData(float DeltaTime, 13 | const FLiveLinkSkeletonStaticData* InSkeletonData, 14 | const FLiveLinkAnimationFrameData* InFrameData, 15 | FCompactPose& OutPose) 16 | { 17 | const TArray& SourceBoneNames = InSkeletonData->BoneNames; 18 | 19 | TArray> TransformedBoneNames; 20 | TransformedBoneNames.Reserve(SourceBoneNames.Num()); 21 | 22 | // Find remapped bone names and cache them for fast subsequent retrieval. 23 | for (const FName& SrcBoneName : SourceBoneNames) 24 | { 25 | FName* TargetBoneName = BoneNameMap.Find(SrcBoneName); 26 | if (TargetBoneName == nullptr) 27 | { 28 | /* User will create a blueprint child class and implement this function using a switch statement. */ 29 | FName NewName = GetRemappedBoneName(SrcBoneName); 30 | TransformedBoneNames.Add(NewName); 31 | BoneNameMap.Add(SrcBoneName, NewName); 32 | } 33 | else 34 | { 35 | TransformedBoneNames.Add(*TargetBoneName); 36 | } 37 | } 38 | 39 | // Iterate over remapped bone names, find the index of that bone on the skeleton, and apply the Live Link pose data. 40 | for (int32 i = 0; i < TransformedBoneNames.Num(); i++) 41 | { 42 | FName BoneName = TransformedBoneNames[i]; 43 | FTransform BoneTransform = InFrameData->Transforms[i]; 44 | const int32 MeshIndex = OutPose.GetBoneContainer().GetPoseBoneIndexForBoneName(BoneName); 45 | if (MeshIndex != INDEX_NONE) 46 | { 47 | FCompactPoseBoneIndex CPIndex = OutPose.GetBoneContainer().MakeCompactPoseIndex( 48 | FMeshPoseBoneIndex(MeshIndex)); 49 | if (CPIndex != INDEX_NONE) 50 | { 51 | FQuat ConvertedLiveLinkRotation; 52 | // Only use position + rotation data for root. For all other bones, set rotation only. 53 | if (BoneName == GetTargetRootName()) 54 | { 55 | OutPose[CPIndex].SetLocation(ConvertRootPosition(BoneTransform.GetTranslation())); 56 | ConvertedLiveLinkRotation = ConvertRootRotation(BoneTransform.GetRotation()); 57 | } 58 | else 59 | { 60 | ConvertedLiveLinkRotation = ConvertBoneRotation(BoneTransform.GetRotation()); 61 | } 62 | // Retrieves the default reference pose for the skeleton. Live Link data contains relative transforms from the default pose. 63 | auto RefBoneTransform = OutPose.GetRefPose(CPIndex); 64 | 65 | OutPose[CPIndex].SetRotation(RefBoneTransform.GetRotation() * ConvertedLiveLinkRotation); 66 | } 67 | } 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/RadicalLiveLinkRemapAssetBase.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "LiveLinkRemapAsset.h" 7 | #include "RadicalLiveLinkRemapAssetBase.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class UNREALLLSAMPLE_31_API URadicalLiveLinkRemapAssetBase : public ULiveLinkRemapAsset 14 | { 15 | GENERATED_BODY() 16 | 17 | virtual void BuildPoseFromAnimationData(float DeltaTime, const FLiveLinkSkeletonStaticData* InSkeletonData, 18 | const FLiveLinkAnimationFrameData* InFrameData, 19 | FCompactPose& OutPose) override; 20 | protected: 21 | // Override these in child classes 22 | virtual FVector ConvertRootPosition(FVector LLPosition) const { return LLPosition; }; 23 | virtual FQuat ConvertRootRotation(FQuat LLRotation) const { return LLRotation; }; 24 | virtual FQuat ConvertBoneRotation(FQuat LLRotation) const { return LLRotation; }; 25 | 26 | // This is the bone we will apply position translation to. 27 | // Radical 3.1 Live Link position data is mapped to the hips. 28 | // For other skeletons, the hip bone's name can differ and you can override this method. 29 | virtual FName GetTargetRootName() const { return "Hips"; } 30 | 31 | // Cached lookup results from GetRemappedBoneName 32 | TMap BoneNameMap; 33 | }; 34 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/UnrealLLSample_31.Build.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class UnrealLLSample_31 : ModuleRules 6 | { 7 | public UnrealLLSample_31(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); 12 | 13 | PrivateDependencyModuleNames.AddRange(new string[] { }); 14 | 15 | // Uncomment if you are using Slate UI 16 | // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 17 | 18 | // Uncomment if you are using online features 19 | // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 20 | 21 | // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/UnrealLLSample_31.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "UnrealLLSample_31.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, UnrealLLSample_31, "UnrealLLSample_31" ); 7 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31/UnrealLLSample_31.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | -------------------------------------------------------------------------------- /Source/UnrealLLSample_31Editor.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class UnrealLLSample_31EditorTarget : TargetRules 7 | { 8 | public UnrealLLSample_31EditorTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Editor; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | 13 | ExtraModuleNames.AddRange( new string[] { "UnrealLLSample_31" } ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Tutorial_Images/install_dotnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/get-rad/unrealLLsample_31/8d1f25771363cd980dc1bc6364ca45f487914ba5/Tutorial_Images/install_dotnet.png -------------------------------------------------------------------------------- /UnrealLLSample_31.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "4.25", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "UnrealLLSample_31", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default", 11 | "AdditionalDependencies": [ 12 | "LiveLink" 13 | ] 14 | } 15 | ], 16 | "Plugins": [ 17 | { 18 | "Name": "LiveLink", 19 | "Enabled": true 20 | } 21 | ] 22 | } --------------------------------------------------------------------------------