我想知道如何在单击它们时在 Unity 中的网格中重新着色单个三角形。我下面的代码允许我检测点击在 3D 空间中的网格表面上的位置。从那里我尝试从网格中获取三角形索引并将颜色数组中的相应索引设置为红色。
但是,我可以看到我单击的位置(绿色立方体在图像中转换到的位置)甚至不接近三角形在网格上重新着色的位置。是否需要进行某种索引或坐标转换才能为光线投射/点击与网格碰撞的确切三角形着色?
我正在为图像中的球体使用标准的无光照着色器,有时会出现索引越界错误,这表明我在尝试将颜色数组设置为红色时超出了颜色数组的长度。
对此的任何帮助或见解将不胜感激。谢谢!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyRayDraw : MonoBehaviour
{
public GameObject cube;
private MeshRenderer meshRenderer;
Mesh mesh;
Vector3[] vertices;
Color[] colorArray;
private void Start()
{
mesh = transform.GetComponent<MeshFilter>().mesh;
vertices = mesh.vertices;
// create new colors array where the colors will be created
colorArray = new Color[vertices.Length];
for (int k = 0; k < vertices.Length; k++)
{
colorArray[k] = Color.white;
}
mesh.colors = colorArray;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
Debug.Log(hit.triangleIndex);
cube.transform.position = hit.point;
colorArray[hit.triangleIndex] = Color.red;
mesh.colors = colorArray;
}
else
{
Debug.Log("no hit");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
mesh.colors是顶点的颜色而不是三角形的颜色。
您想要做的不是为单个顶点着色,而是为您击中的三角形着色。
该数组是包含顶点数组索引的三角形列表。三角形数组的大小必须始终是 3 的倍数。可以通过简单地索引到同一个顶点来共享顶点。
在RaycastHit.triangleIndex您可以找到如何获取某个三角形索引的相应顶点索引的示例。
为了更好地理解,我在这里留下了一个立方体网格的例子。
顶点是
INDEX | 3D-Position
0 | ( 0.5, -0.5, 0.5)
1 | (-0.5, -0.5, 0.5)
2 | ( 0.5, 0.5, 0.5)
3 | (-0.5, 0.5, 0.5)
4 | ( 0.5, 0.5, -0.5)
5 | (-0.5, 0.5, -0.5)
6 | ( 0.5, -0.5, -0.5)
7 | (-0.5, -0.5, -0.5)
8 | ( 0.5, 0.5, 0.5)
9 | (-0.5, 0.5, 0.5)
10 | ( 0.5, 0.5, -0.5)
11 | (-0.5, 0.5, -0.5)
12 | ( 0.5, -0.5, -0.5)
13 | ( 0.5, -0.5, 0.5)
14 | (-0.5, -0.5, 0.5)
15 | (-0.5, -0.5, -0.5)
16 | (-0.5, -0.5, 0.5)
17 | (-0.5, 0.5, 0.5)
18 | (-0.5, 0.5, -0.5)
19 | (-0.5, -0.5, -0.5)
20 | ( 0.5, -0.5, -0.5)
21 | ( 0.5, 0.5, -0.5)
22 | ( 0.5, 0.5, 0.5)
23 | ( 0.5, -0.5, 0.5)
Run Code Online (Sandbox Code Playgroud)
引用范围从0到的顶点索引的三角形列表23看起来像
(0, 2, 3, 0, 3, 1, 8, 4, 5, 8, 5, 9, 10, 6, 7, 10, 7, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23)
triangleIndex: 0 1 2 3 4 5 6 7 8 9 10 11
Run Code Online (Sandbox Code Playgroud)
如您所见,它是一个简单的列表。因此,为了首先从该列表中取出某个三角形,您必须使用triangleIndex其中一组正好包含3 个顶点索引的方式“跳过”一定数量的顶点集。
然后你取三个连续的顶点索引,你就有了目标三角形的 3 个顶点。
然而,对于球体来说,有515顶点但有2304三角形!=>为最triangleIndex,你得到了一个IndexOutOfRangeException试图通过直接访问mesh.verteces[some index > 511]。
INDEX | 3D-Position
0 | ( 0.5, -0.5, 0.5)
1 | (-0.5, -0.5, 0.5)
2 | ( 0.5, 0.5, 0.5)
3 | (-0.5, 0.5, 0.5)
4 | ( 0.5, 0.5, -0.5)
5 | (-0.5, 0.5, -0.5)
6 | ( 0.5, -0.5, -0.5)
7 | (-0.5, -0.5, -0.5)
8 | ( 0.5, 0.5, 0.5)
9 | (-0.5, 0.5, 0.5)
10 | ( 0.5, 0.5, -0.5)
11 | (-0.5, 0.5, -0.5)
12 | ( 0.5, -0.5, -0.5)
13 | ( 0.5, -0.5, 0.5)
14 | (-0.5, -0.5, 0.5)
15 | (-0.5, -0.5, -0.5)
16 | (-0.5, -0.5, 0.5)
17 | (-0.5, 0.5, 0.5)
18 | (-0.5, 0.5, -0.5)
19 | (-0.5, -0.5, -0.5)
20 | ( 0.5, -0.5, -0.5)
21 | ( 0.5, 0.5, -0.5)
22 | ( 0.5, 0.5, 0.5)
23 | ( 0.5, -0.5, 0.5)
Run Code Online (Sandbox Code Playgroud)