20 Protons – SAM – Physics Engine – Voronoi – Initial Explore:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;
using UnityEngine.UI;

public class Edo_Voronoi : MonoBehaviour
{
    private Vector3 startPosition;
    public bool bPrint_Debug = false;

    public float radius = 1;
    public float like_to_like = 500f;
    public float opp_to_opp = -200f;

    public float centering_Mult = 1;
    private VRTK_InteractableObject vrtk_Interact_1;

    public GameObject preFab_Pos;
    public GameObject preFab_Neg;

    public GameObject instance_Location;

    [Range(-10, 10f)]
    public float restore_Coeff = 1f;

    [Range(0, 36f)]
    public float sphere_Radius = 24f;

    private GameObject[] positives = new GameObject[36];
    private GameObject[] negatives = new GameObject[36];

    public Slider pos_sld;
    public Slider neg_sld;

    public enum Handle_States
    {
        NORMAL,
        TOUCHED,
        GRABBED,
    }

    private Handle_States handle_State = Handle_States.NORMAL;

    public Color handle_Base_Col;
    public Color handle_Touched_Col;
    public Color handle_Grabbed_Col;
    private Color handle_Base_Emissive_Col;

    private VU_UI_MANAGER VU_UI;

    void Start()
    {
        startPosition = transform.position;

        vrtk_Interact_1 = GetComponent<VRTK_InteractableObject>();
        VU_UI = VU_UI_MANAGER.Instance;

        vrtk_Interact_1.InteractableObjectTouched += new InteractableObjectEventHandler(DoObject_1_Touched);
        vrtk_Interact_1.InteractableObjectUntouched += new InteractableObjectEventHandler(DoObject_1_Untouched);

        vrtk_Interact_1.InteractableObjectGrabbed += new InteractableObjectEventHandler(DoObject_1_Grabbed);
        vrtk_Interact_1.InteractableObjectUngrabbed += new InteractableObjectEventHandler(DoObject_1_Ungrabbed);

        float dp = 10.61803f;
        Vector3 vDP = Vector3.one;
        Vector3 vNegStart = dp * Vector3.right;
        for (int i = 0; i < 36; i++)
        {
            positives[i] = Instantiate(preFab_Pos, instance_Location.transform.position + vDP, Quaternion.identity);
            negatives[i] = Instantiate(preFab_Neg, instance_Location.transform.position + vNegStart + vDP, Quaternion.identity);
            vDP += dp * Vector3.up + dp*Vector3.forward;

            if (i < 4)
            {
                positives[i].SetActive(true);
                negatives[i].SetActive(true);
            }
            else
            {
                positives[i].SetActive(false);
                negatives[i].SetActive(false);
            }
        }
    }

    private void DoObject_1_Touched(object sender, InteractableObjectEventArgs e)
    {
        handle_State = Handle_States.TOUCHED;
        VU_UI.Report_Touched(vrtk_Interact_1.gameObject, e.interactingObject);
    }

    private void DoObject_1_Untouched(object sender, InteractableObjectEventArgs e)
    {
        handle_State = Handle_States.NORMAL;
        VU_UI.Report_UnTouched(vrtk_Interact_1.gameObject, e.interactingObject);
    }

    private void DoObject_1_Grabbed(object sender, InteractableObjectEventArgs e)
    {
        handle_State = Handle_States.GRABBED;
    }

    private void DoObject_1_Ungrabbed(object sender, InteractableObjectEventArgs e)
    {
        handle_State = Handle_States.NORMAL;
    }

