Unity Native Spline

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
using UnityEngine.Serialization;

[AddComponentMenu("Miscellaneous/Bezier Spline")]
public class Bezier3DSpline : MonoBehaviour{

	public int KnotCount { get { return curves.Length+(closed?0:1); } }
	public int CurveCount { get { return curves.Length; } }
    /// <summary> Interpolation steps per curve </summary>
    public int cacheDensity { get { return _cacheDensity; } }
    [SerializeField] protected int _cacheDensity = 60;
    /// <summary> Whether the end of the spline connects to the start of the spline </summary>
    public bool closed { get { return _closed; } }
    [SerializeField] protected bool _closed = false;
    /// <summary> Sum of all curve lengths </summary>
    public float totalLength { get { return _totalLength; } }
    [SerializeField] protected float _totalLength = 2.370671f;
    /// <summary> Curves of the spline </summary>
    [SerializeField] protected Bezier3DCurve[] curves = new Bezier3DCurve[] { new Bezier3DCurve( new Vector3(-1,0,0), new Vector3(1,0,1), new Vector3(-1,0,-1), new Vector3(1,0,0), 60)};
    /// <summary> Automatic knots don't have handles. Instead they have a percentage and adjust their handles accordingly. A percentage of 0 indicates that this is not automatic </summary>
    [SerializeField] protected List<float> autoKnot = new List<float>() { 0, 0 };
    [SerializeField] protected List<NullableQuaternion> orientations = new List<NullableQuaternion>() { new NullableQuaternion(null), new NullableQuaternion(null) };
    [SerializeField] protected Vector3[] tangentCache = new Vector3[0];

    #region Public methods

    #region Public: get

    public float DistanceToTime(float dist) {
        float t = 0f;
        for (int i = 0; i < CurveCount; i++) {
            if (curves[i].length < dist) {
                dist -= curves[i].length;
                t += 1f / CurveCount;
            }
            else {
                t += curves[i].Dist2Time(dist) / CurveCount;
                return t;
            }
        }
        return 1f;
    }

    /// <summary> Get <see cref="Bezier3DCurve"/> by index </summary>
    public Bezier3DCurve GetCurve(int i) {
        if (i >= CurveCount || i < 0) throw new System.IndexOutOfRangeException("Cuve index " + i + " out of range");
        return curves[i];
    }

    /// <summary> Return <see cref="Knot"/> info in local coordinates </summary>
    public Knot GetKnot(int i) {
        if (i == 0) {
            if (closed) return new Knot(curves[0].a, curves[CurveCount - 1].c, curves[0].b, autoKnot[i], orientations[i].NullableValue);
            else return new Knot(curves[0].a, Vector3.zero, curves[0].b, autoKnot[i], orientations[i].NullableValue);
        }
        else if (i == CurveCount) {
            return new Knot(curves[i - 1].d, curves[i - 1].c, Vector3.zero, autoKnot[i], orientations[i].NullableValue);
        }
        else {
            return new Knot(curves[i].a, curves[i - 1].c, curves[i].b, autoKnot[i], orientations[i].NullableValue);
        }
    }

    #region Public get: Forward
    /// <summary> Return forward vector at set distance along the <see cref="Bezier3DSpline"/>. </summary>
    public Vector3 GetForward(float dist) {
        return transform.TransformDirection(GetForwardLocal(dist));
    }

    /// <summary> Return forward vector at set distance along the <see cref="Bezier3DSpline"/> in local coordinates. </summary>
    public Vector3 GetForwardLocal(float dist) {
        Bezier3DCurve curve = GetCurveDistance(dist, out dist);
        return curve.GetForward(curve.Dist2Time(dist));
    }

    /// <summary> Return forward vector at set distance along the <see cref="Bezier3DSpline"/>. Uses approximation. </summary>
    public Vector3 GetForwardFast(float dist) {
        return transform.TransformDirection(GetForwardLocalFast(dist));
    }

    /// <summary> Return forward vector at set distance along the <see cref="Bezier3DSpline"/> in local coordinates. Uses approximation. </summary>
    public Vector3 GetForwardLocalFast(float dist) {
        Bezier3DCurve curve = GetCurveDistance(dist, out dist);
        return curve.GetForwardFast(curve.Dist2Time(dist));
    }
    #endregion

    #region Public get: Up
    /// <summary> Return up vector at set distance along the <see cref="Bezier3DSpline"/>. </summary>
    public Vector3 GetUp(float dist) {
        return GetUp(dist, GetForward(dist), false);
    }

    /// <summary> Return up vector at set distance along the <see cref="Bezier3DSpline"/> in local coordinates. </summary>
    public Vector3 GetUpLocal(float dist) {
        return GetUp(dist, GetForward(dist), true);
    }
    #endregion

    #region Public get: Point
    /// <summary> Return up vector at set distance along the <see cref="Bezier3DSpline"/>. </summary>
    public Vector3 GetPoint(float dist) {
        Bezier3DCurve curve = GetCurveDistance(dist, out dist);
        return transform.TransformPoint(curve.GetPoint(curve.Dist2Time(dist)));
    }

    /// <summary> Return point at lerped position where 0 = start, 1 = end </summary>
    public Vector3 GetPointLocal(float dist) {
        Bezier3DCurve curve = GetCurveDistance(dist, out dist);
        return curve.GetPoint(curve.Dist2Time(dist));
    }
    #endregion

    #region Public get: Orientation
    public Quaternion GetOrientation(float dist) {
        Vector3 forward = GetForward(dist);
        Vector3 up = GetUp(dist, forward, false);
        if (forward.sqrMagnitude != 0) return Quaternion.LookRotation(forward, up);
        else return Quaternion.identity;
    }

    public Quaternion GetOrientationFast(float dist) {
        Vector3 forward = GetForwardFast(dist);
        Vector3 up = GetUp(dist, forward, false);
        if (forward.sqrMagnitude != 0) return Quaternion.LookRotation(forward, up);
        else return Quaternion.identity;
    }

    public Quaternion GetOrientationLocal(float dist) {
        Vector3 forward = GetForwardLocal(dist);
        Vector3 up = GetUp(dist, forward, true);
        if (forward.sqrMagnitude != 0) return Quaternion.LookRotation(forward, up);
        else return Quaternion.identity;
    }

    public Quaternion GetOrientationLocalFast(float dist) {
        Vector3 forward = GetForwardLocalFast(dist);
        Vector3 up = GetUp(dist, forward, true);
        if (forward.sqrMagnitude != 0) return Quaternion.LookRotation(forward, up);
        else return Quaternion.identity;
    }
    #endregion

    #endregion

    #region Public: Set
    /// <summary> Setting spline to closed will generate an extra curve, connecting end point to start point </summary>
    public void SetClosed(bool closed) {
        if (closed != _closed) {
            _closed = closed;
            if (closed) {
                List<Bezier3DCurve> curveList = new List<Bezier3DCurve>(curves);
                curveList.Add(new Bezier3DCurve(curves[CurveCount - 1].d, -curves[CurveCount - 1].c, -curves[0].b, curves[0].a, cacheDensity));
                curves = curveList.ToArray();
            }
            else {
                List<Bezier3DCurve> curveList = new List<Bezier3DCurve>(curves);
                curveList.RemoveAt(CurveCount - 1);
                curves = curveList.ToArray();
            }
            _totalLength = GetTotalLength();
        }
    }

    /// <summary> Recache all individual curves with new step amount </summary> 
    /// <param name="density"> Number of steps per curve </param>
    public void SetCacheDensity(int steps) {
        _cacheDensity = steps;
        for (int i = 0; i < CurveCount; i++) {
            curves[i] = new Bezier3DCurve(curves[i].a, curves[i].b, curves[i].c, curves[i].d, _cacheDensity);
        }
        _totalLength = GetTotalLength();
    }

    public void RemoveKnot(int i) {
        if (i == 0) {
            Knot knot = GetKnot(1);

            List<Bezier3DCurve> curveList = new List<Bezier3DCurve>(curves);
            curveList.RemoveAt(0);
            curves = curveList.ToArray();

            autoKnot.RemoveAt(0);
            orientations.RemoveAt(0);

            SetKnot(0, knot);
        }
        else if (i == CurveCount) {

            List<Bezier3DCurve> curveList = new List<Bezier3DCurve>(curves);
            curveList.RemoveAt(i - 1);
            curves = curveList.ToArray();

            autoKnot.RemoveAt(i);
            orientations.RemoveAt(i);

            if (autoKnot[KnotCount - 1] != 0) SetKnot(KnotCount - 1, GetKnot(KnotCount - 1));
        }
        else {
            int preCurveIndex, postCurveIndex;
            GetCurveIndicesForKnot(i, out preCurveIndex, out postCurveIndex);

            Bezier3DCurve curve = new Bezier3DCurve(curves[preCurveIndex].a, curves[preCurveIndex].b, curves[postCurveIndex].c, curves[postCurveIndex].d, cacheDensity);

            curves[preCurveIndex] = curve;

            List<Bezier3DCurve> curveList = new List<Bezier3DCurve>(curves);
            curveList.RemoveAt(postCurveIndex);
            curves = curveList.ToArray();

            autoKnot.RemoveAt(i);
            orientations.RemoveAt(i);

            int preKnotIndex, postKnotIndex;
            GetKnotIndicesForKnot(i, out preKnotIndex, out postKnotIndex);

            SetKnot(preKnotIndex, GetKnot(preKnotIndex));
        }
    }

    public void AddKnot(Knot knot) {
        Bezier3DCurve curve = new Bezier3DCurve(curves[CurveCount - 1].d, -curves[CurveCount - 1].c, knot.handleIn, knot.position, cacheDensity);

        List<Bezier3DCurve> curveList = new List<Bezier3DCurve>(curves);
        curveList.Add(curve);
        curves = curveList.ToArray();

        autoKnot.Add(knot.auto);
        orientations.Add(knot.orientation);
        SetKnot(KnotCount - 1, knot);
    }

    public void InsertKnot(int i, Knot knot) {
        Bezier3DCurve curve;
        if (i == 0) curve = new Bezier3DCurve(knot.position, knot.handleOut, -curves[0].b, curves[0].a, cacheDensity);
        else if (i == CurveCount) curve = GetCurve(i - 1);
        else curve = GetCurve(i);

        List<Bezier3DCurve> curveList = new List<Bezier3DCurve>(curves);
        curveList.Insert(i, curve);
        curves = curveList.ToArray();

        autoKnot.Insert(i, knot.auto);
        orientations.Insert(i, knot.orientation);
        SetKnot(i, knot);
    }

    /// <summary> Set Knot info in local coordinates </summary>
    public void SetKnot(int i, Knot knot) {
        //If knot is set to auto, adjust handles accordingly
        orientations[i] = knot.orientation;
        autoKnot[i] = knot.auto;
        if (knot.auto != 0) AutomateHandles(i, ref knot);

        //Automate knots around this knot
        int preKnotIndex, postKnotIndex;
        GetKnotIndicesForKnot(i, out preKnotIndex, out postKnotIndex);

        Knot preKnot = new Knot();
        if (preKnotIndex != -1) {
            preKnot = GetKnot(preKnotIndex);
            if (preKnot.auto != 0) {
                int preKnotPreCurveIndex, preKnotPostCurveIndex;
                GetCurveIndicesForKnot(preKnotIndex, out preKnotPreCurveIndex, out preKnotPostCurveIndex);
                if (preKnotPreCurveIndex != -1) {
                    AutomateHandles(preKnotIndex, ref preKnot, curves[preKnotPreCurveIndex].a, knot.position);
                    curves[preKnotPreCurveIndex] = new Bezier3DCurve(curves[preKnotPreCurveIndex].a, curves[preKnotPreCurveIndex].b, preKnot.handleIn, preKnot.position, cacheDensity);
                }
                else {
                    AutomateHandles(preKnotIndex, ref preKnot, Vector3.zero, knot.position);
                }
            }
        }

        Knot postKnot = new Knot();
        if (postKnotIndex != -1) {
            postKnot = GetKnot(postKnotIndex);
            if (postKnot.auto != 0) {
                int postKnotPreCurveIndex, postKnotPostCurveIndex;
                GetCurveIndicesForKnot(postKnotIndex, out postKnotPreCurveIndex, out postKnotPostCurveIndex);
                if (postKnotPostCurveIndex != -1) {
                    AutomateHandles(postKnotIndex, ref postKnot, knot.position, curves[postKnotPostCurveIndex].d);
                    curves[postKnotPostCurveIndex] = new Bezier3DCurve(postKnot.position, postKnot.handleOut, curves[postKnotPostCurveIndex].c, curves[postKnotPostCurveIndex].d, cacheDensity);
                }
                else {
                    AutomateHandles(postKnotIndex, ref postKnot, knot.position, Vector3.zero);
                }
            }
        }

        //Get the curve indices in direct contact with knot
        int preCurveIndex, postCurveIndex;
        GetCurveIndicesForKnot(i, out preCurveIndex, out postCurveIndex);

        //Adjust curves in direct contact with the knot
        if (preCurveIndex != -1) curves[preCurveIndex] = new Bezier3DCurve(preKnot.position, preKnot.handleOut, knot.handleIn, knot.position, cacheDensity);
        if (postCurveIndex != -1) curves[postCurveIndex] = new Bezier3DCurve(knot.position, knot.handleOut, postKnot.handleIn, postKnot.position, cacheDensity);

        _totalLength = GetTotalLength();

    }

    /// <summary> Flip the spline </summary>
    public void Flip() {
        Bezier3DCurve[] curves = new Bezier3DCurve[CurveCount];
        for (int i = 0; i < CurveCount; i++) {
            curves[CurveCount - 1 - i] = new Bezier3DCurve(this.curves[i].d, this.curves[i].c, this.curves[i].b, this.curves[i].a, cacheDensity);
        }
        this.curves = curves;
        autoKnot.Reverse();
        orientations.Reverse();
    }
    #endregion

    #endregion

    public struct Knot {
        public Vector3 position;
        public Vector3 handleIn;
        public Vector3 handleOut;
        public float auto;
        public Quaternion? orientation;

        /// <summary> Constructor </summary>
        /// <param name="position">Position of the knot local to spline transform</param>
        /// <param name="handleIn">Left handle position local to knot position</param>
        /// <param name="handleOut">Right handle position local to knot position</param>
        /// <param name="automatic">Any value above 0 will result in an automatically configured knot (ignoring handle inputs)</param>
        public Knot(Vector3 position, Vector3 handleIn, Vector3 handleOut, float automatic = 0f, Quaternion? orientation = null) {
            this.position = position;
            this.handleIn = handleIn;
            this.handleOut = handleOut;
            this.auto = automatic;
            this.orientation = orientation;
        }
    }

    #region Private methods
    private Vector3 GetUp(float dist, Vector3 tangent, bool local) {
        float t = DistanceToTime(dist);
        t *= CurveCount;

        Quaternion rot_a = Quaternion.identity, rot_b = Quaternion.identity;
        int t_a = 0, t_b = 0;

        //Find preceding rotation
        for (int i = Mathf.Min((int)t, CurveCount); i >= 0; i--) {
            i = (int)Mathf.Repeat(i, KnotCount - 1);
            if (orientations[i].HasValue) {
                rot_a = orientations[i].Value;
                rot_b = orientations[i].Value;
                t_a = i;
                t_b = i;
                break;
            }
        }
        //Find proceding rotation
        for (int i = Mathf.Max((int)t + 1, 0); i < orientations.Count; i++) {
            if (orientations[i].HasValue) {
                rot_b = orientations[i].Value;
                t_b = i;
                break;
            }
        }
        t = Mathf.InverseLerp(t_a, t_b, t);
        Quaternion rot = Quaternion.Lerp(rot_a, rot_b, t);
        if (!local) rot = transform.rotation * rot;
        //Debug.Log(t_a + " / " + t_b + " / " + t);
        return Vector3.ProjectOnPlane(rot * Vector3.up, tangent).normalized;
    }

    /// <summary> Get the curve indices in direct contact with knot </summary>
    private void GetCurveIndicesForKnot(int knotIndex, out int preCurveIndex, out int postCurveIndex) {
        //Get the curve index in direct contact with, before the knot
        preCurveIndex = -1;
        if (knotIndex != 0) preCurveIndex = knotIndex - 1;
        else if (closed) preCurveIndex = CurveCount - 1;

        //Get the curve index in direct contact with, after the knot
        postCurveIndex = -1;
        if (knotIndex != CurveCount) postCurveIndex = knotIndex;
        else if (closed) postCurveIndex = 0;
    }

