A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
VREPhysicsConstraintComponent.h
Go to the documentation of this file.
1#pragma once
2
3#include "CoreMinimal.h"
4#include "UObject/ObjectMacros.h"
5#include "PhysicsEngine/PhysicsConstraintComponent.h"
6
7// Delete this eventually when the physics interface is fixed
8#if PHYSICS_INTERFACE_PHYSX
9#include "PhysXPublic.h"
10#endif // WITH_PHYSX
11
12#include "VREPhysicsConstraintComponent.generated.h"
13
17UCLASS(ClassGroup = Physics, meta = (BlueprintSpawnableComponent), HideCategories = (Activation, "Components|Activation", Physics, Mobility), ShowCategories = ("Physics|Components|PhysicsConstraint", "VRE Constraint Settings"))
18class VREXPANSIONPLUGIN_API UVREPhysicsConstraintComponent : public UPhysicsConstraintComponent
19{
21 GENERATED_BODY()
22public:
24 UFUNCTION(BlueprintCallable, Category = "VRE Physics Constraint Component")
25 void SetConstraintToForceBased(bool bUseForceConstraint)
26 {
27#if PHYSICS_INTERFACE_PHYSX
28 // This is a temp workaround until epic fixes the drive creation to allow force constraints
29 // I wanted to use the new interface and not directly set the drive so that it is ready to delete this section
30 // When its fixed
31 //#if PHYSICS_INTERFACE_PHYSX
32
33
34 if (!ConstraintInstance.ConstraintHandle.ConstraintData)
35 return;
36
37 PxD6JointDriveFlags JointFlags;
38 if (!bUseForceConstraint)
39 JointFlags = PxD6JointDriveFlag::eACCELERATION;
40
41
42 PxD6JointDrive driveVal = ConstraintInstance.ConstraintHandle.ConstraintData->getDrive(PxD6Drive::Enum::eX);
43 driveVal.flags = JointFlags;
44 ConstraintInstance.ConstraintHandle.ConstraintData->setDrive(PxD6Drive::Enum::eX, driveVal);
45
46 driveVal = ConstraintInstance.ConstraintHandle.ConstraintData->getDrive(PxD6Drive::Enum::eY);
47 driveVal.flags = JointFlags;
48 ConstraintInstance.ConstraintHandle.ConstraintData->setDrive(PxD6Drive::Enum::eY, driveVal);
49
50 driveVal = ConstraintInstance.ConstraintHandle.ConstraintData->getDrive(PxD6Drive::Enum::eZ);
51 driveVal.flags = JointFlags;
52 ConstraintInstance.ConstraintHandle.ConstraintData->setDrive(PxD6Drive::Enum::eZ, driveVal);
53
54 // Check if slerp
55 if (ConstraintInstance.ProfileInstance.AngularDrive.AngularDriveMode == EAngularDriveMode::SLERP)
56 {
57 driveVal = ConstraintInstance.ConstraintHandle.ConstraintData->getDrive(PxD6Drive::Enum::eSLERP);
58 driveVal.flags = JointFlags;
59 ConstraintInstance.ConstraintHandle.ConstraintData->setDrive(PxD6Drive::Enum::eSLERP, driveVal);
60 }
61 else
62 {
63 driveVal = ConstraintInstance.ConstraintHandle.ConstraintData->getDrive(PxD6Drive::Enum::eSWING);
64 driveVal.flags = JointFlags;
65 ConstraintInstance.ConstraintHandle.ConstraintData->setDrive(PxD6Drive::Enum::eSWING, driveVal);
66
67 driveVal = ConstraintInstance.ConstraintHandle.ConstraintData->getDrive(PxD6Drive::Enum::eTWIST);
68 driveVal.flags = JointFlags;
69 ConstraintInstance.ConstraintHandle.ConstraintData->setDrive(PxD6Drive::Enum::eTWIST, driveVal);
70 }
71
72#elif WITH_CHAOS
73
74 if (!ConstraintInstance.ConstraintHandle.IsValid())
75 return;
76
77 if (ConstraintInstance.ConstraintHandle->IsType(Chaos::EConstraintType::JointConstraintType))
78 {
79 if (Chaos::FJointConstraint* Constraint = static_cast<Chaos::FJointConstraint*>(ConstraintInstance.ConstraintHandle.Constraint))
80 {
81 Constraint->SetLinearDriveForceMode(bUseForceConstraint ? Chaos::EJointForceMode::Force : Chaos::EJointForceMode::Acceleration);
82 Constraint->SetAngularDriveForceMode(bUseForceConstraint ? Chaos::EJointForceMode::Force : Chaos::EJointForceMode::Acceleration);
83 }
84 }
85
86#endif
87 //#endif
88 }
89
90
91 UFUNCTION(BlueprintCallable, Category = "VRE Physics Constraint Component")
92 void GetConstraintReferenceFrame(EConstraintFrame::Type Frame, FTransform& RefFrame)
93 {
94 RefFrame = ConstraintInstance.GetRefFrame(Frame);
95 }
96
97 UFUNCTION(BlueprintCallable, Category = "VRE Physics Constraint Component")
98 FTransform GetLocalPose(EConstraintFrame::Type ConstraintFrame)
99 {
100 if (ConstraintInstance.IsValidConstraintInstance())
101 {
102 if (ConstraintFrame == EConstraintFrame::Frame1)
103 {
104 return FTransform(ConstraintInstance.PriAxis1, ConstraintInstance.SecAxis1, ConstraintInstance.PriAxis1 ^ ConstraintInstance.SecAxis1, ConstraintInstance.Pos1);
105 }
106 else
107 {
108 return FTransform(ConstraintInstance.PriAxis2, ConstraintInstance.SecAxis2, ConstraintInstance.PriAxis2 ^ ConstraintInstance.SecAxis2, ConstraintInstance.Pos2);
110
111 }
112
113 return FTransform::Identity;
114 }
115
116 UFUNCTION(BlueprintCallable, Category = "VRE Physics Constraint Component")
117 void GetGlobalPose(EConstraintFrame::Type ConstraintFrame, FTransform& GlobalPose)
118 {
119 if (ConstraintInstance.IsValidConstraintInstance())
120 {
121 GlobalPose = FPhysicsInterface::GetGlobalPose(ConstraintInstance.ConstraintHandle, ConstraintFrame);
122 }
123 else
124 GlobalPose = FTransform::Identity;
125 }
126
127 // Gets the current linear distance in world space on the joint in +/- from the initial reference frame
128 UFUNCTION(BlueprintPure, Category = "VRE Physics Constraint Component")
129 FVector GetCurrentLinearDistance(EConstraintFrame::Type FrameOfReference)
130 {
131 EConstraintFrame::Type Frame2 = FrameOfReference;
132 EConstraintFrame::Type Frame1 = (FrameOfReference == EConstraintFrame::Frame1) ? EConstraintFrame::Frame2 : EConstraintFrame::Frame1;
133
134 FTransform Frame1Trans = this->GetBodyTransform(Frame1);
135 FTransform Frame2Trans = this->GetBodyTransform(Frame2);
136
137 FTransform LocalPose = GetLocalPose(Frame1);
138 FTransform LocalPose2 = GetLocalPose(Frame2);
139
140 Frame1Trans.SetScale3D(FVector(1.f));
141 Frame1Trans = LocalPose * Frame1Trans;
142
143 FVector OffsetLoc = Frame1Trans.GetRotation().UnrotateVector(Frame1Trans.GetLocation() - Frame2Trans.GetLocation());
144 FVector OffsetLoc2 = LocalPose2.GetRotation().UnrotateVector(LocalPose2.GetLocation());
145 FVector FinalVec = OffsetLoc2 - OffsetLoc;
147 return FinalVec;
148 }
149
150 // Gets the angular offset on the constraint
151 UFUNCTION(BlueprintPure, Category = "VRE Physics Constraint Component")
152 FRotator GetAngularOffset()
153 {
154 return ConstraintInstance.AngularRotationOffset;
155 }
156
157 // Sets the angular offset on the constraint and re-initializes it
158 UFUNCTION(BlueprintCallable, Category="VRE Physics Constraint Component")
159 void SetAngularOffset(FRotator NewAngularOffset)
160 {
161
162 // If the constraint is broken then there is no reason to do everything below
163 // Just early out of it.
164 if (!ConstraintInstance.IsValidConstraintInstance() || ConstraintInstance.IsBroken())
165 {
166 ConstraintInstance.AngularRotationOffset = NewAngularOffset;
167 return;
168 }
169
170 // I could remove a full step if I calc delta in Frame2 local and then apply to the new
171 // Values. However I am keeping it like this for now, would require an extra inverse / relative calc, this may not even be slower
173 FVector RefPos = ConstraintInstance.Pos2;
174 const float RefScale = FMath::Max(GetConstraintScale(), 0.01f);
175 if (GetBodyInstance(EConstraintFrame::Frame2))
176 {
177 RefPos *= RefScale;
178 }
179
180 FQuat AngRotOffset = ConstraintInstance.AngularRotationOffset.Quaternion();
181 FQuat newAngRotOffset = NewAngularOffset.Quaternion();
183 FTransform A2Transform = GetBodyTransform(EConstraintFrame::Frame2);
184 A2Transform.RemoveScaling();
185
186 FTransform CurrentLocalFrame(ConstraintInstance.PriAxis2, ConstraintInstance.SecAxis2, ConstraintInstance.PriAxis2 ^ ConstraintInstance.SecAxis2, ConstraintInstance.Pos2);
187 FTransform WorldLocalFrame = (CurrentLocalFrame * A2Transform);
188
189 FVector WPri21 = GetComponentTransform().TransformVectorNoScale(AngRotOffset.GetForwardVector());
190 FVector WOrth21 = GetComponentTransform().TransformVectorNoScale(AngRotOffset.GetRightVector());
191
192 FTransform OriginalRotOffset(WPri21, WOrth21, WPri21 ^ WOrth21, FVector::ZeroVector);
193 FQuat DeltaRot = WorldLocalFrame.GetRotation() * OriginalRotOffset.GetRotation().Inverse();
194 DeltaRot.Normalize();
195
196 FVector WPri2 = GetComponentTransform().TransformVectorNoScale(newAngRotOffset.GetForwardVector());
197 FVector WOrth2 = GetComponentTransform().TransformVectorNoScale(newAngRotOffset.GetRightVector());
198
199 WPri2 = DeltaRot.RotateVector(WPri2);
200 WOrth2 = DeltaRot.RotateVector(WOrth2);
201
202 ConstraintInstance.PriAxis2 = A2Transform.InverseTransformVectorNoScale(WPri2);
203 ConstraintInstance.SecAxis2 = A2Transform.InverseTransformVectorNoScale(WOrth2);
204 ConstraintInstance.AngularRotationOffset = NewAngularOffset;
205
206 FPhysicsInterface::ExecuteOnUnbrokenConstraintReadWrite(ConstraintInstance.ConstraintHandle, [&](const FPhysicsConstraintHandle& InUnbrokenConstraint)
207 {
208 FTransform URefTransform = FTransform(ConstraintInstance.PriAxis2, ConstraintInstance.SecAxis2, ConstraintInstance.PriAxis2 ^ ConstraintInstance.SecAxis2, RefPos);
209 FPhysicsInterface::SetLocalPose(InUnbrokenConstraint, URefTransform, EConstraintFrame::Frame2);
210 });
211
212 return;
213 }
214
215 //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRE Constraint Settings")
216 //bool bSetAndMaintainCOMOnFrame2;
217
218 //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRE Constraint Settings")
219 // bool bUseForceConstraint;
220};
UCLASS(ClassGroup = Physics, meta = (BlueprintSpawnableComponent), HideCategories = (Activation,...
void SetAngularOffset(FRotator NewAngularOffset)
UFUNCTION(BlueprintCallable, Category="VRE Physics Constraint Component")
FTransform GetLocalPose(EConstraintFrame::Type ConstraintFrame)
UFUNCTION(BlueprintCallable, Category = "VRE Physics Constraint Component")
void GetConstraintReferenceFrame(EConstraintFrame::Type Frame, FTransform &RefFrame)
UFUNCTION(BlueprintCallable, Category = "VRE Physics Constraint Component")
void SetConstraintToForceBased(bool bUseForceConstraint)
UFUNCTION(BlueprintCallable, Category = "VRE Physics Constraint Component")
FRotator GetAngularOffset()
UFUNCTION(BlueprintPure, Category = "VRE Physics Constraint Component")
FVector GetCurrentLinearDistance(EConstraintFrame::Type FrameOfReference)
UFUNCTION(BlueprintPure, Category = "VRE Physics Constraint Component")
void GetGlobalPose(EConstraintFrame::Type ConstraintFrame, FTransform &GlobalPose)
UFUNCTION(BlueprintCallable, Category = "VRE Physics Constraint Component")