using System;
namespace UnityEngine.Rendering.HighDefinition
{
/// Settings to use when capturing a probe.
[Serializable]
public struct ProbeCapturePositionSettings
{
/// Default value.
[Obsolete("Since 2019.3, use ProbeCapturePositionSettings.NewDefault() instead.")]
public static readonly ProbeCapturePositionSettings @default = default;
/// Default value.
/// The default value.
public static ProbeCapturePositionSettings NewDefault() => new ProbeCapturePositionSettings(
Vector3.zero, Quaternion.identity,
Vector3.zero, Quaternion.identity,
Matrix4x4.identity
);
/// The proxy position.
public Vector3 proxyPosition;
/// The proxy rotation.
public Quaternion proxyRotation;
///
/// The reference position.
///
/// This additional information is used to compute the actual capture position. (usually, the viewer position) ()
///
public Vector3 referencePosition;
///
/// The reference rotation.
///
/// This additional information is used to compute the actual capture position. (usually, the viewer rotation) ()
///
public Quaternion referenceRotation;
///
/// The matrix for influence to world.
///
public Matrix4x4 influenceToWorld;
/// Create a new settings with only the probe transform.
/// The proxy position.
/// The proxy rotation.
/// Influence to world matrix
public ProbeCapturePositionSettings(
Vector3 proxyPosition,
Quaternion proxyRotation,
Matrix4x4 influenceToWorld
)
{
this.proxyPosition = proxyPosition;
this.proxyRotation = proxyRotation;
referencePosition = Vector3.zero;
referenceRotation = Quaternion.identity;
this.influenceToWorld = influenceToWorld;
}
/// Create new settings.
/// The proxy position.
/// The proxy rotation.
/// The reference position.
/// The reference rotation.
/// Influence to world matrix
public ProbeCapturePositionSettings(
Vector3 proxyPosition,
Quaternion proxyRotation,
Vector3 referencePosition,
Quaternion referenceRotation,
Matrix4x4 influenceToWorld
)
{
this.proxyPosition = proxyPosition;
this.proxyRotation = proxyRotation;
this.referencePosition = referencePosition;
this.referenceRotation = referenceRotation;
this.influenceToWorld = influenceToWorld;
}
///
/// Compute the probe capture settings from an HDProbe and a reference transform.
///
/// The probe to extract settings from.
/// The reference transform. Use null when no reference is available.
/// The probe capture position settings.
public static ProbeCapturePositionSettings ComputeFrom(HDProbe probe, Transform reference)
{
var referencePosition = Vector3.zero;
var referenceRotation = Quaternion.identity;
if (reference != null)
{
referencePosition = reference.position;
referenceRotation = reference.rotation;
}
else
{
if (probe.type == ProbeSettings.ProbeType.PlanarProbe)
{
var planar = (PlanarReflectionProbe)probe;
return ComputeFromMirroredReference(planar, planar.referencePosition);
}
}
var result = ComputeFrom(probe, referencePosition, referenceRotation);
return result;
}
///
/// Compute the probe capture settings from an HDProbe and a reference position.
/// The position will be mirrored based on the mirror position of the probe.
///
/// The probe to extract settings from.
/// The reference position to use.
/// The probe capture position setting.
public static ProbeCapturePositionSettings ComputeFromMirroredReference(
HDProbe probe, Vector3 referencePosition
)
{
var positionSettings = ComputeFrom(
probe,
referencePosition, Quaternion.identity
);
// Set proper orientation for the reference rotation
var proxyMatrix = Matrix4x4.TRS(
positionSettings.proxyPosition,
positionSettings.proxyRotation,
Vector3.one
);
var mirrorPosition = proxyMatrix.MultiplyPoint(probe.settings.proxySettings.mirrorPositionProxySpace);
positionSettings.referenceRotation = Quaternion.LookRotation(mirrorPosition - positionSettings.referencePosition);
return positionSettings;
}
///
/// Compute a hash based on the settings' values
///
///
public Hash128 ComputeHash()
{
var h = new Hash128();
var h2 = new Hash128();
HashUtilities.QuantisedVectorHash(ref proxyPosition, ref h);
HashUtilities.QuantisedVectorHash(ref referencePosition, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
var euler = proxyRotation.eulerAngles;
HashUtilities.QuantisedVectorHash(ref euler, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
euler = referenceRotation.eulerAngles;
HashUtilities.QuantisedVectorHash(ref euler, ref h2);
HashUtilities.AppendHash(ref h2, ref h);
return h;
}
static ProbeCapturePositionSettings ComputeFrom(
HDProbe probe,
Vector3 referencePosition, Quaternion referenceRotation
)
{
var result = new ProbeCapturePositionSettings();
var proxyToWorld = probe.proxyToWorld;
result.proxyPosition = proxyToWorld.GetColumn(3);
// If reference position and proxy position is exactly the same, we end up in some degeneracies triggered
// by engine code when computing culling parameters. This is an extremely rare case, but can happen
// in editor when focusing on the planar probe. So if that happens, we offset them 0.1 mm apart.
if (Vector3.Distance(result.proxyPosition, referencePosition) < 1e-4f)
{
referencePosition += new Vector3(1e-4f, 1e-4f, 1e-4f);
}
result.proxyRotation = proxyToWorld.rotation;
result.referencePosition = referencePosition;
result.referenceRotation = referenceRotation;
result.influenceToWorld = probe.influenceToWorld;
return result;
}
}
}