    private bool isValid_Vector(Vector3 v)
    {
        if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public void On_Pos_Slider()
    {
        int num_pos = (int)pos_sld.value;

        float dp = 10.61803f;
        Vector3 vDP = Vector3.one;
        Vector3 vNegStart = dp * Vector3.right;

        for (int i = 0; i<36; i++)
        {
            if (i < num_pos)
            {
                positives[i].SetActive(true);
                positives[i].transform.position = instance_Location.transform.position + vDP;
                vDP += dp * Vector3.up + dp * Vector3.forward;
            }
            else
            {
                positives[i].SetActive(false);
            }
        }
    }

    public void On_Neg_Slider()
    {
        int num_neg = (int)neg_sld.value;

        float dy = 0.1f;
        float dp = 10.61803f;
        Vector3 vDP = Vector3.one;
        Vector3 vNegStart = dp * Vector3.right;

        for (int i = 0; i < 36; i++)
        {
            if (i < num_neg)
            {
                negatives[i].SetActive(true);
                negatives[i].transform.position = instance_Location.transform.position +vNegStart + vDP;
                vDP += dp * Vector3.up + dp * Vector3.forward;
            }
            else
            {
                negatives[i].SetActive(false);
            }
        }
    }

    public void On_Run_Button()
    {

    }


    public void Return_To_Start_Position()
    {
        transform.position = startPosition;
    }

    void FixedUpdate()
    {
        //public float restore_Coeff = 1f;
        //public float sphere_Radius = 24f;
        
        //Distribute around sphere - Voronoi Action
        foreach (GameObject go in positives)
        {
            if(go.activeSelf)
            {
                Rigidbody rb = go.GetComponent<Rigidbody>();
                Rigidbody rbInner;
                Vector3 vFrom;
                Vector3 vSum;
                Vector3 vRecip;

                Vector3 dist = transform.position - rb.position;

                float amt = dist.magnitude - sphere_Radius;
                rb.AddForce(amt * dist.normalized * restore_Coeff);

                foreach (GameObject gInner in positives)
                {
                    if (gInner.activeSelf)
                    {
                        vSum = Vector3.zero;
                        float r;//Radius from Neighbor

                        if (go != gInner)
                        {
                            rbInner = gInner.GetComponent<Rigidbody>();
                            vFrom = rb.position - rbInner.position;
                            r = vFrom.magnitude;
                            vRecip = (1f / r) * vFrom.normalized;
                            vSum += vRecip;
                        }
                        if (isValid_Vector(vSum))
                        {
                            rb.AddForce(like_to_like * vSum);
                        }
                    }
                }
            }
        }

        foreach (GameObject go in negatives)
        {
            if (go.activeSelf)
            {
                Rigidbody rb = go.GetComponent<Rigidbody>();
                Rigidbody rbInner;
                Vector3 vFrom;
                Vector3 vSum;
                Vector3 vRecip;

                Vector3 dist = transform.position - rb.position;

                float amt = dist.magnitude - sphere_Radius;
                rb.AddForce(amt * dist.normalized * restore_Coeff);

                foreach (GameObject gInner in negatives)
                {
                    if (gInner.activeSelf)
                    {
                        vSum = Vector3.zero;
                        float r;//Radius from Neighbor

                        if (go != gInner)
                        {
                            rbInner = gInner.GetComponent<Rigidbody>();
                            vFrom = rb.position - rbInner.position;
                            r = vFrom.magnitude;
                            vRecip = (1f / r) * vFrom.normalized;
                            vSum += vRecip;
                        }
                        if (isValid_Vector(vSum))
                        {
                            rb.AddForce(like_to_like * vSum);
                        }
                    }
                }
            }
        }
        //Opposites
        foreach (GameObject go in positives)
        {
            if (go.activeSelf)
            {
                Rigidbody rb = go.GetComponent<Rigidbody>();
                Rigidbody rbInner;
                Vector3 vFrom;
                Vector3 vSum;
                Vector3 vRecip;

                Vector3 dist = transform.position - rb.position;

                float amt = dist.magnitude - sphere_Radius;
                rb.AddForce(amt * dist.normalized * restore_Coeff);

                foreach (GameObject gInner in negatives)
                {
                    if (gInner.activeSelf)
                    {
                        vSum = Vector3.zero;
                        float r;//Radius from Neighbor

                        if (go != gInner)
                        {
                            rbInner = gInner.GetComponent<Rigidbody>();
                            vFrom = rb.position - rbInner.position;
                            r = vFrom.magnitude;
                            vRecip = (1f / r) * vFrom.normalized;
                            vSum += vRecip;
                        }
                        if (isValid_Vector(vSum))
                        {
                            rb.AddForce(-opp_to_opp * vSum);
                        }
                    }
                }
            }
        }

        foreach (GameObject go in negatives)
        {
            if (go.activeSelf)
            {
                Rigidbody rb = go.GetComponent<Rigidbody>();
                Rigidbody rbInner;
                Vector3 vFrom;
                Vector3 vSum;
                Vector3 vRecip;

                Vector3 dist = transform.position - rb.position;

                float amt = dist.magnitude - sphere_Radius;
                rb.AddForce(amt * dist.normalized * restore_Coeff);

                foreach (GameObject gInner in positives)
                {
                    if (gInner.activeSelf)
                    {
                        vSum = Vector3.zero;
                        float r;//Radius from Neighbor

                        if (go != gInner)
                        {
                            rbInner = gInner.GetComponent<Rigidbody>();
                            vFrom = rb.position - rbInner.position;
                            r = vFrom.magnitude;
                            vRecip = (1f / r) * vFrom.normalized;
                            vSum += vRecip;
                        }
                        if (isValid_Vector(vSum))
                        {
                            rb.AddForce(-opp_to_opp * vSum);
                        }
                    }
                }
            }
        }

        if (bPrint_Debug)
        {
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    //print("VN_[" + i.ToString() + "," + j.ToString() + "] points to " + vN_Points_to[i, j].ToString());
                }
            }
            bPrint_Debug = false;
        }
    }

    Color curr_Color;
    Color curr_dot_Color;
    Color targ_Color;
    Color targ_dot_Color;

    float theta = 390;
    float target_theta = 0;
    public void Animate_Handle_Material()//UI HANDLE
    {
        curr_Color = Color.Lerp(curr_Color, targ_Color, Time.deltaTime * 1.61803f);
        curr_dot_Color = Color.Lerp(curr_dot_Color, targ_dot_Color, Time.deltaTime * 1.61803f);

        if (handle_State == Handle_States.NORMAL)
        {
            //target_theta = 300;
            targ_Color = handle_Base_Col;
        }
        else if (handle_State == Handle_States.TOUCHED)
        {
            //target_theta = 390;
            targ_Color = handle_Touched_Col;
        }
        else if (handle_State == Handle_States.GRABBED)
        {
            //target_theta = 570;
            targ_Color = handle_Grabbed_Col;
        }
        Renderer rend = GetComponent<Renderer>();
        rend.material.SetColor("_Color", curr_Color);
        rend.material.SetColor("_EmissionColor", curr_Color);
    }

    private void Update()
    {
        Animate_Handle_Material();

    }
}