Unity-单击时如何使用网格triangleIndex为三角形重新着色?

时间:2019-08-08 05:21:59

标签: unity3d

我想知道如何在单击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");
            }
        }
    }
}

enter image description here

1 个答案:

答案 0 :(得分:3)

mesh.colors顶点而不是三角形的颜色。

您要执行的操作不是为单个顶点着色,而是为您击中的三角形着色。

mesh.triangles

  

该数组是一个三角形列表,其中包含顶点数组的索引。三角形数组的大小必须始终为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)

引用从023范围内的顶点索引的三角形列表看起来像

              (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

如您所见,它是一个普通列表。因此,为了从列表中删除某个三角形,您首先必须使用triangleIndex“跳”到一定数量的顶点集,其中一个集合完全由 3 个顶点组成索引。

然后,您获取三个连续的顶点索引,并且拥有目标三角形的3个顶点。

但是对于一个球体,有515个顶点,但有2304个三角形! =>对于大多数triangleIndex,您通过尝试直接访问IndexOutOfRangeException得到了mesh.verteces[some index > 511]

int[] triangles;

private void Start()
{
    ...

    triangles = mesh.triangles;
}

private void Update()
{
    ...

        var vertIndex1 = triangles[hit.triangleIndex * 3 + 0];
        var vertIndex2 = triangles[hit.triangleIndex * 3 + 1];
        var vertIndex3 = triangles[hit.triangleIndex * 3 + 2];

        colorArray[vert1] = Color.red;
        colorArray[vert2] = Color.red;
        colorArray[vert3] = Color.red;

        mesh.colors = colorArray;

    ...
}

enter image description here

相关问题