bool UVREditorMode::IsHandAimingTowardsCapsule( UViewportInteractor* Interactor, const FTransform& CapsuleTransform, FVector CapsuleStart, const FVector CapsuleEnd, const float CapsuleRadius, const float MinDistanceToCapsule, const FVector CapsuleFrontDirection, const float MinDotForAimingAtCapsule ) const { bool bIsAimingTowards = false; const float WorldScaleFactor = GetWorldScaleFactor(); FVector LaserPointerStart, LaserPointerEnd; if( Interactor->GetLaserPointer( /* Out */ LaserPointerStart, /* Out */ LaserPointerEnd ) ) { const FVector LaserPointerStartInCapsuleSpace = CapsuleTransform.InverseTransformPosition( LaserPointerStart ); const FVector LaserPointerEndInCapsuleSpace = CapsuleTransform.InverseTransformPosition( LaserPointerEnd ); FVector ClosestPointOnLaserPointer, ClosestPointOnUICapsule; FMath::SegmentDistToSegment( LaserPointerStartInCapsuleSpace, LaserPointerEndInCapsuleSpace, CapsuleStart, CapsuleEnd, /* Out */ ClosestPointOnLaserPointer, /* Out */ ClosestPointOnUICapsule ); const bool bIsClosestPointInsideCapsule = ( ClosestPointOnLaserPointer - ClosestPointOnUICapsule ).Size() <= CapsuleRadius; const FVector TowardLaserPointerVector = ( ClosestPointOnLaserPointer - ClosestPointOnUICapsule ).GetSafeNormal(); // Apply capsule radius ClosestPointOnUICapsule += TowardLaserPointerVector * CapsuleRadius; if( false ) // @todo vreditor debug { const float RenderCapsuleLength = ( CapsuleEnd - CapsuleStart ).Size() + CapsuleRadius * 2.0f; // @todo vreditor: This capsule draws with the wrong orientation if( false ) { DrawDebugCapsule( GetWorld(), CapsuleTransform.TransformPosition( CapsuleStart + ( CapsuleEnd - CapsuleStart ) * 0.5f ), RenderCapsuleLength * 0.5f, CapsuleRadius, CapsuleTransform.GetRotation() * FRotator( 90.0f, 0, 0 ).Quaternion(), FColor::Green, false, 0.0f ); } DrawDebugLine( GetWorld(), CapsuleTransform.TransformPosition( ClosestPointOnLaserPointer ), CapsuleTransform.TransformPosition( ClosestPointOnUICapsule ), FColor::Green, false, 0.0f ); DrawDebugSphere( GetWorld(), CapsuleTransform.TransformPosition( ClosestPointOnLaserPointer ), 1.5f * WorldScaleFactor, 32, FColor::Red, false, 0.0f ); DrawDebugSphere( GetWorld(), CapsuleTransform.TransformPosition( ClosestPointOnUICapsule ), 1.5f * WorldScaleFactor, 32, FColor::Green, false, 0.0f ); } // If we're really close to the capsule if( bIsClosestPointInsideCapsule || ( ClosestPointOnUICapsule - ClosestPointOnLaserPointer ).Size() <= MinDistanceToCapsule ) { const FVector LaserPointerDirectionInCapsuleSpace = ( LaserPointerEndInCapsuleSpace - LaserPointerStartInCapsuleSpace ).GetSafeNormal(); if( false ) // @todo vreditor debug { DrawDebugLine( GetWorld(), CapsuleTransform.TransformPosition( FVector::ZeroVector ), CapsuleTransform.TransformPosition( CapsuleFrontDirection * 5.0f ), FColor::Yellow, false, 0.0f ); DrawDebugLine( GetWorld(), CapsuleTransform.TransformPosition( FVector::ZeroVector ), CapsuleTransform.TransformPosition( -LaserPointerDirectionInCapsuleSpace * 5.0f ), FColor::Purple, false, 0.0f ); } const float Dot = FVector::DotProduct( CapsuleFrontDirection, -LaserPointerDirectionInCapsuleSpace ); if( Dot >= MinDotForAimingAtCapsule ) { bIsAimingTowards = true; } } } return bIsAimingTowards; }
bool CreatureCore::IsBluePrintBonesCollide(FVector test_point, float bone_size, FTransform base_transform) { if (bone_size <= 0) { bone_size = 1.0f; } FTransform xform = base_transform; FVector local_test_point = xform.InverseTransformPosition(test_point); auto render_composition = creature_manager->GetCreature()->GetRenderComposition(); auto& bones_map = render_composition->getBonesMap(); glm::vec4 real_test_pt(local_test_point.X, local_test_point.Y, local_test_point.Z, 1.0f); for (auto cur_data : bones_map) { auto cur_bone = cur_data.second; auto bone_start_pt = cur_bone->getWorldStartPt(); auto bone_end_pt = cur_bone->getWorldEndPt(); auto bone_vec = bone_end_pt - bone_start_pt; auto bone_length = glm::length(bone_vec); auto bone_unit_vec = bone_vec / bone_length; auto rel_vec = real_test_pt - bone_start_pt; float proj_length_u = glm::dot(rel_vec, bone_unit_vec); if (proj_length_u >= 0 && proj_length_u <= bone_length) { // quick rotation by 90 degrees auto bone_unit_normal_vec = bone_unit_vec; bone_unit_normal_vec.x = -bone_unit_vec.y; bone_unit_normal_vec.y = bone_unit_vec.x; float proj_length_v = fabs(glm::dot(rel_vec, bone_unit_normal_vec)); if (proj_length_v <= bone_size) { return true; } } } return false; }
FBox FBox::InverseTransformBy(const FTransform & M) const { FVector Vertices[8] = { FVector(Min), FVector(Min.X, Min.Y, Max.Z), FVector(Min.X, Max.Y, Min.Z), FVector(Max.X, Min.Y, Min.Z), FVector(Max.X, Max.Y, Min.Z), FVector(Max.X, Min.Y, Max.Z), FVector(Min.X, Max.Y, Max.Z), FVector(Max) }; FBox NewBox(0); for (int32 VertexIndex = 0; VertexIndex < ARRAY_COUNT(Vertices); VertexIndex++) { FVector4 ProjectedVertex = M.InverseTransformPosition(Vertices[VertexIndex]); NewBox += ProjectedVertex; } return NewBox; }
FVector UKismetMathLibrary::InverseTransformLocation(const FTransform& T, FVector Location) { return T.InverseTransformPosition(Location); }