//function to create the voxel noises and caves etc.
        public static byte[, , ]CreateVoxels(byte[,,] m_voxels,Vector3 m_pos,VoxelChunk chunk,NoiseModule noiseModule)
        {
            //float startTime = Time.realtimeSinceStartup;

            //Creates the data the mesh is created form. Fills m_voxels with values between -1 and 1 where
            //-1 is a soild voxel and 1 is a empty voxel.

            int w = m_voxels.GetLength(0);
            int h= m_voxels.GetLength(1);
            int l = m_voxels.GetLength(2);
            float worldX;
            float worldZ;
            float worldY;
            float ht;
            for(int x = 0; x < w; x++)
            {
            for(int z = 0; z < l; z++)
            {

            //world pos is the voxels position plus the voxel chunks position
            worldX = x+m_pos.x;
            worldZ = z+m_pos.z;
            ht = generator.noise.FillVoxel2d(worldX,worldZ,m_pos,SurfacePerlin,CavePerlin);

            for(int y = 0; y < h; y++)
                {
            worldY = y+m_pos.y;
            float HT=ht+worldY-h/2;

            if(MakeCaves&&y<h/2-50)
            HT -= generator.noise.FillVoxel3d(worldX,worldY,worldZ,m_pos);

            HT/=16;
            HT = Mathf.Clamp(HT , -0.5f, 0.5f);

            HT+=0.5f;
            HT*=255;

            m_voxels[x,y,z]=(byte)HT;

            m_voxels[x,y,z]=(byte)Mathf.Clamp(m_voxels[x,y,z],0,255);

            if(y>=h-5&&m_voxels[x,y,z]<=127)m_voxels[x,y,z]=255;
            if(y<=5&&m_voxels[x,y,z]>=127)m_voxels[x,y,z]=0;

                    }
            }
            }

            return m_voxels;
        }
示例#2
0
 public static Vector3[] Createvertices(byte[,,] m_voxels, VoxelChunk chunk, int lod)
 {
     Vector3[] vertices = MarchingCubes.CreateVertices(m_voxels, chunk, 2, 2, lod);
     return(vertices);
 }
 public static Vector3[] CreateverticesVoxels(byte[,,] m_voxels,VoxelChunk chunk)
 {
     Vector3[] vertices = MarchingCubesVoxels.CreateVertices(m_voxels,chunk,2,2);
     return vertices;
 }
示例#4
0
        /// <summary>
        /// Creates the vertices with new voxel data
        /// </summary>
        /// <returns>The vertices.</returns>
        /// <param name="voxels">Voxels.</param>
        /// <param name="start">Start.</param>
        /// <param name="end">End.</param>
        public static Vector3[] CreateVertices(byte[,,] voxels, VoxelChunk chunk, int start, int end, int lod)
        {
            List <int>     index = new List <int>();
            List <Vector3> verts = new List <Vector3>();

            Vector3[] edgeVertex = new Vector3[12];
            byte[]    cube       = new byte[8];
            for (int z = start; z < voxels.GetLength(2) - 1 - end; z++)
            {
                for (int y = start; y < voxels.GetLength(1) - 1 - end; y++)
                {
                    for (int x = start; x < voxels.GetLength(0) - 1 - end; x++)
                    {
                        int i, j, vert, idx;
                        //Get the values in the 8 neighbours which make up a cube
                        for (i = 0; i < 8; i++)
                        {
                            cube[i] = voxels[x + vertexOffset[i, 0], y + vertexOffset[i, 1],
                                             z + vertexOffset[i, 2]];
                        }
                        //Perform algorithm
                        int   flagIndex = 0;
                        float offset    = 0.0f;

                        //Find which vertices are inside of the surface and which are outside
                        for (i = 0; i < 8; i++)
                        {
                            if (cube[i] >= target)
                            {
                                flagIndex |= 1 << i;
                            }
                        }
                        //Find which edges are intersected by the surface
                        int edgeFlags = cubeEdgeFlags[flagIndex];

                        //If the cube is entirely inside or outside of the surface,
                        //then there will be no intersections
                        if (edgeFlags != 0)
                        {
                            //Find the point of intersection of the surface with each edge
                            for (i = 0; i < 12; i++)
                            {
                                //if there is an intersection on this edge
                                if ((edgeFlags & (1 << i)) != 0)
                                {
                                    offset = GetOffset(cube[edgeConnection[i, 0]], cube[edgeConnection[i, 1]]);


                                    edgeVertex[i].z = z + (vertexOffset[edgeConnection[i, 0], 2]
                                                           + offset * edgeDirection[i, 2]);

                                    edgeVertex[i].y = y + (vertexOffset[edgeConnection[i, 0], 1]
                                                           + offset * edgeDirection[i, 1]);

                                    edgeVertex[i].x = x + (vertexOffset[edgeConnection[i, 0], 0]
                                                           + offset * edgeDirection[i, 0]);
                                }
                            }

                            //Save the triangles that were found. There can be up to five per cube
                            for (i = 0; i < 5; i++)
                            {
                                if (triangleConnectionTable[flagIndex, 3 * i] < 0)
                                {
                                    break;
                                }

                                idx = verts.Count;

                                for (j = 0; j < 3; j++)
                                {
                                    vert = triangleConnectionTable[flagIndex, 3 * i + j];
                                    index.Add(idx + windingOrder[j]);
                                    verts.Add(edgeVertex[vert] * VoxelTerrainEngine.TriSize[lod]);
                                }
                            }
                        }
                    }
                    //MarchCube(new Vector3(x,y,z), cube, verts, index);
                }
            }


            if (verts.Count > 65000)
            {
                //If you get this error its means that the voxels array contaions to much information and
                //a mesh larger than 65000 verts is need to represent it. You can fix this by using a smaller arrays of voxel,
                //make less 'noisey' data, or manually split up the mesh into sub meshes.
                Debug.Log("MarchingCubes::CreateMesh - " +
                          "Number of mesh verts greater than 65000. Can not create mesh");
                return(null);
            }



            chunk.tris = index.ToArray();
            return(verts.ToArray());
        }