    /// <summary> Get the knot indices in direct contact with knot </summary>
    private void GetKnotIndicesForKnot(int knotIndex, out int preKnotIndex, out int postKnotIndex) {
        //Get the curve index in direct contact with, before the knot
        preKnotIndex = -1;
        if (knotIndex != 0) preKnotIndex = knotIndex - 1;
        else if (closed) preKnotIndex = KnotCount - 1;

        //Get the curve index in direct contact with, after the knot
        postKnotIndex = -1;
        if (knotIndex != KnotCount - 1) postKnotIndex = knotIndex + 1;
        else if (closed) postKnotIndex = 0;
    }

    private Bezier3DCurve GetCurve(float splineT, out float curveT) {
        splineT *= CurveCount;
        for (int i = 0; i < CurveCount; i++) {
            if (splineT > 1f) splineT -= 1f;
            else {
                curveT = splineT;
                return curves[i];
            }
        }
        curveT = 1f;
        return curves[CurveCount - 1];
    }

    private Bezier3DCurve GetCurveDistance(float splineDist, out float curveDist) {
        for (int i = 0; i < CurveCount; i++) {
            if (curves[i].length < splineDist) splineDist -= curves[i].length;
            else {
                curveDist = splineDist;
                return curves[i];
            }
        }
        curveDist = curves[CurveCount -1].length;
        return curves[CurveCount - 1];
    }

    /// <summary> Automate handles based on previous and next point positions </summary>
    private void AutomateHandles(int i, ref Knot knot) {
        //Terminology: Points are referred to as A B and C
        //A = prev point, B = current point, C = next point

        Vector3 prevPos;
        if (i != 0) prevPos = curves[i - 1].a;
        else if (closed) prevPos = curves[CurveCount - 1].a;
        else prevPos = Vector3.zero;

        Vector3 nextPos;
        if (i != KnotCount - 1) nextPos = curves[i].d;
        else if (closed) nextPos = curves[0].a;
        else nextPos = Vector3.zero;

        AutomateHandles(i, ref knot, prevPos, nextPos);
    }

    /// <summary> Automate handles based on previous and next point positions </summary>
    private void AutomateHandles(int i, ref Knot knot, Vector3 prevPos, Vector3 nextPos) {
        //Terminology: Points are referred to as A B and C
        //A = prev point, B = current point, C = next point
        float amount = knot.auto;

        //Calculate directional vectors
        Vector3 AB = knot.position - prevPos;
        Vector3 CB = knot.position - nextPos;
        //Calculate the across vector
        Vector3 AB_CB = (CB.normalized - AB.normalized).normalized;

        if (!closed) {
            if (i == 0) {
                knot.handleOut = CB * -amount;
            }
            else if (i == CurveCount) {
                knot.handleIn = AB * -amount;
            }
            else {
                knot.handleOut = -AB_CB * CB.magnitude * amount;
                knot.handleIn = AB_CB * AB.magnitude * amount;
            }
        }
        else {
            if (KnotCount == 2) {
                Vector3 left = new Vector3(AB.z, 0,-AB.x) * amount;
                if (i == 0) {
                    knot.handleIn = left;
                    knot.handleOut = -left;
                }
                if (i == 1) {
                    knot.handleIn = left;
                    knot.handleOut = -left;
                }
            }
            else {
            knot.handleIn = AB_CB * AB.magnitude * amount;
            knot.handleOut = -AB_CB * CB.magnitude * amount;
            }
        }
    }

    private float GetTotalLength() {
        float length = 0f;
        for (int i = 0; i < CurveCount; i++) {
            length += curves[i].length;
        }
        return length;
    }
    #endregion

    /// <summary> Unity doesn't support serialization of nullable types, so here's a custom struct that does exactly the same thing </summary>
    [Serializable]
    protected struct NullableQuaternion {
        public Quaternion Value { get { return rotation; } }
        public Quaternion? NullableValue { get { if (hasValue) return rotation; else return null; } }
        public bool HasValue { get { return hasValue; } }

        [SerializeField] private Quaternion rotation;
        [SerializeField] private bool hasValue;

        public NullableQuaternion(Quaternion? rot) {
            rotation = rot.HasValue?rot.Value:Quaternion.identity;
            hasValue = rot.HasValue;
        }

        //  User-defined conversion from nullable type to NullableQuaternion
        public static implicit operator NullableQuaternion(Quaternion? r) {
            return new NullableQuaternion(r);
        }
    }
#if UNITY_EDITOR
    void OnDrawGizmos() {
        //Set color depending on selection
        if (Array.IndexOf(UnityEditor.Selection.gameObjects, gameObject) >= 0) {
            Gizmos.color = Color.yellow;
        } else  Gizmos.color = new Color(1, 0.6f, 0f);

        //Loop through each curve in spline
        for (int i = 0; i < CurveCount; i++) {
            Bezier3DCurve curve = GetCurve(i);

            //Get curve in world space
            Vector3 a, b, c, d;
            a = transform.TransformPoint(curve.a);
            b = transform.TransformPoint(curve.b + curve.a);
            c = transform.TransformPoint(curve.c + curve.d);
            d = transform.TransformPoint(curve.d);

            int segments = 50;
            float spacing = 1f / segments;
            Vector3 prev = Bezier3DCurve.GetPoint(a, b, c, d, 0f);
            for (int k = 0; k <= segments; k++) {
                Vector3 cur = Bezier3DCurve.GetPoint(a, b, c, d, k * spacing);
                Gizmos.DrawLine(prev, cur);
                prev = cur;
            }
        }
    }
#endif
}

 

Wave Fields WR







 







 




https://youtu.be/ziarrVCK0G4




https://youtu.be/oTNI8hpWUrw




 

 

 

 

 

FOCUS ANDROID DEBUG BRIDGE QUICK TIPS

 To load apps onto your Focus device, we suggest using Android Debug Bridge (adb) or your favorite command line tool. For more information refer to the Android Debug Bridge User Guide.

 

  You can use Terminal from your desktop or from within Android Studio to navigate to and utilize the debug bridge. (NOTE: On a Mac in order to use adb, you must type “./adb” and then the command each time).

For example to show connected devices:

  “adb devices”

  To install an app on a connected device:

“adb install [directory location of apk]”

 If an app is already installed, and you wish to replace it:

“adb install -r [directory location of apk]”

To uninstall an app from a connected device:

“adb uninstall com.CompanyName.AppName”

Even more Tips:

# set and start launcher:
adb shell cmd package set-home-activity com.htc.mobilevr.launcher/com.htc.vr.unity.WVRUnityVRActivity
adb shell am start -n com.htc.mobilevr.launcher/com.htc.vr.unity.WVRUnityVRActivity

 

# reset launcher back to the Android phone launcher:
adb shell cmd package set-home-activity com.android.launcher/com.android.launcher2.Launcher
adb shell am start -n com.android.launcher/com.android.launcher2.Launcher

 

# run an app:
adb shell am start -n <package-name>/<activity-name>
# e.g. adb shell am start -n com.htc.bowshot_3DOF/com.htc.vr.unity.WVRUnityVRActivity

 

# list 3rd party installed packages:
adb shell cmd package list packages -3

 

# find activity of an installed package: (from an apk: aapt dump badging yourapp.apk)
adb shell cmd package resolve-activity –brief <package-name>

 

# uninstall a package e.g. Vysor:
adb uninstall com.koushikdutta.vysor

 

# turn bluetooth on:
adb root
adb shell service call bluetooth_manager 6

# use 8 to turn off

# for wifi use: adb shell svc wifi enable # or disable
adb unroot

 

# power down:
adb shell reboot -p

 

# check battery level:
adb shell “dumpsys battery | grep level”

 

# adb over wifi (setup wifi connection first):
# find ip address:
adb shell “ifconfig wlan0 | grep ‘inet addr:'”

# restart adb over wifi:
adb tcpip 5555

# connect over wifi: (you can now disconnect usb cable)
adb connect <ip address>:5555

# to revert to usb:
adb usb # or just reboot

CODE REFERENCE

Unity Native Spline

 

 

 

SPHERE EXPANDER – FROM Fundamental Flower

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ProceduralToolkit;
using UnityEngine.UI;
using System;
using ArgosTweenSpacePuppy;
using VRTK;
using System.IO;
using UnityEngine.EventSystems;
using System.Linq;

public class Sphere_Expander : MonoBehaviour
{
    public bool bSeparate_Faces = false;
    public bool bDrawTetrahedron = false;

    public int totalVerts = 0;
    public int filteredVerts = 0;

    public int vSort_Count_0;
    public int vSort_Count_1;
    public int vSort_Count_2;

    private ArgosMeshDraft   aMD_TetraTerrean;
    private ArgosMeshDraft   aMD_TT_Sleeve;
    private ArgosMeshDraft[] aMD_tt_Faces = new ArgosMeshDraft[4];
    private GameObject[]     tt_Faces = new GameObject[4];
    private ArgosMeshDraft   aMD_Spheres;
    private ArgosMeshDraft   cylinder_MD;
    private ArgosMeshDraft   scythe_MD;
    private GameObject       scythe_GO;
    public  Color            col_edge_Cylinder;
    public  Color            col_Sphere;
    private GameObject[]     spheres = new GameObject[4];
    private Vector3[]        sphere_pos = new Vector3[4];
    public  GameObject       meshPF;
    public  GameObject       tetra_Vert_GOPF;
    private GameObject[]     tetra_Verts_GO = new GameObject[4];
    private GameObject[]     tetra_Edges    = new GameObject[6];
    private GameObject       TetraTerrien_GO;
    private GameObject       TT_Sleeve_GO;

    public float[] lengths = new float[256];
    public float[] hyperbola_of_R = new float[256];

    public int all_Shape_Depth = 4;

    Vector3[] vC = new Vector3[4];

    public class Vector_Sort
    {
        public Vector3 vert;
        public float dist = 0;
        public int vIDX = 0;
    }

    internal class PlaneHelper
    {
        /// <summary>
        /// Returns a value indicating what side (positive/negative) of a plane a point is
        /// </summary>
        /// <param name="point">The point to check with</param>
        /// <param name="plane">The plane to check against</param>
        /// <returns>Greater than zero if on the positive side, less than zero if on the negative size, 0 otherwise</returns>
        public static float ClassifyPoint(ref Vector3 point, ref Plane plane)
        {
            return point.x * plane.Normal.x + point.y * plane.Normal.y + point.z * plane.Normal.z + plane.D;
        }

        /// <summary>
        /// Returns the perpendicular distance from a point to a plane
        /// </summary>
        /// <param name="point">The point to check</param>
        /// <param name="plane">The place to check</param>
        /// <returns>The perpendicular distance from the point to the plane</returns>
        public static float PerpendicularDistance(ref Vector3 point, ref Plane plane)
        {
            // dist = (ax + by + cz + d) / sqrt(a*a + b*b + c*c)
            return Mathf.Abs((plane.Normal.x * point.x + plane.Normal.y * point.y + plane.Normal.z * point.z)
                                    / Mathf.Sqrt(plane.Normal.x * plane.Normal.x + plane.Normal.y * plane.Normal.y + plane.Normal.z * plane.Normal.z));
        }
    }

    public struct Plane 
    {
        #region Public Fields

        public float D;
        public Vector3 Normal;

        #endregion Public Fields

        #region Constructors

        public Plane(Vector4 value)
            : this(new Vector3(value.x, value.y, value.z), value.w)
        {

        }

        public Plane(Vector3 normal, float d)
        {
            Normal = normal;
            D = d;
        }

        public Plane(Vector3 a, Vector3 b, Vector3 c)
        {
            Vector3 ab = b - a;
            Vector3 ac = c - a;

            Vector3 cross = Vector3.Cross(ab, ac);
            Normal = Vector3.Normalize(cross);
            D = -(Vector3.Dot(Normal, a));
        }

        public Plane(float a, float b, float c, float d)
            : this(new Vector3(a, b, c), d)
        {

        }

        #endregion Constructors

        public override string ToString()
        {
            return string.Format("{{Normal:{0} D:{1}}}", Normal, D);
        }
    }

    public enum TT_TYPE
    {
        SPHERICAL,
        HYPERBOLIC,
        OTHER,
        NONE,
    }
    public TT_TYPE ttType = TT_TYPE.SPHERICAL;

    public bool bSpheresON = true;
    public bool bTetraTerrean_On = false;

    [Range(0, 50f)]
    public float tetra_Radius;
    private float tetra_Radius_Last = 0;

    [Range(0, 100f)]
    public float scale_TT= 100f;
 
    [Range(0, 500f)]
    public float sphere_Radius;
    private float sphere_Radius_Last = 0;

    [Range(0, 0.5f)]
    public float cylinder_Radius;

    private Vector3[] tetra_Verts  = new Vector3[4];
    private Vector3[] face_Centers = new Vector3[4];

    [Space(12)]
    [Header("Hyperbolic Settings")]
    [Space(12)]

    [Range(0, 1f)]
    public float base_Distance;

    [Range(0, 1f)]
    public float tangent_Base;

    [Range(0, 1f)]
    public float tangent_H;

    [Range(0, 1f)]
    public float smidge;

    public GameObject H_Editor_Label;
    public GameObject C_Editor_Label;
    public GameObject B_Editor_Label;
    public GameObject I_Editor_Label;
    public GameObject T1_Editor_Label;
    public GameObject T2_Editor_Label;
    private int frameCount = 1;
    private Vector3 vCHn, vIHn, vT1n, vT2n;
    private Vector3 vIH;

    StreamWriter sWrite;
    public bool bPrint_Trace = false;

    private Vector3[] beeS = new Vector3[4];

    StreamWriter sLineVectors;

    private ArgosMeshDraft aMD_Nurbs_Mesh;
    GameObject pQuad_CARBON_LINE_go;

    private ArgosMeshDraft aMD_PQUAD_TMP;

    public enum RESOLUTION
    {
        RES_LOW,
        RES_MED,
        RES_HIGH,
    }

    public RESOLUTION rESOLUTION = RESOLUTION.RES_LOW;
    private RESOLUTION resolution_Last = RESOLUTION.RES_LOW;

    private int nRESOLUTION = 7;

    private List<Vector3> lst_mesh_v = new List<Vector3>();
    public float[] spline_lengths = new float[256];

    [Range(0, 10f)]
    public float short_Tan_mag = 1;

    [Range(0, 10f)]
    public float long_Tan_mag = 1;

    void Start()
    {
        sLineVectors = new StreamWriter("sLineVectors.txt");

        aMD_TetraTerrean = new ArgosMeshDraft();
        aMD_Spheres = new ArgosMeshDraft();
        aMD_Spheres.Add(MeshDraft.Sphere(1,16,16));
        cylinder_MD = new ArgosMeshDraft();
        aMD_TT_Sleeve = new ArgosMeshDraft();

        scythe_MD = new ArgosMeshDraft();
        scythe_GO = Instantiate(meshPF, transform);
        scythe_GO.name = "SCYTHE_OUTLINE";

        aMD_Nurbs_Mesh = new ArgosMeshDraft();
        pQuad_CARBON_LINE_go = Instantiate(meshPF, transform);
        pQuad_CARBON_LINE_go.name = "pQuad_CARBON_LINE_go";

        pQuad_CARBON_LINE_go.GetComponent<MeshRenderer>().enabled = false;//so we can see the TT

        sWrite = new StreamWriter("Hyperbolic_Params.txt");

        for (int i = 0; i<4; i++)
        {
            spheres[i] = Instantiate(meshPF, transform);
            spheres[i].name = "sphere_" + i.ToString();
            SetColor_Element(col_Sphere, spheres[i]);
            spheres[i].GetComponent<MeshFilter>().mesh = aMD_Spheres.ToMeshInternal();

            tetra_Verts_GO[i] = Instantiate(tetra_Vert_GOPF, transform);
            tetra_Verts_GO[i].name = "TetVERT_" + i.ToString();

            tt_Faces[i] = Instantiate(meshPF, transform);
            tt_Faces[i].name = "TT_Face_" + i.ToString();
            aMD_tt_Faces[i] = new ArgosMeshDraft();
        }
        for(int i = 0; i<6; i++)
        {
            tetra_Edges[i] = Instantiate(meshPF, transform);
            tetra_Edges[i].name = "edge_" + i.ToString();
            SetColor_Element(col_edge_Cylinder, tetra_Edges[i]);
            tetra_Edges[i].GetComponent<MeshFilter>().mesh = cylinder_MD.ToMeshInternal();
        }
        Set_Tetra_Verts(tetra_Radius);
        TetraTerrien_GO = Instantiate(meshPF, transform);
        TetraTerrien_GO.name = "TetraTerrien_GO";
        aMD_TetraTerrean.Clear();
        //Create_TETRA_TERREAN(all_Shape_Depth);
        //TetraTerrien_GO.GetComponent<MeshFilter>().mesh = aMD_TetraTerrean.ToMeshInternal();

        TT_Sleeve_GO = Instantiate(meshPF, transform);
        TT_Sleeve_GO.name = "TT_Sleeve_GO";
        aMD_TT_Sleeve.Clear();

        aMD_PQUAD_TMP = new ArgosMeshDraft();
    }

