From ef097dfcc43f4e3327d7bbdb7c3d1deb72a8a7b4 Mon Sep 17 00:00:00 2001 From: David Hibbitts Date: Mon, 22 Jan 2018 23:03:45 +0000 Subject: [PATCH] Cameras now come in with the correct Unreal Orientation Fixed a bug where modifying the scene (renames, moves, etc.) would cause objects to add duplicate BoneNames and BoneParents to their Subject Added support for Mirroring the active Camera in the Animation Preview via EditorActiveCamera --- Source/Private/MobuLiveLinkDevice.cpp | 6 +- Source/Private/MobuLiveLinkLayout.cpp | 17 +++-- Source/Public/StreamStore.h | 25 ++++++- Source/StreamObjects/CameraStreamObject.cpp | 8 ++- .../EditorActiveCameraStreamObject.cpp | 70 +++++++++++++++++++ Source/StreamObjects/GenericStreamObject.cpp | 6 +- Source/StreamObjects/LightStreamObject.cpp | 6 +- Source/StreamObjects/StreamObjectBase.cpp | 49 ++++++++++++- 8 files changed, 168 insertions(+), 19 deletions(-) create mode 100644 Source/StreamObjects/EditorActiveCameraStreamObject.cpp diff --git a/Source/Private/MobuLiveLinkDevice.cpp b/Source/Private/MobuLiveLinkDevice.cpp index a7544a51..21541287 100644 --- a/Source/Private/MobuLiveLinkDevice.cpp +++ b/Source/Private/MobuLiveLinkDevice.cpp @@ -57,6 +57,9 @@ bool MobuLiveLink::FBCreate() SetDirty(false); + TSharedPtr EditorCamera((StreamObjectBase*)(new EditorActiveCameraStreamObject(LiveLinkProvider))); + StreamObjects.Emplace((kReference)nullptr, EditorCamera); + return true; } @@ -278,8 +281,7 @@ void MobuLiveLink::UpdateStreamObjects() { for (auto MapPair : StreamObjects) { - bool bInScene = FBSystem().Scene->Components.Find((FBComponent*)MapPair.Value->RootModel) >= 0; - if (bInScene) + if (MapPair.Value->IsValid()) { MapPair.Value->UpdateFromModel(); } diff --git a/Source/Private/MobuLiveLinkLayout.cpp b/Source/Private/MobuLiveLinkLayout.cpp index ae8fb5f5..40d36be4 100644 --- a/Source/Private/MobuLiveLinkLayout.cpp +++ b/Source/Private/MobuLiveLinkLayout.cpp @@ -165,14 +165,17 @@ void MobuLiveLinkLayout::EventUIIdle(HISender Sender, HKEvent Event) void MobuLiveLinkLayout::AddSpreadRowFromStreamObject(StreamObjectPtr Object) { - StreamSpread.RowAdd(Object->RootModel->LongName, (kReference)Object->RootModel); + const FBModel* RootModel = Object->GetRootModel(); + if (RootModel == nullptr) return; - StreamSpread.SetCell((kReference)Object->RootModel, 0, FStringToChar(Object->GetSubjectName().ToString())); - StreamSpread.SetCell((kReference)Object->RootModel, 1, FStringToChar(Object->GetStreamOptions())); - StreamSpread.SetCell((kReference)Object->RootModel, 1, Object->GetStreamingMode()); + StreamSpread.RowAdd(RootModel->LongName, (kReference)RootModel); + + StreamSpread.SetCell((kReference)RootModel, 0, FStringToChar(Object->GetSubjectName().ToString())); + StreamSpread.SetCell((kReference)RootModel, 1, FStringToChar(Object->GetStreamOptions())); + StreamSpread.SetCell((kReference)RootModel, 1, Object->GetStreamingMode()); bool bIsActive = Object->GetActiveStatus(); - StreamSpread.SetCell((kReference)Object->RootModel, 2, bIsActive); - StreamSpread.SetCell((kReference)Object->RootModel, 2, BoolToActiveText(bIsActive)); + StreamSpread.SetCell((kReference)RootModel, 2, bIsActive); + StreamSpread.SetCell((kReference)RootModel, 2, BoolToActiveText(bIsActive)); } @@ -224,7 +227,7 @@ void MobuLiveLinkLayout::EventRemoveFromStream(HISender Sender, HKEvent Event) DeletionObjects.Reserve(LiveLinkDevice->StreamObjects.Num()); for (const auto& MapPair : LiveLinkDevice->StreamObjects) { - kReference RowKey = (kReference)MapPair.Value->RootModel; + kReference RowKey = (kReference)MapPair.Value->GetRootModel(); bool bRowSelected = StreamSpread.GetRow(RowKey).RowSelected; if (bRowSelected) { diff --git a/Source/Public/StreamStore.h b/Source/Public/StreamStore.h index 6f164282..097434fc 100644 --- a/Source/Public/StreamStore.h +++ b/Source/Public/StreamStore.h @@ -13,8 +13,6 @@ class StreamObjectBase { public: - const FBModel* RootModel; - virtual ~StreamObjectBase(); // Optional Interface for modifying class parameters @@ -33,6 +31,10 @@ class StreamObjectBase virtual void UpdateActiveStatus(bool bIsNowActive); + virtual const FBModel* GetRootModel(); + + virtual bool IsValid(); + // Required Interface for object streaming virtual void UpdateFromModel() = 0; @@ -45,9 +47,12 @@ class StreamObjectBase static FTransform MobuTransformToUnreal(FBMatrix& MobuTransfrom); static FTransform UnrealTransformFromModel(FBModel* MobuModel, bool bIsGlobal = true); + static FTransform UnrealTransformFromCamera(FBCamera* CameraModel); protected: + const FBModel* RootModel; + const TSharedPtr Provider; const TArray ConnectionOptions; @@ -57,8 +62,11 @@ class StreamObjectBase int StreamingMode; bool bIsActive; + StreamObjectBase(const FBModel* ModelPointer, const TSharedPtr StreamProvider, std::initializer_list Options); + // model-less constructor + StreamObjectBase(const FName InSubjectName, const TSharedPtr StreamProvider); }; // Generic object that only supports a single transform (Nulls, Cubes, etc.) @@ -100,6 +108,19 @@ class SkeletonHeirarchyStreamObject : public StreamObjectBase public: SkeletonHeirarchyStreamObject(const FBModel* ModelPointer, const TSharedPtr StreamProvider); + void UpdateFromModel() override; + void GetStreamData() override; +}; + + +// Streams the Active Editor Camera wrapper +class EditorActiveCameraStreamObject : public StreamObjectBase +{ +public: + EditorActiveCameraStreamObject(const TSharedPtr StreamProvider); + + bool IsValid() override; + void UpdateFromModel() override; void GetStreamData() override; }; \ No newline at end of file diff --git a/Source/StreamObjects/CameraStreamObject.cpp b/Source/StreamObjects/CameraStreamObject.cpp index 132c28f0..9b4d58f6 100644 --- a/Source/StreamObjects/CameraStreamObject.cpp +++ b/Source/StreamObjects/CameraStreamObject.cpp @@ -8,8 +8,10 @@ CameraStreamObject::CameraStreamObject(const FBModel* ModelPointer, const TShare void CameraStreamObject::UpdateFromModel() { - BoneNames.Emplace(FName("Bone01")); - BoneParents.Emplace(0); + BoneNames.SetNum(1); + BoneNames[0] = FName("Bone01"); + BoneParents.SetNum(1); + BoneParents[0] = -1; Provider->UpdateSubject(SubjectName, BoneNames, BoneParents); } @@ -22,7 +24,7 @@ void CameraStreamObject::GetStreamData() FBCamera* CameraModel = (FBCamera*)RootModel; // Single Bone - BoneTransforms.Emplace(UnrealTransformFromModel(CameraModel)); + BoneTransforms.Emplace(UnrealTransformFromCamera(CameraModel)); TArray CurveData; // If Streaming as Camera then get the Camera Properties diff --git a/Source/StreamObjects/EditorActiveCameraStreamObject.cpp b/Source/StreamObjects/EditorActiveCameraStreamObject.cpp new file mode 100644 index 00000000..42b62303 --- /dev/null +++ b/Source/StreamObjects/EditorActiveCameraStreamObject.cpp @@ -0,0 +1,70 @@ +#include "StreamStore.h" + +EditorActiveCameraStreamObject::EditorActiveCameraStreamObject(const TSharedPtr StreamProvider) + : StreamObjectBase(FName(TEXT("EditorActiveCamera")), StreamProvider) +{ + UpdateFromModel(); +} + +bool EditorActiveCameraStreamObject::IsValid() +{ + return true; +} + +void EditorActiveCameraStreamObject::UpdateFromModel() +{ + BoneNames.SetNum(1); + BoneNames[0] = FName("root"); + + BoneParents.SetNum(1); + BoneParents[0] = -1; + + Provider->UpdateSubject(SubjectName, BoneNames, BoneParents); +} + +void EditorActiveCameraStreamObject::GetStreamData() +{ + if (!bIsActive) return; + + FBSystem System; + FBCamera* CameraModel = System.Scene->Renderer->CurrentCamera; + + TArray BoneTransforms; + + // Single Bone + BoneTransforms.Emplace(UnrealTransformFromCamera(CameraModel)); + + TArray CurveData; + + CurveData.SetNum(9); + + CurveData[0].CurveName = FName(TEXT("FieldOfViewX")); + CurveData[0].CurveValue = CameraModel->FieldOfViewX; + + CurveData[1].CurveName = FName(TEXT("FieldOfViewY")); + CurveData[1].CurveValue = CameraModel->FieldOfViewY; + + CurveData[2].CurveName = FName(TEXT("FieldOfView")); + CurveData[2].CurveValue = CameraModel->FieldOfView; + + CurveData[3].CurveName = FName(TEXT("FocalLength")); + CurveData[3].CurveValue = CameraModel->FocalLength; + + CurveData[4].CurveName = FName(TEXT("FocusSpecificDistance")); + CurveData[4].CurveValue = CameraModel->FocusSpecificDistance; + + CurveData[5].CurveName = FName(TEXT("NearPlaneDistance")); + CurveData[5].CurveValue = CameraModel->NearPlaneDistance; + + CurveData[6].CurveName = FName(TEXT("FarPlaneDistance")); + CurveData[6].CurveValue = CameraModel->FarPlaneDistance; + + CurveData[7].CurveName = FName(TEXT("FilmSizeWidth")); + CurveData[7].CurveValue = CameraModel->FilmSizeWidth; + + CurveData[8].CurveName = FName(TEXT("FilmSizeHeight")); + CurveData[8].CurveValue = CameraModel->FilmSizeHeight; + + FBTime LocalTime = FBSystem().LocalTime; + Provider->UpdateSubjectFrame(SubjectName, BoneTransforms, CurveData, LocalTime.GetSecondDouble(), LocalTime.GetFrame()); +} \ No newline at end of file diff --git a/Source/StreamObjects/GenericStreamObject.cpp b/Source/StreamObjects/GenericStreamObject.cpp index f89fbed3..e5e49fe4 100644 --- a/Source/StreamObjects/GenericStreamObject.cpp +++ b/Source/StreamObjects/GenericStreamObject.cpp @@ -8,8 +8,10 @@ GenericStreamObject::GenericStreamObject(const FBModel* ModelPointer, const TSha void GenericStreamObject::UpdateFromModel() { - BoneNames.Emplace(FName("Bone01")); - BoneParents.Emplace(0); + BoneNames.SetNum(1); + BoneNames[0] = FName("Bone01"); + BoneParents.SetNum(1); + BoneParents[0] = -1; Provider->UpdateSubject(SubjectName, BoneNames, BoneParents); }; diff --git a/Source/StreamObjects/LightStreamObject.cpp b/Source/StreamObjects/LightStreamObject.cpp index c21a0ff1..3cdefc22 100644 --- a/Source/StreamObjects/LightStreamObject.cpp +++ b/Source/StreamObjects/LightStreamObject.cpp @@ -8,8 +8,10 @@ LightStreamObject::LightStreamObject(const FBModel* ModelPointer, const TSharedP void LightStreamObject::UpdateFromModel() { - BoneNames.Emplace(FName("Bone01")); - BoneParents.Emplace(0); + BoneNames.SetNum(1); + BoneNames[0] = FName("Bone01"); + BoneParents.SetNum(1); + BoneParents[0] = -1; Provider->UpdateSubject(SubjectName, BoneNames, BoneParents); }; diff --git a/Source/StreamObjects/StreamObjectBase.cpp b/Source/StreamObjects/StreamObjectBase.cpp index d8bfddb1..c75119de 100644 --- a/Source/StreamObjects/StreamObjectBase.cpp +++ b/Source/StreamObjects/StreamObjectBase.cpp @@ -11,6 +11,12 @@ StreamObjectBase::StreamObjectBase(const FBModel* ModelPointer, const TSharedPtr SubjectName = FName(*ModelLongName); }; +// Model-less constructor +StreamObjectBase::StreamObjectBase(const FName InSubjectName, const TSharedPtr StreamProvider) + : RootModel(nullptr), SubjectName(InSubjectName), Provider(StreamProvider), bIsActive(true), StreamingMode(0) +{ +}; + StreamObjectBase::~StreamObjectBase() { Provider->ClearSubject(SubjectName); @@ -59,10 +65,22 @@ void StreamObjectBase::UpdateActiveStatus(bool bIsNowActive) UpdateFromModel(); }; +const FBModel* StreamObjectBase::GetRootModel() +{ + return RootModel; +}; + +bool StreamObjectBase::IsValid() +{ + // By Default an object is valid if the root model is in the scene + return FBSystem().Scene->Components.Find((FBComponent*)GetRootModel()) >= 0; +}; + // Equality comparison -bool StreamObjectBase::operator==(const StreamObjectBase &other) const { +bool StreamObjectBase::operator==(const StreamObjectBase &other) const +{ return (this->RootModel == other.RootModel); }; @@ -120,6 +138,35 @@ FTransform StreamObjectBase::UnrealTransformFromModel(FBModel* MobuModel, bool b return MobuTransformToUnreal(MobuTransform); }; +FTransform StreamObjectBase::UnrealTransformFromCamera(FBCamera* CameraModel) +{ + // MotionBuilder suggests that GetMatrix is deprecated for Cameras and to + // reconstruct from the Camera Matrices explicitly + + FBMatrix ModelView; + FBMatrix MatOffset; + + CameraModel->GetCameraMatrix(ModelView, FBCameraMatrixType::kFBModelView, nullptr); + FBMatrix InvModelView = ModelView.Inverse(); + + // Y-Up Correction + FBRVector RotOffset(90, 0, 0); + FBRotationToMatrix(MatOffset, RotOffset); + FBMatrixMult(ModelView, MatOffset, ModelView); + + // Camera is now in Unreal Space + FTransform CameraTransform = MobuTransformToUnreal(ModelView); + + // Mobu Cameras look down a different axis so flip them here + // TODO: Consolidate with MobuTransformToUnreal so we're not repeating work + FQuat CameraRotation = CameraTransform.GetRotation(); + FQuat LensRotation; + LensRotation.MakeFromEuler(FVector(-90, -90, 0)); + CameraTransform.SetRotation(CameraRotation * LensRotation); + + return CameraTransform; +} +