Oculus Rift separate view, based on existing tutorial

Hi all,

I am looking to alter the camera control on the Side Scroller C++ example project.
I want to fix the camera in a given position somewhere in the scene and control the camera rotation with the oculus rift to view the scene from different angles - essentially a mouse look.

I am following the short tutorial at: A new, community-hosted Unreal Engine Wiki - Announcements - Epic Developer Community Forums
When I follow the blueprint version on a new side scroller 3d project I indeed get a separate camera component, exactly as I want with its rotation controlled by the oculus.

When I do the c++ version, the camera is still tied to the player controller camera.
If I delete all the camera components from the player, the new camera is ‘stuck’ to the player.

I have created a new c++ PlayerCameraManager class and assigned that to the player controller in c++


	
bAutoManageActiveCameraTarget = false;
PlayerCameraManagerClass = MyPlayerCameraManager::StaticClass();


So this all works - but unlike the blueprint one, the new camera is stuck on the player.
Im chuffed I got to this point but I am unsure what step I need to do next to get that separated camera component.
Do I need to create a blueprint for it in the editor? Then create a normal single camera object and attach it to it?

Cheers

The code provided in the Oculus Rift Separate View tutorial is most likely very, very out of date.
I made the original code during the UE4 Beta :stuck_out_tongue:

That said, yes, try a camera component in your characters Blueprint.
I’ve always used a manually attached one.

Thanks for the reply mate,

I tried what you said but to no avail.

Just to describe my setup for a much better picture

My GameMode only has a constructor:




ATheTowerGameMode::ATheTowerGameMode()
{
	DefaultPawnClass = ATheTowerCharacter::StaticClass();
	PlayerControllerClass = ATowerPlayerController::StaticClass();
}



My TowerCharacter is the sidescroller c++ one, stripped back a little without the camera stuff:



// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "GameFramework/Character.h"
#include "TheTowerCharacter.generated.h"

UCLASS(config=Game)
class ATheTowerCharacter : public ACharacter
{
	GENERATED_BODY()

protected:

	/** Called for side to side input */
	void MoveRight(float Val);

	// APawn interface
	virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;
	// End of APawn interface


public:
	ATheTowerCharacter();

	virtual FRotator GetViewRotation() const override;
};





// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "TheTower.h"
#include "TheTowerCharacter.h"
#include "TowerPlayerController.h"

ATheTowerCharacter::ATheTowerCharacter()
{
	// Set size for collision capsule
	GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

	// Don't rotate when the controller rotates.
	bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false;
	bUseControllerRotationRoll = false;

	// Configure character movement
	GetCharacterMovement()->bOrientRotationToMovement = true; // Face in the direction we are moving..
	GetCharacterMovement()->RotationRate = FRotator(0.0f, 720.0f, 0.0f); // ...at this rotation rate
	GetCharacterMovement()->GravityScale = 2.f;
	GetCharacterMovement()->AirControl = 0.80f;
	GetCharacterMovement()->JumpZVelocity = 1000.f;
	GetCharacterMovement()->GroundFriction = 3.f;
	GetCharacterMovement()->MaxWalkSpeed = 600.f;
	GetCharacterMovement()->MaxFlySpeed = 600.f;

	// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) 
	// are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}

//////////////////////////////////////////////////////////////////////////
// Input

void ATheTowerCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
	// set up gameplay key bindings
	InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
	InputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
	InputComponent->BindAxis("MoveRight", this, &ATheTowerCharacter::MoveRight);

	InputComponent->BindTouch(IE_Pressed, this, &ATheTowerCharacter::TouchStarted);
	InputComponent->BindTouch(IE_Released, this, &ATheTowerCharacter::TouchStopped);
}

void ATheTowerCharacter::MoveRight(float Value)
{
	// add movement in that direction
	AddMovementInput(FVector(0.f,-1.f,0.f), Value);
}

FRotator ATheTowerCharacter::GetViewRotation() const
{
	if (ATowerPlayerController* MYPC = Cast<ATowerPlayerController>(Controller))
	{
		return MYPC->GetViewRotation();
	}
	else if (Role < ROLE_Authority)
	{
		// check if being spectated
		for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator)
		{
			APlayerController* PlayerController = *Iterator;
			if (PlayerController && PlayerController->PlayerCameraManager->GetViewTargetPawn() == this)
			{
				return PlayerController->BlendedTargetViewRotation;
			}
		}
	}

	return GetActorRotation();
}



My Player Controller Class



// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameFramework/PlayerController.h"
#include "TowerPlayerController.generated.h"

/**
 * 
 */
UCLASS()
class THETOWER_API ATowerPlayerController : public APlayerController
{
	GENERATED_BODY()
	
public:
	ATowerPlayerController();

