devNotes 5-26-16 quad pool, object reuse, memory management

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

public class ARGOS_12HORNS : MonoBehaviour
{

    //The following Cartesian coordinates define the vertices
    //of an icosahedron with edge-length 2, 
    //centered at the origin:

    //(0, ±1, ±φ)
    //(±1, ±φ, 0)
    //(±φ, 0, ±1)    


    static float Phi = (Mathf.Sqrt(5f) + 1f)/2f;

    public UI_Control ui;

    public Vector3[] v12HORNS =

    new Vector3[] 
    {
        new Vector3(0, 1f, Phi),
        new Vector3(0, -1f, Phi),
        new Vector3(-Phi, 0, 1),
        new Vector3(Phi, 0, 1f),
        new Vector3(1f, Phi,0),
        new Vector3(1f, -Phi,0),
        new Vector3(-1f, Phi,0),
        new Vector3(-1f, -Phi, 0),
        new Vector3(0, 1f, -Phi),
        new Vector3(0, -1f, -Phi),
        new Vector3(-Phi, 0, -1f), 
        new Vector3(Phi, 0, -1f)
    };

    public GameObject NavSphereWindowPrefab;

    bool isOn_HeadUpDisplay = false;

    public Button LockNavSphereButt;
    public Button RotateNavSphereButt;

    public List<Vector3> v12HORN_Norms = new List<Vector3>();
    List<GameObject> goCircs = new List<GameObject>();

    public float minLen = 0.01f;
    public float radius = 5f;

    float tAccum = 0f;
    List<Vector3> vList = new List<Vector3>();
    Vector3 vLast = Vector3.zero;
    float tLast = 0f;
    float lastAngle;

    public GameObject psRiderPreFab;
    GameObject psRiderInst;
    PS_Rider psRider;
    Phasor phasor_0;

    int[] Color_12_RGB =
    {
        0xffff00,
        0xffc700,
        0xff9100,
        0xff6301,
        0xff0000,
        0xc6037e,
        0x713697,
        0x713697,
        0x444ea1,
        0x2772b2,
        0x2772b2,
        0x008e5b,
        0x008e5b,
        0x8ac819,
    };


    Color fromRGB(int col, float alpha)
    {
        Color c;

        c.r = ((float)((col & 0xff0000) >> 16)) / 256f;
        c.g = ((float)((col & 0x00ff00) >> 8)) / 256f;
        c.b = ((float)((col & 0x0000ff))) / 256f;
        c.a = alpha;
        return c;
    }

    void Start ()
    {
        float mag = v12HORNS[0].magnitude;
        for (int i = 0; i < 12; i++) v12HORN_Norms.Add(v12HORNS[i] / mag);
        ui = GameObject.Find("UI_Control_Canvas").GetComponent<UI_Control>();
        float alpha;
        Quaternion q;
        for(int i = 0; i<12; i++)
        {
            q = Quaternion.LookRotation(v12HORNS[i]);
            goCircs.Add((GameObject)Instantiate(NavSphereWindowPrefab, v12HORNS[i], q));
            goCircs[i].gameObject.transform.SetParent(transform);

            goCircs[i].transform.localScale = new Vector3(12.34f, 12.34f, 12.34f);
            goCircs[i].GetComponentInChildren<Phasor>().freq = ui.arrow_freq;

            goCircs[i].GetComponentInChildren<Canvas>().GetComponentInChildren<Text>().text = i.ToString();
            alpha = goCircs[i].GetComponentInChildren<Canvas>().GetComponentInChildren<Text>().color.a;
            goCircs[i].GetComponentInChildren<Canvas>().GetComponentInChildren<Text>().color = fromRGB(Color_12_RGB[i], alpha);

            alpha = goCircs[i].GetComponent<Renderer>().material.color.a;
            goCircs[i].GetComponent<Renderer>().material.color = fromRGB(Color_12_RGB[i], alpha);

            goCircs[i].gameObject.SetActive(isOn_HeadUpDisplay);

        }
        GetComponent<MeshRenderer>().enabled = isOn_HeadUpDisplay;
        LockNavSphereButt.gameObject.SetActive(isOn_HeadUpDisplay);
        RotateNavSphereButt.gameObject.SetActive(isOn_HeadUpDisplay);

        InitTestPainting();
    }

