Esempio n. 1
0
 /// <summary>
 /// Initializes a new instance of <see cref="SurfaceRegion"/>.
 /// </summary>
 /// <param name="planet">The planet on which this region is found.</param>
 /// <param name="position">The normalized position vector of this region.</param>
 /// <param name="latitudeRange">
 /// <para>
 /// The range of latitudes encompassed by this region, as an angle (in radians).
 /// </para>
 /// <para>
 /// Maximum value is π (a full hemisphere, which produces the full globe).
 /// </para>
 /// </param>
 public SurfaceRegion(Planetoid planet, Vector3 <HugeNumber> position, HugeNumber latitudeRange)
     : base(planet.Id, new Frustum <HugeNumber>(2, position * (planet.Shape.ContainingRadius + planet.Atmosphere.AtmosphericHeight), HugeNumber.Min(latitudeRange, HugeNumber.Pi), 0))
 {
 }
Esempio n. 2
0
    // -------------------------------------------------------------------------------

    private void OnPlanetoidChange(Planetoid newPlanetoid)
    {
        mGameManager.ChangeGameplayState(GameplayStates.RidingSunbeams);
        FinishAction();
    }
Esempio n. 3
0
 internal Atmosphere(
     Planetoid planet,
     double pressure,
     params (ISubstanceReference substance, decimal proportion)[] constituents) : this(pressure)