	virtual void UpdateRotation(float DeltaTime) override;

	UFUNCTION(BlueprintCallable, Category = "Pawn")
	FRotator GetViewRotation() const;

	UFUNCTION(BlueprintCallable, Category = "Pawn")
	virtual void SetViewRotation(const FRotator& NewRotation);

	virtual void SetControlRotation(const FRotator& NewRotation) override;

protected:

	/**
	*  View & Movement direction are now separate.
	*  The controller rotation will determine which direction we will move.
	*  ViewRotation represents where we are looking.
	*/
	UPROPERTY()
		FRotator ViewRotation;
	
	
};




// Fill out your copyright notice in the Description page of Project Settings.

#include "TheTower.h"
#include "TowerPlayerController.h"
#include "TowerCameraManager.h"

// Make sure you include this!!
#include "IHeadMountedDisplay.h"
ATowerPlayerController::ATowerPlayerController()
{
	bAutoManageActiveCameraTarget = false;
	PlayerCameraManagerClass = ATowerCameraManager::StaticClass();
}

void ATowerPlayerController::UpdateRotation(float DeltaTime)
{
	// Calculate Delta to be applied on ViewRotation
	FRotator DeltaRot(RotationInput);

	FRotator NewControlRotation = GetControlRotation();

	if (PlayerCameraManager)
	{
		PlayerCameraManager->ProcessViewRotation(DeltaTime, NewControlRotation, DeltaRot);
	}

	SetControlRotation(NewControlRotation);

	if (!PlayerCameraManager || !PlayerCameraManager->bFollowHmdOrientation)
	{
		if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHeadTrackingAllowed())
		{
			FQuat HMDOrientation;
			FVector HMDPosition;

			// Disable bUpdateOnRT if using this method.
			GEngine->HMDDevice->GetCurrentOrientationAndPosition(HMDOrientation, HMDPosition);

			FRotator NewViewRotation = HMDOrientation.Rotator();

			// Only keep the yaw component from the controller.
			NewViewRotation.Yaw += NewControlRotation.Yaw;

			SetViewRotation(NewViewRotation);
		}
	}

	APawn* const P = GetPawnOrSpectator();
	if (P)
	{
		P->FaceRotation(NewControlRotation, DeltaTime);
	}
}

void ATowerPlayerController::SetControlRotation(const FRotator& NewRotation)
{
	ControlRotation = NewRotation;

	// Anything that is overriding view rotation will need to 
	// call SetViewRotation() after SetControlRotation().
	SetViewRotation(NewRotation);

	if (RootComponent && RootComponent->bAbsoluteRotation)
	{
		RootComponent->SetWorldRotation(GetControlRotation());
	}
}

void ATowerPlayerController::SetViewRotation(const FRotator& NewRotation)
{
	ViewRotation = NewRotation;
}

FRotator ATowerPlayerController::GetViewRotation() const
{
	return ViewRotation;
}



Finally my camera manager class ONLY has a constructor and it is only this:




ATowerCameraManager::ATowerCameraManager()
{
	bFollowHmdOrientation = true;
}


If you look at my screenshots, I have 2: one shows where the camera is, ‘attached’ on the player, and the other describes Ideally what I am trying to do.
I want the camera decoupled from the player, hopefully it’s own component and it sits in the same position and uses oculus to rotate and view the scene…

Does that explain it a little better?
Im about 6 months new to Unreal, but a seasoned dev in my professional life so I am hoping for some best practice guidance here!
Cheers again

Just quickly - When I knocked this up via blueprints, it worked as expected though the camera was in a weird spot it did allow me to see the scene.
If I could do all that is required via code, I would be pretty happy. That includes positioning the separate camera etc…

So…feeling reasonably stupid, but after some reading The easiest step from this point was to set the camera view target on the player controller via the level blueprint.
Simply placing my camera in the world, and then following the documentation.

No additional code for now but I might move this into c++

cheers

For anyone interested, the only change needed from c++ was to add a public actor variable to the character class to hold our camera object, and override BeginPlay in the same class:



public:
	ATheTowerCharacter();

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "View Target")
	ACameraActor* ViewTarget;

	virtual FRotator GetViewRotation() const override;

	virtual void BeginPlay() override;





void ATheTowerCharacter::BeginPlay()
{
	Super::BeginPlay();

	ATowerPlayerController* PlayerController = Cast<ATowerPlayerController>(Controller);
	if (PlayerController && this->ViewTarget)
	{
		PlayerController->SetViewTarget(this->ViewTarget);
	}
}


It opens up a whole new realm of thought and possibilities with multiple cameras and triggers…etc…

Cheers