    void InitTestPainting()
    {
        psRiderInst = (GameObject)Instantiate(psRiderPreFab, Vector3.zero, Quaternion.identity);
        psRider = psRiderInst.GetComponent<PS_Rider>();
        phasor_0 = goCircs[0].GetComponentInChildren<Phasor>();
    }


    float phasorUpdate()
    {
        float angle = (360f * ui.arrow_freq*tAccum);

        phasor_0.transform.localRotation = Quaternion.Euler(0f, 0f, angle);

        return angle;
    }

    void phasorSubFrame(float angle)
    {
        phasor_0.transform.localRotation = Quaternion.Euler(0f, 0f, angle);
    }

    int frameCounter = 0;

    void Update ()
    {
        tAccum += Time.deltaTime;

        frameCounter++;
        if (frameCounter % 120 == 0) System.GC.Collect();


        float currAngle = phasorUpdate();

        Vector3 vCurr = Func(tAccum);
        vCurr.Normalize();
        vCurr *= radius;

        Vector3 vPointing = vCurr - vLast;

        vList.Clear();
        if(vPointing.magnitude > minLen)
        {
            float numSegs = vPointing.magnitude / minLen;

            if (numSegs > 10) numSegs = 10f;
            float t = tLast;
            float delt = (tAccum - tLast) / numSegs;

            float angle = lastAngle;
            float deltThet = (currAngle - lastAngle) / numSegs;
            for(int i = 0; i<numSegs;i++)
            {
                phasorSubFrame(angle);

                vCurr = Func(t);
                vCurr.Normalize();
                vCurr *= radius;

                vList.Add(vCurr);
                t += delt;
                angle += deltThet;
            }
        }
        psRider.paintList(vList,ui.duration,ui.line_width,ui.fade_start);
        tLast = tAccum;
        vLast = vCurr;
        lastAngle = currAngle;
    }

    Vector3 Func(float t)
    {
        return v12HORNS[0] + phasor_0.transform.right
            * ui.phasor_len * ((1f - ui.ab_ratio) + ui.ab_ratio * Mathf.Sin(2f * Mathf.PI * t * ui.brush_freq));

    }


