// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #pragma once #include "backend/cpp/core/transformTypes.hpp" #include "coordinates.hpp" #include "transformGeoParams.hpp" #include namespace VideoStitch { namespace Core { class InputDefinition; namespace TransformStack { /** * @brief Class that geometric transformation on the CPU. */ class GeoTransform { public: /** * Creates a Transform that maps the given input into the given panorama. * @param pano The PanoDefinition * @param im The InputDefinition */ static GeoTransform* create(const PanoDefinition& pano, const InputDefinition& im); virtual ~GeoTransform(); /** * Transforms a single point on the CPU from panorama to rig unit sphere. * @param uv Coordinates, relative to the center of the panorama. * @returns Coordinates in rig sphere. */ SphericalCoords3 mapPanoramaToRigSpherical(CenterCoords2 uv) const; /** * Transforms a single point on the CPU from panorama to input coordinates. * @param im Input definition. Must be the same as the one that was used to create the Transform. * @param uv Coordinates, relative to the center of the panorama. * @param time time of the geometry * @returns Coordinates in input space, relative to the center of the input. */ CenterCoords2 mapPanoramaToInput(const InputDefinition& im, CenterCoords2 uv, int time) const; /** * Transforms a single point on the CPU from input to panorama coordinates. * @param im Input definition. Must be the same as the one that was used to create the Transform. * @param uv coordinates in input space, relative to the center of the input. * @param time time of the geometry * @returns Coordinates in spherical space. */ CenterCoords2 mapInputToPanorama(const InputDefinition& im, CenterCoords2 uv, int time) const; /** * Transforms a single point on the CPU from spherical rig-center based coordinates to input coordinates. * @param im Input definition. Must be the same as the one that was used to create the Transform. * @param pt coordinates in spherical rig space. * @param time time of the geometry * @returns Coordinates in input space, relative to the center of the input. */ CenterCoords2 mapRigSphericalToInput(const InputDefinition& im, const SphericalCoords3& pt, int time) const; /** * Transforms a single point on the CPU from input to spherical rig-center based coordinates. * @param im Input definition. Must be the same as the one that was used to create the Transform. * @param uv coordinates in input space, relative to the center of the input. * @param time time of the geometry * @param radius radius of the rig sphere (note that this is not the camera sphere if the camera has a translation off * the rig center) * @returns Coordinates in spherical space. * @note radius should be large enough to contain the camera center of projection * @note the minimum radius value is given by getInputMinimumRigSphereRadius() */ SphericalCoords3 mapInputToRigSpherical(const InputDefinition& im, CenterCoords2 uv, int time, float rigSphereRadius) const; /** * Same transformation, using sphereScale from PanoDef */ SphericalCoords3 mapInputToRigSpherical(const InputDefinition& im, CenterCoords2 uv, int time) const { return mapInputToRigSpherical(im, uv, time, rigSphereRadius); } /** * Transforms a single point on the CPU from input to its camera sphere. Coordinates translated to rig-center base. * @param im Input definition. Must be the same as the one that was used to create the Transform. * @param uv coordinates in input space, relative to the center of the input. * @param time time of the geometry * @param radius radius of the sphere * @returns Coordinates in spherical rig space. */ SphericalCoords3 mapInputToScaledCameraSphereInRigBase(const InputDefinition& im, CenterCoords2 uv, int time, float cameraSphereRadius = 1.0f) const; /** * Gets the minimum rig sphere radius that contains the center of projection of the camera * @param im Input definition. Must be the same as the one that was used to create the Transform. * @param time time of the geometry * @note calling mapInputToRigSpherical() with a radius value smaller than this one is an error, an assert will fail * in debug mode */ float computeInputMinimumRigSphereRadius(const InputDefinition& im, int time) const; /** * Returns true if a point is within bounds. * @param im Input definition. Must be the same as the one that was used to create the Transform. * @param uv coordinates in input space, relative to the top-left of the input. */ bool isWithinInputBounds(const InputDefinition& im, TopLeftCoords2 uv) const; protected: GeoTransform(const GeoTransform& other); GeoTransform(); private: float2 distort(float2 uv, const float2 inputScale, const vsDistortion distortion, const float2 centerShift) const; float3 mapInputToCameraSpherical(const InputDefinition& im, const GeometryDefinition& geometry, const TransformGeoParams& params, const CenterCoords2 uv) const; // mapping implementation shared with GPU float2 mapPanoramaToInput(float2 uv, const float2 panoScale, const vsfloat3x4 pose, const float2 inputScale, const vsDistortion distortion, const float2 centerShift) const; float2 mapInputToPanorama(float2 uv, const float2 panoScale, const vsfloat3x4 poseInverse, const float rigSphereRadius, const float2 inputScale, const vsDistortion distortion, const float2 centerShift) const; float2 mapRigSphericalToInput(float3 pt, const vsfloat3x4 pose, const float2 inputScale, const vsDistortion distortion, const float2 centerShift) const; float3 mapInputToCameraSphere(float2 uv, const float2 inputScale, const vsDistortion distortion, const float2 centerShift) const; float3 mapInputToRigSpherical(float2 uv, const vsfloat3x4 poseInverse, const float rigSphereRadius, const float2 inputScale, const vsDistortion distortion, const float2 centerShift) const; float3 tracePointToRigSphere(float3 pt, const vsfloat3x4 poseInverse, const float rigSphereRadius) const; // Host-side transform functions Convert2D3DFnT fromOutputToSphereHostFn; Convert3D2DFnT fromSphereToInputHostFn; Convert3D2DFnT fromSphereToOutputHostFn; Convert2D3DFnT fromInputToSphereHostFn; IsWithinFnT isWithinHostFn; DistortionTransformFnt distortionTransformMetersHostFn; DistortionTransformFnt distortionTransformPixelsHostFn; DistortionTransformFnt inverseDistortionTransformMetersHostFn; DistortionTransformFnt inverseDistortionTransformPixelsHostFn; float2 panoScale; float rigSphereRadius; }; } // namespace TransformStack } // namespace Core } // namespace VideoStitch