From aab3c8010c690db86affc2670ed3b72f2b108e88 Mon Sep 17 00:00:00 2001 From: Scott Johnston Date: Thu, 15 Jun 2023 12:16:06 -0700 Subject: [PATCH] Correct from full FOV to assimp half-fov in camera. Compute from filmWidth and focalLength if FOV not specified. --- code/AssetLib/FBX/FBXConverter.cpp | 24 ++++++++++++++++++++---- code/AssetLib/FBX/FBXDocument.h | 6 +++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 51ec79583..cca5da596 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -93,6 +93,8 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo mSceneOut(out), doc(doc), mRemoveEmptyBones(removeEmptyBones) { + + // animations need to be converted first since this will // populate the node_anim_chain_bits map, which is needed // to determine which nodes need to be generated. @@ -427,12 +429,26 @@ void FBXConverter::ConvertCamera(const Camera &cam, const std::string &orig_name out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f); out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f); - out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); + // NOTE: Some software (maya) does not put FieldOfView in FBX, so we compute + // mHorizontalFOV from FocalLength and FilmWidth with unit conversion. - out_camera->mClipPlaneNear = cam.NearPlane(); - out_camera->mClipPlaneFar = cam.FarPlane(); + // TODO: This is not a complete solution for how FBX cameras can be stored. + // TODO: Incorporate non-square pixel aspect ratio. + // TODO: FBX aperture mode might be storing vertical FOV in need of conversion with aspect ratio. + + float fov_deg = cam.FieldOfView(); + // If FOV not specified in file, compute using FilmWidth and FocalLength. + if (fov_deg == FBX_FOV_UNKNOWN) { + float film_width_inches = cam.FilmWidth(); + float focal_length_mm = cam.FocalLength(); + ASSIMP_LOG_VERBOSE_DEBUG("FBX FOV unspecified. Computing from FilmWidth (", film_width_inches, "inches) and FocalLength (", focal_length_mm, "mm)."); + double half_fov_rad = std::atan2(film_width_inches * 25.4 * 0.5, focal_length_mm); + out_camera->mHorizontalFOV = half_fov_rad; + } else { + // FBX fov is full-view degrees. We want half-view radians. + out_camera->mHorizontalFOV = AI_DEG_TO_RAD(fov_deg) * 0.5; + } - out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); out_camera->mClipPlaneNear = cam.NearPlane(); out_camera->mClipPlaneFar = cam.FarPlane(); } diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index e229eef52..503c94833 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -55,9 +55,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _AI_CONCAT(a,b) a ## b #define AI_CONCAT(a,b) _AI_CONCAT(a,b) +/* Use an 'illegal' default FOV value to detect if the FBX camera has set the FOV. */ +#define FBX_FOV_UNKNOWN -1.0f + namespace Assimp { namespace FBX { + class Parser; class Object; struct ImportSettings; @@ -247,7 +251,7 @@ public: fbx_simple_property(FilmAspectRatio, float, 1.0f) fbx_simple_property(ApertureMode, int, 0) - fbx_simple_property(FieldOfView, float, 1.0f) + fbx_simple_property(FieldOfView, float, FBX_FOV_UNKNOWN) fbx_simple_property(FocalLength, float, 1.0f) };