    /// <image url="$(SolutionDir)\EMB\Quad_Nurb.png" scale="0.15" /> 


    public void PQuad_SetUp_VertsAndTans()
    {
        Vector3 v0;
        Vector3 v1;
        Vector3 v2;
        Vector3 v3;
        Vector3 t01;
        Vector3 t10;
        Vector3 t13;
        Vector3 t31;
        Vector3 t23;
        Vector3 t32;
        Vector3 t20;
        Vector3 t02;

        v0 = tetra_Verts[2];
        v1 = v0;
        v1.y = -v1.y;

        v2 = tetra_Verts[3];
        v3 = v2;
        v3.y = -v3.y;

        //short_Tan_mag;
        //long_Tan_mag;

        Vector3[] vTansNorm = new Vector3[4];

        vTansNorm[0] = -v0.normalized;
        vTansNorm[1] = -v1.normalized;
        vTansNorm[2] = -v2.normalized;
        vTansNorm[3] = -v3.normalized;

        t01 = v0 + vTansNorm[0] * short_Tan_mag;
        t02 = v0 + vTansNorm[0] * long_Tan_mag;

        t10 = v1 + vTansNorm[1] * short_Tan_mag;
        t13 = v1 + vTansNorm[1] * long_Tan_mag;

        t23 = v2 + vTansNorm[2] * short_Tan_mag;
        t20 = v2 + vTansNorm[2] * long_Tan_mag;

        t32 = v3 + vTansNorm[3] * short_Tan_mag;
        t31 = v3 + vTansNorm[3] * long_Tan_mag;

        P_Quad_Generate(v0, v1, v2, v3,
                       t01, t10, t13, t31,
                       t23, t32, t20, t02);
    }


    public void P_Quad_Generate(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3,
                       Vector3 t01, Vector3 t10, Vector3 t13, Vector3 t31,
                       Vector3 t23, Vector3 t32, Vector3 t20, Vector3 t02)
    {
        Set_Resolution();

        lst_mesh_v.Clear();
        aMD_Nurbs_Mesh.Clear();

        float u = 0;
        float v = 0;
        float du = 1 / (float)nRESOLUTION;
        float dv = 1 / (float)nRESOLUTION;

        Vector3 t0, t1;
        Vector3 p0, p1;
        Vector3 p;

        for (int i = 0; i < nRESOLUTION + 1; i++)
        {
            t0 = GetPointOnBezierCurve(t02, t01, t10, t13, get_Adjusted(u, ref spline_lengths));
            p0 = GetPointOnBezierCurve(v0, t01, t10, v1, get_Adjusted(u, ref spline_lengths));
            t1 = GetPointOnBezierCurve(t20, t23, t32, t31, get_Adjusted(u, ref spline_lengths));
            p1 = GetPointOnBezierCurve(v2, t23, t32, v3, get_Adjusted(u, ref spline_lengths));

            Compute_Dist(ref spline_lengths, v0, t02, t20, v2);

            v = 0f;
            for (int j = 0; j < nRESOLUTION + 1; j++)
            {
                p = GetPointOnBezierCurve(p0, t0, t1, p1, get_Adjusted(v, ref spline_lengths));
                lst_mesh_v.Add(p);
                v += dv;
            }
            u += du;
        }

        int stride = nRESOLUTION + 1;
        int k = 0;
        for (int i = 0; i < nRESOLUTION; i++)
        {
            for (int j = 0; j < nRESOLUTION; j++)
            {
                aMD_Nurbs_Mesh.Add(MeshDraft.Quad(lst_mesh_v[k], lst_mesh_v[k + 1], lst_mesh_v[k + stride + 1], lst_mesh_v[k + stride]));
                k++;
            }
            k++;
        }

        Quaternion q;
        float angle = 120;

        ArgosMeshDraft amdTmp = new ArgosMeshDraft();

        amdTmp.Copy_MeshDraft(aMD_Nurbs_Mesh);

        amdTmp.Rotate(Quaternion.AngleAxis(angle, Vector3.up));

        aMD_Nurbs_Mesh.Add(amdTmp);

        amdTmp.Rotate(Quaternion.AngleAxis(angle, Vector3.up));

        aMD_Nurbs_Mesh.Add(amdTmp);

        aMD_PQUAD_TMP.Clear();

        subdivide_PQUAD_TRIANGLE(tetra_Verts[2], tetra_Verts[3], tetra_Verts[1], all_Shape_Depth, spheres[2].transform.localPosition, 3, true);

        aMD_Nurbs_Mesh.Add(aMD_PQUAD_TMP);

        aMD_PQUAD_TMP.Rotate(Quaternion.AngleAxis(180, Vector3.forward));

        aMD_Nurbs_Mesh.Add(aMD_PQUAD_TMP);

        pQuad_CARBON_LINE_go.GetComponent<MeshFilter>().mesh = aMD_Nurbs_Mesh.ToMeshInternal();
        pQuad_CARBON_LINE_go.GetComponent<MeshFilter>().mesh.RecalculateNormals(60);

    }

    void subdivide_PQUAD_TRIANGLE(Vector3 v1, Vector3 v2, Vector3 v3, int depth, Vector3 sector_Foc, int nID, bool bFlipNorm)
    {
        Vector3 v12, v23, v31;
        Vector3 v12_n, v23_n, v31_n;

        if (depth == 0)
        {
            if (bFlipNorm)
            {
                addTriangle_UV_Tag_PQUAD(v1, v3, v2, (float)nID);
            }
            else
            {
                //if (nID == 1)
                //{
                //    vTest[i] = v1;
                //    vTest2[i] = v2;
                //    i++;
                //}
                addTriangle_UV_Tag_PQUAD(v3, v2, v1, (float)nID);
            }
            return;
        }

        v12 = (v1 + v2) / 2.0f;
        v23 = (v2 + v3) / 2.0f;
        v31 = (v3 + v1) / 2.0f;

        v12_n = Sphere_Surf(v12, sector_Foc); //sector_Foc
        v23_n = Sphere_Surf(v23, sector_Foc);
        v31_n = Sphere_Surf(v31, sector_Foc);

        //v12_n = v12; //sector_Foc
        //v23_n = v23;
        //v31_n = v31;

        /* recursively subdivide new triangles */
        subdivide_PQUAD_TRIANGLE(v1, v12_n, v31_n, depth - 1, sector_Foc, 1, bFlipNorm);
        subdivide_PQUAD_TRIANGLE(v12_n, v2, v23_n, depth - 1, sector_Foc, 2, bFlipNorm);
        subdivide_PQUAD_TRIANGLE(v31_n, v23_n, v3, depth - 1, sector_Foc, 3, bFlipNorm);
        subdivide_PQUAD_TRIANGLE(v23_n, v31_n, v12_n, depth - 1, sector_Foc, 4, bFlipNorm);
    }

    private void Create_Top_Bottom(int depth)
    {
        //sleeve(tetra_Verts[1], tetra_Verts[2], tetra_Verts[3], spheres[2].transform.localPosition);
        subdivide_CarbonLine(tetra_Verts[1], tetra_Verts[3], tetra_Verts[2], depth, spheres[2].transform.localPosition, 3, false);
        List<Vector_Sort>[] vsortList = new List<Vector_Sort>[3];

        vsortList[0] = new List<Vector_Sort>();
        vsortList[1] = new List<Vector_Sort>();
        vsortList[2] = new List<Vector_Sort>();

        int[] id = new int[] { 0, 1, 2, 0, 2, 3, 0, 3, 1 };
        Vector3 vert;

        for (int j = 0; j < 3; j++)
        {
            Plane p = new Plane(tetra_Verts[id[3 * j]], tetra_Verts[id[3 * j + 1]], tetra_Verts[id[3 * j + 2]]);
            p.D = p.D * 0.999f;

            Vector_Sort vs;

            filteredVerts = 0;

            for (int i = 0; i < aMD_TT_Sleeve.vertices.Count; i++)
            {
                vert = aMD_TT_Sleeve.vertices[i];
                float res = PlaneHelper.ClassifyPoint(ref vert, ref p);

                if (res > 0)
                {
                    filteredVerts++;
                    vs = new Vector_Sort();
                    vs.vert = vert;
                    vs.vIDX = i;
                    vsortList[j].Add(vs);
                }
            }
            RemoveDuplicates(vsortList[j]);
            for (int i = 0; i < vsortList[j].Count; i++)
            {
                vsortList[j][i].dist = (tetra_Verts[j + 1] - vsortList[j][i].vert).magnitude;
            }

            var ordered = from element in vsortList[j]
                          orderby element.dist
                          select element;

            vsortList[j] = ordered.ToList<Vector_Sort>();
        }

        for (int i = 0; i < aMD_TT_Sleeve.vertices.Count; i++)
        {
            aMD_TT_Sleeve.vertices[i] = Sphere_Surf(aMD_TT_Sleeve.vertices[i], spheres[2].transform.localPosition);
        }

        Plane p2 = new Plane(Vector3.up, 0);
        int vertCount = aMD_TT_Sleeve.vertices.Count;

        ArgosMeshDraft amdTemp = new ArgosMeshDraft();

        amdTemp.Add(aMD_TT_Sleeve);
        aMD_TT_Sleeve.FlipTriangles();

        aMD_TT_Sleeve.Add(amdTemp);
        aMD_TT_Sleeve.FlipNormals();
        float d;

        for (int i = 0; i < vertCount; i++)//FLIP
        {
            vert = aMD_TT_Sleeve.vertices[i];
            d = PlaneHelper.ClassifyPoint(ref vert, ref p2);
            aMD_TT_Sleeve.vertices[i] = vert - 2f * d * Vector3.up;
        }

        List<Vector3> vInnerLower = new List<Vector3>();
        List<Vector3> vInnerUpper = new List<Vector3>();

        List<Vector3> vPrint = new List<Vector3>();

        for (int j = 0; j < 3; j++)
        {
            for (int i = 0; i < vsortList[j].Count; i++)
            {
                vert = aMD_TT_Sleeve.vertices[vsortList[j][i].vIDX];
                //vCurr.y = 0;
                d = PlaneHelper.ClassifyPoint(ref vert, ref p2);

                if (j == 0)
                {
                    vPrint.Add(vert - 2f * d * Vector3.up);
                }

                vInnerLower.Add(vert);
                vInnerUpper.Add(vert - 2f * d * Vector3.up);
            }
        }
        aMD_TT_Sleeve.Add(MeshDraft.Band(vInnerUpper, vInnerLower));
        aMD_TT_Sleeve.Add(MeshDraft.Band(vInnerLower, vInnerUpper));

        Generate_Line_List(vPrint);

        vSort_Count_0 = vsortList[0].Count;
        vSort_Count_1 = vsortList[1].Count;
        vSort_Count_2 = vsortList[2].Count;
    }

    private float get_Adjusted(float t, ref float[] lengths)
    {
        int i = 0;
        while (i < 256 && lengths[i] < t)
        {
            i++;
        }
        return (float)i / 256;
    }

