예제 #1
0
        /// <summary>
        /// Returns the initial corners for the Diamond Square Algorithm.
        /// </summary>
        /// <param name="vmap"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="width"></param>
        /// <param name="depth"></param>
        /// <returns></returns>
        public float[] InitializeCorners(VertexMap vmap, int x, int y, int width, int depth)
        {
            float[] corners = new float[4];
            //corner lower left
            int vx = x - (width - 1) / 2; //vertex x
            int vy = y - (width - 1) / 2; //vertex y

            if (!float.IsNaN(corners[1] = vmap.GetHeight(vx, vy)))
            {
                corners[0] = 0f;
            }
            //corner lower right
            vx = x + (width - 1) / 2; //vertex x
            vy = y - (width - 1) / 2; //vertex y
            if (!float.IsNaN(corners[1] = vmap.GetHeight(vx, vy)))
            {
                corners[1] = 0f;
            }
            //corner upper right
            vx = x + (width - 1) / 2; //vertex x
            vy = y + (width - 1) / 2; //vertex y
            if (!float.IsNaN(corners[1] = vmap.GetHeight(vx, vy)))
            {
                corners[2] = 0f;
            }
            //corner upper left
            vx = x - (width - 1) / 2; //vertex x
            vy = y + (width - 1) / 2; //vertex y
            if (!float.IsNaN(corners[1] = vmap.GetHeight(vx, vy)))
            {
                corners[3] = 0f;
            }
            return(corners);
        }
예제 #2
0
        void CalculateBlend2()
        {
            float max = 0f;

            VertexMap map = DynamicTerrain.Instance.VertexMap;
            Vertex    l   = map.VertexAt(_x - 1, _y);

            if (l != null && l._loaded)
            {
                float diff = Mathf.Abs(l._height - _height);
                if (diff > max)
                {
                    max = diff;
                }
            }

            Vertex r = map.VertexAt(_x + 1, _y);

            if (r != null && r._loaded)
            {
                float diff = Mathf.Abs(r._height - _height);
                if (diff > max)
                {
                    max = diff;
                }
            }

            Vertex u = map.VertexAt(_x, _y + 1);

            if (u != null && u._loaded)
            {
                float diff = Mathf.Abs(u._height - _height);
                if (diff > max)
                {
                    max = diff;
                }
            }

            Vertex d = map.VertexAt(_x, _y - 1);

            if (d != null && d._loaded)
            {
                float diff = Mathf.Abs(d._height - _height);
                if (diff > max)
                {
                    max = diff;
                }
            }

            _color.a = Mathf.Clamp01(max / 50f);
        }
예제 #3
0
        void Start()
        {
            int chunkLoadRadius = WorldManager.Instance.ChunkLoadRadius;
            int chunkRes        = WorldManager.Instance.ChunkResolution;

            // Init verts
            int verts = 2 * chunkLoadRadius * (chunkRes - 1);

            _loadOpsToDo = verts * verts;

            // Init vertex map
            _vertexMap = new VertexMap();

            // Init chunk map
            _chunkMap = new Map <Chunk>(chunkLoadRadius * 2);

            // Init frequency data vars
            int freqSampleSize = WorldManager.Instance.FrequencySampleSize;

            _data = new float[freqSampleSize];
        }
예제 #4
0
        /// <summary>
        /// Resets necessary variables after de-pooling a chunk.
        /// </summary>
        public void Reuse(int x, int y)
        {
            DynamicTerrain terrain   = DynamicTerrain.Instance;
            VertexMap      vmap      = terrain.VertexMap;
            float          chunkSize = WorldManager.Instance.ChunkSize;

            // Update vars
            _x = x;
            _y = y;

            // Move chunk to appropriate position
            transform.position = new Vector3(x * chunkSize - chunkSize / 2f, 0f, y * chunkSize - chunkSize / 2f);

            // Update chunk name
            gameObject.name = "Chunk (" + x + "," + y + ") Position:" + transform.position.ToString();

            _priority = 0f;

            // Clear decoration list
            _decorations.Clear();

            // Register all vertices with vertex map
            // Move vertices, generate normals/colors
            for (int i = 0; i < _numVerts; i++)
            {
                // Get VMap coords
                IntVector2 coord = IntToV2(i);
                _coords[i] = coord;

                // Get corresponding vertex
                _mapVerts[i] = vmap.VertexAt(coord, true);

                // Get height from vertex
                UpdateVertex(i, _mapVerts[i].Height);
            }

            _hasCheckedForRoad = false;

            UpdateCollider();
        }
