void URotatingMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { // skip if we don't want component updated when not rendered or if updated component can't move if (ShouldSkipUpdate(DeltaTime)) { return; } Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if (!IsValid(UpdatedComponent)) { return; } // Compute new rotation const FQuat OldRotation = UpdatedComponent->GetComponentQuat(); const FQuat DeltaRotation = (RotationRate * DeltaTime).Quaternion(); const FQuat NewRotation = bRotationInLocalSpace ? (OldRotation * DeltaRotation) : (DeltaRotation * OldRotation); // Compute new location FVector DeltaLocation = FVector::ZeroVector; if (!PivotTranslation.IsZero()) { const FVector OldPivot = OldRotation.RotateVector(PivotTranslation); const FVector NewPivot = NewRotation.RotateVector(PivotTranslation); DeltaLocation = (OldPivot - NewPivot); // ConstrainDirectionToPlane() not necessary because it's done by MoveUpdatedComponent() below. } const bool bEnableCollision = false; MoveUpdatedComponent(DeltaLocation, NewRotation, bEnableCollision); }
//Conversion - use find and replace to change behavior, no scaling version is typically used for orientations FVector ConvertLeapToUE(Leap::Vector LeapVector) { //Convert Axis FVector ConvertedVector = FVector(-LeapVector.z, LeapVector.x, LeapVector.y); //Hmd orientation adjustment if (LeapShouldAdjustForFacing) { FRotator Rotation = FRotator(90.f, 0.f, 180.f); ConvertedVector = FQuat(Rotation).RotateVector(ConvertedVector); if (LeapShouldAdjustRotationForHMD) { if (GEngine->HMDDevice.IsValid()) { FQuat orientationQuat; FVector position; GEngine->HMDDevice->GetCurrentOrientationAndPosition(orientationQuat, position); ConvertedVector = orientationQuat.RotateVector(ConvertedVector); } } } return ConvertedVector; }
//Conversion - use find and replace to change behavior, no scaling version is typically used for orientations FVector convertLeapToUE(Leap::Vector leapVector) { //Convert Axis FVector vect = FVector(-leapVector.z, leapVector.x, leapVector.y); //Hmd orientation adjustment if (LeapShouldAdjustForFacing) { FRotator rotation = FRotator(90.f, 0.f, 180.f); vect = FQuat(rotation).RotateVector(vect); if (LeapShouldAdjustRotationForHMD) { if (GEngine->HMDDevice.IsValid()) { FQuat orientationQuat; FVector position; GEngine->HMDDevice->GetCurrentOrientationAndPosition(orientationQuat, position); vect = orientationQuat.RotateVector(vect); } } } return vect; }
void UDestructibleComponent::SetChunksWorldTM(const TArray<FUpdateChunksInfo>& UpdateInfos) { const FQuat InvRotation = ComponentToWorld.GetRotation().Inverse(); for (const FUpdateChunksInfo& UpdateInfo : UpdateInfos) { // Bone 0 is a dummy root bone const int32 BoneIndex = ChunkIdxToBoneIdx(UpdateInfo.ChunkIndex); const FVector WorldTranslation = UpdateInfo.WorldTM.GetLocation(); const FQuat WorldRotation = UpdateInfo.WorldTM.GetRotation(); const FQuat BoneRotation = InvRotation*WorldRotation; const FVector BoneTranslation = InvRotation.RotateVector(WorldTranslation - ComponentToWorld.GetTranslation()) / ComponentToWorld.GetScale3D(); GetEditableSpaceBases()[BoneIndex] = FTransform(BoneRotation, BoneTranslation); } // Mark the transform as dirty, so the bounds are updated and sent to the render thread MarkRenderTransformDirty(); // New bone positions need to be sent to render thread MarkRenderDynamicDataDirty(); //Update bone visibilty and flip the editable space base buffer FlipEditableSpaceBases(); }
FVector adjustForHMD(FVector in) { if (GEngine->HMDDevice.IsValid()) { FQuat orientationQuat; FVector position; GEngine->HMDDevice->GetCurrentOrientationAndPosition(orientationQuat, position); FVector out = orientationQuat.RotateVector(in); if (LeapShouldAdjustPositionForHMD) { if (LeapShouldAdjustForMountOffset) position += orientationQuat.RotateVector(FVector(LEAP_MOUNT_OFFSET, 0, 0)); out += position; } return out; } else return in; }
FVector USplineComponent::GetRightVectorAtSplineInputKey(float InKey, ESplineCoordinateSpace::Type CoordinateSpace) const { const FQuat Quat = GetQuaternionAtSplineInputKey(InKey, ESplineCoordinateSpace::Local); FVector RightVector = Quat.RotateVector(FVector::RightVector); if (CoordinateSpace == ESplineCoordinateSpace::World) { RightVector = ComponentToWorld.TransformVectorNoScale(RightVector); } return RightVector; }
void UBerserkCameraComponent::UpdateCameraBounds(const APlayerController* playerController) { auto const* const localPlayer = Cast<ULocalPlayer>(playerController->Player); if (localPlayer == nullptr || localPlayer->ViewportClient == nullptr) return; FVector2D currentViewportSize; localPlayer->ViewportClient->GetViewportSize(currentViewportSize); // calc frustum edge direction, from bottom left corner if (CameraMovementBounds.GetSize() == FVector::ZeroVector || currentViewportSize != CameraMovementViewportSize) { // calc frustum edge direction, from bottom left corner const FVector frustumRay2dDir = FVector(1, 1, 0).GetSafeNormal(); const FVector frustumRay2dRight = FVector::CrossProduct(frustumRay2dDir, FVector::UpVector); const FQuat rotQuat(frustumRay2dRight, FMath::DegreesToRadians(90.0f - playerController->PlayerCameraManager->GetFOVAngle() * 0.5f)); const FVector frustumRayDir = rotQuat.RotateVector(frustumRay2dDir); // collect 3 world bounds' points and matching frustum rays (bottom left, top left, bottom right) auto const* const gameState = GetWorld()->GetGameState<ABerserkGameState>(); if (gameState) { const auto worldBounds = gameState->WorldBounds; if (worldBounds.GetSize() != FVector::ZeroVector) { const FVector worldBoundPoints[] = { FVector(worldBounds.Min.X, worldBounds.Min.Y, worldBounds.Max.Z), FVector(worldBounds.Min.X, worldBounds.Max.Y, worldBounds.Max.Z), FVector(worldBounds.Max.X, worldBounds.Min.Y, worldBounds.Max.Z) }; const FVector frustumRays[] = { FVector(frustumRayDir.X, frustumRayDir.Y, frustumRayDir.Z), FVector(frustumRayDir.X, -frustumRayDir.Y, frustumRayDir.Z), FVector(-frustumRayDir.X, frustumRayDir.Y, frustumRayDir.Z) }; // get camera plane for intersections const auto cameraPlane = FPlane(playerController->GetFocalLocation(), FVector::UpVector); // get matching points on camera plane const FVector cameraPlanePoints[3] = { FProjectionUtils::IntersectRayWithPlane(worldBoundPoints[0], frustumRays[0], cameraPlane) * MiniMapBoundsLimit, FProjectionUtils::IntersectRayWithPlane(worldBoundPoints[1], frustumRays[1], cameraPlane) * MiniMapBoundsLimit, FProjectionUtils::IntersectRayWithPlane(worldBoundPoints[2], frustumRays[2], cameraPlane) * MiniMapBoundsLimit }; // create new bounds CameraMovementBounds = FBox(cameraPlanePoints, 3); CameraMovementViewportSize = currentViewportSize; } } } }
FVector adjustForHMDOrientation(FVector In) { if (GEngine->HMDDevice.IsValid()) { FQuat OrientationQuat; FVector Position; GEngine->HMDDevice->GetCurrentOrientationAndPosition(OrientationQuat, Position); FVector Out = OrientationQuat.RotateVector(In); return Out; } else return In; }
FVector AdjustForHMD(FVector In) { if (GEngine->HMDDevice.IsValid()) { FQuat OrientationQuat; FVector Position; GEngine->HMDDevice->GetCurrentOrientationAndPosition(OrientationQuat, Position); FVector Out = OrientationQuat.RotateVector(In); if (LeapShouldAdjustPositionForHMD) { if (LeapShouldAdjustForMountOffset) { Position += OrientationQuat.RotateVector(LeapMountOffset); } Out += Position; } return Out; } else { return In; } }
FVector adjustForHMDOrientation(FVector in) { if (GEngine->HMDDevice.IsValid()) { FQuat orientationQuat; FVector position; GEngine->HMDDevice->GetCurrentOrientationAndPosition(orientationQuat, position); FVector out = orientationQuat.RotateVector(in); return out; } else return in; }
FQuat USplineComponent::GetQuaternionAtSplineInputKey(float InKey, ESplineCoordinateSpace::Type CoordinateSpace) const { FQuat Quat = SplineRotInfo.Eval(InKey, FQuat::Identity); Quat.Normalize(); const FVector Direction = SplineInfo.EvalDerivative(InKey, FVector::ZeroVector).GetSafeNormal(); const FVector UpVector = Quat.RotateVector(DefaultUpVector); FQuat Rot = (FRotationMatrix::MakeFromXZ(Direction, UpVector)).ToQuat(); if (CoordinateSpace == ESplineCoordinateSpace::World) { Rot = ComponentToWorld.GetRotation() * Rot; } return Rot; }
FTransform FActorPositioning::GetSurfaceAlignedTransform(const FPositioningData& Data) { // Sort out the rotation first, then do the location FQuat RotatorQuat = Data.StartTransform.GetRotation(); if (Data.ActorFactory) { RotatorQuat = Data.ActorFactory->AlignObjectToSurfaceNormal(Data.SurfaceNormal, RotatorQuat); } // Choose the largest location offset of the various options (global viewport settings, collision, factory offset) const float SnapOffsetExtent = GetDefault<ULevelEditorViewportSettings>()->SnapToSurface.SnapOffsetExtent; const float CollisionOffsetExtent = FVector::BoxPushOut(Data.SurfaceNormal, Data.PlacementExtent); FVector LocationOffset = Data.SurfaceNormal * FMath::Max(SnapOffsetExtent, CollisionOffsetExtent); if (Data.ActorFactory && LocationOffset.SizeSquared() < Data.ActorFactory->SpawnPositionOffset.SizeSquared()) { // Rotate the Spawn Position Offset to match our rotation LocationOffset = RotatorQuat.RotateVector(-Data.ActorFactory->SpawnPositionOffset); } return FTransform(Data.bAlignRotation ? RotatorQuat : Data.StartTransform.GetRotation(), Data.SurfaceLocation + LocationOffset); }
/** * Updates the camera position. Called every frame by UpdateSimulation. * * @param UserImpulse User impulse data for the current frame * @param DeltaTime Time interval * @param MovementSpeedScale Additional movement accel/speed scale * @param CameraEuler Current camera rotation * @param InOutCameraPosition [in, out] Camera position */ void FEditorCameraController::UpdatePosition( const FCameraControllerUserImpulseData& UserImpulse, const float DeltaTime, const float MovementSpeedScale, const FVector& CameraEuler, FVector& InOutCameraPosition ) { // Compute local impulse FVector LocalSpaceImpulse; { // NOTE: Forward/back and right/left impulse are applied in local space, but up/down impulse is // applied in world space. This is because it feels more intuitive to always move straight // up or down with those controls. LocalSpaceImpulse = FVector( UserImpulse.MoveForwardBackwardImpulse, // Local space forward/back UserImpulse.MoveRightLeftImpulse, // Local space right/left 0.0f ); // Local space up/down } // Compute world space acceleration FVector WorldSpaceAcceleration; { // Compute camera orientation, then rotate our local space impulse to world space const FQuat CameraOrientation = FQuat::MakeFromEuler( CameraEuler ); FVector WorldSpaceImpulse = CameraOrientation.RotateVector( LocalSpaceImpulse ); // Accumulate any world space impulse we may have // NOTE: Up/down impulse is applied in world space. See above comments for more info. WorldSpaceImpulse += FVector( 0.0f, // World space forward/back 0.0f, // World space right/left UserImpulse.MoveUpDownImpulse ); // World space up/down // Cap impulse by normalizing, but only if our magnitude is greater than 1.0 //if( WorldSpaceImpulse.SizeSquared() > 1.0f ) { //WorldSpaceImpulse = WorldSpaceImpulse.UnsafeNormal(); } // Compute world space acceleration WorldSpaceAcceleration = WorldSpaceImpulse * Config.MovementAccelerationRate * MovementSpeedScale; } if( Config.bUsePhysicsBasedMovement ) { // Accelerate the movement velocity MovementVelocity += WorldSpaceAcceleration * DeltaTime; // Apply damping { const float DampingFactor = FMath::Clamp( Config.MovementVelocityDampingAmount * DeltaTime, 0.0f, 0.75f ); // Decelerate MovementVelocity += -MovementVelocity * DampingFactor; } } else { // No physics, so just use the acceleration as our velocity MovementVelocity = WorldSpaceAcceleration; } // Constrain maximum movement speed if( MovementVelocity.Size() > Config.MaximumMovementSpeed * MovementSpeedScale ) { MovementVelocity = MovementVelocity.GetUnsafeNormal() * Config.MaximumMovementSpeed * MovementSpeedScale; } // Clamp velocity to a reasonably small number if( MovementVelocity.Size() < KINDA_SMALL_NUMBER ) { MovementVelocity = FVector::ZeroVector; } // Update camera position InOutCameraPosition += MovementVelocity * DeltaTime; }
void FViewExtension::PreRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& View) { check(IsInRenderingThread()); FViewExtension& RenderContext = *this; FGameFrame* CurrentFrame = static_cast<FGameFrame*>(RenderContext.RenderFrame.Get()); if (!RenderContext.ShowFlags.Rendering || !CurrentFrame || !CurrentFrame->Settings->IsStereoEnabled()) { return; } const ovrEyeType eyeIdx = (View.StereoPass == eSSP_LEFT_EYE) ? ovrEye_Left : ovrEye_Right; if (RenderContext.ShowFlags.Rendering && CurrentFrame->Settings->Flags.bUpdateOnRT) { FQuat CurrentEyeOrientation; FVector CurrentEyePosition; CurrentFrame->PoseToOrientationAndPosition(RenderContext.CurEyeRenderPose[eyeIdx], CurrentEyeOrientation, CurrentEyePosition); FQuat ViewOrientation = View.ViewRotation.Quaternion(); // recalculate delta control orientation; it should match the one we used in CalculateStereoViewOffset on a game thread. FVector GameEyePosition; FQuat GameEyeOrient; CurrentFrame->PoseToOrientationAndPosition(CurrentFrame->EyeRenderPose[eyeIdx], GameEyeOrient, GameEyePosition); const FQuat DeltaControlOrientation = ViewOrientation * GameEyeOrient.Inverse(); // make sure we use the same viewrotation as we had on a game thread check(View.ViewRotation == CurrentFrame->CachedViewRotation[eyeIdx]); if (CurrentFrame->Flags.bOrientationChanged) { // Apply updated orientation to corresponding View at recalc matrices. // The updated position will be applied from inside of the UpdateViewMatrix() call. const FQuat DeltaOrient = View.BaseHmdOrientation.Inverse() * CurrentEyeOrientation; View.ViewRotation = FRotator(ViewOrientation * DeltaOrient); //UE_LOG(LogHMD, Log, TEXT("VIEWDLT: Yaw %.3f Pitch %.3f Roll %.3f"), DeltaOrient.Rotator().Yaw, DeltaOrient.Rotator().Pitch, DeltaOrient.Rotator().Roll); } if (!CurrentFrame->Flags.bPositionChanged) { // if no positional change applied then we still need to calculate proper stereo disparity. // use the current head pose for this calculation instead of the one that was saved on a game thread. FQuat HeadOrientation; CurrentFrame->PoseToOrientationAndPosition(RenderContext.CurHeadPose, HeadOrientation, View.BaseHmdLocation); } // The HMDPosition already has HMD orientation applied. // Apply rotational difference between HMD orientation and ViewRotation // to HMDPosition vector. const FVector DeltaPosition = CurrentEyePosition - View.BaseHmdLocation; const FVector vEyePosition = DeltaControlOrientation.RotateVector(DeltaPosition) + CurrentFrame->Settings->PositionOffset; View.ViewLocation += vEyePosition; //UE_LOG(LogHMD, Log, TEXT("VDLTPOS: %.3f %.3f %.3f"), vEyePosition.X, vEyePosition.Y, vEyePosition.Z); if (CurrentFrame->Flags.bOrientationChanged || CurrentFrame->Flags.bPositionChanged) { View.UpdateViewMatrix(); } } FSettings* FrameSettings = CurrentFrame->GetSettings(); check(FrameSettings); FrameSettings->EyeLayer.EyeFov.RenderPose[eyeIdx] = RenderContext.CurEyeRenderPose[eyeIdx]; }