Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Galaxy Generation Algorithm

I'm trying to generate a set of points (represented by a Vector struct) that roughly models a spiral galaxy.

The C# code I've been playing with is below; but I can only seem to get it to generate a single 'arm' of the galaxy.

    public Vector3[] GenerateArm(int numOfStars, int numOfArms, float rotation)
    {
        Vector3[] result = new Vector3[numOfStars];
        Random r = new Random();

        float fArmAngle = (float)((360 / numOfArms) % 360);
        float fAngularSpread = 180 / (numOfArms * 2);

        for (int i = 0; i < numOfStars; i++)
        {

            float fR = (float)r.NextDouble() * 64.0f;
            float fQ = ((float)r.NextDouble() * fAngularSpread) * 1;
            float fK = 1;

            float fA = ((float)r.NextDouble() % numOfArms) * fArmAngle;


            float fX = fR * (float)Math.Cos((MathHelper.DegreesToRadians(fA + fR * fK + fQ)));
            float fY = fR * (float)Math.Sin((MathHelper.DegreesToRadians(fA + fR * fK + fQ)));

            float resultX = (float)(fX * Math.Cos(rotation) - fY * Math.Sin(rotation));
            float resultY = (float)(fY * Math.Cos(rotation) - fX * Math.Sin(rotation));

            result[i] = new Vector3(resultX, resultY, 1.0f);
        }

        return result;
    }
like image 875
Chris Bampton Avatar asked Feb 02 '23 14:02

Chris Bampton


2 Answers

Check this. It's a simulation of galaxy using density wave theory. Code is available. http://beltoforion.de/galaxy/galaxy_en.html

like image 151
sveco Avatar answered Feb 05 '23 03:02

sveco


I liked this idea so much i had to play around with it on my own and here is my result. Note that i used PointF instead of Vector3, but you should be able to search and replace and add , 0) in a few places.

PointF[] points;

private void Render(Graphics g, int width, int height)
{
    using (Brush brush = new SolidBrush(Color.FromArgb(20, 150, 200, 255)))
    {
        g.Clear(Color.Black);
        foreach (PointF point in points)
        {
            Point screenPoint = new Point((int)(point.X * (float)width), (int)(point.Y * (float)height));
            screenPoint.Offset(new Point(-2, -2));
            g.FillRectangle(brush, new Rectangle(screenPoint, new Size(4, 4)));
        }
        g.Flush();
    }
}

public PointF[] GenerateGalaxy(int numOfStars, int numOfArms, float spin, double armSpread, double starsAtCenterRatio)
{
    List<PointF> result = new List<PointF>(numOfStars);
    for (int i = 0; i < numOfArms; i++)
    {
        result.AddRange(GenerateArm(numOfStars / numOfArms, (float)i / (float)numOfArms, spin, armSpread, starsAtCenterRatio));
    }
    return result.ToArray();
}

public PointF[] GenerateArm(int numOfStars, float rotation, float spin, double armSpread, double starsAtCenterRatio)
{
    PointF[] result = new PointF[numOfStars];
    Random r = new Random();

    for (int i = 0; i < numOfStars; i++)
    {
        double part = (double)i / (double)numOfStars;
        part = Math.Pow(part, starsAtCenterRatio);

        float distanceFromCenter = (float)part;
        double position = (part * spin + rotation) * Math.PI * 2;

        double xFluctuation = (Pow3Constrained(r.NextDouble()) - Pow3Constrained(r.NextDouble())) * armSpread;
        double yFluctuation = (Pow3Constrained(r.NextDouble()) - Pow3Constrained(r.NextDouble())) * armSpread;

        float resultX = (float)Math.Cos(position) * distanceFromCenter / 2 + 0.5f + (float)xFluctuation;
        float resultY = (float)Math.Sin(position) * distanceFromCenter / 2 + 0.5f + (float)yFluctuation;

        result[i] = new PointF(resultX, resultY);
    }

    return result;
}

public static double Pow3Constrained(double x)
{
    double value = Math.Pow(x - 0.5, 3) * 4 + 0.5d;
    return Math.Max(Math.Min(1, value), 0);
}

Example:

points = GenerateGalaxy(80000, 2, 3f, 0.1d, 3);

Result: Galaxy

like image 39
Peter Avatar answered Feb 05 '23 04:02

Peter