Remove faces from a cubemesh

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Tanders

I have a project, in which I have I use a Gridmap to draw the playing field.

There’s different levels, and when the level change, I want to fade out the level to show the next level.

The issue is, when the gridmap tiles are set to transparent, the extra faces from the cubes are shown, like so:

Unwanted faces showing

From my research, the best way to handle this, is simply to remove the unwanted faces. So I have before edited the cubes in blender, and importing them without the unwanted faces, but this is a ton of work, so I want to do it in code. My plan is to make an editor script, which checks if 2 faces are colliding, and then delete said surfaces.

I know I can find the cubes on a gridmap like so:

     foreach (var mesh in GetMeshes())
        {
            if (mesh.GetType() == typeof(CubeMesh))
            {
                CubeMesh cm = (CubeMesh)mesh;

            }
        }

But I can’t quite figure out what to do from here. I tried to see if I could convert them to ArrayMeshes, and then use the MeshDataTool to delete the faces, but I can’t figure out how to do so. Anyone have any suggestion, or maybe different approaches to this issue?

:bust_in_silhouette: Reply From: Tanders

While not a pretty solution, I’ve found a fix for it.

Here’s the code. All you need to ensure, is that the cubemesh has the resource name “tile”. This code runs in the editor, with the variables exported. I’ve tried to ensure that you wont mess up any element by accident.

using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
[Tool]
public class ToolLevelEditor : GridMap
{
    public class SquareSideVertexContainer
    {
        public Vector3 V1, V2, V3, V4, V5, V6;
        public SquareSideVertexContainer(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Vector3 v5, Vector3 v6)
        {
            V1 = v1;
            V2 = v2;
            V3 = v3;
            V4 = v4;
            V5 = v5;
            V6 = v6;
        }
    }

