static Frustum get3DFrustumFrom2D()

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);
}