2014-12-07 19:09:38 -05:00
|
|
|
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
2014-05-07 16:36:18 -04:00
|
|
|
|
2015-06-10 10:57:15 -04:00
|
|
|
#include "AnimGraphRuntimePrivatePCH.h"
|
2014-05-07 16:36:18 -04:00
|
|
|
#include "AnimationRuntime.h"
|
2015-06-10 10:57:15 -04:00
|
|
|
#include "BoneControllers/AnimNode_WheelHandler.h"
|
2014-05-29 17:41:46 -04:00
|
|
|
#include "GameFramework/WheeledVehicle.h"
|
|
|
|
|
#include "Vehicles/WheeledVehicleMovementComponent.h"
|
2014-08-01 07:11:46 -04:00
|
|
|
#include "Vehicles/VehicleWheel.h"
|
2014-05-07 16:36:18 -04:00
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
|
// FAnimNode_WheelHandler
|
|
|
|
|
|
|
|
|
|
FAnimNode_WheelHandler::FAnimNode_WheelHandler()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FAnimNode_WheelHandler::GatherDebugData(FNodeDebugData& DebugData)
|
|
|
|
|
{
|
|
|
|
|
FString DebugLine = DebugData.GetNodeName(this);
|
|
|
|
|
|
|
|
|
|
DebugLine += "(";
|
|
|
|
|
AddDebugNodeData(DebugLine);
|
|
|
|
|
DebugLine += ")";
|
|
|
|
|
|
|
|
|
|
DebugData.AddDebugItem(DebugLine);
|
|
|
|
|
for(const auto & WheelSim : WheelSimulators)
|
|
|
|
|
{
|
|
|
|
|
if (WheelSim.BoneReference.BoneIndex != INDEX_NONE)
|
|
|
|
|
{
|
2014-05-07 17:46:48 -04:00
|
|
|
DebugLine = FString::Printf(TEXT(" [Wheel Index : %d] Bone: %s , Rotation Offset : %s, Location Offset : %s"),
|
2014-05-07 16:36:18 -04:00
|
|
|
WheelSim.WheelIndex, *WheelSim.BoneReference.BoneName.ToString(), *WheelSim.RotOffset.ToString(), *WheelSim.LocOffset.ToString());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-05-07 17:46:48 -04:00
|
|
|
DebugLine = FString::Printf(TEXT(" [Wheel Index : %d] Bone: %s (invalid bone)"),
|
2014-05-07 16:36:18 -04:00
|
|
|
WheelSim.WheelIndex, *WheelSim.BoneReference.BoneName.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DebugData.AddDebugItem(DebugLine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ComponentPose.GatherDebugData(DebugData);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-19 06:19:22 -04:00
|
|
|
void FAnimNode_WheelHandler::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
|
2014-05-07 16:36:18 -04:00
|
|
|
{
|
|
|
|
|
check(OutBoneTransforms.Num() == 0);
|
|
|
|
|
|
2015-05-19 06:19:22 -04:00
|
|
|
const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();
|
2014-05-07 16:36:18 -04:00
|
|
|
for(const auto & WheelSim : WheelSimulators)
|
|
|
|
|
{
|
2015-05-19 06:19:22 -04:00
|
|
|
if (WheelSim.BoneReference.IsValid(BoneContainer))
|
2014-05-07 16:36:18 -04:00
|
|
|
{
|
2015-05-19 06:19:22 -04:00
|
|
|
FCompactPoseBoneIndex WheelSimBoneIndex = WheelSim.BoneReference.GetCompactPoseIndex(BoneContainer);
|
|
|
|
|
|
2014-05-07 16:36:18 -04:00
|
|
|
// the way we apply transform is same as FMatrix or FTransform
|
|
|
|
|
// we apply scale first, and rotation, and translation
|
|
|
|
|
// if you'd like to translate first, you'll need two nodes that first node does translate and second nodes to rotate.
|
2015-05-19 06:19:22 -04:00
|
|
|
FTransform NewBoneTM = MeshBases.GetComponentSpaceTransform(WheelSimBoneIndex);
|
2014-05-07 16:36:18 -04:00
|
|
|
|
2015-05-19 06:19:22 -04:00
|
|
|
FAnimationRuntime::ConvertCSTransformToBoneSpace(SkelComp, MeshBases, NewBoneTM, WheelSimBoneIndex, BCS_ComponentSpace);
|
2014-05-07 16:36:18 -04:00
|
|
|
|
|
|
|
|
// Apply rotation offset
|
|
|
|
|
const FQuat BoneQuat(WheelSim.RotOffset);
|
|
|
|
|
NewBoneTM.SetRotation(BoneQuat * NewBoneTM.GetRotation());
|
|
|
|
|
|
|
|
|
|
// Apply loc offset
|
|
|
|
|
NewBoneTM.AddToTranslation(WheelSim.LocOffset);
|
|
|
|
|
|
|
|
|
|
// Convert back to Component Space.
|
2015-05-19 06:19:22 -04:00
|
|
|
FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, NewBoneTM, WheelSimBoneIndex, BCS_ComponentSpace);
|
2014-05-07 16:36:18 -04:00
|
|
|
|
|
|
|
|
// add back to it
|
2015-05-19 06:19:22 -04:00
|
|
|
OutBoneTransforms.Add(FBoneTransform(WheelSimBoneIndex, NewBoneTM));
|
2014-05-07 16:36:18 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-01 14:45:04 -04:00
|
|
|
bool FAnimNode_WheelHandler::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)
|
2014-05-07 16:36:18 -04:00
|
|
|
{
|
|
|
|
|
// if both bones are valid
|
|
|
|
|
for(const auto & WheelSim : WheelSimulators)
|
|
|
|
|
{
|
|
|
|
|
// if one of them is valid
|
|
|
|
|
if (WheelSim.BoneReference.IsValid(RequiredBones) == true)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-01 14:45:04 -04:00
|
|
|
void FAnimNode_WheelHandler::InitializeBoneReferences(const FBoneContainer& RequiredBones)
|
2014-05-07 16:36:18 -04:00
|
|
|
{
|
|
|
|
|
for (auto & WheelSim : WheelSimulators)
|
|
|
|
|
{
|
|
|
|
|
WheelSim.BoneReference.Initialize(RequiredBones);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sort by bone indices
|
|
|
|
|
WheelSimulators.Sort([](FWheelSimulator L, FWheelSimulator R) { return L.BoneReference.BoneIndex < R.BoneReference.BoneIndex; });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FAnimNode_WheelHandler::Update(const FAnimationUpdateContext& Context)
|
|
|
|
|
{
|
|
|
|
|
if(VehicleSimComponent)
|
|
|
|
|
{
|
|
|
|
|
for(auto & WheelSim : WheelSimulators)
|
|
|
|
|
{
|
|
|
|
|
if(VehicleSimComponent->Wheels.IsValidIndex(WheelSim.WheelIndex))
|
|
|
|
|
{
|
|
|
|
|
UVehicleWheel* Wheel = VehicleSimComponent->Wheels[WheelSim.WheelIndex];
|
|
|
|
|
if(Wheel != nullptr)
|
|
|
|
|
{
|
|
|
|
|
WheelSim.RotOffset.Pitch = Wheel->GetRotationAngle();
|
|
|
|
|
WheelSim.RotOffset.Yaw = Wheel->GetSteerAngle();
|
|
|
|
|
WheelSim.RotOffset.Roll = 0.f;
|
|
|
|
|
|
|
|
|
|
WheelSim.LocOffset.X = 0.f;
|
|
|
|
|
WheelSim.LocOffset.Y = 0.f;
|
|
|
|
|
WheelSim.LocOffset.Z = Wheel->GetSuspensionOffset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FAnimNode_SkeletalControlBase::Update(Context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FAnimNode_WheelHandler::Initialize(const FAnimationInitializeContext& Context)
|
|
|
|
|
{
|
|
|
|
|
// TODO: only check vehicle anim instance
|
|
|
|
|
// UVehicleAnimInstance
|
|
|
|
|
AWheeledVehicle * Vehicle = Cast<AWheeledVehicle> ((CastChecked<USkeletalMeshComponent> (Context.AnimInstance->GetOuter()))->GetOwner());
|
|
|
|
|
;
|
|
|
|
|
// we only support vehicle for this class
|
|
|
|
|
if(Vehicle != nullptr)
|
|
|
|
|
{
|
|
|
|
|
VehicleSimComponent = Vehicle->GetVehicleMovementComponent();
|
|
|
|
|
|
|
|
|
|
int32 NumOfwheels = VehicleSimComponent->WheelSetups.Num();
|
|
|
|
|
if(NumOfwheels > 0)
|
|
|
|
|
{
|
|
|
|
|
WheelSimulators.Empty(NumOfwheels);
|
|
|
|
|
WheelSimulators.AddZeroed(NumOfwheels);
|
|
|
|
|
// now add wheel data
|
|
|
|
|
for(int32 WheelIndex = 0; WheelIndex<WheelSimulators.Num(); ++WheelIndex)
|
|
|
|
|
{
|
|
|
|
|
FWheelSimulator & WheelSim = WheelSimulators[WheelIndex];
|
2014-10-01 14:45:04 -04:00
|
|
|
const FWheelSetup& WheelSetup = VehicleSimComponent->WheelSetups[WheelIndex];
|
2014-05-07 16:36:18 -04:00
|
|
|
|
|
|
|
|
// set data
|
|
|
|
|
WheelSim.WheelIndex = WheelIndex;
|
|
|
|
|
WheelSim.BoneReference.BoneName = WheelSetup.BoneName;
|
|
|
|
|
WheelSim.LocOffset = FVector::ZeroVector;
|
|
|
|
|
WheelSim.RotOffset = FRotator::ZeroRotator;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FAnimNode_SkeletalControlBase::Initialize(Context);
|
|
|
|
|
}
|