您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

102 行
3.1 KiB

using System;
using UnityEngine;
namespace UniVRM10
{
public static class Matrix4x4Extensions
{
/// <summary>
/// from AimConstraint
/// </summary>
/// <param name="Yaw"></param>
/// <param name="m"></param>
/// <param name="target"></param>
/// <returns></returns>
public static (float Yaw, float Pitch) CalcYawPitch(this Matrix4x4 m, Vector3 target)
{
var localPosition = m.inverse.MultiplyPoint(target);
var zaxis = Vector3.Project(localPosition, Vector3.forward);
var yaxis = Vector3.Project(localPosition, Vector3.up);
var xaxis = Vector3.Project(localPosition, Vector3.right);
var xDot = Vector3.Dot(xaxis, Vector3.right) > 0;
var yDot = Vector3.Dot(yaxis, Vector3.up) > 0;
var zDot = Vector3.Dot(zaxis, Vector3.forward) > 0;
// x z plane
var yaw = (float)Math.Atan2(xaxis.magnitude, zaxis.magnitude) * Mathf.Rad2Deg;
if (xDot && zDot)
{
// 1st(0-90)
}
else if (xDot && !zDot)
{
// 2nd(90-180)
yaw = 180 - yaw;
}
else if (!xDot && !zDot)
{
// 3rd
yaw = -180 + yaw;
}
else if (!xDot && zDot)
{
// 4th
yaw = -yaw;
}
else
{
throw new NotImplementedException();
}
// x+y z plane
var pitch = (float)Math.Atan2(yaxis.magnitude, (xaxis + zaxis).magnitude) * Mathf.Rad2Deg;
if (yDot)
{
pitch = -pitch;
}
return (yaw, pitch);
}
/// <summary>
/// yaw: 右が+
/// pitch: 上が+
/// という仕様。vrm-0.x から据え置き
/// </summary>
public static void CalcYawPitch(this Matrix4x4 m, Vector3 target, out float yaw, out float pitch)
{
var z = Vector3.Dot(target, m.GetColumn(2));
var x = Vector3.Dot(target, m.GetColumn(0));
yaw = Mathf.Atan2(x, z) * Mathf.Rad2Deg;
// x+y z plane
var xz = Mathf.Sqrt(x * x + z * z);
var y = Vector3.Dot(target, m.GetColumn(1));
pitch = Mathf.Atan2(y, xz) * Mathf.Rad2Deg;
}
/// <summary>
/// yaw: 右が+
/// pitch: 上が+
/// という仕様。vrm-0.x から据え置き
/// </summary>
public static Quaternion YawPitchRotation(this Matrix4x4 m, float yaw, float pitch)
{
return Quaternion.AngleAxis(yaw, m.GetColumn(1)) * Quaternion.AngleAxis(-pitch, m.GetColumn(0));
}
public static Matrix4x4 RotationToWorldAxis(this Matrix4x4 m)
{
return UnityExtensions.Matrix4x4FromColumns(
m.MultiplyVector(Vector3.right),
m.MultiplyVector(Vector3.up),
m.MultiplyVector(Vector3.forward),
new Vector4(0, 0, 0, 1)
);
}
}
}