Marching cubes not creating expected meshes

319 views Asked by At

I have been trying to implement marching cubes in unity with c# but the meshes that are being created all have a rotation that is off by 90 degrees.

in this example I am trying to create a cube.

example of rotation

this is my current code that I have if any one can figure out what the problem is that would be great thanks.

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

[RequireComponent(typeof(MeshFilter))]
public class train : MonoBehaviour
{
    //setup e.g varables and lists
    //----------------------------------------------------------------------------------------------------
    //size of the chunk
    public int size = 10;
    //binary stuff
    public List<int> binary = new List<int>();
    int bitewisenum = 0;
    //posithions
    public static Vector3 xyz = new Vector3();
    public Vector3 list_edges = new Vector3();
    //how much air      the cut off point bettween air and solid  0.45 - 0.55 works best
    public float dencity = 0.4f;
    //mesh
    public Vector3[] vertices;
    public List<Vector3> vertices_list = new List<Vector3>();
    public List<Vector3> vertices_list_store = new List<Vector3>();
    public List<Vector3> inverlist = new List<Vector3>();
    //we can convert it back to an array later 
    public List<int> tri = new List<int>();
    Mesh mesh;
    private int[] num;
    private float airsolid_test;
    public float cutoff; // 11 works best
  
    //perlin noise
    //---------------------------------------------------------------------------------------------------
    public static float Perlin3D(float x, float y, float z, float cut)
    {
        //float AB = Mathf.PerlinNoise(x, y);
        //float BC = Mathf.PerlinNoise(y, z);
        //float AC = Mathf.PerlinNoise(x, z);
        //
        //
        //float BA = Mathf.PerlinNoise(y, x);
        //float CB = Mathf.PerlinNoise(z, y);
        //float CA = Mathf.PerlinNoise(z, x);
        //
        ////get the avarge
        //float ABC = AB + BC + AC + BA + CB + CA;
        //float per = ABC / 6f;
        //if (y > cut)
        //{
        //    per = Mathf.Pow(per * (y / 8.5f), 2.718f) + 0.3f;
        //}

        //testing
        float per;
        if (x >= cut)
        {
            per = 0f;
        } else if (y >= cut)
        {
            per = 0f;
        }
        else if (z <= 0)
        {
            per = 0f;
        }
        else if (x <= 0)
        {
            per = 0f;
        }
        else if (z >= cut)
        {
            per = 0f;
        }
        else if (y <= 0)
        {
            per = 0f;
        }else
        {
            per = 10f;
        }
        //testing ends
        return per;
    }
    //----------------------------------------------------------------------------------------
    private void Start()
    {
        //set up binary
        binary.Add(1);
        binary.Add(2);
        binary.Add(4);
        binary.Add(8);
        binary.Add(16);
        binary.Add(32);
        binary.Add(64);
        binary.Add(128);

        //setup mesh
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;
        tri.Clear();

        //testing --------------------------------------
        airsolid_test = dencity;
        //0.1 is because of the perlin noise
        for (float x = 0.1f; x < 16; x++)
        {
            for (int y = 0; y < 15; y++)
            {
                for (int z = 0; z < 15; z++)
                {
                    //airsolid_test = dencity;
                    //if (y >= cutoff)
                    //{//mountans
                    //    airsolid_test += 0.0f;//0.2f
                    //}
                    //else
                    //{//caves
                    //    airsolid_test -= 0.005f;//0.005
                    //}
                    xyz.x = x;
                    xyz.y = y;
                    xyz.z = z;
                    createshape(x, y, z);
                    upmesh();
                }
            }
        }
    }
    //xyz.x = x;
    // xyz.y = y;
    // xyz.z = z;
    // createshape(x, y, z);
    //upmesh();
    //upmesh stands for update mesh
    void upmesh()
    {
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = tri.ToArray();
        mesh.RecalculateNormals();
    }


    //-------------------------------------------------------------------------------------

