Evenly distributed points on a surface of a sphere

If anybody should need a script (UnityScript) for evenly distributing points on a surface of a sphere then here it is.

Save as PointsOnSphere.js

Edit: Would be interesting to see the difference in execution time between this UnityScript version and in pure c# (if anybody wants to do it :wink: )

/*
	Points on a sphere
	Adaptation from Patrick Boucher: [url]http://www.xsi-blog.com/archives/115[/url]
	
	Description:
	If you need to distribute objects evenly on the surface of a sphere then this script could be helpful.
	
	Usage:
	Simply attach this script to a GameObject, edit the scaling value and the numbers of spheres you want created.
	The spheres are then created as children.
	
	Philipp Smolka
	07.07.09

*/

function Start() {
	var scaling :  float = 10;
	var pts : Vector3[] = PointsOnSphere(1024);
	var uspheres = new Array();
	var i : int = 0;
	
	for (var value : Vector3 in pts){
		uspheres.Push(GameObject.CreatePrimitive(PrimitiveType.Sphere));
		uspheres[i].transform.parent = transform;
		uspheres[i].transform.position = value * scaling;
		i++;
	}
}

function PointsOnSphere(n) {
	var upts = new Array();
	var inc : float = Mathf.PI * (3 - Mathf.Sqrt(5));
	var off : float = 2.0 / n;
	var x : float;
	var y : float;
	var z : float;
	var r : float;
	var phi : float;
	
	for (var k = 0; k < n; k++){
		y = k * off - 1 + (off /2);
		r = Mathf.Sqrt(1 - y * y);
		phi = k * inc;
		x = Mathf.Cos(phi) * r;
		z = Mathf.Sin(phi) * r;
		
		upts.Push(Vector3(x, y, z));
	}
	var pts : Vector3[] = upts.ToBuiltin(Vector3);
	return pts;
}
function Update () {
}

best regards
Preludian

4 Likes

a bit late but this is awesome thanks!

Thank you for this :slight_smile:

Here’s a c# version in case anyone needs it:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class PointDistribution : MonoBehaviour
{
    void Start ()
    {
        float scaling = 32;
        Vector3[] pts = PointsOnSphere(128);
        List<GameObject> uspheres = new List<GameObject>();
        int i = 0;
       
        foreach (Vector3 value in pts)
        {
            uspheres.Add(GameObject.CreatePrimitive(PrimitiveType.Sphere));
            uspheres[i].transform.parent = transform;
            uspheres[i].transform.position = value * scaling;
            i++;
        }
    }

    Vector3[] PointsOnSphere(int n)
    {
        List<Vector3> upts = new List<Vector3>();
        float inc = Mathf.PI * (3 - Mathf.Sqrt(5));
        float off = 2.0f / n;
        float x = 0;
        float y = 0;
        float z = 0;
        float r = 0;
        float phi = 0;
       
        for (var k = 0; k < n; k++){
            y = k * off - 1 + (off /2);
            r = Mathf.Sqrt(1 - y * y);
            phi = k * inc;
            x = Mathf.Cos(phi) * r;
            z = Mathf.Sin(phi) * r;
           
            upts.Add(new Vector3(x, y, z));
        }
        Vector3[] pts = upts.ToArray();
        return pts;
    }
}
16 Likes

Awsome!

Now how do I replace each point with a button?

This is years later, but since this is one of the places that Google took me when researching the problem I thought I’d share here. I took a different approach to solving this for my own game, and since there wasn’t any recent scripts that I had any luck with. I ended up taking the final script and posting it in the Asset Store if anyone in the future is interested: ShapeCover | Modeling | Unity Asset Store

2 Likes

You don’t need to replace. You initiate an object using the point as a coordinate.

When I use this the points appear to be evenly distributed, however they are not on the sphere. They are off and down to the right completely off the sphere.

FIXED

I just changed line 18 to uspheres.transform.localposition = value * scaling;
Edit #2:
If previous doesnt fix the issue, instead of applying scaling on line 18 do this
inside of pointsOnSphere and pass scaling to the method
```csharp
*Vector3 b = new Vector3(x,y,z);
Vector3 a = new Vector3(0,0,0);
Vector3 correction = (b - a).normalized * scaling/2;

upts.Add(correction);
_
```*_

2 Likes

Could someone help me figure out how to get triangles from this for a mesh?

If you need a spherical mesh, then why not simply create a sphere gameobject? This here is rather helpful if you have a sphere (or sphere-like) object and want to place something on or around it - like for example trees on a planet.

Mostly because I like the challenge! But for practical reasons, I want to simulate each point on the sphere separately to create a blob-like shape. Each point is connected to a center point and to it’s neighbors via springs.

hi from 2021 :slight_smile: what is the meaning of these mathematical calculations? could you explain what is going on in for loop?

hi @anon_44140449 is this used to calculate a fibonnacci sphere?

My attempt at a sphere slice instead of a full sphere (from altitude and azimuth angles) :

    public Vector3[] GenerateSphereSclice(float _altitudeAngle , float _azimuthAngle)
    {
        List<Vector3> ptsList = new List<Vector3>();
        int precision = 11;

        float sideInc = (_altitudeAngle / precision);
        float topInc = (_azimuthAngle / (precision * 4));
        float range = 5;

        for (int h = 0 ; h < precision; h++)
        {
            for (int k = 0 ; k < (precision * 4); k++)
            {
                float theta = h * sideInc * Mathf.Deg2Rad;
                float phi = k * topInc * Mathf.Deg2Rad;

                float x = range * Mathf.Sin(phi) * Mathf.Cos(theta);
                float y = range * Mathf.Sin(phi) * Mathf.Sin(theta);
                float z = range * Mathf.Cos(phi);

                ptsList.Add(new Vector3(x, y, z));

            }
        }

        return ptsList.ToArray();
    }

I know this is awfully old but could someone explain the math in this code, please?
Thank you.