    private void Compute_Dist(ref float[] lengths, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
    {
        float t = 0.0f;
        float dt = 1f / 256;

        Vector3 vB = GetPointOnBezierCurve(p0, p1, p2, p3, t);
        Vector3 vB_Last = vB;
        float running_Len = 0;

        for (int i = 0; i < 256; i++)
        {
            vB = GetPointOnBezierCurve(p0, p1, p2, p3, t);
            running_Len += (vB - vB_Last).magnitude;
            lengths[i] = running_Len;
            vB_Last = vB;
            t += dt;
        }
        for (int i = 0; i < 256; i++)
        {
            lengths[i] /= running_Len;
        }
    }

    private void Set_Resolution()
    {
        if (rESOLUTION != resolution_Last)
        {
            if (rESOLUTION == RESOLUTION.RES_LOW)
            {
                nRESOLUTION = 7;
            }
            else if (rESOLUTION == RESOLUTION.RES_MED)
            {
                nRESOLUTION = 18;
            }
            else if (rESOLUTION == RESOLUTION.RES_HIGH)
            {
                nRESOLUTION = 36;
            }
        }
        resolution_Last = rESOLUTION;
    }


    //void OnDrawGizmos()
    //{
    //    Gizmos.DrawIcon(H_Editor_Label.transform.position, "H.png", true);
    //    Gizmos.DrawIcon(C_Editor_Label.transform.position, "C.png", true);
    //    Gizmos.DrawIcon(I_Editor_Label.transform.position, "I.png", true);
    //    Gizmos.DrawIcon(B_Editor_Label.transform.position, "B.png", true);
    //    Gizmos.DrawIcon(T1_Editor_Label.transform.position, "T1.png", true);
    //    Gizmos.DrawIcon(T2_Editor_Label.transform.position, "T2.png", true);
    //    Gizmos.color = Color.green;
    //    Gizmos.DrawLine(B_Editor_Label.transform.position, T1_Editor_Label.transform.position);
    //    Gizmos.DrawLine(H_Editor_Label.transform.position, T2_Editor_Label.transform.position);
    //}

    private void OnApplicationQuit()
    {
        sWrite.Close();
    }

    /// <image url="$(SolutionDir)\EMB\hyperbole2.png" scale="0.35"></image>

    private void build_Reference_Hyperbolic_Spline(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 vI)
    {
        //p4 = H
        float t = 0.0f;
        float dt = 1f / 256;

        Vector3 vB = GetPointOnBezierCurve(p0, p1, p2, p3, t);
        Vector3 vB_Last = vB;
        float running_Len = 0;

        float   vI_Len = vI.magnitude;
        Vector3 vIn    = vI.normalized;

        for (int i = 0; i < 256; i++)
        {
            vB = GetPointOnBezierCurve(p0, p1, p2, p3, t);
            running_Len += (vB - vB_Last).magnitude;
            lengths[i] = running_Len;
            hyperbola_of_R[i] = Vector3.Dot(vB, vIn);
            vB_Last = vB;
            t += dt;
        }
        for (int i = 0; i < 256; i++)
        {
            lengths[i] /= running_Len;
        }
    }

    public void Print_Trace(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 vI)
    {
        for (int i = 0; i < 256; i++)
        {
            sWrite.WriteLine(i.ToString() + "\t " + " -\t " + hyperbola_of_R[i].ToString("F2"));
        }
        sWrite.WriteLine("p0 Base " + "\t " + " -\t " + p0.ToString("F2"));
        sWrite.WriteLine("p1 Tangent_0 " + "\t " + " -\t " + p1.ToString("F2"));
        sWrite.WriteLine("p2 Tangent_1 " + "\t " + " -\t " + p2.ToString("F2"));
        sWrite.WriteLine("p3 H " + "\t " + " -\t " + p3.ToString("F2"));
        sWrite.WriteLine("vI " + "\t " + " -\t " + vI.ToString("F2"));
    }

    private void SetColor_Element(Color col, GameObject go)
    {
        float alpha = col.a;
        float alpha_out = alpha / 3f;

        Color cola = col;
        cola.a = alpha_out;

        go.GetComponent<MeshRenderer>().material.SetColor("_EmissionColor", cola);
        go.GetComponent<MeshRenderer>().material.SetColor("_Color", col);
    }

    public void Set_Tetra_Verts(float radius)
    {
        float tetrahedralAngle = Mathf.PI * -19.471220333f / 180;
        float segmentAngle = Mathf.PI * 2 / 3;
        float currentAngle = 0f;

        Vector3 v = new Vector3(0, radius, 0);
        tetra_Verts[0] = v;
        for (var i = 1; i < 4; i++)
        {
            tetra_Verts[i] = PTUtils.PointOnSphere(radius, currentAngle, tetrahedralAngle);
            currentAngle += segmentAngle;
        }

        face_Centers[0] = (tetra_Verts[0] + tetra_Verts[1] + tetra_Verts[2]) / 3f;
        face_Centers[1] = (tetra_Verts[0] + tetra_Verts[2] + tetra_Verts[3]) / 3f;
        face_Centers[2] = (tetra_Verts[1] + tetra_Verts[2] + tetra_Verts[3]) / 3f;
        face_Centers[3] = (tetra_Verts[0] + tetra_Verts[1] + tetra_Verts[3]) / 3f;

        float edge_length = (tetra_Verts[0] - tetra_Verts[1]).magnitude;
        edge_length = radius * 2f * Mathf.Sqrt(2f) / Mathf.Sqrt(3);

        cylinder_MD.Add(MeshDraft.Cylinder_Z(cylinder_Radius, 5, edge_length));

        //tetra_Edges[0].transform.localPosition = tetra_Verts[0];
        //tetra_Edges[0].transform.localRotation = Quaternion.LookRotation(tetra_Verts[1] - tetra_Verts[0]);
        //tetra_Edges[0].GetComponent<MeshFilter>().mesh = cylinder_MD.ToMeshInternal();

        //tetra_Edges[1].transform.localPosition = tetra_Verts[1];
        //tetra_Edges[1].transform.localRotation = Quaternion.LookRotation(tetra_Verts[2] - tetra_Verts[1]);
        //tetra_Edges[1].GetComponent<MeshFilter>().mesh = cylinder_MD.ToMeshInternal();

        //tetra_Edges[2].transform.localPosition = tetra_Verts[2];
        //tetra_Edges[2].transform.localRotation = Quaternion.LookRotation(tetra_Verts[3] - tetra_Verts[2]);
        //tetra_Edges[2].GetComponent<MeshFilter>().mesh = cylinder_MD.ToMeshInternal();

        //tetra_Edges[3].transform.localPosition = tetra_Verts[3];
        //tetra_Edges[3].transform.localRotation = Quaternion.LookRotation(tetra_Verts[0] - tetra_Verts[3]);
        //tetra_Edges[3].GetComponent<MeshFilter>().mesh = cylinder_MD.ToMeshInternal();

        //tetra_Edges[4].transform.localPosition = tetra_Verts[1];
        //tetra_Edges[4].transform.localRotation = Quaternion.LookRotation(tetra_Verts[3] - tetra_Verts[1]);
        //tetra_Edges[4].GetComponent<MeshFilter>().mesh = cylinder_MD.ToMeshInternal();

        //tetra_Edges[5].transform.localPosition = tetra_Verts[2];
        //tetra_Edges[5].transform.localRotation = Quaternion.LookRotation(tetra_Verts[0] - tetra_Verts[2]);
        //tetra_Edges[5].GetComponent<MeshFilter>().mesh = cylinder_MD.ToMeshInternal();
    }

    private void Create_Scythe(int depth)
    {


        subdivide_CarbonLine(tetra_Verts[1], tetra_Verts[3], tetra_Verts[2], depth, spheres[2].transform.localPosition, 3, false);

    }

    void Update() 
    {
        PQuad_SetUp_VertsAndTans();

        cylinder_MD.Clear();
        scythe_MD.Clear();
        Set_Tetra_Verts(tetra_Radius);

        if (sphere_Radius_Last != sphere_Radius)
        {
            float face_dist;
            float tetra_Height;
            Vector3 face_Norm;
            float a, b;

            aMD_Spheres.Clear();
            aMD_Spheres.Add(MeshDraft.Sphere(sphere_Radius, 36, 32));
            for (int i = 0; i < 4; i++)
            {
                face_dist = face_Centers[i].magnitude;
                tetra_Height = 1.33333f * tetra_Radius;
                a = 2 * Mathf.Sqrt(2) / 3;
                b = Mathf.Sqrt(sphere_Radius * sphere_Radius - tetra_Radius * tetra_Radius * 8f / 9f);
                face_Norm = face_Centers[i].normalized;

                spheres[i].transform.localPosition = face_Norm * (tetra_Radius / 3 + b);
                spheres[i].transform.localRotation = Quaternion.LookRotation(sphere_pos[i]);
                spheres[i].GetComponent<MeshFilter>().mesh = aMD_Spheres.ToMeshInternal();
                tetra_Verts_GO[i].transform.localPosition = tetra_Verts[i];
            }
        }
        sphere_Radius_Last = sphere_Radius;
        tetra_Radius_Last = tetra_Radius;
        if (bSpheresON)
        {
            ShowSpheres(true);
        }
        else
        {
            ShowSpheres(false);
        }

        aMD_TetraTerrean.Clear();

        for (int i = 0; i < 4; i++)
        {
            aMD_tt_Faces[i].Clear();
        }

        Create_TETRA_TERREAN(all_Shape_Depth);
        if (bSeparate_Faces)
        {
            for (int i = 0; i < 4; i++)
            {
                tt_Faces[i].GetComponent<MeshFilter>().mesh = aMD_tt_Faces[i].ToMeshInternal();
            }
        }
        else
        {
            aMD_TetraTerrean.FlipTriangles();
            aMD_TetraTerrean.FlipNormals();

            TetraTerrien_GO.GetComponent<MeshFilter>().mesh = aMD_TetraTerrean.ToMeshInternal();
            TetraTerrien_GO.GetComponent<MeshFilter>().mesh.RecalculateNormals(60);
        }

        //Create_Scythe(all_Shape_Depth);

        //aMD_TT_Sleeve.Clear();
        //Create_TETRA_TERREAN_Sleeve(all_Shape_Depth);
        //TT_Sleeve_GO.GetComponent<MeshFilter>().mesh = aMD_TT_Sleeve.ToMeshInternal();
        //TT_Sleeve_GO.GetComponent<MeshFilter>().mesh.RecalculateNormals(60);

        sphere_Radius_Last = sphere_Radius;
        tetra_Radius_Last  = tetra_Radius;
    }

    private void ShowSpheres(bool bOn)
    {
        for(int i = 0; i<4; i++)
        {
            spheres[i].GetComponent<MeshRenderer>().enabled = bOn;
        }
    }

    public void Calc_Tetra_Verts(float radius)
    {
        float tetrahedralAngle = Mathf.PI * -19.471220333f / 180;
        float segmentAngle = Mathf.PI * 2 / 3;
        float currentAngle = 0f;

        Vector3 v = new Vector3(0, radius, 0);
        sphere_pos[0] = v;
        for (var i = 1; i < 4; i++)
        {
            sphere_pos[i] = PTUtils.PointOnSphere(radius, currentAngle, tetrahedralAngle);
            currentAngle += segmentAngle;
        }
    }

    private Vector3 Sphere_Surf(Vector3 vP0, Vector3 sector_Focus)
    {
        Vector3 l = vP0.normalized;

        Vector3 OminC = -sector_Focus;
        float rsqr = sphere_Radius * sphere_Radius;

        float dotLOminC = Vector3.Dot(l, OminC);
        float Omag = OminC.magnitude;

        float d = -dotLOminC - Mathf.Sqrt(dotLOminC * dotLOminC - Omag * Omag + sphere_Radius * sphere_Radius);

        return l * d;
    }

    private Vector3 Hyperbolic(Vector3 vP0, Vector3 face_Center)
    {
        Vector3 vFCn = face_Center.normalized;
        Vector3 dotV = Vector3.Dot(vP0, vFCn)* vFCn;
        Vector3 radV = vP0 - dotV;
        Vector3 vP0n = vP0.normalized;
        float   radial_mag = radV.magnitude;
        float   perc = (radial_mag / vIH.magnitude)*255;
        float   gVal = 0f;

        //if (perc < 256)
        //{
        gVal = hyperbola_of_R[(int)perc];
        //}

        return  (gVal*vFCn + radV);
    }
     
    void Extrude_1(Vector3 v1, Vector3 v2, Vector3 v3, int nID, Vector3 sector_Foc)
    {
        Vector3 nSect = tetra_Verts[0].normalized;
        float spar = (1f / 9f) * sphere_Radius;

        float d1, d2, d3;

        d1 = Vector3.Dot(v1, nSect);
        d2 = Vector3.Dot(v2, nSect);
        d3 = Vector3.Dot(v3, nSect);

        Vector3 ob1 = (spar - d1) * nSect;
        Vector3 ob2 = (spar - d2) * nSect;
        Vector3 ob3 = (spar - d3) * nSect;

        if (nID == 0)
        {
            addTriangle(v1 + 2 * ob1, v2 + 2 * ob2, v3 + 2 * ob3);
        }
        else
        {
            ob1 = PosCheck(nSect, d1, (d1 / spar), v1 - d1 * nSect);
            ob2 = PosCheck(nSect, d2, (d2 / spar), v2 - d2 * nSect);
            ob3 = PosCheck(nSect, d3, (d3 / spar), v3 - d3 * nSect);
            addTriangle(v1 + ob1, v2 + ob2, v3 + ob3);
        }
    }

    private Vector3 PosCheck(Vector3 v1, float d, float multiplier, Vector3 vHorz)
    {
        return Vector3.zero;
    }

    public static void RemoveDuplicates(List<Vector_Sort> list)
    {
        if (list == null)
        {
            return;
        }
        int i = 1;
        while (i < list.Count)
        {
            int j = 0;
            bool remove = false;
            while (j < i && !remove)
            {
                if (list[i].vert.Equals(list[j].vert))
                {
                    remove = true;
                }
                j++;
            }
            if (remove)
            {
                list.RemoveAt(i);
            }
            else
            {
                i++;
            }
        }
    }

    private void Create_TETRA_TERREAN_Sleeve(int depth)
    {
        //sleeve(tetra_Verts[1], tetra_Verts[2], tetra_Verts[3], spheres[2].transform.localPosition);
        subdivide_CarbonLine(tetra_Verts[1], tetra_Verts[3], tetra_Verts[2], depth, spheres[2].transform.localPosition, 3, false);
        List<Vector_Sort>[] vsortList = new List<Vector_Sort>[3];

        vsortList[0] = new List<Vector_Sort>();
        vsortList[1] = new List<Vector_Sort>();
        vsortList[2] = new List<Vector_Sort>();

        int[] id = new int [] { 0, 1, 2, 0, 2, 3, 0, 3, 1 }; 
        Vector3   vert;

        for (int j = 0; j < 3; j++)
        {
            Plane p = new Plane(tetra_Verts[id[3*j]], tetra_Verts[id[3*j+1]], tetra_Verts[id[3*j+2]]);
            p.D = p.D * 0.999f;
            
            Vector_Sort vs;

            filteredVerts = 0;

            for (int i = 0; i < aMD_TT_Sleeve.vertices.Count; i++)
            {
                vert = aMD_TT_Sleeve.vertices[i];
                float res = PlaneHelper.ClassifyPoint(ref vert, ref p);

                if (res > 0)
                {
                    filteredVerts++;
                    vs = new Vector_Sort();
                    vs.vert = vert;
                    vs.vIDX = i;
                    vsortList[j].Add(vs);
                }
            }
            RemoveDuplicates(vsortList[j]);
            for (int i = 0; i < vsortList[j].Count; i++)
            {
                vsortList[j][i].dist = (tetra_Verts[j+1] - vsortList[j][i].vert).magnitude;
            }

            var ordered = from element in vsortList[j]
                      orderby element.dist
                      select element;

            vsortList[j] = ordered.ToList<Vector_Sort>();
        }

        for(int i = 0; i < aMD_TT_Sleeve.vertices.Count; i++)
        {
            aMD_TT_Sleeve.vertices[i] = Sphere_Surf(aMD_TT_Sleeve.vertices[i], spheres[2].transform.localPosition);
        }

        Plane p2 = new Plane(Vector3.up, 0);
        int vertCount = aMD_TT_Sleeve.vertices.Count;

        ArgosMeshDraft amdTemp = new ArgosMeshDraft();

        amdTemp.Add(aMD_TT_Sleeve);
        aMD_TT_Sleeve.FlipTriangles();
        
        aMD_TT_Sleeve.Add(amdTemp);
        aMD_TT_Sleeve.FlipNormals();
        float d;

        for(int i = 0; i < vertCount; i++)//FLIP
        {
            vert = aMD_TT_Sleeve.vertices[i];
            d = PlaneHelper.ClassifyPoint(ref vert, ref p2);
            aMD_TT_Sleeve.vertices[i] = vert - 2f * d * Vector3.up;
        }

        List<Vector3> vInnerLower = new List<Vector3>();
        List<Vector3> vInnerUpper = new List<Vector3>();

        List<Vector3> vPrint = new List<Vector3>();

        for (int j = 0; j < 3; j++)
        {
            for (int i = 0; i < vsortList[j].Count; i++)
            {
                vert = aMD_TT_Sleeve.vertices[vsortList[j][i].vIDX];
                //vCurr.y = 0;
                d = PlaneHelper.ClassifyPoint(ref vert, ref p2);

                if(j==0)
                {
                    vPrint.Add(vert - 2f * d * Vector3.up);
                }

                vInnerLower.Add(vert);
                vInnerUpper.Add(vert - 2f * d * Vector3.up);
            }
        }
        aMD_TT_Sleeve.Add(MeshDraft.Band(vInnerUpper, vInnerLower));
        aMD_TT_Sleeve.Add(MeshDraft.Band(vInnerLower, vInnerUpper));

        Generate_Line_List(vPrint);

        vSort_Count_0 = vsortList[0].Count;
        vSort_Count_1 = vsortList[1].Count;
        vSort_Count_2 = vsortList[2].Count;
    }


    bool bwritten = false;
    void Generate_Line_List(List<Vector3> vPrint)
    {
        if (!bwritten)
        {
            vPrint.Insert(0, tetra_Verts[1]);
            vPrint.Add(tetra_Verts[2]);
            //vPrint[0] = tetra_Verts[1];
            //vPrint[vPrint.Count - 1] = tetra_Verts[2];

            for (int i = 0; i < vPrint.Count-1; i++)
            {
                sLineVectors.Write("new Vector3(" + vPrint[i].x.ToString("F3") + "f, " + vPrint[i].y.ToString("F3") + "f, " + vPrint[i].z.ToString("F3") + "f), " +
                                   "new Vector3(" + vPrint[i+1].x.ToString("F3") + "f, " + vPrint[i+1].y.ToString("F3") + "f, " + vPrint[i+1].z.ToString("F3") + "f), ");
            }

            Quaternion q;
            float angle = 120f;
            Vector3 axis = Vector3.up;

            q = Quaternion.AngleAxis(angle, axis);
            Vector3 vRota;
            Vector3 vRota2;

            for (int i = 0; i< vPrint.Count-1; i++)
            {
                vRota  = q * vPrint[i];
                vRota2 = q * vPrint[i+1];
                sLineVectors.Write("new Vector3(" + vRota.x.ToString("F3") + "f, " + vRota.y.ToString("F3") + "f, " + vRota.z.ToString("F3") + "f), " +
                    "new Vector3(" + vRota2.x.ToString("F3") + "f, " + vRota2.y.ToString("F3") + "f, " + vRota2.z.ToString("F3") + "f), ");


            }
            angle = 240;
            q = Quaternion.AngleAxis(angle, axis);
            for (int i = 0; i < vPrint.Count - 1; i++)
            {
                vRota = q * vPrint[i];
                vRota2 = q * vPrint[i + 1];
                sLineVectors.Write("new Vector3(" + vRota.x.ToString("F3") + "f, " + vRota.y.ToString("F3") + "f, " + vRota.z.ToString("F3") + "f), " +
                    "new Vector3(" + vRota2.x.ToString("F3") + "f, " + vRota2.y.ToString("F3") + "f, " + vRota2.z.ToString("F3") + "f), ");

            }
            /////////////////////////UPPERS//////////////////////

            List<Vector3> vlUppers = new List<Vector3>();
            axis = tetra_Verts[1].normalized;
            angle = 120;
            q = Quaternion.AngleAxis(angle, axis);
            for (int i = 0; i < vPrint.Count - 1; i++)
            {
                vRota = q * vPrint[i];
                vRota2 = q * vPrint[i + 1];

                vlUppers.Add(vRota);
                vlUppers.Add(vRota2);

                sLineVectors.Write("new Vector3(" + vRota.x.ToString("F3") + "f, " + vRota.y.ToString("F3") + "f, " + vRota.z.ToString("F3") + "f), " +
                    "new Vector3(" + vRota2.x.ToString("F3") + "f, " + vRota2.y.ToString("F3") + "f, " + vRota2.z.ToString("F3") + "f), ");

            }

            axis = Vector3.up;
            angle = 120;
            q = Quaternion.AngleAxis(angle, axis);
            for (int i = 0; i < vlUppers.Count - 1; i++)
            {
                vRota = q * vlUppers[i];
                vRota2 = q * vlUppers[i + 1];
                sLineVectors.Write("new Vector3(" + vRota.x.ToString("F3") + "f, " + vRota.y.ToString("F3") + "f, " + vRota.z.ToString("F3") + "f), " +
                    "new Vector3(" + vRota2.x.ToString("F3") + "f, " + vRota2.y.ToString("F3") + "f, " + vRota2.z.ToString("F3") + "f), ");
            }
            angle = 240;
            q = Quaternion.AngleAxis(angle, axis);
            for (int i = 0; i < vlUppers.Count - 1; i++)
            {
                vRota = q * vlUppers[i];
                vRota2 = q * vlUppers[i + 1];
                sLineVectors.Write("new Vector3(" + vRota.x.ToString("F3") + "f, " + vRota.y.ToString("F3") + "f, " + vRota.z.ToString("F3") + "f), " +
                    "new Vector3(" + vRota2.x.ToString("F3") + "f, " + vRota2.y.ToString("F3") + "f, " + vRota2.z.ToString("F3") + "f), ");
            }
        }
        sLineVectors.Close();
        bwritten = true;
    }

    void sleeve(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 sector_Foc)
    {
        Vector3 vCurr;

        //v1.y = v2.y = v3.y = 0;

        List<Vector3> vInnerLower = new List<Vector3>();
        List<Vector3> vInnerUpper = new List<Vector3>();

        Vector3 vUp = Vector3.up;

        Vector3[] vAlpha = new[] { v1, v2, v3 };
        Vector3[] vOmega = new[] { v2, v3, v1 };

        float t = 0;
        float dt = 1 / 60f;
        float d;
        float el;
        for (int j = 0; j < 3; j++)
        {
            t = 0;
            for (int i = 0; i < 60; i++)
            {
                vCurr = Sphere_Surf(Vector3.Lerp(vAlpha[j], vOmega[j], t), sector_Foc);
                //vCurr.y = 0;
                d  =  vCurr.y;
                el = Mathf.Sqrt(tetra_Radius * tetra_Radius - d * d); 

                //vInnerLower.Add(vCurr + el*vUp);
                //vInnerUpper.Add(vCurr - el*vUp);

                vInnerLower.Add(vCurr);
                vInnerUpper.Add(vCurr - 2f * d * vUp);

                t += dt;
            }
        }
        aMD_TT_Sleeve.Add(MeshDraft.Band(vInnerUpper, vInnerLower));
        aMD_TT_Sleeve.Add(MeshDraft.Band(vInnerLower, vInnerUpper));
    }


    Vector3[] vTest = new Vector3[1024];
    Vector3[] vTest2 = new Vector3[1024];
    int i = 0;
    void subdivide_CarbonLine(Vector3 v1, Vector3 v2, Vector3 v3, int depth, Vector3 sector_Foc, int nID, bool bFlipNorm)
    {
        Vector3 v12, v23, v31;
        Vector3 v12_n, v23_n, v31_n;

        if (depth == 0)
        {
            if (bFlipNorm)
            {
                addTriangle_UV_Tag_CarbonLine(v1, v3, v2, (float)nID);
            }
            else
            {
                //if (nID == 1)
                //{
                //    vTest[i] = v1;
                //    vTest2[i] = v2;
                //    i++;
                //}
                addTriangle_UV_Tag_CarbonLine(v1, v2, v3, (float)nID);
            }
            return;
        }

        v12 = (v1 + v2) / 2.0f;
        v23 = (v2 + v3) / 2.0f;
        v31 = (v3 + v1) / 2.0f;

        //v12_n = Sphere_Surf(v12, sector_Foc); //sector_Foc
        //v23_n = Sphere_Surf(v23, sector_Foc);
        //v31_n = Sphere_Surf(v31, sector_Foc);

        v12_n = v12; //sector_Foc
        v23_n = v23;
        v31_n = v31;

        /* recursively subdivide new triangles */
        subdivide_CarbonLine(v1, v12_n, v31_n, depth - 1, sector_Foc, 1, bFlipNorm);
        subdivide_CarbonLine(v12_n, v2, v23_n, depth - 1, sector_Foc, 2, bFlipNorm);
        subdivide_CarbonLine(v31_n, v23_n, v3, depth - 1, sector_Foc, 3, bFlipNorm);
        subdivide_CarbonLine(v23_n, v31_n, v12_n, depth - 1, sector_Foc, 4, bFlipNorm);
    }

    private void Create_TETRA_TERREAN(int depth)
    {
        float scl = scale_TT / 100f;

        if (ttType == TT_TYPE.SPHERICAL)
        {
            subdivide(tetra_Verts[0], tetra_Verts[1], tetra_Verts[2], depth, spheres[0].transform.localPosition, 0, true);
            subdivide(tetra_Verts[0], tetra_Verts[2], tetra_Verts[3], depth, spheres[1].transform.localPosition, 1, true);
            subdivide(tetra_Verts[0], tetra_Verts[3], tetra_Verts[1], depth, spheres[3].transform.localPosition, 2, true);
            subdivide(tetra_Verts[1], tetra_Verts[3], tetra_Verts[2], depth, spheres[2].transform.localPosition, 3, true);
            //subdivide(tetra_Verts[0], tetra_Verts[1], tetra_Verts[2], depth, spheres[0].transform.localPosition, 0, false);//Inside
            //subdivide(tetra_Verts[0], tetra_Verts[2], tetra_Verts[3], depth, spheres[1].transform.localPosition, 1, false);
            //subdivide(tetra_Verts[0], tetra_Verts[3], tetra_Verts[1], depth, spheres[3].transform.localPosition, 2, false);
        }
        else if(ttType == TT_TYPE.HYPERBOLIC)
        {
            Vector3[] fc = new Vector3[4];

            fc[0] = (tetra_Verts[0] + tetra_Verts[1] + tetra_Verts[2]) / 3f;
            fc[1] = (tetra_Verts[0] + tetra_Verts[2] + tetra_Verts[3]) / 3f;
            fc[2] = (tetra_Verts[1] + tetra_Verts[3] + tetra_Verts[2]) / 3f;
            fc[3] = (tetra_Verts[0] + tetra_Verts[3] + tetra_Verts[1]) / 3f;

            beeS[0] = base_Distance * tetra_Radius * fc[0].normalized;
            beeS[1] = base_Distance * tetra_Radius * fc[1].normalized;
            beeS[2] = base_Distance * tetra_Radius * fc[2].normalized;
            beeS[3] = base_Distance * tetra_Radius * fc[3].normalized;

            subdivide(tetra_Verts[0], tetra_Verts[1], tetra_Verts[2], depth, fc[0], 0, false);
            subdivide(tetra_Verts[0], tetra_Verts[2], tetra_Verts[3], depth, fc[1], 1, false);
            subdivide(tetra_Verts[1], tetra_Verts[3], tetra_Verts[2], depth, fc[2], 2, false);
            subdivide(tetra_Verts[0], tetra_Verts[3], tetra_Verts[1], depth, fc[3], 3, false);

            Scale_Radially();
        }
    }

    private void Scale_Radially()
    {
        float ratio = 0;
        Vector3 v;
        float fidx;
        float len;

        for (int i = 0; i<aMD_TetraTerrean.vertices.Count; i++)
        {  
            fidx  = aMD_TetraTerrean.uv[i].x;

            ratio = aMD_TetraTerrean.vertices[i].magnitude / tetra_Radius;

            aMD_TetraTerrean.vertices[i] *= ((smidge * ratio) + (1 - smidge));
        }
    }

    void subdivide(Vector3 v1, Vector3 v2, Vector3 v3, int depth, Vector3 sector_Foc, int nID, bool bFlipNorm)
    {
        Vector3 v12, v23, v31;
        Vector3 v12_n, v23_n, v31_n;

        if (depth == 0)
        {
            if (ttType == TT_TYPE.SPHERICAL || ttType == TT_TYPE.HYPERBOLIC)
            {
                if (bFlipNorm)
                {
                    addTriangle_UV_Tag(v1, v3, v2, (float)nID);
                }
                else
                {
                    addTriangle_UV_Tag(v1, v2, v3, (float)nID);
                }
            }
            else if (ttType == TT_TYPE.OTHER)
            {
                Extrude_1(v1, v2, v3, nID, sector_Foc);
            }
            return;
        }

        v12 = (v1 + v2) / 2.0f;
        v23 = (v2 + v3) / 2.0f;
        v31 = (v3 + v1) / 2.0f;

        //intrude midpoints
        if (ttType == TT_TYPE.SPHERICAL)
        {
            v12_n = Sphere_Surf(v12, sector_Foc); //sector_Foc
            v23_n = Sphere_Surf(v23, sector_Foc);
            v31_n = Sphere_Surf(v31, sector_Foc);
        }
        else if(ttType == TT_TYPE.HYPERBOLIC)
        {
            v12_n = Hyperbolic(v12, sector_Foc); //sector_Foc
            v23_n = Hyperbolic(v23, sector_Foc);
            v31_n = Hyperbolic(v31, sector_Foc);
        }
        else if (ttType == TT_TYPE.OTHER)
        {
            v12_n = Extrude_1(v12, sector_Foc); //sector_Foc
            v23_n = Extrude_1(v23, sector_Foc);
            v31_n = Extrude_1(v31, sector_Foc);
        }
        else
        {
            v12_n = Vector3.zero;
            v23_n = Vector3.zero;
            v31_n = Vector3.zero;
        }
        /* recursively subdivide new triangles */
        subdivide(v1,    v12_n, v31_n, depth - 1, sector_Foc, nID, bFlipNorm);
        subdivide(v12_n, v2,    v23_n, depth - 1, sector_Foc, nID, bFlipNorm);
        subdivide(v31_n, v23_n, v3,    depth - 1, sector_Foc, nID, bFlipNorm);
        subdivide(v23_n, v31_n, v12_n, depth - 1, sector_Foc, nID, bFlipNorm);
    }

    private Vector3 Extrude_1(Vector3 vP0, Vector3 sector_Focus)
    {
        Vector3 l = vP0.normalized;

        Vector3 OminC = -sector_Focus;
        float rsqr = sphere_Radius * sphere_Radius;

        float dotLOminC = Vector3.Dot(l, OminC);
        float Omag = OminC.magnitude;

        float d = -dotLOminC - Mathf.Sqrt(dotLOminC * dotLOminC - Omag * Omag + sphere_Radius * sphere_Radius);

        return (l * d);
    }

    void addTriangle(Vector3 v0, Vector3 v1, Vector3 v2)
    {
        aMD_TetraTerrean.Add(MeshDraft.Triangle(v0, v1, v2));
    }

    void addTriangle_UV_Tag(Vector3 v0, Vector3 v1, Vector3 v2, float uvTag)
    {
        if (bSeparate_Faces)
        {
            aMD_tt_Faces[(int)uvTag].Add(MeshDraft.Triangl_UV_Tag(v0, v1, v2, uvTag));
        }
        else
        {
            aMD_TetraTerrean.Add(MeshDraft.Triangl_UV_Tag(v0, v1, v2, uvTag));
        }
    }

    void addTriangle_UV_Tag_CarbonLine(Vector3 v0, Vector3 v1, Vector3 v2, float uvTag)
    {
        aMD_TT_Sleeve.Add(MeshDraft.Triangl_UV_Tag(v0, v1, v2, uvTag));
    }

    void addTriangle_Skythe(Vector3 v0, Vector3 v1, Vector3 v2, float uvTag)
    {
        scythe_MD.Add(MeshDraft.Triangl_UV_Tag(v0, v1, v2, uvTag));
    }

    void addTriangle_UV_Tag_PQUAD(Vector3 v0, Vector3 v1, Vector3 v2, float uvTag)
    {
        aMD_PQUAD_TMP.Add(MeshDraft.Triangl_UV_Tag(v0, v1, v2, uvTag));
    }

    public Vector3 GetPointOnBezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
    {
        float u = 1f - t;
        float t2 = t * t;
        float u2 = u * u;
        float u3 = u2 * u;
        float t3 = t2 * t;

        Vector3 result =
            (u3) * p0 +
            (3f * u2 * t) * p1 +
            (3f * u * t2) * p2 +
            (t3) * p3;

        return result;
    }

    /// <image url="$(SolutionDir)\EMB\hyperbole.png" scale="0.45"></image>
    /// 



}







/// <image url="$(SolutionDir)\EMB\CD.png" scale="0.16803" /> 


//int countDown = 10;
//void Update() // Original
//{
//    H_Editor_Label.transform.position  = tetra_Verts_GO[0].transform.position;
//    C_Editor_Label.transform.position  = transform.position;

//    Vector3 v = (tetra_Verts_GO[0].transform.localPosition + tetra_Verts_GO[1].transform.localPosition + tetra_Verts_GO[2].transform.localPosition) /3;

//    I_Editor_Label.transform.position = v + transform.position;
//    B_Editor_Label.transform.position = transform.position + base_Distance*tetra_Radius*v.normalized;

//    vCHn = (H_Editor_Label.transform.localPosition - C_Editor_Label.transform.localPosition).normalized;
//    vIH  = (H_Editor_Label.transform.localPosition - I_Editor_Label.transform.localPosition);
//    vIHn = vIH.normalized;

//    vT1n = Vector3.Dot(vCHn, vIHn) * vIHn;
//    vT2n = vCHn;

//    T1_Editor_Label.transform.localPosition = (vT1n * tangent_Base * tetra_Radius + B_Editor_Label.transform.localPosition);
//    T2_Editor_Label.transform.localPosition = (H_Editor_Label.transform.localPosition - vT2n * tangent_H * tetra_Radius);

//    if(frameCount-- == 0 || bPrint_Trace)
//    {
//        frameCount = 10;
//        build_Reference_Hyperbolic_Spline(B_Editor_Label.transform.localPosition,  T1_Editor_Label.transform.localPosition, 
//                                          T2_Editor_Label.transform.localPosition, H_Editor_Label.transform.localPosition,
//                                          I_Editor_Label.transform.localPosition);

//        if(--countDown == 0 || bPrint_Trace)
//        {
//            Print_Trace(B_Editor_Label.transform.localPosition, T1_Editor_Label.transform.localPosition,
//                                          T2_Editor_Label.transform.localPosition, H_Editor_Label.transform.localPosition,
//                                          I_Editor_Label.transform.localPosition);             
//        }
//    }
//    bPrint_Trace = false;
//    aMD_Spheres.Clear();
//    aMD_Spheres.Add(MeshDraft.Sphere(sphere_Radius, 36, 32));
//    cylinder_MD.Clear();

//    Set_Tetra_Verts(tetra_Radius);

//    float face_dist;
//    float tetra_Height;
//    Vector3 face_Norm;
//    float a, b;

//    if (sphere_Radius_Last != sphere_Radius)
//    {
//        for (int i = 0; i < 4; i++)
//        {
//            face_dist = face_Centers[i].magnitude;
//            tetra_Height = 1.33333f * tetra_Radius;
//            a = 2 * Mathf.Sqrt(2) / 3;
//            b = Mathf.Sqrt(sphere_Radius * sphere_Radius - tetra_Radius * tetra_Radius * 8f / 9f);
//            face_Norm = face_Centers[i].normalized;

//            spheres[i].transform.localPosition = face_Norm * (tetra_Radius / 3 + b);
//            spheres[i].transform.localRotation = Quaternion.LookRotation(sphere_pos[i]);
//            spheres[i].GetComponent<MeshFilter>().mesh = aMD_Spheres.ToMeshInternal();
//            tetra_Verts_GO[i].transform.localPosition = tetra_Verts[i];
//        }
//    }
//    sphere_Radius_Last = sphere_Radius;
//    tetra_Radius_Last = tetra_Radius;
//    //if ((sphere_Radius_Last != sphere_Radius || tetra_Radius_Last != tetra_Radius) && bTetraTerrean_On)
//    //{
//    aMD_TetraTerrean.Clear();

//    for (int i = 0; i < 4; i++)
//    {
//        aMD_tt_Faces[i].Clear();
//    }

//    Create_TETRA_TERREAN(all_Shape_Depth);
//    if (bSeparate_Faces)
//    {
//        for (int i = 0; i < 4; i++)
//        {
//            tt_Faces[i].GetComponent<MeshFilter>().mesh = aMD_tt_Faces[i].ToMeshInternal();
//        }
//    }
//    else
//    {
//        TetraTerrien_GO.GetComponent<MeshFilter>().mesh = aMD_TetraTerrean.ToMeshInternal();
//        TetraTerrien_GO.GetComponent<MeshFilter>().mesh.RecalculateNormals(60);
//    }

//    aMD_TT_Sleeve.Clear();
//    Create_TETRA_TERREAN_Sleeve();
//    TT_Sleeve_GO.GetComponent<MeshFilter>().mesh = aMD_TT_Sleeve.ToMeshInternal();
//    TT_Sleeve_GO.GetComponent<MeshFilter>().mesh.RecalculateNormals(60);

//    sphere_Radius_Last = sphere_Radius;
//    tetra_Radius_Last  = tetra_Radius;

//    if (bSpheresON)
//    {
//        ShowSpheres(true);
//    }
//    else
//    {
//        ShowSpheres(false);
//    }
//}

 

Unexpected Result

