// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Engine/EngineTypes.h" #include "Chaos/ChaosEngineInterface.h" #include "PhysicsAssetUtils.generated.h" class UBodySetup; class UPhysicsAsset; class UPhysicsConstraintTemplate; class USkeletalMesh; class USkeletalMeshComponent; UENUM() enum EPhysAssetFitGeomType { EFG_Box UMETA(DisplayName = "Box"), EFG_Sphyl UMETA(DisplayName = "Capsule"), EFG_Sphere UMETA(DisplayName = "Sphere"), EFG_TaperedCapsule UMETA(DisplayName = "Tapered Capsule (Cloth Only)"), EFG_SingleConvexHull UMETA(DisplayName = "Single Convex Hull"), EFG_MultiConvexHull UMETA(DisplayName = "Multi Convex Hull") }; UENUM() enum EPhysAssetFitVertWeight { EVW_AnyWeight UMETA(DisplayName = "Any Weight"), EVW_DominantWeight UMETA(DisplayName = "Dominant Weight"), }; /** Parameters for PhysicsAsset creation */ USTRUCT() struct FPhysAssetCreateParams { GENERATED_BODY() FPhysAssetCreateParams() { MinBoneSize = 20.0f; MinWeldSize = KINDA_SMALL_NUMBER; GeomType = EFG_Sphyl; VertWeight = EVW_DominantWeight; bAutoOrientToBone = true; bCreateConstraints = true; bWalkPastSmall = true; bBodyForAll = false; bDisableCollisionsByDefault = true; AngularConstraintMode = ACM_Limited; HullCount = 4; MaxHullVerts = 16; } /** Bones that are shorter than this value will be ignored for body creation */ UPROPERTY(EditAnywhere, Category = "Body Creation") float MinBoneSize; /** Bones that are smaller than this value will be merged together for body creation */ UPROPERTY(EditAnywhere, AdvancedDisplay, Category = "Body Creation") float MinWeldSize; /** The geometry type that should be used when creating bodies */ UPROPERTY(EditAnywhere, Category = "Body Creation", meta = (DisplayName = "Primitive Type")) TEnumAsByte GeomType; /** How vertices are mapped to bones when approximating them with bodies */ UPROPERTY(EditAnywhere, Category = "Body Creation", meta = (DisplayName = "Vertex Weighting Type")) TEnumAsByte VertWeight; /** Whether to automatically orient the created bodies to their corresponding bones */ UPROPERTY(EditAnywhere, Category = "Body Creation") bool bAutoOrientToBone; /** Whether to create constraints between adjacent created bodies */ UPROPERTY(EditAnywhere, Category = "Constraint Creation") bool bCreateConstraints; /** Whether to skip small bones entirely (rather than merge them with adjacent bones) */ UPROPERTY(EditAnywhere, Category = "Body Creation", meta = (DisplayName = "Walk Past Small Bones")) bool bWalkPastSmall; /** Forces creation of a body for each bone */ UPROPERTY(EditAnywhere, Category = "Body Creation", meta = (DisplayName = "Create Body for All Bones")) bool bBodyForAll; /** Whether to disable collision of body with other bodies on creation */ UPROPERTY(EditAnywhere, Category = "Body Creation") bool bDisableCollisionsByDefault; /** The type of angular constraint to create between bodies */ UPROPERTY(EditAnywhere, Category = "Constraint Creation", meta = (EditCondition = "bCreateConstraints")) TEnumAsByte AngularConstraintMode; /** When creating multiple convex hulls, the maximum number that will be created. */ UPROPERTY(EditAnywhere, AdvancedDisplay, Category = "Body Creation") int32 HullCount; /** When creating convex hulls, the maximum verts that should be created */ UPROPERTY(EditAnywhere, AdvancedDisplay, Category = "Body Creation") int32 MaxHullVerts; }; class UPhysicsAsset; class UPhysicsConstraintTemplate; struct FBoneVertInfo; /** Collection of functions to create and setup PhysicsAssets */ namespace FPhysicsAssetUtils { /** * Given a USkeletalMesh, construct a new PhysicsAsset automatically, using the vertices weighted to each bone to calculate approximate collision geometry. * Ball-and-socket joints will be created for every joint by default. * * @param PhysicsAsset The PhysicsAsset instance to setup * @param SkelMesh The Skeletal Mesh to create the physics asset from * @param Params Additional creation parameters * @param OutErrorMessage Additional error information * @param bSetToMesh Whether or not to apply the physics asset to SkelMesh immediately */ UNREALED_API bool CreateFromSkeletalMesh(UPhysicsAsset* PhysicsAsset, USkeletalMesh* SkelMesh, const FPhysAssetCreateParams& Params, FText& OutErrorMessage, bool bSetToMesh = true); /** Replaces any collision already in the BodySetup with an auto-generated one using the parameters provided. * * @warning Certain physics geometry types, such as multi-convex hull, must recreate internal caches every time this function is called. * If you find you're calling this function repeatedly for different bone indices on the same mesh, * CreateFromSkeletalMesh or CreateCollisionFromBones will provide better performance. * * @param bs BodySetup to create the collision for * @param skelMesh The SkeletalMesh we create collision for * @param BoneIndex Index of the bone the collision is created for * @param Params Additional parameters to control the creation * @param Info The vertices to create the collision for * @return Returns true if successfully created collision from bone */ UNREALED_API bool CreateCollisionFromBone(UBodySetup* bs, USkeletalMesh* skelMesh, int32 BoneIndex, const FPhysAssetCreateParams& Params, const FBoneVertInfo& Info); /** Replaces any collision already in the BodySetup with an auto-generated one using the parameters provided. * * @param bs BodySetup to create the collision for * @param skelMesh The SkeletalMesh we create collision for * @param BoneIndices Indices of the bones the collisions are created for * @param Params Additional parameters to control the creation * @param Info The vertices to create the collision for * @return Returns true if successfully created collision from all specified bones */ UNREALED_API bool CreateCollisionFromBones(UBodySetup* bs, USkeletalMesh* skelMesh, const TArray& BoneIndices, FPhysAssetCreateParams& Params, const FBoneVertInfo& Info); /** * Does a few things: * - add any collision primitives from body2 into body1 (adjusting the tm of each). * - reconnect any constraints between 'add body' to 'base body', destroying any between them. * - update collision disable table for any pairs including 'add body' */ UNREALED_API void WeldBodies(UPhysicsAsset* PhysAsset, int32 BaseBodyIndex, int32 AddBodyIndex, USkeletalMeshComponent* SkelComp); /** * Creates a new constraint * * @param PhysAsset The PhysicsAsset to create the constraint for * @param InConstraintName Name of the constraint * @param InConstraintSetup Optional constraint setup * @return Returns the index of the newly created constraint. **/ UNREALED_API int32 CreateNewConstraint(UPhysicsAsset* PhysAsset, FName InConstraintName, UPhysicsConstraintTemplate* InConstraintSetup = NULL); /** * Destroys the specified constraint * * @param PhysAsset The PhysicsAsset for which the constraint should be destroyed * @param ConstraintIndex The index of the constraint to destroy */ UNREALED_API void DestroyConstraint(UPhysicsAsset* PhysAsset, int32 ConstraintIndex); /** * Create a new BodySetup and default BodyInstance if there is not one for this body already. * * @param PhysAsset The PhysicsAsset to create the body for * @param InBodyName Name of the new body * @return The Index of the newly created body. */ UNREALED_API int32 CreateNewBody(UPhysicsAsset* PhysAsset, FName InBodyName, const FPhysAssetCreateParams& Params); /** * Destroys the specified body * * @param PhysAsset The PhysicsAsset for which the body should be destroyed * @param BodyIndex Index of the body to destroy */ UNREALED_API void DestroyBody(UPhysicsAsset* PhysAsset, int32 BodyIndex); }; // namespace FPhysicsAssetUtils