예제 #5
0
        public void SmoothHeight(float h, float factor, float range)
        {
            SetHeight(h);
            Vector2   v   = new Vector2((float)_x, (float)_y);
            VertexMap map = DynamicTerrain.Instance.VertexMap;

            for (int ix = map.XMin; ix <= map.XMax; ix++)
            {
                if ((float)Mathf.Abs(ix - _x) > range)
                {
                    continue;
                }
                for (int iy = map.YMin; iy <= map.YMax; iy++)
                {
                    if ((float)Mathf.Abs(iy - _y) > range)
                    {
                        continue;
                    }

                    Vector2 n    = new Vector2((float)ix, (float)iy);
                    float   dist = Vector2.Distance(n, v);
                    if (dist > range)
                    {
                        continue;
                    }

                    if (ix == _x && iy == _y)
                    {
                        continue;
                    }

                    Vertex vert = map.VertexAt(ix, iy);
                    if (vert != null && !vert._locked)
                    {
                        vert.Smooth(h, factor * (range - dist) / range);
                    }
                }
            }
        }
예제 #6
0
        void CalculateBlend()
        {
            bool debug = (UnityEngine.Random.Range(0, 10000) == 1);

            if (debug)
            {
                Debug.Log(ToString());
            }

            int   numNeighbors = 0;
            float delta        = 0f;

            VertexMap map = DynamicTerrain.Instance.VertexMap;
            Vertex    l   = map.VertexAt(_x - 1, _y);

            if (l != null && l._loaded)
            {
                numNeighbors++;
                float diff = Mathf.Abs(_height - l._height);
                if (debug)
                {
                    Debug.Log("Left: " + l.ToString() + " " + diff);
                }
                delta += diff;
            }

            Vertex r = map.VertexAt(_x + 1, _y);

            if (r != null && r._loaded)
            {
                numNeighbors++;
                float diff = Mathf.Abs(_height - r._height);
                if (debug)
                {
                    Debug.Log("Right: " + r.ToString() + " " + diff);
                }
                delta += diff;
            }

            Vertex u = map.VertexAt(_x, _y + 1);

            if (u != null && u._loaded)
            {
                numNeighbors++;
                float diff = Mathf.Abs(_height - u._height);
                if (debug)
                {
                    Debug.Log("Up: " + u.ToString() + " " + diff);
                }
                delta += diff;
            }

            Vertex d = map.VertexAt(_x, _y - 1);

            if (d != null && d._loaded)
            {
                numNeighbors++;
                float diff = Mathf.Abs(_height - d._height);
                if (debug)
                {
                    Debug.Log("Down: " + d.ToString() + " " + diff);
                }
                delta += diff;
            }

            _color.a = delta / (float)numNeighbors / 100f;
            if (debug)
            {
                Debug.Log("final blend: " + _color.a);
            }
        }