    public void OnShow_Differential_Rings()
    {
        if (amd == null)
        {
            amd = new ArgosMeshDraft();
        }
        else
        {
            amd.Clear();
        }

        GetComponent<MeshRenderer>().enabled = true;
        setColor(orbitColor);

        List<Vector3> vInnerLower = new List<Vector3>();
        List<Vector3> vOuterLower = new List<Vector3>();
        List<Vector3> vInnerUpper = new List<Vector3>();
        List<Vector3> vOuterUpper = new List<Vector3>();

        List<Vector3> vDisk = new List<Vector3>();

        float op = Mathf.PI * 2f;
        float delta_theta = op / 180;
        float theta = 0;

        Vector3 vPos_Lower;
        Vector3 vPos_Upper;
        Vector3 vNorm;
        float w_by_2 = cylinder_Width * 0.66666f;//to differentiate from Helix
        float rad = cylinder_Radius;

        Vector3 vZero = (cylinder_Offset + cylinder_Height / 2) * Vector3.up;
        vDisk.Add(vZero);

        for (int i = 0; i < 180; i++)
        {
            vPos_Lower = rad * Mathf.Cos(theta) * Vector3.right + rad * Mathf.Sin(theta) * Vector3.forward;

            float theta_Mod = theta % (Mathf.PI*2f/3f);
            float lout = rad;

            if (theta_Mod < 60)
            {
                lout = (1f - 0.5f * theta_Mod / (Mathf.PI/ 3f));
            }
            else
            {
                lout = (0.5f + 0.5f * (theta_Mod - (Mathf.PI / 3f)) / (Mathf.PI / 3f));
            }
            vPos_Lower *= lout;
            vPos_Upper = vPos_Lower;
            vNorm = vPos_Lower.normalized;
            vPos_Lower += cylinder_Offset * Vector3.up;

            vInnerLower.Add(vPos_Lower - w_by_2 * vNorm);
            vOuterLower.Add(vPos_Lower + w_by_2 * vNorm);

            vPos_Lower += (cylinder_Height / 2) * Vector3.up;
            vDisk.Add(vPos_Lower - w_by_2 * vNorm);

            vPos_Upper += cylinder_Height * Vector3.up + cylinder_Offset * Vector3.up;

            vInnerUpper.Add(vPos_Upper - w_by_2 * vNorm);
            vOuterUpper.Add(vPos_Upper + w_by_2 * vNorm);

            theta += delta_theta;
        }
        amd.Add(MeshDraft.Band(vOuterLower, vInnerLower));
        amd.Add(MeshDraft.Band(vInnerUpper, vOuterUpper));
        amd.Add(MeshDraft.Band(vInnerLower, vInnerUpper));
        amd.Add(MeshDraft.Band(vOuterUpper, vOuterLower));

        if (bAdd_Disk)
        {
            amd.Add(MeshDraft.TriangleFan(vDisk));
        }
        GetComponent<MeshFilter>().mesh = amd.ToMeshInternal();
    }


 

 

MultiVerse – Electric Universe Introduction

plasma discharge in rock
&

plasma discharge in laboratory 

If you saw last month’s edition and watched the various videos you will have a basic understanding of our Electric Universe and how it controls our environment. In part two we look a little deeper into our charged reality.
Even if your interest is to see if and how it might fit in with alternative healing techniques like Reiki and working with Quart Crystals or whether free energy is possible, then a basic understanding of electrics should be gained. Like what a capacitor does and how it works will with the comprehension, make your work even more successful, as well as helping with the understanding of the whole cosmology.

 

PIEZOELECTRICITY
Parts 1 2
For example, the earth/ionosphere system is a capacitor with the earth being one pole and the ionosphere being the other, with atmosphere being the insulation between the two with the cloud layers being circuit breakers as the voltage from the ionosphere grounds to earth.
Because the cosmology is simple and is totally scalable from the very, very small to the very, very big, an understanding of the workings is advisable but not necessary. Unlike the standard model though, one thing is for sure; you don’t have to believe in it with blind faith like the traditional (I won’t call it science as it has little if anything to do with science) fiction, as it comes from the ideals of the true scientific method of Observation, Measurement, Lab Experimentation and Prediction that proves correct.
Even though both the standard model of cosmology and the electric one have both been around for over a hundred years, the electric one was forced into the shadows with the main stream keeping electric cosmology hidden from view. It threatens every thing they believe to be true and what gives them a wage, power and prestige.
So sad truth, they are not going to give up easily without a fight. They do not want to admit to themselves or have the world know that they are just believers in very bad fiction. After all it is easier to accept the money along with the poor mathematical speculation rather than something they know very little about, electrical engineering and plasma physics.
This is plainly seen when they ask a typical question like- ‘If the sun is arcing from electrical activity rather than being fired by a internal nuclear reaction, why doesn’t all the planets fry by the current coming from the galactic centre?’ This shows that they have no absolutely no idea about the fourth state of matter or how in reality it functions with its plasma sheaves.
bipolar nebular M2-9

The reason mater plasma was named after blood plasma was because of its many life like properties, including that of a tiny cell. Like a biological cell it creates a cell wall to protect itself from the environment, so anything inside that wall will be protected and this is the reason why the planets and other bodies revolving around the sun don’t get fried.
The current that is constricting the ionized gases that form the sun (Z-Pinch) can’t hit the planets directly as the arcing sun sets up its own protective sheaf. So even if a wandering glowing gas giant that was travelling through interstellar space and which was picking up the current from galactic centre, once it entered the suns heliosphere it would then stop glowing as the power would be turned off by the sun’s protective sheaf.

 

Because it was now receiving its electricity from the sun rather than the galactic centre the power would be stepped down and would then in turn step down its power and relay the electricity to its own satellites.

 

WHAT IS CHARGE SEPARATION? (+ & -)

 

When thinking of charge separation I look at it as more charge and less charge and because all things in nature likes to balance, it is the greater giving some of its charge to the lesser to arrive at balance and bring the charge back together.

 

MAGNETS
Electricity creates magnetic fields with one being an intrinsic part of the other but it is the electricity that is the original source. Every bi-polar bar magnet is just an induced object aligning the spin of its atoms to one direction but the original source is flowing electricity in a circuit. So even though a bi-polar magnet doesn’t have any electrical power itself, it was electricity that even through is generations down the line, is the source of the magnetism.

 

CAPACITORS
The dielectric (insulator) in a capacitor between the two poles, be it paper or atmosphere between the ionosphere and the earth is a poor conductor of electricity and so stops the balancing of the lesser and higher charge until enough charge has been built up in the dielectric so it can then bridge the gap and complete the circuit.
There are two main types of capacitors, one like in a flashgun of a camera which lets the charge first build up before letting it go in one bright blast (or like Ionosphere to ground via lightning on Venus) and the other more commonly used one which is used in circuit boards and acts like a water tank. It fills up with charge and then releases that charge through an overflow in a steady flow.

 

ELECTRICAL FLOW GIVES THREE TYPES OF PLASMA
Power lines transmit high tension electricity down their lines and we usually can’t see if they are turned on or off due to their insulating coating but even though they are protected by their coating, they can sometimes be seen to glow under the right atmospheric conditions, misty and when the sun is not blasting light everywhere i.e. dawn.
We don’t see the electricity in a cable be it high tension or in lower voltage in the home because the right amount of current is following through it for its size plus it has its protective coating. But if we increase the current in the wire it will glow like we see in the filament of a light bulb and if even more current is applied, then an electrical explosion will occur as it tears itself apart under the electrical tension. Like a meteor fire ball trying to take on the electrical potential of entering earth’s electrical environment and then exploding.

 

The are three types of mode of electrified plasma.

1, Dark Mode when the voltage is low so we don’t see anything but can still measure it (I though prefer to call it ‘invisible mode’ to differentiate from mystical substances like dark matter which can’t be in any way be detected or measured), just like radio waves which are not seen.

2, Glow Mode when there is an increase in power and we start to see it, like in a fluorescent tube.

3, When there is even more power and it arcs, like a lighting bolt or the surface of the sun as a arcing plasmoid. This is clearly seen in bipolar nebular with the Z-Pinch clearly in effect by constricting the ionized gas and then making it glow.

bipolar nebular IRAS 13208-6020

<><><>
EXAMPLES OF AN ELECTRICAL UNIVERSE EVERYWHERE
Sitting in the Western Sahara Desert in Mauritania and which can be seen from space is a geological oddity called the Richat Structure, aka The Eye of Africa. It is not a small earth feature, with London very easily sitting inside of it.
First guess by the traditionalists was that it was a volcano but this was eventually ruled out because even though it was extrapolated from the traditional mathematical guess work, it was in fact a really silly idea because it was absolutely nothing like a volcano.
Now the last piece of speculation is that it is simply a perfectly round uplift in the crust. They of course can’t explain why it looks the way it does with it being round with multiple circular formations within it and that it looks like a plasma discharge, so they completely ignore this.
If this doesn’t show that a lot of traditional science guesses very poorly first based on doctrine and then looks at the evidence to try and shoehorn it into an ill fitting tenet, I don’t know what does.

 

&
THE MAINSTREAM NOW SEES ELECTRICITY IN SPACE?

 

In the article it says that the team thinks that the magnetic fields are from a black hole which is then somehow creating the current, mmm. Once again they can’t describe the mechanism behind it of course.
Anyone who has studied plasma physics knows that all magnetism originates from electricity. This is real basic stuff, so what does that also say about the publications that print this type of article.
&
&
SATURN’S ELECTRIC MOON ENCELADUS
 
 

It was reported and confirmed this week that the mainstream scientific community are as much in the dark as they have ever been. So once again we must ask, is this more evidence of ignorance in the main stream because they have been blinded by quasi religious doctrine and tenet?

To me this is probably the reason for most, which means that they should be just sacked without delay so they can give up on science, go back to school and learn some physics.

But for others it seems like they are they deliberately trying to cover up the actual truth of the true scientific method that is being carried out by real scientists and researchers, in which case they should be fined to the full extend and sent to jail for fraud because of the funding that they receive from the tax payer?
&
Parts 1 & 2
THE STANDARD MODEL CONTINUES TO CRUMBLE
 
supposed hexagon impact craters on mars

As it becomes continuously evident to more and more people that the old worn out ideas of how our reality works is not only wrong but really stupid and even amounting to fraud, some traditional scientists are now actually opening their eyes and looking to see the evidence that we live in an Electric Universe.
Even after decades of failing, it seems almost laughable how most traditional scientists still cling onto guesswork that plainly does not work and has been proved that it hasn’t worked for many decades.
In many discussions with various teachers and university lecturers over the last couple of years, the vast majority that I have talked too have said how disillusioned they are with just preaching doctrine and that there should really be a change in how we educate. The system is broken and a Band-Aid plaster is just not enough when there is major blood loss. So we are looking to come up with new ideas so we can excite and encourage learning and development and so forward humanity.
And this starts with teaching truth over doctrine and reestablishing the Scientific Method and getting rid of meaningless contorted mathematical speculation. You can only describe something with math and so is important but as we have continually seen, it can’t predict anything as it is just very poor fantasy which can only take us down into a very dark void if we carry on with this path.

 

We do have hope for the future though, as now this deceit that masquerades as truth is being forced into the wider consciousness with the religious like dictates of scientism being proven to be on a continuing slide into absurdity.

 

But for those scientists in the scientism quasi religion who are now looking to follow the true ideals of the scientific method over ridiculously poor guess work. They are finding themselves in a quandary, as they will have to either give up on doctrine that at the moment brings an income and disrespect, or join in the revolution to bring to an end and short circuit the current situation and hold their heads high.

 

*
How ever much they push and squeeze their ideas though, scientism is being continually shown that they know very little, apart from incredibly poor imaginings and has nothing at all to do with physics. Physics only deals with real stuff which is truly quantifiable and not conceptual guesswork.
Could most of accepted gospel really be wrong? Oh yes, because of the way our education system works which is a hierarchal system built on a constructed gauge of intelligence just built on IQ with just the capacity to remember doctrine and some other real facts, name and dates. It doesn’t at all include common sense, creativity, or emotional maturity which is among most of my academic teaching friends, now an absolute must.
It has been clearly shown that without these we stay in the state that we are now in. But when we especially take into account emotional maturity, we can see that intelligence can actually change over a life time. So this posses some interesting questions and indicates that, once you reach a level, that level can then be adjusted up and indeed down.
*
&
*
“GRAVITY WAVE DETECTION IS KAPUT”
“In the Electric Universe paradigm, laboratory experiments requiring relatively inexpensive equipment can be conducted and compared to the theory. Since electricity’s effects are scalable by many orders of magnitude, how it behaves in space is often consistent with its behavior in the lab.”

 

*
THE LATEST FROM EU2014
DAVID TALBOTT: SYMBOLS OF AN ALIEN SKY
This talk was given by David Talbott on the opening night of EU2014 conference in Albuquerque, New Mexico. It was an introduction to his two Sunday presentations that previewed Episodes 4 and 5 of the Symbols of an Alien Sky series.
&
DWARDU CARDONA: EARTH’S PRIMORDIAL STELLAR HOST
Dwardu Cardona showed that a reconstruction of Earth’s cosmic history can be distilled from the universal “mytho-historical record,” complemented by studies in earth history and space science. Most recently, the strongest scientific validation comes from space, as new instruments enable the viewer to see extraordinary electro-magnetic detail across the cosmos, confirming that this is indeed an Electric Universe.
&
WAL THORNHILL: REINTERPRETING THE MAVEN MISSION TO MARS
Wal Thornhill looked critically at the assumptions behind the recent MAVEN Mars Probe (Mars Atmosphere and Volatile Evolution Mission.) The probe, NASA says, seeks to measure the loss of volatiles from the Martian atmosphere in order to draw conclusions about the planet’s remote past. He reminded us that all of the scientific objectives of the MAVEN Mission were developed under standard assumptions about a 4 billion-year old solar system. What’s more, Wal showed how, under the inertia of belief systems, evidence can be distorted or ignored and contrasted this with the rapidly accumulating evidence for a highly catastrophic and recent history of Mars.
&
MEL ACHESON: HOW SCIENCE CAN LOSE ITS WAY
“Mel Acheson has contributed numerous insights to the Electric Universe movement for more than 15 years, giving readers both a chuckle and something to think about.”
&
*
THE ELECTRIC UNIVERSE: A BOOT CAMP FOR THE SERIOUS MINDED
If you are into the real scientific method of Observation, Measurement, Lab experimentation & Prediction that proves correct, rather than mathematically guessing first and then finding evidence that don’t back up the pointless speculation, then you might want to consider being at the forefront of teaching proper science in the future.
<><><>
<><><>
INTERVIEW WITH NIKOLA TESLA IN 1899?
Most people will be totally amazed that Mr. Tesla said these things even before the twentieth century began. But is it true? In the world of information and disinformation how accurate is it, as the article doesn’t say where the original source of the transcript came from we are left to guess if it’s real.
<><><>
LEPOINT & THE THUNDERBOLTS PROJECT
The most famous independent plasma researcher who is not directly or indirectly connected to the Thunderbolts Project is David LePoint (not his real name), with his experimentation and ideas leading him to think that he not only knows how matter works but also light.
When I spoke to Dave T last year I asked him about LePoint’s work Primer Fields and if they going to invite him to EU2014. He said that they had real trouble contacting him to start with but when they finally did, he came across as a touch antagonistic and suspicious and because he hasn’t researched the subject past his own work, this isn’t going to happen at any time soon due to his misunderstanding of what is going on with his own experimentation.
If LePoint’s doesn’t really want to discus his ideas openly or even look more deeply into plasma physics, then he will not know that he will have adjust his thinking and so will stay in the dark, even if he lights up his vacuum chamber.
The fundamental differences between what LePoint says and what is known by the Electric Universe is the way Le Point constructs his plasmoids. Where as a normal plasmoid is formed by a Z-Pinch with the constricting magnetism holding the plasmoid together and then arcing on the outside.
He does it by the anode (+) of the electrical circuit being at the centre which then builds the plasmoid around it and so making it glow from the inside. This means that rather than the plasmoid being formed by an electrical current forming a magnetic pinch from the electrical circuit, he has to use external artificially constructed magnetic bowl emitters to make it hold its shape.
So even though it looks impressive, what he has actually created is a type of fluorescent tube. But seeing he seems to be such a recluse, he doesn’t to want to discuss it, or even know what else is really being experimented with by those connected to the Thunderbolts Project i.e. the Sapphire Project.

 

&
&
<><><>
TAKEN TO COURT OVER FOSSILS
 
 
As we have seen in previous months the question of the conventional ideas of how animals remains became stone has been shown that it couldn’t have happened as traditionally guessed.

&

<><><>
THE FREE ENERGY PARTY IN THE U.S
“We are asking loyal Democrats and Republicans to boycott their parties in 2016 and vote for  the FEP. This is the only hope for saving your party for the future, possibly even the US, as we know it. The FEP is the first party in history supporting what people want and demand. A landslide election in 2016 is vital to remove the for sale sign in Washington. Do you believe politicians should be for sale? NO! This party stands up for FREEDOM in the marketplace. Fascism is the illegal marriage between Monopolies and government, clearly collusion and racketeering under the RICO act and is illegal in this great country.”
&
<><><>

 

NASA STARTS TO LOOK AT AN ELECTRICAL EXPLANATION BUT NOT EVERYWHERE
 
The standard model is falling apart before our eyes and at an every increasing rate and they are now desperately trying to catch up. So why don’t they just ask those in the Thunderbolts Project and find out what is actually happening. Ego comes to mind with the fear that everybody will find out that they are continually wrong in their poor guess work. This will also lead to their other fear, that they will loose their pay packets and have to get a real job.
I have suggested before that because some fast food chains are looking for people with letters after their name to prove that their food products are wholesome and perfectly fine, they would fit in perfectly and so should maybe apply without haste.
Because mainstream’s knowledge of how plasma and electrical engineering works amounts to a not a lot, they still have to say thing like this (from their YouTube page)-
NASA Goddard “For the first time, scientists have watched a pulsar transition from a low-energy to a high-energy system. Watch an animation on how we think this happened”. Of course they don’t actually speculate where the energy comes from and so have to use these throw away remarks as they have to say something.
They do say that they discovered the pulsar in the first place because of its radio emissions but fail to mention that radio like light is all part of the Electromagnetic Spectrum. But somehow they missed the electrical connection, so should these people be allowed to take the Mick out of themselves and want to do it so openly? Surely they should really go and seek medical help from a mind doctor as they plainly suffering from cognitive dissonance.
In reality the terminology that should be used in the accompany copy to the video should be something along the lines of- Actually even though the engineers have built some fantastic pieces of equipment, we still don’t know what the **** is going on.

 

Even though one branch of NASA is now trying to somehow get an electrical explanation by using the word ‘Transformer’ in the title of the video, other branches are clearly not.
In the next clip we hear the traditional non-understanding of what is going on. Are these people really scientists? Well maybe by qualifications only but certainly not by what science is supposed to represent..
I am actually now wondering if they put out this guess work just to give us something to laugh and write about. Of course I really doubt this but I would like to take this opportunity to say thanks for giving us such a belly ache at the ridiculous nature of it all.
<><><>
Since Hawking and a colleague came up with equations to prove that black holes theoretically exist, Hawking has since adjusted his mind to something else, money for old rope comes to mind. For those who are more mathematically minded, this is once again the Mathman talking total sense, so it’s no wonder that the main stream don’t like Stephen Crothers.
<><><>
THE RECENT WHOLE IN SIBERIA
 
&

As we see from the video the crater at the top looks like it has dendritic ridges in the crater walls and is similar to one on mars but without the whole underneath.

So this could be an electrical event which then caused a gas explosion underground. If it was purely a gas explosion I thought there would be more debris around the crater because of the size and depth of the hole and now some scientists who have visited the site have said that there is no evidence that there was an explosion but there is scorching marks around the crater.
So we need to examine the crater walls and see if fulgurites are present in the dendridic ridges of the crater walls. This is after all a landscape rich in historical electromagnetic activity, the Siberian flux lobe with the whole area pocked marked with holes in the surrounding landscape.
&
<><><>
SWARM CONFIRMS POLE SHIFT
 
 
The electrical engineers who built this fantastic piece of satellite kit should be applauded as it was designed to do real science in the first place and is now returning real data to help us understand our reality.
&
&
<><><>
<><><>
<><><>
“DUTCH ARCHAEOLOGISTS FIND 13,000 YEAR OLD SILVER BOWL”
Once again more evidence is being unearthed that traditional scientific guesswork is wrong. With the level of workmanship on this bowl, it is hard to believe that stone-age man and woman whose conversation amounted to words like ‘ugggg’ could possibly produce such a fabulous works of art as this.
<><><>
9 YEAR OLD GIRL USED CANNABIS THERAPY TO CURE HER CANCER
 
 
While other countries around the world are seriously looking at the wonder plant for its medical uses, the massive money making pharmaceutical companies in the UK and U.S carry on lining their pockets with their government’s blessings.
<><><>
<><><>
<><><>
A NEW MODEL FOR EVOLUTION
Getting away from the purely mechanistic view of reality that is taught as gospel means that there are other ways at looking for truth. Once we get away from belief, doctrine and tenet, we can see that evolution rather than purely happening by random mutation of our genes, could also involve the continuation of a species by passing on information through telepathy and other methods and that this would require an all encompassing field for the information to travel through.
&
&
&
WE NEED MORE REAL SCIENTISTS LIKE THIS
 
 
Rupert Sheldrake is now famous (in proper scientific circles) for his scientific observation and measurement showing how his research which he calls Morphic Field seems to produce templates in nature.
&
<><><>
NOT BEING HELD BACK BY TRADITIONAL SCIENTIFIC DOGMA
 
 
We are all capable of making mistakes and that is why forums like the independent and unofficial Thunderbolts Project Facebook page is so useful. But not only in strict terms of accepted plasma cosmology but also, other free thinking ideas connected to the Electric Universe. Because it is the unofficial TP page we can get into some quite interesting spheres where the less obvious is also discussed, an example from yours truly-
“From the book Sirius (previously mentioned) D.K aka The Tibetan Master back when he was associating with Bailey said of an electric sun on a base level- “The mystery of Electricity, connected with the physical sun and the third aspect.” & “…and direct three major streams of electrical force in connection with our present globe.” Because the other side of the fence includes people who are not aware that another cosmology even exists and because they come from all levels exoteric and esoteric, they are prepared to take it on board when it is explained.
I know in this modern age of science we need to verify by the scientific method what is true and what is false but as this comes from the very old Ancient Wisdom Teachings, we can only go by what is written and see if today’s scientific method can verify it and so yes it will be classed as mysticism. This though shouldn’t be automatically disregarded just because it isn’t written with today’s scientific understanding, measurement and calculations.
Because of the many thousands of years since this was seemed to be known about, the world that we know now has gone through massive disruptions, so we can’t possibly know if it was intuited or measured at the time but because of it looking like the pyramids were used to collect electricity on a world wide scale we shouldn’t ignore it.
So at this point in time all we do is look at how it aligns with today’s known facts and they do align very well. Obviously such modern terms as Birkeland Currents wouldn’t have be used and so words like streams would have been used but at a time of its first printing in 1951, Bailey’s work (which is taken directly from D.K. the Tibetan) does say that the sun is electric when the common view was that it was nuclear.”

 

&
THE BOSNIAN PYRAMID
 
This is still an ongoing question in my mind. I have debated many times as to the validity of this strange structure. A lot of people in the E.U community think that it is a gigantic ongoing money making hoax and quote articles that they say proves it is just a hill. But the trouble is that they can only show examples from 2006 and as we have seen, a hell off a lot has happened in the last eight years, both in the normal world as well as the world of science.
I am not saying that I believe that it is real but that there is enough evidence to take the investigation further. Unfortunately there is some evidence (yet to be fully verified) that the man leading the investigation might not have told the whole truth in what he has said in the past.
*
“There has been much talk of the Bosnian Pyramid over the years and weather it’s a hoax. If you look in wikipedia you see that they call it a hoax but then again they call our Electric Universe rubbish and pseudo science so we can’t automatically take what they with anything else but a very large pinch of salt.”
*
“Suspicious of anything main stream like the Smithsonian, especially when they have an opening gambit of “amateur archaeologist” in the article. This a typical trick to put people in a disbelieving frame of mind to start with. We can see this trick when they talk about people being into the EU as cranks. When you look at his credentials I don’t think amateur is hardly a truthful description and so I wouldn’t trust anything they say. Maybe I am wrong but surely someone who is- Anthropology Professor at the American University in Bosnia. Foreign Member of the Russian Academy of National Science. Member of the Archaeology Society of Alexandria. PhD in Mayan Studies can really be described as an amateur. The only reason that they can get away with it is because he set up the non-profit “Archaeological Park: Bosnian Pyramid of the Sun” Foundation.”
*
“What, does the mainstream media, governments and scientific institutions really get involved in cover ups and direct miss truths? There are thousands of pyramids all over the world and on every continent and the first 45 mins deals with this. It then goes onto to talk about the biggest pyramid in the world and even touches on Tesla who lived by coincidence just a little way away from it.”
&
HOW WERE THE EGYPTIAN PYRAMIDS BUILT
 
 

I have shown this before but that was a while ago now, so is worth a look if you haven’t seen it yet. Even though it goes with the traditional estimation as to when it was built, the importance of this is the construction.

<><><>
<><><>
<><><>
STRANGE SOUNDS AROUND THE WORLD

I haven’t touched on this for a while so in light of our electrically active earth environment and the amount of metal particulates in chemtrails that are being pumped into the atmosphere, I think we should once again remind ourselves of the phenomena. I like the report @ 07:55 because it happened at a live sports event and was commented on.

<><><>
POST 2012
 
 
The Mayan scholar John Major Jenkins was very much at the centre of the fuss that surrounded the date of 21st of December 2012 and was then of course at the centre of the controversy after not much on the surface seemed to happen.
Even though it was the MSM that was building it up to be the End of the World rather than being the End of the World as we Know it, it was them who quickly starting shouting foul when the world didn’t end as they reported it.
But with a change of such a big cycle (26,000 years) surely shouldn’t we have seen some sort of massive change. Shouldn’t even the ‘End of the World as we Know it’ show some sort of movement to a new state of things. With such big cycles though, any instant change has to be seen taken place over a few years rather than just one day.
If we think that half way around this great cycle was the end of the Ice-Age and the then explosion of creative thought and development within humanity, then we were right to expect something at least as big as that last shift but we must also remember that it didn’t happen overnight. So has our reality now started to go through unbelievable changes?
Undoubtedly the massive melt which would have happened after the last big freeze would have had a massive psychological effect on humanity. So what will be the catalyst to wake people up this time?
From my perspective I see the battle that is now raging between the old mechanical nuclear driven universe and is a continuation of a belief system and our electric one built on the true scientific method being that event. When everyone takes on board that all we have been taught to think of as gospel, when it is in fact just very poor fiction, this will be the alarm clock that wakes people up.
When we consider that modern mathemagicians uses only the force of gravity (remember according to Einstein it isn’t even a force but a curvature of space/time) with only 3 types of matter (Solid, Liquid & Gas) and mainly ignores Plasma the fourth state of matter. (which makes up at least 99.99% of all matter in the universe) we begin to see that it is not only science or even education that will change but a whole lot of other stuff too.
And when we consider that the electromagnetic fields running through Plasma, which is 1000, billion, billion, billion, billion times more powerful than gravity, we can see just how wrong the standard model is and how big the shift if likely to be, with our whole world going down an electrical path into a new era.
<><><>
<><><>
<><><>
<><><>
EXTRATERRESTRIAL AFFAIRS
NASA DISCUSSES THE SEARCH FOR OTHER LIFE IN THE UNIVERSE
Traditional scientists continually ask, “If ET is out there then why haven’t we seen them”. Is this just arrogance at their own belief that they have a superior intellect and so should be the only ones that ET would naturally want to say hello to. In a total disregard of all the hundreds of thousands of reports that go back into the distant past, they seem to think that only their guess work matters?
I bet they haven’t once considered the fact that because they are part of religion of scientism and believe in mythical substances like dark matter & energy and gene like objects in the middle of galaxies, Et might actually be looking for intelligent life on earth elsewhere and that they found it in the common man who although that they might not always have the highest I.Q’s, might actually have abundant common sense, creativity and emotional intelligence and so take an interest in and commune with them instead.

Because of the size of their own self importance this wouldn’t even occur to them because apart from being able to do some complicated sums and spout unproven doctrine, there really isn’t too much else there. Personally I couldn’t watch much of the following video (about 15 mins) because I have heard it all before and it’s the same poor guess fiction and so is pointless and a waist of time in my life.

<><><>
<><><>
&
<><><>
<><><>
<><><>
FROM 1976: OVERLORDS OF THE UFO
A scientific documentary that was suppressed and banned. It features military footage, lost photos and other evidence.

Code Reference – AllShape

 

Thor Brigsted

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

/// <summary>
/// Helper class that represents a parameterized vertex
/// </summary>
public class Vector3Param {
	///bernstein polynomial packing 
	public List<List<float>> bernPolyPack;

