Exemplo n.º 1
0
    static MarchingCubes computeSphereChunk(MarchingCubes mc, float[,,] noiseMap, float heightScale, int bodyRadius, Vector3 offset, int vertexIncrement, int chunkSize)
    {
        for (int z = 0; z < (chunkSize / vertexIncrement) + 1; z++)
        {
            for (int y = 0; y < (chunkSize / vertexIncrement) + 1; y++)
            {
                for (int x = 0; x < (chunkSize / vertexIncrement) + 1; x++)
                {
                    float xComponent = (x * vertexIncrement + offset.x);
                    float yComponent = (y * vertexIncrement + offset.y);
                    float zComponent = (z * vertexIncrement + offset.z);

                    float surface = (xComponent * xComponent) + (yComponent * yComponent) + (zComponent * zComponent) - (bodyRadius * bodyRadius) + bodyRadius;
                    mc.set_data(surface - heightScale * bodyRadius * noiseMap[x * vertexIncrement, y * vertexIncrement, z * vertexIncrement], x, y, z);
                }
            }
        }
        return(mc);
    }
Exemplo n.º 2
0
    void Start()
    {
        currentTarget = target;
        m_perlin      = new PerlinNoise(2);

        //Target is the value that represents the surface of mesh
        //For example the perlin noise has a range of -1 to 1 so the mid point is were we want the surface to cut through
        //The target value does not have to be the mid point it can be any value with in the range
        MarchingCubes.SetTarget(target);

        //Winding order of triangles use 2,1,0 or 0,1,2
        MarchingCubes.SetWindingOrder(0, 1, 2);

        //Set the mode used to create the mesh
        //Cubes is faster and creates less verts, tetrahedrons is slower and creates more verts but better represents the mesh surface
        //MarchingCubes.SetModeToCubes();
        MarchingCubes.SetModeToCubes();

        //The size of voxel array. Be carefull not to make it to large as a mesh in unity can only be made up of 65000 verts
        int width  = 32;
        int height = 32;
        int length = 32;

        voxels = new float[width, height, length];

        //Fill voxels with values. Im using perlin noise but any method to create voxels will work
        CalcVoxels(width, height, length);

        Mesh mesh = MarchingCubes.CreateMesh(voxels);

        //The diffuse shader wants uvs so just fill with a empty array, there not actually used
        mesh.uv = new Vector2[mesh.vertices.Length];
        mesh.RecalculateNormals();

        m_mesh = new GameObject("Mesh");
        m_mesh.AddComponent <MeshFilter>();
        m_mesh.AddComponent <MeshRenderer>();
        m_mesh.GetComponent <Renderer>().material = m_material;
        m_mesh.GetComponent <MeshFilter>().mesh   = mesh;
        //Center mesh
        m_mesh.transform.localPosition = new Vector3(-32 / 2, -32 / 2, -32 / 2);
    }
Exemplo n.º 3
0
    // Use the marching cubes algorithm to extract the isosurface
    private void ExtractIsosurface()
    {
        // Get the gameobject and mesh
        GameObject o = this.gameObject;

        GetMesh(ref o, ref m, true);

        // Clear lists
        vertices.Clear();
        triangles.Clear();
        uv.Clear();

        // March through each cell in the grid
        for (int z = 0; z < GridSize.z; z++)
        {
            for (int y = 0; y < GridSize.y; y++)
            {
                for (int x = 0; x < GridSize.x; x++)
                {
                    // Set the vertices of the cell
                    cell.p[0] = grid[x, y, z + 1];
                    cell.p[1] = grid[x + 1, y, z + 1];
                    cell.p[2] = grid[x + 1, y, z];
                    cell.p[3] = grid[x, y, z];
                    cell.p[4] = grid[x, y + 1, z + 1];
                    cell.p[5] = grid[x + 1, y + 1, z + 1];
                    cell.p[6] = grid[x + 1, y + 1, z];
                    cell.p[7] = grid[x, y + 1, z];
                    MarchingCubes.Triangulate(ref cell, Isolevel);
                    BuildCellMesh(ref cell);
                }
            }
        }

        // Convert the vertex, triangle and uv lists to arrays
        Vector3[] vertexArray   = vertices.ToArray();
        int[]     triangleArray = triangles.ToArray();
        Vector2[] uvArray       = uv.ToArray();

        // Set the grid mesh
        SetMesh(ref o, ref vertexArray, ref triangleArray, ref uvArray);
    }
Exemplo n.º 4
0
        /// <summary>
        /// Builds NavMesh from grid using MarchingCubes algorithm
        /// </summary>
        public void MarchCubes()
        {
            if (!gridSettings)
            {
                return;
            }
            var filter   = GetComponent <MeshFilter>();
            var collider = GetComponent <MeshCollider>();

            filter.sharedMesh   = null;
            collider.sharedMesh = null;
            if (grid == null)
            {
                GenerateGrid();
            }
            var mesh = MarchingCubes.March(grid, gridSettings.isoLevel);

            filter.sharedMesh   = mesh;
            collider.sharedMesh = mesh;
        }
Exemplo n.º 5
0
        private void TestClosed(int a, int b, int c, int d, int e, int f, int g, int h)
        {
            // ARRANGE
            float[,,] cells = new float[, , ] {
                { { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } },
                { { -1, -1, -1, -1 }, { -1, a, b, -1 }, { -1, c, d, -1 }, { -1, -1, -1, -1 } },
                { { -2, -2, -2, -2 }, { -2, e, f, -2 }, { -2, g, h, -2 }, { -2, -2, -2, -2 } },
                { { -2, -2, -2, -2 }, { -2, -2, -2, -2 }, { -2, -2, -2, -2 }, { -2, -2, -2, -2 } },
            };

            // ACT
            ArrayGrid   grid = new ArrayGrid(cells, Vector3.Zero, Vector3.One);
            ListSurface s    = new ListSurface();

            MarchingCubes.MarchIntoSurface(grid, 0, s);
            bool isClosed = s.IsClosed();

            // ASSERT
            Assert.IsTrue(isClosed);
        }
Exemplo n.º 6
0
    void CreateChunkMesh(Vector3Int Position)
    {
        foreach (Vector3Int neighbor in Utils.ChunkNeighbors)
        {
            if (!LoadedChunks.ContainsKey(Position + neighbor))
            {
                CreateChunkData(Position + neighbor);
            }
        }
        ChunkData Chunk = LoadedChunks[Position];

        if (!Chunk.IsDirty)
        {
            return;
        }
        MarchingCubes meshGen = new MarchingCubes();

        Chunk.MeshData = meshGen.GenerateMesh(Chunk);
        Chunk.IsDirty  = false;
    }
Exemplo n.º 7
0
        public void GridGenerateSurface_SingleValue1_OtherValueMinus1_Iso0_GeneratesCorrectTriangle()
        {
            // ARRANGE
            ArrayGrid   grid     = GenerateSingle(1, -1, 0);
            ListSurface expected = new ListSurface();

            expected.AddVertex(new Vector3(0.5f, 0, 0));
            expected.AddVertex(new Vector3(0, 0.5f, 0));
            expected.AddVertex(new Vector3(0, 0, 0.5f));
            expected.AddTriangle(0, 1, 2);

            // ACT
            ListSurface s = new ListSurface();

            MarchingCubes.MarchIntoSurface(grid, 0, s);
            bool areEqual = ListSurface.AreSurfacesEquivalent(expected, s);

            // ASSERT
            Assert.IsTrue(areEqual);
        }
Exemplo n.º 8
0
 public void Generate(float isolevel, Action callback = null)
 {
     MarchingCubes.Target = isolevel;
     MarchingCubes.SetWindingOrder(WindingOrder.i, WindingOrder.j, WindingOrder.k);
     MarchingCubes.GeneratorMode = MarchingCubes.Mode.MarchingCube;
     // CalculateNormals();
     primitive = CreateMesh();
     if (mf != null)
     {
         mf.mesh = primitive;
     }
     if (mc != null)
     {
         mc.sharedMesh = primitive;
     }
     if (callback != null)
     {
         callback();
     }
 }
    void Start()
    {
        //Make 2 perlin noise objects, one is used for the surface and the other for the caves
        PerlinNoise m_surfacePerlin = new PerlinNoise(m_surfaceSeed);
        PerlinNoise m_cavePerlin    = new PerlinNoise(m_caveSeed);

        //Set some varibles for the marching cubes plugin
        MarchingCubes.SetTarget(0.0f);
        MarchingCubes.SetWindingOrder(2, 1, 0);
        MarchingCubes.SetModeToCubes();

        //create a array to hold the voxel chunks
        m_voxelChunk = new VoxelChunk[m_chunksX, m_chunksY, m_chunksZ];

        //The offset is used to centre the terrain on the x and z axis. For the Y axis
        //we can have a certain amount of chunks above the y=0 and the rest will be below
        Vector3 offset = new Vector3(m_chunksX * m_voxelWidth * -0.5f, -(m_chunksY - m_chunksAbove0) * m_voxelHeight, m_chunksZ * m_voxelLength * -0.5f);

        for (int x = 0; x < m_chunksX; x++)
        {
            for (int y = 0; y < m_chunksY; y++)
            {
                for (int z = 0; z < m_chunksZ; z++)
                {
                    //The position of the voxel chunk
                    Vector3 pos = new Vector3(x * m_voxelWidth, y * m_voxelHeight, z * m_voxelLength);
                    //Create the voxel object
                    m_voxelChunk[x, y, z] = new VoxelChunk(pos + offset, m_voxelWidth, m_voxelHeight, m_voxelLength, m_surfaceLevel);
                    //Create the voxel data
                    m_voxelChunk[x, y, z].CreateVoxels(m_surfacePerlin, m_cavePerlin);
                    //Smooth the voxels, is optional but I think it looks nicer
                    m_voxelChunk[x, y, z].SmoothVoxels();
                    //Create the normals. This will create smoothed normal.
                    //This is optional and if not called the unsmoothed mesh normals will be used
                    m_voxelChunk[x, y, z].CalculateNormals();
                    //Creates the mesh form voxel data using the marching cubes plugin and creates the mesh collider
                    m_voxelChunk[x, y, z].CreateMesh(m_material);
                }
            }
        }
    }
Exemplo n.º 10
0
    void Update()
    {
        time += Time.deltaTime;

        center1 = new Vector3(Mathf.Cos(Time.time * 3.14f) * 16 + 16, 32, Mathf.Sin(Time.time * 3.14f) * 16 + 16);

        if (time > 1 / 30f)
        {
            time         -= 1 / 30f;
            currentTarget = target;
            MarchingCubes.SetTarget(target);
            CalcVoxels(32, 32, 32);
            Mesh mesh = MarchingCubes.CreateMesh(voxels);

            //The diffuse shader wants uvs so just fill with a empty array, there not actually used
            mesh.uv = new Vector2[mesh.vertices.Length];
            mesh.RecalculateNormals();
            DestroyImmediate(m_mesh.GetComponent <MeshFilter>().sharedMesh, true);
            m_mesh.GetComponent <MeshFilter>().mesh = mesh;
        }
    }
Exemplo n.º 11
0
            /// <summary>
            /// Executes the code necessary to loading/generating chunk entity data.
            /// </summary>
            /// <param name="index">
            /// The index of the job being performed.
            /// </param>
            public void Execute()
            {
                // Prep chunk generation.
                noiseSettings.offset = location * noiseSettings.size;
                noiseSettings.size  += 1;

                // Perform chunk generation.
                var volumeData = VolumeGenerator.generateData(noiseSettings);
                var meshData   = MarchingCubes.generate(volumeData, noiseSettings.size - 1, lod: 1);

                // Manually copy mesh data.
                for (int index = 0; index < meshData.Length; index++)
                {
                    chunkInfo.meshData.Add(meshData[index]);
                }

                // Copy data and dispose of temporaries from callees.
                chunkInfo.volumeData.CopyFrom(volumeData);
                volumeData.Dispose();
                meshData.Dispose();
            }