    [Export]
    bool RemoveUnnecessaryFaces = false;
    [Export]
    bool UndoRemoveUnnecessaryFaces = false;
    public override void _Process(float delta)
    {
        if (UndoRemoveUnnecessaryFaces)
        {
            if (GetChildren().Count == 0)
            {
                GD.Print("Nothing to undo!");
                UndoRemoveUnnecessaryFaces = false;
                return;
            }
            foreach (var mesh in GetMeshes())
            {
                if (mesh.GetType() == typeof(CubeMesh))
                {
                    CubeMesh cm = (CubeMesh)mesh;
                    if (cm.ResourceName == "tile")
                    {
                        var mat = (SpatialMaterial)cm.Material;
                        mat.AlbedoColor = new Color(0.5f, 0, 0, 1);
                    }
                }
            }
            foreach (MeshInstance childMesh in GetChildren())
            {
                childMesh.QueueFree();
            }
            UndoRemoveUnnecessaryFaces = false;
        }

        if (RemoveUnnecessaryFaces)
        {
            if (GetChildren().Count != 0)
            {
                GD.Print("Undo first!");
                RemoveUnnecessaryFaces = false;
                return;
            }
            List<MeshInstance> meshes = new List<MeshInstance>();
            List<Transform> transforms = new List<Transform>();
            List<SquareSideVertexContainer> triangles = new List<SquareSideVertexContainer>();
            Transform prevTrans = new Transform();

            foreach (var mesh in GetMeshes())
            {
                if (mesh.GetType() == typeof(Transform))
                {
                    prevTrans = (Transform)mesh;
                }
                MeshInstance mi = new MeshInstance();
                if (mesh.GetType() == typeof(CubeMesh))
                {
                    CubeMesh cm = (CubeMesh)mesh;
                    if (cm.ResourceName == "tile")
                    {
                        var mat = (SpatialMaterial)cm.Material;
                        mat.AlbedoColor = new Color(0.5f, 0, 0, 0);

                        for (int i = 0; i < cm.GetFaces().Length; i += 6)
                        {
                            triangles.Add(new SquareSideVertexContainer(cm.GetFaces()[i], cm.GetFaces()[i + 1], cm.GetFaces()[i + 2], cm.GetFaces()[i + 3], cm.GetFaces()[i + 4], cm.GetFaces()[i + 5]));
                        }

                        meshes.Add(mi);
                        transforms.Add((Transform)prevTrans);
                    }
                }
            }

            List<SquareSideVertexContainer> tmp = new List<SquareSideVertexContainer>();
            List<int> removedIndexes = new List<int>();
            foreach (var vectorContainer in triangles)
            {
                tmp.Add(new SquareSideVertexContainer(vectorContainer.V1, vectorContainer.V2, vectorContainer.V3, vectorContainer.V4, vectorContainer.V5, vectorContainer.V6));
            }
            for (int i = 0; i < triangles.Count; i++)
            {
                var individualFaces = tmp.Count / meshes.Count;
                triangles[i].V1 += transforms[(int)i / individualFaces].origin;
                triangles[i].V2 += transforms[(int)i / individualFaces].origin;
                triangles[i].V3 += transforms[(int)i / individualFaces].origin;
                triangles[i].V4 += transforms[(int)i / individualFaces].origin;
                triangles[i].V5 += transforms[(int)i / individualFaces].origin;
                triangles[i].V6 += transforms[(int)i / individualFaces].origin;
            }
            for (int i = triangles.Count - 1; i >= 0; i--)
            {
                int matches = 0;
                for (int j = 0; j < triangles.Count; j++)
                {
                    bool xCheck = false, yCheck = false, zCheck = false, V5check = false; ;
                    if (triangles[i].V1 == triangles[j].V1 || triangles[i].V1 == triangles[j].V2 || triangles[i].V1 == triangles[j].V3 || triangles[i].V1 == triangles[j].V5)
                    {
                        xCheck = true;
                        if (triangles[i].V2 == triangles[j].V1 || triangles[i].V2 == triangles[j].V2 || triangles[i].V2 == triangles[j].V3 || triangles[i].V2 == triangles[j].V5)
                        {
                            yCheck = true;
                            if (triangles[i].V3 == triangles[j].V1 || triangles[i].V3 == triangles[j].V2 || triangles[i].V3 == triangles[j].V3 || triangles[i].V3 == triangles[j].V5)
                            {
                                zCheck = true;
                                if (triangles[i].V5 == triangles[j].V1 || triangles[i].V5 == triangles[j].V2 || triangles[i].V5 == triangles[j].V3 || triangles[i].V5 == triangles[j].V5)
                                {
                                    V5check = true;
                                }
                            }
                        }
                    }
                    if (xCheck == true && yCheck == true && zCheck == true && V5check == true)
                    {
                        matches++;
                        if (matches == 2)
                        {
                            tmp[i] = new SquareSideVertexContainer(Vector3.Zero, Vector3.Zero, Vector3.Zero, Vector3.Zero, Vector3.Zero, Vector3.Zero);
                        }
                    }
                }
            }
            for (int i = 0; i < meshes.Count; i++)
            {
                var st = new SurfaceTool();

                var individualFaces = tmp.Count / meshes.Count;
                var tmpMesh = new ArrayMesh();
                for (int j = 0; j < individualFaces; j++)
                {
                    if (tmp[i * individualFaces + j] != new SquareSideVertexContainer(Vector3.Zero, Vector3.Zero, Vector3.Zero, Vector3.Zero, Vector3.Zero, Vector3.Zero))
                    {
                        st.Begin(Mesh.PrimitiveType.TriangleFan);
                        st.AddNormal(new Vector3(0, 0, 1));
                        st.AddVertex(tmp[i * individualFaces + j].V1);
                        st.AddVertex(tmp[i * individualFaces + j].V2);
                        st.AddVertex(tmp[i * individualFaces + j].V3);
                        st.Commit(tmpMesh);

                        st.Begin(Mesh.PrimitiveType.TriangleFan);
                        st.AddNormal(new Vector3(0, 0, 1));
                        st.AddVertex(tmp[i * individualFaces + j].V4);
                        st.AddVertex(tmp[i * individualFaces + j].V5);
                        st.AddVertex(tmp[i * individualFaces + j].V6);
                        st.Commit(tmpMesh);
                    }
                }

                meshes[i].Mesh = tmpMesh;

                var mat2 = new SpatialMaterial();
                mat2.FlagsTransparent = true;
                mat2.AlbedoColor = new Color(1, 0, 0, 0.5f);
                meshes[i].MaterialOverride = mat2;
                meshes[i].Translate(transforms[i].origin);
                AddChild(meshes[i]);
                meshes[i].Owner = GetTree().EditedSceneRoot;
            }
            RemoveUnnecessaryFaces = false;
        }
    }
}

Some notes: The code is pretty poorly optimized, so I don’t suggest running this runtime.
It works by finding squares of vertexes that are opposite each other, and removes them if 2 are identical.

Hope some can find this of use!