    // this is the main function and you give it an xyz cordanit and it sets the mesh's triangles and veticeys
    void createshape(float x, float y, float z)
    {
        //list for the binary
        List<int> bite = new List<int>();
        bite.Clear();
        bitewisenum = 0;



        //this is getting the binay representation for each point on the cube if the point is > the density value store it as a 1 else as a 0 
        // so we end up with a binary number like 10011101
        //position 7
        if (Perlin3D(x + 1, y, z + 1, cutoff) > airsolid_test)
        {
            bite.Add(1);
            //these store the value for intertopilation later but im not using it yet
            float Pose_7 = Perlin3D(x + 1, y, z + 1,cutoff);
        }
        else
        {
            bite.Add(0);
        }
        //position 6
        if (Perlin3D(x + 1, y + 1, z + 1, cutoff) > airsolid_test)
        {
            bite.Add(1);
            float Pose_6 = Perlin3D(x + 1, y + 1, z + 1, cutoff);
        }
        else
        {
            bite.Add(0);
        }
        //position 5
        if (Perlin3D(x, y + 1, z + 1, cutoff) > airsolid_test)
        {
            bite.Add(1);
            float Pose_5 = Perlin3D(x, y + 1, z + 1, cutoff);
        }
        else
        {
            bite.Add(0);
        }
        //position 4
        if (Perlin3D(x, y, z + 1, cutoff) > airsolid_test)
        {
            bite.Add(1);
            float Pose_4 = Perlin3D(x, y, z + 1, cutoff);
        }
        else
        {
            bite.Add(0);
        }
        //position 3
        if (Perlin3D(x + 1, y, z, cutoff) > airsolid_test)
        {
            bite.Add(1);
            float Pose_3 = Perlin3D(x + 1, y, z, cutoff);
        }
        else
        {
            bite.Add(0);
        }
        //position 2
        if (Perlin3D(x + 1, y + 1, z, cutoff) > airsolid_test)
        {
            bite.Add(1);
            float Pose_2 = Perlin3D(x + 1, y + 1, z, cutoff);
        }
        else
        {
            bite.Add(0);
        }
        //position 1
        if (Perlin3D(x, y + 1, z, cutoff) > airsolid_test)
        {
            bite.Add(1);
            float Pose_1 = Perlin3D(x, y + 1, z, cutoff);
        }
        else
        {
            bite.Add(0);
        }
        //position 0
        if (Perlin3D(x, y, z, cutoff) > airsolid_test)
        {
            bite.Add(1);
            float Pose_0 = Perlin3D(x, y, z, cutoff);
        }
        else
        {
            bite.Add(0);
        }



        //convert binary in to decimal because i dont know an easy way to do this but
        //loop throught all items in the binary list and change them
        for (int i = 0; i <= 7; i++)
        {
            if (bite[i] == 1)
            {
                bitewisenum += binary[i];
            }
        }
        //print(bitewisenum);

        //check if its not all air or inside an object
        //this means that we check if its 0 or 255
        //now we need to make the mesh and show it
        if (bitewisenum != 0 && bitewisenum != 255)
        {
            //Debug.Log("made a mesh");
            //store the int array for easyer use
            int[] trian = table.TriangleTable[bitewisenum];
            /*
             * at this point the int array describes edges not postions
             * and we need to change that so what we do is loop through ever item in the list and
             * parce it through a function(table.transform_to_postion) this returns a Vector 3
             * which we then add to a list
             */
            vertices_list.Clear();
            for (int num = 0; num < trian.Length; num++)
            {
                //get the actule postions
                //we give the function a edge index as an int which represents a edge index and it gives you the actule postion back as a vector 3
                list_edges = transform_to_postion(trian[num]);

                //add them to the list
                vertices_list.Add(list_edges);
                vertices_list_store.Add(list_edges);
                //end of the for loop
            }
            // set vetaceys
            vertices = vertices_list_store.ToArray();
            //

            //setting the triangles based off how many items there are on the verticeys list
            if (vertices_list.Count / 3 == 1)
            {
                for (int i = 1; i < 4; i++)
                {
                    tri.Add(tri.Count);
                }
            }
            else if (vertices_list.Count / 3 == 2)
            {
                for (int i = 1; i < 7; i++)
                {
                    tri.Add(tri.Count);
                }
            }
            else if (vertices_list.Count / 3 == 3)
            {
                for (int i = 1; i < 10; i++)
                {
                    tri.Add(tri.Count);
                }
            }
            else if (vertices_list.Count / 3 == 4)
            {
                for (int i = 1; i < 13; i++)
                {
                    tri.Add(tri.Count);
                }
            }
            else if (vertices_list.Count / 3 == 5)
            {
                for (int i = 1; i < 16; i++)
                {
                    tri.Add(tri.Count);
                }
            }
            /*
            Debug.Log("the legnth of verticys: "+vertices.Length);                                                                                                    
            Debug.Log("the legnth of tri: "+tri.Length);
            Debug.Log("tri legnth  " + tri.Length);
            end of the if loop
            */
        }

        //end of the function                                                                                
    }