示例#5
0
        public void Update()
        {
            int maxLoadChunks = 5;
            int maxMeshChunks = 1;

            int loadedChunks = 0;
            while (chunkLoadQueue.Count > 0 && loadedChunks < maxLoadChunks)
            {
                // load chunk
                var coords = chunkLoadQueue.Dequeue();
                var chunk = new VoxelChunk(coords.Item1, coords.Item2, ChunkWidth, ChunkHeight, ChunkDepth);

                // generate terrain
                for (int x = 0; x < ChunkWidth; x++)
                {
                    for (int z = 0; z < ChunkDepth; z++)
                    {
                        int h = (int)(ChunkHeight * (0.5 + 0.5 * noise.Evaluate((coords.Item1 * ChunkWidth + x) * 0.009, (coords.Item2 * ChunkDepth + z) * 0.009)));

                        for (int y = 0; y < h; y++)
                        {
                            chunk[x, y, z] = Extensions.ColorFromHSV(110, 0.94, (h / (double)ChunkHeight)*0.4+0.55).ToShortColor(); // (ushort)(ChunkCount + 1);
                        }
                    }
                }

                chunksToMesh.Add(coords, chunk);
            }

            List<Tuple<int, int>> meshedChunks = new List<Tuple<int, int>>();
            int chunksMeshed = 0;
            foreach (var kvp in chunksToMesh)
            {
                var coords = kvp.Key;
                int x = coords.Item1;
                int z = coords.Item2;

                if (ChunkMeshedOrLoaded(x - 1, z) && ChunkMeshedOrLoaded(x + 1, z) && ChunkMeshedOrLoaded(x, z - 1) && ChunkMeshedOrLoaded(x, z + 1))
                {
                    var chunk = kvp.Value;
                    chunk.BuildMesh();
                    meshedChunks.Add(coords);
                    chunksMeshed++;
                    if (chunksMeshed >= maxMeshChunks)
                        break;
                }
            }

            foreach (var coords in meshedChunks)
            {
                var chunk = chunksToMesh[coords];
                chunksToMesh.Remove(coords);
                chunks.Add(coords, chunk);
            }
            //Console.WriteLine("loaded chunks: {0}  meshed chunks: {1}", loadedChunks, chunksMeshed);
        }
示例#6
0
//main method for calling chunk creation some optimizations could be done here
        void GenerateTerrains()
        {
            while (CanContinue)
            {
                try
                {
                    //Vector2 Refpos =new Vector2(playerGlobal.x,playerGlobal.z);
                    //basic routine for creating chunks
                    for (int i = 0; i < distanceToload * m_voxelWidth; i += m_voxelWidth)
                    {
                        //set player positon relative to chunks basically rounding to chunk size
                        PosX = Mathf.RoundToInt(PlayerGlobal.x / m_voxelWidth) * m_voxelWidth;

                        PosY = Mathf.RoundToInt(PlayerGlobal.y / m_voxelHeight) * m_voxelHeight;

                        PosZ = Mathf.RoundToInt(PlayerGlobal.z / m_voxelWidth) * m_voxelWidth;

                        for (int x = (int)PosX - i; x < (int)PosX + i; x += m_voxelWidth)
                        {
                            if (CanContinue)
                            {
                                for (int z = (int)PosZ - i; z < (int)PosZ + i; z += m_voxelWidth)
                                {
                                    if (CanContinue)
                                    {
                                        //this is for the voxel editing at runtime
                                        //if theres any new chunks that need to be updated they are added here
                                        if (NewVoxelChunk.Count > 0)
                                        {
                                            for (int N = 0; N < NewVoxelChunk.Count; N++)
                                            {
                                                if (CanContinue)
                                                {
                                                    int C = NewVoxelChunk.Count - 1;
                                                    //Create the voxel data

                                                    if (C < NewVoxelChunk.Count && NewVoxelChunk[C] != null)
                                                    {
                                                        //set various flags so the engine knows it needs to create a new mesh for terrain

                                                        NewVoxelChunk[C].hascollider = false;

                                                        NewVoxelChunk[C].HasVoxel = false;

                                                        NewVoxelChunk[C].CreateMeshesWithVoxels();

                                                        NewVoxelChunk.Remove(NewVoxelChunk[C]);
                                                    }
                                                }
                                            }
                                        }

                                        //if the terrain has been edited calling saveTerrains() method
                                        //will save the voxel data to a file
                                        //here i just set the flag of this script to cansave =true; and it saves automatically
                                        if (cansave)
                                        {
                                            SaveTerrains();

                                            cansave = false;
                                        }

                                        //set up variables for distance checking

                                        Vector2 chunkpos = new Vector2((x), (z));

                                        Vector2 playerpos = new Vector2(Player.x, Player.z);

                                        //distance checking
                                        Dist = Vector2.Distance(playerpos, chunkpos);

                                        if (Dist < distanceToload)
                                        {
                                            //check if the chunk already exists if not create a chunk with x *y * z of voxels

                                            if (!m_voxelChunk.ContainsKey(x, z))
                                            {
                                                Pos = new Vector3(chunkpos.x, 0, chunkpos.y);

                                                //set variables for chunk creation
                                                Chunk = new VoxelChunk(Pos, m_voxelWidth, m_voxelHeight, m_voxelLength, m_surfaceLevel);

                                                //add chunk to double key dictionary
                                                m_voxelChunk.Add(x, z, Chunk);

                                                //set flag on chunk
                                                m_voxelChunk[x, z].hasproccessed = true;

                                                //add chunk to list of chunks that need noise added to them
                                                RequestedChunks.Add(m_voxelChunk[x, z]);
                                            }
                                        }
                                        //if the chunk already exists and its distance is greater then render distance
                                        //+ 50 then call destroy on the chunk
                                        else if (m_voxelChunk.ContainsKey(x, z) && Dist > distanceToload + 64)
                                        {
                                            Destroy(x, z);
                                        }
                                    }
                                }
                            }
                        }
                    }



                    //catch exceptions
                }catch (Exception e)
                { Debug.LogError(e.StackTrace); }
            }
        }
示例#7
0
        void CreateChunks()
        {
            try
            {
                //basic routine for creating chunks
                for (int i = 0; i < distanceToLoad * m_voxelWidthLength; i += m_voxelWidthLength)
                {
                    //set player positon relative to chunks basically rounding to chunk size

                    for (int x = 0; x < i; x += m_voxelWidthLength)
                    {
                        if (CanGenerate)
                        {
                            for (int z = 0; z < i; z += m_voxelWidthLength)
                            {
                                if (CanGenerate)
                                {
                                    //this is for the voxel editing at runtime
                                    //if theres any new chunks that need to be updated they are added here


                                    /*if the terrain has been edited calling saveTerrains() method
                                     * will save the voxel data to a file
                                     * here i just set the flag of this script to cansave =true; and it saves automatically*/
                                    if (Save)
                                    {
                                        SaveTerrains();

                                        Save = false;
                                    }
                                    //set up variables for distance checking
                                    Vector2 chunkpos = new Vector2(x, z);

                                    Vector2 playerpos = Vector2.zero;
                                    float   Dist      = Vector2.Distance(playerpos, chunkpos);

                                    //check if the chunk already exists if not create a chunk with x *y * z of voxels
                                    if (!m_voxelChunk.ContainsKey(new Vector3(x, 0, z), new Vector3(m_voxelWidthLength, m_voxelHeight, m_voxelWidthLength) * minLod))
                                    {
                                        if (Dist <= distanceToLoad)
                                        {
                                            Vector3 Pos = new Vector3(x, 0, z);

                                            //set variables for chunk creation
                                            VoxelChunk Chunk = new VoxelChunk(Pos, m_voxelWidthLength, m_voxelHeight, minLod);



                                            //add chunk to double key dictionary
                                            m_voxelChunk.Add(Pos, new Vector3(m_voxelWidthLength, m_voxelHeight, m_voxelWidthLength) * minLod, Chunk);

                                            //set flag on chunk
                                            Chunk.hasproccessed = true;

                                            //add chunk to list of chunks that need noise added to them
                                            GenerateVoxels.Enqueue(Chunk);
                                            return;
                                        }
                                    }

                                    //if the chunk already exists and its distance is greater then render distance
                                }
                            }
                        }
                    }
                }
            }catch (Exception e)
            { Debug.LogError(e.StackTrace); }
        }
示例#8
0
        public void UpdateTerrain()
        {
            if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode && playMode == EditorPlay.isEditor)
            {
                Transform[] gamos = GetComponentsInChildren <Transform>();
                CanGenerate = false;
                EndAllThreads();
                for (int i = 0; i < gamos.Length; i++)
                {
                    if (gamos[i] != transform)
                    {
                        DestroyImmediate(gamos[i].gameObject);
                    }
                }
                SaveTerrains();
                playMode = EditorPlay.isPlaying;
            }
            if (playMode == EditorPlay.isEditor)
            {
                if (UnityEditor.EditorApplication.isCompiling == false && CanGenerate == false)
                {
                    Transform[] gamos = GetComponentsInChildren <Transform>();
                    for (int i = 0; i < gamos.Length; i++)
                    {
                        if (gamos[i] != transform)
                        {
                            DestroyImmediate(gamos[i].gameObject);
                        }
                    }
                    SaveTerrains();
                    Initialize();
                }
                else if (UnityEditor.EditorApplication.isCompiling && CanGenerate == true)
                {
                    CanGenerate = false;
                    Transform[] gamos = GetComponentsInChildren <Transform>();
                    for (int i = 0; i < gamos.Length; i++)
                    {
                        if (gamos[i] != transform)
                        {
                            DestroyImmediate(gamos[i].gameObject);
                            for (int t = 0; t < thread.Length; t++)
                            {
                                if (thread[t] != null)
                                {
                                    thread[t].Abort();
                                }
                            }

                            CanGenerate = false;
                        }
                    }
                    SaveTerrains();
                }
            }

            if (Camera.current != null && UnityEditor.Selection.Contains(gameObject))
            {
                if (timer <= 0.25f)
                {
                    timer += 0.03f;
                }
                Ray myray;
                if (playMode == EditorPlay.isEditor)
                {
                    myray = UnityEditor.HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
                    RaycastHit hit;

                    if (Physics.Raycast(myray, out hit, Mathf.Infinity))
                    {
                        Shader.SetGlobalVector("_highlightArea", hit.point);
                        Event E = Event.current;
                        if (E.button == 1 && E.control && timer >= 0.25f)
                        {
                            SetVoxels(hit.point, value, effectArea);
                            timer = 0;
                        }
                        if (E.button == 1 && E.alt && timer >= 0.25f)
                        {
                            setMaterial(hit.point, VoxelMaterial, effectArea);
                            timer = 0;
                        }

                        Shader.SetGlobalFloat("_highlightSize", effectArea);
                    }
                }
            }
            else
            {
                Shader.SetGlobalFloat("_highlightSize", 0);
            }



            //set the wind variables on the shader comment this out if you dont use my grass shader
            if (Zone != null)
            {
                Shader.SetGlobalFloat("WindAmount", Zone.windMain);
                Shader.SetGlobalFloat("WaveSize", Zone.windPulseMagnitude);
                Shader.SetGlobalFloat("windSpeed", Zone.windPulseFrequency);
                Shader.SetGlobalFloat("SqrDistance", Zone.windTurbulence);
                Shader.SetGlobalFloat("WindDirectionx", Zone.transform.forward.x);
                Shader.SetGlobalFloat("WindDirectiony", Zone.transform.forward.y);
                Shader.SetGlobalFloat("WindDirectionz", Zone.transform.forward.z);
            }

            //if we have meshes to destroy destroy them
            //need to implement a pooling system will save on memory
            //as well as stop the garbage collector from being called
            if (Trash.Count > 0)
            {
                VoxelChunk myChunk = Trash.Dequeue();
                if (myChunk.mesh != null)
                {
                    DestroyImmediate(myChunk.mesh);
                }
                myChunk.mesh = null;
                DestroyImmediate(myChunk.m_mesh);
                myChunk.canDraw       = false;
                myChunk.canCreatemesh = false;
            }
            //create the mesh . this is done in update as calling it from another thread is not allowed
            if (MeshChunks.Count > 0)
            {
                VoxelChunk chunk = MeshChunks.Dequeue();
                chunk.CreateMesh();
                chunk.canCreatemesh = false;
                if (ActiveChunks.Contains(chunk) == false)
                {
                    ActiveChunks.Add(chunk);
                }
            }
            if (ActiveChunks.Count > 0)
            {
                for (int i = 0; i < ActiveChunks.Count; i++)
                {
                    ActiveChunks[i].RenderGrass();
                }
            }
            //need to some how check for occlusion and not render things behind other objects
        }
        //main method for calling chunk creation some optimizations could be done here
        void GenerateTerrains()
        {
            while (CanContinue)
            {
            try
            {

            //Vector2 Refpos =new Vector2(playerGlobal.x,playerGlobal.z);
            //basic routine for creating chunks
            for(int i =0;i<distanceToload*m_voxelWidth;i+=m_voxelWidth){

            //set player positon relative to chunks basically rounding to chunk size
            PosX = Mathf.RoundToInt( PlayerGlobal.x/m_voxelWidth)*m_voxelWidth;

            PosY = Mathf.RoundToInt(PlayerGlobal.y/m_voxelHeight)*m_voxelHeight;

            PosZ = Mathf.RoundToInt( PlayerGlobal.z/m_voxelWidth)*m_voxelWidth;

            for(int x=(int)PosX -i;x <(int)PosX +i ;x+=m_voxelWidth){if(CanContinue){

            for(int z=(int)PosZ -i;z <(int)PosZ +i;z+=m_voxelWidth){if(CanContinue){

            //this is for the voxel editing at runtime
            //if theres any new chunks that need to be updated they are added here
            if(NewVoxelChunk.Count >0){

            for(int N=  0;N < NewVoxelChunk.Count;N++){if(CanContinue){

            int C = NewVoxelChunk.Count-1;
            //Create the voxel data

            if(C<NewVoxelChunk.Count&&NewVoxelChunk[C]!=null){
            //set various flags so the engine knows it needs to create a new mesh for terrain

            NewVoxelChunk[C].hascollider=false;

            NewVoxelChunk[C].HasVoxel=false;

            NewVoxelChunk[C].CreateMeshesWithVoxels();

            NewVoxelChunk.Remove(NewVoxelChunk[C]);

                                                    }

                                                }

                                            }
                                        }

            //if the terrain has been edited calling saveTerrains() method
            //will save the voxel data to a file
            //here i just set the flag of this script to cansave =true; and it saves automatically
            if(cansave){

            SaveTerrains();

            cansave = false;
                                        }

            //set up variables for distance checking

            Vector2 chunkpos = new Vector2((x) ,(z));

            Vector2 playerpos = new Vector2(Player.x,Player.z);

            //distance checking
            Dist = Vector2.Distance(playerpos , chunkpos);

            if(Dist < distanceToload){
            //check if the chunk already exists if not create a chunk with x *y * z of voxels

            if(!m_voxelChunk.ContainsKey(x,z)){
            Pos = new Vector3(chunkpos.x, 0 , chunkpos.y);

            //set variables for chunk creation
            Chunk = new VoxelChunk(Pos, m_voxelWidth, m_voxelHeight, m_voxelLength, m_surfaceLevel);

            //add chunk to double key dictionary
            m_voxelChunk.Add(x,z,Chunk) ;

            //set flag on chunk
            m_voxelChunk[x,z].hasproccessed=true;

            //add chunk to list of chunks that need noise added to them
            RequestedChunks.Add(m_voxelChunk[x,z]);

                                                    }
                                                }
            //if the chunk already exists and its distance is greater then render distance
            //+ 50 then call destroy on the chunk
            else if(m_voxelChunk.ContainsKey(x,z) && Dist > distanceToload+64){

            Destroy(x,z);
                                        }
                                    }
                                }
                            }
                        }
                    }

            //catch exceptions
            }catch (Exception e)
            {Debug.LogError(e.StackTrace);
            }

            }
        }
        //check if voxel exists and to what chunk it belongs to
        //just VoxelTerrainEngine.raycastvoxels to raycast for a
        //voxel then check the hit.point against this
        //should return a chunk
        public bool CheckVoxels(Vector3 HitPoint,out VoxelChunk chunk)
        {
            int C = ActiveChunks.Count;

                chunk = null;

            for(int c = 0;c < C;c++){

            if(ActiveChunks[c].CheckVoxels(HitPoint)){

                        chunk = ActiveChunks[c];

                    }
            }
            if(chunk!=null)

                return true;

            else

                return false;
        }