	///Point after applying s,t,u to p0, should result in original point
	public Vector3 p = Vector3.zero;

	///Origin
	public Vector3 p0 = Vector3.zero;

	///Distances along S/T/U axes
	public float s,t,u;

	public Vector3Param()
	{
		s = 0.0f;
		t = 0.0f;
		u = 0.0f;
	}

	public Vector3Param(Vector3Param v)
	{
		s = v.s;
		t = v.t;
		u = v.u;
		p = v.p;
		p0 = v.p0;
	}

};

/// <summary>
/// Free form deformation class
/// 
/// Based off of the paper 'Free-Form Deformation of Solid Geometric Models'[1] this class
/// creates a system of control points that can deform a mesh as if that mesh was embedded
/// in a flexible parallelpiped.
/// 
/// Confused?  Yeah, who uses the term parallelpiped.  The idea is to create a uniformly spaced
/// grid of control points around some mesh.  Each control point has some effect on the mesh, like
/// bone weighting in animation.  The effect each control point has is directly proportional to the
/// total number of control points in the entire grid, each exerts some control.
/// 
/// [1] - http://pages.cpsc.ucalgary.ca/~blob/papers/others/ffd.pdf
/// </summary>
public class FreeFormDeformer : MonoBehaviour {

	/// <summary>
	/// Allow FixedUpdate to modify the mesh.
	/// </summary>
	public bool AllowMeshUpdate = false;