Exemplo n.º 12
0
        public static void TestMarchingCubes()
        {
            MarchingCubes mc = new MarchingCubes();

            LocalProfiler p = new LocalProfiler();

            p.Start("GENERATE");
            mc.ParallelCompute = true;
            mc.Generate();
            p.Stop("GENERATE");
            DebugUtil.Log(2, p.AllTimes());

            MeshNormals.QuickCompute(mc.Mesh);

            DebugUtil.WriteDebugMesh(mc.Mesh, "c:\\scratch\\MARCHING_CUBES.obj");

            DMeshSO meshSO = new DMeshSO();

            meshSO.Create(mc.Mesh, CC.ActiveScene.DefaultMeshSOMaterial);
            CC.ActiveScene.AddSceneObject(meshSO, false);
        }
Exemplo n.º 13
0
    public void Build()
    {
        float[,,] voxels = new float[size + 1, size + 1, size + 1];
        int   height;
        float hFactor;

        for (int z = 0; z < size + 1; z++)
        {
            for (int y = 0; y < size + 1; y++)
            {
                height  = yi + y;
                hFactor = (float)(maxHeight - 2 * height) / (float)maxHeight;
                for (int x = 0; x < size + 1; x++)
                {
                    voxels[x, y, z] = -hFactor + m_perlin.FractalNoise3D((float)(xi + x), (float)(yi + y), (float)(zi + z), 3, freq, 1.0f);
                }
            }
        }

        mesh = MarchingCubes.CreateMesh(voxels);

        //UV MAPPING
        Vector3[] vertices = mesh.vertices;
        Vector2[] uvs      = new Vector2[mesh.vertices.Length];
        for (int i = 0; i < uvs.Length; i++)
        {
            uvs[i] = new Vector2(vertices[i].x, vertices[i].z);
        }
        mesh.uv = uvs;
        //NORMALS
        mesh.RecalculateNormals();
        //TANGENTS
        TangentSolver.Solve(mesh);
        mesh.Optimize();
        AssetDatabase.CreateAsset(mesh, "Assets/Resources/meshes/mesh" + xi + yi + zi + ".asset");
        //GAMEOBJECT SETUP
        m_mesh.GetComponent <MeshFilter>().mesh = mesh;
        m_mesh.transform.localPosition          = gPos;
        m_mesh.AddComponent <MeshCollider>();
    }
Exemplo n.º 14
0
    void Awake()
    {
        mesh = new Mesh();
        mc   = new MarchingCubes();
        mc.m_marchingCubesShader    = m_MarchingCubesShader;
        mc.m_clearVerticesShader    = m_FillBufferShader;
        mc.m_calculateNormalsShader = m_calculateNormalsShader;
        mc.m_recalculateNormals     = m_recalculateNormals;
        mc.Initalize(m_x_dim, m_y_dim, m_z_dim, m_size, m_LOD);
        m_densityMap = new float[m_x_dim * m_y_dim * m_z_dim];
        //Random.InitState(20);
        //for(int i = 0; i < m_densityMap.Length; i++) m_densityMap[i] = Random.Range(-1f, 1f);
        //float radius = 7.0f;
        Vector3 center = new Vector3(m_x_dim / 2, m_y_dim / 2, m_z_dim / 2);

        for (int z = 0; z < m_z_dim; z++)
        {
            for (int y = 0; y < m_y_dim; y++)
            {
                for (int x = 0; x < m_x_dim; x++)
                {
                    Vector3 point = center - new Vector3(x, y, z);
                    m_densityMap[x + y * m_x_dim + z * m_x_dim * m_y_dim] = Mathf.Clamp((-1.0f / m_radius) * point.magnitude + 1, -1.0f, 1.0f);
                }
            }
        }

        /*
         * for(int z = 0; z < m_z_dim; z++)
         * {
         *      for(int y = 0; y < m_y_dim; y++)
         *      {
         *              for(int x = 0; x < m_x_dim; x++)
         *              {
         *                      m_densityMap[x + y * m_x_dim + z * m_x_dim * m_y_dim] = -y / (m_y_dim / 2f) + 1f;
         *              }
         *      }
         * }*/
    }
Exemplo n.º 15
0
    public static MeshData GenerateSphereMesh(NoiseMapData mapData, SphereMeshSettings sphereSettings, int vertexIncrement)
    {
        int           mcExpand     = Mathf.Min(Mathf.CeilToInt(sphereSettings.noiseHeightScale * sphereSettings.radius * 3) * 2 + 2, 59);
        int           halfMCExpand = mcExpand / 2;
        Vector3       addOffset    = new Vector3(-halfMCExpand, -halfMCExpand, -halfMCExpand);
        MarchingCubes mc           = new MarchingCubes(sphereSettings.chunkSize / vertexIncrement + mcExpand, sphereSettings.chunkSize / vertexIncrement + mcExpand, sphereSettings.chunkSize / vertexIncrement + mcExpand);

        mc.init_all();
        mc = computeSphere(mc, mapData.noiseMap, sphereSettings.noiseHeightScale, sphereSettings.radius, mapData.offset, vertexIncrement, sphereSettings.chunkSize, halfMCExpand);
        mc.run();
        mc.clean_temps();

        MeshData meshData = new MeshData();

        meshData.vertices = VertexToVector3Vertices(mc.vertices, mc.nverts(), mapData.offset + addOffset, vertexIncrement);
        meshData.normals  = VertexToVector3Normals(mc.vertices, mc.nverts());
        //meshData.uv = NormalsToUVs(mesh.normals);
        meshData.uv        = VerticesToUVs(meshData.vertices);
        meshData.triangles = TrianglesToInt(mc.triangles, mc.ntrigs());

        return(meshData);
    }
Exemplo n.º 16
0
    public MeshData GenerateMesh(bool createVoxels)
    {
        // so while SIZE is 16, which means theres 16 cells/blocks in grid
        // you need 17 values to be able to construct those blocks
        // (think of 17 points in a grid and the blocks are the 16 spaces in between)
        // if smoothing then need a buffer of 2 around (front and back so +4) for smoothing and normal calculation
        // (so mesh goes from 2-19 basically (0, 1, 20, 21) are not visible in final result)

#if (SMOOTH_SHADING)
        if (createVoxels)
        {
            voxels = WorldGenerator.CreateVoxels(SIZE + 5, depth, voxelSize, pos);
        }
        MeshData data = MarchingCubes.CalculateMeshData(voxels, voxelSize, 2, 2);
        data.CalculateVertexSharing();
        //Simplification simp = new Simplification(data.vertices, data.triangles);
        //data.normals = VoxelUtils.CalculateSmoothNormals(voxels, voxelSize, data.vertices);
        //data.SplitEdgesCalcSmoothness();
        data.CalculateSharedNormals();  // todo figure out why this doesnt make it smoothed...
#else
        if (createVoxels)
        {
            voxels = WorldGenerator.CreateVoxels(SIZE + 1, depth, voxelSize, worldPos);
        }

        //if (!needsMesh) {
        //    return null;
        //}

        //MeshData data = MarchingTetrahedra.CalculateMeshData(voxels, voxelSize);

        MeshData data = MarchingCubes.CalculateMeshData(voxels, voxelSize);
        data.CalculateNormals();
#endif

        //data.CalculateColorsByDepth(depth);
        return(data);
    }
Exemplo n.º 17
0
    IEnumerator Start()
    {
        marchCube = gameObject.GetComponent <MarchingCubes>();
        chunk     = new Chunk[Mathf.RoundToInt(chunkPositions.x * chunkPositions.y)];

        //Create the chunks
        int iterator = 0;

        for (int x = 0; x < chunkPositions.x; x++)
        {
            for (int y = 0; y < chunkPositions.y; y++)
            {
                //refreshHM = false;
                GameObject chunkInst = (GameObject)Instantiate(chunkObj, new Vector3((chunkSize.x - 1) * x, 0, (chunkSize.z - 1) * y), Quaternion.identity);
                chunkInst.transform.parent = this.transform;
                chunk[iterator]            = chunkInst.AddComponent <Chunk>();
                chunk[iterator].Assign(iterator, Mathf.RoundToInt((chunkSize.x) * x), Mathf.RoundToInt((chunkSize.z) * y));
                chunk[iterator].generateCaves = generateCaves;
                chunk[iterator].Initialize(heightMapFractals, caveFractal, chunkSize, new Vector2(x, y));
                marchCube.density = chunk[iterator].density;
                marchCube.Initialize(chunkSize);


                chunkInst.GetComponent <MeshFilter>().mesh         = marchCube.mesh;
                chunkInst.GetComponent <MeshCollider>().sharedMesh = marchCube.mesh;
                chunkInst.GetComponent <MeshFilter>().mesh.RecalculateBounds();
                chunkInst.GetComponent <MeshFilter>().mesh.RecalculateNormals();
                chunkInst.GetComponent <MeshRenderer>().material = mat;
                iterator++;
                yield return(1);
            }
        }

        //Used for mesh combining to minimize draw calls
        //gameObject.GetComponent<CombineChildren>().Combine();
        //An octree for future development
        //gameObject.GetComponent<Octree>().Initialize();
    }
Exemplo n.º 18
0
    //Method to generate given creature
    public void Generate(Creature c)
    {
        //Initialise variables
        balls.Clear();
        gridPoints.Clear();
        gridItterations = new Vector2();
        Vector3 difference = new Vector3();

        //Make meta balls
        MakeBalls(c);

        //Set max and min
        min = new Vector3(min.x - excess, min.y - excess, min.z - excess);
        max = new Vector3(max.x + excess, max.y + excess, max.z + excess);
        //Find difference of max and min
        difference = max - min;
        startGrid  = min;

        //Make grid
        GenerateGrid(difference);

        if (mesh == null)
        {
            //New mesh
            GetComponent <MeshFilter>().mesh = mesh = new Mesh();
            mesh.name = "creature bod";
        }
        else
        {
            GetComponent <MeshFilter>().mesh.Clear();
            mesh = GetComponent <MeshFilter>().mesh;
        }
        //Generate mesh
        MarchingCubes.GenerateMesh(gridPoints, gridItterations, ref mesh);
        //recalculate normals
        mesh.RecalculateNormals();
    }
Exemplo n.º 19
0
        protected override void OnContentRendered(EventArgs e)
        {
            // adjusts viewport grid size and step
            model1.GetGrid().Min  = new Point3D(-5, -5);
            model1.GetGrid().Max  = new Point3D(+5, +5);
            model1.GetGrid().Step = .5;

            // declare the function to be used to evaluate the 3D scalar field
            ScalarField3D func = new ScalarField3D(myScalarField);

            // initialize marching cube algorithm
            mc = new MarchingCubes(new Point3D(0, -2.5, 0), 50, .1f, 25, .1f, 25, .1f, func);

            mc.IsoLevel = trackBar1.Value;

            mc.DoWork();

            // iso surface generation
            Mesh isoSurf = mc.Result;

            // adds the surface to the entities collection with Magenta color
            model1.Entities.Add(isoSurf, System.Drawing.Color.Magenta);

            // updates the iso level label
            isoLevelLabel.Content = "Iso level = " + mc.IsoLevel;

            // sets trimetric view
            model1.SetView(viewType.Trimetric);

            // fits the model in the viewport
            model1.ZoomFit();

            // refresh the viewport
            model1.Invalidate();

            base.OnContentRendered(e);
        }
    public static void Generate(Thread thread, ChunkProcessor.Process process)
    {
        process.flag = ChunkProcessor.Flag.Processing;

        Marching mcubes = new MarchingCubes();

        mcubes.Surface = 0;

        float[] voxels = new float[(int)(Chunk.RESOLUTION * Chunk.RESOLUTION * Chunk.RESOLUTION)];

        GeometricalSchemaTemplate temp = new GeometricalSchemaTemplate();

        temp.Init();

        for (int x = 0; x < Chunk.RESOLUTION; x++)
        {
            for (int y = 0; y < Chunk.RESOLUTION; y++)
            {
                for (int z = 0; z < Chunk.RESOLUTION; z++)
                {
                    temp.Feed(x, y, z, process.chunk.data.position.x, process.chunk.data.position.y, process.chunk.data.position.z);
                    voxels[x + y * Chunk.RESOLUTION + z * Chunk.RESOLUTION * Chunk.RESOLUTION] = temp.Voxel();
                }
            }
        }
        List <Vector3> verts   = new List <Vector3>();
        List <int>     indices = new List <int>();

        mcubes.Generate(voxels, Chunk.RESOLUTION, Chunk.RESOLUTION, Chunk.RESOLUTION, verts, indices);

        process.chunk.data.vertices  = verts.ToArray();
        process.chunk.data.triangles = indices.ToArray();

        process.flag    = ChunkProcessor.Flag.Ready;
        process.success = true;
        thread.Abort();
    }
Exemplo n.º 21
0
    public void UpdateMesh()
    {
        if (!generator)
        {
            return;
        }

        if (generator.EnableJob)
        {
            MarchingCubes.GenerateMarchingCubesWithJob(voxels, generator.CellSize, generator.ChunkScale, generator.EnableTriangleIndexing, vertices, triangles, colors);
        }
        else
        {
            MarchingCubes.GenerateMarchingCubes(voxels, generator.CellSize, generator.ChunkScale, generator.EnableTriangleIndexing, vertices, triangles, colors);
        }
        mesh.Clear();
        mesh.SetVertices(vertices);
        mesh.SetTriangles(triangles, 0);
        mesh.SetColors(colors);
        mesh.RecalculateNormals();

        meshCollider.sharedMesh = mesh;
        dirty = false;
    }
Exemplo n.º 22
0
    private Group TestEdgeToVector(float[,,] cell)
    {
        LinkedList <bool> batch         = new LinkedList <bool>();
        MarchingCubes     marchingCubes = new MarchingCubes();

        marchingCubes.SetVolume(cell);

        MarchingCubes.Positon pos = new MarchingCubes.Positon();

        pos.x = 1;
        pos.y = 0;
        pos.z = 0;

        float expected = Mathf.Lerp(1f, 2f, Mathf.Abs(1.1f) / Mathf.Abs(-1f - 1.1f));

        expected = Mathf.Round(expected * 100000) / 100000;

        float actual = marchingCubes.EdgeToVector(3, pos)[0];

        actual = Mathf.Round(actual * 100000) / 100000;

        Assert <float>("Edge To Vector Test & LerpVectors 1", ref batch, expected, actual);
        return(new Group("EdgeToVector", batch));
    }
Exemplo n.º 23
0
        public static void test_marching_cubes()
        {
            MarchingCubes c = new MarchingCubes();

            LocalProfiler profiler = new LocalProfiler();

            profiler.Start("Generate");

            c.ParallelCompute = true;
            c.Generate();

            profiler.Stop("Generate");

            System.Console.WriteLine("Tris: {0} Times: {1}", c.Mesh.TriangleCount, profiler.AllTimes());

            Reducer r = new Reducer(c.Mesh);

            r.ReduceToEdgeLength(c.CubeSize * 0.25);

            System.Console.WriteLine("after reduce: {0}", c.Mesh.TriangleCount);

            MeshNormals.QuickCompute(c.Mesh);
            TestUtil.WriteTestOutputMesh(c.Mesh, "marching_cubes.obj");
        }
Exemplo n.º 24
0
        private void TestMC()
        {
            eyeshot.GetGrid().Visible = true;

            eyeshot.GetGrid().Min = new Point3D(-5, -5);

            eyeshot.GetGrid().Max = new Point3D(+5, +5);

            eyeshot.GetGrid().Step = .5;

            ScalarField3D func = new ScalarField3D(ScalarFieldFunc);

            double resolution = 0.5;

            int span = 100;

            MarchingCubes mc = new MarchingCubes(new Point3D(-5, -5, -5), span, resolution, span, resolution, span, resolution, func);

            mc.IsoLevel = 4;

            eyeshot.DoWork(mc);

            Mesh res = mc.Result;

            res.FlipNormal();

            Mesh sphere = Mesh.CreateSphere(Math.Sqrt(mc.IsoLevel), 16, 32);

            // eyeshot.Entities.Add(sphere, 0, Color.FromArgb(170, Color.Blue));

            eyeshot.Entities.Add(res, 0, Color.FromArgb(170, Color.Red));

            eyeshot.Invalidate();

            eyeshot.ZoomFit();
        }
Exemplo n.º 25
0
        private void Generate()
        {
            var seed   = System.DateTime.Now.Millisecond;
            var perlin = new GeneratorValue(seed, 1, 0.5f, 0.025f, 2, 4);

            float[] density = new float[width * height * depth];

            for (int k = 0; k < depth; k++)
            {
                for (int j = 0; j < height; j++)
                {
                    for (int i = 0; i < width; i++)
                    {
                        density[i + j * width + k * width * height] = perlin.GetNoise3D(new Vector3(i, j, k));
                    }
                }
            }

            var cubeMarcher = new MarchingCubes(0.1f);

            var verts    = new List <Vector3>();
            var indicies = new List <int>();

            cubeMarcher.GenerateMesh(density, width, height, depth, verts, indicies);
            Debug.Log(verts.Count);
            Debug.Log(indicies.Count);

            var mesh = new Mesh();

            mesh.SetVertices(verts);
            mesh.SetIndices(indicies.ToArray(), MeshTopology.Triangles, 0);
            mesh.RecalculateBounds();
            mesh.RecalculateNormals();

            meshFilter.mesh = mesh;
        }
    Mesh MeshDensityArray()
    {
        Marching marching = new MarchingCubes();

        marching.Surface = 0.0f;

        int sl     = chunkSettings.ChunkSL + 1;
        int width  = sl;
        int height = sl;
        int length = sl;



        List <Vector3> verts   = new List <Vector3>();
        List <int>     indices = new List <int>();

        //The mesh produced is not optimal. There is one vert for each index.
        //Would need to weld vertices for better quality mesh.
        marching.Generate(renderBuffer, width, height, length, verts, indices);
        List <Color32> colors = new List <Color32>();

        foreach (Vector3 vertex in verts)
        {
            colors.Add(Random.ColorHSV());
        }

        Mesh mesh = new Mesh();

        mesh.vertices  = verts.ToArray();
        mesh.triangles = indices.ToArray();
        mesh.colors32  = colors.ToArray();
        mesh.RecalculateNormals();


        return(mesh);
    }
Exemplo n.º 27
0
	void CreateSmoothTerrain(MyMesh TerrainMesh, MarchingCubes marchingCubes, Blocks MyBlocks) {
		Debug.Log ("Creating Smooth Terrain");
		Vector3 BlockScale = MyBlocks.Scale;
		// Marching cubes is one too small!
		// for some reason the size has to be like this
		Vector3 WorldSize_ = MyBlocks.Size;
		int expand = 0;// WorldCore->MarchingExpand;
		WorldSize_.x += expand;
		WorldSize_.y += expand;
		WorldSize_.z += expand;
		// = 18 now out of 16 0 to 15
		// I need to perform this calculation PER CUBE and not per grid
		// So perform calculation depending on surrounding cubes, but not whole thing
		//MarchingCubesData.Clear();
		//for (int i = 0; i < (WorldSize_.x)*(WorldSize_.y)*(WorldSize_.z); i++)
		//	MarchingCubesData.Add(0.0f);
		//marchingCubes.ClearData(MarchingCubesData);
		marchingCubes = new MarchingCubes(new Vector3(WorldSize_.x, WorldSize_.x, WorldSize_.x), Mathf.RoundToInt(WorldSize_.x));
		marchingCubes.PolygonizeData(MyBlocks, WorldSize_);
		
		TerrainMesh.ClearMesh ();
		for (int i = 0; i < marchingCubes.trilist.Count; i++) {	// for every triangle in list
			marchingCubes.trilist[i].calcnormal(true);
			
			TerrainMesh.Verticies.Add (marchingCubes.trilist[i].position[0]);
			TerrainMesh.Verticies.Add (marchingCubes.trilist[i].position[1]);
			TerrainMesh.Verticies.Add (marchingCubes.trilist[i].position[2]);
			
			TerrainMesh.Colors.Add (marchingCubes.trilist[i].colors[0]);
			TerrainMesh.Colors.Add (marchingCubes.trilist[i].colors[1]);
			TerrainMesh.Colors.Add (marchingCubes.trilist[i].colors[2]);
			
			TerrainMesh.Indicies.Add (TerrainMesh.Verticies.Count-3);
			TerrainMesh.Indicies.Add (TerrainMesh.Verticies.Count-2);
			TerrainMesh.Indicies.Add (TerrainMesh.Verticies.Count-1);
		}
		Debug.Log ("Created Smooth Terrain");
	}
Exemplo n.º 28
0
        protected virtual void update_level_set()
        {
            double unsigned_offset = Math.Abs(offset_distance);

            if (cached_sdf == null ||
                unsigned_offset > cached_sdf_max_offset ||
                grid_cell_size != cached_sdf.CellSize)
            {
                DMesh3 meshIn      = MeshSource.GetDMeshUnsafe();
                int    exact_cells = (int)(unsigned_offset / grid_cell_size) + 1;

                // only use spatial DS if we are computing enough cells
                DMeshAABBTree3 use_spatial = GenerateClosedMeshOp.MeshSDFShouldUseSpatial(
                    input_spatial, exact_cells, grid_cell_size, input_mesh_edge_stats.z);
                MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(meshIn, grid_cell_size, use_spatial)
                {
                    ExactBandWidth = exact_cells
                };
                if (use_spatial != null)
                {
                    sdf.NarrowBandMaxDistance = unsigned_offset + grid_cell_size;
                    sdf.ComputeMode           = MeshSignedDistanceGrid.ComputeModes.NarrowBand_SpatialFloodFill;
                }

                sdf.CancelF = is_invalidated;
                sdf.Compute();
                if (is_invalidated())
                {
                    return;
                }
                cached_sdf            = sdf;
                cached_sdf_max_offset = unsigned_offset;
                cached_sdf_bounds     = meshIn.CachedBounds;
            }

            var           iso = new DenseGridTrilinearImplicit(cached_sdf.Grid, cached_sdf.GridOrigin, cached_sdf.CellSize);
            MarchingCubes c   = new MarchingCubes();

            c.Implicit = iso;
            c.IsoValue = offset_distance;
            c.Bounds   = cached_sdf_bounds;
            c.CubeSize = mesh_cell_size;
            c.Bounds.Expand(offset_distance + 3 * c.CubeSize);
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps;
            c.RootModeSteps = 5;

            c.CancelF = is_invalidated;
            c.Generate();
            if (is_invalidated())
            {
                return;
            }

            Reducer r = new Reducer(c.Mesh);

            r.FastCollapsePass(c.CubeSize * 0.5, 3, true);
            if (is_invalidated())
            {
                return;
            }

            if (min_component_volume > 0)
            {
                MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume);
            }
            if (is_invalidated())
            {
                return;
            }

            ResultMesh = c.Mesh;
        }
