1
\$\begingroup\$

This code uses a Raycast to get the vertices, triangles, etc. of a Primitive Cube, them using RaycastHit.triangleIndex, I can get the triangle that the Raycast hitted, but there is a easy way to get the another triangle? So that I can delete the whole face that the Raycast hitted?

I tryied modifying x in [hit.triangleIndex * 3 + x] to another values, but all the combinations that I tried deleted triangles from another faces.

if (Input.GetMouseButtonUp(0))
{       
        RaycastHit hit;

        var camera = Camera.main;

        if (!Physics.Raycast (camera.ScreenPointToRay(Input.mousePosition), out hit))
        {
            return;
        }

        var meshCollider = hit.collider as MeshCollider;

        if (meshCollider == null || meshCollider.sharedMesh == null)
            return;
        
        var mesh = meshCollider.sharedMesh;
        var vertices = mesh.vertices;
        var triangles = mesh.triangles;
        Transform objectPosition = hit.transform;

        var p0 = vertices[triangles[hit.triangleIndex * 3 + 0]];
        var p1 = vertices[triangles[hit.triangleIndex * 3 + 1]];
        var p2 = vertices[triangles[hit.triangleIndex * 3 + 2]];

        GameObject newCube = new GameObject();
        newCube.transform.position = objectPosition;

        newCube.AddComponent<MeshFilter>();
        newCube.AddComponent<MeshRenderer>();

        newCube.GetComponent<MeshRenderer>().material = defaultMaterial;

        Mesh mesh = new Mesh()

        for (int i = 0; i < triangles.Count; i+=3)
        {
            bool trianglePoint1 = (triangles[i + 0] == p0);
            bool trianglePoint2 = (triangles[i + 1] == p1);
            bool trianglePoint3 = (triangles[i + 2] == p2);
 
            if (trianglePoint1 && trianglePoint2 && trianglePoint3)
            {
                triangles.RemoveRange(i, 3);
            }
        }
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        newCube.GetComponent<MeshFilter>().mesh = mesh;
}
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I found a link that helped me to solve this using normals. To solve this, first you calculate the normals of each point of the triangle that the Raycast hitted:

var normalHittedTriangle0 = normals[triangles[hit.triangleIndex * 3 + 0]];
var normalHittedTriangle1 = normals[triangles[hit.triangleIndex * 3 + 1]];
var normalHittedTriangle2 = normals[triangles[hit.triangleIndex * 3 + 2]];

And them the normal of the face of the cube:

var hittedTriangleNormal = ((normalHittedTriangle0 + normalHittedTriangle1 + normalHittedTriangle2) / 3);

And them you loop through all the triangles in the Cube. Get the normal of each point of the triangle, get the normal of the whole triangle and check if it match with the normal of the triangle that the Raycast hitted, if it matched add it to a list.

List<int> trianglesToRemove = new List<int>();
 
for (int i = 0; i < triangles.Length; i += 3)
{
        var p0 = vertices[triangles[i + 0]];
        var p1 = vertices[triangles[i + 1]];
        var p2 = vertices[triangles[i + 2]];
 
        p0 = normals[triangles[i + 0]];
        p1 = normals[triangles[i + 1]];
        p2 = normals[triangles[i + 2]];
 
        if (((p0 + p1 + p2) / 3) == hittedTriangleNormal)
        {
                trianglesToRemove.Add(triangles[i + 0]);
                trianglesToRemove.Add(triangles[i + 1]);
                trianglesToRemove.Add(triangles[i + 2]);
        }
}

Loop through the triangles of the Cube by a step of 3 (Because triangles are grouped by 3), find the 2 triangles that match with the list and then if it matched, remove it from the triangles of the Cube.

for (int i = 0; i < triangles.Length; i+=3)
{
        bool v1 = (triangles[i + 0] == trianglesToRemove[0]);
        bool v2 = (triangles[i + 1] == trianglesToRemove[1]);
        bool v3 = (triangles[i + 2] == trianglesToRemove[2]);
 
        if ((v1 && v2 && v3))
        {
                triangles.RemoveRange(i, trianglesToRemove.Count);
        }
}

All the code:

if (Input.GetMouseButtonUp(0))
{
        RaycastHit hit;
 
        var camera = Camera.main;
 
        if (!Physics.Raycast (camera.ScreenPointToRay(Input.mousePosition), out hit))
        {
           return;
        }
 
        var meshCollider = hit.collider as MeshCollider;
 
        if (meshCollider == null || meshCollider.sharedMesh == null)
           return;
 
        var mesh = meshCollider.sharedMesh;
        var triangles = mesh.triangles;
        var normals = mesh.normals;
        Transform objectPosition = hit.transform;
 
        var normalHittedTriangle0 = normals[triangles[hit.triangleIndex * 3 + 0]];
        var normalHittedTriangle1 = normals[triangles[hit.triangleIndex * 3 + 1]];
        var normalHittedTriangle2 = normals[triangles[hit.triangleIndex * 3 + 2]];
 
        var hittedTriangleNormal = ((normalHittedTriangle0 + normalHittedTriangle1 + normalHittedTriangle2) / 3);
 
        List<int> trianglesToRemove = new List<int>();
 
        for (int i = 0; i < triangles.Length; i += 3)
        {
            var p0 = vertices[triangles[i + 0]];
            var p1 = vertices[triangles[i + 1]];
            var p2 = vertices[triangles[i + 2]];
 
            p0 = normals[triangles[i + 0]];
            p1 = normals[triangles[i + 1]];
            p2 = normals[triangles[i + 2]];
 
            if (((p0 + p1 + p2) / 3) == hittedTriangleNormal)
            {
                trianglesToRemove.Add(triangles[i + 0]);
                trianglesToRemove.Add(triangles[i + 1]);
                trianglesToRemove.Add(triangles[i + 2]);
            }
        }

        GameObject newCube = new GameObject();
        newCube.transform.position = objectPosition;

        newCube.AddComponent<MeshFilter>();
        newCube.AddComponent<MeshRenderer>();
 
        for (int i = 0; i < triangles.Length; i+=3)
        {
            bool v1 = (triangles[i + 0] == trianglesToRemove[0]);
            bool v2 = (triangles[i + 1] == trianglesToRemove[1]);
            bool v3 = (triangles[i + 2] == trianglesToRemove[2]);
 
            if ((v1 && v2 && v3))
            {
                triangles.RemoveRange(i, trianglesToRemove.Count);
            }
        }
 
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        newCube.GetComponent<MeshFilter>().mesh = mesh;
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .