When the UE4 API doesn't play ball

So it’s probably just my inexperience, but every now and then I run into API or C++ (or both) issues that make me scratch my head. Like in this case where I’m trying to implement the most simple thing in C++ that took all but 10 secs in Blueprint.

reset_vr_view.png

What this intricate algorithm does is, well, reset the VR view. You put that helmet on, sit up straight and relaxed and reset the view to match your viewing position. Let’s implement this in C++ just for the heck of it. So let’s start by looking behind the curtain of that node.

Runtime\Engine\Classes\Kismet\HeadMountedDisplayFunctionLibrary.h



	UFUNCTION(BlueprintCallable, Category="Input|HeadMountedDisplay")
	static void ResetOrientationAndPosition(float Yaw = 0.f);


Runtime\Engine\Private\HeadMountedDisplayFunctionLibrary.cpp



void UHeadMountedDisplayFunctionLibrary::ResetOrientationAndPosition(float Yaw)
{
	if (GEngine->HMDDevice.IsValid() && GEngine->IsStereoscopic3D())
	{
		GEngine->HMDDevice->ResetOrientationAndPosition(Yaw);
	}
}


Alright, that seems straight forward. Of course that stuff doesn’t get exported so I can’t use that function outright? And also I probably shouldn’t because they were meant for Blueprints. That’s what the annoying guy in the back of my head says anyway. So let’s just use it in my Pawn like this:



void AIkoPawn::ResetVRView()
{
	if (GEngine->HMDDevice.IsValid() && GEngine->IsStereoscopic3D())
	{
		GEngine->HMDDevice->ResetOrientationAndPosition(0.f);
	}
}


Compiler: Ay, ay, ay, no me gusta!



Error	1	error C2027: use of undefined type 'IHeadMountedDisplay'
Error	2	error C2039: 'ResetOrientationAndPosition' : is not a member of 'TSharedPtr<IHeadMountedDisplay,0>'


Hmm… let’s try to find something to include! That’s always fun, bit like easter.



#include "Runtime/HeadMountedDisplay/Public/IHeadMountedDisplay.h"


Compiler: Pfft, not even gonna honor that with a response…
Me: Sorry! You never know!
Compiler: …



Error	1	error C2027: use of undefined type 'IHeadMountedDisplay'
Error	2	error C2039: 'ResetOrientationAndPosition' : is not a member of 'TSharedPtr<IHeadMountedDisplay,0>'


So lets try to outsmart UE4. It’s as easy as beating Kasparov in chess. What’s in that interface?



virtual void ResetOrientationAndPosition(float Yaw = 0.f) = 0;


And who dares implement that?

Plugins\Runtime\OculusRift\Source\OculusRift\Private\OculusRiftHMD.h


virtual void ResetOrientationAndPosition(float yaw = 0.f) override;

Plugins\Experimental\SteamVR\Source\SteamVR\Private\SteamVRHMD.h


virtual void ResetOrientationAndPosition(float yaw = 0.f) override;

Can’t very well include a plugin header file can I. It couldn’t possibly make sense to include those 2 implementations anyway. In the background a compiler giggles faintly. Oh, I know!



void AIkoPawn::ResetVRView()
{
	if (GEngine->HMDDevice.IsValid() && GEngine->IsStereoscopic3D())
	{
		FOculusRiftHMD::ResetOrientationAndPosition(0.f);
	}
}


Compiler: HA HA HA!! You god damned fool don’t even know what a static method is! Hint: this isn’t one!
Me: Oh shut it.
Compiler: And you’re calling code in a PLUGIN! Keep 'em coming, you’re a ******* comedian!

Ok maybe a little more systematic. Concentrate, think. After some testing the error actually happens here:



	GEngine->HMDDevice**->**ResetOrientationAndPosition(0.f);


Intellisense says “pointer to incomplete class type is not allowed”, and of course that error from earlier, ‘ResetOrientationAndPosition’ : is not a member of ‘TSharedPtr<IHeadMountedDisplay,0>’.

So let’s look at this TSharedPtr. Aha, oho, interesting. Perhaps I need to do something really intelligent.



void AIkoPawn::ResetVRView()
{
	if (GEngine->HMDDevice.IsValid() && GEngine->IsStereoscopic3D())
	{
		TSharedPtr<IHeadMountedDisplay> Dudley;
		Dudley = GEngine->HMDDevice;
		FOculusRiftHMD Dudders = Cast<FOculusRiftHMD>(*dudley);
		dudders->ResetOrientationAndPosition(0.f);
	}
}


Squiggly hell. Maybe a little more Rama.



[FONT=Comic Sans MS]void AIkoPawn::ResetVRView()
{
	if (GEngine->HMDDevice.IsValid() && GEngine->IsStereoscopic3D())
	{
		[COLOR="#FFD700"]♥TSharedPtr<IHeadMountedDisplay> ♥Dudley;
		Dudley = GEngine->HMDDevice;
                ♥♥♥♥♥♥
		FOculusRiftHMD Dudders = Cast<FOculusRiftHMD>(*dudley);
		dudders->ResetOrientationAndPosition(0.f);♥
	}[/COLOR]
}


Compiler (giving Gollum impression): My eyses, they burn!!!
Me: You know what, I’ll do it in Blueprint.
Compiler: Owned.


#include "Runtime/HeadMountedDisplay/Public/IHeadMountedDisplay.h"
..
Error	1	error C2027: use of undefined type 'IHeadMountedDisplay'


So, something didn’t work the way you expected it to.
Is your code in a header file in turn? Do you have mutual inclusion problems? Is the include actually ahead of the function call? Is it included inside a namespace by accident?
Because, that should work. If it doesn’t, then something else is wrong, and you’d be better of figuring out what that is, than trying to “cheat.”
Btw: If you figure this out, I’d be interested in hearing, because there may be some subtle gotcha that makes supposedly straightforward code go pear shaped, and the more cases I hear about, the better prepared I am :slight_smile:

It was late, I wasn’t entirely serious. I’ll probably look into it some more but if someone has a solution I’m all ears :slight_smile:

I don’t have a HeadSet to test it with, but for me, adding include “Runtime/HeadMountedDisplay/Public/HeadMountedDisplay.h” and adding “HeadMountedDisplay” to the PublicDependencyModuleNames in my build.cs file, allows the code to compile with no errors.



if (GEngine->HMDDevice.IsValid() && GEngine->IsStereoscopic3D())
{
	GEngine->HMDDevice->ResetOrientationAndPosition(Yaw);
}

Indeed it does! I do still get a squiggly on GEngine saying “pointer to incomplete class type is not allowed”, but it compiles and works. So it was actually a UBT issue and had nothing to do with C++? I really need to look into the whole building thing more, that’s the last place I would have expected an issue.

Thanks a lot sir :slight_smile: