Forum Discussion
owenwp
13 years agoExpert Protege
Incorrect IPD math (maybe)
I have been feeling that the world scale has been weird since the first release despite using correct numbers. I have also seen comments concerning IPD adjustment seeming to not have much effect. After digging through the code I have finally figured out why.
The IPD math is off. The ingame cameras are being spaced (your IPD)+64mm apart, which for the average person makes the world appear exactly half its expected size. This stuff is kind of off the beaten path of CG, so I will try to be thorough if a bit long-winded. Please bear with me.
The reason is that an IPD offset is being applied on top of the lens offset. When the projection matrix is constructed it is transformed 32mm in either direction in post-perspective-transform screen space so that it lines up with the center of the each lens. For a 1:1 scale world that results in a 32mm transform in world space as well. You can make sense of this by thinking of sliding the eye position along the near plane of the camera.
But, after this is done, the camera transform position is also shifted IPD/2mm in either direction. For the above person, this would put the centers of the ingame cameras a total of 128mm apart.
Try substituting the OVRCameraController.ConfigureCamera method with the code below, which instead offsets the eye positions by the difference between IPD and inter-lens distance:
If you load up Tuscany, set your IPD and height correctly (it defaults to you being super tall) and play standing, you should see a night and day difference from before. Everything seems exactly as big and as distant as it should be. The high vaulted ceiling looks as impressive as it should be for being over two stories high. Go back to the unmodified Tuscany and it feels like a dollhouse.
If you don't trust my explanation, try to simply set eyePositionOffset to zero. Far from getting zero stereo separation as you might intuitively expect, it should look very close to correct if you have average IPD.
I haven't looked at the C++ samples yet, and I don't think the Unreal code is accessible, but I suspect they have the same problem. The Unreal demos I tried also made the world seem tiny, though thats made worse by the intentionally out of proportion design of most unreal samples.
The IPD math is off. The ingame cameras are being spaced (your IPD)+64mm apart, which for the average person makes the world appear exactly half its expected size. This stuff is kind of off the beaten path of CG, so I will try to be thorough if a bit long-winded. Please bear with me.
The reason is that an IPD offset is being applied on top of the lens offset. When the projection matrix is constructed it is transformed 32mm in either direction in post-perspective-transform screen space so that it lines up with the center of the each lens. For a 1:1 scale world that results in a 32mm transform in world space as well. You can make sense of this by thinking of sliding the eye position along the near plane of the camera.
But, after this is done, the camera transform position is also shifted IPD/2mm in either direction. For the above person, this would put the centers of the ingame cameras a total of 128mm apart.
Try substituting the OVRCameraController.ConfigureCamera method with the code below, which instead offsets the eye positions by the difference between IPD and inter-lens distance:
void UpdateCameras()
{
// Values that influence the stereo camera orientation up and above the tracker
if(FollowOrientation != null)
OrientationOffset = FollowOrientation.rotation;
if(UpdateCamerasDirtyFlag == false)
return;
float ipdDifference = IPD - 0.064f; // I assume the lenses are exactly 64mm center to center
float distOffset = 0.5f + (LensOffsetLeft * 0.5f);
float perspOffset = LensOffsetLeft;
float eyePositionOffset = -ipdDifference * 0.5f;
ConfigureCamera(ref CameraLeft, distOffset, perspOffset, eyePositionOffset);
distOffset = 0.5f + (LensOffsetRight * 0.5f);
perspOffset = LensOffsetRight;
eyePositionOffset = ipdDifference * 0.5f;
ConfigureCamera(ref CameraRight, distOffset, perspOffset, eyePositionOffset);
UpdateCamerasDirtyFlag = false;
}
If you load up Tuscany, set your IPD and height correctly (it defaults to you being super tall) and play standing, you should see a night and day difference from before. Everything seems exactly as big and as distant as it should be. The high vaulted ceiling looks as impressive as it should be for being over two stories high. Go back to the unmodified Tuscany and it feels like a dollhouse.
If you don't trust my explanation, try to simply set eyePositionOffset to zero. Far from getting zero stereo separation as you might intuitively expect, it should look very close to correct if you have average IPD.
I haven't looked at the C++ samples yet, and I don't think the Unreal code is accessible, but I suspect they have the same problem. The Unreal demos I tried also made the world seem tiny, though thats made worse by the intentionally out of proportion design of most unreal samples.
15 Replies
Replies have been turned off for this discussion
- CapyvaraExplorerJust tried your code and in Tuscany I found it looked strange/wrong.
For example the candles in the wall used to look like a normal candle size, getting very close to it looked like it would almost touch my face. With your code the candles size seemed bigger than a large wood log, and even getting the closest as possible to them gave the impression they were still out of my arms reach. - longshotHonored GuestTried it in both my own project and the tuscany project.
I agree that something isn't quite right with depth. However, this code doesn't seem right either. It gave me immediate eyestrain, and although everything was much bigger, and there was much better perception of depth, it was almost as if I was having an orthographic view being rendered in 3D. Something is still off.
- drashHeroic ExplorerWatching this thread like a HAWK.
- owenwpExpert ProtegeI thought about it some more and yeah, its still not quite right. I didn't take into account the physical position of your eyes, so if your IPD is wider that has the effect of panning the image you are looking at inward, so the correct value of eyePositionOffset is actually zero no matter what your IPD may be.
However that's still not quite enough because the center of projection should match your eye position, or else your view will appear sheared. I suspect this is what you are experiencing.
I think the change Oculus made to the projection in the latest SDK was actually a step in the wrong direction. I think they may have confused which transform is invariant to IPD between projection offset and camera position offset.
The scale distortion due to the extra wide camera positions may have masked the discrepancy, as these issues only become obvious when it gets close enough to your actual vision to make a comparison. I will do more experiments and post my results, as unfortunately my IPD is very close to 64mm which makes the Oculus projection match for me out of the box. After reading your comments I have noticed a slight warping as I turn my head, though its very subtle. - owenwpExpert ProtegeTry giving this a spin. I made it using the old SDK with an eyeOffsetPosition of zero. There may be other issues, but this seems closer to correct.
Note that setting the correct IPD is way more important in this version, a little off in either direction and everything looks distorted. I would be especially interested to hear from anyone who has had their IPD measured by an optometrist.
http://zombieprocess.org/files/OculusTuscanyIPD1.zip - adamHonored GuestHi,
I just spent a fair bit of time switching between yours (A) and the original shipped demo (B).
My Observations
(for all testing I set the IPD to 65mm, which is what TF2 calibration said I have)
(A)
- Changing the IPD has an obvious result on screen.
- I feel too tall, like my feet are not on the ground.
- If I go up to the candles, the become huge. This does not feel right.
- Depth perception seems to be increased, look up and circle strafe around the chandelier for most obvious effect.
(B)
- Changing the IPD has no obvious result on screen.
- I feel correct height, and that my feet are on the ground.
- If I go up to the candles, they stay same 'size'. This feels right to me.
- Not as much visual depth change when move around looking at chandelier.
I can't comment on the correctness of the math, but (A) feels more right to me. I do like what (B) is doing from a depth persepective.
Cheers, Adam. - owenwpExpert ProtegeI also noticed that the TF2 calibrated IPD did not feel quite right, and ended up fine tuning it down almost a millimeter to make it feel comfortable. I'm not sure yet if thats a math error, or where it might be.
Also keep in mind that the default player height in Tuscany places your eyes 2 meters above the floor. That would make you about 6 and a half feet tall. You can use the 5 and 6 keys to adjust that. Also the candles are almost 4 inches thick.
I have been using the furniture as my scale reference, pulling the Rift on and off while looking at a chair placed in the same spot as a real chair. - CapyvaraExplorerActually your height is 1.85 meters (6"1'), the candles have about 5 centimeters (2 inches) of diameter.
Sincerely, I don't think the depth perception is wrong the way it is, maybe your impression is due to the low res? or you were expecting the house to be bigger?
Also I took a quick look at the Unity code and I think you may have misunderstood the math, the offset added to the camera perspective projection is only the difference between the left and right camera rendering center (centered in 1/4 for the left eye and 3/4 for the right) to the lens center position, which in the current DK is about 5 millimeters. Check the SDK docs (not the Unity integration, the other one) that has much more details about that.
Edit:
Made a quick gif showing the difference with eye distance set to zero, the black lines are at 1/4 and 3/4 of the screen, while the green lines indicate the lens center, the second frame is with the lens center offset on perspective matrix.
Note that the images are the same, only with an offset, if this represented a change in viewpoint you would see the side of the white cube, or the amount of the table behind that is visible will change, but they remain constant.
Also I did the test you mentioned of setting eyePositionOffset to zero and the stereoscopy disappeared. The other depth cues may give the impression that it still "3D", but actually it's not. - owenwpExpert ProtegeYou are right, I came to the wrong conclusion. It doesn't give proper stereo separation. I was also thrown off by the height. It is ~1.95 meters from floor to eye, which is closer to 7 feet than 6 when you add the size of the head. The HUD is reporting eye height, which you can verify by printing out the world space position of the camera, and there is also a gap between the collider and the floor that you can see in the editor. That really shouldn't look right unless you are similarly tall.
And even with such an extreme height, with the current SDK the floor appears close enough to cut through my knees when I play standing, something still seems to be off. I think the old SDK may have had the correct math, or closer to correct. I'll try some more things. - longshotHonored GuestPlayed around with the tuscany demo, just to add another piece to the puzzle, it seems that the height adjustment isn't correct.
I'm 1.727 meters tall, however, at this height( 1.720 in-game ), it feels like my feet and shins are going through the floor. Adjusting to 1.780 meters tall, feels 95% correct. I have an average length neck and near average IPD (64.25), and am pretty much just average, so either VR adds 2 inches O_o, or there's a mistake in the head and neck settings, or a mistake in math somewhere.
Also, it feels like the height adjustment changes your perceived height, way too much. It doesn't feel like I raised my eyes 2 inches, in terms of perception, it feels more like a foot or two.
Quick Links
- Horizon Developer Support
- Quest User Forums
- Troubleshooting Forum for problems with a game or app
- Quest Support for problems with your device