Example #1
0
        public void PopulateCluster(Vector3 position, Rect boundary, float minScale, float maxScale, float density, float resolution)
        {
            // Empty the cluster
            if (positionList == null)
            {
                positionList = new List <Vector3>();
            }
            else
            {
                positionList.Clear();
            }

            if (scaleList == null)
            {
                scaleList = new List <Vector3>();
            }
            else
            {
                scaleList.Clear();
            }

            Vector3 origin = new Vector3(position.x - (boundary.width / 2f), position.y, position.z - (boundary.height / 2f));

            float   noiseOffset          = UnityEngine.Random.Range(0f, boundary.width);
            Vector2 noiseCoords          = Vector2.zero;
            float   clusterNoiseTileSize = boundary.width / 5f;

            // Convert values from float to int to avoid a float for(;;) loop
            int resolutionInt = Mathf.FloorToInt(resolution * 1000f);
            int widthInt      = Mathf.FloorToInt(boundary.width * 1000);
            int lengthInt     = Mathf.FloorToInt(boundary.height * 1000);

            float xF = 0f, zF = 0f;

            for (int x = 0; x < widthInt; x += resolutionInt)
            {
                for (int z = 0; z < lengthInt; z += resolutionInt)
                {
                    // Convert back to floats
                    xF = x / 1000f;
                    zF = z / 1000f;

                    // Get a perlin noise value for this point in the cluster
                    noiseCoords.x = xF + noiseOffset;
                    noiseCoords.y = zF + noiseOffset;
                    float noiseValue = Mathf.Abs(LBNoise.PerlinFractalNoise(noiseCoords.x / clusterNoiseTileSize, noiseCoords.y / clusterNoiseTileSize, 5) - 0.5f) * 4f;
                    // If the noise value is less than density don't create the position
                    if (noiseValue < density)
                    {
                        positionList.Add(new Vector3(origin.x + xF, origin.y, origin.z + zF));
                        scaleList.Add(Vector3.one * UnityEngine.Random.Range(minScale, maxScale));
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Find a random offset (position) within an area with the given radius for a GroupMember.
        /// USAGE: Vector2 offset = LBGroupMember.GetRandomOffset(lbGroupMember, basePlaneWidth / 2f, 100);
        /// </summary>
        /// <param name="lbGroupMember"></param>
        /// <param name="radius"></param>
        /// <param name="maxAttempts"></param>
        /// <returns></returns>
        public static Vector2 GetRandomOffset(LBGroupMember lbGroupMember, float radius, int maxAttempts)
        {
            Vector2 offset      = Vector2.zero;
            Vector2 noiseCoords = Vector2.zero;

            // Declare and initialise variables
            // To start with we have made zero attempts and not found a legal placement
            // (by this we mean a placement within the circle, and following some extra rules like noise)
            bool foundLegalPlacement = false;
            int  attempts            = 0;

            // Repeat until we find a legal placement or we try maxAttempts times
            while (!foundLegalPlacement && attempts < maxAttempts)
            {
                // Generate a random position - the chance of this placement not being legal
                // is (4 - PI) / 4 = 21.5% (so chance of it being legal is 78.5%)
                // Thus it is 99% likely that within 3 attempts we will have found a correct placement
                offset.x = UnityEngine.Random.Range(-radius, radius);
                offset.y = UnityEngine.Random.Range(-radius, radius);
                // Judge legality: First, based on whether placement is within radius...
                foundLegalPlacement = offset.magnitude < radius;
                if (foundLegalPlacement && lbGroupMember != null && lbGroupMember.useNoise)
                {
                    // ... then by whether it follows noise rules
                    noiseCoords.x = offset.x + lbGroupMember.noiseOffset;
                    noiseCoords.y = offset.y + lbGroupMember.noiseOffset;
                    float noiseValue = Mathf.Abs(LBNoise.PerlinFractalNoise(noiseCoords.x / lbGroupMember.noiseTileSize, noiseCoords.y / lbGroupMember.noiseTileSize, 5) - 0.5f) * 4f;
                    // If the noise value is less than (1 - prefab cutoff value) placement is not legal
                    foundLegalPlacement = noiseValue >= 1f - lbGroupMember.noisePlacementCutoff;
                }

                attempts++;
            }

            // If we have tried maxAttempts times and still not found a correct placement, just set the position to the centre
            if (!foundLegalPlacement)
            {
                offset = Vector2.zero;
            }

            return(offset);
        }