예제 #1
0
        /// <summary>
        /// Draw gizmos
        /// </summary>
        void OnDrawGizmosSelected()
        {
            if (m_resources == null)
            {
                return;
            }

            if (m_spawner == null)
            {
                return;
            }

            if (m_terrainHeightMap == null)
            {
                return;
            }

            //Lets visualise fitness
            float x, y = transform.position.y, z;
            float xStart   = transform.position.x - m_range;
            float xEnd     = transform.position.x + m_range;
            float zStart   = transform.position.z - m_range;
            float zEnd     = transform.position.z + m_range;
            float ballsize = Mathf.Clamp(m_resolution * 0.25f, 0.5f, 5f);

            m_spawner.m_spawnRange    = m_range;
            m_spawner.m_spawnerBounds = new Bounds(transform.position, new Vector3(m_range * 2f, m_range * 20f, m_range * 2f));

            SpawnInfo spawnInfo = new SpawnInfo();
            Vector3   location  = new Vector3();
            float     fitness   = 0f;

            //Create caches
            if ((DateTime.Now - m_lastCacheUpdateDate).TotalSeconds > 5)
            {
                m_lastCacheUpdateDate = DateTime.Now;
                m_spawner.DeleteSpawnCaches();
                m_spawner.CreateSpawnCaches(m_selectedResourceType, m_selectedResourceIdx);

                //Also update the location so make moving it easier
                Terrain terrain = TerrainHelper.GetTerrain(transform.position);
                if (terrain != null)
                {
                    transform.position = new Vector3(transform.position.x, terrain.SampleHeight(transform.position) + 5f, transform.position.z);
                }
            }

            //Set up the texture layer array in spawn info
            spawnInfo.m_textureStrengths = new float[Terrain.activeTerrain.terrainData.alphamapLayers];

            //Now visualise fitness
            for (x = xStart; x < xEnd; x += m_resolution)
            {
                for (z = zStart; z < zEnd; z += m_resolution)
                {
                    location.Set(x, y, z);
                    if (m_spawner.CheckLocation(location, ref spawnInfo))
                    {
                        fitness = GetFitness(ref spawnInfo);
                        if (fitness < m_minimumFitness)
                        {
                            continue;
                        }
                        Gizmos.color = Color.Lerp(m_unfitColour, m_fitColour, fitness);
                        Gizmos.DrawSphere(spawnInfo.m_hitLocationWU, ballsize);
                    }
                }
            }

            //Now draw water
            //Water
            if (m_resources != null)
            {
                Bounds bounds = new Bounds();
                if (TerrainHelper.GetTerrainBounds(transform.position, ref bounds) == true)
                {
                    bounds.center = new Vector3(bounds.center.x, m_resources.m_seaLevel, bounds.center.z);
                    bounds.size   = new Vector3(bounds.size.x, 0.05f, bounds.size.z);
                    Gizmos.color  = new Color(Color.blue.r, Color.blue.g, Color.blue.b, Color.blue.a / 4f);
                    Gizmos.DrawCube(bounds.center, bounds.size);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Return fitness of the spawninfo object - not ideal as it forces closer coupling
        /// </summary>
        /// <param name="spawnInfo">Spawn infor object</param>
        /// <returns>Fitness at that location 0..1</returns>
        public float GetFitness(ref SpawnInfo spawnInfo)
        {
            //Make sure we are initialised
            if (!m_isInitialised)
            {
                Initialise(spawnInfo.m_spawner);
            }

            //Check for active or not
            if (!m_isActive)
            {
                return(0f);
            }

            //Check for virgin (clear terrain)
            if (m_virginTerrain == true)
            {
                if (spawnInfo.m_wasVirginTerrain != true)
                {
                    return(0f);
                }
            }

            //Set default fitness
            float fitness = 1f;

            //Check height
            if (m_checkHeight)
            {
                fitness = Mathf.Min(fitness, GetHeightFitness(spawnInfo.m_terrainHeightWU, GaiaSessionManager.GetSessionManager().GetSeaLevel()));
            }

            //Check slope
            if (m_checkSlope && fitness > 0f)
            {
                if (m_checkType == GaiaConstants.SpawnerLocationCheckType.PointCheck)
                {
                    fitness = Mathf.Min(fitness, GetSlopeFitness(spawnInfo.m_terrainSlopeWU));
                }
                else
                {
                    //fitness = Mathf.Min(fitness, GetSlopeFitness(spawnInfo.m_areaHitSlopeWU));
                    fitness = Mathf.Min(fitness, GetSlopeFitness(spawnInfo.m_areaAvgSlopeWU));
                }
            }

            //Check textures
            if (m_checkTexture && fitness > 0f)
            {
                fitness = Mathf.Min(fitness, GetTextureFitness(spawnInfo.m_textureStrengths));
            }

            //Check proximity
            if (m_checkProximity && fitness > 0f)
            {
                Rect       area          = new Rect(spawnInfo.m_hitLocationWU.x - m_maxProximity, spawnInfo.m_hitLocationWU.z - m_maxProximity, m_maxProximity * 2f, m_maxProximity * 2f);
                GameObject closestObject = null; //spawnInfo.m_spawner.GetClosestObject(m_proximityTag, area);
                if (closestObject != null)
                {
                    fitness = Mathf.Min(fitness, GetProximityFitness(Vector3.Distance(closestObject.transform.position, spawnInfo.m_hitLocationWU)));
                }
                else
                {
                    fitness = 0f;
                }
            }

            //Exit with final fitness
            return(fitness);
        }
예제 #3
0
        /// <summary>
        /// Return the value of the least fittest object in the spawn criteria
        /// </summary>
        /// <param name="spawner">The spawner we belong to</param>
        /// <param name="location">The location we are checking</param>
        /// <param name="slope"></param>
        /// <returns>Fitness in range 0..1f</returns>
        public float GetMinFitness(ref SpawnInfo spawnInfo)
        {
            //Get the filters
            SpawnCritera[] filters;
            switch (m_selectedResourceType)
            {
            case GaiaConstants.SpawnerResourceType.TerrainDetail:
            {
                if (m_selectedResourceIdx >= spawnInfo.m_spawner.m_resources.m_detailPrototypes.Length)
                {
                    return(0f);
                }
                filters = spawnInfo.m_spawner.m_resources.m_detailPrototypes[m_selectedResourceIdx].m_spawnCriteria;
                break;
            }

            case GaiaConstants.SpawnerResourceType.TerrainTexture:
            {
                if (m_selectedResourceIdx >= spawnInfo.m_spawner.m_resources.m_texturePrototypes.Length)
                {
                    return(0f);
                }
                filters = spawnInfo.m_spawner.m_resources.m_texturePrototypes[m_selectedResourceIdx].m_spawnCriteria;
                break;
            }

            case GaiaConstants.SpawnerResourceType.TerrainTree:
            {
                if (m_selectedResourceIdx >= spawnInfo.m_spawner.m_resources.m_treePrototypes.Length)
                {
                    return(0f);
                }
                filters = spawnInfo.m_spawner.m_resources.m_treePrototypes[m_selectedResourceIdx].m_spawnCriteria;
                break;
            }

            default:
            {
                if (m_selectedResourceIdx >= spawnInfo.m_spawner.m_resources.m_gameObjectPrototypes.Length)
                {
                    return(0f);
                }
                filters = spawnInfo.m_spawner.m_resources.m_gameObjectPrototypes[m_selectedResourceIdx].m_spawnCriteria;
                break;
            }
            }

            //Drop out if we have no filters
            if (filters == null || filters.Length == 0)
            {
                return(0f);
            }

            //Now calculate fitness
            float        minFitness = float.MaxValue;
            int          filterIdx;
            SpawnCritera filter;
            float        fitness = 0f;

            for (filterIdx = 0; filterIdx < filters.Length; filterIdx++)
            {
                filter = filters[filterIdx];
                //Check to see of this filter needs a bounds check
                if (filter.m_checkType == GaiaConstants.SpawnerLocationCheckType.BoundedAreaCheck)
                {
                    if (!spawnInfo.m_spawner.CheckLocationBounds(ref spawnInfo, GetMaxScaledRadius(ref spawnInfo)))
                    {
                        return(0f);
                    }
                }
                //Now calculate and process fitness
                fitness = filter.GetFitness(ref spawnInfo);
                if (fitness < minFitness)
                {
                    minFitness = fitness;
                    if (minFitness <= 0f)
                    {
                        return(minFitness);
                    }
                }
            }

            if (minFitness == float.MaxValue)
            {
                return(0f);
            }
            else
            {
                return(minFitness);
            }
        }
        /// <summary>
        /// Call this to get the degree of completion in range 0..1.
        /// </summary>
        /// <param name="spawner">The spawner this is for</param>
        /// <param name="objSpawned">The object that was spawned in the spawn step (if relevant)</param>
        /// <returns>Return the completion in range of 0 (not started) .. 1 (completed)</returns>
        public override void PostSpawn(SpawnRule spawnRule, ref SpawnInfo spawnInfo)
        {
            //See if we can load the texture
            if (m_textureHM == null || !m_textureHM.HasData())
            {
                return;
            }

            //Get the terrain
            Terrain t = Gaia.TerrainHelper.GetTerrain(spawnInfo.m_hitLocationWU);

            if (t == null)
            {
                return;
            }

            //Get the cached texture maps
            List <HeightMap> txtMaps = spawnInfo.m_spawner.GetTextureMaps(spawnInfo.m_hitTerrain.GetInstanceID());

            if (txtMaps == null || m_textureIndex >= txtMaps.Count)
            {
                return;
            }

            //Make some speedy calculations
            float   widthWU = spawnInfo.m_hitTerrain.terrainData.size.x;
            float   depthWU = spawnInfo.m_hitTerrain.terrainData.size.z;
            float   radiusWU = spawnRule.GetMaxScaledRadius(ref spawnInfo) * m_scaleMask;
            float   xStartWU = spawnInfo.m_hitLocationWU.x - (radiusWU / 2f);
            float   zStartWU = spawnInfo.m_hitLocationWU.z - (radiusWU / 2f);
            float   xEndWU = xStartWU + radiusWU;
            float   zEndWU = zStartWU + radiusWU;
            float   stepWU = 0.5f;
            Vector3 locationWU = Vector3.zero;
            float   xRotNU = 0f, zRotNU = 0f;
            float   currStrength = 0f, newStrength = 1f;

            for (float x = xStartWU; x < xEndWU; x += stepWU)
            {
                for (float z = zStartWU; z < zEndWU; z += stepWU)
                {
                    //Need to rotate x,z around the pivot by the rotation angle
                    locationWU = new Vector3(x, spawnInfo.m_hitLocationWU.y, z);
                    locationWU = Gaia.Utils.RotatePointAroundPivot(locationWU, spawnInfo.m_hitLocationWU, new Vector3(0f, spawnInfo.m_spawnRotationY, 0f));

                    //Now normalise the result
                    xRotNU = (locationWU.x / widthWU) + 0.5f;
                    zRotNU = (locationWU.z / depthWU) + 0.5f;

                    //Drop out if out of bounds
                    if (xRotNU < 0f || xRotNU >= 1f || zRotNU < 0f || zRotNU > 1f)
                    {
                        continue;
                    }

                    //Only interested in increasing values
                    currStrength = txtMaps[m_textureIndex][zRotNU, xRotNU];
                    newStrength  = m_textureHM[(x - xStartWU) / radiusWU, (z - zStartWU) / radiusWU];
                    if (newStrength > currStrength)
                    {
                        float delta      = newStrength - currStrength;
                        float theRest    = 1f - currStrength;
                        float adjustment = 0f;
                        if (theRest != 0f)
                        {
                            adjustment = 1f - (delta / theRest);
                        }

                        for (int idx = 0; idx < txtMaps.Count; idx++)
                        {
                            if (idx == m_textureIndex)
                            {
                                txtMaps[idx][zRotNU, xRotNU] = newStrength;
                            }
                            else
                            {
                                txtMaps[idx][zRotNU, xRotNU] *= adjustment;
                            }
                        }
                    }
                }
            }

            spawnInfo.m_spawner.SetTextureMapsDirty();
        }