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