Exemplo n.º 29
0
        public void genMesh(VoxelUpdateInfo info)
        {
            if (control == null)
            {
                return;
            }

            size = info.size;

            Queue <int[]> triangleSet = new Queue <int[]>();

            vertices          = new Dictionary <int, object>();
            vertexSubstances  = new Dictionary <int, byte>();
            Voxel[, ,] voxels = createVoxelArray(info);
            MarchingCubes.setup(info.size / VOXEL_DIMENSION, control.isoLevel, ref vertices, ref vertexSubstances, ref voxels, position - new Vector3(0.5f, 0.5f, 0.5f) * size / VOXEL_DIMENSION, null);
            int totalTris = 0;

            for (byte x = (byte)(1 - xExtend), x1 = (byte)(x + 1); x1 < xDim; x = x1++)
            {
                for (byte y = (byte)(1 - yExtend), y1 = (byte)(y + 1); y1 < yDim; y = y1++)
                {
                    for (byte z = (byte)(1 - zExtend), z1 = (byte)(z + 1); z1 < zDim; z = z1++)
                    {
                        lock (control) {
                            VoxelHolder block = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION + x, VOXEL_DIMENSION + y, VOXEL_DIMENSION + z);
                            voxels[x1, y1, z1] = block.toVoxel();
                            int[] tris = MarchingCubes.lookupTriangles(x, y, z, x1, y1, z1);
                            if (tris == null)
                            {
                                continue;
                            }
                            triangleSet.Enqueue(tris);
                            totalTris += tris.Length;
                        }
                    }
                }
            }

            if (vertices.Count < 1)
            {
                applied = true;
                return;
            }


            List <int>     triangles     = new List <int>();
            List <Vector3> finalVertices = new List <Vector3>(vertices.Count);

            //List<byte> finalMats = new List<byte>(vertices.Count);
            while (triangleSet.Count > 0)
            {
                int[] triangleList = triangleSet.Dequeue();
                for (int i = 0; i < triangleList.Length; ++i)
                {
                    if (vertices[triangleList[i]].GetType() == typeof(Vector3))
                    {
                        finalVertices.Add((Vector3)vertices[triangleList[i]]);
                        //finalMats.Add(vertexSubstances[triangleList[i]]);
                        vertices[triangleList[i]] = finalVertices.Count - 1;
                    }
                    triangles.Add((int)vertices[triangleList[i]]);
                }
            }
            VERTS = finalVertices.ToArray();
            TRIS  = triangles.ToArray();
            //MATS = finalMats.ToArray();
            calcNorms();

            alignEdge(info, 0, 1, 1);
            alignEdge(info, 2, 1, 1);
            alignEdge(info, 1, 0, 1);
            alignEdge(info, 1, 2, 1);
            alignEdge(info, 1, 1, 0);
            alignEdge(info, 1, 1, 2);
            lock (control) {
                control.enqueueJob(new ApplyMeshJob(this, info.detailLevel, info.x, info.y, info.z));
            }
        }
Exemplo n.º 30
0
        /// <summary>
        /// Sample analytic winding number into grid in narrow-band around target isovalue,
        /// and then extract using marching cubes.
        ///
        /// TODO: don't need to discard current grid when isovalue changes, just need to
        ///   re-run the front propagation part of mwn.Compute()!
        ///   If this is done, then use this instead of update_winding_fast() for open meshes
        /// </summary>
        protected virtual void update_winding()
        {
            DMesh3 meshIn = MeshSource.GetDMeshUnsafe();

            if (spatialPro == null || spatial_timestamp != meshIn.ShapeTimestamp)
            {
                spatialPro = new DMeshAABBTreePro(meshIn, true);
                spatialPro.FastWindingNumber(Vector3d.Zero);
                spatial_timestamp = meshIn.ShapeTimestamp;
            }
            if (is_invalidated())
            {
                return;
            }

            if (cached_mwn_grid == null ||
                grid_cell_size != cached_mwn_grid.CellSize ||
                (float)winding_iso != cached_mwn_grid.IsoValue)
            {
                Func <Vector3d, double> fastWN = (q) => { return(spatialPro.FastWindingNumber(q)); };
                var mwn = new MeshScalarSamplingGrid(meshIn, grid_cell_size, fastWN)
                {
                    IsoValue = (float)winding_iso
                };
                mwn.CancelF = is_invalidated;
                mwn.Compute();
                if (is_invalidated())
                {
                    return;
                }
                cached_mwn_grid   = mwn;
                cached_mwn_bounds = meshIn.CachedBounds;
            }

            MarchingCubes c = new MarchingCubes();

            c.Implicit = new SampledGridImplicit(cached_mwn_grid);
            c.IsoValue = 0.0;
            c.Bounds   = cached_mwn_bounds;
            c.CubeSize = mesh_cell_size;
            c.Bounds.Expand(3 * c.CubeSize);
            c.RootMode      = MarchingCubes.RootfindingModes.Bisection;
            c.RootModeSteps = 10;

            c.CancelF = is_invalidated;
            c.Generate();
            if (is_invalidated())
            {
                return;
            }

            Reducer r = new Reducer(c.Mesh);

            r.FastCollapsePass(c.CubeSize * 0.5, 3, true);
            if (is_invalidated())
            {
                return;
            }

            if (min_component_volume > 0)
            {
                MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume);
            }
            if (is_invalidated())
            {
                return;
            }

            // reproject - if we want to do this, we need to create spatial and meshIn above!
            gParallel.ForEach(c.Mesh.VertexIndices(), (vid) => {
                if (is_invalidated())
                {
                    return;
                }
                Vector3d v = c.Mesh.GetVertex(vid);
                int tid    = spatialPro.FindNearestTriangle(v, grid_cell_size * MathUtil.SqrtTwo);
                if (tid != DMesh3.InvalidID)
                {
                    var query = MeshQueries.TriangleDistance(meshIn, tid, v);
                    if (v.Distance(query.TriangleClosest) < grid_cell_size)
                    {
                        c.Mesh.SetVertex(vid, query.TriangleClosest);
                    }
                }
            });

            if (is_invalidated())
            {
                return;
            }

            ResultMesh = c.Mesh;
        }