    public void onDisplayICO_Button()
    {
        isOn_HeadUpDisplay = !isOn_HeadUpDisplay;
        for(int i = 0; i<12; i++)
        {
            goCircs[i].gameObject.SetActive(isOn_HeadUpDisplay);
        }
        GetComponent<MeshRenderer>().enabled = isOn_HeadUpDisplay;

        LockNavSphereButt.gameObject.SetActive(isOn_HeadUpDisplay);
        RotateNavSphereButt.gameObject.SetActive(isOn_HeadUpDisplay);
    }
}
    public class ArgosQuad //tracks VB list divided by 6
    {
        public float lifeTime = 0f;
        public float currTime = 0f;
        public float fadeStart = 0f;
        public Vector3[] vertices = new Vector3[4];
        public int[] triangles = new int[6];
        public Vector3[] normals = new Vector3[4];
        public Vector2[] uv = new Vector2[4];
        public Color[] colors = new Color[4];
        public bool bActive = false;

        public ArgosQuad()
        {
        }

        public void initWithStamp(MeshDraft md)
        {
            for(int i = 0; i<4; i++)
            {
                uv[i] = md.uv[i];
                colors[i] = md.colors[i];
                triangles[i] = md.triangles[i];
            }
            triangles[4] = md.triangles[4];
            triangles[5] = md.triangles[5];
        }
    }

    public class ArgosMeshDraft : MeshDraft
    {
        public List<Vector3> vTriCenter = new List<Vector3>();
        public List<int> vQual = new List<int>();
        public List<ArgVert> icoPointCloud = new List<ArgVert>();
        public List<ArgosQuad> quadLst = new List<ArgosQuad>();

        public ArgosQuad[] quadPool;
        public int qpCurrIdx = 0;
        public int qpLen = 0;

        MeshDraft mdScatch = new MeshDraft();
        Mesh meshInternal = new Mesh(); 

        public ArgosMeshDraft() : base()
        {
            
        }

        public void initQuadPool(int poolCount)
        {
            quadPool = new ArgosQuad[poolCount];
            Color col = new Color(1, 1, 1, 1); 
            mdScatch.Add(Quad(Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero,col));

            for (int i = 0; i < poolCount; i++)
            {
                quadPool[i] = new ArgosQuad();
                quadPool[i].initWithStamp(mdScatch);
            }
            qpCurrIdx = 0;
            qpLen = poolCount;
        }

        public ArgosQuad getPoolQuad()
        {
            bool scan = true;
            int idx = qpCurrIdx;
            int cnt = 0;

            while (scan)
            {
                cnt++;
                if (quadPool[idx].bActive == false)
                {
                    quadPool[idx].bActive = true;
                    qpCurrIdx = idx;
                    return quadPool[idx];
                }
                if(++idx > qpLen-1)
                {
                    idx = 0;
                }
                if(cnt > qpLen)
                {
                    scan = false;
                }
            }
            return null;
        }

        public Mesh ToMeshInternal()
        {
            meshInternal.Clear();
            meshInternal.vertices = vertices.ToArray();
            meshInternal.triangles = triangles.ToArray();
            meshInternal.normals = normals.ToArray();
            meshInternal.uv = uv.ToArray();
            meshInternal.colors = colors.ToArray();
            return meshInternal;
        }

        public void Quad_Paint(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, Color col, float lifetime, float fade_start)
        {
            ArgosQuad aq = getPoolQuad();
            if (aq == null) return;//no non active quads

            aq.lifeTime = lifetime;
            aq.fadeStart = fade_start;
            aq.currTime = 0f;
            quadLst.Add(aq);

            Add(Quad_fromPool(aq, v0, v1, v2, v3, col));
        }

        public MeshDraft Quad_fromPool(ArgosQuad aq, Vector3 vertex0, Vector3 vertex1, Vector3 vertex2, Vector3 vertex3, Color col)
        {
            Vector3 normal = Vector3.Cross((vertex1 - vertex0), (vertex2 - vertex0)).normalized;

            mdScatch.vertices[0] = aq.vertices[0] = vertex0;
            mdScatch.vertices[1] = aq.vertices[1] = vertex1;
            mdScatch.vertices[2] = aq.vertices[2] = vertex2;
            mdScatch.vertices[3] = aq.vertices[3] = vertex3;

            mdScatch.normals[0] = aq.normals[0] = normal;
            mdScatch.normals[1] = aq.normals[1] = normal;
            mdScatch.normals[2] = aq.normals[2] = normal;
            mdScatch.normals[3] = aq.normals[3] = normal;

            for (int i = 0; i < 4; i++)
            {
                mdScatch.uv[i] = aq.uv[i];
                mdScatch.colors[i] = aq.colors[i];
                mdScatch.triangles[i] = aq.triangles[i];
            }
            mdScatch.triangles[4] = aq.triangles[4];
            mdScatch.triangles[5] = aq.triangles[5];

            return mdScatch;
        }

        public void QuadListUpdate()
        {
            for(int i = 0; i<quadLst.Count; i++)
            {
                quadLst[i].currTime += Time.deltaTime;

                float fadeStart = quadLst[i].fadeStart * quadLst[i].lifeTime;

                if (quadLst[i].currTime > fadeStart)
                {
                    float attenAlpha = 1.0f - (quadLst[i].currTime - fadeStart) / (quadLst[i].lifeTime - fadeStart);
                    Color col;
                    
                    for (int j = 0; j < 4; j++)
                    {
                        col = colors[4 * i + j];
                        col.a = attenAlpha;
                        colors[4 * i + j] = col;
                    }
                }

                if (quadLst[i].currTime > quadLst[i].lifeTime)
                {
                    quadLst[i].bActive = false;
                    RemoveQuad(i);
                }
            }
        }

        public void RemoveQuad(int i)
        {
            quadLst.RemoveAt(i);
            vertices.RemoveRange(i * 4, 4);
            uv.RemoveRange(i * 4, 4);
            colors.RemoveRange(i * 4, 4);
            normals.RemoveRange(i * 4, 4);
            triangles.RemoveRange(i * 6, 6);

            for (int j = i * 6; j < triangles.Count; j++)
            {
                triangles[j] -= 4;
            }
        }

 

Object Pool

object_pool

sdfbfdsb7

thumb