void ALeapMotionHandActor::UpdateBones(float DeltaSeconds) { if (BoneActors.Num() == 0) { return; } float CombinedScale = GetCombinedScale(); FLeapMotionDevice* Device = FLeapMotionControllerPlugin::GetLeapDeviceSafe(); if (Device && Device->IsConnected()) { int BoneArrayIndex = 0; for (ELeapBone LeapBone = bShowArm ? ELeapBone::Forearm : ELeapBone::Palm; LeapBone <= ELeapBone::Finger4Tip; ((int8&)LeapBone)++) { FVector TargetPosition; FRotator TargetOrientation; bool Success = Device->GetBonePostionAndOrientation(HandId, LeapBone, TargetPosition, TargetOrientation); if (Success) { // Offset target position & rotation by the SpawnReference actor's transform FQuat RefQuat = GetRootComponent()->GetComponentRotation().Quaternion(); TargetPosition = RefQuat * TargetPosition * CombinedScale + GetRootComponent()->GetComponentLocation(); TargetOrientation = (RefQuat * TargetOrientation.Quaternion()).Rotator(); // Get current position & rotation ALeapMotionBoneActor* BoneActor = BoneActors[BoneArrayIndex++]; UPrimitiveComponent* PrimitiveComponent = Cast<UPrimitiveComponent>(BoneActor->GetRootComponent()); if (PrimitiveComponent && PrimitiveComponent->IsSimulatingPhysics()) { FVector CurrentPositon = PrimitiveComponent->GetComponentLocation(); FRotator CurrentRotation = PrimitiveComponent->GetComponentRotation(); // Compute linear velocity FVector LinearVelocity = (TargetPosition - CurrentPositon) / DeltaSeconds; // Compute angular velocity FVector Axis; float Angle; ConvertDeltaRotationsToAxisAngle(CurrentRotation, TargetOrientation, Axis, Angle); if (Angle > PI) { Angle -= 2 * PI; } FVector AngularVelcity = Axis * (Angle / DeltaSeconds); // Apply velocities PrimitiveComponent->SetPhysicsLinearVelocity(LinearVelocity); PrimitiveComponent->SetAllPhysicsAngularVelocity(AngularVelcity * 180.0f / PI); } } } } }
bool ULeapMotionFunctionLibrary::GetBonePostionAndOrientation(int32 HandId, ELeapBone LeapBone, FVector& OutPosition, FRotator& OutOrientation) { OutPosition = FVector::ZeroVector; OutOrientation = FRotator::ZeroRotator; FLeapMotionDevice* LeapDevice = FLeapMotionControllerPlugin::GetLeapDeviceSafe(); if (LeapDevice) { LeapDevice->SetReferenceFrameOncePerTick(); return LeapDevice->GetBonePostionAndOrientation(HandId, LeapBone, OutPosition, OutOrientation); } return false; }
void ALeapMotionHandActor::CreateBones(const TSubclassOf<class ALeapMotionBoneActor>& BoneBlueprint) { FActorSpawnParameters SpawnParams; SpawnParams.Owner = GetOwner(); SpawnParams.Instigator = GetInstigator(); float CombinedScale = GetCombinedScale(); FLeapMotionDevice* Device = FLeapMotionControllerPlugin::GetLeapDeviceSafe(); if (Device && Device->IsConnected()) { for (ELeapBone LeapBone = bShowArm ? ELeapBone::Forearm : ELeapBone::Palm; LeapBone <= ELeapBone::Finger4Tip; ((int8&)LeapBone)++) { FVector Position; FRotator Orientation; float Width; float Length; bool Success = Device->GetBonePostionAndOrientation(HandId, LeapBone, Position, Orientation); Success &= Device->GetBoneWidthAndLength(HandId, LeapBone, Width, Length); if (Success) { FQuat RefQuat = GetRootComponent()->GetComponentRotation().Quaternion(); Position = RefQuat * Position * CombinedScale + GetRootComponent()->GetComponentLocation(); Orientation = (RefQuat * Orientation.Quaternion()).Rotator(); ALeapMotionBoneActor* BoneActor = GWorld->SpawnActor<ALeapMotionBoneActor>(BoneBlueprint ? BoneBlueprint : ALeapMotionBoneActor::StaticClass(), Position, Orientation, SpawnParams); if (BoneActor) { BoneActors.Add(BoneActor); # if WITH_EDITOR BoneActor->SetActorLabel(*FString::Printf(TEXT("LeapBone:%s"), ANSI_TO_TCHAR(LEAP_GET_BONE_NAME(LeapBone)))); # endif BoneActor->AttachRootComponentToActor(this, NAME_None, EAttachLocation::KeepWorldPosition, true); BoneActor->Init(LeapBone, CombinedScale, Width, Length, bShowCollider, bShowMesh); } } } } }