## devNotes 4-18-16 triangle center quality – projections to/from the uv plane

Test Pattern

First Pass:

```    public int Find_UV_PointQuality(Vector3 vTestPoint)//thinking about generalizing
{
Vector2 vTestScaled;
float rHex = Mathf.Tan(Mathf.PI / 6);//units normalized to fCelHeight
Vector2 vCT_M;

Vector2 A, AB, BC, AM;

vTestScaled.x = vTestPoint.x; vTestScaled.y = vTestPoint.y;
vTestScaled /= m_fCelHt;

float cs = Mathf.Cos(Mathf.PI/3);
float sn = Mathf.Sin(Mathf.PI/3);

for (int i = 0; i< 18; i++)
{
vCT_M = vTestScaled - vQualCenter[i];
if (vCT_M.magnitude < rHex)
{
A.x = -rHex;
A.y = -1 / 2;

AB.x = 0;
AB.y = 1;

BC.x = 2 * rHex;
BC.y = 0f;

AM = vCT_M - A;

int VerfiedCnt = 0;

float dotAB_AM;
float dotAB_AB;
float dotBC_AM;
float dotBC_BC;

for (int j = 0; j < 3; j++)
{
dotAB_AM = Vector2.Dot(AB, AM);
dotAB_AB = Vector2.Dot(AB, AB);
dotBC_AM = Vector2.Dot(BC, AM);
dotBC_BC = Vector2.Dot(BC, BC);

if (dotAB_AM > 0 && dotAB_AM < dotAB_AB && dotBC_AM > 0 && dotBC_AM < dotBC_BC)
{
if(++VerfiedCnt == 3)
{
//In This Cell
return i;
}

Rota2D(ref A,  Mathf.PI / 3);
Rota2D(ref AB, Mathf.PI / 3);
Rota2D(ref BC, Mathf.PI / 3);

AM = vCT_M - A;
}
}
}
}
return TriQual.UNDEFINED;
}

public void Rota2D(ref Vector2 v, float thetaRad)
{

v.x = v.x * cs - v.y * sn;
v.y = v.x * sn + v.y * cs;
}```

Go through these…

```    Vector2[] vQualCenters = new[]
{
new Vector2(0, 0),                      //A
new Vector2(0, 1),                      //B  (m_fCelHt)
new Vector2(Mathf.Sqrt(3f)/2f, 0.5f),   //C
new Vector2(Mathf.Sqrt(3f)/2f, 0.5f),   //D
new Vector2(0, -1),                     //E
new Vector2( -Mathf.Sqrt(3f)/2f, -0.5f),//F
new Vector2( -Mathf.Sqrt(3f)/2f, 0.5f), //G
new Vector2(0,2),                       //H
new Vector2(1f, Mathf.Sqrt(3f)),        //I
new Vector2(Mathf.Sqrt(3f), 1f),        //J
new Vector2(2, 0),                      //K
new Vector2(Mathf.Sqrt(3f), -1f),       //L
new Vector2(1f, -Mathf.Sqrt(3f)),       //M
new Vector2(0,-2),                      //N
new Vector2(-1f, -Mathf.Sqrt(3f)),      //O
new Vector2(-Mathf.Sqrt(3f), -1f),      //P
new Vector2(-2, 0),                     //Q
new Vector2(-Mathf.Sqrt(3f), 1f),       //R
new Vector2(-1f, Mathf.Sqrt(3f)),       //S
};```

