parent
aa63c7d28e
commit
321d9fbb03
10 changed files with 1255 additions and 49 deletions
@ -0,0 +1,987 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using UnityEngine; |
||||||
|
|
||||||
|
namespace Metamesh |
||||||
|
{ |
||||||
|
public class PrimaryIsoTriangle |
||||||
|
{ |
||||||
|
public int m; |
||||||
|
public int n; |
||||||
|
public List<Vector3> cartesian = new List<Vector3>(); |
||||||
|
public List<IsoVector> vertices = new List<IsoVector>(); |
||||||
|
public List<int> max = new List<int>(); |
||||||
|
public List<int> min = new List<int>(); |
||||||
|
public Dictionary<string, int> vecToidx = new Dictionary<string, int>(); |
||||||
|
public Dictionary<string, List<int>> vertByDist = new Dictionary<string, List<int>>(); |
||||||
|
public List<List<int>> closestTo = new List<List<int>>(); |
||||||
|
|
||||||
|
public List<List<string>> innerFacets = new List<List<string>>(); |
||||||
|
public List<List<IsoVector>> isoVecsABOB = new List<List<IsoVector>>(); |
||||||
|
public List<List<IsoVector>> isoVecsOBOA = new List<List<IsoVector>>(); |
||||||
|
public List<List<IsoVector>> isoVecsBAOA = new List<List<IsoVector>>(); |
||||||
|
public List<List<int>> vertexTypes = new List<List<int>>(); |
||||||
|
|
||||||
|
public float coau; |
||||||
|
public float cobu; |
||||||
|
public float coav; |
||||||
|
public float cobv; |
||||||
|
|
||||||
|
//float PHI = (1 + Mathf.Sqrt(5f)) / 2; |
||||||
|
const float PHI = 1.618034f; |
||||||
|
public PolyhedronData IDATA = new PolyhedronData( |
||||||
|
"icosahedron", |
||||||
|
"Regular", |
||||||
|
new List<Vector3> { |
||||||
|
new Vector3(0, PHI, -1), |
||||||
|
new Vector3(-PHI, 1, 0), |
||||||
|
new Vector3(-1, 0, -PHI), |
||||||
|
new Vector3(1, 0, -PHI), |
||||||
|
new Vector3(PHI, 1, 0), |
||||||
|
new Vector3(0, PHI, 1), |
||||||
|
new Vector3(-1, 0, PHI), |
||||||
|
new Vector3(-PHI, -1, 0), |
||||||
|
new Vector3(0, -PHI, -1), |
||||||
|
new Vector3(PHI, -1, 0), |
||||||
|
new Vector3(1, 0, PHI), |
||||||
|
new Vector3(0, -PHI, 1), |
||||||
|
}, |
||||||
|
new List<List<int>> { |
||||||
|
new List<int> {0, 2, 1}, |
||||||
|
new List<int> {0, 3, 2}, |
||||||
|
new List<int> {0, 4, 3}, |
||||||
|
new List<int> {0, 5, 4}, |
||||||
|
new List<int> {0, 1, 5}, |
||||||
|
new List<int> {7, 6, 1}, |
||||||
|
new List<int> {8, 7, 2}, |
||||||
|
new List<int> {9, 8, 3}, |
||||||
|
new List<int> {10, 9, 4}, |
||||||
|
new List<int> {6, 10, 5}, |
||||||
|
new List<int> {2, 7, 1}, |
||||||
|
new List<int> {3, 8, 2}, |
||||||
|
new List<int> {4, 9, 3}, |
||||||
|
new List<int> {5, 10, 4}, |
||||||
|
new List<int> {1, 6, 5}, |
||||||
|
new List<int> {11, 6, 7}, |
||||||
|
new List<int> {11, 7, 8}, |
||||||
|
new List<int> {11, 8, 9}, |
||||||
|
new List<int> {11, 9, 10}, |
||||||
|
new List<int> {11, 10, 6}, |
||||||
|
} |
||||||
|
); |
||||||
|
|
||||||
|
private int HighestCommonFactor(int a, int b) |
||||||
|
{ |
||||||
|
var r = a % b; |
||||||
|
if (r == 0) |
||||||
|
{ |
||||||
|
return b; |
||||||
|
} |
||||||
|
return HighestCommonFactor(b, r); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void SetIndices() |
||||||
|
{ |
||||||
|
var indexCount = 12; // 12 vertices already assigned |
||||||
|
var vecToidx = new Dictionary<string, int>(); |
||||||
|
var m = this.m; |
||||||
|
var n = this.n; |
||||||
|
var g = m; // hcf of m, n when n != 0 |
||||||
|
var m1 = 1; |
||||||
|
var n1 = 0; |
||||||
|
if (n != 0) |
||||||
|
{ |
||||||
|
g = HighestCommonFactor(m, n); |
||||||
|
} |
||||||
|
m1 = m / g; |
||||||
|
n1 = n / g; |
||||||
|
|
||||||
|
int fr; //face to the right of current face |
||||||
|
string rot; //rotation about which vertex for fr |
||||||
|
int O; |
||||||
|
int A; |
||||||
|
int B; |
||||||
|
var oVec = IsoVector.Zero(); |
||||||
|
var aVec = new IsoVector(m, n); |
||||||
|
var bVec = new IsoVector(-n, m + n); |
||||||
|
var oaVec = IsoVector.Zero(); |
||||||
|
var abVec = IsoVector.Zero(); |
||||||
|
var obVec = IsoVector.Zero(); |
||||||
|
var verts = new List<int>(); |
||||||
|
string idx; |
||||||
|
string idxR; |
||||||
|
string isoId; |
||||||
|
string isoIdR; |
||||||
|
|
||||||
|
var closestTo = new List<List<int>>(); |
||||||
|
var vDist = this.vertByDist; |
||||||
|
|
||||||
|
System.Action<int, int, string, string> matchIdx = (f, fr, isoId, isoIdR) => |
||||||
|
{ |
||||||
|
idx = f + "|" + isoId; |
||||||
|
idxR = fr + "|" + isoIdR; |
||||||
|
if (!(vecToidx.ContainsKey(idx) || vecToidx.ContainsKey(idxR))) |
||||||
|
{ |
||||||
|
vecToidx[idx] = indexCount; |
||||||
|
vecToidx[idxR] = indexCount; |
||||||
|
indexCount++; |
||||||
|
} |
||||||
|
else if (vecToidx.ContainsKey(idx) && !(vecToidx.ContainsKey(idxR))) |
||||||
|
{ |
||||||
|
vecToidx[idxR] = vecToidx[idx]; |
||||||
|
} |
||||||
|
else if (vecToidx.ContainsKey(idxR) && !(vecToidx.ContainsKey(idx))) |
||||||
|
{ |
||||||
|
vecToidx[idx] = vecToidx[idxR]; |
||||||
|
} |
||||||
|
if (vDist[isoId][0] > 2) |
||||||
|
{ |
||||||
|
closestTo[vecToidx[idx]] = new List<int> { -vDist[isoId][0], vDist[isoId][1], vecToidx[idx] }; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
closestTo[vecToidx[idx]] = new List<int> { verts[vDist[isoId][0]], vDist[isoId][1], vecToidx[idx] }; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
this.IDATA.edgematch = new List<(int, string, int, string)> { |
||||||
|
(1, "B", 0, ""), |
||||||
|
(2, "B", 0, ""), |
||||||
|
(3, "B", 0, ""), |
||||||
|
(4, "B", 0, ""), |
||||||
|
(0, "B", 0, ""), |
||||||
|
(10, "O", 14, "A"), |
||||||
|
(11, "O", 10, "A"), |
||||||
|
(12, "O", 11, "A"), |
||||||
|
(13, "O", 12, "A"), |
||||||
|
(14, "O", 13, "A"), |
||||||
|
(0, "O", 0, ""), |
||||||
|
(1, "O", 0, ""), |
||||||
|
(2, "O", 0, ""), |
||||||
|
(3, "O", 0, ""), |
||||||
|
(4, "O", 0, ""), |
||||||
|
(19, "B", 5, "A"), |
||||||
|
(15, "B", 6, "A"), |
||||||
|
(16, "B", 7, "A"), |
||||||
|
(17, "B", 8, "A"), |
||||||
|
(18, "B", 9, "A"), |
||||||
|
}; |
||||||
|
|
||||||
|
/***edges AB to OB***** rotation about B*/ |
||||||
|
for (var f = 0; f < 20; f++) |
||||||
|
{ |
||||||
|
//f current face |
||||||
|
|
||||||
|
verts = this.IDATA.face[f]; |
||||||
|
O = verts[2]; |
||||||
|
A = verts[1]; |
||||||
|
B = verts[0]; |
||||||
|
|
||||||
|
isoId = oVec.x + "|" + oVec.y; |
||||||
|
idx = f + "|" + isoId; |
||||||
|
if (!vecToidx.ContainsKey(idx)) |
||||||
|
{ |
||||||
|
vecToidx[idx] = O; |
||||||
|
closestTo[O] = new List<int> { verts[vDist[isoId][0]], vDist[isoId][1] }; |
||||||
|
} |
||||||
|
|
||||||
|
isoId = aVec.x + "|" + aVec.y; |
||||||
|
idx = f + "|" + isoId; |
||||||
|
if (!vecToidx.ContainsKey(idx)) |
||||||
|
{ |
||||||
|
vecToidx[idx] = A; |
||||||
|
closestTo[A] = new List<int> { verts[vDist[isoId][0]], vDist[isoId][1] }; |
||||||
|
} |
||||||
|
|
||||||
|
isoId = bVec.x + "|" + bVec.y; |
||||||
|
idx = f + "|" + isoId; |
||||||
|
if (!vecToidx.ContainsKey(idx)) |
||||||
|
{ |
||||||
|
vecToidx[idx] = B; |
||||||
|
closestTo[B] = new List<int> { verts[vDist[isoId][0]], vDist[isoId][1] }; |
||||||
|
} |
||||||
|
|
||||||
|
//for edge vertices |
||||||
|
fr = this.IDATA.edgematch[f].Item1; |
||||||
|
rot = this.IDATA.edgematch[f].Item2; |
||||||
|
if (rot == "B") |
||||||
|
{ |
||||||
|
for (var i = 1; i < g; i++) |
||||||
|
{ |
||||||
|
abVec.x = m - i * (m1 + n1); |
||||||
|
abVec.y = n + i * m1; |
||||||
|
obVec.x = -i * n1; |
||||||
|
obVec.y = i * (m1 + n1); |
||||||
|
isoId = abVec.x + "|" + abVec.y; |
||||||
|
isoIdR = obVec.x + "|" + obVec.y; |
||||||
|
matchIdx(f, fr, isoId, isoIdR); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (rot == "O") |
||||||
|
{ |
||||||
|
for (var i = 1; i < g; i++) |
||||||
|
{ |
||||||
|
obVec.x = -i * n1; |
||||||
|
obVec.y = i * (m1 + n1); |
||||||
|
oaVec.x = i * m1; |
||||||
|
oaVec.y = i * n1; |
||||||
|
isoId = obVec.x + "|" + obVec.y; |
||||||
|
isoIdR = oaVec.x + "|" + oaVec.y; |
||||||
|
matchIdx(f, fr, isoId, isoIdR); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fr = this.IDATA.edgematch[f].Item3; |
||||||
|
rot = this.IDATA.edgematch[f].Item4; |
||||||
|
if (rot == "A") |
||||||
|
{ |
||||||
|
for (var i = 1; i < g; i++) |
||||||
|
{ |
||||||
|
oaVec.x = i * m1; |
||||||
|
oaVec.y = i * n1; |
||||||
|
abVec.x = m - (g - i) * (m1 + n1); //reversed for BA |
||||||
|
abVec.y = n + (g - i) * m1; //reversed for BA |
||||||
|
isoId = oaVec.x + "|" + oaVec.y; |
||||||
|
isoIdR = abVec.x + "|" + abVec.y; |
||||||
|
matchIdx(f, fr, isoId, isoIdR); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (var i = 0; i < this.vertices.Count; i++) |
||||||
|
{ |
||||||
|
isoId = this.vertices[i].x + "|" + this.vertices[i].y; |
||||||
|
idx = f + "|" + isoId; |
||||||
|
if (!vecToidx.ContainsKey(idx)) |
||||||
|
{ |
||||||
|
vecToidx[idx] = indexCount++; |
||||||
|
if (vDist[isoId][0] > 2) |
||||||
|
{ |
||||||
|
closestTo[vecToidx[idx]] = new List<int> { -vDist[isoId][0], vDist[isoId][1], vecToidx[idx] }; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
closestTo[vecToidx[idx]] = new List<int> { verts[vDist[isoId][0]], vDist[isoId][1], vecToidx[idx] }; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.closestTo = closestTo; |
||||||
|
this.vecToidx = vecToidx; |
||||||
|
} |
||||||
|
|
||||||
|
public void CalcCoeffs() |
||||||
|
{ |
||||||
|
var m = this.m; |
||||||
|
var n = this.n; |
||||||
|
var thirdR3 = Mathf.Sqrt(3) / 3; |
||||||
|
|
||||||
|
var LSQD = m * m + n * n + m * n; |
||||||
|
|
||||||
|
this.coau = (m + n) / LSQD; |
||||||
|
this.cobu = -n / LSQD; |
||||||
|
this.coav = (-thirdR3 * (m - n)) / LSQD; |
||||||
|
this.cobv = (thirdR3 * (2 * m + n)) / LSQD; |
||||||
|
} |
||||||
|
|
||||||
|
public void CreateInnerFacets() |
||||||
|
{ |
||||||
|
var m = this.m; |
||||||
|
var n = this.n; |
||||||
|
for (var y = 0; y < n + m + 1; y++) |
||||||
|
{ |
||||||
|
for (var x = this.min[y]; x < this.max[y] + 1; x++) |
||||||
|
{ |
||||||
|
if (x < this.max[y] && x < this.max[y + 1] + 1) |
||||||
|
{ |
||||||
|
this.innerFacets.Add(new List<string> { "|" + x + "|" + y, "|" + x + "|" + (y + 1), "|" + (x + 1) + "|" + y }); |
||||||
|
} |
||||||
|
if (y > 0 && x < this.max[y - 1] && x + 1 < this.max[y] + 1) |
||||||
|
{ |
||||||
|
this.innerFacets.Add(new List<string> { "|" + x + "|" + y, "|" + (x + 1) + "|" + y, "|" + (x + 1) + "|" + (y - 1) }); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void EdgeVecsABOB() |
||||||
|
{ |
||||||
|
var m = this.m; |
||||||
|
var n = this.n; |
||||||
|
|
||||||
|
var B = new IsoVector(-n, m + n); |
||||||
|
|
||||||
|
for (var y = 1; y < m + n; y++) |
||||||
|
{ |
||||||
|
var point = new IsoVector(this.min[y], y); |
||||||
|
var prev = new IsoVector(this.min[y - 1], y - 1); |
||||||
|
var next = new IsoVector(this.min[y + 1], y + 1); |
||||||
|
var pointR = point.Clone(); |
||||||
|
var prevR = prev.Clone(); |
||||||
|
var nextR = next.Clone(); |
||||||
|
|
||||||
|
pointR.Rotate60About(B); |
||||||
|
prevR.Rotate60About(B); |
||||||
|
nextR.Rotate60About(B); |
||||||
|
|
||||||
|
var maxPoint = new IsoVector(this.max[pointR.y], pointR.y); |
||||||
|
var maxPrev = new IsoVector(this.max[pointR.y - 1], pointR.y - 1); |
||||||
|
var maxLeftPrev = new IsoVector(this.max[pointR.y - 1] - 1, pointR.y - 1); |
||||||
|
|
||||||
|
if (pointR.x != maxPoint.x || pointR.y != maxPoint.y) |
||||||
|
{ |
||||||
|
if (pointR.x != maxPrev.x) |
||||||
|
{ |
||||||
|
// type2 |
||||||
|
//up |
||||||
|
this.vertexTypes.Add(new List<int> { 1, 0, 0 }); |
||||||
|
this.isoVecsABOB.Add(new List<IsoVector> { point, maxPrev, maxLeftPrev }); |
||||||
|
//down |
||||||
|
this.vertexTypes.Add(new List<int> { 1, 0, 0 }); |
||||||
|
this.isoVecsABOB.Add(new List<IsoVector> { point, maxLeftPrev, maxPoint }); |
||||||
|
} |
||||||
|
else if (pointR.y == nextR.y) |
||||||
|
{ |
||||||
|
// type1 |
||||||
|
//up |
||||||
|
this.vertexTypes.Add(new List<int> { 1, 1, 0 }); |
||||||
|
this.isoVecsABOB.Add(new List<IsoVector> { point, prev, maxPrev }); |
||||||
|
//down |
||||||
|
this.vertexTypes.Add(new List<int> { 1, 0, 1 }); |
||||||
|
this.isoVecsABOB.Add(new List<IsoVector> { point, maxPrev, next }); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
// type 0 |
||||||
|
//up |
||||||
|
this.vertexTypes.Add(new List<int> { 1, 1, 0 }); |
||||||
|
this.isoVecsABOB.Add(new List<IsoVector> { point, prev, maxPrev }); |
||||||
|
//down |
||||||
|
this.vertexTypes.Add(new List<int> { 1, 0, 0 }); |
||||||
|
this.isoVecsABOB.Add(new List<IsoVector> { point, maxPrev, maxPoint }); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MapABOBtoOBOA() |
||||||
|
{ |
||||||
|
var point = new IsoVector(0, 0); |
||||||
|
for (var i = 0; i < this.isoVecsABOB.Count; i++) |
||||||
|
{ |
||||||
|
var temp = new List<IsoVector>(); |
||||||
|
for (var j = 0; j < 3; j++) |
||||||
|
{ |
||||||
|
point.x = this.isoVecsABOB[i][j].x; |
||||||
|
point.y = this.isoVecsABOB[i][j].y; |
||||||
|
if (this.vertexTypes[i][j] == 0) |
||||||
|
{ |
||||||
|
point.RotateNeg120(this.m, this.n); |
||||||
|
} |
||||||
|
temp.Add(point.Clone()); |
||||||
|
} |
||||||
|
this.isoVecsOBOA.Add(temp); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MapABOBtoBAOA() |
||||||
|
{ |
||||||
|
var point = new IsoVector(0, 0); |
||||||
|
for (var i = 0; i < this.isoVecsABOB.Count; i++) |
||||||
|
{ |
||||||
|
var temp = new List<IsoVector>(); |
||||||
|
for (var j = 0; j < 3; j++) |
||||||
|
{ |
||||||
|
point.x = this.isoVecsABOB[i][j].x; |
||||||
|
point.y = this.isoVecsABOB[i][j].y; |
||||||
|
if (this.vertexTypes[i][j] == 1) |
||||||
|
{ |
||||||
|
point.Rotate120(this.m, this.n); |
||||||
|
} |
||||||
|
temp.Add(point.Clone()); |
||||||
|
} |
||||||
|
this.isoVecsBAOA.Add(temp); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MapToFace(int faceNb, PolyhedronData geodesicData) |
||||||
|
{ |
||||||
|
var F = this.IDATA.face[faceNb]; |
||||||
|
var oidx = F[2]; |
||||||
|
var aidx = F[1]; |
||||||
|
var bidx = F[0]; |
||||||
|
|
||||||
|
var oidxVec = this.IDATA.vertex[oidx]; |
||||||
|
var aidxVec = this.IDATA.vertex[aidx]; |
||||||
|
var bidxVec = this.IDATA.vertex[bidx]; |
||||||
|
var O = new Vector3(oidxVec[0], oidxVec[1], oidxVec[2]); |
||||||
|
var A = new Vector3(aidxVec[0], aidxVec[1], aidxVec[2]); |
||||||
|
var B = new Vector3(bidxVec[0], bidxVec[1], bidxVec[2]); |
||||||
|
|
||||||
|
var OA = A - O; |
||||||
|
var OB = B - O; |
||||||
|
|
||||||
|
var x = OA * this.coau + OB * this.cobu; |
||||||
|
var y = OA * this.coav + OB * this.cobv; |
||||||
|
|
||||||
|
var mapped = new List<List<float>>(); |
||||||
|
|
||||||
|
string idx; |
||||||
|
for (var i = 0; i < this.cartesian.Count; i++) |
||||||
|
{ |
||||||
|
var tempVec = x * this.cartesian[i].x + y * this.cartesian[i].y + O; |
||||||
|
mapped[i] = new List<float> { tempVec.x, tempVec.y, tempVec.z }; |
||||||
|
idx = faceNb + "|" + this.vertices[i].x + "|" + this.vertices[i].y; |
||||||
|
geodesicData.vertex[this.vecToidx[idx]] = tempVec; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//statics |
||||||
|
/**Creates a primary triangle |
||||||
|
* @internal |
||||||
|
*/ |
||||||
|
|
||||||
|
public PrimaryIsoTriangle Build(int m, int n) |
||||||
|
{ |
||||||
|
var vertices = new List<IsoVector>(); |
||||||
|
|
||||||
|
var O = IsoVector.Zero(); |
||||||
|
var A = new IsoVector(m, n); |
||||||
|
var B = new IsoVector(-n, m + n); |
||||||
|
vertices.AddRange(new IsoVector[] { O, A, B }); |
||||||
|
|
||||||
|
//max internal isoceles triangle vertices |
||||||
|
for (var iy = n; iy < m + 1; iy++) |
||||||
|
{ |
||||||
|
for (var ix = 0; ix < m + 1 - iy; ix++) |
||||||
|
{ |
||||||
|
vertices.Add(new IsoVector(ix, iy)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//shared vertices along edges when needed |
||||||
|
if (n > 0) |
||||||
|
{ |
||||||
|
var g = HighestCommonFactor(m, n); |
||||||
|
var m1 = m / g; |
||||||
|
var n1 = n / g; |
||||||
|
|
||||||
|
for (var i = 1; i < g; i++) |
||||||
|
{ |
||||||
|
vertices.Add(new IsoVector(i * m1, i * n1)); //OA |
||||||
|
vertices.Add(new IsoVector(-i * n1, i * (m1 + n1))); //OB |
||||||
|
vertices.Add(new IsoVector(m - i * (m1 + n1), n + i * m1)); // AB |
||||||
|
} |
||||||
|
|
||||||
|
//lower rows vertices and their rotations |
||||||
|
var ratio = m / n; |
||||||
|
for (var iy = 1; iy < n; iy++) |
||||||
|
{ |
||||||
|
for (var ix = 0; ix < iy * ratio; ix++) |
||||||
|
{ |
||||||
|
vertices.Add(new IsoVector(ix, iy)); |
||||||
|
vertices.Add(new IsoVector(ix, iy).Rotate120(m, n)); |
||||||
|
vertices.Add(new IsoVector(ix, iy).RotateNeg120(m, n)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
//order vertices by x and then y |
||||||
|
vertices.Sort((a, b) => |
||||||
|
{ |
||||||
|
return a.x - b.x; |
||||||
|
}); |
||||||
|
|
||||||
|
vertices.Sort((a, b) => |
||||||
|
{ |
||||||
|
return a.y - b.y; |
||||||
|
}); |
||||||
|
|
||||||
|
var min = new List<int> { m + n + 1 }; |
||||||
|
var max = new List<int> { m + n + 1 }; |
||||||
|
for (var i = 0; i < min.Count; i++) |
||||||
|
{ |
||||||
|
min[i] = int.MaxValue; |
||||||
|
max[i] = int.MinValue; |
||||||
|
} |
||||||
|
|
||||||
|
var y = 0; |
||||||
|
var x = 0; |
||||||
|
|
||||||
|
var len = vertices.Count; |
||||||
|
for (var i = 0; i < len; i++) |
||||||
|
{ |
||||||
|
x = vertices[i].x; |
||||||
|
y = vertices[i].y; |
||||||
|
min[y] = Mathf.Min(x, min[y]); |
||||||
|
max[y] = Mathf.Max(x, max[y]); |
||||||
|
} |
||||||
|
|
||||||
|
//calculates the distance of a vertex from a given primary vertex |
||||||
|
Func<IsoVector, string, int> distFrom = (IsoVector vert, string primVert) => |
||||||
|
{ |
||||||
|
var v = vert.Clone(); |
||||||
|
if (primVert == "A") |
||||||
|
{ |
||||||
|
v.RotateNeg120(m, n); |
||||||
|
} |
||||||
|
if (primVert == "B") |
||||||
|
{ |
||||||
|
v.Rotate120(m, n); |
||||||
|
} |
||||||
|
if (v.x < 0) |
||||||
|
{ |
||||||
|
return v.y; |
||||||
|
} |
||||||
|
return v.x + v.y; |
||||||
|
}; |
||||||
|
|
||||||
|
var cartesian = new List<Vector3>(); |
||||||
|
var distFromO = new List<int>(); |
||||||
|
var distFromA = new List<int>(); |
||||||
|
var distFromB = new List<int>(); |
||||||
|
var vertByDist = new Dictionary<string, List<int>>(); |
||||||
|
; |
||||||
|
var vertData = new List<List<int>>(); |
||||||
|
var closest = -1; |
||||||
|
var dist = -1; |
||||||
|
for (var i = 0; i < len; i++) |
||||||
|
{ |
||||||
|
cartesian[i] = vertices[i].ToCartesianOrigin(new IsoVector(0, 0), 0.5f); |
||||||
|
distFromO[i] = distFrom(vertices[i], "O"); |
||||||
|
distFromA[i] = distFrom(vertices[i], "A"); |
||||||
|
distFromB[i] = distFrom(vertices[i], "B"); |
||||||
|
|
||||||
|
if (distFromO[i] == distFromA[i] && distFromA[i] == distFromB[i]) |
||||||
|
{ |
||||||
|
closest = 3; |
||||||
|
dist = distFromO[i]; |
||||||
|
} |
||||||
|
else if (distFromO[i] == distFromA[i]) |
||||||
|
{ |
||||||
|
closest = 4; |
||||||
|
dist = distFromO[i]; |
||||||
|
} |
||||||
|
else if (distFromA[i] == distFromB[i]) |
||||||
|
{ |
||||||
|
closest = 5; |
||||||
|
dist = distFromA[i]; |
||||||
|
} |
||||||
|
else if (distFromB[i] == distFromO[i]) |
||||||
|
{ |
||||||
|
closest = 6; |
||||||
|
dist = distFromO[i]; |
||||||
|
} |
||||||
|
if (distFromO[i] < distFromA[i] && distFromO[i] < distFromB[i]) |
||||||
|
{ |
||||||
|
closest = 2; |
||||||
|
dist = distFromO[i]; |
||||||
|
} |
||||||
|
if (distFromA[i] < distFromO[i] && distFromA[i] < distFromB[i]) |
||||||
|
{ |
||||||
|
closest = 1; |
||||||
|
dist = distFromA[i]; |
||||||
|
} |
||||||
|
if (distFromB[i] < distFromA[i] && distFromB[i] < distFromO[i]) |
||||||
|
{ |
||||||
|
closest = 0; |
||||||
|
dist = distFromB[i]; |
||||||
|
} |
||||||
|
vertData.Add(new List<int> { closest, dist, vertices[i].x, vertices[i].y }); |
||||||
|
} |
||||||
|
|
||||||
|
vertData.Sort((a, b) => |
||||||
|
{ |
||||||
|
return a[2].CompareTo(b[2]); |
||||||
|
}); |
||||||
|
vertData.Sort((a, b) => |
||||||
|
{ |
||||||
|
return a[3].CompareTo(b[3]); |
||||||
|
}); |
||||||
|
vertData.Sort((a, b) => |
||||||
|
{ |
||||||
|
return a[1].CompareTo(b[1]); |
||||||
|
}); |
||||||
|
vertData.Sort((a, b) => |
||||||
|
{ |
||||||
|
return a[0].CompareTo(b[0]); |
||||||
|
}); |
||||||
|
|
||||||
|
for (var v = 0; v < vertData.Count; v++) |
||||||
|
{ |
||||||
|
vertByDist[vertData[v][2] + "|" + vertData[v][3]] = new List<int> { vertData[v][0], vertData[v][1], v }; |
||||||
|
} |
||||||
|
|
||||||
|
this.m = m; |
||||||
|
this.n = n; |
||||||
|
this.vertices = vertices; |
||||||
|
this.vertByDist = vertByDist; |
||||||
|
this.cartesian = cartesian; |
||||||
|
this.min = min; |
||||||
|
this.max = max; |
||||||
|
|
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class PolyhedronData |
||||||
|
{ |
||||||
|
public string name; |
||||||
|
public string category; |
||||||
|
public List<Vector3> vertex; |
||||||
|
public List<List<int>> face; |
||||||
|
public List<(int, string, int, string)> edgematch; |
||||||
|
|
||||||
|
public PolyhedronData( |
||||||
|
string name, |
||||||
|
string category, |
||||||
|
List<Vector3> vertex, |
||||||
|
List<List<int>> face |
||||||
|
) |
||||||
|
{ |
||||||
|
this.name = name; |
||||||
|
this.category = category; |
||||||
|
this.vertex = vertex; |
||||||
|
this.face = face; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class GeodesicData : PolyhedronData |
||||||
|
{ |
||||||
|
//public override edgematch: (number | string)[][]; |
||||||
|
public List<List<int>> adjacentFaces; |
||||||
|
public int sharedNodes; |
||||||
|
public int poleNodes; |
||||||
|
|
||||||
|
public GeodesicData( |
||||||
|
string name, |
||||||
|
string category, |
||||||
|
List<Vector3> vertex, |
||||||
|
List<List<int>> face |
||||||
|
) : base(name, category, vertex, face) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void innerToData(int face, PrimaryIsoTriangle primTri) |
||||||
|
{ |
||||||
|
for (var i = 0; i < primTri.innerFacets.Count; i++) |
||||||
|
{ |
||||||
|
this.face.Add(primTri.innerFacets[i].Select((el) => primTri.vecToidx[face + el]).ToList()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MapABOBtoDATA(int faceNb, PrimaryIsoTriangle primTri) |
||||||
|
{ |
||||||
|
var fr = primTri.IDATA.edgematch[faceNb].Item1; |
||||||
|
for (var i = 0; i < primTri.isoVecsABOB.Count; i++) |
||||||
|
{ |
||||||
|
var temp = new List<string>(); |
||||||
|
for (var j = 0; j < 3; j++) |
||||||
|
{ |
||||||
|
if (primTri.vertexTypes[i][j] == 0) |
||||||
|
{ |
||||||
|
temp.Add(faceNb + "|" + primTri.isoVecsABOB[i][j].x + "|" + primTri.isoVecsABOB[i][j].y); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
temp.Add(fr + "|" + primTri.isoVecsABOB[i][j].x + "|" + primTri.isoVecsABOB[i][j].y); |
||||||
|
} |
||||||
|
} |
||||||
|
this.face.Add(new List<int> { primTri.vecToidx[temp[0]], primTri.vecToidx[temp[1]], primTri.vecToidx[temp[2]] }); |
||||||
|
} |
||||||
|
} |
||||||
|
/** |
||||||
|
* @internal |
||||||
|
*/ |
||||||
|
public void MapOBOAtoDATA(int faceNb, PrimaryIsoTriangle primTri) |
||||||
|
{ |
||||||
|
var fr = primTri.IDATA.edgematch[faceNb].Item1; |
||||||
|
for (var i = 0; i < primTri.isoVecsOBOA.Count; i++) |
||||||
|
{ |
||||||
|
var temp = new List<string>(); |
||||||
|
for (var j = 0; j < 3; j++) |
||||||
|
{ |
||||||
|
if (primTri.vertexTypes[i][j] == 1) |
||||||
|
{ |
||||||
|
temp.Add(faceNb + "|" + primTri.isoVecsOBOA[i][j].x + "|" + primTri.isoVecsOBOA[i][j].y); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
temp.Add(fr + "|" + primTri.isoVecsOBOA[i][j].x + "|" + primTri.isoVecsOBOA[i][j].y); |
||||||
|
} |
||||||
|
} |
||||||
|
this.face.Add(new List<int> { primTri.vecToidx[temp[0]], primTri.vecToidx[temp[1]], primTri.vecToidx[temp[2]] }); |
||||||
|
} |
||||||
|
} |
||||||
|
/** |
||||||
|
* @internal |
||||||
|
*/ |
||||||
|
public void MapBAOAtoDATA(int faceNb, PrimaryIsoTriangle primTri) |
||||||
|
{ |
||||||
|
var fr = primTri.IDATA.edgematch[faceNb].Item3; |
||||||
|
for (var i = 0; i < primTri.isoVecsBAOA.Count; i++) |
||||||
|
{ |
||||||
|
var temp = new List<string>(); |
||||||
|
for (var j = 0; j < 3; j++) |
||||||
|
{ |
||||||
|
if (primTri.vertexTypes[i][j] == 1) |
||||||
|
{ |
||||||
|
temp.Add(faceNb + "|" + primTri.isoVecsBAOA[i][j].x + "|" + primTri.isoVecsBAOA[i][j].y); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
temp.Add(fr + "|" + primTri.isoVecsBAOA[i][j].x + "|" + primTri.isoVecsBAOA[i][j].y); |
||||||
|
} |
||||||
|
} |
||||||
|
this.face.Add(new List<int> { primTri.vecToidx[temp[0]], primTri.vecToidx[temp[1]], primTri.vecToidx[temp[2]] }); |
||||||
|
} |
||||||
|
} |
||||||
|
/** |
||||||
|
* @internal |
||||||
|
*/ |
||||||
|
public void OrderData(PrimaryIsoTriangle primTri) |
||||||
|
{ |
||||||
|
var nearTo = new Dictionary<int, List<List<int>>>(); |
||||||
|
for (var i = 0; i < 13; i++) |
||||||
|
{ |
||||||
|
nearTo[i] = new List<List<int>>(); |
||||||
|
} |
||||||
|
var close = primTri.closestTo; |
||||||
|
for (var i = 0; i < close.Count; i++) |
||||||
|
{ |
||||||
|
if (close[i][0] > -1) |
||||||
|
{ |
||||||
|
if (close[i][1] > 0) |
||||||
|
{ |
||||||
|
nearTo[close[i][0]].Add(new List<int> { i, close[i][1] }); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
nearTo[12].Add(new List<int> { i, close[i][0] }); |
||||||
|
} |
||||||
|
} |
||||||
|
/* |
||||||
|
var near = new List<int>(); |
||||||
|
for (var i = 0; i < 12; i++) |
||||||
|
{ |
||||||
|
near[i] = i; |
||||||
|
} |
||||||
|
*/ |
||||||
|
var near = Enumerable.Range(0, 12).ToList(); |
||||||
|
var nearIndex = 12; |
||||||
|
for (var i = 0; i < 12; i++) |
||||||
|
{ |
||||||
|
nearTo[i].Sort((a, b) => |
||||||
|
{ |
||||||
|
return a[1] - b[1]; |
||||||
|
}); |
||||||
|
/* |
||||||
|
for (var j = 0; j < nearTo[i].Count; j++) |
||||||
|
{ |
||||||
|
near[nearTo[i][j][0]] = nearIndex++; |
||||||
|
} |
||||||
|
*/ |
||||||
|
foreach (var item in nearTo[i]) |
||||||
|
{ |
||||||
|
near[item[0]] = nearIndex++; |
||||||
|
} |
||||||
|
} |
||||||
|
/* |
||||||
|
for (var j = 0; j < nearTo[12].Count; j++) |
||||||
|
{ |
||||||
|
near[nearTo[12][j][0]] = nearIndex++; |
||||||
|
} |
||||||
|
*/ |
||||||
|
foreach (var item in nearTo[12]) |
||||||
|
{ |
||||||
|
near[item[0]] = nearIndex++; |
||||||
|
} |
||||||
|
/* |
||||||
|
for (var i = 0; i < this.vertex.Count; i++) |
||||||
|
{ |
||||||
|
//FIX |
||||||
|
this.vertex[i].Add(near[i]); |
||||||
|
} |
||||||
|
|
||||||
|
this.vertex.Sort((a, b) => |
||||||
|
{ |
||||||
|
return a[3].CompareTo(b[3]); |
||||||
|
}); |
||||||
|
|
||||||
|
for (var i = 0; i < this.vertex.Count; i++) |
||||||
|
{ |
||||||
|
//FIX |
||||||
|
this.vertex[i].RemoveAt(this.vertex[i].Count - 1); |
||||||
|
} |
||||||
|
*/ |
||||||
|
this.vertex = this.vertex |
||||||
|
.Select((v, index) => (Vertex: v, SortKey: near[index])) |
||||||
|
.OrderBy(x => x.SortKey) |
||||||
|
.Select(x => x.Vertex) |
||||||
|
.ToList(); |
||||||
|
|
||||||
|
for (var i = 0; i < this.face.Count; i++) |
||||||
|
{ |
||||||
|
for (var j = 0; j < this.face[i].Count; j++) |
||||||
|
{ |
||||||
|
this.face[i][j] = near[this.face[i][j]]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.sharedNodes = nearTo[12].Count; |
||||||
|
this.poleNodes = this.vertex.Count - this.sharedNodes; |
||||||
|
} |
||||||
|
|
||||||
|
public List<int> SetOrder(int m, List<int> faces) |
||||||
|
{ |
||||||
|
var adjVerts = new List<int>(); |
||||||
|
var dualFaces = new List<int>(); |
||||||
|
var face = faces.Last(); |
||||||
|
faces.RemoveAt(faces.Count - 1); |
||||||
|
dualFaces.Add(face); |
||||||
|
var index = this.face[face].IndexOf(m); |
||||||
|
index = (index + 2) % 3; |
||||||
|
var v = this.face[face][index]; |
||||||
|
adjVerts.Add(v); |
||||||
|
var f = 0; |
||||||
|
while (faces.Count > 0) |
||||||
|
{ |
||||||
|
face = faces[f]; |
||||||
|
if (this.face[face].IndexOf(v) > -1) |
||||||
|
{ |
||||||
|
// v is a vertex of face f |
||||||
|
index = (this.face[face].IndexOf(v) + 1) % 3; |
||||||
|
v = this.face[face][index]; |
||||||
|
adjVerts.Add(v); |
||||||
|
dualFaces.Add(face); |
||||||
|
faces.RemoveAt(f); |
||||||
|
f = 0; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
f++; |
||||||
|
} |
||||||
|
} |
||||||
|
this.adjacentFaces.Add(adjVerts); |
||||||
|
return dualFaces; |
||||||
|
} |
||||||
|
|
||||||
|
public PolyhedronData ToGoldbergPolyhedronData() |
||||||
|
{ |
||||||
|
var goldbergPolyhedronData = new PolyhedronData("GeoDual", "Goldberg", new List<Vector3>(), new List<List<int>>()); |
||||||
|
goldbergPolyhedronData.name = "GD dual"; |
||||||
|
var verticesNb = this.vertex.Count; |
||||||
|
var map = new List<int>[verticesNb]; |
||||||
|
for (var v = 0; v < verticesNb; v++) |
||||||
|
{ |
||||||
|
map[v] = new List<int>(); |
||||||
|
} |
||||||
|
for (var f = 0; f < this.face.Count; f++) |
||||||
|
{ |
||||||
|
for (var i = 0; i < 3; i++) |
||||||
|
{ |
||||||
|
map[this.face[f][i]].Add(f); |
||||||
|
} |
||||||
|
} |
||||||
|
float cx; |
||||||
|
float cy; |
||||||
|
float cz; |
||||||
|
List<int> face; |
||||||
|
Vector3 vertex; |
||||||
|
this.adjacentFaces = new List<List<int>>(); |
||||||
|
for (var m = 0; m < map.Length; m++) |
||||||
|
{ |
||||||
|
goldbergPolyhedronData.face[m] = this.SetOrder(m, new List<int>(map[m])); |
||||||
|
foreach (var el in map[m]) |
||||||
|
{ |
||||||
|
cx = 0; |
||||||
|
cy = 0; |
||||||
|
cz = 0; |
||||||
|
face = this.face[el]; |
||||||
|
for (var i = 0; i < 3; i++) |
||||||
|
{ |
||||||
|
vertex = this.vertex[face[i]]; |
||||||
|
cx += vertex[0]; |
||||||
|
cy += vertex[1]; |
||||||
|
cz += vertex[2]; |
||||||
|
} |
||||||
|
goldbergPolyhedronData.vertex[el] = new Vector3(cx / 3, cy / 3, cz / 3); |
||||||
|
} |
||||||
|
; |
||||||
|
} |
||||||
|
return goldbergPolyhedronData; |
||||||
|
} |
||||||
|
|
||||||
|
public static GeodesicData BuildGeodesicData(PrimaryIsoTriangle primTri) |
||||||
|
{ |
||||||
|
float PHI = (1 + Mathf.Sqrt(5f)) / 2; |
||||||
|
var geodesicData = new GeodesicData( |
||||||
|
"Geodesic-m-n", |
||||||
|
"Geodesic", |
||||||
|
new List<Vector3>() { |
||||||
|
new Vector3(0, PHI, -1), |
||||||
|
new Vector3(-PHI, 1, 0), |
||||||
|
new Vector3(-1, 0, -PHI), |
||||||
|
new Vector3(1, 0, -PHI), |
||||||
|
new Vector3(PHI, 1, 0), |
||||||
|
new Vector3(0, PHI, 1), |
||||||
|
new Vector3(-1, 0, PHI), |
||||||
|
new Vector3(-PHI, -1, 0), |
||||||
|
new Vector3(0, -PHI, -1), |
||||||
|
new Vector3(PHI, -1, 0), |
||||||
|
new Vector3(1, 0, PHI), |
||||||
|
new Vector3(0, -PHI, 1), |
||||||
|
}, |
||||||
|
new List<List<int>>() |
||||||
|
); |
||||||
|
|
||||||
|
primTri.SetIndices(); |
||||||
|
primTri.CalcCoeffs(); |
||||||
|
primTri.CreateInnerFacets(); |
||||||
|
primTri.EdgeVecsABOB(); |
||||||
|
primTri.MapABOBtoOBOA(); |
||||||
|
primTri.MapABOBtoBAOA(); |
||||||
|
|
||||||
|
for (var f = 0; f < primTri.IDATA.face.Count; f++) |
||||||
|
{ |
||||||
|
primTri.MapToFace(f, geodesicData); |
||||||
|
geodesicData.innerToData(f, primTri); |
||||||
|
if (primTri.IDATA.edgematch[f].Item2 == "B") |
||||||
|
{ |
||||||
|
geodesicData.MapABOBtoDATA(f, primTri); |
||||||
|
} |
||||||
|
if (primTri.IDATA.edgematch[f].Item2 == "O") |
||||||
|
{ |
||||||
|
geodesicData.MapOBOAtoDATA(f, primTri); |
||||||
|
} |
||||||
|
if (primTri.IDATA.edgematch[f].Item4 == "A") |
||||||
|
{ |
||||||
|
geodesicData.MapBAOAtoDATA(f, primTri); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
geodesicData.OrderData(primTri); |
||||||
|
var radius = 1f; |
||||||
|
geodesicData.vertex = geodesicData.vertex.Select((el) => |
||||||
|
{ |
||||||
|
var a = el[0]; |
||||||
|
var b = el[1]; |
||||||
|
var c = el[2]; |
||||||
|
var d = Mathf.Sqrt(a * a + b * b + c * c); |
||||||
|
el[0] *= radius / d; |
||||||
|
el[1] *= radius / d; |
||||||
|
el[2] *= radius / d; |
||||||
|
return el; |
||||||
|
}).ToList(); |
||||||
|
|
||||||
|
return geodesicData; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 5ba9950a73f64cb4fa05dd46d677a642 |
||||||
@ -0,0 +1,174 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using UnityEngine; |
||||||
|
using UnityEngine.Rendering; |
||||||
|
|
||||||
|
namespace Metamesh |
||||||
|
{ |
||||||
|
public class GoldbergBuilder |
||||||
|
{ |
||||||
|
public class GoldbergVertexDataOption |
||||||
|
{ |
||||||
|
public float size = 1; |
||||||
|
public float sizeX = 1; |
||||||
|
public float sizeY = 1; |
||||||
|
public float sizeZ = 1; |
||||||
|
}; |
||||||
|
|
||||||
|
public class GoldbergCreationOption : GoldbergVertexDataOption |
||||||
|
{ |
||||||
|
public int m; |
||||||
|
public int n; |
||||||
|
} |
||||||
|
|
||||||
|
public class VertexData |
||||||
|
{ |
||||||
|
public List<Vector3> vertices; |
||||||
|
public List<int> indices; |
||||||
|
public List<Vector3> normals; |
||||||
|
public List<Vector2> uvs; |
||||||
|
} |
||||||
|
|
||||||
|
public VertexData CreateGoldbergVertexData(GoldbergVertexDataOption options, PolyhedronData goldbergData) |
||||||
|
{ |
||||||
|
var size = options.size; |
||||||
|
var sizeX = options.sizeX;// || size || 1; |
||||||
|
var sizeY = options.sizeY;// || size || 1; |
||||||
|
var sizeZ = options.sizeZ;// || size || 1; |
||||||
|
|
||||||
|
var positions = new List<Vector3>(); |
||||||
|
var indices = new List<int>(); |
||||||
|
var normals = new List<Vector3>(); |
||||||
|
var uvs = new List<Vector2>(); |
||||||
|
|
||||||
|
var minX = float.MaxValue; |
||||||
|
var maxX = float.MinValue; |
||||||
|
var minY = float.MaxValue; |
||||||
|
var maxY = float.MinValue; |
||||||
|
|
||||||
|
for (var v = 0; v < goldbergData.vertex.Count; v++) |
||||||
|
{ |
||||||
|
minX = Mathf.Min(minX, goldbergData.vertex[v].x * sizeX); |
||||||
|
maxX = Mathf.Max(maxX, goldbergData.vertex[v].x * sizeX); |
||||||
|
minY = Mathf.Min(minY, goldbergData.vertex[v].y * sizeY); |
||||||
|
maxY = Mathf.Max(maxY, goldbergData.vertex[v].y * sizeY); |
||||||
|
} |
||||||
|
|
||||||
|
var index = 0; |
||||||
|
for (var f = 0; f < goldbergData.face.Count; f++) |
||||||
|
{ |
||||||
|
var verts = goldbergData.face[f]; |
||||||
|
var a = goldbergData.vertex[verts[0]]; |
||||||
|
var b = goldbergData.vertex[verts[2]]; |
||||||
|
var c = goldbergData.vertex[verts[1]]; |
||||||
|
var ba = b - a; |
||||||
|
var ca = c - a; |
||||||
|
var norm = Vector3.Cross(ca, ba).normalized; |
||||||
|
for (var v = 0; v < verts.Count; v++) |
||||||
|
{ |
||||||
|
normals.Add(norm); |
||||||
|
var pdata = goldbergData.vertex[verts[v]]; |
||||||
|
positions.Add(new Vector3(pdata[0] * sizeX, pdata[1] * sizeY, pdata[2] * sizeZ)); |
||||||
|
var vCoord = (pdata[1] * sizeY - minY) / (maxY - minY); |
||||||
|
uvs.Add(new Vector2((pdata[0] * sizeX - minX) / (maxX - minX), vCoord)); |
||||||
|
} |
||||||
|
for (var v = 0; v < verts.Count - 2; v++) |
||||||
|
{ |
||||||
|
indices.AddRange(new int[] { index, index + v + 2, index + v + 1 }); |
||||||
|
} |
||||||
|
index += verts.Count; |
||||||
|
} |
||||||
|
/* |
||||||
|
VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs); |
||||||
|
|
||||||
|
const vertexData = new VertexData(); |
||||||
|
vertexData.positions = positions; |
||||||
|
vertexData.indices = indices; |
||||||
|
vertexData.normals = normals; |
||||||
|
vertexData.uvs = uvs; |
||||||
|
return vertexData; |
||||||
|
*/ |
||||||
|
return new VertexData() |
||||||
|
{ |
||||||
|
vertices = positions, |
||||||
|
indices = indices, |
||||||
|
normals = normals, |
||||||
|
uvs = uvs, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates the Mesh for a Goldberg Polyhedron which is made from 12 pentagonal and the rest hexagonal faces |
||||||
|
* @see https://en.wikipedia.org/wiki/Goldberg_polyhedron |
||||||
|
* @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/polyhedra/goldberg_poly |
||||||
|
* @param name defines the name of the mesh |
||||||
|
* @param options an object used to set the following optional parameters for the polyhedron, required but can be empty |
||||||
|
* @param scene defines the hosting scene |
||||||
|
* @returns Goldberg mesh |
||||||
|
*/ |
||||||
|
public VertexData CreateGoldberg(GoldbergCreationOption options) |
||||||
|
{ |
||||||
|
var size = options.size; |
||||||
|
var sizeX = options.sizeX;// || size || 1; |
||||||
|
var sizeY = options.sizeY;// || size || 1; |
||||||
|
var sizeZ = options.sizeZ;// || size || 1; |
||||||
|
var m = options.m;// || 1; |
||||||
|
var n = options.n;// || 0; |
||||||
|
if (n > m) |
||||||
|
{ |
||||||
|
var temp = n; |
||||||
|
n = m; |
||||||
|
m = temp; |
||||||
|
Debug.LogWarning("n > m therefore m and n swapped"); |
||||||
|
} |
||||||
|
var primTri = new PrimaryIsoTriangle(); |
||||||
|
primTri.Build(m, n); |
||||||
|
var geodesicData = GeodesicData.BuildGeodesicData(primTri); |
||||||
|
var goldbergData = geodesicData.ToGoldbergPolyhedronData(); |
||||||
|
|
||||||
|
//var goldberg = new Mesh(); |
||||||
|
//goldberg.name = name; |
||||||
|
|
||||||
|
var vertexData = CreateGoldbergVertexData(options, goldbergData); |
||||||
|
return vertexData; |
||||||
|
|
||||||
|
/* |
||||||
|
vertexData.applyToMesh(goldberg, options.updatable); |
||||||
|
|
||||||
|
goldberg.goldbergData.nbSharedFaces = geodesicData.sharedNodes; |
||||||
|
goldberg.goldbergData.nbUnsharedFaces = geodesicData.poleNodes; |
||||||
|
goldberg.goldbergData.adjacentFaces = geodesicData.adjacentFaces; |
||||||
|
goldberg.goldbergData.nbFaces = goldberg.goldbergData.nbSharedFaces + goldberg.goldbergData.nbUnsharedFaces; |
||||||
|
goldberg.goldbergData.nbFacesAtPole = (goldberg.goldbergData.nbUnsharedFaces - 12) / 12; |
||||||
|
|
||||||
|
for (var f = 0; f < geodesicData.vertex.Count; f++) |
||||||
|
{ |
||||||
|
|
||||||
|
goldberg.goldbergData.faceCenters.push(Vector3.FromArray(geodesicData.vertex[f])); |
||||||
|
goldberg.goldbergData.faceCenters[f].x *= sizeX; |
||||||
|
goldberg.goldbergData.faceCenters[f].y *= sizeY; |
||||||
|
goldberg.goldbergData.faceCenters[f].z *= sizeZ; |
||||||
|
goldberg.goldbergData.faceColors.push(new Color4(1, 1, 1, 1)); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
for (var f = 0; f < goldbergData.face.Count; f++) |
||||||
|
{ |
||||||
|
var verts = goldbergData.face[f]; |
||||||
|
var a = goldbergData.vertex[verts[0]]; |
||||||
|
var b = goldbergData.vertex[verts[2]]; |
||||||
|
var c = goldbergData.vertex[verts[1]]; |
||||||
|
var ba = b - a; |
||||||
|
var ca = c - a; |
||||||
|
var norm = Vector3.Cross(ca, ba).normalized; |
||||||
|
var z = Vector3.Cross(ca, norm).normalized; |
||||||
|
//goldberg.goldbergData.faceXaxis.push(ca.normalize()); |
||||||
|
//goldberg.goldbergData.faceYaxis.push(norm); |
||||||
|
//goldberg.goldbergData.faceZaxis.push(z); |
||||||
|
} |
||||||
|
|
||||||
|
return goldberg; |
||||||
|
*/ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 7d8371f81baddd64e8c1450945f7f75f |
||||||
@ -1,43 +0,0 @@ |
|||||||
using System.Linq; |
|
||||||
using UnityEngine; |
|
||||||
using UnityEngine.Rendering; |
|
||||||
|
|
||||||
namespace Metamesh |
|
||||||
{ |
|
||||||
public class GoldbergPolyhedron : MonoBehaviour |
|
||||||
{ |
|
||||||
public float radius = 1; |
|
||||||
public uint subdivision = 2; |
|
||||||
|
|
||||||
private void Start() |
|
||||||
{ |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
private void Update() |
|
||||||
{ |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public void Generate() |
|
||||||
{ |
|
||||||
var builder = new IcosphereBuilder(); |
|
||||||
for (var i = 1; i < subdivision; ++i) |
|
||||||
{ |
|
||||||
builder = new IcosphereBuilder(builder); |
|
||||||
} |
|
||||||
|
|
||||||
var vertices = builder.Vertices.Select(v => (Vector3)(v * radius)); |
|
||||||
var normals = builder.Vertices.Select(v => (Vector3)v); |
|
||||||
var indices = builder.Indices; |
|
||||||
|
|
||||||
/* |
|
||||||
if (builder.VertexCount > 65535) mesh.indexFormat = IndexFormat.UInt32; |
|
||||||
mesh.SetVertices(vtx.ToList()); |
|
||||||
mesh.SetNormals(nrm.ToList()); |
|
||||||
mesh.SetIndices(idx.ToList(), MeshTopology.Triangles, 0); |
|
||||||
*/ |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@ -1,2 +0,0 @@ |
|||||||
fileFormatVersion: 2 |
|
||||||
guid: 825ce87dd8b71e444a6c78436e3d9903 |
|
||||||
@ -0,0 +1,67 @@ |
|||||||
|
using UnityEngine; |
||||||
|
|
||||||
|
namespace Metamesh |
||||||
|
{ |
||||||
|
public class IsoVector |
||||||
|
{ |
||||||
|
public int x; |
||||||
|
public int y; |
||||||
|
|
||||||
|
public IsoVector(int x, int y) |
||||||
|
{ |
||||||
|
this.x = x; |
||||||
|
this.y = y; |
||||||
|
} |
||||||
|
|
||||||
|
public IsoVector Clone() |
||||||
|
{ |
||||||
|
return new IsoVector(x, y); |
||||||
|
} |
||||||
|
|
||||||
|
public IsoVector Rotate60About(IsoVector other) |
||||||
|
{ |
||||||
|
var x = this.x; |
||||||
|
this.x = other.x + other.y - this.y; |
||||||
|
this.y = x + this.y - other.x; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public IsoVector RotateNeg60About(IsoVector other) |
||||||
|
{ |
||||||
|
var x = this.x; |
||||||
|
this.x = x + this.y - other.y; |
||||||
|
this.y = other.x + other.y - x; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public IsoVector Rotate120(int m, int n) |
||||||
|
{ |
||||||
|
var x = this.x; |
||||||
|
this.x = m - x - this.y; |
||||||
|
this.y = n + x; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public IsoVector RotateNeg120(int m, int n) |
||||||
|
{ |
||||||
|
var x = this.x; |
||||||
|
this.x = this.y - n; |
||||||
|
this.y = m + n - x - this.y; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3 ToCartesianOrigin(IsoVector origin, float isoGridSize) |
||||||
|
{ |
||||||
|
var point = Vector3.zero; |
||||||
|
point.x = origin.x + 2 * this.x * isoGridSize + this.y * isoGridSize; |
||||||
|
point.y = origin.y + Mathf.Sqrt(3) * this.y * isoGridSize; |
||||||
|
return point; |
||||||
|
} |
||||||
|
|
||||||
|
public static IsoVector Zero() |
||||||
|
{ |
||||||
|
return new IsoVector(0, 0); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
@ -0,0 +1,2 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1b57a079742a0234e892f0128b45703f |
||||||
Reference in new issue