    public static Vector3 transform_to_postion(int number_edge)
    {

        Vector3 xyz_of_edge = new Vector3();
        //check which one it is and then set the xyz
        if (number_edge == 0)
        {
            xyz_of_edge.x = xyz.x + 0.5f;
            xyz_of_edge.y = xyz.y;
            xyz_of_edge.z = xyz.z + 1f;
        }
        else if (number_edge == 1)
        {
            xyz_of_edge.x = xyz.x + 1f;
            xyz_of_edge.y = xyz.y;
            xyz_of_edge.z = xyz.z + 0.5f;
        }
        else if (number_edge == 2)
        {
            xyz_of_edge.x = xyz.x + 0.5f;
            xyz_of_edge.y = xyz.y;
            xyz_of_edge.z = xyz.z;
        }
        else if (number_edge == 3)
        {
            xyz_of_edge.x = xyz.x;
            xyz_of_edge.y = xyz.y;
            xyz_of_edge.z = xyz.z + 0.5f;
        }
        else if (number_edge == 4)
        {
            xyz_of_edge.x = xyz.x + 0.5f;
            xyz_of_edge.y = xyz.y + 1f;
            xyz_of_edge.z = xyz.z + 1f;
        }
        else if (number_edge == 5)
        {
            xyz_of_edge.x = xyz.x + 1f;
            xyz_of_edge.y = xyz.y + 1f;
            xyz_of_edge.z = xyz.z + 0.5f;
        }
        else if (number_edge == 6)
        {
            xyz_of_edge.x = xyz.x + 0.5f;
            xyz_of_edge.y = xyz.y + 1f;
            xyz_of_edge.z = xyz.z;
        }
        else if (number_edge == 7)
        {
            xyz_of_edge.x = xyz.x;
            xyz_of_edge.y = xyz.y + 1;
            xyz_of_edge.z = xyz.z + 0.5f;
        }
        else if (number_edge == 8)
        {
            xyz_of_edge.x = xyz.x;
            xyz_of_edge.y = xyz.y + 0.5f;
            xyz_of_edge.z = xyz.z + 1f;
        }
        else if (number_edge == 9)
        {
            xyz_of_edge.x = xyz.x + 1f;
            xyz_of_edge.y = xyz.y + 0.5f;
            xyz_of_edge.z = xyz.z + 1f;
        }
        else if (number_edge == 10)
        {
            xyz_of_edge.x = xyz.x + 1f;
            xyz_of_edge.y = xyz.y + 0.5f;
            xyz_of_edge.z = xyz.z;
        }
        else if (number_edge == 11)
        {
            xyz_of_edge.x = xyz.x;
            xyz_of_edge.y = xyz.y + 0.5f;
            xyz_of_edge.z = xyz.z;
        }
        //Debug.Log("edge index " + number_edge);
        //Debug.Log("edges "+xyz_of_edge);
        //Debug.Log(xyz_of_edge);
        return xyz_of_edge;
    }
}
1

There are 1 answers

0
Paradox On BEST ANSWER

I figured out that the problem was the way that I was labeling the points of the cube. I had had them wrong for the triangulation table this was causing the orientation error. to fix it all I did was in my code I redefined the points to there actual value.