You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
5.7 KiB
143 lines
5.7 KiB
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
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 List<Vector4> barycentrics;
|
|
}
|
|
|
|
private static 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 barycentrics = new List<Vector4>();
|
|
|
|
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];
|
|
if (verts.Any(v => v >= goldbergData.vertex.Count))
|
|
{
|
|
Debug.LogWarning($"Polygon#{f} has some index > {goldbergData.vertex.Count}");
|
|
continue;
|
|
}
|
|
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 x = verts.Average(v => goldbergData.vertex[v].x);
|
|
var y = verts.Average(v => goldbergData.vertex[v].y);
|
|
var z = verts.Average(v => goldbergData.vertex[v].z);
|
|
var centroid = new Vector3(x, y, z);
|
|
var rot = Quaternion.FromToRotation(norm, Vector3.up);
|
|
var mtx = Matrix4x4.TRS(Vector3.zero, rot, Vector3.one);
|
|
var right = mtx.MultiplyVector(a - centroid);
|
|
var angle = Vector2.SignedAngle(new Vector2(right.x, right.z), Vector2.right) * Mathf.Deg2Rad;
|
|
for (var v = 0; v < verts.Count; v++)
|
|
{
|
|
normals.Add(norm);
|
|
var pdata = goldbergData.vertex[verts[v]];
|
|
var pos = pdata;//new Vector3(pdata.x * sizeX, pdata.y * sizeY, pdata.z * sizeZ);
|
|
positions.Add(pos);
|
|
var vCoord = (pdata[1] * sizeY - minY) / (maxY - minY);
|
|
uvs.Add(new Vector3((pdata[0] * sizeX - minX) / (maxX - minX), vCoord, f));
|
|
|
|
var dir = mtx.MultiplyVector(pos - centroid);
|
|
var braycentric = new Vector2(dir.x, dir.z).Rotate(angle).normalized * 0.5f;
|
|
barycentrics.Add(new Vector4(braycentric.x, braycentric.y, verts.Count, f));
|
|
}
|
|
for (var v = 0; v < verts.Count - 2; v++)
|
|
{
|
|
indices.AddRange(new int[] { index, index + v + 1, index + v + 2 });
|
|
}
|
|
|
|
index += verts.Count;
|
|
}
|
|
|
|
return new VertexData()
|
|
{
|
|
vertices = positions,
|
|
indices = indices,
|
|
normals = normals,
|
|
uvs = uvs,
|
|
barycentrics = barycentrics,
|
|
};
|
|
}
|
|
|
|
public static 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)
|
|
{
|
|
(n, m) = (m, n);
|
|
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 nbSharedFaces = geodesicData.sharedNodes;
|
|
var nbUnsharedFaces = geodesicData.poleNodes;
|
|
var adjacentFaces = geodesicData.adjacentFaces;
|
|
var nbFaces = nbSharedFaces + nbUnsharedFaces;
|
|
var nbFacesAtPole = (nbUnsharedFaces - 12) / 12;
|
|
var faceCenters = geodesicData.vertex.Keys.Select(v => v * size).ToArray();
|
|
var faceColors = geodesicData.vertex.Keys.Select(_ => Color.white).ToArray();
|
|
*/
|
|
var vertexData = CreateGoldbergVertexData(options, goldbergData);
|
|
return vertexData;
|
|
}
|
|
}
|
|
|
|
} |