```    public int FindCenterQuality(Vector3 vTestPoint, float fCelHeight)//thinking about generalizing
{
//triple rectangle rotation verify - transform - Up In Right

//m_vnPointing = transform.forward;

//Angle_to_Rotate = 360 / (float)NUM_cells_Circ;

//m_fCelHt = Mathf.Tan(2f * Mathf.PI * Angle_to_Rotate / 360f) * cosaHedra.radius; //TOA -> AO/A = O
//m_rHex = Mathf.Tan(Mathf.PI / 6f) * m_fCelHt;
//m_fRadius_UV = (256f / 121f) * m_fCelHt;//from texture

return TriQual.UNDEFINED;
}

public void Paint_UV(float fCelHeight)
{
Vector3 cPos = transform.forward * cosaHedra.radius;//m_vPointingLoc

ICO_ArgosDraft = cosaHedra.getArgosMeshDraft();
List<int> tL = ICO_ArgosDraft.triangles;
List<Vector3> vL = ICO_ArgosDraft.vertices;
List<Vector2> uvL = ICO_ArgosDraft.uv;
List<int> tQual = ICO_ArgosDraft.vQual;//triangle center quality
List<Vector3> tCent = ICO_ArgosDraft.vTriCenter;

int numVerts = tL.Count;

Vector3 vTCProjection;//Tri Center Projection
Vector3 vTC;  //Tri Center Location
Vector3 vVProj; //Tri Vertex Projection
Vector2[] uv = new Vector2[3];
bool reject = false;

Vector3 vIn;
Vector3 vUp;
Vector3 vRight;

int iQuality = TriQual.UNDEFINED;

float x, y;

for (int i = 0; i < numVerts - 2; i += 3)
{
vTC = tCent[tL[i]];//requires this.transform at origin - can generalize

//project onto UV Plane
vTCProjection.x = Vector3.Dot(vTC, transform.right) * cosaHedra.radius / Vector3.Dot(vTC, transform.forward);
vTCProjection.y = Vector3.Dot(vTC, transform.up) * cosaHedra.radius / Vector3.Dot(vTC, transform.forward);
vTCProjection.z = 0f; //2D UV Plane

if (vTCProjection.magnitude < 1.414 * m_fRadius_UV)//in range of texture
{
//Determine quality here
iQuality = FindCenterQuality(vTCProjection, fCelHeight);

for (int k = i; k < i + 3; k++)
{
vUp = transform.up;
vIn = vL[tL[k]].normalized;
vRight = Vector3.Cross(vUp, vIn);
Vector3.Normalize(vRight);
vUp = Vector3.Cross(vIn, vRight);
vVProj = vL[tL[k]] - m_vPointingLoc;  //TODO NOT PROJ YET - push out to plane of UV - Avoid Lensing

x = 0.5f + Vector3.Dot(vVProj, vRight);
y = 0.5f + Vector3.Dot(vVProj, vUp);

if (x >= 0 && x <= 1 && y >= 0 && y <= 1)//Check if each triangle vertex is within bounds of texture
{
uv[k - i] = new Vector2(x, y);
}
else reject = true;
}
if (!reject)
{
for (int k = i; k < i + 3; k++)
{
uvL[tL[k]] = uv[k - i];
}
}
reject = false;
}
}
cosaHedra.writeMesh();
}```

### Ready to Start now 🙂

