Rasagar/Library/PackageCache/com.unity.formats.fbx/Editor/CameraVisitor.cs
2024-08-30 17:33:54 +03:00

140 lines
6.3 KiB
C#

using UnityEngine;
using Autodesk.Fbx;
using UnityEditor.Formats.Fbx.Exporter.CustomExtensions;
using System.Collections.Generic;
namespace UnityEditor.Formats.Fbx.Exporter
{
namespace Visitors
{
internal static class CameraVisitor
{
private static Dictionary<Camera.GateFitMode, FbxCamera.EGateFit> s_mapGateFit = new Dictionary<Camera.GateFitMode, FbxCamera.EGateFit>()
{
{ Camera.GateFitMode.Fill, FbxCamera.EGateFit.eFitFill },
{ Camera.GateFitMode.Horizontal, FbxCamera.EGateFit.eFitHorizontal },
{ Camera.GateFitMode.None, FbxCamera.EGateFit.eFitNone },
{ Camera.GateFitMode.Overscan, FbxCamera.EGateFit.eFitOverscan },
{ Camera.GateFitMode.Vertical, FbxCamera.EGateFit.eFitVertical }
};
/// <summary>
/// Visit Object and configure FbxCamera
/// </summary>
public static void ConfigureCamera(Camera unityCamera, FbxCamera fbxCamera)
{
if (unityCamera.usePhysicalProperties)
ConfigurePhysicalCamera(fbxCamera, unityCamera);
else
ConfigureGameCamera(fbxCamera, unityCamera);
}
/// <summary>
/// Configure FbxCameras from GameCamera
/// </summary>
private static void ConfigureGameCamera(FbxCamera fbxCamera, Camera unityCamera)
{
// Configure FilmBack settings as a 35mm TV Projection (0.816 x 0.612)
float aspectRatio = unityCamera.aspect;
float apertureHeightInInches = 0.612f;
float apertureWidthInInches = aspectRatio * apertureHeightInInches;
FbxCamera.EProjectionType projectionType =
unityCamera.orthographic ? FbxCamera.EProjectionType.eOrthogonal : FbxCamera.EProjectionType.ePerspective;
fbxCamera.ProjectionType.Set(projectionType);
fbxCamera.FilmAspectRatio.Set(aspectRatio);
fbxCamera.SetApertureWidth(apertureWidthInInches);
fbxCamera.SetApertureHeight(apertureHeightInInches);
fbxCamera.SetApertureMode(FbxCamera.EApertureMode.eVertical);
// Focal Length
double focalLength = fbxCamera.ComputeFocalLength(unityCamera.fieldOfView);
fbxCamera.FocalLength.Set(focalLength);
// Field of View
fbxCamera.FieldOfView.Set(unityCamera.fieldOfView);
// NearPlane
fbxCamera.SetNearPlane(unityCamera.nearClipPlane.Meters().ToCentimeters());
// FarPlane
fbxCamera.SetFarPlane(unityCamera.farClipPlane.Meters().ToCentimeters());
return;
}
public static Vector2 GetSizeOfMainGameView()
{
#if UNITY_2020_1_OR_NEWER
return Handles.GetMainGameViewSize();
#else
System.Type T = System.Type.GetType("UnityEditor.GameView,UnityEditor");
System.Reflection.MethodInfo GetSizeOfMainGameView = T.GetMethod("GetSizeOfMainGameView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
System.Object Res = GetSizeOfMainGameView.Invoke(null, null);
return (Vector2)Res;
#endif // UNITY_2020_1_OR_NEWER
}
/// <summary>
/// Configure FbxCameras from a Physical Camera
/// </summary>
private static void ConfigurePhysicalCamera(FbxCamera fbxCamera, Camera unityCamera)
{
Debug.Assert(unityCamera.usePhysicalProperties);
// Configure FilmBack settings
float apertureHeightInInches = unityCamera.sensorSize.y.Millimeters().ToInches();
float apertureWidthInInches = unityCamera.sensorSize.x.Millimeters().ToInches();
float aspectRatio = apertureWidthInInches / apertureHeightInInches;
FbxCamera.EProjectionType projectionType = unityCamera.orthographic
? FbxCamera.EProjectionType.eOrthogonal
: FbxCamera.EProjectionType.ePerspective;
// NOTE: it is possible to match some of the sensor sizes to the
// predefined EApertureFormats : e16mmTheatrical, eSuper16mm,
// e35mmFullAperture, eIMAX. However the round in the sizes is not
// consistent between Unity and FBX so we choose
// to leave the values as a eCustomAperture setting.
fbxCamera.ProjectionType.Set(projectionType);
fbxCamera.FilmAspectRatio.Set(aspectRatio);
Vector2 gameViewSize = GetSizeOfMainGameView();
fbxCamera.SetAspect(FbxCamera.EAspectRatioMode.eFixedRatio, gameViewSize.x / gameViewSize.y, 1.0);
fbxCamera.SetApertureWidth(apertureWidthInInches);
fbxCamera.SetApertureHeight(apertureHeightInInches);
// Fit the resolution gate horizontally within the film gate.
fbxCamera.GateFit.Set(s_mapGateFit[unityCamera.gateFit]);
// Lens Shift ( Film Offset ) as a percentage 0..1
// FBX FilmOffset is in inches
fbxCamera.FilmOffsetX.Set(apertureWidthInInches * Mathf.Clamp(Mathf.Abs(unityCamera.lensShift.x), 0f, 1f) * Mathf.Sign(unityCamera.lensShift.x));
fbxCamera.FilmOffsetY.Set(apertureHeightInInches * Mathf.Clamp(Mathf.Abs(unityCamera.lensShift.y), 0f, 1f) * Mathf.Sign(unityCamera.lensShift.y));
// Focal Length
fbxCamera.SetApertureMode(FbxCamera.EApertureMode.eFocalLength);
double focalLength = (double)unityCamera.focalLength;
fbxCamera.FocalLength.Set(focalLength); /* in millimeters */
// NearPlane
fbxCamera.SetNearPlane((double)unityCamera.nearClipPlane.Meters().ToCentimeters());
// FarPlane
fbxCamera.SetFarPlane((float)unityCamera.farClipPlane.Meters().ToCentimeters());
#if UNITY_2022_2_OR_NEWER
fbxCamera.UseDepthOfField.Set(true);
fbxCamera.FocusDistance.Set(unityCamera.focusDistance.Meters().ToCentimeters());
#endif
return;
}
}
}
}