Exemplo n.º 31
0
        public void addEdge(VoxelUpdateInfo info, byte x, byte y, byte z)
        {
            if (vertices == null)
            {
                return;
            }
            bool recalculate = false;

            Voxel[, ,] voxels = new Voxel[VERTEX_DIMENSION, VERTEX_DIMENSION, VERTEX_DIMENSION];
            if (x == 0 /* && xExtend == 0*/)
            {
                recalculate = true;
                xExtend     = 1;
                for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi)
                {
                    for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi)
                    {
                        voxels[0, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - xExtend, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel();
                        voxels[1, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel();
                    }
                }
            }
            else if (x == 2 /* && xDim < VERTEX_DIMENSION*/)
            {
                recalculate = true;
                xDim        = VERTEX_DIMENSION;
                for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi)
                {
                    for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi)
                    {
                        voxels[VOXEL_DIMENSION + 1, yi, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION * 2, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel();
                        voxels[VOXEL_DIMENSION, yi, zi]     = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION * 2 - 1, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - 1 + zi).toVoxel();
                    }
                }
            }
            else if (y == 0 /* && yExtend == 0*/)
            {
                recalculate = true;
                yExtend     = 1;
                for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi)
                {
                    for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi)
                    {
                        voxels[xi, 0, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - yExtend, VOXEL_DIMENSION - 1 + zi).toVoxel();
                        voxels[xi, 1, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION, VOXEL_DIMENSION - 1 + zi).toVoxel();
                    }
                }
            }
            else if (y == 2 /* && yDim < VERTEX_DIMENSION*/)
            {
                recalculate = true;
                yDim        = VERTEX_DIMENSION;
                for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi)
                {
                    for (byte zi = (byte)(1 - zExtend); zi < zDim; ++zi)
                    {
                        voxels[xi, VOXEL_DIMENSION + 1, zi] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION * 2, VOXEL_DIMENSION - 1 + zi).toVoxel();
                        voxels[xi, VOXEL_DIMENSION, zi]     = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION * 2 - 1, VOXEL_DIMENSION - 1 + zi).toVoxel();
                    }
                }
            }
            else if (z == 0 /* && zExtend == 0*/)
            {
                recalculate = true;
                zExtend     = 1;
                for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi)
                {
                    for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi)
                    {
                        voxels[xi, yi, 0] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION - zExtend).toVoxel();
                        voxels[xi, yi, 1] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION).toVoxel();
                    }
                }
            }
            else if (z == 2 /* && zDim < VERTEX_DIMENSION*/)
            {
                recalculate = true;
                zDim        = VERTEX_DIMENSION;
                for (byte xi = (byte)(1 - xExtend); xi < xDim; ++xi)
                {
                    for (byte yi = (byte)(1 - yExtend); yi < yDim; ++yi)
                    {
                        voxels[xi, yi, VOXEL_DIMENSION + 1] = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION * 2).toVoxel();
                        voxels[xi, yi, VOXEL_DIMENSION]     = info.getSub(VOXEL_COUNT_POWER, VOXEL_DIMENSION - 1 + xi, VOXEL_DIMENSION - 1 + yi, VOXEL_DIMENSION * 2 - 1).toVoxel();
                    }
                }
            }

            if (recalculate)
            {
                Queue <int[]> triangleSet = new Queue <int[]>();
                MarchingCubes.setup(info.size / VOXEL_DIMENSION, control.isoLevel, ref vertices, ref vertexSubstances, ref voxels, position - new Vector3(0.5f, 0.5f, 0.5f) * size / VOXEL_DIMENSION, VERTS);

                byte xStart = (byte)(1 - xExtend + (VOXEL_DIMENSION + xExtend - 1) * (x / 2));
                byte xEnd   = (byte)(2 + (xDim - 2) * ((x + 1) / 2));
                byte yStart = (byte)(1 - yExtend + (VOXEL_DIMENSION + yExtend - 1) * (y / 2));
                byte yEnd   = (byte)(2 + (yDim - 2) * ((y + 1) / 2));
                byte zStart = (byte)(1 - zExtend + (VOXEL_DIMENSION + zExtend - 1) * (z / 2));
                byte zEnd   = (byte)(2 + (zDim - 2) * ((z + 1) / 2));

                for (byte xi = xStart, x1 = (byte)(xi + 1); x1 < xEnd; xi = x1++)
                {
                    for (byte yi = yStart, y1 = (byte)(yi + 1); y1 < yEnd; yi = y1++)
                    {
                        for (byte zi = zStart, z1 = (byte)(zi + 1); z1 < zEnd; zi = z1++)
                        {
                            int[] tris = MarchingCubes.lookupTriangles(xi, yi, zi, x1, y1, z1);
                            if (tris == null)
                            {
                                continue;
                            }
                            triangleSet.Enqueue(tris);
                        }
                    }
                }

                if (vertices.Count < 1)
                {
                    return;
                }


                List <int>     newTriangles = new List <int>(TRIS);
                List <Vector3> newVertices  = new List <Vector3>(VERTS);
                int            tri          = 0;
                while (triangleSet.Count > 0)
                {
                    int[] triangleList = triangleSet.Dequeue();
                    for (int i = 0; i < triangleList.Length; ++i)
                    {
                        if (vertices[triangleList[i]].GetType() == typeof(Vector3))
                        {
                            newVertices.Add((Vector3)vertices[triangleList[i]]);
                            vertices[triangleList[i]] = newVertices.Count - 1;
                        }
                        newTriangles.Add((int)vertices[triangleList[i]]);
                    }
                    tri += triangleList.Length;
                }

                Vector3[] finalNorms = new Vector3[newVertices.Count];
                Array.Copy(NORMS, finalNorms, NORMS.Length);
                int oldNormCount = NORMS.Length;

                VERTS = newVertices.ToArray();
                TRIS  = newTriangles.ToArray();
                calcNorms();
                Array.Copy(NORMS, oldNormCount, finalNorms, oldNormCount, finalNorms.Length - oldNormCount);
                NORMS = finalNorms;
            }

            alignEdge(info, x, y, z);
            control.enqueueJob(new ApplyMeshJob(this, info.detailLevel, info.x, info.y, info.z));
        }