Last active
February 10, 2023 14:05
-
-
Save nukadelic/7449f0872f708065bc1afeb19df666f7 to your computer and use it in GitHub Desktop.
Fibonacci Sphere ( Unity3D )
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
#endif | |
public class FibonacciSphere : MonoBehaviour | |
{ | |
[Range(0,500)] public int count = 200; | |
[Range(0,2f)] public float radius = 1f; | |
[HideInInspector] public float min = 0f; | |
[HideInInspector] public float max = 1f; | |
[Range(-180,180)] | |
public float angleStart = 0f; | |
[Range(0,360)] | |
public float angleRange = 360f; | |
public enum Direction { Up, Forward, Left, Right, Back, Down } | |
public Direction direction = Direction.Up; | |
/// <summary> -- golden angle in radians -- </summary> | |
static float Phi = Mathf.PI * ( 3f - Mathf.Sqrt( 5f ) ); | |
static float Pi2 = Mathf.PI * 2; | |
private void OnDrawGizmos( ) | |
{ | |
Gizmos.color = Color.red; | |
for( var i = 0; i < count; ++i ) | |
{ | |
var _p = Point( radius, i, count, min, max, angleStart, angleRange ); | |
if( direction != Direction.Up ) _p = Shift( _p, direction ); | |
Gizmos.DrawSphere( transform.position + _p, 0.04f ); | |
} | |
} | |
public static Vector3 Point( float radius , int index , int total , float min = 0f, float max = 1f , float angleStartDeg = 0f, float angleRangeDeg = 360 ) | |
{ | |
// y goes from min (-) to max (+) | |
var y = ( ( index / ( total - 1f ) ) * ( max - min ) + min ) * 2f - 1f; | |
// https://stackoverflow.com/a/26127012/2496170 | |
// y goes from 1 to -1 | |
//var y = 1f - ( i / ( count - 1f ) ) * 2f; | |
// radius at y | |
var rY = Mathf.Sqrt( 1 - y * y ); | |
// golden angle increment | |
var theta = Phi * index ; | |
if( angleStartDeg != 0 || angleRangeDeg != 360 ) | |
{ | |
theta = ( theta % ( Pi2 ) ) ; | |
theta = theta < 0 ? theta + Pi2 : theta ; | |
var a1 = angleStartDeg * Mathf.Deg2Rad; | |
var a2 = angleRangeDeg * Mathf.Deg2Rad; | |
theta = theta * a2 / Pi2 + a1; | |
} | |
var x = Mathf.Cos( theta ) * rY; | |
var z = Mathf.Sin( theta ) * rY; | |
return new Vector3( x, y, z ) * radius; | |
} | |
public static Vector3 Shift( Vector3 p, Direction direction = Direction.Up ) | |
{ | |
switch( direction ) | |
{ | |
default: | |
case Direction.Up: return new Vector3( p.x, p.y, p.z ); | |
case Direction.Right: return new Vector3( p.y, p.x, p.z ); | |
case Direction.Left: return new Vector3( -p.y, p.x, p.z ); | |
case Direction.Down: return new Vector3( p.x, -p.y, p.z ); | |
case Direction.Forward: return new Vector3( p.x, p.z, p.y ); | |
case Direction.Back: return new Vector3( p.x, p.z, -p.y ); | |
} | |
} | |
#if UNITY_EDITOR | |
[CustomEditor(typeof(FibonacciSphere))] | |
public class FibonacciSphereEditor : Editor | |
{ | |
public override void OnInspectorGUI( ) | |
{ | |
EditorGUILayout.HelpBox("This MonoBehavious is used for gizmo visualization only , " + | |
"use the static methods of the FibonacciSphere class instead", MessageType.None); | |
GUILayout.Space( 30 ); | |
base.OnInspectorGUI( ); | |
// Draw min max slider | |
var min = serializedObject.FindProperty("min"); | |
var max = serializedObject.FindProperty("max"); | |
var minVal = min.floatValue; | |
var maxVal = max.floatValue; | |
EditorGUI.BeginChangeCheck(); | |
EditorGUILayout.MinMaxSlider( "Min Max", ref minVal, ref maxVal, 0f, 1f ); | |
if( EditorGUI.EndChangeCheck() ) | |
{ | |
min.floatValue = minVal; | |
max.floatValue = maxVal; | |
} | |
serializedObject.ApplyModifiedProperties(); | |
} | |
} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment