using UnityEngine;
namespace Nxr.Internal
{
///
///
///
public class NibiruMarker : MonoBehaviour
{
[Tooltip("Scale the position from Marker units (mm) into Unity units (m). example : \n" +
" 1 means = mm -> m \n 10 means = mm -> dm \n 100 means = mm ->cm ")]
public float PositonScaleFactor = 1.0f;
//
public delegate void OnMarkerFound();
public delegate void OnMarkerLost();
///
/// The callback when Marker is found.
///
public static OnMarkerFound OnMarkerFoundHandler = null;
///
/// The callback when Marker is lost.
///
public static OnMarkerLost OnMarkerLostHandler = null;
NibiruService nibiruService;
Transform mTransform;
bool visible = false;
private Matrix4x4 cameraPoseMat;
private Matrix4x4 cameraPoseMatLeft;
private Matrix4x4 cameraPoseMatRight;
GameObject origin;
public bool AutoStartMarkerRecognize = true;
public bool IsVisible()
{
return visible;
}
// Use this for initialization
void Start()
{
nibiruService = NxrViewer.Instance.GetNibiruService();
mTransform = gameObject.transform;
origin = GameObject.Find("MarkerRoot");
// Polaroid DTR
bool dtrMode = NxrGlobal.supportDtr && NxrGlobal.distortionEnabled;
if (dtrMode)
{
NxrViewer.Instance.SwitchControllerMode(false);
}
NxrGlobal.isMarkerVisible = false;
if (nibiruService != null && AutoStartMarkerRecognize)
{
nibiruService.StartMarkerRecognize();
}
cameraPoseMat = new Matrix4x4();
}
// Update is called once per frame
void Update()
{
if (nibiruService != null && nibiruService.IsMarkerRecognizeRunning)
{
float[] leftEyeArray = nibiruService.GetMarkerViewMatrix(0);
float[] rightEyeArray = nibiruService.GetMarkerViewMatrix(1);
if (leftEyeArray != null && rightEyeArray != null)
{
leftEyeArray[12] *= 0.001f * PositonScaleFactor;
leftEyeArray[13] *= 0.001f * PositonScaleFactor;
leftEyeArray[14] *= 0.001f * PositonScaleFactor;
rightEyeArray[12] *= 0.001f * PositonScaleFactor;
rightEyeArray[13] *= 0.001f * PositonScaleFactor;
rightEyeArray[14] *= 0.001f * PositonScaleFactor;
Matrix4x4 matrixRawLeft = ARUtilityFunctions.MatrixFromFloatArray(leftEyeArray);
Matrix4x4 matrixRawRight = ARUtilityFunctions.MatrixFromFloatArray(rightEyeArray);
Matrix4x4 transformationMatrixLeft = ARUtilityFunctions.LHMatrixFromRHMatrix(matrixRawLeft);
Matrix4x4 transformationMatrixRight = ARUtilityFunctions.LHMatrixFromRHMatrix(matrixRawRight);
cameraPoseMatLeft = transformationMatrixLeft.inverse;
cameraPoseMatRight = transformationMatrixRight.inverse;
}
float[] array = nibiruService.GetMarkerViewMatrix();
if (array != null)
{
if (!visible)
{
if (OnMarkerFoundHandler != null)
{
OnMarkerFoundHandler();
}
visible = true;
NxrGlobal.isMarkerVisible = true;
for (int i = 0; i < mTransform.childCount; i++)
{
mTransform.GetChild(i).gameObject.SetActive(true);
Debug.Log("MARKER VISBILE " + mTransform.GetChild(i).gameObject.name);
}
if (origin != null)
{
Matrix4x4 pose;
// If this marker is the base, no need to take base inverse etc.
pose = origin.transform.localToWorldMatrix;
transform.position = ARUtilityFunctions.PositionFromMatrix(pose);
transform.rotation = ARUtilityFunctions.QuaternionFromMatrix(pose);
}
}
// Filter data
array = FilterData(array);
// Scale the position from ARToolKit units (mm) into Unity units (m).
array[12] *= 0.001f * PositonScaleFactor;
array[13] *= 0.001f * PositonScaleFactor;
array[14] *= 0.001f * PositonScaleFactor;
Matrix4x4 matrixRaw = ARUtilityFunctions.MatrixFromFloatArray(array);
// Debug.Log("MarkerViewMatrix>>>>" + matrixRaw.ToString());
Matrix4x4 transformationMatrix = ARUtilityFunctions.LHMatrixFromRHMatrix(matrixRaw);
cameraPoseMat = transformationMatrix.inverse;
//Debug.Log("transformationMatrix>>>>" + transformationMatrix.ToString());
//Quaternion quaternion = ARUtilityFunctions.QuaternionFromMatrix(transformationMatrix);
//Vector3 eulerAngles = quaternion.eulerAngles;
// z轴朝上,转换成z轴朝里,符合unity
//mTransform.rotation = Quaternion.Euler(eulerAngles.x - 90, eulerAngles.y, eulerAngles.z);
//mTransform.position = ARUtilityFunctions.PositionFromMatrix(transformationMatrix);
}
else if (array == null)
{
if (visible)
{
Debug.Log("MARKER VISIBLE -> NOT VISBILE");
}
else
{
Debug.Log("MARKER INIT NOT VISBILE");
}
if (OnMarkerLostHandler != null)
{
OnMarkerLostHandler();
}
NxrGlobal.isMarkerVisible = false;
visible = false;
for (int i = 0; i < mTransform.childCount; i++)
{
mTransform.GetChild(i).gameObject.SetActive(false);
}
}
}
}
public Matrix4x4 CameraPose()
{
return cameraPoseMat;
}
public Vector3 CameraPosition(int eyeType)
{
Vector3 arPosition = ARUtilityFunctions.PositionFromMatrix(eyeType == 0 ? cameraPoseMatLeft : cameraPoseMatRight);
return arPosition;
}
private void OnApplicationPause(bool pause)
{
if (pause)
{
visible = false;
NxrGlobal.isMarkerVisible = false;
for (int i = 0; i < mTransform.childCount; i++)
{
mTransform.GetChild(i).gameObject.SetActive(false);
}
}
if (AutoStartMarkerRecognize && pause && nibiruService != null)
{
nibiruService.StopMarkerRecognize();
}
else if (AutoStartMarkerRecognize && nibiruService != null)
{
nibiruService.StartMarkerRecognize();
}
}
private void OnDestroy()
{
// change scene
if (AutoStartMarkerRecognize && nibiruService != null && nibiruService.IsMarkerRecognizeRunning)
{
nibiruService.StopMarkerRecognize();
}
}
private void OnApplicationQuit()
{
// exit app
if (AutoStartMarkerRecognize && nibiruService != null && nibiruService.IsMarkerRecognizeRunning)
{
nibiruService.StopMarkerRecognize();
}
}
//******************Filter Data******************
private float[] lastDataArr;
public bool filterMarkerJitter = true;
private float[] FilterData(float[] newArray)
{
if (!filterMarkerJitter)
{
return newArray;
}
if (lastDataArr == null)
{
lastDataArr = new float[newArray.Length];
newArray.CopyTo(lastDataArr, 0);
}
int length = newArray.Length;
for (int i = 0; i < length; i++)
{
float diff = Mathf.Abs(newArray[i] - lastDataArr[i]);
float absValue = Mathf.Abs(newArray[i]);
if (absValue > 100 && diff < 0.05f)
{
continue;
}
else if (absValue > 20 && diff < 0.014f)
{
continue;
}
else if (diff < 0.004f)
{
continue;
}
// 大数据更新
lastDataArr[i] = newArray[i];
}
return lastDataArr;
}
//******************Filter Data******************
}
}