# "LockToHMD" causes HMD tracking to be world rather than parent relative

**URL:** <https://forums.unrealengine.com/t/locktohmd-causes-hmd-tracking-to-be-world-rather-than-parent-relative/353567>\
**Category:** XR Development\
**Tags:** rotation, axis, world-space, unreal-engine, hmd, question\
**Created:** [April 9, 2016, 7:03pm UTC](https://forums.unrealengine.com/t/locktohmd-causes-hmd-tracking-to-be-world-rather-than-parent-relative/353567 "2016-04-09T19:03:46Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Teiwaz](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Teiwaz](https://forums.unrealengine.com/u/Teiwaz)\
**Post date:** [April 9, 2016, 7:03pm UTC](https://forums.unrealengine.com/t/locktohmd-causes-hmd-tracking-to-be-world-rather-than-parent-relative/353567/1 "2016-04-09T19:03:46Z")

</div>

In 4.11, in the VR camera refactor, a “bLockToHMD” flag was added in order to make tracking the player head in world space easier.

However, the way this was implemented, the head transform is always applied in world space, no matter which way the camera component is actually facing (due to being attached to a parent component which can rotate). So leaning forward always causes the camera to move on the world +x axis, even if the player pawn is facing down the y axis.

The root of the problem is in UCameraComponent::GetCameraView:

```
if (bLockToHmd && GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHeadTrackingAllowed())
	{
		ResetRelativeTransform();
		const FTransform ParentWorld = GetComponentToWorld();

		GEngine->HMDDevice->SetupLateUpdate(ParentWorld, this);

		FQuat Orientation;
		FVector Position;
		if (GEngine->HMDDevice->UpdatePlayerCamera(Orientation, Position))
		{
			SetRelativeTransform(FTransform(Orientation, Position));
		}
	}

```

Should be:

```
if (bLockToHmd && GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHeadTrackingAllowed())
	{
		ResetRelativeTransform();
		
		FTransform ParentWorld;
		if (GetAttachParent())
		{
			ParentWorld = GetAttachParent()->GetComponentToWorld();
		}
		else
		{
			ParentWorld = GetComponentToWorld();
		}

		GEngine->HMDDevice->SetupLateUpdate(ParentWorld, this);

		FQuat Orientation;
		FVector Position;
		if (GEngine->HMDDevice->UpdatePlayerCamera(Orientation, Position))
		{
			SetRelativeTransform(FTransform(Orientation, Position));
		}
	}
```

---

<div class="post-metadata">

**Author:** ![Nintynuts](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Nintynuts](https://forums.unrealengine.com/u/Nintynuts)\
**Post date:** [April 11, 2016, 9:06am UTC](https://forums.unrealengine.com/t/locktohmd-causes-hmd-tracking-to-be-world-rather-than-parent-relative/353567/2 "2016-04-11T09:06:45Z")

</div>

I think you have to use an empty “Scene” base as a parent to set the position and rotation, but there still seems to be issues with it. These questions are related, and one of them mentions a submitted fix.

> **[4.11 VR Camera rotation/world scale issues](https://forums.unrealengine.com/questions/401872/411-vr-camera-rotationworld-scale-issues.html)**
>
> I have had this problem with both 4.11.1 and 4.11. I am trying to use the couch knights demo, and it works fine for the first player, but not player 2. The camera orientation relative to the character head is always facing in the same direction. I...

> **[4.11 VR Camera - Lock to HMD - Broken First Person VR](https://forums.unrealengine.com/questions/397245/411-vr-camera-lock-to-hmd-first-person.html)**
>
> The new Lock to HMD functionality of the new Camera Component seems great. It allows me to know where the camera's location is without doing some math. It also lets me attach objects to the camera without doing math on tick. This is great, but it's...

---

<div class="post-metadata">

**Author:** ![Teiwaz](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Teiwaz](https://forums.unrealengine.com/u/Teiwaz)\
**Post date:** [April 16, 2016, 7:06pm UTC](https://forums.unrealengine.com/t/locktohmd-causes-hmd-tracking-to-be-world-rather-than-parent-relative/353567/3 "2016-04-16T19:06:39Z")

</div>

The empty scene base lets you properly offset the camera position in the world. The problem is that translation from head positional tracking is applied in the parent’s local space, but rather to world space, whereas rotation _is_ applied in the parent’s local space. This means that if you rotate the parent, the camera’s rotation inherits the rotation, but then when you move your head the translation is applied out of alignment with the current head rotation. (i.e. if the parent is rotated 90o right, the camera looks 90o right, but if you lean forward the camera moves 90o left relative to its orientation.)

The post with the fix you linked above was mine, and the fix I was referring to was the one in this bug report. It _hasn’t_ been pushed to the git project, because of lawyers and the fact that I don’t …entirely… understand why it works. (SetupLateUpdate heads into rendererland and I think the root problem is a timing issue. There there be dragons.)

---

<div class="post-metadata">

**Author:** ![Nintynuts](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Nintynuts](https://forums.unrealengine.com/u/Nintynuts)\
**Post date:** [April 16, 2016, 10:07pm UTC](https://forums.unrealengine.com/t/locktohmd-causes-hmd-tracking-to-be-world-rather-than-parent-relative/353567/4 "2016-04-16T22:07:14Z")

</div>

By bad. Didn’t realise you were the same person. I hope someone who understands it completely will push a fix to GitHub and soon after release a hotfix.

---

<div class="post-metadata">

**Author:** ![anonymous\_user\_e729f54e](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@anonymous\_user\_e729f54e](https://forums.unrealengine.com/u/anonymous_user_e729f54e)\
**Post date:** [April 18, 2016, 5:09pm UTC](https://forums.unrealengine.com/t/locktohmd-causes-hmd-tracking-to-be-world-rather-than-parent-relative/353567/5 "2016-04-18T17:09:00Z")

</div>

Hello Teiwaz,

I was able to reproduce this issue on our end. I have written up a report (UE-29579) and I have submitted to the developers for further consideration. I will provide updates with any pertinent information as it becomes available. Thank you for your time and information.

Make it a great day

---

<div class="post-metadata">

**Author:** ![Cameron\_Abt](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Cameron\_Abt](https://forums.unrealengine.com/u/Cameron_Abt)\
**Post date:** [June 17, 2016, 3:02pm UTC](https://forums.unrealengine.com/t/locktohmd-causes-hmd-tracking-to-be-world-rather-than-parent-relative/353567/6 "2016-06-17T15:02:37Z")

</div>

I was having the same issue with the late update translating the wrong direction when having the player start not rotated at 0,0,0. Though I don’t see UE-29579 in the 4.12.3 hotfix changelog ([4.12.3 Hotfix Released - Announcements - Epic Developer Community Forums](https://forums.unrealengine.com/showthread.php?114235-4-12-3-Hotfix-Released)), when I merged the 4.12.3 code into my current engine branch, and it seemed to fix the issue. Now whenever I rotate the player start everything works correctly.

I haven’t tried to rotate the player in-game, but translating it (teleporting) doesn’t cause an issue.

Maybe this JIRA# was also a fix for this issue? UE-31787 : Positional Latency w/ Rotation

Here’s the code change inside of SteamVRHMD.cpp from GitHub:

```
     if (bImplicitHmdPosition)
       {
 + const FQuat DeltaControlOrientation = View.ViewRotation.Quaternion() * TrackingFrame.DeviceOrientation[vr::k_unTrackedDeviceIndex_Hmd].Inverse();
           const FVector DeltaPosition = TrackingFrame.DevicePosition[vr::k_unTrackedDeviceIndex_Hmd] - View.BaseHmdLocation;
 - View.ViewLocation += DeltaPosition;
 + View.ViewLocation += DeltaControlOrientation.RotateVector(DeltaPosition);
       }

```

Thanks,  
Cameron
