Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
504f2a2a4This file is pinned to the selected release. Download the original to open it in your design tool.
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text;
namespace SharpGLTF.Transforms
{
public static class Matrix4x4Factory
{
/// <summary>
/// Evaluates a <see cref="Matrix4x4"/> transform based on the available parameters.
/// </summary>
/// <param name="transform">A <see cref="Matrix4x4"/> instance, or null.</param>
/// <param name="scale">A <see cref="Vector3"/> instance, or null.</param>
/// <param name="rotation">A <see cref="Quaternion"/> instance, or null.</param>
/// <param name="translation">A <see cref="Vector3"/> instance, or null.</param>
/// <returns>A <see cref="Matrix4x4"/> transform.</returns>
public static Matrix4x4 CreateFrom(Matrix4x4? transform, Vector3? scale, Quaternion? rotation, Vector3? translation)
{
if (transform.HasValue)
{
// scale, rotation and translation should be null at this point.
return transform.Value;
}
return new AffineTransform(scale, rotation, translation).Matrix;
}
public static Matrix4x4 LocalToWorld(in Matrix4x4 parentWorld, in Matrix4x4 childLocal)
{
return childLocal * parentWorld;
}
public static Matrix4x4 WorldToLocal(in Matrix4x4 parentWorld, in Matrix4x4 childWorld)
{
return childWorld * parentWorld.Inverse();
}
/// <summary>
/// Normalizes the axis of the given matrix, to make it orthogonal.
/// </summary>
/// <param name="xform">The <see cref="Matrix4x4"/> to normalize.</param>
public static void NormalizeMatrix(ref Matrix4x4 xform)
{
var vx = new Vector3(xform.M11, xform.M12, xform.M13);
var vy = new Vector3(xform.M21, xform.M22, xform.M23);
var vz = new Vector3(xform.M31, xform.M32, xform.M33);
var lx = vx.Length();
var ly = vy.Length();
var lz = vz.Length();
// normalize axis vectors
vx /= lx;
vy /= ly;
vz /= lz;
// determine the skew of each axis (the smaller, the more orthogonal the axis is)
var kxy = Math.Abs(Vector3.Dot(vx, vy));
var kxz = Math.Abs(Vector3.Dot(vx, vz));
var kyz = Math.Abs(Vector3.Dot(vy, vz));
var kx = kxy + kxz;
var ky = kxy + kyz;
var kz = kxz + kyz;
// we will use the axis with less skew as our fixed pivot.
// axis X as pivot
if (kx < ky && kx < kz)
{
if (ky < kz)
{
vz = Vector3.Cross(vx, vy);
vy = Vector3.Cross(vz, vx);
}
else
{
vy = Vector3.Cross(vz, vx);
vz = Vector3.Cross(vx, vy);
}
}
// axis Y as pivot
else if (ky < kx && ky < kz)
{
if (kx < kz)
{
vz = Vector3.Cross(vx, vy);
vx = Vector3.Cross(vy, vz);
}
else
{
vx = Vector3.Cross(vy, vz);
vz = Vector3.Cross(vx, vy);
}
}
// axis z as pivot
else
{
if (kx < ky)
{
vy = Vector3.Cross(vz, vx);
vx = Vector3.Cross(vy, vz);
}
else
{
vx = Vector3.Cross(vy, vz);
vy = Vector3.Cross(vz, vx);
}
}
// restore axes original lengths
vx *= lx;
vy *= ly;
vz *= lz;
xform.M11 = vx.X;
xform.M12 = vx.Y;
xform.M13 = vx.Z;
xform.M21 = vy.X;
xform.M22 = vy.Y;
xform.M23 = vy.Z;
xform.M31 = vz.X;
xform.M32 = vz.Y;
xform.M33 = vz.Z;
}
}
}