/****************************************************************************
* Copyright 2019 Nreal Techonology Limited. All rights reserved.
*
* This file is part of NRSDK.
*
* https://www.nreal.ai/
*
*****************************************************************************/
namespace NRKernal
{
using UnityEngine;
/// A conversion utility.
public class ConversionUtility
{
#region transform utility
/// Get a matrix from position and rotation.
/// The position.
/// The rotation.
/// The matrix.
public static Matrix4x4 GetTMatrix(Vector3 position, Quaternion rotation)
{
return Matrix4x4.TRS(position, rotation, Vector3.one);
}
/// Get a matrix from position , rotation and scale.
/// The position.
/// The rotation.
/// The scale.
/// The matrix.
public static Matrix4x4 GetTMatrix(Vector3 position, Quaternion rotation, Vector3 scale)
{
return Matrix4x4.TRS(position, rotation, scale);
}
/// Get the position from a matrix4x4.
/// The matrix.
/// The position from t matrix.
public static Vector3 GetPositionFromTMatrix(Matrix4x4 matrix)
{
Vector3 position;
position.x = matrix.m03;
position.y = matrix.m13;
position.z = matrix.m23;
return position;
}
/// Get the rotation from a matrix4x4.
/// The matrix.
/// The rotation from t matrix.
public static Quaternion GetRotationFromTMatrix(Matrix4x4 matrix)
{
Vector3 forward;
forward.x = matrix.m02;
forward.y = matrix.m12;
forward.z = matrix.m22;
Vector3 upwards;
upwards.x = matrix.m01;
upwards.y = matrix.m11;
upwards.z = matrix.m21;
return Quaternion.LookRotation(forward, upwards);
}
/// Convert position.
/// The vector.
/// The position converted.
public static Vector3 ConvertPosition(Vector3 vec)
{
// Convert to left-handed
return new Vector3((float)vec.x, (float)vec.y, (float)-vec.z);
}
/// Convert orientation.
/// The quaternion.
/// The orientation converted.
public static Quaternion ConvertOrientation(Quaternion quat)
{
// Convert to left-handed
return new Quaternion(-(float)quat.x, -(float)quat.y, (float)quat.z, (float)quat.w);
}
#endregion
/// Unity pose to API pose.
/// [out] The unity pose.
/// [out] The API pose.
public static void UnityPoseToApiPose(Pose unityPose, out NativeMat4f apiPose)
{
Matrix4x4 glWorld_T_glLocal = Matrix4x4.TRS(unityPose.position, unityPose.rotation, Vector3.one);
Matrix4x4 unityWorld_T_glWorld = Matrix4x4.Scale(new Vector3(1, 1, -1));
Matrix4x4 unityWorld_T_unityLocal = unityWorld_T_glWorld * glWorld_T_glLocal * unityWorld_T_glWorld.inverse;
Vector3 position = unityWorld_T_unityLocal.GetColumn(3);
Quaternion rotation = Quaternion.LookRotation(unityWorld_T_unityLocal.GetColumn(2),
unityWorld_T_unityLocal.GetColumn(1));
Matrix4x4 matrix = Matrix4x4.TRS(position, rotation, Vector3.one);
apiPose = new NativeMat4f(matrix);
}
/// API pose to unity pose.
/// The API pose.
/// [out] The unity pose.
public static void ApiPoseToUnityPose(NativeMat4f apiPose, out Pose unityPose)
{
Matrix4x4 glWorld_T_glLocal = apiPose.ToUnityMat4f();
Matrix4x4 unityWorld_T_glWorld = Matrix4x4.Scale(new Vector3(1, 1, -1));
Matrix4x4 unityWorld_T_unityLocal = unityWorld_T_glWorld * glWorld_T_glLocal * unityWorld_T_glWorld.inverse;
Vector3 position = unityWorld_T_unityLocal.GetColumn(3);
Quaternion rotation = unityWorld_T_unityLocal.rotation;
unityPose = new Pose(position, rotation);
}
/// API pose to unity matrix.
/// The API pose.
/// [out] The unity matrix.
public static void ApiPoseToUnityMatrix(NativeMat4f apiPose, out Matrix4x4 unityMatrix)
{
Matrix4x4 glWorld_T_glLocal = apiPose.ToUnityMat4f();
Matrix4x4 unityWorld_T_glWorld = Matrix4x4.Scale(new Vector3(1, 1, -1));
Matrix4x4 unityWorld_T_unityLocal = unityWorld_T_glWorld * glWorld_T_glLocal * unityWorld_T_glWorld.inverse;
unityMatrix = unityWorld_T_unityLocal;
}
/// Gets projection matrix from fov.
/// The fov.
/// The near.
/// The far.
/// The projection matrix from fov.
public static NativeMat4f GetProjectionMatrixFromFov(NativeFov4f fov, float z_near, float z_far)
{
NativeMat4f pm = NativeMat4f.identity;
float l = fov.left_tan;
float r = fov.right_tan;
float t = fov.top_tan;
float b = fov.bottom_tan;
pm.column0.X = 2f / (r - l);
pm.column1.Y = 2f / (t - b);
pm.column2.X = (r + l) / (r - l);
pm.column2.Y = (t + b) / (t - b);
pm.column2.Z = (z_near + z_far) / (z_near - z_far);
pm.column2.W = -1f;
pm.column3.Z = (2 * z_near * z_far) / (z_near - z_far);
pm.column3.W = 0f;
return pm;
}
public static Pose ApiWorldToUnityWorld(Pose apiworld)
{
Matrix4x4 world_offse_matrix = NRFrame.GetWorldMatrixFromUnityToNative();
Matrix4x4 native_pose_matrix = world_offse_matrix * Matrix4x4.TRS(apiworld.position, apiworld.rotation, Vector3.one);
return new Pose(ConversionUtility.GetPositionFromTMatrix(native_pose_matrix), ConversionUtility.GetRotationFromTMatrix(native_pose_matrix));
}
public static Matrix4x4 UnityPoseToCVMatrix(Pose unityPose)
{
Matrix4x4 unityMat = GetTMatrix(unityPose.position, unityPose.rotation);
Matrix4x4 cv_T_unity = Matrix4x4.Scale(new Vector3(1, -1, 1));
Matrix4x4 cvWorld = cv_T_unity * unityMat * cv_T_unity.inverse;
return cvWorld;
}
public static Matrix4x4 UnityMatrixToCVMatrix(Matrix4x4 unityMat)
{
Matrix4x4 cv_T_unity = Matrix4x4.Scale(new Vector3(1, -1, 1));
Matrix4x4 cvWorld = cv_T_unity * unityMat * cv_T_unity.inverse;
return cvWorld;
}
}
}