|
|
|
@ -44,21 +44,11 @@ namespace Metamesh |
|
|
|
|
|
|
|
|
|
|
|
private Mesh ImportAsMesh() |
|
|
|
private Mesh ImportAsMesh() |
|
|
|
{ |
|
|
|
{ |
|
|
|
var mesh = new Mesh(); |
|
|
|
var mesh = new Mesh |
|
|
|
mesh.name = "Mesh"; |
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
var builder = new IcosphereBuilder(); |
|
|
|
|
|
|
|
for (var i = 1; i < subdivision; ++i) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
builder = new IcosphereBuilder(builder); |
|
|
|
name = "Mesh" |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var vertices = builder.Vertices.Select(v => (Vector3)(v * radius)).ToList(); |
|
|
|
|
|
|
|
var normals = builder.Vertices.Select(v => (Vector3)v).ToList(); |
|
|
|
|
|
|
|
var indices = builder.Indices.ToList(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ApplyGoldbergTransformation(vertices, normals, indices); |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
var builder = new GoldbergBuilder(); |
|
|
|
var builder = new GoldbergBuilder(); |
|
|
|
var options = new GoldbergCreationOption() |
|
|
|
var options = new GoldbergCreationOption() |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -82,161 +72,5 @@ namespace Metamesh |
|
|
|
|
|
|
|
|
|
|
|
return mesh; |
|
|
|
return mesh; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void ApplyGoldbergTransformation(List<Vector3> vertices, List<Vector3> normals, List<int> indices) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var newVertices = new List<Vector3>(); |
|
|
|
|
|
|
|
var newNormals = new List<Vector3>(); |
|
|
|
|
|
|
|
var newIndices = new List<int>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var centers = new Dictionary<int, List<int>>(); |
|
|
|
|
|
|
|
var edges = new HashSet<int>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var neighbors = FindNeighbors(0, indices); |
|
|
|
|
|
|
|
centers.Add(0, neighbors); |
|
|
|
|
|
|
|
foreach (var i in neighbors) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
edges.Add(i); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int inc = 0; |
|
|
|
|
|
|
|
while (edges.Count + centers.Count < vertices.Count) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
inc++; |
|
|
|
|
|
|
|
if (inc > 3) break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var ccs = FindCenters(edges, indices).Where(c => !centers.ContainsKey(c)).Distinct().ToArray(); |
|
|
|
|
|
|
|
Debug.Log($"while cc in nb: {ccs.Where(c => edges.Contains(c)).Count()}"); |
|
|
|
|
|
|
|
var nbs = ccs.SelectMany(c => |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var neighbors = FindNeighbors(c, indices); |
|
|
|
|
|
|
|
centers.Add(c, neighbors); |
|
|
|
|
|
|
|
return neighbors; |
|
|
|
|
|
|
|
}).Distinct().Where(i => !edges.Contains(i) && !centers.ContainsKey(i)).ToArray(); |
|
|
|
|
|
|
|
Debug.Log($"while nb in cc: {nbs.Where(c => centers.ContainsKey(c)).Count()}"); |
|
|
|
|
|
|
|
foreach (var i in nbs) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
edges.Add(i); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Debug.Log($"centers: {ccs.Count()}/{centers.Count}, edges: {nbs.Count()}/{edges.Count}, vertices: {vertices.Count}"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Debug.Log($"cc in nb: {centers.Keys.Where(c => edges.Contains(c)).Count()}"); |
|
|
|
|
|
|
|
Debug.Log($"nb in cc: {edges.Where(c => centers.Keys.Contains(c)).Count()}"); |
|
|
|
|
|
|
|
Debug.Log($"missing: {Enumerable.Range(0, vertices.Count).Where(i => !centers.ContainsKey(i)).Where(i => !edges.Contains(i)).Count()}"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var pentagon = 0; |
|
|
|
|
|
|
|
var hexagon = 0; |
|
|
|
|
|
|
|
var start = 0; |
|
|
|
|
|
|
|
foreach (var i in centers.Keys) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var neighbors = centers[i].Distinct().ToArray(); |
|
|
|
|
|
|
|
var neighborCount = neighbors.Length; |
|
|
|
|
|
|
|
if (neighborCount != 5 && neighborCount != 6) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Debug.Log($"Unexpected number of neighbors: {neighborCount}"); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (neighborCount == 5) pentagon++; |
|
|
|
|
|
|
|
if (neighborCount == 6) hexagon++; |
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
var p1 = vertices[neighbors[0]]; |
|
|
|
|
|
|
|
var p2 = vertices[neighbors[2]]; |
|
|
|
|
|
|
|
var p3 = vertices[neighbors[4]]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var edge1 = p2 - p1; |
|
|
|
|
|
|
|
var edge2 = p3 - p1; |
|
|
|
|
|
|
|
var normal = Vector3.Cross(edge1, edge2).normalized; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var projection = ProjectPointOntoPlane(p1, normal); |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
var x = neighbors.Average(i => vertices[i].x); |
|
|
|
|
|
|
|
var y = neighbors.Average(i => vertices[i].y); |
|
|
|
|
|
|
|
var z = neighbors.Average(i => vertices[i].z); |
|
|
|
|
|
|
|
vertices[i] = new Vector3(x, y, z); |
|
|
|
|
|
|
|
var normal = vertices[i]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var q = Quaternion.FromToRotation(vertices[i], Vector3.up); |
|
|
|
|
|
|
|
//var mtx = Matrix4x4.TRS(-vertices[i], q, Vector3.one); |
|
|
|
|
|
|
|
var mtx = Matrix4x4.TRS(Vector3.zero, q, Vector3.one) * Matrix4x4.TRS(-vertices[i], Quaternion.identity, Vector3.one); |
|
|
|
|
|
|
|
var sortedNeighbors = neighbors.OrderBy(n => |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var direction = mtx.MultiplyPoint(vertices[n]).normalized; |
|
|
|
|
|
|
|
var crossProduct = Vector3.Cross(direction, Vector3.up); |
|
|
|
|
|
|
|
return Mathf.Atan2(crossProduct.z, crossProduct.x); |
|
|
|
|
|
|
|
}).ToArray(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newVertices.Add(vertices[i]); |
|
|
|
|
|
|
|
newVertices.AddRange(sortedNeighbors.Select(n => vertices[n])); |
|
|
|
|
|
|
|
newNormals.AddRange(Enumerable.Repeat(normal, neighborCount + 1)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int k = 0; k < neighborCount; ++k) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
newIndices.Add(start); |
|
|
|
|
|
|
|
newIndices.Add(start + (k + 1) % neighborCount); |
|
|
|
|
|
|
|
newIndices.Add(start + (k + 0) % neighborCount); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
start += neighborCount + 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vertices.Clear(); |
|
|
|
|
|
|
|
vertices.AddRange(newVertices); |
|
|
|
|
|
|
|
normals.Clear(); |
|
|
|
|
|
|
|
normals.AddRange(newNormals); |
|
|
|
|
|
|
|
indices.Clear(); |
|
|
|
|
|
|
|
indices.AddRange(newIndices); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Debug.Log($"Pentagon: {pentagon}, Hexagon: {hexagon}"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Vector3 ProjectPointOntoPlane(Vector3 planePoint, Vector3 planeNormal) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
float distance = Vector3.Dot(planeNormal, Vector3.zero - planePoint); |
|
|
|
|
|
|
|
Vector3 projection = Vector3.zero - planeNormal * distance; |
|
|
|
|
|
|
|
return projection; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<int> FindNeighbors(int index, List<int> indices) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var results = new List<int>(); |
|
|
|
|
|
|
|
for (int i = 0; i < indices.Count; i += 3) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var i0 = indices[i + 0]; |
|
|
|
|
|
|
|
var i1 = indices[i + 1]; |
|
|
|
|
|
|
|
var i2 = indices[i + 2]; |
|
|
|
|
|
|
|
if (i0 == index) results.AddRange(new[] { i1, i2 }); |
|
|
|
|
|
|
|
if (i1 == index) results.AddRange(new[] { i0, i2 }); |
|
|
|
|
|
|
|
if (i2 == index) results.AddRange(new[] { i0, i1 }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
results = results.Distinct().ToList(); |
|
|
|
|
|
|
|
if (results.Count != 5 && results.Count != 6) |
|
|
|
|
|
|
|
Debug.Log($"Center#{index}'s neighbors count is {results.Count}"); |
|
|
|
|
|
|
|
return results; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<int> FindCenters(HashSet<int> edges, List<int> indices) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var results = new List<int>(); |
|
|
|
|
|
|
|
for (int i = 0; i < indices.Count; i += 3) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var i0 = indices[i + 0]; |
|
|
|
|
|
|
|
var i1 = indices[i + 1]; |
|
|
|
|
|
|
|
var i2 = indices[i + 2]; |
|
|
|
|
|
|
|
var notInEdges = new List<int> { i0, i1, i2 } |
|
|
|
|
|
|
|
.Where(v => !edges.Contains(v)) |
|
|
|
|
|
|
|
.ToList(); |
|
|
|
|
|
|
|
if (notInEdges.Count == 1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var candidate = notInEdges[0]; |
|
|
|
|
|
|
|
var neighbors = FindNeighbors(candidate, indices); |
|
|
|
|
|
|
|
if (neighbors.Count != 5 && neighbors.Count != 6) |
|
|
|
|
|
|
|
Debug.Log($"candidate#{candidate}'s neighbors count is {neighbors.Count}"); |
|
|
|
|
|
|
|
results.Add(candidate); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return results.Distinct().ToList(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |