Files
2025-05-18 13:04:45 +08:00

482 lines
15 KiB
C

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "RigPhysicsBodyComponent.h"
#include "RigPhysicsSolverComponent.h"
#include "RigPhysicsSimulation.h"
#include "PhysicsControlData.h"
#include "Units/Execution/RigUnit_DynamicHierarchy.h"
#include "RigPhysicsExecution.generated.h"
#define UE_API CONTROLRIGPHYSICS_API
/**
* Base struct for all other mutable physics nodes
*/
USTRUCT(meta = (Category = "RigPhysics", NodeColor = "1.0 0.6 0.3", Keywords = "Physics"))
struct FRigUnit_PhysicsBaseMutable: public FRigUnitMutable
{
GENERATED_BODY()
};
/**
* Base struct for all other non-mutable physics nodes
*/
USTRUCT(meta = (Category = "RigPhysics", NodeColor = "1.0 0.6 0.3", Keywords = "Physics"))
struct FRigUnit_PhysicsBase : public FRigUnit
{
GENERATED_BODY()
};
/**
* Adds a new physics solver as a component on the owner element.
* Note: This node only runs as part of the construction event.
*/
USTRUCT(meta=(DisplayName="Add Physics Solver Component", Keywords="Spawn,Construction,Create,New,Simulation", Varying))
struct FRigUnit_AddPhysicsSolver : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_AddPhysicsSolver()
{
Owner.Type = ERigElementType::Bone;
// Default the material here to have friction and restitution. Then the interactions are
// easily adjusted on the dynamic bodies.
SolverSettings.Collision.Material.Friction = 1.0f;
SolverSettings.Collision.Material.Restitution = 1.0f;
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
/**
* The owner of the newly created component (must be set/valid)
*/
UPROPERTY(meta = (Input, BoneName))
FRigElementKey Owner;
UPROPERTY(meta = (Output))
FRigComponentKey PhysicsSolverComponentKey;
UPROPERTY(meta = (Input))
FRigPhysicsSolverSettings SolverSettings;
UPROPERTY(meta = (Input))
FRigPhysicsSimulationSpaceSettings SimulationSpaceSettings;
};
/**
* Instantiates all the objects in the physics world. Some properties can't be modified after this happens.
* Note that it will happen automatically during the first simulation step if it hasn't been explicitly
* requested. Explicit instantiation allows the timing to be controlled, as allocations etc may cause some
* delays.
*/
USTRUCT(meta = (DisplayName = "Instantiate physics"))
struct FRigUnit_InstantiatePhysics : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_InstantiatePhysics()
{
PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
/*
* The solver to relate this new physics element to
*/
UPROPERTY(meta = (Input))
FRigComponentKey PhysicsSolverComponentKey;
};
/**
* Steps the specified physics solver
*/
USTRUCT(meta = (DisplayName = "Step Physics Solver", Keywords = "Simulate"))
struct FRigUnit_StepPhysicsSolver : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_StepPhysicsSolver()
{
PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
// The physics solver
UPROPERTY(meta = (Input))
FRigComponentKey PhysicsSolverComponentKey;
// If this is zero, then the execute context time will be used. If this is positive then it will
// override the delta time. A negative value will prevent the solver from stepping, but there will
// still be update costs associated with the node.
UPROPERTY(meta = (Input))
float DeltaTimeOverride = 0.0f;
// If this is zero, then the simulation delta time will be used for evaluating movement of the
// simulation space. If this is positive then it will override. This may be needed if the
// component movement is being done in parallel, in which case you might need to pass in the
// previous time delta here.
UPROPERTY(meta = (Input, ClampMin = "0.0"))
float SimulationSpaceDeltaTimeOverride = 0.0f;
// How much of the simulation is combined with the input bone. This currently happens in
// component space. Note that the simulation will continue to run, even if alpha = 0
UPROPERTY(meta = (Input, ClampMin = "0.0", ClampMax = "1.0"))
float Alpha = 1.0f;
UPROPERTY(meta = (Input))
FRigPhysicsVisualizationSettings VisualizationSettings;
};
// Sets all the simulation space settings on the solver
USTRUCT(meta = (DisplayName = "Set Physics Solver Simulation Space Settings"))
struct FRigUnit_SetPhysicsSolverSimulationSpaceSettings : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_SetPhysicsSolverSimulationSpaceSettings()
{
PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
// The physics solver
UPROPERTY(meta = (Input))
FRigComponentKey PhysicsSolverComponentKey;
// The new simulation space settings
UPROPERTY(meta = (Input))
FRigPhysicsSimulationSpaceSettings SimulationSpaceSettings;
};
// Sets the external velocity of the simulation - used for adding wind effects
USTRUCT(meta = (DisplayName = "Set Physics Solver External Velocity"))
struct FRigUnit_SetPhysicsSolverExternalVelocity : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_SetPhysicsSolverExternalVelocity()
{
PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
// The physics solver
UPROPERTY(meta = (Input))
FRigComponentKey PhysicsSolverComponentKey;
// Additional velocity that is added to the component velocity so the simulation acts as if the
// actor is moving at speed, even when stationary. The vector is in world space. This could be
// used for wind effects etc. Typical values are similar to the velocity of the object or
// effect, and usually around or less than 1000 for characters/wind.
UPROPERTY(meta = (Input))
FVector ExternalLinearVelocity = FVector::ZeroVector;
// Additional angular velocity that is added to the component angular velocity. This can be used
// to make the simulation act as if the actor is rotating even when it is not. E.g., to apply
// physics to a character on a podium as the camera rotates around it, to emulate the podium
// itself rotating. Vector is in world space. Units are deg/s.
UPROPERTY(meta = (Input))
FVector ExternalAngularVelocity = FVector::ZeroVector;
// This will treat the external velocity like a wind field and add turbulence to it. Units are
// the same as velocity, so this is the approximate magnitude of the turbulence.
UPROPERTY(meta = (Input))
FVector ExternalTurbulenceVelocity = FVector::ZeroVector;
};
/**
* Forces tracking of the input animation (on all physics bodies) for the next N frames
*/
USTRUCT(meta = (DisplayName = "Track Input Pose", Keywords = "Simulate"))
struct FRigUnit_TrackInputPose : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_TrackInputPose()
{
PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
// The solver to relate this new physics element to
UPROPERTY(meta = (Input))
FRigComponentKey PhysicsSolverComponentKey;
// The number of frames to track the input pose for
UPROPERTY(meta = (Input, ClampMin = "0"))
int NumberOfFrames = 1;
// If true, then the number will be forced, potentially reducing the number. If false, then the
// NumberOfFrames will only be used to increase the number of frames remaining.
UPROPERTY(meta = (Input))
bool bForceNumberOfFrames = false;
};
// Adds a set of physics components including the body, joint and controls
USTRUCT(meta = (DisplayName = "Add Physics Components", Keywords = "Spawn,Construction,Create,New", Varying))
struct FRigUnit_AddPhysicsComponents : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_AddPhysicsComponents()
{
Owner.Type = ERigElementType::Bone;
Solver.PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
Solver.PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
/**
* The owner of the newly created component (must be set/valid)
*/
UPROPERTY(meta = (Input, BoneName))
FRigElementKey Owner;
UPROPERTY(meta = (Input))
bool bAddJoint = true;
UPROPERTY(meta = (Input))
bool bAddSimSpaceControl = true;
UPROPERTY(meta = (Input))
bool bAddParentSpaceControl = true;
UPROPERTY(meta = (Output))
FRigComponentKey PhysicsBodyComponentKey;
UPROPERTY(meta = (Output))
FRigComponentKey PhysicsJointComponentKey;
UPROPERTY(meta = (Output))
FRigComponentKey SimSpaceControlComponentKey;
UPROPERTY(meta = (Output))
FRigComponentKey ParentSpaceControlComponentKey;
// The solver to relate this new physics element to
UPROPERTY(meta = (Input))
FRigPhysicsBodySolverSettings Solver;
// The dynamics properties of the new physics body
UPROPERTY(meta = (Input))
FRigPhysicsDynamics Dynamics;
// The collision properties of the new physics body
UPROPERTY(meta = (Input))
FRigPhysicsCollision Collision;
// The runtime modifiable data of the new physics body
UPROPERTY(meta = (Input))
FPhysicsControlModifierData BodyData;
// The properties of the joint
UPROPERTY(meta = (Input))
FRigPhysicsJointData JointData;
// Optional motor/drive associated with the physics joint
UPROPERTY(meta = (Input))
FRigPhysicsDriveData DriveData;
// Data for the simulation space control
UPROPERTY(meta = (Input))
FPhysicsControlData SimSpaceControlData;
// Data for the parent space control
UPROPERTY(meta = (Input))
FPhysicsControlData ParentSpaceControlData;
};
// Imports/creates bones from the physics asset and creates collision for them.
// The bones will lose their hierarchy and be placed under the specified parent - ready to be moved around.
USTRUCT(meta = (DisplayName = "Import Collision From Physics Asset", Keywords = "Construction,Create,New", Varying))
struct FRigUnit_HierarchyImportCollisionFromPhysicsAsset : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_HierarchyImportCollisionFromPhysicsAsset()
{
PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
// Note that setting the solver component, if known, has the benefit of avoiding the need to
// search for an automatic solver.
UPROPERTY(meta = (Input))
FRigComponentKey PhysicsSolverComponentKey;
// If true (and the physics solver is not explicitly set), then this component will be added to
// any physics solver that exists above it in the hierarchy, if that solver allows automatically
// adding physics components.
UPROPERTY(meta = (Input))
bool bUseAutomaticSolver = true;
UPROPERTY(meta = (Input))
TObjectPtr<UPhysicsAsset> PhysicsAsset;
// Name of the constraint profile to use. If empty (or invalid), the default profile will be used
UPROPERTY(meta = (Input))
FName ConstraintProfileName;
// If this is empty, then all bones with bodies in the physics asset will be created. Otherwise
// only bodies that relate to the specified bones will be created.
UPROPERTY(meta = (Input))
TArray<FName> BonesToUse;
// Prefix to the bone names
UPROPERTY(meta = (Input))
FName NameSpace = "Physics_";
// Parent/owner for all the new bones
UPROPERTY(meta = (Input))
FRigElementKey Owner;
UPROPERTY(meta = (Output))
TArray<FRigElementKey> BoneKeys;
UPROPERTY(meta = (Output))
TArray<FRigComponentKey> PhysicsBodyComponentKeys;
};
// Creates multiple physics components based on the supplied physics asset.
// Note that the resulting simulation bodies may not precisely match the physics asset.
USTRUCT(meta = (DisplayName = "Instantiate From Physics Asset", Keywords = "Construction,Create,New", Varying))
struct FRigUnit_HierarchyInstantiateFromPhysicsAsset : public FRigUnit_PhysicsBaseMutable
{
GENERATED_BODY()
FRigUnit_HierarchyInstantiateFromPhysicsAsset()
{
PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
// Note that setting the solver component, if known, has the benefit of avoiding the need to
// search for an automatic solver.
UPROPERTY(meta = (Input))
FRigComponentKey PhysicsSolverComponentKey;
// If true (and the physics solver is not explicitly set), then this component will be added to
// any physics solver that exists above it in the hierarchy, if that solver allows automatically
// adding physics components.
UPROPERTY(meta = (Input))
bool bUseAutomaticSolver = true;
UPROPERTY(meta = (Input))
TObjectPtr<UPhysicsAsset> PhysicsAsset;
// Name of the constraint profile to use. If empty (or invalid), the default profile will be used
UPROPERTY(meta = (Input))
FName ConstraintProfileName;
// If this is empty, then all bodies in the physics asset that match a bone in the hierarchy
// will be created. Otherwise only bodies that relate to the specified bones will be created.
UPROPERTY(meta = (Input))
TArray<FRigElementKey> BonesToUse;
// Whether to enable the joints authored in the physics asset. Note that you can't have drives
// without joints.
UPROPERTY(meta = (Input))
bool bEnableJoints = true;
// Whether to enable the drives authored in the physics asset. Note that if you are creating
// parent space controls, you may not want the drives
UPROPERTY(meta = (Input))
bool bEnableDrives = true;
UPROPERTY(meta = (Input))
bool bAddSimSpaceControl = false;
UPROPERTY(meta = (Input))
bool bAddParentSpaceControl = false;
// Data for the simulation space control
UPROPERTY(meta = (Input))
FPhysicsControlData SimSpaceControlData;
// Data for the parent space control
UPROPERTY(meta = (Input))
FPhysicsControlData ParentSpaceControlData;
UPROPERTY(meta = (Output))
TArray<FRigComponentKey> PhysicsBodyComponentKeys;
UPROPERTY(meta = (Output))
TArray<FRigComponentKey> PhysicsJointComponentKeys;
UPROPERTY(meta = (Output))
TArray<FRigComponentKey> SimSpaceControlComponentKeys;
UPROPERTY(meta = (Output))
TArray<FRigComponentKey> ParentSpaceControlComponentKeys;
};
// Retrieves the simulation space data. Note that this will have been generated during the
// simulation step, so the values returned will relate to the previous update if the solver has not
// yet been stepped.
USTRUCT(meta = (DisplayName = "Get Physics Solver Space Data", Keywords = "Debug"))
struct FRigUnit_GetPhysicsSolverSpaceData : public FRigUnit_PhysicsBase
{
GENERATED_BODY()
FRigUnit_GetPhysicsSolverSpaceData()
{
PhysicsSolverComponentKey.ElementKey.Type = ERigElementType::Bone;
PhysicsSolverComponentKey.Name = FRigPhysicsSolverComponent::GetDefaultName();
}
RIGVM_METHOD()
UE_API virtual void Execute() override;
// The solver to relate this new physics element to
UPROPERTY(meta = (Input))
FRigComponentKey PhysicsSolverComponentKey;
UPROPERTY(meta = (Output))
FVector LinearVelocity = FVector::ZeroVector;
UPROPERTY(meta = (Output))
FVector AngularVelocity = FVector::ZeroVector;
UPROPERTY(meta = (Output))
FVector LinearAcceleration = FVector::ZeroVector;
UPROPERTY(meta = (Output))
FVector AngularAcceleration = FVector::ZeroVector;
UPROPERTY(meta = (Output))
FVector Gravity = FVector::ZeroVector;
};
#undef UE_API