Esempio n. 4
0
    // returns null if nothing was sliced
    // even when hit by the laser nothing might get sliced
    //	this is because I limit the minimum size of a new
    //	planetoid for performance reasons.
    //
    public Planetoid Slice(Ray2D laser, float laserPower, PlanetoidsManager manager)
    {
        if (_fading)
        {
            return(null);
        }

        try {
            Vector2 start = transform.InverseTransformPoint(laser.origin);
            Vector2 end   = transform.InverseTransformPoint(laser.origin + laser.direction * Laser.LASER_DISTANCE);

            SlicePoint[] slicePoints = new SlicePoint[2];
            Vector2[]    vertices    = _collider.points;
            int          foundPoints = 0;
            for (int i = 0; i < vertices.Length && foundPoints <= 2; ++i)
            {
                //Calculate intersectionPoint
                //For formula see http://en.wikipedia.org/wiki/Line-line_intersection
                //I'm using x1, x2, ... since that's easier to write.
                float   x1 = start.x, x2 = end.x, x3 = vertices[i].x, x4 = vertices[(i + 1) % vertices.Length].x;
                float   y1 = start.y, y2 = end.y, y3 = vertices[i].y, y4 = vertices[(i + 1) % vertices.Length].y;
                Vector2 intersectionPoint = new Vector2(
                    (((x1 * y2 - y1 * x2) * (x3 - x4)) - ((x1 - x2) * (x3 * y4 - y3 * x4))) / (((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))),
                    (((x1 * y2 - y1 * x2) * (y3 - y4)) - ((y1 - y2) * (x3 * y4 - y3 * x4))) / (((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4)))
                    );

                //See if the point is is actually on the side & laser.

                float startx = Mathf.Min(vertices[i].x, vertices[(i + 1) % vertices.Length].x);              //side
                float endx   = Mathf.Max(vertices[i].x, vertices[(i + 1) % vertices.Length].x);
                float starty = Mathf.Min(vertices[i].y, vertices[(i + 1) % vertices.Length].y);
                float endy   = Mathf.Max(vertices[i].y, vertices[(i + 1) % vertices.Length].y);

                float start2x = Mathf.Min(start.x, end.x);                 //laser
                float end2x   = Mathf.Max(start.x, end.x);
                float start2y = Mathf.Min(start.y, end.y);
                float end2y   = Mathf.Max(start.y, end.y);
                if (intersectionPoint.x >= startx && intersectionPoint.x < endx && intersectionPoint.y >= starty && intersectionPoint.y < endy &&
                    intersectionPoint.x >= start2x && intersectionPoint.x < end2x && intersectionPoint.y >= start2y && intersectionPoint.y < end2y)
                {
                    //Add to the slicePoints vector if you find anything
                    // throws when too many points were found
                    slicePoints[foundPoints] = new SlicePoint(intersectionPoint, i);
                    ++foundPoints;
                }
            }

            if (foundPoints != 2)
            {
                throw new UnityException("Wrong number of points found while slicing: " + foundPoints);
            }

            //Calculate the number of sides each part of the rock will have
            int numberOfPoints1 = Mathf.Abs(slicePoints[0].side - slicePoints[1].side);
            int numberOfPoints2 = vertices.Length - numberOfPoints1;
            //numberOfPoints1 = min(numberOfPoints1, b2_maxPolygonVertices-2); //Make sure there aren't too many vertexes (Box2D 'limitation')
            //numberOfPoints2 = min(numberOfPoints2, b2_maxPolygonVertices-2); //I raised the max Polygon verts to 16 (default 8) so it will almost never happen, though when it does it's almost invisible
            //Create vectors to save the sides of each new rock
            Vector2[] sides1 = new Vector2[numberOfPoints1 + 2];
            Vector2[] sides2 = new Vector2[numberOfPoints2 + 2];

            //Filling in the first vector
            int counter = slicePoints[0].side + 1;
            for (var i = 0; i < numberOfPoints1; ++i)
            {
                if (counter >= vertices.Length)
                {
                    throw new UnityException("Whoops, something wrong with the slicing. Should never happen, please report this.");                     //Should never go over 0
                }
                sides1[i] = vertices[counter];
                ++counter;
            }
            //Lastly add the intersection points to the sides1.
            sides1[numberOfPoints1 + 0] = slicePoints[1].point;             //Since I add them to the back the second one found will always be the first one here.
            sides1[numberOfPoints1 + 1] = slicePoints[0].point;

            //Filling in the second one
            for (var i = 0; i < numberOfPoints2; ++i)
            {
                counter   = counter % vertices.Length;
                sides2[i] = vertices[counter];
                ++counter;
            }
            sides2[numberOfPoints2 + 0] = slicePoints[0].point;
            sides2[numberOfPoints2 + 1] = slicePoints[1].point;

            //Check if both new polygons are valid. Their size & winding will be checked, also they have to be convex.
            if (GetArea(sides1) < MINIMUM_AREA || GetArea(sides2) < MINIMUM_AREA)
            {
                throw new UnityException("At least one of the new planetoids is too small, not slicing for performance reasons.");
            }

            //Get some values needed to set later.
            Vector2 linVel   = _rigidbody.velocity;
            float   angleVel = _rigidbody.angularVelocity;
            Vector2 dir      = laser.direction;
            Vector2 lr       = new Vector2(-dir.y, dir.x);
            lr.Normalize();
            lr *= laserPower;

            //Change this rock.
            Initialize(sides1, manager);

            //Make the other part.
            Planetoid newRock = manager.GetNewOrCashedPlanetoid();
            newRock.Initialize(sides2, manager);
            newRock.transform.position         = transform.position;
            newRock.transform.rotation         = transform.rotation;
            newRock._rigidbody.velocity        = linVel;
            newRock._rigidbody.angularVelocity = angleVel;
            newRock._density = _density;

            //Set Velocities.
            _rigidbody.AddForce(lr, ForceMode2D.Impulse);
            newRock._rigidbody.AddForce(-lr, ForceMode2D.Impulse);

            return(newRock);
        }
        catch (UnityException ex) {
            Debug.Log("Failed slicing: " + ex.Message);
            return(null);
        }
        catch {
            Debug.Log("Failed slicing for an unknown reason");
            return(null);
        }
    }
Esempio n. 5
0
 /// <summary>
 /// Initializes a new instance of <see cref="PlanetChildDefinition"/>.
 /// </summary>
 /// <param name="density">
 /// The density of this type of child within the containing parent region.
 /// </param>
 /// <param name="planemoType">
 /// The type of <see cref="Planetoid"/>.
 /// </param>
 public PlanetChildDefinition(HugeNumber density, PlanetType planemoType = PlanetType.Dwarf) : base(Planetoid.GetSpaceForType(planemoType), density) => PlanetType = planemoType;
