You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
270 lines
9.9 KiB
C++
270 lines
9.9 KiB
C++
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "AnimPhysicsSolver.h"
|
|
#include "AnimNode_SkeletalControlBase.h"
|
|
#include "AnimNode_AnimDynamics.generated.h"
|
|
|
|
/** Supported angular constraint types */
|
|
UENUM()
|
|
enum class AnimPhysAngularConstraintType : uint8
|
|
{
|
|
Angular,
|
|
Cone
|
|
};
|
|
|
|
/** Supported linear axis constraints */
|
|
UENUM()
|
|
enum class AnimPhysLinearConstraintType : uint8
|
|
{
|
|
Free,
|
|
Limited,
|
|
};
|
|
|
|
/** Helper mapping a rigid body to a bone reference */
|
|
struct FAnimPhysBoneRigidBody
|
|
{
|
|
FAnimPhysBoneRigidBody(TArray<FAnimPhysShape>& Shapes, const FVector& Position, const FBoneReference& LinkedBone)
|
|
: PhysBody(Shapes, Position)
|
|
, BoundBone(LinkedBone)
|
|
{}
|
|
|
|
FAnimPhysRigidBody PhysBody;
|
|
FBoneReference BoundBone;
|
|
};
|
|
|
|
/** Helper describing a body linked to an optional parent (can be nullptr) */
|
|
struct FAnimPhysLinkedBody
|
|
{
|
|
FAnimPhysLinkedBody(TArray<FAnimPhysShape>& Shapes, const FVector& Position, const FBoneReference& LinkedBone)
|
|
: RigidBody(Shapes, Position, LinkedBone)
|
|
, ParentBody(nullptr)
|
|
{}
|
|
|
|
FAnimPhysBoneRigidBody RigidBody;
|
|
FAnimPhysBoneRigidBody* ParentBody;
|
|
};
|
|
|
|
/** Constraint setup struct, holds data required to build a physics constraint */
|
|
USTRUCT()
|
|
struct FAnimPhysConstraintSetup
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
FAnimPhysConstraintSetup()
|
|
: LinearXLimitType(AnimPhysLinearConstraintType::Limited)
|
|
, LinearYLimitType(AnimPhysLinearConstraintType::Limited)
|
|
, LinearZLimitType(AnimPhysLinearConstraintType::Limited)
|
|
, AngularConstraintType(AnimPhysAngularConstraintType::Angular)
|
|
, TwistAxis(AnimPhysTwistAxis::AxisX)
|
|
, ConeAngle(0.0f)
|
|
, AngularXAngle_DEPRECATED(0.0f)
|
|
, AngularYAngle_DEPRECATED(0.0f)
|
|
, AngularZAngle_DEPRECATED(0.0f)
|
|
{}
|
|
|
|
/** Whether to limit the linear X axis */
|
|
UPROPERTY(EditAnywhere, Category = Linear)
|
|
AnimPhysLinearConstraintType LinearXLimitType;
|
|
|
|
/** Whether to limit the linear Y axis */
|
|
UPROPERTY(EditAnywhere, Category = Linear)
|
|
AnimPhysLinearConstraintType LinearYLimitType;
|
|
|
|
/** Whether to limit the linear Z axis */
|
|
UPROPERTY(EditAnywhere, Category = Linear)
|
|
AnimPhysLinearConstraintType LinearZLimitType;
|
|
|
|
/** Minimum linear movement per-axis (Set zero here and in the max limit to lock) */
|
|
UPROPERTY(EditAnywhere, Category = Linear, meta = (UIMax = "0", ClampMax = "0"))
|
|
FVector LinearAxesMin;
|
|
|
|
/** Maximum linear movement per-axis (Set zero here and in the min limit to lock) */
|
|
UPROPERTY(EditAnywhere, Category = Linear, meta = (UIMin = "0", ClampMin = "0"))
|
|
FVector LinearAxesMax;
|
|
|
|
/** Method to use when constraining angular motion */
|
|
UPROPERTY(EditAnywhere, Category = Angular)
|
|
AnimPhysAngularConstraintType AngularConstraintType;
|
|
|
|
/** Axis to consider for twist when constraining angular motion (forward axis) */
|
|
UPROPERTY(EditAnywhere, Category = Angular)
|
|
AnimPhysTwistAxis TwistAxis;
|
|
|
|
/** Angle to use when constraining using a cone */
|
|
UPROPERTY(EditAnywhere, Category = Angular, meta = (UIMin = "0", UIMax = "90", ClampMin = "0", ClampMax = "90"))
|
|
float ConeAngle;
|
|
|
|
/** X-axis limit for angular motion when using the "Angular" constraint type (Set to 0 to lock, or 180 to remain free) */
|
|
UPROPERTY()
|
|
float AngularXAngle_DEPRECATED;
|
|
|
|
/** Y-axis limit for angular motion when using the "Angular" constraint type (Set to 0 to lock, or 180 to remain free) */
|
|
UPROPERTY()
|
|
float AngularYAngle_DEPRECATED;
|
|
|
|
/** Z-axis limit for angular motion when using the "Angular" constraint type (Set to 0 to lock, or 180 to remain free) */
|
|
UPROPERTY()
|
|
float AngularZAngle_DEPRECATED;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Angular, meta = (UIMin = "-180", UIMax = "180", ClampMin = "-180", ClampMax = "180"))
|
|
FVector AngularLimitsMin;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Angular, meta = (UIMin = "-180", UIMax = "180", ClampMin = "-180", ClampMax = "180"))
|
|
FVector AngularLimitsMax;
|
|
|
|
/** Axis on body1 to match to the angular target direction. */
|
|
UPROPERTY(EditAnywhere, Category = Angular)
|
|
AnimPhysTwistAxis AngularTargetAxis;
|
|
|
|
/** Target direction to face for body1 (in body0 local space) */
|
|
UPROPERTY(EditAnywhere, Category = Angular)
|
|
FVector AngularTarget;
|
|
|
|
/** The values below are calculated on initialisation and used when building the limits */
|
|
|
|
/** If all axes are locked we can use 3 linear limits instead of the 6 needed for limited axes */
|
|
UPROPERTY()
|
|
bool bLinearFullyLocked;
|
|
};
|
|
|
|
USTRUCT()
|
|
struct ANIMGRAPHRUNTIME_API FAnimNode_AnimDynamics : public FAnimNode_SkeletalControlBase
|
|
{
|
|
GENERATED_BODY();
|
|
|
|
FAnimNode_AnimDynamics();
|
|
|
|
/** Set to true to use the solver to simulate a connected chain */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
bool bChain;
|
|
|
|
/** The bone to attach the physics body to, if bChain is true this is the top of the chain */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
FBoneReference BoundBone;
|
|
|
|
/** If bChain is true this is the bottom of the chain, otherwise ignored */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup, meta=(EditCondition = bChain))
|
|
FBoneReference ChainEnd;
|
|
|
|
/** Extents of the box to use for simulation */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
FVector BoxExtents;
|
|
|
|
/** Vector relative to the body being simulated to attach the constraint to */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
FVector LocalJointOffset;
|
|
|
|
/** Scale for gravity, higher values increase forces due to gravity */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
float GravityScale;
|
|
|
|
/** If true the body will attempt to spring back to its initial position */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
bool bLinearSpring;
|
|
|
|
/** If true the body will attempt to align itself with the specified angular target */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
bool bAngularSpring;
|
|
|
|
/** Spring constant to use when calculating linear springs, higher values mean a stronger spring.*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
float LinearSpringConstant;
|
|
|
|
/** Spring constant to use when calculating angular springs, higher values mean a stronger spring */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Setup)
|
|
float AngularSpringConstant;
|
|
|
|
/** If true, the override value will be used for linear damping */
|
|
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category = Setup)
|
|
bool bOverrideLinearDamping;
|
|
|
|
/** Overridden linear damping value */
|
|
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category = Setup)
|
|
float LinearDampingOverride;
|
|
|
|
/** If true, the override value will be used for angular damping */
|
|
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category = Setup)
|
|
bool bOverrideAngularDamping;
|
|
|
|
/** Overridden angular damping value */
|
|
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category = Setup)
|
|
float AngularDampingOverride;
|
|
|
|
/** If true we will perform physics update, otherwise skip - allows visualisation of the initial state of the bodies */
|
|
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category = Setup)
|
|
bool bDoUpdate;
|
|
|
|
/** If true we will perform bone transform evaluation, otherwise skip - allows visualisation of the initial anim state compared to the physics sim */
|
|
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category = Setup)
|
|
bool bDoEval;
|
|
|
|
/** Number of update passes on the linear and angular limits before we solve the position of the bodies recommended to be four times the value of NumSolverIterationsPostUpdate */
|
|
UPROPERTY(EditAnywhere, AdvancedDisplay, Category = Setup)
|
|
int32 NumSolverIterationsPreUpdate;
|
|
|
|
/** Number of update passes on the linear and angular limits after we solve the position of the bodies, recommended to be around a quarter of NumSolverIterationsPreUpdate */
|
|
UPROPERTY(EditAnywhere, AdvancedDisplay, Category = Setup)
|
|
int32 NumSolverIterationsPostUpdate;
|
|
|
|
/** Data describing the constraints we will apply to the body */
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Constraint)
|
|
FAnimPhysConstraintSetup ConstraintSetup;
|
|
|
|
// FAnimNode_SkeletalControlBase interface
|
|
virtual void Initialize(const FAnimationInitializeContext& Context) override;
|
|
virtual void Update(const FAnimationUpdateContext& Context) override;
|
|
virtual void EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms) override;
|
|
virtual void GatherDebugData(FNodeDebugData& DebugData) override;
|
|
// End of FAnimNode_SkeletalControlBase interface
|
|
|
|
void RequestInitialise() { bRequiresInit = true; }
|
|
void InitPhysics(USkeletalMeshComponent* Component, FCSPose<FCompactPose>& MeshBases);
|
|
void TermPhysics();
|
|
|
|
void UpdateLimits(FCSPose<FCompactPose>& MeshBases);
|
|
|
|
int32 GetNumBodies() const;
|
|
const FAnimPhysRigidBody& GetPhysBody(int32 BodyIndex) const;
|
|
|
|
protected:
|
|
|
|
// FAnimNode_SkeletalControlBase protected interface
|
|
virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;
|
|
virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones);
|
|
// End of FAnimNode_SkeletalControlBase protected interface
|
|
|
|
private:
|
|
|
|
// We can't get clean bone positions unless we are in the evaluate step.
|
|
// Requesting an init or reinit sets this flag for us to pick up during evaluate
|
|
bool bRequiresInit;
|
|
|
|
// Maximum time to consider when accumulating time debt to avoid spiraling
|
|
static const float MaxTimeDebt;
|
|
|
|
// Cached timestep from the update phase (needed in evaluate phase)
|
|
float NextTimeStep;
|
|
|
|
// Current amount of time debt
|
|
float TimeDebt;
|
|
|
|
// Active body list
|
|
TArray<FAnimPhysLinkedBody> Bodies;
|
|
|
|
// List of current linear limits built for the current frame
|
|
TArray<FAnimPhysLinearLimit> LinearLimits;
|
|
|
|
// List of current angular limits built for the current frame
|
|
TArray<FAnimPhysAngularLimit> AngularLimits;
|
|
|
|
// List of spring force generators created for this frame
|
|
TArray<FAnimPhysSpring> Springs;
|
|
|
|
// Local space offsets for each body
|
|
TArray<FVector> JointOffsets;
|
|
|
|
// List of bone references for all bodies in this node
|
|
TArray<FBoneReference> BoundBoneReferences;
|
|
}; |