rj-action-library/Runtime/Procedural/Baking/Baker.cs

170 lines
3.3 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class Baker:Node
{
public enum CameraDistanceDetectionType
{
Automatic_Distance_Detection,
Custom_Distance
}
public enum CameraFOVMode
{
Keep_Fov,
Compute_Fov_With_Distance,
Custom_Fov
}
public enum MeshMode
{
World_Scale,
Custom_Scale
}
[Export]
public bool update = false;
[Export]
public bool updateAlways = false;
[Export]
public Viewport viewport;
[Export]
public Node3D target;
[Export]
public Camera3D camera;
[Export]
public float originalFOV = 75;
[Export]
public bool assignFOV = false;
[Export]
public float placingDistance = 500;
[Export]
public float computedFOV = 75;
[Export]
public bool useCustomFOV = false;
[Export]
public float customFOV = 75;
[Export]
public bool useCustomDistance = false;
[Export]
public float customDistance = 50;
[Export]
public float outputScale = 1;
[Export]
public Node3D outputTexture;
[Export]
public float outputTextureSize = 1;
[Export( PropertyHint.Range, "-180,180")]
public float yaw = 0;
[Export( PropertyHint.Range, "-180,180")]
public float pitch = 0;
public Quaternion bakingRotation => Math3D.YawPitchRotation( yaw, pitch );
[Export]
public float zoom = 1;
[Export]
public float distance = 1;
public override void _Process( double delta )
{
if ( ! ( update || updateAlways ) )
{
return;
}
update = false;
Bake();
}
void Bake()
{
if ( viewport == null || target == null || camera == null )
{
return;
}
var box = target.GetWorldBounds();
if ( box == null )
{
RJLog.Log( "No target" );
return;
}
var sphere = Sphere.ContainingBox( box );
camera.Fov = originalFOV;
var billboardFOV = camera.Fov;
if ( assignFOV )
{
computedFOV = Cameras.ComputeFOVForBillboard( originalFOV, sphere.radius, placingDistance );
billboardFOV = computedFOV;
camera.Fov = billboardFOV;
}
if ( useCustomFOV )
{
billboardFOV = customFOV;
camera.Fov = billboardFOV;
}
var newDistance = useCustomDistance ? customDistance : Cameras.ComputeCameraFrameFittingDistance( billboardFOV, sphere.radius / zoom );
if ( newDistance != distance )
{
distance = newDistance;
RJLog.Log( "New Distance:", box, sphere, distance );
}
var cameraRotation = Math3D.RotateXDegrees( pitch ) * Math3D.RotateYDegrees( yaw );
var offset = ( Vector3.Back * distance ) * cameraRotation ;
camera.GlobalPosition = target.GlobalPosition + offset;
camera.SetGlobalQuaternion( cameraRotation.Inverse() );
RJLog.Log( "Set Rotation", cameraRotation, ">>", camera.GetGlobalQuaternion() );
outputScale = Cameras.ComputeCameraFittingScale( camera.Fov, distance );
if ( outputTexture != null )
{
outputTexture.Scale = Vector3.One * outputScale;
}
}
}
}