Search code examples
c#unity-game-enginemathprocedural-generation

Formula to make the ends of the arms of a spiral galaxy less dense


I want to make a spiral galaxy in Unity 3D using C# ( i use a derived logarithmic spiral ). I want to set the end of the arms less dense than the middle, but mine are the same density throughout.

I want this:

desired galazy appearance

I have this result currently:

actual galaxy appearance
(source: noelshack.com)

I have absolutely no idea to how do that but the value used for dispersion is randomOffsetXY.


public int numArms = 5;
public float armOffsetMax = 0.5f;
public float rotationFactor = 5;
public float randomOffsetXY = 0.02f;
public float percentStarInCentre = 5;



for (int i = 0; i < PixelMath.instanceStarCount; i++)
        {
            if(type == GalaxyTypes.Spiral)
            {
                float distance = Random.value;
                distance = Mathf.Pow (distance, PixelMath.percentStarInCentre / 100) ;
                
                      
                // Choose an angle between 0 and 2 * PI.
                float angle = Random.value * 2 * Mathf.PI;
                float armOffset = Random.value * PixelMath.armsOffetSetMax;

                armOffset = armOffset - PixelMath.armsOffetSetMax / 2;
                armOffset = armOffset * (1 / distance);

                float squaredArmOffset = Mathf.Pow (armOffset, 2);

                if (armOffset < 0)
                    squaredArmOffset = squaredArmOffset * -1;
                armOffset = squaredArmOffset;

                float rotation = distance * PixelMath.rotationFactor;

                // Compute the angle of the arms.
                angle = (int) (angle / armSeparationDistance ) * armSeparationDistance + armOffset + rotation;



                // Convert polar coordinates to 2D cartesian coordinates.
                float starX =  Mathf.Sin (angle) * distance;
                float starZ =  Mathf.Cos (angle) * distance;
                float starY = 0;
                



Solution

  • Change the line from

    distance = Mathf.Pow (distance, PixelMath.percentStarInCentre / 100) ;
    

    to something with a second argument that is larger than 1. So something like

    distance = Mathf.Pow (distance, 2f);
    

    or depending on how exaggerated of an effect you want,

    distance = Mathf.Pow (distance, 5f);
    

    If you want to have less of a cluster in the center, you will want a mix of linear and parabolic:

    float pow
    float distance = Random.value;
    float slopeMod = 0.8f; // between 0 and 1, higher is more linear
    distance = Mathf.Pow(distance, 2f) *(1-slopeMod) + distance*slopeMod;
    

    The link you posted says about squaring the distance:

    Now it’s starting to come together. We can see clearly defined arms in our galaxy, which have clearly defined spines running down the middle. At this point, you might notice that due to our squaring, the futher areas of the arms appear more dense than they were before. Let’s resolve this by pulling all the stars closer to the center with a distance squaring operation, the same way we just pulled stars closer to their arms:

    saying that doing so will take the output from something that looks like what you currently have:

    galaxy with dense arms

    To something with a lower comparative density of the outer parts of the arms like you want:

    galaxy with sparse arms