|
|
@ -7,37 +7,30 @@ |
|
|
|
#include "util.h" |
|
|
|
#include "util.h" |
|
|
|
#include "Kismet/KismetMathLibrary.h" |
|
|
|
#include "Kismet/KismetMathLibrary.h" |
|
|
|
|
|
|
|
|
|
|
|
Vector3d UJoint::GetFirstWorldDirection() const{ |
|
|
|
Vector3d UJoint::GetFirstWorldPosition() const{ |
|
|
|
return FirstLink->Orientation * FirstLocalPosition; |
|
|
|
return FirstLink->Position + FirstLink->Orientation * FirstLocalPosition; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Vector3d UJoint::GetSecondWorldDirection() const{ |
|
|
|
Vector3d UJoint::GetSecondWorldPosition() const{ |
|
|
|
return SecondLink->Orientation * SecondLocalPosition; |
|
|
|
return SecondLink->Position + SecondLink->Orientation * SecondLocalPosition; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Vector3d UJoint::GetConnection() const{ |
|
|
|
|
|
|
|
return FirstLink->Position + GetFirstWorldDirection() - (SecondLink->Position + GetSecondWorldDirection()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Vector3d UJoint::GetFirstWorldAxis() const{ |
|
|
|
Vector3d UJoint::GetFirstWorldAxis() const{ |
|
|
|
return FirstLink->Orientation * FirstRotateAxis; |
|
|
|
return FirstLink->Orientation * FirstRotateAxis; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Vector3d UJoint::GetSecondWorldAxis() const{ |
|
|
|
Vector3d UJoint::GetSecondWorldAxis() const{ |
|
|
|
return SecondLink->Orientation * SecondRotateAxis; |
|
|
|
return SecondLink->Orientation * SecondRotateAxis; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UJoint::SolvePosition(const double H) const{ |
|
|
|
void UJoint::SolvePosition(const double H) const{ |
|
|
|
ULink* L1 = FirstLink; |
|
|
|
ULink* L1 = FirstLink; |
|
|
|
ULink* L2 = SecondLink; |
|
|
|
ULink* L2 = SecondLink; |
|
|
|
|
|
|
|
|
|
|
|
// Positional Constraints
|
|
|
|
// Positional Constraints
|
|
|
|
{ |
|
|
|
{ |
|
|
|
const Vector3d R1 = GetFirstWorldDirection(); |
|
|
|
const Vector3d R1 = GetFirstWorldPosition(); |
|
|
|
const Vector3d R2 = GetSecondWorldDirection(); |
|
|
|
const Vector3d R2 = GetSecondWorldPosition(); |
|
|
|
const Vector3d D = GetConnection(); |
|
|
|
const Vector3d D = R1 - R2; // Original PBD (not R2 - R1), because Impulse P is negated
|
|
|
|
const Vector3d N = D.normalized(); |
|
|
|
const Vector3d N = D.normalized(); |
|
|
|
const double C = D.norm(); |
|
|
|
const double C = D.norm(); |
|
|
|
const Matrix3d I1 = L1->GetInertia(); |
|
|
|
const Matrix3d I1 = L1->GetInertia(); |
|
|
@ -49,7 +42,6 @@ void UJoint::SolvePosition(const double H) const{ |
|
|
|
const double W2 = L2->GetPositionalInverseMass(R2, N); |
|
|
|
const double W2 = L2->GetPositionalInverseMass(R2, N); |
|
|
|
|
|
|
|
|
|
|
|
constexpr double A = 1. / 10000000; // Compliance (inverse of stiffness)
|
|
|
|
constexpr double A = 1. / 10000000; // Compliance (inverse of stiffness)
|
|
|
|
|
|
|
|
|
|
|
|
const Vector3d P = -C / (W1 + W2 + A / (H * H)) * N; |
|
|
|
const Vector3d P = -C / (W1 + W2 + A / (H * H)) * N; |
|
|
|
|
|
|
|
|
|
|
|
L1->Position += P / M1; |
|
|
|
L1->Position += P / M1; |
|
|
@ -57,21 +49,20 @@ void UJoint::SolvePosition(const double H) const{ |
|
|
|
|
|
|
|
|
|
|
|
Vector3d T1 = I1.inverse() * R1.cross(P); |
|
|
|
Vector3d T1 = I1.inverse() * R1.cross(P); |
|
|
|
Vector3d T2 = I2.inverse() * R2.cross(P); |
|
|
|
Vector3d T2 = I2.inverse() * R2.cross(P); |
|
|
|
const Quaterniond Add1 = Quaterniond(0, T1.x(), T1.y(), T1.z()) * L1->Orientation * 0.5; |
|
|
|
Quaterniond Add1 = Quaterniond(0, T1.x(), T1.y(), T1.z()) * L1->Orientation * 0.5; |
|
|
|
const Quaterniond Add2 = Quaterniond(0, T2.x(), T2.y(), T2.z()) * L2->Orientation * 0.5; |
|
|
|
Quaterniond Add2 = Quaterniond(0, T2.x(), T2.y(), T2.z()) * L2->Orientation * 0.5; |
|
|
|
L1->Orientation = (L1->Orientation + Add1).normalized(); |
|
|
|
//L1->Orientation = L1->Orientation + Add1;
|
|
|
|
L2->Orientation = (L2->Orientation - Add2).normalized(); |
|
|
|
//L2->Orientation = L2->Orientation- Add2;
|
|
|
|
UE_LOG(LogTemp, Log, TEXT("%f | %f | %f"), C, P.norm(), R2.cross(P).norm()); |
|
|
|
//UE_LOG(LogTemp, Log, TEXT("%f %f"), (T1).norm(), T2.norm());
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Rotational Constraints
|
|
|
|
// Rotational Constraints
|
|
|
|
{ |
|
|
|
{ |
|
|
|
const Vector3d A1 = GetFirstWorldAxis(); |
|
|
|
const Vector3d A1 = GetFirstWorldAxis(); |
|
|
|
const Vector3d A2 = GetSecondWorldAxis(); |
|
|
|
const Vector3d A2 = GetSecondWorldAxis(); |
|
|
|
assert(A1.norm() == A2.norm() == 1); |
|
|
|
|
|
|
|
const Vector3d Q = A1.cross(A2); |
|
|
|
const Vector3d Q = A1.cross(A2); |
|
|
|
const Vector3d N = Q.normalized(); |
|
|
|
const Vector3d N = Q.normalized(); |
|
|
|
const double Theta = UKismetMathLibrary::Asin(Q.norm());// * 180. / PI;
|
|
|
|
const double Theta = Q.norm(); |
|
|
|
|
|
|
|
|
|
|
|
const Matrix3d I1 = L1->GetInertia(); |
|
|
|
const Matrix3d I1 = L1->GetInertia(); |
|
|
|
const Matrix3d I2 = L2->GetInertia(); |
|
|
|
const Matrix3d I2 = L2->GetInertia(); |
|
|
@ -79,16 +70,16 @@ void UJoint::SolvePosition(const double H) const{ |
|
|
|
const double W1 = L1->GetRotationalInverseMass(N); |
|
|
|
const double W1 = L1->GetRotationalInverseMass(N); |
|
|
|
const double W2 = L2->GetRotationalInverseMass(N); |
|
|
|
const double W2 = L2->GetRotationalInverseMass(N); |
|
|
|
|
|
|
|
|
|
|
|
constexpr double A = 0; //1. / 10000000;
|
|
|
|
const double A = 0.000001 / (H * H); |
|
|
|
const Vector3d P = Theta / (W1 + W2 + A / (H * H)) * N; |
|
|
|
const Vector3d P = -Theta / (W1 + W2 + A) * N; |
|
|
|
|
|
|
|
|
|
|
|
Vector3d T1 = I1.inverse() * P; |
|
|
|
Vector3d T1 = I1.inverse() * P; |
|
|
|
Vector3d T2 = I2.inverse() * P; |
|
|
|
Vector3d T2 = I2.inverse() * P; |
|
|
|
const Quaterniond Add1 = Quaterniond(0, T1.x(), T1.y(), T1.z()) * L1->Orientation * 0.5; |
|
|
|
T1 = T2 = P; |
|
|
|
const Quaterniond Add2 = Quaterniond(0, T2.x(), T2.y(), T2.z()) * L2->Orientation * 0.5; |
|
|
|
//L1->Orientation += Quaterniond(0, T1.x(), T1.y(), T1.z()) * L1->Orientation * 0.5;
|
|
|
|
//L1->Orientation = (L1->Orientation + Add1).normalized();
|
|
|
|
//L2->Orientation -= Quaterniond(0, T2.x(), T2.y(), T2.z()) * L2->Orientation * 0.5;
|
|
|
|
//L2->Orientation = (L2->Orientation - Add2).normalized();
|
|
|
|
|
|
|
|
//UE_LOG(LogTemp, Log, TEXT("%f | %f | %f | %f"), N.norm(), W1, W2, Q.norm());
|
|
|
|
// UE_LOG(LogTemp, Log, TEXT("%f | %f"), W1, W2);
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
@ -101,11 +92,11 @@ void UJoint::SolveVelocity(const double H) const{ |
|
|
|
const Vector3d V1 = L1->Velocity; |
|
|
|
const Vector3d V1 = L1->Velocity; |
|
|
|
const Vector3d V2 = L2->Velocity; |
|
|
|
const Vector3d V2 = L2->Velocity; |
|
|
|
|
|
|
|
|
|
|
|
constexpr double MuLin = 10000; // Damping strength
|
|
|
|
constexpr double MuLin = 100000; // Damping strength
|
|
|
|
const Vector3d DeltaV = (V2 - V1) * (MuLin * H < 1 ? MuLin * H : 1); |
|
|
|
const Vector3d DeltaV = (V2 - V1) * UKismetMathLibrary::Min(MuLin * H, 1); |
|
|
|
|
|
|
|
|
|
|
|
const Vector3d R1 = GetFirstWorldDirection(); |
|
|
|
const Vector3d R1 = GetFirstWorldPosition(); |
|
|
|
const Vector3d R2 = GetSecondWorldDirection(); |
|
|
|
const Vector3d R2 = GetSecondWorldPosition(); |
|
|
|
const Vector3d N = (R2 - R1).normalized(); |
|
|
|
const Vector3d N = (R2 - R1).normalized(); |
|
|
|
|
|
|
|
|
|
|
|
const Matrix3d I1 = L1->GetInertia(); |
|
|
|
const Matrix3d I1 = L1->GetInertia(); |
|
|
@ -116,10 +107,10 @@ void UJoint::SolveVelocity(const double H) const{ |
|
|
|
|
|
|
|
|
|
|
|
const Vector3d P = DeltaV / (W1 + W2); |
|
|
|
const Vector3d P = DeltaV / (W1 + W2); |
|
|
|
|
|
|
|
|
|
|
|
//UE_LOG(LogTemp, Log, TEXT("%f | %f | %f | %f | %f"), P.norm(), MuLin * H, DeltaV.norm(), (V2 - V1).norm());
|
|
|
|
// UE_LOG(LogTemp, Log, TEXT("%f | %f"), (V2 - V1).norm(), MuLin * H);
|
|
|
|
|
|
|
|
|
|
|
|
//L1->Velocity += P / L1->Mass;
|
|
|
|
L1->Velocity += P / L1->Mass; |
|
|
|
//L2->Velocity -= P / L2->Mass;
|
|
|
|
L2->Velocity -= P / L2->Mass; |
|
|
|
//L1->AngularVelocity += I1.inverse() * R1.cross(P);
|
|
|
|
//L1->AngularVelocity += I1.inverse() * R1.cross(P);
|
|
|
|
//L2->AngularVelocity -= I2.inverse() * R2.cross(P);
|
|
|
|
//L2->AngularVelocity -= I2.inverse() * R2.cross(P);
|
|
|
|
} |
|
|
|
} |
|
|
|