void Update()
{
if (m_FaceManager.subsystem != null && faceInfoText != null)
{
faceInfoText.text = $"Supported number of tracked faces: {m_FaceManager.supportedFaceCount}\n" +
$"Max number of faces to track: {m_FaceManager.maximumFaceCount}\n" +
$"Number of tracked faces: {m_FaceManager.trackables.count}";
// 这样可以在UI上看到顶点的数量
faceInfoText.text += "\n当前脸部Mesh的顶点数为:" + _verticeCount;
}
if (Input.GetMouseButtonUp(0))
{
var camera = GetComponent<ARSessionOrigin>().camera;
var ray = camera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit, 1000))
{
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = Vector3.one * 0.01f;
// 设置父物体为人脸,这样物体会跟随人脸移动
go.transform.SetParent(hit.transform);
go.transform.position = hit.point;
// !!!下面是添加的代码
var face = hit.transform.GetComponent<ARFace>();
// 创建一个int类型的私有成员
_verticeCount = face.vertices.Length;
}
}
}
通过这一步,咱们就能确认脸部的网格固定是11510个顶点了,可以放心进入第二步了。
2、计算脸部Mesh上离射线检测点最近的顶点的索引
这一步咱们需要找到几个特殊点的索引,我准备找到的点是鼻尖、4个眼角、2个嘴角。
代码如下:
void Update()
{
if (m_FaceManager.subsystem != null && faceInfoText != null)
{
faceInfoText.text = $"Supported number of tracked faces: {m_FaceManager.supportedFaceCount}\n" +
$"Max number of faces to track: {m_FaceManager.maximumFaceCount}\n" +
$"Number of tracked faces: {m_FaceManager.trackables.count}";
// 这样可以在UI上看到顶点的数量
faceInfoText.text += "\n当前脸部Mesh的顶点数为:" + _verticeCount;
// 这样可以在UI上看到顶点的索引
faceInfoText.text += "\n离点击位置最近的顶点索引是:" + _verticeCount;
}
// !!!下面是添加的代码
if (Input.GetMouseButtonUp(0))
{
var camera = GetComponent<ARSessionOrigin>().camera;
var ray = camera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit, 1000))
{
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = Vector3.one * 0.01f;
// 设置父物体为人脸,这样物体会跟随人脸移动
go.transform.SetParent(hit.transform);
go.transform.position = hit.point;
var face = hit.transform.GetComponent<ARFace>();
// 需要在类中创建一个int类型的私有成员
_verticeCount = face.vertices.Length;
var min = float.MaxValue;
// 需要在类中创建一个int类型的私有成员
minIndex = -1;
for (var index = 0; index < face.vertices.Length; index++)
{
var v = face.vertices[index];
var local = hit.transform.InverseTransformPoint(hit.point);
// 使用sqrMagnitude可以减少一次开方计算,结果一样,性能更好
var distance = (v - local).sqrMagnitude;
if (distance < min)
{
minIndex = index;
min = distance;
}
}
}
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.ARFoundation;
[RequireComponent(typeof(ARFaceManager))]
public class DisplayFaceInfo : MonoBehaviour
{
[SerializeField] Text m_FaceInfoText;
public Text faceInfoText
{
get { return m_FaceInfoText; }
set { m_FaceInfoText = value; }
}
ARFaceManager m_FaceManager;
private int minIndex;
private int[] PointIndexs = {10655, 9265, 9218, 10796, 8940, 10609, 9103};
// 下面的颜色是调试用的,因为大智忘了上面那些数字对应是那些位置了 /(ㄒoㄒ)/~~
private Color[] Colors = {Color.black, Color.white, Color.blue, Color.gray, Color.green, Color.red, Color.yellow};
private Dictionary<int, GameObject> BallMap = new Dictionary<int, GameObject>();
private int _verticeCount;
void Awake()
{
m_FaceManager = GetComponent<ARFaceManager>();
m_FaceManager.facesChanged += delegate(ARFacesChangedEventArgs args)
{
if (args.added.Count > 0)
{
var face = args.added[0];
for (var i = 0; i < PointIndexs.Length; i++)
{
var index = PointIndexs[i];
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = Vector3.one * 0.01f;
var pos = face.vertices[index];
// 设置父物体为人脸,这样物体会跟随人脸移动
go.transform.SetParent(face.transform);
go.transform.localPosition = pos;
go.GetComponent<Renderer>().material.color = Colors[];
BallMap[index] = go;
}
}
// 更新点的位置,added的时候可能mesh还不准确,顶点位置有可能更新
if (args.updated.Count > 0)
{
var face = args.updated[0];
foreach (var index in PointIndexs)
{
var pos = face.vertices[index];
var go = BallMap[index];
go.transform.localPosition = pos;
}
}
};
}
void Update()
{
if (m_FaceManager.subsystem != null && faceInfoText != null)
{
faceInfoText.text = $"Supported number of tracked faces: {m_FaceManager.supportedFaceCount}\n" +
$"Max number of faces to track: {m_FaceManager.maximumFaceCount}\n" +
$"Number of tracked faces: {m_FaceManager.trackables.count}";
// 这样可以在UI上看到顶点的数量
faceInfoText.text += "\n当前脸部Mesh的顶点数为:" + _verticeCount;
// 这样可以在UI上看到顶点的索引
faceInfoText.text += "\n离点击位置最近的顶点索引是:" + _verticeCount;
}
// !!!下面是添加的代码
if (Input.GetMouseButtonUp(0))
{
var camera = GetComponent<ARSessionOrigin>().camera;
var ray = camera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit, 1000))
{
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = Vector3.one * 0.01f;
// 设置父物体为人脸,这样物体会跟随人脸移动
go.transform.SetParent(hit.transform);
go.transform.position = hit.point;
var face = hit.transform.GetComponent<ARFace>();
// 需要在类中创建一个int类型的私有成员
_verticeCount = face.vertices.Length;
var min = float.MaxValue;
// 需要在类中创建一个int类型的私有成员
minIndex = -1;
for (var index = 0; index < face.vertices.Length; index++)
{
var v = face.vertices[index];
var local = hit.transform.InverseTransformPoint(hit.point);
// 使用sqrMagnitude可以减少一次开方计算,结果一样,性能更好
var distance = (v - local).sqrMagnitude;
if (distance < min)
{
minIndex = index;
min = distance;
}
}
}
}
}
}