	/// <summary>
	/// Target to be morphed
	/// </summary>
	Mesh MorphTarget = null;

	/// <summary>
	/// Target to be filtered (assumed to contain a meshfilter and valid mesh)
	/// </summary>
	public MeshFilter MorphTargetFilter = null;

	/// <summary>
	/// Update frequency in seconds
	/// </summary>
	public float UpdateFrequency = 1.0f;

	/// <summary>
	/// Game object to represent a control point.  Can be anything really, I suggest spheres.
	/// </summary>
	public GameObject ControlPointPrefab;

	/// <summary>
	/// Local coordinate system
	/// </summary>
	Vector3 S, T, U;

	/// <summary>
	/// Number of controls for S, T, & U respectively.  (L,M, and N MUST be >= 1)
	/// </summary>
	public int L=1, M=1, N=1;

	/// <summary>
	/// Time elapsed since last update
	/// </summary>
	float elapsedTime = 0.0f;

	/// <summary>
	/// Grid of controls points. Stored as 3D grid for easier because width,height, and depth can randomly vary. 
	/// </summary>
	GameObject[, ,] controlPoints;

	/// <summary>
	/// Original vertices from MorphTarget
	/// </summary>
	Vector3[] originalVertices;

	/// <summary>
	/// Current updated vertices for MorphTarget
	/// </summary>
	Vector3[] transformedVertices;


