in libraries/hvvr/raycaster/sample_hierarchy.cpp [46:123]
static Frustum get3DFrustumFrom2D(const RayPacketFrustum2D& frustum2D,
Sample2Dto3DMappingSettings settings) {
auto lens = settings.thinLens;
auto sampleToCamera = settings.sampleToCamera;
const float farPlane = -100.0f;
vector3 nearPoints[4];
nearPoints[0] = vector3(-lens.radius, -lens.radius, 0);
nearPoints[1] = vector3(+lens.radius, -lens.radius, 0);
nearPoints[2] = vector3(+lens.radius, +lens.radius, 0);
nearPoints[3] = vector3(-lens.radius, +lens.radius, 0);
for (int i = 0; i < 4; ++i) {
// printf("nearPoints[%d] = %s\n", i, toString(nearPoints[i]).c_str());
}
vector3 rayDirections[4];
rayDirections[0] = sampleToCamera * vector3(frustum2D.xMin(), frustum2D.yMax(), 1);
rayDirections[1] = sampleToCamera * vector3(frustum2D.xMax(), frustum2D.yMax(), 1);
rayDirections[2] = sampleToCamera * vector3(frustum2D.xMax(), frustum2D.yMin(), 1);
rayDirections[3] = sampleToCamera * vector3(frustum2D.xMin(), frustum2D.yMin(), 1);
if (settings.type == Sample2Dto3DMappingSettings::MappingType::SphericalSection) {
// TODO: undo sample-space padding of tile extents, and calculate correct padding in camera space
float uv[4][2] = {
frustum2D.xMin(), frustum2D.yMax(), frustum2D.xMax(), frustum2D.yMax(),
frustum2D.xMax(), frustum2D.yMin(), frustum2D.xMin(), frustum2D.yMin(),
};
for (int i = 0; i < 4; i++) {
vector2 uvCurrent = {uv[i][0], uv[i][1]};
rayDirections[i] = sphericalUVToDirection(uvCurrent, settings.fovXDegrees, settings.fovYDegrees);
}
return Frustum(nearPoints, rayDirections);
}
// Compute extrema points on the focal plane
vector3 focusPositions[4];
for (int i = 0; i < 4; ++i) {
focusPositions[i] = rayDirections[i] * (lens.focalDistance / -rayDirections[i].z);
}
for (int i = 0; i < 4; ++i) {
// printf("focusPositions[%d] = %s\n", i, toString(focusPositions[i]).c_str());
}
// On the far plane
float farXMax = -INFINITY;
float farXMin = +INFINITY;
float farYMax = -INFINITY;
float farYMin = +INFINITY;
// Construct all rays from extrema points on the lens AABB to extrema points on the far plane
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
vector3 rayPos = nearPoints[i];
vector3 rayDir = normalize(focusPositions[j] - rayPos);
// Intersect with far plane
vector3 p = rayPos + rayDir * (farPlane / rayDir.z);
farXMax = max(farXMax, p.x);
farXMin = min(farXMin, p.x);
farYMax = max(farYMax, p.y);
farYMin = min(farYMin, p.y);
}
}
vector3 farPoints[4];
farPoints[0] = vector3(farXMin, farYMin, farPlane);
farPoints[1] = vector3(farXMax, farYMin, farPlane);
farPoints[2] = vector3(farXMax, farYMax, farPlane);
farPoints[3] = vector3(farXMin, farYMax, farPlane);
vector3 finalDirections[4];
for (int i = 0; i < 4; ++i) {
finalDirections[i] = normalize(farPoints[i] - nearPoints[i]);
}
return Frustum(nearPoints, finalDirections);
}