```using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using ProceduralToolkit;
using System.IO;

//Argos Solid Angle Painter 4/17/16
//
//This class is designed to be located at the center of the ArgosSphere/Cosahedra
//Its transform is used to index/locate/analyze and paint cells on the surface of the Cosahedra

public class ArgosSolidAnglePainter : MonoBehaviour
{
StreamWriter sWrite;

public int NUM_cells_Circ = 60;

public float Angle_to_Rotate = 10f;

public GameObject hexPrefab;

GameObject ArgosSphere;
ArgosSphere_Indexing asi;
ArgSphereUtility asu;

GameObject IcoSphere;
Cosahedra cosaHedra;

GameObject userMovement;
UserMovement uMove;

ArgosMeshDraft ICO_ArgosDraft;

public Vector3 m_vnPointing;
public Vector3 m_vPointLoc;

public float m_fCelHt; //individual Cell Height
public float m_rHex;   //radius of individual Cell

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

ArgosSphere = GameObject.Find("Argos_Sphere");
asi = ArgosSphere.GetComponent<ArgosSphere_Indexing>();
asu = GetComponent<ArgSphereUtility>();

IcoSphere = GameObject.Find("Ico_Sphere");
cosaHedra = IcoSphere.GetComponent<Cosahedra>();

userMovement = GameObject.Find("User_Movement");
uMove = userMovement.GetComponent<UserMovement>();

//Color col = getRandColor();
//asu.init();
//asu.lightHex(4096, hexPrefab, col);
}

void Update()
{
m_vnPointing = transform.forward;

Angle_to_Rotate = 360 / (float)NUM_cells_Circ;

m_fCelHt = Mathf.Tan(2f * Mathf.PI * Angle_to_Rotate / 360f) * cosaHedra.radius; //TOA -> AO/A = O
m_rHex = Mathf.Tan(Mathf.PI / 6f) * m_fCelHt;
fRadius_UV = (256f / 121f) * m_fCelHt;//from texture
}

Vector2[] vQualCenters = new[]
{
new Vector2(0, 0), 					    //A
new Vector2(0, 1), 					    //B  (m_fCelHt)
new Vector2(Mathf.Sqrt(3f)/2f, 0.5f),	//C
new Vector2(Mathf.Sqrt(3f)/2f, 0.5f),	//D
new Vector2(0, -1),					    //E
new Vector2( -Mathf.Sqrt(3f)/2f, -0.5f),//F
new Vector2( -Mathf.Sqrt(3f)/2f, 0.5f),	//G
new Vector2(0,2),					    //H
new Vector2(1f, Mathf.Sqrt(3f)),		//I
new Vector2(Mathf.Sqrt(3f), 1f),		    //J
new Vector2(2, 0),					        //K
new Vector2(Mathf.Sqrt(3f), -1f),		//L
new Vector2(1f, -Mathf.Sqrt(3f)),		//M
new Vector2(0,-2),					    //N
new Vector2(-1f, -Mathf.Sqrt(3f)),		//O
new Vector2(-Mathf.Sqrt(3f), -1f),		//P
new Vector2(-2, 0),					    //Q
new Vector2(-Mathf.Sqrt(3f), 1f),		//R
new Vector2(-1f, Mathf.Sqrt(3f)),		//S
};

public int FindCenterQuality(Vector3 vTestPoint, float fCelHeight)
{
return TriQual.UNDEFINED;
}

public void Paint_UV(float fCelHeight)
{
Vector3 cPos = transform.forward * cosaHedra.radius;//m_vPointLoc

ICO_ArgosDraft = cosaHedra.getArgosMeshDraft();
List<int> tL = ICO_ArgosDraft.triangles;
List<Vector3> vL = ICO_ArgosDraft.vertices;
List<Vector2> uvL = ICO_ArgosDraft.uv;

int numVerts = tL.Count;

Vector3 vToLoc;
Vector2[] uv = new Vector2[3];
bool reject = false;
Vector3 vC;

Vector3 vIn;
Vector3 vUp;
Vector3 vRight;

int iQuality = TriQual.UNDEFINED;

float x, y;

for (int i = 0; i < numVerts - 2; i += 3)
{
vC = (vL[tL[i]] + vL[tL[i + 1]] + vL[tL[i + 2]]) / 3f;

vToLoc = vC;

vToLoc.x = Vector3.Dot(vToLoc, transform.right) * cosaHedra.radius / Vector3.Dot(vToLoc, transform.forward);
vToLoc.y = Vector3.Dot(vToLoc, transform.up) * cosaHedra.radius / Vector3.Dot(vToLoc, transform.forward);
vToLoc.z = 0f;

if (vToLoc.magnitude < 1.414 * fRadius_UV)//in range of texture
{
//Determine quality here
iQuality = FindCenterQuality(vToLoc, fCelHeight);

for (int k = i; k < i + 3; k++)
{
vUp = transform.up;
vIn = vL[tL[k]].normalized;
vRight = Vector3.Cross(vUp, vIn);
Vector3.Normalize(vRight);
vUp = Vector3.Cross(vIn, vRight);
vToLoc = vL[tL[k]] - cPos;              //push out to plane of UV - Avoid Lensing

x = 0.5f + Vector3.Dot(vToLoc, vRight);
y = 0.5f + Vector3.Dot(vToLoc, vUp);

if (x >= 0 && x <= 1 && y >= 0 && y <= 1)//Check if each triangle vertex is within bounds of texture
{
uv[k - i] = new Vector2(x, y);
}
else reject = true;
}
if (!reject)
{
for (int k = i; k < i + 3; k++)
{
uvL[tL[k]] = uv[k - i];
}
}
reject = false;
}
}
cosaHedra.writeMesh();
}

//C = scaleFactor
//D = scaleFactor * Sqrt(3)

//0)  Rotate on X ->  -C
//1)  Rotate on X -> -C/2  Rotate on Y -> C* Sqrt(3)/2
//2)  Rotate on X -> (C/2) Rotate on Y -> C* Sqrt(3)/2
//3)  Rotate on X -> (C)
//4)  Rotate on X -> (C/2) Rotate on Y -> (-C* Sqrt(3)/2)
//5)  Rotate on X -> -C/2 Rotate on Y -> (-C* Sqrt(3)/2)

//6)  Rotate on X -> -D* Sqrt(3)/2 Rotate on Y -> D/2
//7)  Rotate on Y -> -D
//8)  Rotate on X -> (D* Sqrt(3)/2) Rotate on Y D/2
//9)  Rotate on X -> (D* Sqrt(3)/2) Rotate on Y(-D/2)
//10) Rotate on Y -> (D)
//11) Rotate on X ->  -D* Sqrt(3)/2) Rotate on Y(-D/2)

Vector2[] rota = new[] {
new Vector2(-1, 0),
new Vector2(-0.5f, Mathf.Sqrt(3f)/2f),
new Vector2(0.5f, Mathf.Sqrt(3f)/2f),
new Vector2(1, 0),
new Vector2(0.5f, -Mathf.Sqrt(3f)/2f),
new Vector2(-0.5f, -Mathf.Sqrt(3f)/2f),
new Vector2( -Mathf.Sqrt(3f)/2f, 0.5f),
new Vector2(0, 1),
new Vector2( Mathf.Sqrt(3f)/2f,0.5f),
new Vector2( Mathf.Sqrt(3f)/2f,-0.5f),
new Vector2(0, -1),
new Vector2(- Mathf.Sqrt(3f)/2f,-0.5f) };

public void onUV_Indexed_Paint(int i)
{
float scaleFactor = 1;
float dir = 1;
Angle_to_Rotate = 360 / (float)NUM_cells_Circ;

if ((i > 5 && i < 12) || (i > 17 && i < 24))
{
scaleFactor = Mathf.Sqrt(3);
}
if (i > 11)
{
dir = -1f;
i -= 12;
}
m_fCelHt = Mathf.Tan(2f * Mathf.PI * Angle_to_Rotate / 360f) * cosaHedra.radius;

fRadius_UV = (256f / 121f) * m_fCelHt;

float angleX = rota[i].x * Angle_to_Rotate * scaleFactor * dir;
float angleY = rota[i].y * Angle_to_Rotate * scaleFactor * dir;

transform.Rotate(angleX, 0, 0);
transform.Rotate(0, angleY, 0);
Paint_UV(m_fCelHt);
}

Color getRandColor()
{
Color col;

col.r = 0.4f + Random.Range(0.0f, 0.6f);
col.g = 0.5f + Random.Range(0.0f, 0.5f);
col.b = 0.1f + Random.Range(0.0f, 0.9f);
col.a = 0.8f + Random.Range(0.0f, 0.2f);
return col;
}
}```