Esempio n. 6
0
    private static void AddPrecipitationString(
        StringBuilder sb,
        Planetoid planet,
        Image <L16> elevationMap,
        Image <L16> precipitationMap,
        double normalizedSeaLevel,
        int landCoords,
        WeatherMaps maps)
    {
        sb.Append("Max precip: ")
        .Append(Math.Round(planet.Atmosphere.MaxPrecipitation, 3))
        .AppendLine("mm/hr");

        sb.AppendLine("Precipitation (average, land):");
        if (landCoords == 0)
        {
            sb.AppendLine("  No land.");
            return;
        }

        var n         = 0;
        var temperate = 0.0;
        var list      = new List <double>();

        for (var x = 0; x < maps.XLength; x++)
        {
            for (var y = 0; y < maps.YLength; y++)
            {
                if (((double)elevationMap[x, y].PackedValue / ushort.MaxValue) - normalizedSeaLevel < 0)
                {
                    continue;
                }

                var precipitation = (double)precipitationMap[x, y].PackedValue / ushort.MaxValue * planet.Atmosphere.MaxPrecipitation;

                list.Add(precipitation);

                if (maps.ClimateMap[x][y] is ClimateType.CoolTemperate
                    or ClimateType.WarmTemperate)
                {
                    temperate += precipitation;
                    n++;
                }
            }
        }
        list.Sort();
        if (n == 0)
        {
            temperate = 0;
        }
        else
        {
            temperate /= n;
        }

        var avg = list.Average();

        sb.AppendFormat("  Avg:                     {0}mm/hr ({1:+0.##;-0.##;on-targ\\et})", Math.Round(avg, 3), Math.Round(avg - 0.11293634496919917864476386036961, 3));
        sb.AppendLine();
        var avg90 = list.Take((int)Math.Floor(list.Count * 0.9)).Average();

        sb.AppendFormat("  Avg (<=P90):             {0}mm/hr ({1:+0.##;-0.##;on-targ\\et})", Math.Round(avg90, 3), Math.Round(avg90 - 0.11293634496919917864476386036961, 3));
        sb.AppendLine();
        var avgList = planet.Atmosphere.AveragePrecipitation;

        sb.AppendFormat("  Avg (listed):            {0}mm/hr ({1:+0.##;-0.##;on-targ\\et})", Math.Round(avgList, 3), Math.Round(avgList - 0.11293634496919917864476386036961, 3));
        sb.AppendLine();
        sb.AppendFormat("  Avg (Temperate):         {0}mm/hr ({1:+0.##;-0.##;on-targ\\et})", Math.Round(temperate, 3), Math.Round(temperate - 0.12548482774355464293862651152179, 3));
        sb.AppendLine();

        sb.AppendFormat("  Min:                     {0}mm/hr", Math.Round(list[0], 3));
        sb.AppendLine();
        sb.AppendFormat("  P10:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.1)).First(), 3));
        sb.AppendLine();
        sb.AppendFormat("  P20:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.2)).First(), 3));
        sb.AppendLine();
        sb.AppendFormat("  P30:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.3)).First(), 3));
        sb.AppendLine();
        sb.AppendFormat("  P40:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.4)).First(), 3));
        sb.AppendLine();
        sb.AppendFormat("  P50:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.5)).First(), 3));
        sb.AppendLine();
        sb.AppendFormat("  P60:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.6)).First(), 3));
        sb.AppendLine();
        sb.AppendFormat("  P70:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.7)).First(), 3));
        sb.AppendLine();
        sb.AppendFormat("  P80:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.8)).First(), 3));
        sb.AppendLine();
        sb.AppendFormat("  P90:                     {0}mm/hr", Math.Round(list.Skip((int)Math.Floor(list.Count * 0.9)).First(), 3));
        sb.AppendLine();
        var max = list.Last();

        sb.AppendFormat("  Max:                     {0}mm/hr ({1:+0.##;-0.##;on-targ\\et})", Math.Round(max), Math.Round(max - 1.3542094455852156057494866529774, 3));

        sb.AppendLine();
    }
Esempio n. 7
0
 public static Planetoid GenerateRandomMoon(Planetoid parent, string name)
 {
     return(new Planetoid(parent.System, name, parent));
 }
Esempio n. 8
0
 /// <summary>
 /// Produces an elevation map projection of this region.
 /// </summary>
 /// <param name="region">The mapped region.</param>
 /// <param name="planet">The planet being mapped.</param>
 /// <param name="resolution">The vertical resolution of the projection.</param>
 /// <param name="equalArea">
 /// If <see langword="true"/> the projection will be a cylindrical equal-area projection.
 /// Otherwise, an equirectangular projection will be used.
 /// </param>
 /// <returns>
 /// A projected map of elevation. Pixel luminosity indicates elevation relative to <see
 /// cref="Planetoid.MaxElevation"/>, with values below the midpoint indicating elevations
 /// below the mean surface.
 /// </returns>
 public static Image <L16> GetElevationMap(
     this SurfaceRegion region,
     Planetoid planet,
     int resolution,
     bool equalArea = false) => planet.GetElevationMap(resolution, region.GetProjection(planet, equalArea));
Esempio n. 9
0
    public void EarthlikePlanet()
    {
        // First run to ensure timed runs do not include any one-time initialization costs.
        _ = Planetoid.GetPlanetForSunlikeStar(out _);

        var stopwatch = new Stopwatch();

        stopwatch.Start();

        var planet = Planetoid.GetPlanetForSunlikeStar(out _);

        stopwatch.Stop();

        Assert.IsNotNull(planet);

        Console.WriteLine($"Planet generation time: {stopwatch.Elapsed:s'.'FFF} s");
        Console.WriteLine($"Radius: {planet!.Shape.ContainingRadius / 1000:N0} km");
        Console.WriteLine($"Surface area: {planet!.Shape.ContainingRadius.Square() * HugeNumberConstants.FourPi / 1000000:N0} km²");

        stopwatch.Restart();

        using (var elevationMap = planet.GetElevationMap(MapResolution))
        {
            var(winterTemperatureMap, summerTemperatureMap) = planet.GetTemperatureMaps(elevationMap, MapResolution);
            var(precipitationMaps, snowfallMaps)            = planet
                                                              .GetPrecipitationAndSnowfallMaps(winterTemperatureMap, summerTemperatureMap, MapResolution, Seasons);
            for (var i = 0; i < snowfallMaps.Length; i++)
            {
                snowfallMaps[i].Dispose();
            }
            using var precipitationMap = SurfaceMapImage.AverageImages(precipitationMaps);
            for (var i = 0; i < precipitationMaps.Length; i++)
            {
                precipitationMaps[i].Dispose();
            }
            _ = new WeatherMaps(
                planet,
                elevationMap,
                winterTemperatureMap,
                summerTemperatureMap,
                precipitationMap,
                MapResolution,
                MapProjectionOptions.Default);
            winterTemperatureMap.Dispose();
            summerTemperatureMap.Dispose();
        }

        stopwatch.Stop();

        Console.WriteLine($"Equirectangular surface map generation time: {stopwatch.Elapsed:s'.'FFF} s");

        var projection = new MapProjectionOptions(equalArea: true);

        stopwatch.Restart();

        using var elevationMapEA = planet.GetElevationMap(MapResolution, projection);
        var(winterTemperatureMapEA, summerTemperatureMapEA) = planet.GetTemperatureMaps(elevationMapEA, MapResolution, projection, projection);
        using var temperatureMapEA = SurfaceMapImage.AverageImages(winterTemperatureMapEA, summerTemperatureMapEA);
        var(precipitationMapsEA, snowfallMapsEA) = planet
                                                   .GetPrecipitationAndSnowfallMaps(winterTemperatureMapEA, summerTemperatureMapEA, MapResolution, Seasons, projection, projection);
        for (var i = 0; i < snowfallMapsEA.Length; i++)
        {
            snowfallMapsEA[i].Dispose();
        }
        using var precipitationMapEA = SurfaceMapImage.AverageImages(precipitationMapsEA);
        for (var i = 0; i < precipitationMapsEA.Length; i++)
        {
            precipitationMapsEA[i].Dispose();
        }
        var climateMapsEA = new WeatherMaps(
            planet,
            elevationMapEA,
            winterTemperatureMapEA,
            summerTemperatureMapEA,
            precipitationMapEA,
            MapResolution,
            projection);

        winterTemperatureMapEA.Dispose();
        summerTemperatureMapEA.Dispose();

        stopwatch.Stop();

        Console.WriteLine($"Cylindrical equal-area surface map generation time: {stopwatch.Elapsed:s'.'FFF} s");

        var normalizedSeaLevel = planet.SeaLevel / planet.MaxElevation;
        var elevationRange     = planet.GetElevationRange(elevationMapEA);
        var landCoords         = 0;

        if (planet.Hydrosphere?.IsEmpty == false)
        {
            for (var x = 0; x < elevationMapEA.Width; x++)
            {
                for (var y = 0; y < elevationMapEA.Height; y++)
                {
                    var value = (2.0 * elevationMapEA[x, y].PackedValue / ushort.MaxValue) - 1;
                    if (value - normalizedSeaLevel > 0)
                    {
                        landCoords++;
                    }
                }
            }
        }
        var sb = new StringBuilder();

        AddTempString(sb, temperatureMapEA);
        sb.AppendLine();
        AddTerrainString(sb, planet, elevationMapEA, landCoords);
        sb.AppendLine();
        AddClimateString(sb, elevationMapEA, normalizedSeaLevel, landCoords, climateMapsEA);
        sb.AppendLine();
        AddPrecipitationString(sb, planet, elevationMapEA, precipitationMapEA, normalizedSeaLevel, landCoords, climateMapsEA);
        Console.WriteLine(sb.ToString());
    }
Esempio n. 10
0
        public void InitializeSystem()
        {
            //Clear old data
            if (generateName)
            {
                name = (new Spaceworks.PhenomicNameGenerator()).Generate(4, 8);
            }

            DestorySystem();

            //Make the floating origin if it does not exist
            FloatingOrigin.Make();

            //Create the sun's reference (0,0,0) in the model (view not made)
            this.sun = new KeplerBody(this.SolarMass, null);

            //Create the initial states of all planetoids
            this.planetStates = new PlanetoidState[this.planetoids.Length];
            for (int i = 0; i < this.planetoids.Length; i++)
            {
                try {
                    //Init references
                    Planetoid      planet   = this.planetoids[i];
                    GameObject     planetGO = new GameObject(string.IsNullOrEmpty(planet.planetData.name) ? this.name + " - " + i : planet.planetData.name);
                    PlanetoidState state    = new PlanetoidState();
                    this.planetStates[i] = state;

                    //Init orbit model
                    state.orbit      = new KeplerOrbit(this.sun, planet.orbit);
                    state.body       = new KeplerBody(planet.mass, state.orbit);
                    state.gameobject = planetGO;

                    //Configure components
                    FloatingTransform transform = planetGO.AddComponent <FloatingTransform>();
                    transform.worldPosition = new WorldPosition(state.orbit.GetCurrentPosition());
                    state.transform         = transform;

                    CubemapMeshGenerator meshService = planetGO.AddComponent <CubemapMeshGenerator>();
                    meshService.range     = planet.mountains;
                    meshService.useSkirts = true;
                    meshService.heights   = planet.heights;
                    meshService.Init();

                    CubemapTextureService textureService = planetGO.AddComponent <CubemapTextureService>();
                    textureService.top = planet.baseMaterial;
                    textureService.top.SetTexture("_MainTex", planet.textures.top);

                    textureService.bottom = planet.baseMaterial;
                    textureService.bottom.SetTexture("_MainTex", planet.textures.bottom);

                    textureService.left = planet.baseMaterial;
                    textureService.left.SetTexture("_MainTex", planet.textures.left);

                    textureService.right = planet.baseMaterial;
                    textureService.right.SetTexture("_MainTex", planet.textures.right);

                    textureService.front = planet.baseMaterial;
                    textureService.front.SetTexture("_MainTex", planet.textures.front);

                    textureService.back = planet.baseMaterial;
                    textureService.back.SetTexture("_MainTex", planet.textures.back);

                    PlanetConfig pcc = new PlanetConfig(planet.planetData);
                    pcc.generationService = meshService;
                    pcc.textureService    = textureService;

                    Planet p = new Planet(pcc);
                    p.RenderOn(planetGO);
                    if (Camera.main)
                    {
                        p.ForceUpdateLODs(Camera.main.transform.position);
                    }

                    state.planet = p;
                }
                catch (Exception e) {
                    Debug.Log("Failed to fully instanciate planetoid: " + i + " because");
                    Debug.Log(e.Message);
                    Debug.Log(e.StackTrace);
                }
            }
        }
Esempio n. 11
0
 public void InitSetPlanetoidUniforms(Planetoid planetoid)
 {
     InitPlanetoidUniforms(planetoid);
     SetPlanetoidUniforms(planetoid);
 }
Esempio n. 12
0
 /// <summary>
 /// Determines whether the given <paramref name="moment"/> falls within the range indicated.
 /// </summary>
 /// <param name="planet">The mapped planet.</param>
 /// <param name="range">The range being interpolated.</param>
 /// <param name="moment">The time at which the determination is to be performed.</param>
 /// <returns><see langword="true"/> if the range indicates a positive result for the given
 /// <paramref name="moment"/>; otherwise <see langword="false"/>.</returns>
 public static bool GetAnnualRangeIsPositiveAtTime(
     this Planetoid planet,
     FloatRange range,
     Instant moment) => SurfaceMap.GetAnnualRangeIsPositiveAtTime(range, (float)planet.GetProportionOfYearAtTime(moment));
Esempio n. 13
0
    // -------------------------------------------------------------------------------

    public void OnSpawned(Vector3 groundNormal, PlantData plantData, GameObject dirtDecal, Planetoid planetoidOwner, bool spawnedByPlayer)
    {
        if (!Animator)
        {
            Animator = GetComponent <Animator>();
        }

        mWilteredShaderPopertyId = Shader.PropertyToID("_Wilted");
        mPlanetoidOwner          = planetoidOwner;

        mPlantManager     = PlantManager.Instance;
        PlantData         = plantData;
        mMainGrowth       = (1.0f - PlantData.InitialGrowth);
        mBeingHarvested   = false;
        mNormalisedGrowth = 0.0f;
        mGrowthTime       = 0.0f;

        mDirtDecalRenderer = dirtDecal.GetComponent <Renderer>();
        if (spawnedByPlayer)
        {
            LeanTween.scale(mDirtDecalRenderer.gameObject, mDirtDecalRenderer.transform.localScale, 1.0f);
            mDirtDecalRenderer.transform.localScale = Vector3.zero;
            AudioManager.Instance.PlayRandomSfx(MyAudioSource, 0f, "Drop1", "Drop2", "Drop3");
        }
        mDirtDecalRenderer.material.color = Color.Lerp(mPlantManager.DirtDecalUnwateredColor, mPlantManager.DirtDecalWateredColor, Mathf.Clamp01(WaterCharge));

        mSkinnedMeshRenderer = GetComponentInChildren <SkinnedMeshRenderer>();

        PlantType     = plantData.PlantType;
        mNumGrowAnims = plantData.NumGrowthAnims;
        Animator.SetInteger("GrowIndex", Random.Range(0, mNumGrowAnims));

        transform.up = GroundNormal = groundNormal;
        mSkinnedMeshRenderer.material.SetFloat(mWilteredShaderPopertyId, mWilted);
    }
 void GeneratePlanetoid()
 {
     current_planetoid = new Planetoid();
     current_planetoid.terrain_colors = possible_terrain_colors[Random.Range(0, possible_terrain_colors.Length)];
 }