Repository navigation
Expand file tree
/
Copy pathHeadTrackingMathProbe.cpp
More file actions
69 lines (69 loc) · 4.36 KB
/
Copy pathHeadTrackingMathProbe.cpp
File metadata and controls
69 lines (69 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "HeadTrackingMath.h"
#include <cstdio>
using namespace HeadTrackingMath;
bool close(float a,float b){return std::abs(a-b)<0.0001f;}
int main(){
PackedCamera b{{1,0,0,0,0,1,0,-1,0,10,20,30}};
Transport::Pose anchor{{0,0,0,1},{1,2,3}};
Transport::Pose left=anchor,right=anchor;left.position.x-=0.032f;right.position.x+=0.032f;
auto l=EyeCamera(b,anchor,left,1),r=EyeCamera(b,anchor,right,1);
if(!Valid(l)||!Valid(r)||!close(r.v[9]-l.v[9],0.064f)||!close(l.v[10],20)||!close(l.v[11],30))return 1;
auto neutral=EyeCamera(b,anchor,anchor,1);for(unsigned i=0;i<12;i++)if(!close(neutral.v[i],b.v[i]))return 2;
float s=std::sqrt(0.5f);Transport::Pose yaw{{0,s,0,s},anchor.position};
auto y=EyeCamera(b,anchor,yaw,1);if(!close(y.v[0],0)||!close(y.v[1],1)||!close(y.v[2],0))return 3;
auto expanded=Expand(b);if(!close(expanded.v[12],10)||!close(expanded.v[13],20)||!close(expanded.v[14],30)||!close(expanded.v[15],1))return 4;
Matrix native{};native.v[10]=-3000.f/(3000.f-0.05f);native.v[11]=-1;native.v[14]=-0.05f*3000.f/(3000.f-0.05f);
Transport::Eye eye{};eye.left=-0.9f;eye.right=0.7f;eye.up=0.8f;eye.down=-0.75f;Matrix p{};
if(!Projection(native,eye,p))return 5;
auto clip=[&](float x,float y,float z,unsigned component){return component==0?(x*p.v[0]+z*p.v[8])/-z:(y*p.v[5]+z*p.v[9])/-z;};
if(!close(clip(std::tan(eye.left),0,-1,0),-1)||!close(clip(std::tan(eye.right),0,-1,0),1)||
!close(clip(0,std::tan(eye.up),-1,1),1)||!close(clip(0,std::tan(eye.down),-1,1),-1))return 6;
if(!close(p.v[10],native.v[10])||!close(p.v[14],native.v[14])||p.v[12]!=0)return 7;
auto round=Rotate(Inverse(yaw.orientation),Rotate(yaw.orientation,{0.4f,-0.2f,1.5f}));
if(!close(round.x,0.4f)||!close(round.y,-0.2f)||!close(round.z,1.5f))return 8;
// Exact observed retail ordering: camera context left/right is prepared
// while NVAPI still selects the previous output; it switches before draws.
// Reconstruct a distant landmark through the receiving headset lens.
// Reusing the previous output eye assigns the opposite asymmetric lens.
Transport::Eye runtime[2]{};
for(unsigned e=0;e<2;e++){
runtime[e].pose={{0,0,0,1},{e?0.032f:-0.032f,0,0}};
runtime[e].left=e?-0.620896816f:-0.767549992f;
runtime[e].right=e?0.767549992f:0.620896816f;
runtime[e].up=0.726982594f;runtime[e].down=-0.837898076f;
}
PackedCamera identity{{1,0,0,0,1,0,0,0,1,0,0,0}};
Transport::Pose origin{{0,0,0,1},{0,0,0}};
struct Pass {bool left;unsigned activeBefore,activeForDraw;};
Pass passes[]{{true,1,2},{false,2,1}};
unsigned capturedMask=0;
for(auto pass:passes){
unsigned cameraEye=RuntimeEyeForCamera(pass.left);
unsigned receivingEye=pass.activeForDraw==2?0:1;
auto camera=EyeCamera(identity,origin,runtime[cameraEye].pose,1);
Matrix rendered{},lens{};
if(!Projection(native,runtime[cameraEye],rendered)||!Projection(native,runtime[receivingEye],lens))return 9;
const float distance=10000;
float pixel=(-camera.v[9]*rendered.v[0]-distance*rendered.v[8])/distance;
float recoveredRay=(pixel+lens.v[8])/lens.v[0];
float expectedRay=-runtime[receivingEye].pose.position.x/distance;
if(std::abs(recoveredRay-expectedRay)>1e-6f)return 10;
// Ensure this fixture actually detects the previous-eye regression.
unsigned wrongEye=pass.activeBefore==2?0:1;
Matrix wrong{};Projection(native,runtime[wrongEye],wrong);
auto wrongCamera=EyeCamera(identity,origin,runtime[wrongEye].pose,1);
float wrongPixel=(-wrongCamera.v[9]*wrong.v[0]-distance*wrong.v[8])/distance;
float wrongRay=(wrongPixel+lens.v[8])/lens.v[0];
if(std::abs(wrongRay-expectedRay)<0.2f)return 11;
capturedMask|=1u<<receivingEye;
}
if(capturedMask!=3)return 12;
for(const auto& eye:runtime){
Matrix actual{};if(!Projection(native,eye,actual))return 13;
float fov{},aspect{};if(!ProjectionLensFields(actual,fov,aspect))return 14;
float reconstructedY=1/std::tan(fov*0.008726646259971648f);
if(!close(reconstructedY,actual.v[5])||!close(reconstructedY/aspect,actual.v[0]))return 15;
if(fov<85||fov>95||aspect<0.8f||aspect>0.9f)return 16;
}
puts("PASS: camera mapping, recenter, eye separation, frustum/depth, delayed eye routing and native lens metadata reconstruction.");return 0;
}