using UnityEngine; using System; using System.Collections; using ProceduralToolkit; using System.Collections.Generic; namespace ProceduralToolkit { public static class TriQual { public const int A = 0; public const int B = 1; public const int C = 2; public const int D = 3; public const int E = 4; public const int F = 5; public const int G = 6; public const int H = 7; public const int I = 8; public const int J = 9; public const int K = 10; public const int L = 11; public const int M = 12; public const int N = 13; public const int O = 14; public const int P = 15; public const int Q = 16; public const int R = 17; public const int S = 18; public const int UNDEFINED = int.MaxValue; } 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 float maxDistToNeighbor = 0; public float minDistToNeighbor = float.MaxValue; public int idx; public class NB { public ArgVert aV; public float distFrom; public NB() { aV = null; distFrom = float.MaxValue; } } public List<NB> avNeigbor = new List<NB>(); public ArgVert() { for (int i = 0; i < 6; i++) { avNeigbor.Add(new NB()); avNeigbor[i].aV = this; } vPos = new Vector3(); } public float getMaxDistToNeighbor() { maxDistToNeighbor = 0; for (int i = 0; i < 6; i++) { if (avNeigbor[i].distFrom > maxDistToNeighbor) { maxDistToNeighbor = avNeigbor[i].distFrom; } } return maxDistToNeighbor; } public float getMinDistToNeighbor() { minDistToNeighbor = float.MaxValue; for (int i = 0; i < 6; i++) { if (avNeigbor[i].distFrom < minDistToNeighbor) { minDistToNeighbor = avNeigbor[i].distFrom; } } return minDistToNeighbor; } public bool isAVinNeighborList(ArgVert aV) { for (int i = 0; i < 6; i++) { if (avNeigbor[i].aV == aV) return true; } return false; } public int isLessThan(float dist) { for (int i = 0; i < 6; i++) { if (dist < avNeigbor[i].distFrom) return i; } return -1; } public bool goesHere(int i, float dist, ArgVert aV_Contender) { if (dist < avNeigbor[i].distFrom) { NB nb = new NB(); nb.aV = aV_Contender; nb.distFrom = dist; nb.aV.idx = aV_Contender.idx; avNeigbor.Insert(i, nb); avNeigbor.RemoveAt(6); return true; } return false; } public void insNeighbor_One_Shot(float dist, ArgVert aV_Contender) { for (int i = 0; i < 6; i++) { if (goesHere(i, dist, aV_Contender)) return; } } } 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, int ITG_idx) { 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; aV.idx = ITG_idx; icoPointCloud.Add(aV); } public void SetSortDist(Vector3 Apex) { foreach (ArgVert aV in icoPointCloud) { aV.dist = (aV.vPos - Apex).magnitude; } } public void sortPointCloud() { icoPointCloud.Sort((x, y) => x.dist.CompareTo(y.dist)); } public void AddTriQual(MeshDraft tri) { Vector3 vC = (tri.vertices[0] + tri.vertices[1] + tri.vertices[2]) / 3f; int qual = TriQual.UNDEFINED; Add(tri); for (int i = 0; i < 3; i++)//Track the quality of the triangle UVs { vTriCenter.Add(vC); vQual.Add(qual); } } public void AddHex(MeshDraft tri)//from triangle see: http://argos.vu/wp-content/uploads/2016/04/HCs-1.png { Vector3 HC = (tri.vertices[0] + tri.vertices[1] + tri.vertices[2]) / 3f; Vector3 H0 = (tri.vertices[1] + tri.vertices[0]) / 2f; Vector3 H1 = (tri.vertices[1] + HC) / 2f; Vector3 H2 = (tri.vertices[2] + tri.vertices[1]) / 2f; Vector3 H3 = (tri.vertices[2] + HC) / 2f; Vector3 H4 = (tri.vertices[0] + tri.vertices[2]) / 2f; Vector3 H5 = (tri.vertices[0] + HC) / 2f; List<Vector3> vL = new List<Vector3>(8) { HC, H0, H1, H2, H3, H4, H5, H0 }; List<Vector2> uvMapL = new List<Vector2>(8) { new Vector2(0.5f, 0.5f), new Vector2(0.5f, 1f), new Vector2(1, 0.75f), new Vector2(1, 0.25f), new Vector2(0.5f, 0), new Vector2(0, 0.25f), new Vector2(0, 0.75f), new Vector2(0.5f, 1f) }; Add(HexFan(vL, uvMapL)); } public void AddTriQual(MeshDraft tri, int qual) { Vector3 vC = (tri.vertices[0] + tri.vertices[1] + tri.vertices[2]) / 3f; Add(tri); for (int i = 0; i < 3; i++)//Track the quality of the triangle UVs { vTriCenter.Add(vC); vQual.Add(qual); } } } }
Convert to ArgosMesh
using UnityEngine; using System.Collections; using ProceduralToolkit; using UnityEngine.UI; public class PaintElement : MonoBehaviour { Mesh mesh; private MeshDraft mDraft; public MeshDraft Mdraft { get { return mDraft; } } void Start () { MeshFilter mf = GetComponent<MeshFilter>(); if (mf.mesh == null) mf.mesh = new Mesh(); mesh = mf.mesh; mDraft = new MeshDraft(); } void Update () { } public int GetNumVertices() { return mDraft.vertices.Count; } public Vector3 GetVertex(int i) { return mDraft.vertices[i]; } public void SetVertex(int i, Vector3 v) { mDraft.vertices[i] = v; } public void MeshDraft_ToMesh() { if (mDraft != null) { GetComponent<MeshFilter>().mesh = mDraft.ToMesh(); } } public void initAddMeshDraft(MeshDraft md) { MeshFilter mf = GetComponent<MeshFilter>(); if (mf.mesh == null) mf.mesh = new Mesh(); mesh = mf.mesh; mDraft = new MeshDraft(); if (mDraft != null) { mDraft.Add(md); GetComponent<MeshFilter>().mesh = mDraft.ToMesh(); } } public void AddMeshDraft(MeshDraft md) { if (mDraft != null) { mDraft.Add(md); GetComponent<MeshFilter>().mesh = mDraft.ToMesh(); } } public void AddMeshDraft_Only(MeshDraft md) { if (mDraft != null) { mDraft.Add(md); } } public void AddQuad(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3) { if (mDraft != null) { mDraft.Add(MeshDraft.Quad(v0, v1, v2, v3)); GetComponent<MeshFilter>().mesh = mDraft.ToMesh(); } } public void AddQuad(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, Color col) { if (mDraft != null) { mDraft.Add(MeshDraft.Quad(v0, v1, v2, v3, col)); GetComponent<MeshFilter>().mesh = mDraft.ToMesh(); //mesh.RecalculateBounds(); } } }
Diagram argos_NavSphere structure
SubFrame Tweening needed:
UNITY Script Execution
All Awake calls
All Start Calls
while (stepping towards variable delta time)
All FixedUpdate functions
Physics simulation
OnEnter/Exit/Stay trigger functions
OnEnter/Exit/Stay collision functions
Rigidbody interpolation applies transform.position and rotation
OnMouseDown/OnMouseUp etc. events
All Update functions