in Cosahedra.cs
public void OnStopButtonDown()
{
bSimulateForces = false;
List<ArgVert> aVL = aMD_IcosaSphere.icoPointCloud;
for (int i = 0; i < aMD_IcosaSphere.icoPointCloud.Count - 1; i++)
{
sWrite.WriteLine(i.ToString()
+ " NodePath = " + aVL[i].itn.nodePath
+ "| N0 = " + aVL[i].avNeigbor[0].aV.itn.nodePath.ToString() + " d = " + aVL[i].avNeigbor[0].distFrom.ToString("F4") + " Sect = " + aVL[i].avNeigbor[0].aV.itn.sector.ToString()
+ " N1 = " + aVL[i].avNeigbor[1].aV.itn.nodePath.ToString() + " d = " + aVL[i].avNeigbor[1].distFrom.ToString("F4") + " Sect = " + aVL[i].avNeigbor[1].aV.itn.sector.ToString()
+ " N2 = " + aVL[i].avNeigbor[2].aV.itn.nodePath.ToString() + " d = " + aVL[i].avNeigbor[2].distFrom.ToString("F4") + " Sect = " + aVL[i].avNeigbor[2].aV.itn.sector.ToString()
+ " N3 = " + aVL[i].avNeigbor[3].aV.itn.nodePath.ToString() + " d = " + aVL[i].avNeigbor[3].distFrom.ToString("F4") + " Sect = " + aVL[i].avNeigbor[3].aV.itn.sector.ToString()
+ " N4 = " + aVL[i].avNeigbor[4].aV.itn.nodePath.ToString() + " d = " + aVL[i].avNeigbor[4].distFrom.ToString("F4") + " Sect = " + aVL[i].avNeigbor[4].aV.itn.sector.ToString()
+ " N5 = " + aVL[i].avNeigbor[5].aV.itn.nodePath.ToString() + " d = " + aVL[i].avNeigbor[5].distFrom.ToString("F4") + " Sect = " + aVL[i].avNeigbor[5].aV.itn.sector.ToString()
+ " v = " + aVL[i].vPos.ToString("F3") + " sector = " + aVL[i].itn.sector
);
}
}
in ArgosMeshDraft.cs
public class ICO_Tree_Node_ID
{
public int sector; // 20 sectors to ICO
public int nodePath; // 2 bits per depth level
}
public class ArgVert
{
public Vector3 vPos;
public ICO_Tree_Node_ID itn = new ICO_Tree_Node_ID();
public float dist;
public Vector3 vForce; //constrain position to sphere radius
public Vector3 vVel;
public class NB
{
public ArgVert aV;
public float distFrom;
public NB()
{
aV = null;
distFrom = float.MaxValue;
}
}
public NB[] avNeigbor = new NB[6];
public ArgVert()
{
for(int i = 0; i<6; i++)
{
avNeigbor[i] = new NB();
avNeigbor[i].aV = this;
}
}
public void insNeighbor(float dist, ArgVert aV_Contender)//Top 6 Contenders
{
NB avTmp;
for (int i = 0; i<6; i++)
{
if(avNeigbor[i].distFrom > dist)
{
avTmp = avNeigbor[i];
for (int j = i; j<6; j++)
{
if (j == i)
{
avNeigbor[j].aV = aV_Contender;
avNeigbor[j].distFrom = dist;
}
else
{
avNeigbor[j] = avTmp;
}
if(j<5)
{
avTmp = avNeigbor[j + 1];
}
}
}
}
}
}
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 ArgosMeshDraft() :base()
{
}
public void Add_ITN_Node(MeshDraft tri,int sector,int nodePath)
{
Vector3 vC = (tri.vertices[0] + tri.vertices[1] + tri.vertices[2] )/ 3f;
ArgVert aV = new ArgVert();
aV.vPos = vC;
aV.itn.sector = sector;
aV.itn.nodePath = nodePath;
icoPointCloud.Add(aV);
}
VIDEO
using UnityEngine;
using System.Collections;
using ProceduralToolkit;
using UnityEngine.UI;
using System.Collections.Generic;
using System.IO;
public class Cosahedra : MonoBehaviour
{
public Text NumTrisText;
public float m_fRadius = 1.5f;
public ArgosMeshDraft aMD = new ArgosMeshDraft();
public ArgosMeshDraft aMD_IcosaSphere = new ArgosMeshDraft();
MeshDraft mD_Tri = new MeshDraft();
public GameObject hexPreFab;
public float m_fFact = 1; // force Multiplier
StreamWriter sWrite;
public int depth = 3;
bool bSimulateForces = false;
public enum ICO_Type
{
HEX,
TRIANGLE,
ICO_TREE_GENERATOR,
};
public ICO_Type icoType;
public class GO_Tracker
{
public GameObject go;
public ArgVert aVNode;
}
public List<GO_Tracker> lstHex_GO = new List<GO_Tracker>();
void Start ()
{
sWrite = new StreamWriter("Argos_ICO_Tree_Hex_Construction.txt");
aMD.Clear();
aMD.Add(MeshDraft.Icosahedron(m_fRadius));
aMD_IcosaSphere.Clear();
Create_GP(depth);
Vector3 vApex = new Vector3(0.0f, 5.0f, 0.0f);
//aMD_IcosaSphere.SetSortDist(vApex);
//aMD_IcosaSphere.sortPointCloud();
Quaternion q;
Vector3 vN_In;
foreach(ArgVert aV in aMD_IcosaSphere.icoPointCloud)
{
vN_In = aV.vPos.normalized;
q = Quaternion.LookRotation(vN_In);
int lev0, lev1, lev2, lev3;
GameObject gO;
GO_Tracker gT;
gO = (GameObject)Instantiate(hexPreFab, aV.vPos, q);
gT = new GO_Tracker();
gT.go = gO;
gT.aVNode = aV;
lstHex_GO.Add(gT);
lev3 = aV.itn.nodePath;
lev0 = lev3 >> 6;
lev1 = lev3 >> 4 & 3;
lev2 = lev3 >> 2 & 3;
lev3 = lev3 & 3;
lstHex_GO[lstHex_GO.Count - 1].go.GetComponentInChildren<Text>().text = lev0.ToString() + lev1.ToString() + lev2.ToString() + lev3.ToString();
}
foreach (GO_Tracker gActedUpon in lstHex_GO)
{
gActedUpon.go.transform.position = gActedUpon.aVNode.vPos;
}
//for (int i = 0; i < aMD_IcosaSphere.icoPointCloud.Count - 1; i++)
//{
// //if (aMD_IcosaSphere.icoPointCloud[i].itn.sector == 5)
// //{
// //sWrite.WriteLine("v = " + aMD_IcosaSphere.icoPointCloud[i].vPos.ToString("F3") + " sector = " + aMD_IcosaSphere.icoPointCloud[i].itn.sector
// // + " NodePath = " + aMD_IcosaSphere.icoPointCloud[i].itn.nodePath + " sector = " + aMD_IcosaSphere.icoPointCloud[i].itn.sector
// // + " dist = " + aMD_IcosaSphere.icoPointCloud[i].dist);
// //}
//}
aMD_IcosaSphere.FlipNormals();
GetComponent<MeshFilter>().mesh = aMD_IcosaSphere.ToMesh();
}
public void quickVoronoi()
{
Vector3 vForce;
Vector3 vAccumForce;
float dist_sqd;
float fMag = 0;
float delta = 0.05f;
foreach (GO_Tracker gActedUpon in lstHex_GO)
{
vAccumForce = Vector3.zero;
foreach (GO_Tracker gPushing in lstHex_GO)
{
if (gActedUpon != gPushing)
{
vForce = gActedUpon.aVNode.vPos - gPushing.aVNode.vPos;
dist_sqd = vForce.x * vForce.x + vForce.y * vForce.y + vForce.z * vForce.z;
vAccumForce += vForce.normalized / dist_sqd;
}
}
fMag = vAccumForce.magnitude;
vAccumForce = vAccumForce.normalized;
gActedUpon.aVNode.vForce = 100f * vAccumForce;
gActedUpon.aVNode.vPos += gActedUpon.aVNode.vForce * (delta * delta);
gActedUpon.aVNode.vPos = gActedUpon.aVNode.vPos.normalized;
gActedUpon.aVNode.vPos *= m_fRadius;
}
}
public void OnStartButtonDown()
{
bSimulateForces = true;
}
public void OnStopButtonDown()
{
bSimulateForces = false;
for (int i = 0; i < aMD_IcosaSphere.icoPointCloud.Count - 1; i++)
{
//if (aMD_IcosaSphere.icoPointCloud[i].itn.sector == 5)
//{
sWrite.WriteLine(i.ToString() + " v = " + aMD_IcosaSphere.icoPointCloud[i].vPos.ToString("F3") + " sector = " + aMD_IcosaSphere.icoPointCloud[i].itn.sector
+ " NodePath = " + aMD_IcosaSphere.icoPointCloud[i].itn.nodePath + " sector = " + aMD_IcosaSphere.icoPointCloud[i].itn.sector
+ " dist = " + aMD_IcosaSphere.icoPointCloud[i].dist);
//}
}
}
void Update ()
{
if (bSimulateForces)
{
quickVoronoi();
foreach (GO_Tracker gActedUpon in lstHex_GO)
{
gActedUpon.go.transform.position = gActedUpon.aVNode.vPos;
}
}
}
void OnApplicationQuit()
{
sWrite.Close();
}
void Create_GP(int depth)
{
for(int i = 0; i<20; i++)
{
Vector3 v0 = aMD.vertices[aMD.triangles[i*3]];
Vector3 v1 = aMD.vertices[aMD.triangles[i*3 +1]];
Vector3 v2 = aMD.vertices[aMD.triangles[i*3 + 2]];
Color col = getWhite();
subdivide(v0, v1, v2, depth, col,i,0);
}
}
void subdivide(Vector3 v1, Vector3 v2, Vector3 v3, int depth, Color col,int sector, int nID)
{
Vector3 v12, v23, v31;
Vector3 v12_n, v23_n, v31_n;
int i;
if (depth == 0)
{
if (icoType == ICO_Type.HEX)
{
addHex(v1, v2, v3, col);
}
else if(icoType == ICO_Type.TRIANGLE)
{
addTriangle(v1, v2, v3, col);
}
else if(icoType == ICO_Type.ICO_TREE_GENERATOR)
{
addITG_Node(v1, v2, v3, sector, nID);
}
return;
}
v12 = (v1 + v2) / 2.0f;
v23 = (v2 + v3) / 2.0f;
v31 = (v3 + v1) / 2.0f;
/* extrude midpoints to lie on unit sphere */
v12_n = v12.normalized * m_fRadius;
v23_n = v23.normalized * m_fRadius;
v31_n = v31.normalized * m_fRadius;
int shifter = nID;
shifter = shifter << 2;
/* recursively subdivide new triangles */
subdivide(v1, v12_n, v31_n, depth - 1, col, sector, shifter | 0);
subdivide(v12_n, v2, v23_n, depth - 1, col, sector, shifter | 1);
subdivide(v31_n, v23_n, v3, depth - 1, col, sector, shifter | 2);
subdivide(v23_n, v31_n, v12_n, depth - 1, col, sector, shifter | 3);
}
void addITG_Node(Vector3 v0, Vector3 v1, Vector3 v2,int Sector, int nID)
{
mD_Tri = MeshDraft.Triangle(v0, v1, v2);
aMD_IcosaSphere.Add_ITN_Node(mD_Tri, Sector, nID);
}
void addTriangle(Vector3 v0, Vector3 v1, Vector3 v2, Color col)
{
mD_Tri.Clear();
mD_Tri = MeshDraft.Triangle(v0, v1, v2);
mD_Tri.Paint(col);
aMD_IcosaSphere.AddTriQual(mD_Tri);
}
void addHex(Vector3 v0, Vector3 v1, Vector3 v2, Color col)
{
mD_Tri.Clear();
mD_Tri = MeshDraft.Triangle(v0, v1, v2);
mD_Tri.Paint(col);
aMD_IcosaSphere.AddHex(mD_Tri);
}
public void writeMesh()
{
GetComponent<MeshFilter>().mesh = aMD_IcosaSphere.ToMesh();
}
public ArgosMeshDraft getArgosMeshDraft()
{
return aMD_IcosaSphere;
}
Color getIDXolor(int i)
{
Color col;
col.r = 0.2f + (float)(i) * 0.8f / 20f ;
col.g = 0.5f + (float)(i) * 0.5f / 20f;
col.b = 1f - (float)(i) * 0.8f / 20f;
col.a = 1f;
return col;
}
Color getWhite() // :)
{
Color col;
col.r = 1f;
col.g = 1f;
col.b = 1f;
col.a = 1f;
return col;
}
Color getINColor(int i)
{
Color col;
col.r = (float)(i) / 1024f;
col.g = 1f - (float)(i) / 1024f;
col.b = 0.5f - (float)(i) / 1024f;
if(col.b>0) col.b = 1f- (float)(i) / 1024f;
col.a = 1f;
return col;
}
}