Search code examples
c#unity-game-engineexceptionmemorycube

Out of Memory Exception in Unity generating Cube subdividing each face of the cube 4 times


I want to generate a cube and subdivide each face of the cube 4 times, in this way a cube of 6 faces will have 24 faces. I'm am trying doing this in Unity3d but its giving me Out of Memory Exception when I try executing it. I think it may be due to some bad efficient code, but I think I'm missing something because I'm trying to see if I can make it more efficient and I don't really see nothing very bad.

Here is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class sphereMesh : MonoBehaviour
{
// Start is called before the first frame update

Mesh mesh;
List<Vector3> vertices  = new List<Vector3>();
List<int> triangulos = new List<int>();

public int numeroSubdivisiones = 1;
static Vector3[] faceCubes = {
    new Vector3(1, 1, 1), //0
    new Vector3(-1, 1, 1), //1
    new Vector3(-1, -1, 1), //2
    new Vector3(1, -1, 1), //3
    new Vector3(-1, 1, -1), //4
    new Vector3(1, 1, -1), //5
    new Vector3(1, -1, -1), //6
    new Vector3(-1, -1, -1) //7
};

static int[][] facetriangulos = {
    // Cara trasera
    new int[]{0,1,2,3},
    // Cara derecha
    new int[]{5,0,3,6},
    // Cara frontal
    new int[]{4,5,6,7},
    // Cara izquierda
    new int[]{1,4,7,2},
    // Cara arriba
    new int[]{5,4,1,0},
    // Cara abajo
    new int[]{3,2,7,6},
};

void MakeFace(int dir)
{
    vertices.AddRange(faceVertices(dir));

    int vCount = vertices.Count;
    triangulos.Add(vCount - 4);
    triangulos.Add(vCount - 4 + 1);
    triangulos.Add(vCount - 4 + 2);
    triangulos.Add(vCount - 4);
    triangulos.Add(vCount - 4 + 2);
    triangulos.Add(vCount - 4 + 3);
}

void MakeCube()
{
    vertices = new List<Vector3>();
    triangulos = new List<int>();

    for (int i = 0; i <6; i++)
    {
        MakeFace(i);
    }
}

// Funcion que crea una cara de vertices
public static Vector3[] faceVertices(int dir)
{
    Vector3[] fv = new Vector3[4];

    for (int i = 0; i < fv.Length; i++)
    {
        // La direccion y la posicion del array
        fv[i] = faceCubes[facetriangulos[dir][i]];
    }

    return fv;
}

// Modifica la lista de vertices y la actualiza
// De forma que un cuadrado da lugar a otros cuatro cuadrados
// T --> Top, D --> Down, L --> Left, R --> Right
// v --> Vertice
void subdividirCuadrado(Vector3 vTL, Vector3 vTR, Vector3 vDL, Vector3 vDR)
{
    Vector3 vT = vT = Vector3.Lerp(vTR, vTL, 0.5f);
    Vector3 vD = vD = Vector3.Lerp(vDR, vDL, 0.5f);

    Vector3 vR =  vR = Vector3.Lerp(vTR,vDR, 0.5f);
    Vector3 vL =  vL = Vector3.Lerp(vTL,vDL, 0.5f);

    Vector3 vCenter = Vector3.Lerp(vR, vL, 0.5f);

    int size = vertices.Count;
    vertices.AddRange(new List<Vector3> {vT, vD, vL, vR, vTL, vTR, vDL, vDR, vCenter});

    int tT = size + 0;
    int tD = size + 1;
    int tL = size + 2;
    int tR = size + 3;
    int tTL = size + 4;
    int tTR = size + 5;
    int tDL = size + 6;
    int tDR = size + 7;
    int tCenter = size + 8;

    triangulos.AddRange(new List<int> {tL, tTL, tT});
    triangulos.AddRange(new List<int> {tL, tT, tCenter});

    triangulos.AddRange(new List<int> {tCenter, tT, tTR});
    triangulos.AddRange(new List<int> {tCenter, tTR, tR});

    triangulos.AddRange(new List<int> {tDL, tL, tCenter});
    triangulos.AddRange(new List<int> {tDL, tCenter, tD});
    
    triangulos.AddRange(new List<int> {tD, tCenter, tR});
    triangulos.AddRange(new List<int> {tD, tR, tDR});
}

void subCubo()
{
    for(int j = 0; j < numeroSubdivisiones; j++)
    {
        Debug.Log("AAAAA" + vertices.Count);

        for (int i = 0; i < vertices.Count; i += 4)
        {
            subdividirCuadrado(vertices[i], vertices[i+1], vertices[i+2], vertices[i+3]);

/*
            mesh.vertices[i][0] =  mesh.vertices[i][0]/i;
            mesh.vertices[i][1] =  mesh.vertices[i][1]/i;
            mesh.vertices[i][2] =  mesh.vertices[i][2]/i;

            mesh.vertices[i+1][0] =  mesh.vertices[i+1][0]/i+1;
            mesh.vertices[i+1][1] =  mesh.vertices[i+1][1]/i+1;
            mesh.vertices[i+1][2] =  mesh.vertices[i+1][2]/i+1;

            mesh.vertices[i+2][0] =  mesh.vertices[i+2][0]/i+2;
            mesh.vertices[i+2][1] =  mesh.vertices[i+2][1]/i+2;
            mesh.vertices[i+2][2] =  mesh.vertices[i+2][2]/i+2;

            mesh.vertices[i+3][0] =  mesh.vertices[i+3][0]/i+3;
            mesh.vertices[i+3][1] =  mesh.vertices[i+3][1]/i+3;
            mesh.vertices[i+3][2] =  mesh.vertices[i+3][2]/i+3;
*/
        }
    }
}

void Awake()
{
    mesh = GetComponent<MeshFilter>().mesh;
}

void Start()
{
    MakeCube();
    subCubo();
    UpdateMesh();
}

// Update is called once per frame
void UpdateMesh()
{
    mesh.Clear();

    mesh.vertices = vertices.ToArray();
    mesh.triangles = triangulos.ToArray();
    mesh.RecalculateNormals();
}

}

Solution

  • I think this is infinity loop:

    for (int i = 0; i < vertices.Count; i += 4)
        {
            subdividirCuadrado(vertices[i], vertices[i+1], vertices[i+2], vertices[i+3]);
    

    You keep going through the loop until i is bigger than count of items in vertices. During each iteration i is increased by 4, but there are 9 new items in vertices:

    vertices.AddRange(new List<Vector3> {vT, vD, vL, vR, vTL, vTR, vDL, vDR, vCenter});
    

    Therefore i is never bigger than vertices.count and thus the loop is infinite.