FMatrix USkeletalMeshComponent::GetTransformMatrix() const { FTransform RootTransform = GetBoneTransform(0); FVector Translation; FQuat Rotation; // if in editor, it should always use localToWorld // if root motion is ignored, use root transform if( GetWorld()->IsGameWorld() || !SkeletalMesh ) { // add root translation info Translation = RootTransform.GetLocation(); } else { Translation = ComponentToWorld.TransformPosition(SkeletalMesh->RefSkeleton.GetRefBonePose()[0].GetTranslation()); } // if root rotation is ignored, use root transform rotation Rotation = RootTransform.GetRotation(); // now I need to get scale // only LocalToWorld will have scale FVector ScaleVector = ComponentToWorld.GetScale3D(); Rotation.Normalize(); return FScaleMatrix(ScaleVector)*FQuatRotationTranslationMatrix(Rotation, Translation); }
void ACharacter::OnRep_ReplicatedBasedMovement() { if (Role != ROLE_SimulatedProxy) { return; } // Skip base updates while playing root motion, it is handled inside of OnRep_RootMotion if (IsPlayingNetworkedRootMotionMontage()) { return; } TGuardValue<bool> bInBaseReplicationGuard(bInBaseReplication, true); const bool bBaseChanged = (BasedMovement.MovementBase != ReplicatedBasedMovement.MovementBase || BasedMovement.BoneName != ReplicatedBasedMovement.BoneName); if (bBaseChanged) { // Even though we will copy the replicated based movement info, we need to use SetBase() to set up tick dependencies and trigger notifications. SetBase(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName); } // Make sure to use the values of relative location/rotation etc from the server. BasedMovement = ReplicatedBasedMovement; if (ReplicatedBasedMovement.HasRelativeLocation()) { // Update transform relative to movement base const FVector OldLocation = GetActorLocation(); MovementBaseUtility::GetMovementBaseTransform(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName, CharacterMovement->OldBaseLocation, CharacterMovement->OldBaseQuat); const FVector NewLocation = CharacterMovement->OldBaseLocation + ReplicatedBasedMovement.Location; if (ReplicatedBasedMovement.HasRelativeRotation()) { // Relative location, relative rotation FRotator NewRotation = (FRotationMatrix(ReplicatedBasedMovement.Rotation) * FQuatRotationTranslationMatrix(CharacterMovement->OldBaseQuat, FVector::ZeroVector)).Rotator(); // TODO: need a better way to not assume we only use Yaw. NewRotation.Pitch = 0.f; NewRotation.Roll = 0.f; SetActorLocationAndRotation(NewLocation, NewRotation); } else { // Relative location, absolute rotation SetActorLocationAndRotation(NewLocation, ReplicatedBasedMovement.Rotation); } // When position or base changes, movement mode will need to be updated. This assumes rotation changes don't affect that. CharacterMovement->bJustTeleported |= (bBaseChanged || GetActorLocation() != OldLocation); INetworkPredictionInterface* PredictionInterface = Cast<INetworkPredictionInterface>(GetMovementComponent()); if (PredictionInterface) { PredictionInterface->SmoothCorrection(OldLocation); } } }
FMatrix PTransform2UMatrix(const PxTransform& PTM) { FQuat UQuat = P2UQuat(PTM.q); FVector UPos = P2UVector(PTM.p); FMatrix Result = FQuatRotationTranslationMatrix(UQuat, UPos); return Result; }
bool ACharacter::RestoreReplicatedMove(const FSimulatedRootMotionReplicatedMove& RootMotionRepMove) { UPrimitiveComponent* ServerBase = RootMotionRepMove.RootMotion.MovementBase; const FName ServerBaseBoneName = RootMotionRepMove.RootMotion.MovementBaseBoneName; // Relative Position if( RootMotionRepMove.RootMotion.bRelativePosition ) { bool bSuccess = false; if( MovementBaseUtility::UseRelativeLocation(ServerBase) ) { FVector BaseLocation; FQuat BaseRotation; MovementBaseUtility::GetMovementBaseTransform(ServerBase, ServerBaseBoneName, BaseLocation, BaseRotation); const FVector ServerLocation = BaseLocation + RootMotionRepMove.RootMotion.Location; FRotator ServerRotation; if (RootMotionRepMove.RootMotion.bRelativeRotation) { // Relative rotation ServerRotation = (FRotationMatrix(RootMotionRepMove.RootMotion.Rotation) * FQuatRotationTranslationMatrix(BaseRotation, FVector::ZeroVector)).Rotator(); } else { // Absolute rotation ServerRotation = RootMotionRepMove.RootMotion.Rotation; } UpdateSimulatedPosition(ServerLocation, ServerRotation); bSuccess = true; } // If we received local space position, but can't resolve parent, then move can't be used. :( if( !bSuccess ) { return false; } } // Absolute position else { UpdateSimulatedPosition(RootMotionRepMove.RootMotion.Location, RootMotionRepMove.RootMotion.Rotation); } SetBase( ServerBase, ServerBaseBoneName ); return true; }
bool AAIController::BuildPathfindingQuery(const FAIMoveRequest& MoveRequest, FPathFindingQuery& Query) const { bool bResult = false; UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld()); const ANavigationData* NavData = (NavSys == nullptr) ? nullptr : MoveRequest.IsUsingPathfinding() ? NavSys->GetNavDataForProps(GetNavAgentPropertiesRef()) : NavSys->GetAbstractNavData(); if (NavData) { FVector GoalLocation = MoveRequest.GetGoalLocation(); if (MoveRequest.IsMoveToActorRequest()) { const INavAgentInterface* NavGoal = Cast<const INavAgentInterface>(MoveRequest.GetGoalActor()); if (NavGoal) { const FVector Offset = NavGoal->GetMoveGoalOffset(this); GoalLocation = FQuatRotationTranslationMatrix(MoveRequest.GetGoalActor()->GetActorQuat(), NavGoal->GetNavAgentLocation()).TransformPosition(Offset); } else { GoalLocation = MoveRequest.GetGoalActor()->GetActorLocation(); } } FSharedConstNavQueryFilter NavFilter = UNavigationQueryFilter::GetQueryFilter(*NavData, this, MoveRequest.GetNavigationFilter()); Query = FPathFindingQuery(*this, *NavData, GetNavAgentLocation(), GoalLocation, NavFilter); Query.SetAllowPartialPaths(MoveRequest.IsUsingPartialPaths()); if (PathFollowingComponent) { PathFollowingComponent->OnPathfindingQuery(Query); } bResult = true; } else { UE_VLOG(this, LogAINavigation, Warning, TEXT("Unable to find NavigationData instance while calling AAIController::BuildPathfindingQuery")); } return bResult; }
void DrawDebugCapsule(const UWorld* InWorld, FVector const& Center, float HalfHeight, float Radius, const FQuat & Rotation, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority) { // no debug line drawing on dedicated server if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer) { const int32 DrawCollisionSides = 16; FVector Origin = Center; FMatrix Axes = FQuatRotationTranslationMatrix(Rotation, FVector::ZeroVector); FVector XAxis = Axes.GetScaledAxis( EAxis::X ); FVector YAxis = Axes.GetScaledAxis( EAxis::Y ); FVector ZAxis = Axes.GetScaledAxis( EAxis::Z ); // Draw top and bottom circles float HalfAxis = FMath::Max<float>(HalfHeight - Radius, 1.f); FVector TopEnd = Origin + HalfAxis*ZAxis; FVector BottomEnd = Origin - HalfAxis*ZAxis; DrawCircle(InWorld, TopEnd, XAxis, YAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority); DrawCircle(InWorld, BottomEnd, XAxis, YAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority); // Draw domed caps DrawHalfCircle(InWorld, TopEnd, YAxis, ZAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority); DrawHalfCircle(InWorld, TopEnd, XAxis, ZAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority); FVector NegZAxis = -ZAxis; DrawHalfCircle(InWorld, BottomEnd, YAxis, NegZAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority); DrawHalfCircle(InWorld, BottomEnd, XAxis, NegZAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority); // Draw connecty lines DrawDebugLine(InWorld, TopEnd + Radius*XAxis, BottomEnd + Radius*XAxis, Color, bPersistentLines, LifeTime, DepthPriority); DrawDebugLine(InWorld, TopEnd - Radius*XAxis, BottomEnd - Radius*XAxis, Color, bPersistentLines, LifeTime, DepthPriority); DrawDebugLine(InWorld, TopEnd + Radius*YAxis, BottomEnd + Radius*YAxis, Color, bPersistentLines, LifeTime, DepthPriority); DrawDebugLine(InWorld, TopEnd - Radius*YAxis, BottomEnd - Radius*YAxis, Color, bPersistentLines, LifeTime, DepthPriority); } }