예제 #7
0
        public void SmoothHeight(float h, float factor)
        {
            SetHeight(h);
            VertexMap map = DynamicTerrain.Instance.VertexMap;
            Vertex    l   = map.LeftNeighbor(this);

            if (l != null && !l._locked && !l.NearRoad)
            {
                l.Smooth(h, factor);
            }

            Vertex r = map.RightNeighbor(this);

            if (r != null && !r._locked && r.NearRoad)
            {
                r.Smooth(h, factor);
            }

            Vertex d = map.DownNeighbor(this);

            if (d != null && !d._locked && d.NearRoad)
            {
                d.Smooth(h, factor);
            }

            Vertex u = map.UpNeighbor(this);

            if (u != null && !u._locked && u.NearRoad)
            {
                u.Smooth(h, factor);
            }

            float factor_squared = factor * factor;

            if (u != null)
            {
                Vertex ul = map.LeftNeighbor(u);
                if (ul != null && !ul._locked && ul.NearRoad)
                {
                    ul.Smooth(h, factor_squared);
                }

                Vertex ur = map.RightNeighbor(u);
                if (ur != null && !ur._locked && ur.NearRoad)
                {
                    ur.Smooth(h, factor_squared);
                }
            }

            if (d != null)
            {
                Vertex dl = map.LeftNeighbor(d);
                if (dl != null && !dl._locked && dl.NearRoad)
                {
                    dl.Smooth(h, factor_squared);
                }

                Vertex dr = map.RightNeighbor(d);
                if (dr != null && !dr._locked && dr.NearRoad)
                {
                    dr.Smooth(h, factor_squared);
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Coroutine to update the vertices of a chunk.
        /// </summary>
        /// <returns>The verts.</returns>
        private IEnumerator UpdateVerts()
        {
            if (!GameManager.Instance.IsLoaded)
            {
                yield break;
            }

            _isUpdatingVerts = true;
            float          margin    = WorldManager.Instance.ChunkSize / 2;
            float          startTime = Time.realtimeSinceStartup;
            Vector3        playerPos = PlayerMovement.Instance.transform.position;
            Vector3        chunkPos  = transform.position;
            DynamicTerrain terrain   = DynamicTerrain.Instance;
            VertexMap      vmap      = terrain.VertexMap;

            int v = 0;

            for (; v < _numVerts; v++)
            {
                // Get VMap coordinates
                IntVector2 coord = _coords[v];

                // Get coresponding vertex
                Vertex vert = _mapVerts[v];

                // Update vertex height
                UpdateVertex(v, vert.Height);

                if (terrain.FreqData == null)
                {
                    yield break;
                }

                // If vertex is not locked and there is frequency data to use
                if (!vert.Locked)
                {
                    // Distance between player and vertex
                    Vector3 vertPos  = chunkPos + _verts[v];
                    float   distance = Vector3.Distance(vertPos, playerPos);

                    // If vertex is close enough
                    if (CheckDist(distance, WorldManager.Instance.VertexUpdateDistance, margin))
                    {
                        // Calculate new height
                        Vector3 angleVector = vertPos - playerPos;
                        float   angle       = Vector3.Angle(Vector3.right, angleVector);
                        float   linIntInput = angle / 360f;
                        float   newY        = terrain.FreqData.GetDataPoint(linIntInput) *
                                              WorldManager.Instance.HeightScale;

                        // If new height, set it
                        //if (newY != vmap.VertexAt(coord, false).height) vmap.SetHeight (coord, newY);
                        if (newY != 0f)
                        {
                            vmap.AddHeight(coord, newY);
                        }
                    }
                }

                if (v == _numVerts - 1)
                {
                    _isUpdatingVerts = false;
                    yield break;
                }
                else if (Time.realtimeSinceStartup - startTime > GameManager.TargetDeltaTime)
                {
                    yield return(null);

                    startTime = Time.realtimeSinceStartup;
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Initializes a brand new chunk at x and y.
        /// </summary>
        public void Initialize(int x, int y)
        {
            DynamicTerrain terrain = DynamicTerrain.Instance;

            // Init vars
            _x = x;
            _y = y;

            VertexMap vmap      = terrain.VertexMap;
            int       chunkRes  = WorldManager.Instance.ChunkResolution;
            float     chunkSize = WorldManager.Instance.ChunkSize;

            // Generate vertices
            _verts    = CreateUniformVertexArray(chunkRes);
            _numVerts = _verts.Length;

            // Generate triangles
            _triangles = CreateSquareArrayTriangles(chunkRes);

            // Init normals
            _normals = new Vector3[_numVerts];

            // Generate UVs
            _uvs = CreateUniformUVArray(chunkRes);

            // Init colors
            _colors = new Color[_numVerts];

            // Init coords and mapVerts
            _coords   = new IntVector2[_numVerts];
            _mapVerts = new Vertex[_numVerts];

            // Build initial chunk mesh
            _mesh = CreateChunkMesh();

            // Assign mesh
            GetComponent <MeshFilter>().mesh = _mesh;

            // Move GameObject to appropriate position
            transform.position = new Vector3(x * chunkSize - chunkSize / 2f, 0f, y * chunkSize - chunkSize / 2f);

            // Initialize name
            gameObject.name = "Chunk (" + x + "," + y + ") Position:" + transform.position.ToString();

            // Init decorations list
            _decorations = new List <GameObject>();

            // Register all vertices with vertex map
            // Move vertices, generate normals/colors
            for (int i = 0; i < _numVerts; i++)
            {
                // Init normal/color
                _normals[i] = Vector3.up;
                _colors[i]  = Color.white;

                // Get VMap coords
                IntVector2 coord = IntToV2(i);
                _coords[i] = coord;

                // Get corresponding vertex
                _mapVerts[i] = vmap.VertexAt(coord, true);

                // If vertex exists, get height
                UpdateVertex(i, _mapVerts[i].Height);
                UpdateColor(i, _mapVerts[i].Color);
            }

            // Assign material
            MeshRenderer renderer = GetComponent <MeshRenderer>();

            renderer.sharedMaterial       = WorldManager.Instance.TerrainMaterial;
            renderer.shadowCastingMode    = UnityEngine.Rendering.ShadowCastingMode.On;
            renderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;

            // Assign collision mesh
            MeshCollider collider = GetComponent <MeshCollider>();

            collider.sharedMesh = _mesh;
            collider.convex     = false;

            // Init rigidbody
            Rigidbody rigidbody = GetComponent <Rigidbody>();

            rigidbody.freezeRotation = true;
            rigidbody.isKinematic    = true;
            rigidbody.useGravity     = false;
            rigidbody.constraints    = RigidbodyConstraints.FreezeAll;

            // Add grass system
            _grassEmitter = GameObject.Instantiate(WorldManager.Instance.GrassEmitterPrefab);
            _grassEmitter.transform.parent        = transform;
            _grassEmitter.transform.localPosition = Vector3.zero;

            // Randomize grass density
            ParticleSystem sys = _grassEmitter.GetComponent <ParticleSystem>();

            sys.maxParticles = UnityEngine.Random.Range(0, WorldManager.Instance.GrassPerChunk);
            sys.playOnAwake  = true;

            // Assign particle system emission shape
            ParticleSystem.ShapeModule shape = sys.shape;
            shape.mesh = _mesh;

            // Assign particle system emission rate
            ParticleSystem.EmissionModule emit = sys.emission;
            emit.rate = new ParticleSystem.MinMaxCurve(WorldManager.Instance.DecorationsPerStep);

            UpdateCollider();
        }