	/// <summary>
	/// Vertex parameters
	/// 
	/// Each vertex is given a set of parameters that will define
	/// its final position based on a local coordinate system.
	/// </summary>
	List<Vector3Param> vertexParams = new List<Vector3Param>();

	void Start () {
		MorphTarget = MorphTargetFilter.mesh ;
		originalVertices = MorphTarget.vertices;
		transformedVertices = new Vector3[originalVertices.Length];

		Parameterize();
	}

	/// <summary>
	/// Calculate a binomial coefficient using the multiplicative formula
	/// </summary>
	float binomialCoeff(int n, int k){
		float total = 1.0f;
		for(int i = 1; i <= k; i++){
			total *= (n - (k - i)) / (float)i;
		}
		return total;
	}

	/// <summary>
	/// Calculate a bernstein polynomial
	/// </summary>
	float bernsteinPoly(int n, int v, float x)
	{
		return binomialCoeff(n,v) * Mathf.Pow(x, (float)v) * Mathf.Pow((float)(1.0f - x), (float)(n - v));
	}

	/// <summary>
	/// Calculate local coordinates
	/// </summary>
	void calculateSTU(Vector3 max, Vector3 min){
		S = new Vector3(max.x - min.x, 0.0f, 0.0f);
		T = new Vector3(0.0f, max.y - min.y, 0.0f);
		U = new Vector3(0.0f, 0.0f, max.z - min.z);
	}

	/// <summary>
	/// Calculate the trivariate bernstein polynomial as described by [1]
	/// 
	/// My method adapts [1] slightly by precalculating the BP coefficients and storing
	/// them in Vector3Param.  When it comes time to extract a world coordinate, 
	/// it's just a matter of summing up multiplications through each polynomial from eq (2).
	/// </summary>
	/// <links>
	///  [1] - Method based on: http://pages.cpsc.ucalgary.ca/~blob/papers/others/ffd.pdf
	/// </links>
	/// <param name="p0">Origin of our coordinate system (where STU meet)</param>
	void calculateTrivariateBernsteinPolynomial(Vector3 p0){
		Vector3 TcU = Vector3.Cross(T, U);
		Vector3 ScU = Vector3.Cross(S, U);
		Vector3 ScT = Vector3.Cross(S, T);

		float TcUdS = Vector3.Dot(TcU, S);
		float ScUdT = Vector3.Dot(ScU, T);
		float ScTdU = Vector3.Dot(ScT, U);

		for (int v = 0; v < originalVertices.Length; v++)
		{
			Vector3 diff = originalVertices[v] - p0;

			Vector3Param tmp = new Vector3Param();
			tmp.s = Vector3.Dot(TcU, diff / TcUdS);
			tmp.t = Vector3.Dot(ScU, diff / ScUdT);
			tmp.u = Vector3.Dot(ScT, diff / ScTdU);
			tmp.p = p0 + (tmp.s * S) + (tmp.t * T) + (tmp.u * U);
			tmp.p0 = p0;
			tmp.bernPolyPack = new List<List<float>>();

			{	// Reserve room for each bernstein polynomial pack.
				tmp.bernPolyPack.Add(new List<float>(L));	//outer bernstein poly
				tmp.bernPolyPack.Add(new List<float>(M));	//middle bernstein poly
				tmp.bernPolyPack.Add(new List<float>(N));	//inner bernstein poly
			}

			{	// Pre-calculate bernstein polynomial expansion.  It only needs to be done once per parameterization
				for (int i = 0; i <= L; i++)
				{
					for (int j = 0; j <= M; j++)
					{
						for (int k = 0; k <= N; k++)
						{
							tmp.bernPolyPack[2].Add(bernsteinPoly(N, k, tmp.u));
						}
						tmp.bernPolyPack[1].Add(bernsteinPoly(M, j, tmp.t));
					}
					tmp.bernPolyPack[0].Add(bernsteinPoly(L, i, tmp.s));
				}
			}
			vertexParams.Add(tmp);
			if (Vector3.Distance(tmp.p, originalVertices[v]) > 0.001f)
			{
				//Debug.Log("Warning, mismatched parameterization");
			}
		}
	}

	/// <summary>
	/// Parameterize MorphTarget's vertices
	/// </summary>
	void Parameterize(){
		Vector3 min = new Vector3(Mathf.Infinity,Mathf.Infinity,Mathf.Infinity);
		Vector3 max = new Vector3(-Mathf.Infinity,-Mathf.Infinity,-Mathf.Infinity);
		foreach(Vector3 v in originalVertices){
			max = Vector3.Max(v,max);
			min = Vector3.Min(v,min);
		}
		calculateSTU(max, min);
		calculateTrivariateBernsteinPolynomial(min);
		createControlPoints(min);
	}


	/// <summary>
	/// Create grid of control points.
	/// </summary>
	void createControlPoints(Vector3 origin){
		controlPoints = new GameObject[L + 1, M + 1, N + 1];
		for(int i = 0; i <= L; i++){
			for(int j = 0; j <= M; j++){
				for(int k = 0; k <= N; k++){
					controlPoints[i, j, k] = createControlPoint(origin, i, j, k);
				}
			}
		}
	}

	/// <summary>
	/// Create a single control point.
	/// </summary>
	GameObject createControlPoint(Vector3 p0, int i, int j, int k)
	{
		Vector3 position = p0 + (i / (float)L * S) + (j / (float)M * T) + (k / (float)N * U);
		return (GameObject)Instantiate(ControlPointPrefab, position, Quaternion.identity);
	}

	/// <summary>
	/// Convert parameterized vertex in to a world coordinate
	/// </summary>
	Vector3 getWorldVector3(Vector3Param r){
		int l = L;
		int m = M;
		int n = N;

		Vector3 tS = Vector3.zero;
		for(int i = 0; i <= l; i++){
			
			Vector3 tM = Vector3.zero;
			for(int j = 0; j <= m; j++){

				Vector3 tK = Vector3.zero;
				for(int k = 0; k <= n; k++){
					tK += r.bernPolyPack[2][k] * controlPoints[i,j,k].transform.position;
				}
				tM += r.bernPolyPack[1][j] * tK;
			}
			tS += r.bernPolyPack[0][i] * tM;
		}
		return tS;
	}


	void UpdateMesh(){
		elapsedTime = 0.0f;

		int idx = 0;
		foreach(Vector3Param vp in vertexParams){
			Vector3 p = getWorldVector3(vp);
			transformedVertices[idx++] = p;
		}

		MorphTarget.vertices = transformedVertices;
		MorphTarget.RecalculateBounds();
		MorphTarget.RecalculateNormals();
		MorphTarget.Optimize();
	}

	void FixedUpdate()
	{
		elapsedTime += Time.fixedDeltaTime;
		if (AllowMeshUpdate)
		{
			if (elapsedTime >= UpdateFrequency) UpdateMesh();
		}
	}
	// Update is called once per frame
	void Update () {
	
	}
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;
using VRTK.GrabAttachMechanics;
using ArgosTweenSpacePuppy;

public class Tetra_MAJOR : MonoBehaviour
{
    public enum State
    {
        FREE,
        ATTACHED,
    }

    public bool bTurn_Off_Collider = false;

    public State state;

    public enum SpokeState
    {
        OPEN,
        OCCUPIED,
    }

    public class Spoke_Tracker
    {
        public SpokeState spokeState = SpokeState.OPEN;
        public GameObject go_occupying = null;
        public float touchTimer = 0;
        public GameObject genSpoke;
    }

    private int id = 0;

    public GameObject[] vertsHT = new GameObject[4]; 

    public Spoke_Tracker[] spoke_Tracker = new Spoke_Tracker[4];
    [Range(0, 10f)]
    public float Radius_of_Action = 7f;

    [Range(0, 1.61803f)]
    public float tDurr = 0.7f;

    private bool bForce_update = false;

    private float tAccum = 0f;

    private float tween_Val = 0f;

    private float touchTimer = 0;

    private Spoke_Tracker attachedSpoke;
    private GameObject attachedTetra_go;

    private Vector3 start_Pos;
    private Vector3 end_Pos;
    private Quaternion qStart;
    private Quaternion qEnd;

    private HMD_Ctrl_Tracking hmd_Ctrl_Tracking;
    private VU_UI_MANAGER VU_UI;
    private ALL_Shape_Instancer all_shape_instancer;
    private bool bTouchGrabEnabled = true;
    private bool bGrabbed = false;

    private VRTK_InteractableObject vrtk_interact;

    public bool bInteractive = true;

    void Start()
    {
        hmd_Ctrl_Tracking = HMD_Ctrl_Tracking.Instance;
        VU_UI = VU_UI_MANAGER.Instance;

        all_shape_instancer = VU_UI.GetComponent<ALL_Shape_Instancer>();

        vrtk_interact = GetComponent<VRTK_InteractableObject>();

        vrtk_interact.InteractableObjectGrabbed   += new InteractableObjectEventHandler(DoObjectGrabbed);
        vrtk_interact.InteractableObjectUngrabbed += new InteractableObjectEventHandler(DoObjectUnGrabbed);

        Vector3[] face_Center = new Vector3[4];

        face_Center[0] = (vertsHT[0].transform.localPosition + vertsHT[1].transform.localPosition + vertsHT[2].transform.localPosition) / 3f;
        face_Center[1] = (vertsHT[1].transform.localPosition + vertsHT[2].transform.localPosition + vertsHT[3].transform.localPosition) / 3f;
        face_Center[2] = (vertsHT[0].transform.localPosition + vertsHT[2].transform.localPosition + vertsHT[3].transform.localPosition) / 3f;
        face_Center[3] = (vertsHT[0].transform.localPosition + vertsHT[1].transform.localPosition + vertsHT[3].transform.localPosition) / 3f;

        float avg_FC = (face_Center[0].magnitude + face_Center[1].magnitude + face_Center[2].magnitude + face_Center[3].magnitude) / 4f;

        Vector3 axis = new Vector3();
        Quaternion q;

        for (int i = 0; i < 4; i++)
        {
            spoke_Tracker[i] = new Spoke_Tracker();
            spoke_Tracker[i].spokeState = SpokeState.OPEN;
            spoke_Tracker[i].genSpoke = new GameObject();

            spoke_Tracker[i].genSpoke.name = "genSpoke_" + i.ToString();

            spoke_Tracker[i].genSpoke.transform.parent = transform;

            spoke_Tracker[i].genSpoke.transform.localPosition = face_Center[i].normalized * 2f*avg_FC;

            axis = vertsHT[i].transform.localPosition - face_Center[i];

            q = Quaternion.AngleAxis(180f, axis);

            spoke_Tracker[i].genSpoke.transform.localRotation = q;
        }


        //if (bInteractive)
        //{
        //    for (int i = 0; i < tet.Length; i++)
        //    {
        //        tet[i].id = i;
        //        tetras.Add(tet[i]);
        //    }
        //}


    }

    private void DoObjectGrabbed(object sender, InteractableObjectEventArgs e)
    {
        bGrabbed = true;

        touchTimer = 1f;

        //if (state == State.ATTACHED)
        //{
        //    //octa_Major.Detach(id);
        //    state = State.FREE;
        //}
    }

    private void DoObjectUnGrabbed(object sender, InteractableObjectEventArgs e)
    {
        bGrabbed = false;
    }

    public void Detach(int id)
    {
        //for (int i = 0; i < spoke_Tracker.Length; i++)
        //{
        //    if (spoke_Tracker[i].go_occupying != null)
        //    {
        //        if (spoke_Tracker[i].go_occupying.GetComponent<Tetra_MAJOR>().id == id)
        //        {
        //            spoke_Tracker[i].touchTimer = 2f;
        //            spoke_Tracker[i].go_occupying = null;
        //            print("OPEN HAPPENED");
        //        }
        //    }
        //}
    }

    void Update()
    {
        touchTimer -= Time.deltaTime;
        if (bGrabbed)
        {
            float dist;
            foreach (GameObject g in all_shape_instancer.getList())
            {
                Spoke_Tracker[] sp = g.GetComponent<Tetra_MAJOR>().spoke_Tracker;

                if (g != gameObject)
                {                
                    for (int i = 0; i < 4; i++)
                    {
                        dist = (sp[i].genSpoke.transform.position - transform.position).magnitude;
   
                        if (dist < Radius_of_Action && sp[i].spokeState == SpokeState.OPEN && touchTimer < 0)
                        {
                            print("Within Range of idx: " + i.ToString());

                            //disconnect
                            GetComponent<VRTK_FixedJointGrabAttach>().StopGrab(false);

                            //sp[i].spokeState = SpokeState.OCCUPIED;
                            sp[i].go_occupying = this.gameObject;
                            //t.state = Tetra_MAJOR.State.ATTACHED;

                            attachedSpoke = sp[i];
                            attachedTetra_go = gameObject;
                            start_Pos = transform.position;
                            end_Pos = sp[i].genSpoke.transform.position;
                            qStart = transform.rotation;
                            qEnd = sp[i].genSpoke.transform.rotation;
                            tAccum = 0;

                            StartCoroutine(Tween_Move_to_Spoke());
                        }
                    }
                }
            }
            //Switch off Touch Grab if in the VU
            //if (!bTouchGrabEnabled && hmd_Ctrl_Tracking.Get_Current_USER_Location() != HMD_Ctrl_Tracking.USER_LOCATION.IN_THE_VU)
            //{
            //    Enable_Touch_Grab();
            //    bTouchGrabEnabled = true;
            //}
            //else if (bTouchGrabEnabled && hmd_Ctrl_Tracking.Get_Current_USER_Location() == HMD_Ctrl_Tracking.USER_LOCATION.IN_THE_VU)
            //{
            //    Disable_Touch_Grab();
            //    bTouchGrabEnabled = false;
            //}
        }
    }

    private void Enable_Touch_Grab()
    {
        //GetComponent<SphereCollider>().enabled = true;
        //foreach (Tetra_MAJOR t in tetras)
        //{
        //    t.GetComponent<SphereCollider>().enabled = true;
        //}
    }

    private void Disable_Touch_Grab()
    {
        //GetComponent<SphereCollider>().enabled = false;
        //foreach (GameObject g in all_shape_instancer.getList())
        //{
        //    g.GetComponent<SphereCollider>().enabled = false;
        //}
    }

    private IEnumerator Tween_Move_to_Spoke()
    {
        int i = 0; //Sanity check for infinite loops
        float linProg = tAccum / tDurr;

        while (i < 180 && (linProg < 1))
        {
            bForce_update = true;
            tAccum += Time.deltaTime;
            linProg = tAccum / tDurr;
            Mathf.Clamp(tAccum, 0, tDurr);

            tween_Val = EaseMethods.QuintEaseOut(tAccum, 0, 1, tDurr);
            Move_To_Spoke(tween_Val);

            yield return true;
            i++;
        }

        tAccum = tDurr;
        tween_Val = 1;

        Move_To_Spoke(tween_Val);
        bForce_update = false;
        StopCoroutine("Tween_State");
    }

    private void Move_To_Spoke(float val)
    {
        transform.position = Vector3.Lerp(start_Pos, end_Pos, val);
        transform.rotation = Quaternion.Slerp(qStart, qEnd, val);
    }
}