using UnityEngine;
using System;
using System.Collections;
using ProceduralToolkit;
using System.Collections.Generic;
using UnityEngine.UI;
using thelab.mvc;
namespace ProceduralToolkit
{
[HelpURL("http://argos.vu/devnotes-7-20-16-spline-brush-draw/")]
public class SplinePnt
{
public Vector3 p;
public Vector3 n;
public Color col;
public float lifeTime;
public float currTime;
public float nrmFade_Start;
public float lenToPrev;
public bool active = false;
public void init(Vector3 p1, Vector3 n1, Color col1, float lifetime1, float nrmFade_Start1, float len)
{
p = p1;
n = n1;
col = col1;
lifeTime = lifetime1;
currTime = 0f;
nrmFade_Start = nrmFade_Start1;
lenToPrev = len;
active = true;
}
}
public class EquiDistPnts
{
public Vector3 p;
public Vector3 n;
public Color col = Color.white;
}
public class SplineQuad //tracks VB list divided by 6
{
public float lifeTime = 0f;
public float currTime = 0f;
public float fadeStart = 0f;
public MeshDraft mdQuad;
public bool bActive = false;
public SplineQuad()
{
mdQuad = new MeshDraft();
}
public void initWithStamp(MeshDraft md)
{
mdQuad.Add(md);
}
}
public class SplineDraw : MeshDraft
{
public Controller ArgosCtrl;
public float segmentLen = 0.05f;
public SplinePoint[] sPointPool;
public EquiDistPoints[] equiPoints;
public SplineQuad[] quadPool;
public int qpCurrIdx = 0;
public int qpLen = 0;
private int spCurrIdx = 0;
private int spLen = 0;
MeshDraft mdScatch = new MeshDraft();
Mesh meshInternal = new Mesh();
public SplineDraw() : base()
{
}
public void OnSegmentChanged(float val)
{
segmentLen = val;
Debug.Log(val);
}
public void initPools(int poolCount)
{
ArgosController.OnSegmentLenChanged += OnSegmentChanged;
quadPool = new SplineQuad[poolCount];
sPointPool = new SplinePoint[poolCount];
equiPoints = new EquiDistPoints[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 SplineQuad();
sPointPool[i] = new SplinePoint();
quadPool[i].initWithStamp(mdScatch);
}
qpCurrIdx = spCurrIdx = 0;
qpLen = spLen = poolCount;
}
private void PointFades()
{
bool done = false;
int i = spCurrIdx;
int cnt = 0;
while (!done)
{
sPointPool[i].currTime += Time.deltaTime;
float fadeStart = sPointPool[i].nrmFade_Start * quadPool[i].lifeTime;
if (sPointPool[i].currTime > fadeStart && sPointPool[i].active)
{
float attenAlpha = 1.0f - (sPointPool[i].currTime - fadeStart) / (sPointPool[i].lifeTime - fadeStart);
Color col;
col = sPointPool[i].col;
col.a = attenAlpha;
sPointPool[i].col = col;
}
if (sPointPool[i].currTime > sPointPool[i].lifeTime)
{
sPointPool[i].active = false;
}
if (++cnt == spLen) done = true;
if (--i < 0) i = (spLen-1);
}
}
private float getSampleLen()
{
float len = 0f;
bool done = false;
int i = spCurrIdx;
int cnt = 0;
while (!done)
{
len += sPointPool[i].lenToPrev;
if (!sPointPool[i].active) done = true;
if (++cnt == spLen) done = true;
if (--i < 0) i = (spLen - 1);
}
return len;
}
public void Spline_Frame(Text tInfo)
{
PointFades();
float totLen = getSampleLen();
int segments = (int)Mathf.Floor(totLen / segmentLen);
float deltLen = totLen / segments;
float targetLen = 0f;
float sampLen = sPointPool[spCurrIdx].lenToPrev;
float sampLenNext = 0f;
int cnt = 1;
tInfo.text = "totlen = " + totLen.ToString("F4") + " segments = " + segments.ToString();
return;
int scanIdx = prevScan(spCurrIdx);
equiPoints[0].p = sPointPool[spCurrIdx].p;
equiPoints[0].n = sPointPool[spCurrIdx].n;
bool done = false;
while (!done)
{
targetLen += deltLen;
sampLen += sPointPool[scanIdx].lenToPrev;
sampLenNext = sampLen = sPointPool[prevScan(scanIdx)].lenToPrev;//circ buff
if (targetLen > sampLen & targetLen < sampLenNext)
{
float perc = (targetLen - sampLen) / (sampLenNext - sampLen);
Vector3 p0 = sPointPool[cmIdx(scanIdx, 0)].p;
Vector3 p1 = sPointPool[scanIdx].p;
Vector3 p2 = sPointPool[cmIdx(scanIdx, 2)].p;
Vector3 p3 = sPointPool[cmIdx(scanIdx, 3)].p;
equiPoints[cnt].p = CatmullRom(perc, p0, p1, p2, p3);
equiPoints[cnt].n = Vector3.Lerp(sPointPool[scanIdx].n, sPointPool[prevScan(scanIdx)].n, perc);
equiPoints[cnt].col = sPointPool[scanIdx].col;
if (++cnt >= segments || cnt >= spLen) done = true;
}
}
}
public void Spline_Point_Paint(Vector3 p, Vector3 n, Color col, float lifetime, float nrmFade_Start)
{
Vector3 v = sPointPool[spCurrIdx].p;
v = p - v;
if (++spCurrIdx > spLen) spCurrIdx = 0;
sPointPool[spCurrIdx].init(p, n, col, lifetime, nrmFade_Start, v.magnitude);
}
public Vector3 CatmullRom(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
Vector3 a = 0.5f * (2f * p1);
Vector3 b = 0.5f * (p2 - p0);
Vector3 c = 0.5f * (2f * p0 - 5f * p1 + 4f * p2 - p3);
Vector3 d = 0.5f * (-p0 + 3f * p1 - 3f * p2 + p3);
Vector3 pos = a + (b * t) + (c * t * t) + (d * t * t * t);
return pos;
}
public SplineQuad 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 Mesh ToMeshInternal_From_QuadPool()
{
Clear();
int poolCount = quadPool.Length;
int v = 0;//verts
int t = 0;//tris
for (int i = 0; i < poolCount; i++)
{
if (quadPool[i].bActive)
{
Add(quadPool[i].mdQuad);
}
}
return ToMeshInternal();
}
public void Quad_Paint(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, Color col, float lifetime, float fade_start)
{
SplineQuad aq = getPoolQuad();
if (aq == null) return;//no non active quads
aq.lifeTime = lifetime;
aq.fadeStart = fade_start;
aq.currTime = 0f;
//quadLst.Add(aq);
Init_Quad_fromPool(aq, v0, v1, v2, v3, col);
}
public void Init_Quad_fromPool(SplineQuad aq, Vector3 vertex0, Vector3 vertex1, Vector3 vertex2, Vector3 vertex3, Color col)//TODO REOWKK QUADPOOL ONLY
{
Vector3 normal = Vector3.Cross((vertex1 - vertex0), (vertex2 - vertex0)).normalized;
aq.mdQuad.vertices[0] = vertex0;
aq.mdQuad.vertices[1] = vertex1;
aq.mdQuad.vertices[2] = vertex2;
aq.mdQuad.vertices[3] = vertex3;
aq.mdQuad.normals[0] = normal;
aq.mdQuad.normals[1] = normal;
aq.mdQuad.normals[2] = normal;
aq.mdQuad.normals[3] = normal;
}
private int prevScan(int scanIdx)
{
if (--scanIdx < 0) return spLen - 1;
else return scanIdx;
}
private int cmIdx(int scanIdx, int idx)
{
//0,2,3
if (idx == 0)
{
if (++scanIdx > spLen) return 0;
else return scanIdx;
}
else if (idx == 2) return prevScan(scanIdx);
else //if(idx == 3)
{
scanIdx -= 2;
if (scanIdx < 0) return spLen + scanIdx;
else return scanIdx;
}
}
public void QuadPoolUpdate()//Change to Pool
{
int poolCount = quadPool.Length;
for (int i = 0; i < poolCount; i++)
{
quadPool[i].currTime += Time.deltaTime;
float fadeStart = quadPool[i].fadeStart * quadPool[i].lifeTime;
if (quadPool[i].currTime > fadeStart && quadPool[i].bActive)
{
float attenAlpha = 1.0f - (quadPool[i].currTime - fadeStart) / (quadPool[i].lifeTime - fadeStart);
Color col;
for (int j = 0; j < 4; j++)
{
col = quadPool[i].mdQuad.colors[j];
col.a = attenAlpha;
quadPool[i].mdQuad.colors[j] = col;
}
}
if (quadPool[i].currTime > quadPool[i].lifeTime)
{
quadPool[i].bActive = false;
//RemoveQuad(i);
}
}
}
}
}